MCP

Point MCP clients at a self-hosted ctx| origin, then diagnose routing and OAuth with ctxpipe doctor mcp and MCPJam.

Self-hosted ctx| exposes the same organisation-scoped Streamable HTTP endpoint as hosted ctx|:

{AUTH_BASE_URL}/mcp?orgSlug=<org-slug>

orgSlug is required. AUTH_BASE_URL must be the public origin clients use, including TLS. Client JSON shapes and OAuth install paths are unchanged from hosted ctx|; see Remote MCP and Authentication.

This page is for operators: confirm the endpoint is reachable, then debug OAuth and tools on a test organisation.

Ready for OAuth is not authenticated proof

npx ctxpipe doctor mcp checks HTTP routing, TLS or reachability, the unauthenticated Bearer challenge, and OAuth discovery. A ready-for-oauth result does not prove that browser OAuth, authenticated tools/list, or ctx_advisor work. The command does not accept bearer tokens and does not test STDIO servers.

Connect a client

Use the same config as Quickstart, with your deployment origin:

{
  "mcpServers": {
    "ctxpipe": {
      "type": "streamable-http",
      "url": "https://ctx.example.com/mcp?orgSlug=your-org-slug"
    }
  }
}

The MCP client must complete OAuth against this deployment. CLI setup sign-in and MCP client OAuth are separate flows.

Diagnose discovery

Run the lightweight doctor against the exact organisation-scoped URL:

npx ctxpipe doctor mcp \
  --url "$AUTH_BASE_URL/mcp?orgSlug=<slug>"

npx ctxpipe doctor mcp \
  --url "$AUTH_BASE_URL/mcp?orgSlug=<slug>" \
  --json

--json is machine-readable. Failures set a non-zero exit code. Loopback HTTP is allowed with a warning; remote endpoints must use HTTPS.

CheckPasses when
TargetPath is /mcp and orgSlug is present
Backend statusGET /.status returns JSON with status: "ok"
OAuth challengeUnauthenticated Streamable HTTP initialize returns 401 with a Bearer WWW-Authenticate challenge that includes resource_metadata
Protected resourceRFC 9728 metadata matches the /mcp audience and names an authorisation server
Authorisation serverRFC 8414 metadata exposes authorisation, token, and registration endpoints

Overall status is ready-for-oauth, warning, or failed.

If TLS fails from a Node CLI against a local CA (Portless or a private CA), set NODE_EXTRA_CA_CERTS to the CA file. Do not disable TLS verification.

Authenticated checks with MCPJam

MCPJam is an external diagnostic client. It is not bundled into ctxpipe or the self-hosted backend. Pin the versions below; do not use @latest. Use a test organisation, not a customer organisation.

npx @mcpjam/[email protected] oauth login \
  --url "$AUTH_BASE_URL/mcp?orgSlug=<slug>" \
  --protocol-version 2025-11-25 \
  --registration dcr \
  --credentials-out .mcpjam/credentials.json \
  --debug-out .mcpjam/oauth-debug.json

npx @mcpjam/[email protected] tools list \
  --url "$AUTH_BASE_URL/mcp?orgSlug=<slug>" \
  --credentials-file .mcpjam/credentials.json

npx @mcpjam/[email protected] tools call \
  --url "$AUTH_BASE_URL/mcp?orgSlug=<slug>" \
  --credentials-file .mcpjam/credentials.json \
  --tool-name ctx_advisor \
  --tool-args '{"prompt":"Health check: confirm org MCP access."}'

For a visual OAuth and JSON-RPC timeline on a local origin:

npx @mcpjam/[email protected] \
  --url "$AUTH_BASE_URL/mcp?orgSlug=<slug>" \
  --name "ctxpipe self-host" \
  --oauth \
  --tab servers

The hosted MCPJam application only reaches public HTTPS. It cannot use localhost or refresh against a local authorisation server.

Artefacts and credentials

Keep OAuth credentials and debug traces out of Git. Write them under .mcpjam/ (gitignored in the ctx| repository). Review files before sharing. The credentials file can include an access token, refresh token, client id, and client secret even when stdout is redacted.

The ctx| doctor never accepts or prints bearer tokens. Do not put access_token on the MCP URL.

MCPJam does not prove token refresh races, dropped-session recovery, or concurrent clients. Do not gate CI on interactive OAuth or LLM evals.

Common failures

  • Missing orgSlug — use /mcp?orgSlug=<slug>, not /mcp.
  • AUTH_BASE_URL mismatch — issuer, callbacks, and MCP discovery must use the same public origin clients see.
  • Remote HTTP — production MCP must be HTTPS.
  • Status unreachable or timed out — backend, DNS, TLS, or an untrusted CA.
  • HTTP 401 without resource_metadata — clients cannot start OAuth discovery.
  • Protected-resource audience mismatch — RFC 9728 resource canonicalises to /mcp without the query string.
  • Authorisation-server metadata missing registration — dynamic client registration cannot proceed.
  • CLI setup sign-in worked, but the MCP client still asks for authorisation — expected. Setup auth and MCP OAuth are separate.