Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include Authorization Info in Tool Calls (and request handlers generally) #166

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

allenzhou101
Copy link
Contributor

@allenzhou101 allenzhou101 commented Feb 28, 2025

Includes the req.auth AuthInfo that's set by the MCP Server bearer auth middleware in the server request handler via SSE Transport, allowing for distinguishing of users in requests (eg. tool use).

Motivation and Context

When an MCP Server makes a tool call it may need to validate that a particular user has the authorization necessary to access a particular resource. For instance, the MCP Client could give any email it would like to the MCP Server, say to fetch audit logs of a project, but the Server should verify that the user has access to that particular project, which has to happen at the tool call level in the server.

This PR allows the developer to access the auth info not only in the initial /sse or /message route handlers but in the server request handler (eg. tool call) itself.

How Has This Been Tested?

Running an authenticated MCP Client session with a Server and validating that the extra param appears in the tool call with auth info.

This allows auth info to be easily used in a tool call:


export const createServer = () => {
    // Create server instance
    const server = new McpServer({
        name: "analytics",
        version: "1.0.0",
    });

    // Add get-schema tool
    server.tool(
        "get-schema",
        "Fetch the database schema",
        {},
        async (_, { authInfo }) => {
            const token = authInfo?.token;

            const scopes = authInfo?.scopes;
            if (!scopes || scopes && scopes.indexOf("get-schema") < 0) {
                return {
                    content: [
                        {
                            type: "text",
                            text: "Unauthorized: Missing get-schema scope",
                            code: 403
                        }
                    ]
                }
            }
import { z } from "zod";

/**
 * Information about a validated access token, provided to request handlers.
 */
export const AuthInfoSchema = z.object({
    /** The access token */
    token: z.string(),

    /** The client ID associated with this token */
    clientId: z.string(),

    /** Scopes associated with this token */
    scopes: z.array(z.string()),

    /** When the token expires (in seconds since epoch) */
    expiresAt: z.number().optional(),
});

export type AuthInfo = z.infer<typeof AuthInfoSchema>;

Breaking Changes

None.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

This allows for simpler access of auth data than simply including the session id in the transport since you'd have to handle mapping in that case: #158

Fixes #171

Sorry, something went wrong.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@allenzhou101 allenzhou101 changed the title Include AuthInfo from bearer validation in transport request handler Include AuthInfo from Bearer Validation in Server Request Handler Feb 28, 2025
Copy link
Contributor

@cliffhall cliffhall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks good, @allenzhou101. Could you add some unit tests?

@cliffhall cliffhall added enhancement New feature or request waiting on submitter Waiting for the submitter to provide more info labels Apr 4, 2025
@allenzhou101
Copy link
Contributor Author

Sure, added!

Copy link
Contributor

@cliffhall cliffhall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks good, builds, and tests run. It seems like a straightforward way to pass the AuthInfo to the individual tool requests. But I couldn't find any discussions or specs about this particular auth-related wrinkle. I would just like one or more of the core team to weigh in on the approach.

Copy link
Member

@jspahrsummers jspahrsummers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I think this broadly makes sense and seems useful, but I'd like to tidy up the interface a little bit.

FWIW the motivation behind my comments is basically: we will have to maintain support for whatever API we land upon. Object types are better for this purpose than positional parameters (they can be extended arbitrarily later), and as a bonus, they are also more self-explanatory and clearer in usage.

Please also update from main and resolve any conflicts.

allenzhou101 and others added 2 commits April 8, 2025 12:49
Co-authored-by: Justin Spahr-Summers <[email protected]>
Co-authored-by: Justin Spahr-Summers <[email protected]>
Copy link
Contributor

@cliffhall cliffhall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this still needs a few tweaks with regard to the extra object.

@allenzhou101
Copy link
Contributor Author

@cliffhall Ah yes sorry, haven't had the chance to make the changes yet. Will lyk when done.

@allenzhou101 allenzhou101 changed the title Include AuthInfo from Bearer Validation in Server Request Handler Include AuthInfo from Bearer Validation in Server Request Handler (eg. include auth in tool calls) Apr 12, 2025
@allenzhou101 allenzhou101 changed the title Include AuthInfo from Bearer Validation in Server Request Handler (eg. include auth in tool calls) Include AuthInfo from Bearer Validation in Server Request Handler (AKA include auth in tool calls) Apr 12, 2025
@allenzhou101 allenzhou101 changed the title Include AuthInfo from Bearer Validation in Server Request Handler (AKA include auth in tool calls) Include Authorization Info in Tool Calls (and request handlers generally) Apr 12, 2025
@apresmoi
Copy link

Hi, following this PR because I need something like this for the server I'm working on.

To understand how we might use this feature once merged, could you clarify these two points:

  • Regarding the Authorization validation, is the expectation that the token will be a standard JWT? or we will be able to use any kind of string?
  • How should the server-side validation logic be configured by the developer using the SDK? Will there be a callback option provided in ServerOptions to implement custom validation and return this AuthInfo?

Thank you!

@allenzhou101
Copy link
Contributor Author

Hi, following this PR because I need something like this for the server I'm working on.

To understand how we might use this feature once merged, could you clarify these two points:

  • Regarding the Authorization validation, is the expectation that the token will be a standard JWT? or we will be able to use any kind of string?
  • How should the server-side validation logic be configured by the developer using the SDK? Will there be a callback option provided in ServerOptions to implement custom validation and return this AuthInfo?

Thank you!

This PR simply adds the ability for the auth key on the request object to be passed from HTTP to SSE sort of automatically, ultimately accessible in the tool call via the extra object. How you set the AuthInfo on that key is up to you--the most common case likely involving usage of the bearer middleware included in the sdk itself that sets this for you. You would likely just have a middleware function that takes the token, validates it, and then sets the auth key with the AuthInfo object.

@apresmoi
Copy link

Hi, following this PR because I need something like this for the server I'm working on.
To understand how we might use this feature once merged, could you clarify these two points:

  • Regarding the Authorization validation, is the expectation that the token will be a standard JWT? or we will be able to use any kind of string?
  • How should the server-side validation logic be configured by the developer using the SDK? Will there be a callback option provided in ServerOptions to implement custom validation and return this AuthInfo?

Thank you!

This PR simply adds the ability for the auth key on the request object to be passed from HTTP to SSE sort of automatically, ultimately accessible in the tool call via the extra object. How you set the AuthInfo on that key is up to you--the most common case likely involving usage of the bearer middleware included in the sdk itself that sets this for you. You would likely just have a middleware function that takes the token, validates it, and then sets the auth key with the AuthInfo object.

Oh, I had not seen the bearer middleware. I have aligned with this now, thank you! Eager for this PR to be merged, currently I have to do a weird mapping to identify the user in the tools/dataset.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request waiting on submitter Waiting for the submitter to provide more info
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support passing auth context downstream into tool/prompt handlers
5 participants