Skip to content

Custom connector step fails for claude.ai/ChatGPT web: MCP server serves no OAuth discovery/DCR endpoints #2

Description

@kyleaton

Summary

The README's copy-paste setup prompt (step 6) and AGENTS.md tell users to connect claude.ai/ChatGPT by adding https://<domain>/mcp as a custom connector and "authenticate using OAuth." This does not work with claude.ai web connectors as written. The connector fails during setup with:

Couldn't register with AgentOS's sign-in service. You can try again, or add an OAuth Client ID in the connector settings.

It's presented as a quick final step, but it's the hardest and most failure-prone part of the flow, and the docs give no working procedure for it.

Environment

  • Template: agno-agi/agentos-railway (fresh clone)
  • agno[os,mcp,slack,pgvector,psycopg]==2.7.1
  • Deployed via scripts/railway/up.sh, RUNTIME_ENV=prd (JWT auth on, default)
  • Client: claude.ai web "Add custom connector"

Root cause

AgentOS's MCP server is a bearer-token resource server (validates a JWT from os.agno.com, or a agno_pat_… service-account token) but does not implement the MCP OAuth 2.1 authorization flow that claude.ai/ChatGPT web clients require. It serves none of the OAuth discovery/registration endpoints.

Verified on a local dev server with authorization=False (so the auth gate is NOT hiding them — the routes genuinely don't exist):

/.well-known/oauth-protected-resource       -> 404
/.well-known/oauth-protected-resource/mcp   -> 404
/.well-known/oauth-authorization-server     -> 404
/.well-known/openid-configuration           -> 404
/register  /authorize  /token               -> 404

Because claude.ai (per the MCP spec) fetches Protected Resource Metadata (RFC 9728) → discovers the auth server (RFC 8414) → does Dynamic Client Registration (RFC 7591), and none of those exist, its automatic registration fails with the error above.

Second, independent issue

In production the auth middleware returns 401 {"detail":"Authorization header missing"} on every path — including /.well-known/* — and with no WWW-Authenticate header:

$ curl -s -D - -o /dev/null https://<domain>/mcp
HTTP/2 401
content-type: application/json
# (no WWW-Authenticate header)

$ curl -s https://<domain>/.well-known/oauth-protected-resource
{"detail":"Authorization header missing"}

OAuth discovery endpoints must be publicly reachable, and a 401 on a protected resource should carry WWW-Authenticate: Bearer resource_metadata="…". So even a spec-compliant client gets no signal about where to authenticate.

Suggested product fix

Make the documented "paste the /mcp URL and OAuth in" flow actually work:

  1. Publish RFC 9728 Protected Resource Metadata at /.well-known/oauth-protected-resource, pointing to os.agno.com as the authorization server.
  2. Return WWW-Authenticate: Bearer resource_metadata="…" on /mcp 401s.
  3. Exempt /.well-known/* (and OAuth endpoints) from the authorization middleware so unauthenticated discovery can start.
  4. Have os.agno.com support Dynamic Client Registration (RFC 7591) or publish a stable OAuth Client ID for the Live connection, and document allowlisting Claude's redirect URI https://claude.ai/api/mcp/auth_callback.

Suggested docs fix (until the above ships)

Replace the single vague bullet in the README / AGENTS.md with the paths that actually work, and set the expectation that this step needs manual OAuth/token config:

Connecting claude.ai / ChatGPT (web). These apps require an OAuth 2.1 handshake the AgentOS MCP server doesn't broker itself, so the automatic "paste the URL" flow fails with a "Couldn't register with…sign-in service" error. Use one of:

  • OAuth Client ID (recommended): In os.agno.com → your Live connection, copy the OAuth Client ID [and Client Secret]. In the chat app's Add custom connector → Advanced settings, paste them alongside the /mcp URL. Allowlist redirect URI https://claude.ai/api/mcp/auth_callback.
  • Bearer token: Mint a service-account token (agno_pat_…) and add Authorization: Bearer <token> in the connector's Request headers field (where supported).

Claude Desktop / Claude Code / Codex / Cursor don't need this — run uvx agno connect --url https://<domain>.

Related smaller gaps found in the same flow

  1. up.sh only pushes OPENAI_API_KEY. AGENTS.md invites switching the default model ("bump the model in one place"), but switching app/settings.py to Anthropic/Claude leaves production agents with no key until you separately run env-sync.sh — nothing warns you. up.sh should forward ANTHROPIC_API_KEY (and other provider keys), or the docs should call this out.
  2. up.sh breaks non-interactively with multiple Railway workspaces. railway init exits with --workspace required in non-interactive mode. Consider accepting a workspace via flag/env var.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions