diff --git a/README.md b/README.md index f2aeef2c..496ebe75 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,117 @@ await test.cleanupItems(); await test.removeUser('test@example.com'); ``` +## MCP Auth + +CDK Serverless includes built-in support for adding [Model Context Protocol (MCP)](https://spec.modelcontextprotocol.io) OAuth authentication to your API. This enables MCP clients like Claude and ChatGPT to authenticate with your API using standard OAuth 2.0 flows. + +When activated, the following endpoints are automatically added to your OpenAPI spec: + +| Endpoint | Method | RFC | Purpose | +|----------|--------|-----|---------| +| `/.well-known/oauth-protected-resource` | GET | RFC 9728 | Resource metadata discovery | +| `/.well-known/oauth-authorization-server` | GET | RFC 8414 | Authorization server metadata | +| `/oauth/authorize` | GET | — | Authorize proxy (redirect to upstream) | +| `/oauth/token` | POST | — | Token proxy (forward to upstream) | +| `/oauth/register` | POST | RFC 7591 | Dynamic client registration | + +All MCP auth endpoints are anonymous (no API authorizer applied). + +### With Cognito + +MCP clients like Claude enforce that all OAuth endpoints (discovery, authorize, token, register) live on the **same origin** as the API itself. Cognito's hosted UI lives on a different domain (`auth.example.com`), so MCP clients cannot talk to it directly. Additionally: + +- Cognito Managed Login v2 requires the RFC 8707 `resource` parameter for custom scopes in authorize requests — MCP clients do not send this parameter. +- MCP clients construct the token endpoint URL from the OAuth metadata `issuer` field rather than using the explicit `token_endpoint` — so the token exchange must be proxied through the API domain. +- Dynamic Client Registration (RFC 7591) is not natively supported by Cognito. + +The MCP auth proxy solves all three problems: it serves discovery metadata on the API domain, strips unsupported parameters before forwarding to Cognito, and implements a simplified registration endpoint that returns a pre-provisioned client ID. + +If your API already uses `CognitoAuthentication`, add MCP auth with minimal config — a dedicated user pool client is created automatically: + +```typescript +const api = new TestApiRestApi(this, 'Api', { + stageName: 'dev', + domainName: 'example.com', + apiHostname: 'api', + authentication: cognitoAuth, + cors: true, + mcpAuth: { + cognito: { + auth: cognitoAuth, // your CognitoAuthentication construct + authDomain: 'auth.example.com', // Cognito custom/hosted domain (required) + }, + serverInfo: { name: 'my-mcp-server', version: '1.0.0' }, + }, +}); +``` + +The `apiDomain` is derived from the RestApi's own domain config (`apiHostname` + `domainName`), and `stageName` is reused — no duplication needed. + +### With any OAuth2 provider + +For non-Cognito providers, use `generic` mode with explicit endpoint URLs: + +```typescript +const api = new TestApiRestApi(this, 'Api', { + // ... + mcpAuth: { + generic: { + authorizeEndpoint: 'https://auth.example.com/authorize', + tokenEndpoint: 'https://auth.example.com/token', + clientId: 'my-pre-provisioned-client-id', + }, + serverInfo: { name: 'my-mcp-server', version: '1.0.0' }, + }, +}); +``` + +### Configuration options + +| Option | Default | Description | +|--------|---------|-------------| +| `serverInfo` | (required) | `{ name, version }` returned in MCP initialize | +| `allowedRedirectUris` | Claude + ChatGPT callbacks | Allowlist for dynamic registration | +| `protocolVersions` | `['2025-11-25', '2025-03-26', '2024-11-05']` | Supported MCP versions | +| `scopes` | `['openid', 'email', 'profile']` | Advertised OAuth scopes | +| `stripParameters` | `['resource']` | Params stripped from authorize/token proxying | +| `lambdaOptions` | — | Lambda config for MCP auth handlers | + +### MCP Server runtime + +The `cdk-serverless/mcp-auth` module also exports a JSON-RPC server for implementing the MCP tool endpoint itself: + +```typescript +import { createMcpServer } from 'cdk-serverless/mcp-auth'; + +const server = createMcpServer({ + serverInfo: { name: 'my-server', version: '1.0.0' }, + protocolVersions: ['2025-11-25'], + resolver: { + async resolve(headers) { + // Validate Bearer token, return principal or throw McpUnauthorizedError + const token = headers.authorization?.replace('Bearer ', ''); + if (!token) throw new McpUnauthorizedError('Bearer'); + return verifyToken(token); + }, + }, + tools: [ + { + name: 'search', + description: 'Search documents', + inputSchema: { type: 'object', properties: { query: { type: 'string' } } }, + async invoke(principal, args) { + const results = await search(principal, (args as any).query); + return { content: [{ type: 'text', text: JSON.stringify(results) }] }; + }, + }, + ], +}); + +// In your Lambda handler: +const response = await server.handle(parsedBody, event.headers); +``` + ## Breaking Change: `axios` Removed CDK Serverless no longer depends on `axios`. The library now uses the diff --git a/docs/constructs/assets/hierarchy.js b/docs/constructs/assets/hierarchy.js index 907e3636..e76642bb 100644 --- a/docs/constructs/assets/hierarchy.js +++ b/docs/constructs/assets/hierarchy.js @@ -1 +1 @@ -window.hierarchyData = "eJyVkztvwyAYRf/LN5MmNoZgtqSVqm59bVEG6pAYlUAEZIr83ytat6WN5cfiwb4f5x4MF3DWBg98w0q0xCjPEcXZFoGTey2roKzxwC+Q5/FpxFECh4dbezAq2NU51NIEVYmYAwTvyuyA54QiODsNHJQJ0u1FJf28e+imDkcNCCotvAcOwe9mcZXZz2T8WCu9c9IA3xTltkFQlEmb/jJZzr7LfDKkn08r8vWiQbDECXQtvFyd1KOzJz8gnkan6mJCEVmw6MzKa3yfZRsZ8PpLYxQRXEQaJjTB3Ttxqp/0SOF/6RHOEci6gX2Kv6nhv0cWLFn/Wfow0iaNjlMhuLhG9Xm0kWEJirP0Gr4oc9DyVbxpeSeC8ME6OXQLu2amnkpakHhGaEGSNr1lOqQnFWl3oGk+AKzSjMo=" \ No newline at end of file +window.hierarchyData = "eJyVk0tzwiAUhf/LXWNVEglhZ9uZTnd97RwXNF4NUwQHcOXkv3ewtqU1k8eGBZx7z/ngcgJnbfAgVrwkRUYoJUWWrwk43GqsgrLGgzgBpXE1co8g4PHO7owKdnkMNZqgKhl1QOBDmQ0IumAEjk6DAGUCuq2s0E/bi27qsNdAoNLSexAQ/GYSu0x+KuNhrfTGoQGxyst1QyAvkzTdYeaUf4c5e6CfjgvytdEQKLLE9FZ6XB7Uk7MH3wOeSsfiZgtG2GwemXl5bd9FeZH0cP1144wwyqNbtmCJ3YOTh/pZDwT+px7AHA15u2EX4q+q//XYbJ70f0EfBtKk0mEojPJrqy6Oi2TICObpN3xVZqfxTb5rvJdB+mAd9v3CtpqxU1nk5xkp8pSzM0wL9Kgglxtomk+59IzW" \ No newline at end of file diff --git a/docs/constructs/assets/navigation.js b/docs/constructs/assets/navigation.js index e34f79f2..5233b221 100644 --- a/docs/constructs/assets/navigation.js +++ b/docs/constructs/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "eJyNlF1PwjAUhv9Lr4kKCX5whxiNxERFoheGi7IdtobSLu1BNIb/bjQb2+zpGdfnOc/ete/2/i0QPlGMxNh7wElqRE8UEnMxEomW3oM/rSYnOW606Im1MqkY9QeX+95h+1p6GBcqXC4H3O7EZkahHW8xB4MqkagsEYPEOO+dk0X+rMlY9YwzPMjNMpW3W5PQkdpzzjQDj2SQcsDtviiTaZjLpYYbidKjdRCKKIqzvlm3Xmm7C03VhNuuOvHkbOFrhTIIbiWTRmv+iLZqMDwPqxM3NQFORBYkro3j3EPq4sTN/xhOd99R/oaVRln5dIfHiAOMlfJ1bHq7K9lWT/0MvNUf4B6L3xj06QYUp2x/ofErI7hu7dzJRJmMC0uBnLj8HcSDNgFORJ193Bqlj30EeJXR7QooTvmK+pgKhBgnrf5n8ddvEd33HkTDr+Jw13Sgs6uL/nCwX/wACnuUNw==" \ No newline at end of file +window.navigationData = "eJyNlU1PAjEQQP9Lz0SFBD+4IUYi0ahI9GA8lKXsNpR20w6iMfx3o9mFLp3O9jxvXqftTPv+w0B8ARuwoXMCRgvNOqzkULAByxR3TrjTOnJSwFqxDltJvWCDbu9y19lnX3MnhqUMk6sAlTsyuZZghhsohAaZcZAGKQPFKO/Y8rJ4VmhZhxhluOfr+YLfbnSGl9SMU6aHrPwrPFRUgZZcb++owotTpqlwgB5HFaByX6TOlZjxuRI3HLgDY0UowijK+mbsaqnMNjTVESq77swna0p3UEgNwi555vXuP9FU9frnYQPHTT5AidA2jWvjOLXIoX3j5iOG0t21jKBnxVFSPtlCijjASCndjr63vSWb6ombCmfUp7CP5V8Z+OkGFKVsvhPxK0O4du3M8kzqnCoWAylx9ShVV02ZUTJBXe+RtO6hBOFYaGFlllBrk0xQJzjTZfHL94EWkTeDpO+Yo7TVFxD3+QAlwuYtbo3SqUsIJ3P8RQkoSvkKKmXsQ4yS1n9YfPsNon3Wg9Lgu9zPN17Q2dVFt9/bffwCDG1v9A==" \ No newline at end of file diff --git a/docs/constructs/assets/search.js b/docs/constructs/assets/search.js index 6f621f2c..7a03f716 100644 --- a/docs/constructs/assets/search.js +++ b/docs/constructs/assets/search.js @@ -1 +1 @@ -window.searchData = "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"; \ No newline at end of file +window.searchData = "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"; \ No newline at end of file diff --git a/docs/constructs/classes/McpAuth.html b/docs/constructs/classes/McpAuth.html new file mode 100644 index 00000000..8e075568 --- /dev/null +++ b/docs/constructs/classes/McpAuth.html @@ -0,0 +1,43 @@ +
ReadonlyfunctionsThe Lambda functions created for the OAuth endpoints.
+ReadonlymcpThe environment variables map that should be injected into the MCP RPC +handler Lambda (if you have one) so it can read MCP config at runtime.
+ReadonlynodeThe tree node.
+Returns a string representation of this construct.
+Applies one or more mixins to this construct.
+Mixins are applied in order. The list of constructs is captured at the
+start of the call, so constructs added by a mixin will not be visited.
+Use multiple with() calls if subsequent mixins should apply to added
+constructs.
The mixins to apply
+This construct for chaining
+StaticisChecks if x is a construct.
Use this method instead of instanceof to properly detect Construct
+instances, even when the construct library is symlinked.
Explanation: in JavaScript, multiple copies of the constructs library on
+disk are seen as independent, completely different libraries. As a
+consequence, the class Construct in each copy of the constructs library
+is seen as a different class, and an instance of one class will not test as
+instanceof the other class. npm install will not create installations
+like this, but users may manually symlink construct libraries together or
+use a monorepo tool: in those cases, multiple copies of the constructs
+library can be accidentally installed, and instanceof will behave
+unpredictably. It is safest to avoid using instanceof, and using
+this type-testing method instead.
Any object
+true if x is an object created from a class which extends Construct.
Convenience construct that creates an McpAuth backed by Amazon Cognito.
+It creates a dedicated Cognito user pool client configured for the +authorization code + PKCE flow and wires it into the generic McpAuth +construct. Use this when your authentication is managed by Cognito; +use McpAuth directly for other OAuth2/OIDC providers.
+const mcpAuth = new McpCognitoAuth(this, 'McpAuth', {
auth: cognitoAuthentication,
apiDomain: 'api.example.com',
authDomain: 'auth.example.com',
serverInfo: { name: 'my-mcp-server', version: '1.0.0' },
stageName: 'dev',
});
const api = new MyApiRestApi(this, 'Api', {
mcpAuth: mcpAuth.mcpAuth,
// ...
});
+
+
+ReadonlymcpThe underlying service-agnostic McpAuth construct.
+Pass this to RestApi's mcpAuth prop.
ReadonlynodeThe tree node.
+ReadonlyuserThe Cognito user pool client created for MCP connectors.
+Returns a string representation of this construct.
+Applies one or more mixins to this construct.
+Mixins are applied in order. The list of constructs is captured at the
+start of the call, so constructs added by a mixin will not be visited.
+Use multiple with() calls if subsequent mixins should apply to added
+constructs.
The mixins to apply
+This construct for chaining
+StaticisChecks if x is a construct.
Use this method instead of instanceof to properly detect Construct
+instances, even when the construct library is symlinked.
Explanation: in JavaScript, multiple copies of the constructs library on
+disk are seen as independent, completely different libraries. As a
+consequence, the class Construct in each copy of the constructs library
+is seen as a different class, and an instance of one class will not test as
+instanceof the other class. npm install will not create installations
+like this, but users may manually symlink construct libraries together or
+use a monorepo tool: in those cases, multiple copies of the constructs
+library can be accidentally installed, and instanceof will behave
+unpredictably. It is safest to avoid using instanceof, and using
+this type-testing method instead.
Any object
+true if x is an object created from a class which extends Construct.
The type definition for the API paths.
The type definition for the API operations.
-The operation IDs to add to the anonymous set.
Protectedcleanupreturn the generated Lambda function for the specified API operation
return a list of all generated Lambda functions
-Visitor method to modify the given functions
+Returns the MCP auth construct if mcpAuth was configured. +Useful for accessing the created Lambda functions or env vars.
+Visitor method to modify the given functions
the list of functions to visit
the function to call for every function
ProtectedpatchAWS does not properly apply the 'security' option to every single path-method. @@ -88,4 +91,4 @@ this type-testing method instead.
Any object
true if x is an object created from a class which extends Construct.
CDK construct that creates Lambda functions for the MCP OAuth façade. +Service-agnostic — proxies authorize/token requests to any upstream +OAuth2/OIDC provider.
+Use with
+RestApiby passingmcpAuthprop, which auto-injects the +required paths into the OpenAPI spec and wires Lambda integrations.Example
+ +