MCP Server with Auth Middleware
December 8, 2025 · View on GitHub
This example demonstrates how to integrate the Go MCP SDK's auth.RequireBearerToken middleware with an MCP server to provide authenticated access to MCP tools and resources.
Features
The server provides authentication and authorization capabilities for MCP tools:
1. Authentication Methods
- JWT Token Authentication: JSON Web Token-based authentication
- API Key Authentication: API key-based authentication
- Scope-based Access Control: Permission-based access to MCP tools
2. MCP Integration
- Authenticated MCP Tools: Tools that require authentication and check permissions
- Token Generation: Utility endpoints for generating test tokens
- Middleware Integration: Seamless integration with MCP server handlers
Setup
cd examples/server/auth-middleware
go mod tidy
go run main.go
Testing
# Run all tests
go test -v
# Run benchmark tests
go test -bench=.
# Generate coverage report
go test -cover
Endpoints
Public Endpoints (No Authentication Required)
GET /health- Health checkGET /.well-known/oauth-protected-resource- OAuth 2.0 Protected Resource Metadata (RFC 9728)
MCP Endpoints (Authentication Required)
POST /mcp/jwt- MCP server with JWT authenticationPOST /mcp/apikey- MCP server with API key authentication
Utility Endpoints
GET /generate-token- Generate JWT tokenPOST /generate-api-key- Generate API key
Available MCP Tools
The server provides three authenticated MCP tools:
1. Say Hi (say_hi)
A simple greeting tool that requires authentication.
Parameters:
- None required
Required Scopes:
- Any authenticated user
2. Get User Info (get_user_info)
Retrieves user information based on the provided user ID.
Parameters:
user_id(string): The user ID to get information for
Required Scopes:
readpermission
3. Create Resource (create_resource)
Creates a new resource with the provided details.
Parameters:
name(string): The name of the resourcedescription(string): The description of the resourcecontent(string): The content of the resource
Required Scopes:
writepermission
Example Usage
1. Generating JWT Token and Using MCP Tools
# Generate a token
curl 'http://localhost:8080/generate-token?user_id=alice&scopes=read,write'
# Use MCP tool with JWT authentication
curl -H 'Authorization: Bearer <generated_token>' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"say_hi","arguments":{}}}' \
http://localhost:8080/mcp/jwt
2. Generating API Key and Using MCP Tools
# Generate an API key
curl -X POST 'http://localhost:8080/generate-api-key?user_id=bob&scopes=read'
# Use MCP tool with API key authentication
curl -H 'Authorization: Bearer <generated_api_key>' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_user_info","arguments":{"user_id":"test"}}}' \
http://localhost:8080/mcp/apikey
3. Testing Scope Restrictions
# Access MCP tool requiring write scope
curl -H 'Authorization: Bearer <token_with_write_scope>' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"create_resource","arguments":{"name":"test","description":"test resource","content":"test content"}}}' \
http://localhost:8080/mcp/jwt
Core Concepts
Authentication Integration
This example demonstrates how to integrate auth.RequireBearerToken middleware with an MCP server to provide authenticated access. The MCP server operates as an HTTP handler protected by authentication middleware.
Key Features
- MCP Server Integration: Create MCP server using
mcp.NewServer - Authentication Middleware: Protect MCP handlers with
auth.RequireBearerToken - Token Verification: Validate tokens using provided
TokenVerifierfunctions - Scope Checking: Verify required permissions (scopes) are present
- Expiration Validation: Check that tokens haven't expired
- Context Injection: Add verified token information to request context
- Authenticated MCP Tools: Tools that operate based on authentication information
- Error Handling: Return appropriate HTTP status codes and error messages on authentication failure
Implementation
// Create MCP server
server := mcp.NewServer(&mcp.Implementation{Name: "authenticated-mcp-server"}, nil)
// Create authentication middleware
authMiddleware := auth.RequireBearerToken(verifier, &auth.RequireBearerTokenOptions{
Scopes: []string{"read", "write"},
})
// Create MCP handler
handler := mcp.NewStreamableHTTPHandler(func(r *http.Request) *mcp.Server {
return server
}, nil)
// Apply authentication middleware to MCP handler
authenticatedHandler := authMiddleware(customMiddleware(handler))
Parameters
- verifier: Function to verify tokens (
TokenVerifiertype) - opts: Authentication options
Scopes: List of required permissionsResourceMetadataURL: OAuth 2.0 resource metadata URL
Error Responses
- 401 Unauthorized: Token is invalid, expired, or missing
- 403 Forbidden: Required scopes are insufficient
- WWW-Authenticate Header: Included when resource metadata URL is configured
Implementation Details
1. TokenVerifier Implementation
func jwtVerifier(ctx context.Context, tokenString string) (*auth.TokenInfo, error) {
// JWT token verification logic
// On success: Return TokenInfo
// On failure: Return auth.ErrInvalidToken
}
2. Using Authentication Information in MCP Tools
// Get authentication information in MCP tool
func MyTool(ctx context.Context, req *mcp.CallToolRequest, args MyArgs) (*mcp.CallToolResult, any, error) {
// Extract authentication info from request
userInfo := req.Extra.TokenInfo
// Check scopes
if !slices.Contains(userInfo.Scopes, "read") {
return nil, nil, fmt.Errorf("insufficient permissions: read scope required")
}
// Execute tool logic
return &mcp.CallToolResult{
Content: []mcp.Content{
&mcp.TextContent{Text: "Tool executed successfully"},
},
}, nil, nil
}
3. Middleware Composition
// Combine authentication middleware with custom middleware
authenticatedHandler := authMiddleware(customMiddleware(mcpHandler))
Security Best Practices
- Environment Variables: Use environment variables for JWT secrets in production
- Database Storage: Store API keys in a database
- HTTPS Usage: Always use HTTPS in production environments
- Token Expiration: Set appropriate token expiration times
- Principle of Least Privilege: Grant only the minimum required scopes
CORS Support
The OAuth metadata endpoint (/.well-known/oauth-protected-resource) supports CORS to enable
cross-origin client discovery. It sets Access-Control-Allow-Origin: * by default because
OAuth metadata is public information meant for client discovery (RFC 9728 §3.1).
Custom CORS Policies
For more sophisticated CORS requirements (origin validation, credentials, etc.), wrap the handler with a CORS middleware library:
Using github.com/rs/cors:
import "github.com/rs/cors"
c := cors.New(cors.Options{
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET", "OPTIONS"},
})
http.Handle("/.well-known/oauth-protected-resource",
c.Handler(auth.ProtectedResourceMetadataHandler(metadata)))
Using github.com/jub0bs/cors:
import "github.com/jub0bs/cors"
corsMiddleware, err := cors.NewMiddleware(cors.Config{
Origins: []string{"https://example.com"},
Methods: []string{"GET", "OPTIONS"},
})
http.Handle("/.well-known/oauth-protected-resource",
corsMiddleware.Wrap(auth.ProtectedResourceMetadataHandler(metadata)))
Use Cases
Ideal for:
- MCP servers requiring authentication and authorization
- Applications needing scope-based access control
- Systems requiring both JWT and API key authentication
- Projects needing secure MCP tool access
- Scenarios requiring audit trails and permission management
Examples:
- Enterprise MCP servers with user management
- Multi-tenant MCP applications
- Secure API gateways with MCP integration
- Development environments with authentication requirements
- Production systems requiring fine-grained access control