How OpenSEO MCP Server Handles OAuth and Direct API Authentication
OpenSEO supports both OAuth 2.0 Authorization Code flows and direct API key authentication for its MCP server, converging both paths on a unified transport layer that strictly enforces the mandatory mcp scope.
The OpenSEO MCP (Machine Control Protocol) server implements a dual-path authentication architecture designed to accommodate interactive user sessions and programmatic API access. According to the every-app/open-seo source code, the system maintains distinct entry points for OAuth-based and API key-based authentication while routing all validated requests through a common transport layer that guarantees authorization consistency.
OAuth 2.0 Authorization Code Flow
The primary authentication method for interactive clients follows the standard OAuth 2.0 Authorization Code flow, implemented in src/server/mcp/oauth-provider.ts through the createOpenSeoOAuthProvider() factory function. This provider integrates with Cloudflare Workers OAuth Provider (@cloudflare/workers-oauth-provider) and Better Auth for persistent storage.
Authorization Endpoint and User Consent
The flow initiates when a client sends a request to /api/auth/oauth2/authorize. The provider parses the request and checks authentication status via resolveHostedContext:
// src/server/mcp/oauth-provider.ts
if (url.pathname === OAUTH_AUTHORIZE_PATH) {
return handleOAuthAuthorizeRequest(request, env);
}
Unauthenticated users are redirected to the sign-in page, while authenticated users proceed to the consent UI at /oauth-consent. The consent interface displays requested scopes, always including the mandatory mcp scope defined in src/lib/oauth-resource.ts. If the user denies consent, the authorization fails immediately.
Token Issuance and Scope Validation
Upon consent approval, the provider creates an OAuth grant containing the user's ID, email, organization, and granted scopes. The system validates scope presence using getGrantedMcpScopes():
// src/server/mcp/oauth-provider.ts
let scopes = getGrantedMcpScopes(authRequest.scope); // throws if `mcp` missing
The grant is stored in the Better Auth KV store, and an authorization code is returned to the client. The client exchanges this code at /api/auth/oauth2/token, where the tokenExchangeCallback validates the grant and issues an access token (TTL: 24 hours) and refresh token (TTL: 30 days).
Direct API Key Authentication
For programmatic access, OpenSEO supports direct authentication via API keys implemented in src/server/mcp/api-key-auth.ts. This path bypasses the OAuth redirect flow while maintaining equivalent security controls and rate limiting.
Key Validation and Rate Limiting
The system inspects incoming requests for an x-api-key header or Bearer token. Valid MCP API keys must carry the oseo_ prefix defined in src/lib/auth-api-key.ts. The key is validated against Better Auth using auth.api.verifyApiKey:
// src/server/mcp/api-key-auth.ts
const apiKey = getApiKey(request); // looks for header 'x-api-key' or Bearer token
if (!apiKey) return null; // fall back to OAuth provider
Upon successful validation, the system applies a per-user rate limit of 5000 requests per minute via the Cloudflare Rate-Limit binding MCP_RATE_LIMIT.
Organization Resolution and Scope Assignment
After validation, resolveExistingActiveHostedOrganization() determines the user's active organization. The system constructs an MCP auth-props object using createWorkersOAuthMcpProps(), assigning the special client ID "api_key" and granting the full set of MCP OAuth scopes (MCP_OAUTH_SCOPES).
Unified Transport Layer Enforcement
Both authentication paths converge at src/server/mcp/transport.ts, where handleAuthenticatedOpenSeoMcpRequest() performs final authorization. The transport extracts the MCP_AUTH_CONTEXT_PROP from either the OAuth token or API key props, then enforces that MCP_SCOPE is present:
// src/server/mcp/transport.ts
if (!result.data[MCP_AUTH_CONTEXT_PROP].scopes.includes(MCP_SCOPE)) {
return new Response("MCP scope required", { status: 403 });
}
If the scope check fails, the server returns a 403 Forbidden response. The transport layer also injects CORS headers allowing requests from any origin, supporting self-hosted MCP clients.
Summary
- Dual authentication paths: OpenSEO supports both OAuth 2.0 Authorization Code flows and direct API keys (
oseo_*) for MCP access. - Mandatory scope enforcement: All authentication methods must explicitly include the
mcpscope, validated insrc/server/mcp/oauth-provider.tsviagetGrantedMcpScopes()and enforced insrc/server/mcp/transport.ts. - Configurable token lifetimes: OAuth access tokens expire after 24 hours, while refresh tokens remain valid for 30 days as configured in
createOpenSeoOAuthProvider(). - Rate limiting: API key authentication applies a 5000 request per minute limit per user via Cloudflare Rate-Limit bindings.
- Unified transport: Both authentication methods converge on
handleAuthenticatedOpenSeoMcpRequest()insrc/server/mcp/transport.tsfor consistent authorization checks.
Frequently Asked Questions
What is the required API key format for OpenSEO MCP authentication?
API keys must start with the oseo_ prefix and are validated via auth.api.verifyApiKey from Better Auth. The system checks the x-api-key header or Bearer token format in src/server/mcp/api-key-auth.ts. Without this prefix, the request falls back to standard OAuth processing or fails authentication entirely.
How does OpenSEO enforce the mandatory MCP scope?
The mcp scope enforcement occurs at multiple points. During OAuth flows, getGrantedMcpScopes() in src/server/mcp/oauth-provider.ts throws an error if the scope is missing. For API keys, createWorkersOAuthMcpProps() automatically assigns all MCP scopes. Finally, src/server/mcp/transport.ts validates scope presence before executing any MCP method, returning 403 Forbidden if absent.
What are the token expiration policies for OpenSEO MCP OAuth?
According to src/server/mcp/oauth-provider.ts, access tokens carry a 24-hour TTL, while refresh tokens remain valid for 30 days. These lifetimes are configured in the OAuthProvider initialization within createOpenSeoOAuthProvider().
Can MCP clients authenticate from self-hosted origins?
Yes. The transport layer in src/server/mcp/transport.ts explicitly adds CORS headers allowing requests from any origin. This enables self-hosted MCP clients to authenticate using either OAuth or API keys against the OpenSEO server, with all security policies enforced uniformly.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →