Customer auth for remote MCP clients
Connect one customer-protected MCP server to standards-based clients with OAuth discovery, DCR, PKCE, refresh tokens, and resource-bound access tokens.
Noodle Seed verifies customer access tokens and protects your MCP tools. For direct or federated OIDC, your application developer still owns the authorization server that signs users in and issues those tokens.
This boundary keeps the architecture simple:
| Person or system | Responsibility |
|---|---|
| App user | Adds the deployed MCP URL to a client and completes the normal sign-in and consent flow. |
| App developer | Publishes standards-compliant OAuth discovery, registration, authorization, token, refresh, and JWKS behavior. |
| Noodle Seed | Advertises the configured issuer, verifies resource-bound access tokens, diagnoses readiness, and runs the tools. |
| MCP client | Discovers the issuer, registers or uses a configured OAuth client, opens sign-in, refreshes tokens, and calls the MCP server. |
Noodle Seed does not put an OAuth compatibility proxy in front of a direct or federated issuer. The app developer fixes the issuer once, and every standards-based remote MCP client benefits.
Choose the customer auth shape
Use a built-in adapter when your customers already sign in with one of the supported managed providers:
auth: customerAuth.firebase({
projectId: variable('FIREBASE_PROJECT_ID'),
apiKey: variable('FIREBASE_WEB_API_KEY'),
authDomain: variable('FIREBASE_AUTH_DOMAIN'),
})Use direct OIDC when one issuer protects the app:
auth: customerAuth.oidc({
issuer: 'https://id.example.com/oauth',
audience: 'https://acme.cloud.noodleseed.dev/support/mcp',
})Use federated OIDC when an exact allowlist of issuers can identify customers:
auth: customerAuth.federatedOidc({
issuers: [
{
issuer: 'https://id.example.com/oauth',
audience: 'https://acme.cloud.noodleseed.dev/support/mcp',
},
],
})The rest of this guide applies to direct and federated OIDC. Built-in adapters use their managed authorization-server path.
What the app developer must publish
1. Direct RFC 8414 discovery
For an issuer with a path, OAuth clients try the path-inserted authorization-server metadata URL first.
| Configured issuer | Required primary discovery URL |
|---|---|
https://id.example.com | https://id.example.com/.well-known/oauth-authorization-server |
https://id.example.com/oauth | https://id.example.com/.well-known/oauth-authorization-server/oauth |
The primary URL must:
- Be publicly reachable without cookies or an existing login.
- Return HTTP
200directly, without a301,302,307, or308login redirect. - Return a JSON object.
- Contain an
issuervalue that exactly matches the configured issuer.
2. Complete OAuth metadata
A minimal interoperable document looks like this:
{
"issuer": "https://id.example.com/oauth",
"authorization_endpoint": "https://id.example.com/oauth/authorize",
"token_endpoint": "https://id.example.com/oauth/token",
"jwks_uri": "https://id.example.com/oauth/jwks",
"registration_endpoint": "https://id.example.com/oauth/register",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["none"]
}The endpoints must use HTTPS. registration_endpoint is Dynamic Client Registration under RFC 7591.
Remote MCP clients are public OAuth clients, so they use PKCE rather than a client secret. Support:
- Authorization code flow.
- PKCE with
S256. - Public clients with token endpoint auth method
none. - Refresh tokens, including safe rotation and revocation.
- The exact redirect URIs submitted during registration.
3. Resource-bound access tokens
Implement the RFC 8707 resource parameter on both authorization and token requests. The resulting
access token must identify the exact MCP resource URL in its aud claim.
For example:
resource=https://acme.cloud.noodleseed.dev/support/mcp
aud=https://acme.cloud.noodleseed.dev/support/mcpDo not issue a generic token for every API. Noodle Seed rejects tokens whose issuer or audience does not match the configured customer auth and deployed MCP resource.
4. A public JWKS
jwks_uri must return HTTP 200 JSON with at least one public RSA, EC, or OKP signing key. Never publish
private fields such as d, p, q, or a symmetric k.
Check before sharing
Run the read-only diagnostic against the authored server:
noodle auth doctor src/server.tsIt verifies the primary RFC 8414 route, exact issuer, endpoints, authorization-code and refresh support, PKCE, public-client support, DCR advertisement, and public JWKS. Its issuer-readiness probes send bounded GET requests only. They do not submit a registration request, create a client, or mutate the authorization server.
For machine-readable findings:
noodle auth doctor src/server.ts --jsonEach finding has a stable code, level, optional issuer, message, and repair instruction. A direct or
federated issuer is ready only when every required check passes.
Then deploy:
noodle deploy src/server.ts --access customersA successful customer deploy runs the same readiness diagnostic. OAuth failures are warnings, not deploy failures, because the MCP artifact is already live and the app developer can repair the issuer independently. JSON output includes:
{
"ok": true,
"data": {
"authReadiness": {
"ready": false,
"checks": [
{
"code": "oauth_metadata_discovery",
"level": "FAIL",
"issuer": "https://id.example.com/oauth",
"message": "the attempted metadata URL and safe HTTP status",
"fix": "Serve the path-inserted RFC 8414 URL directly as HTTP 200 JSON."
}
]
}
}
}Repair the issuer, rerun noodle auth doctor src/server.ts, and reconnect the client. You do not need to
redeploy when only the external authorization server changed.
What the user experiences
When everything is ready:
- The user enters the deployed MCP server URL in a compatible client.
- The client reads protected-resource metadata and discovers the configured authorization server.
- The client dynamically registers a public OAuth client, or uses another standards-supported registration method.
- The browser opens the app's authorization page.
- The user signs in and grants access.
- The authorization server returns an authorization code bound to PKCE and the MCP resource.
- The client exchanges the code, stores the access and refresh tokens, and calls the MCP endpoint.
- Noodle Seed verifies issuer, signature, expiry, and the exact MCP audience before any tool runs.
If the client asks the user for a client ID and secret immediately, discovery or Dynamic Client Registration did not complete. That prompt is a useful compatibility fallback, but it is not the preferred customer experience.
Copy this request to the app developer
Please make our authorization server compatible with standards-based remote MCP clients. Publish the path-inserted RFC 8414 metadata URL as unauthenticated HTTP 200 JSON with the exact issuer and HTTPS
authorization_endpoint,token_endpoint,jwks_uri, and RFC 7591registration_endpoint. Support authorization code, refresh tokens, PKCE S256, public clients using token endpoint auth methodnone, exact registered redirect URIs, RFC 8707resource, access-tokenaudequal to the exact MCP URL, and a public JWKS with no private key material. Do not redirect the metadata URL to login. Verify the result withnoodle auth doctor src/server.ts; the command is read-only and will identify each remaining gap.
Client-specific notes
The OAuth contract above is host-neutral. Client features and availability change independently:
- Gemini Spark's custom Connected Apps documentation says it accepts an MCP server URL and offers manual credentials under Advanced features when the server does not support DCR.
- Claude's remote MCP documentation explicitly supports DCR, manual client credentials as a fallback, token expiry, and refresh.
- ChatGPT's current developer-mode documentation requires a working OAuth flow and calls out refresh-token configuration. Follow its current setup and review requirements in addition to this protocol checklist.
Use the clients' current official documentation when running release acceptance. A client-specific smoke is evidence for that client and date, not a permanent protocol guarantee.
Embed an assistant in your SaaS
Deploy a Noodle Seed assistant, exchange your existing signed-in user on the backend, and mount the published browser SDK without exposing credentials.
Deploy & operate
Ship your server to a governed, identity-gated MCP URL. Environments, access modes, secrets, variables, and rollback.