Build MCP servers with external OAuth
When building production MCP servers, you often need to protect sensitive endpoints with OAuth authentication. This guide shows you how to build an MCP server with external OAuth authentication. We’ll use FusionAuth as an example, but you can use any OAuth 2.0 provider you have set up (such as Auth0, Okta, Keycloak, or your own OAuth server).
We’ll build an enhanced version of the Push Advisor API from earlier guides, adding OAuth-protected endpoints that demonstrate real-world authentication patterns.
:::tip[Already have OAuth set up?] If you already have an API with OAuth authentication and just want to configure Gram to use it, you can skip directly to Configuring Gram to use OAuth. :::
:::note[Live demo available]
You can test the complete OAuth implementation at https://gram-oauth.abdulbaaridavids04.workers.dev
What we’ll build
In this guide, we’ll:
- First, set up an API with both public and OAuth-protected endpoints
- Next, configure an external OAuth provider (we’ll use FusionAuth as an example)
- Then create a manual login flow for token testing
- Finally, integrate with Gram’s OAuth configuration and test protected endpoints in the playground
Setting up the project
First, we’ll start with extending the Push Advisor API
We’ve added a deploy-history
endpoint that requires OAuth authentication. We’ve also added a login
endpoint that provides a manual login page for token generation.
Configuring your OAuth provider
Before we implement OAuth protection in our API, we need to set up an OAuth provider. In this example, we’ll use FusionAuth, but the same principles apply to any OAuth 2.0 compliant provider like Auth0, Okta, Keycloak, or your own implementation.
Application setup
First, we’ll set up our OAuth provider to work with our API. These steps are similar across different OAuth providers:
-
Create Application: In your OAuth provider’s admin panel, create a new application/client named “Push Advisor API”
-
OAuth Configuration:
- Enable Authorization Code grant type
- Set redirect URLs:
- Get Credentials: Note the Client ID and Client Secret for your configuration
API configuration
Now we can configure our OAuth provider settings in the API. Replace these values with your actual OAuth provider’s configuration:
Next, we’ll implement the OAuth protection within the API. We’ll add middleware that validates OAuth tokens against our external provider.
Protected endpoint implementation
Next, we’ll implement endpoints that require authentication:
OAuth discovery endpoint
We’ll also need to implement the OAuth discovery endpoint required by the MCP specification:
Manual login page
For testing purposes, we’ll create a basic login page for token generation:
Defining OAuth in the OpenAPI document
Next, we’ll document our OAuth configuration in the OpenAPI document, you can read more about how Gram uses the OpenAPI document here.
Configuring Gram to use OAuth
Now we’ll configure Gram to work with our external OAuth server. After uploading the OpenAPI document, and creating a new toolset, go to the toolset settings page and click Connect OAuth.
:::note[Note] You’ll need to make your toolset public to use OAuth. :::
In the OAuth configuration page, choose External Server instead of OAuth Proxy and enter the server slug as well as the metadata for your OAuth server.
The OAuth Authorization Server Metadata is a JSON object that describes the OAuth server. It’s used by Gram to discover the OAuth server’s capabilities.
You can read more about the OAuth Authorization Server Metadata here
:::tip[Using different OAuth providers]
The metadata format is standardized across OAuth providers. Most providers offer a discovery endpoint (like /.well-known/openid-configuration
) that returns this metadata automatically. Check your OAuth provider’s documentation for their specific discovery URL or metadata format.
:::
Testing in Gram playground
Finally, let’s test everything in the Gram playground.
After uploading our OpenAPI document and creating a toolset, we’ll go to the playground to test it. When we ask the AI agent to get deployment history, it will automatically detect that OAuth authentication is required:
Notice how the environment variables section shows PUSH_ADVISOR_OAUTH_ACCESS_TOKEN
is <EMPTY>
, and the agent tells us exactly what we need to do to authenticate. The agent can also discover the OAuth requirements automatically by calling the discovery endpoint.
we can see that an OAuth access token is required but not yet provided:
:::note[Note] In the Gram playground, you need to manually add OAuth tokens to environment variables for testing. In a proper MCP client implementation, the OAuth flow would be handled automatically by the client, including token refresh and management. :::
Getting an OAuth token
To test our protected endpoints, we need to get a valid OAuth token. Here’s how a user would get an OAuth token:
- Visit the login page: First, we go to the
/login
page provided by the API to start the authentication process
- Redirect to OAuth Provider: Click “Login with OAuth Provider” which redirects to your OAuth provider’s login screen (in this example, FusionAuth):
-
Complete authentication: After logging in, your OAuth provider redirects back to our API with an authorization code
-
Get the access token: Copy the access token from the success page
Adding the token to Gram
Now we can add our OAuth token to the Authentication environment variables in Gram:
Once we’ve added a valid OAuth token, we can test the protected endpoints in the playground:
Troubleshooting
OAuth is a complex topic, and there are many ways to configure it. Here are some common issues and how to troubleshoot them.
Common issues
Invalid redirect URI: Ensure all redirect URLs are configured in your OAuth provider
Token validation fails: Check that your client credentials are correct and the OAuth provider is accessible
CORS issues: Include proper CORS headers for browser-based OAuth flows
Scope mismatches: Verify that requested scopes match what’s configured in your OAuth provider
Last updated on