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 organization-scoped Streamable HTTP endpoint as hosted ctx|:
{AUTH_BASE_URL}/mcpOAuth connections use the generic URL and bind an organization during
authorization. ?orgSlug=<org-slug> remains valid for legacy and manually
configured clients.
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 organization.
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": "http",
"url": "https://ctx.example.com/mcp"
}
}
}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 public MCP URL:
npx ctxpipe doctor mcp \
--url "$AUTH_BASE_URL/mcp"
npx ctxpipe doctor mcp \
--url "$AUTH_BASE_URL/mcp" \
--json--json is machine-readable. Failures set a non-zero exit code. Loopback HTTP
is allowed with a warning; remote endpoints must use HTTPS.
| Check | Passes when |
|---|---|
| Target | Path is /mcp; remote origins use HTTPS |
| Backend status | GET /.status returns JSON with status: "ok" |
| OAuth challenge | Unauthenticated Streamable HTTP initialize returns 401 with a Bearer WWW-Authenticate challenge that includes resource_metadata |
| Protected resource | RFC 9728 metadata matches the /mcp audience and names an authorization server |
| Authorization server | RFC 8414 metadata exposes authorization, 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
organization, not a customer organization.
npx @mcpjam/[email protected] oauth login \
--url "$AUTH_BASE_URL/mcp" \
--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" \
--credentials-file .mcpjam/credentials.json
npx @mcpjam/[email protected] tools call \
--url "$AUTH_BASE_URL/mcp" \
--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" \
--name "ctxpipe self-host" \
--oauth \
--tab serversThe hosted MCPJam application only reaches public HTTPS. It cannot use
localhost or refresh against a local authorization server.
Artifacts 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
- Grant is not bound to an organization — disconnect and reconnect the MCP
client, then choose an organization during authorization. Old/manual clients
may use
/mcp?orgSlug=<slug>. AUTH_BASE_URLmismatch — 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
resourcecanonicalises to/mcpwithout the query string. - Authorization-server metadata missing registration — dynamic client registration cannot proceed.
- CLI setup sign-in worked, but the MCP client still asks for authorization — expected. Setup auth and MCP OAuth are separate.