Skip to content
Gram

Add OAuth to an MCP Server

Starting March 2025, the MCP specification recommends OAuth-based authentication for MCP Servers. If your API already supports OAuth, placing an OAuth provider in front of your MCP Server is a great option.

The Gram product exposes a variety of different options for OAuth that you can integrate into your Gram MCP Servers. Your OpenAPI spec must include OAuth as a security option for your endpoints.

security:
- oauth2Example: [pets:read]
components:
securitySchemes:
oauth2Example:
type: oauth2
flows:
authorizationCode:
authorizationUrl: /oauth/authorize
tokenUrl: /oauth/token
scopes:
pets:read: Read pet information
pets:write: Modify pet information

Gram always allows passing pre-obtained OAuth access tokens directly to an MCP server. This will be available to a developer for any OAuth flow:

  • authorizationCode
  • clientCredentials
  • implicit

If your API uses the clientCredentials flow, Gram allows you to pass a client_id and client_secret into your MCP server. The server will do the token exchange using those provided environment values. The tool call flow will automatically cache tokens received from a token exchange based on the expiration of that token. We natively support both client_secret_post and client_secret_basic flows.

When the MCP spec refers to placing a user-facing OAuth flow in front of a server, it is typically referring to the authorizationCode flow.

Gram fully supports registering an OAuth server in front of MCP servers for your users to interact with. Something that is important to keep in mind is that the MCP specification has very specific requirements for how a company’s OAuth API needs to work. The main requirement is that MCP clients require OAuth2.1 and Dynamic Client Registration.

The requirements for MCP OAuth can be found here. Dynamic Client Registration (DCR) is typically the feature that most companies do not currently support.

While this is still fairly unadopted, companies like Stripe, Asana & more have started to support DCR in their OAuth flows to accommodate MCP. If you want to host an MCP server for large-scale use by external developers, you should plan to build out support for DCR in your API.

If your underlying API supports the necesarilly OAuth requirements, you can easily place any OAuth server in front of any Gram MCP Server with just a few clicks!

Only one OAuth flow can be placed in front of an MCP server, so it is very important that your MCP server only includes a single downstream API provider that takes in OAuth.

The artifact you are able to produce should look something like this:

{
"issuer": "https://marketplace.stripe.com",
"authorization_endpoint": "https://marketplace.stripe.com/oauth/v2/authorize",
"token_endpoint": "https://marketplace.stripe.com/oauth/v2/token",
"registration_endpoint": "https://marketplace.stripe.com/oauth/v2/register/tailorapp%2AAZfBZ6Q69QAAADJI%23EhcKFWFjY3RfMVJlaTA0QUo4QktoWGxzQw",
"response_types_supported": [
"code"
],
"grant_types_supported": [
"authorization_code",
"refresh_token"
],
"code_challenge_methods_supported": [
"S256"
],
"token_endpoint_auth_methods_supported": [
"none"
]
}

For companies whose OAuth systems do not yet support the MCP requirements, Gram offers an OAuth proxy that translates between MCP requirements and standard OAuth implementations. This proxy will perform an MCP-compliant exchange with an MCP Client on your API’s behalf:

  • Expose the MCP client requirements of OAuth 2.1/Dynamic Client Registration
  • The server will integrate with your actual OAuth API behind the scenes, based on a single client_id and client_secret pairing you provide in your server configuration.

Functionally, this is very similar to solutions others might be familiar with, such as the Cloudflare OAuth proxy.

This solution works well for many use cases, though it may not be suitable for every scenario depending on your server’s specific goals. This is useful for MCP servers that don’t require dynamic public clients, or in cases where acting as a single underlying OAuth provider is a reasonable tradeoff.

You will store the following in Gram to enable our OAuth proxy to interact with your underlying OAuth provider:

  • Authorization Endpoint
  • Token Endpoint
  • Client ID & Client Secret
  • List of Scopes (optional)
  • Token endpoint auth methods supported (optional)
  • You may need to whitelist oauth proxy redirect uris in your OAuth provider (https://{mcp_server_domain}.com/oauth/{mcp_slug}/callback)