Streamable HTTP MCP and OAuth
Availability: The AutoMCP production service is not yet deployed. This page and its examples describe the committed v1 contract for integration planning; requests to the API URL will not succeed until the runtime is released.
The MCP endpoint is https://automcp.api.delino.io/mcp/v1/apps/{app_id} and uses Streamable HTTP from the MCP 2025-11-25 revision. Authenticated GET, POST, and session termination expose the published tool list/call surface plus the caller’s own Run get/watch/cancel behavior. MCP JSON-RPC IDs and MCP-Session-Id are transport values, not Connect mutation IDs. MCP tokens cannot call Connect CreateRun or approval decisions. See the Streamable HTTP transport specification and authorization specification.
OAuth discovery is served by the same issuer, https://automcp.api.delino.io, at /.well-known/oauth-authorization-server. Protected-resource metadata is at /.well-known/oauth-protected-resource/mcp/v1/apps/{app_id} and is advertised in WWW-Authenticate.
The issuer exposes these OAuth routes under the same origin:
/oauth/authorizestarts the authorization-code flow after validating the client, redirect URI, resource, scopes, and PKCE challenge./oauth/tokenexchanges an authorization code or refresh token for tokens bound to the same client, user, resource, and grant./oauth/revokerevokes a refresh or access token and prevents further use of that credential./oauth/registerperforms dynamic client registration for a customer integration.
MCP OAuth scopes
MCP OAuth access tokens accept these scopes, separately from backend-key and browser-token scopes:
runs:readpermits reading metadata for the caller’s own Runs and watching those Runs withWatchRun.runs:writepermits MCP tool execution and canceling the caller’s own Runs.
MCP OAuth tokens do not receive runs:payload, sessions:write, or approval scopes and cannot call Connect CreateRun or make approval decisions. MCP tools/call creates a persistent Run through its separately authorized transport.
The flow is OAuth 2.1 authorization code with S256 PKCE. Owners/admins register one exact public HTTPS customer-login URL and receive a write-only signing secret. AutoMCP sends the login handoff to that URL with an HTTP POST whose content type is application/x-www-form-urlencoded; it does not place the handoff in the query string. The form contains request, a base64url-without-padding encoding of canonical UTF-8 JSON with oauthLoginRequestId, workspaceId, appId, clientId, redirectUri, resource, scope, codeChallenge, codeChallengeMethod, issuedAt, expiresAt, and expectedResourceVersion. It also sends AutoMCP-OAuth-Signature: t=<unix>,v1=<lowercase-hex-hmac-sha256>, computed over <timestamp>.<request> with the UTF-8 signing secret; accept only within the replay window and after checking expiry, one-use status, exact app/client/redirect/resource/PKCE bindings, and signature validity. The backend authenticates its own user, takes oauthLoginRequestId and expectedResourceVersion from the verified request, and completes it through Connect with oauth:login:complete, a fresh UUID-v7 requestId, the configured workspaceId and appId, and its authenticated customerUserId. Requests, codes, refresh tokens, and access tokens cannot be replayed, widened, or substituted across apps, users, clients, redirects, resources, or grants.
When an owner rotates the signing secret, new login requests are signed with the new secret immediately. Keep the previous secret available for verification of requests issued before rotation until each request’s short expiry; after that window, discard the previous secret and reject signatures made with it. Continue enforcing the replay window, one-use status, exact bindings, and signature validity for either secret.
Redirect URIs must match exactly. Browser origins are the lowercase scheme plus host and explicit effective port only: paths, userinfo, wildcards, suffix matching, opaque origins, and null are rejected. CORS and WebSocket Origin checks use the same exact-origin rule.
Complete the customer login and consent
Return HTTP 200 with { "loginUrl": "https://your-login-origin.example/continue" }
after accepting the signed backchannel request. The browser URL must share the
registered login origin. After authenticating your user, complete the request
through CompleteOAuthLoginRequest; its first response includes
browserReturnUrl. Redirect that same browser to the URL. AutoMCP consumes it
with the original nonce cookie and opens the shared web application's customer
consent screen. This screen does not require an administrator login or workspace
membership. Consent returns an authorization code; denial returns access_denied.
Registered redirect URIs must use HTTPS, except exact loopback HTTP callbacks.
Token exchange requires client_id, redirect_uri, resource, and the original
PKCE verifier. Refresh requests include the same client_id and resource and
may narrow scopes. Rotation invalidates the previous access token; reuse of an
old refresh token revokes its family. Codes, handoffs and consent decisions
are one-use, so start a new login if a one-time return credential is lost.
Submit and observe tools
Initialize with protocolVersion: "2025-11-25", retain Mcp-Session-Id, then send
notifications/initialized. Subsequent requests include that session header
and MCP-Protocol-Version: 2025-11-25. POST accepts both application/json and
text/event-stream; authenticated DELETE closes the transport session.
Each published tool's input is { "requestId": "<UUID v7>", "arguments": {} }.
Reuse requestId with identical arguments after a transport failure; changing
the JSON-RPC ID, reconnecting with a new transport session for the same published
version, or refreshing a token does not create a new intended execution.
The response provides Run and Job IDs. automcp_get_run returns status and a
completed MCP tool result; automcp_cancel_run requires the Run's current
resource version and a new mutation request ID. Mutating tools return a hosted
approval link while waiting. An OAuth or model credential cannot approve it.