Contextator
ENTR

Operating

Connecting AI Clients

Ready-to-paste setup for Claude Code, Cursor, Claude Desktop and any other MCP client, plus tokens, remote access and verifying an endpoint without an agent.

Updated:

Each project is one URL. Point a client at it and the agent gains three documentation tools — no other configuration, no API key, no plugin.

http://localhost:3444/mcp/<project-name>

The dashboard’s Connect an agent panel prints every snippet below filled in with the real URL, ready to copy — including the Authorization header when the project requires a token. Replace demo with your project name in the examples, and ctxm_9f3a… with the token the project page showed you.


Claude Code

A new project requires a token by default, so add the header with your project’s token:

claude mcp add --transport http demo-docs http://localhost:3444/mcp/demo \
  --header "Authorization: Bearer ctxm_9f3a…"

If the project’s MCP access was switched to open, the header can be left off:

claude mcp add --transport http demo-docs http://localhost:3444/mcp/demo

Check it worked:

claude mcp list

Then just ask a question about your documentation — Claude Code decides to call search_docs on its own, because the server describes what it holds.

Cursor

~/.cursor/mcp.json for every project, or .cursor/mcp.json inside one repository. A new project requires a token by default:

{
  "mcpServers": {
    "demo-docs": {
      "url": "http://localhost:3444/mcp/demo",
      "headers": { "Authorization": "Bearer ctxm_9f3a…" }
    }
  }
}

If the project’s MCP access was switched to open, the headers block can be left off:

{
  "mcpServers": {
    "demo-docs": { "url": "http://localhost:3444/mcp/demo" }
  }
}

Restart Cursor, then check Settings → MCP for a green indicator.

Claude Desktop

Claude Desktop speaks stdio, so it needs a bridge. A new project requires a token by default, and mcp-remote passes it on with --header, in claude_desktop_config.json:

{
  "mcpServers": {
    "demo-docs": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "http://localhost:3444/mcp/demo",
        "--header", "Authorization: Bearer ctxm_9f3a…"
      ]
    }
  }
}

If the project’s MCP access was switched to open, the --header argument can be left off:

{
  "mcpServers": {
    "demo-docs": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://localhost:3444/mcp/demo"]
    }
  }
}

Restart Claude Desktop. The tools appear under the connectors icon.

Config file locations: macOS ~/Library/Application Support/Claude/claude_desktop_config.json, Windows %APPDATA%\Claude\claude_desktop_config.json.

Any other MCP client

Give it the URL. Contextator serves both MCP transports on the same address and picks by what the client sends:

  • Streamable HTTP (current clients): POST an initialize request; the session id comes back in the mcp-session-id header.
  • HTTP + SSE (protocol 2024-11-05, older clients): GET the URL; the server answers with an endpoint event pointing at /mcp/demo/messages?sessionId=….

No configuration switches between them.

Projects that require a token

A project whose MCP access is token required answers every request without a valid token with 401 and a www-authenticate: Bearer realm="<project-name>" header, whichever transport the client uses. Mint the token on the project page — it is shown once — and send it as an ordinary header:

Authorization: Bearer ctxm_9f3a…
  • The header is checked on every /mcp/* request. On the legacy SSE transport that means the GET that opens the stream and the POSTs to /mcp/demo/messages, so a client that can set a header on only one of the two cannot connect. A browser EventSource is the usual case — leave those projects open, or put the whole instance behind an authenticating proxy.
  • Tokens are per project. A client connected to two token-protected projects needs one for each.
  • Revoking a token cuts its client off immediately, mid-session; so does switching a project from open to token required. Reconnecting with a current token is all that is needed.

Where the switch lives and who may flip it: Projects.

Projects that require an account

account required is the third mode, and the one where this dashboard’s memberships reach /mcp/*. A static ctxm_… token names nobody and is refused there; a client has to act as an account that is a member of the project, and that is re-checked on every request — removing a membership, disabling an account or resetting its password cuts the connection off on its next call rather than at some expiry.

A client gets that credential through OAuth 2.1, which is what browser-based MCP connectors already speak. You configure nothing: point the connector at http://host:3444/mcp/<project-name>, and it discovers this server’s authorization endpoints, registers itself, and sends you to a page here to sign in and approve it. What it gets back acts as your account, renews itself quietly, and expires if the connector goes unused for a month. Changing your password disconnects every connector acting as you.

MCP_OAUTH=0 removes the flow entirely, and then only static tokens open a closed project — which also means browser-based connectors cannot connect at all.

Several projects at once

Add one entry per project. They stay isolated — an agent connected to both simply has two sets of tools, and a search in one never returns documents from the other.

{
  "mcpServers": {
    "billing-docs": { "url": "http://localhost:3444/mcp/billing" },
    "mobile-docs":  { "url": "http://localhost:3444/mcp/mobile" }
  }
}

Connecting from another machine

  1. Make sure the server is reachable: HOST=0.0.0.0 (the default) and the port is open.
  2. Use the server’s address, not localhost: http://docs.internal:3444/mcp/demo.
  3. Behind a reverse proxy, set PUBLIC_BASE_URL so the dashboard prints the right URLs, and disable response buffering — see Installation.

Verifying without an agent

A smoke test ships with the repository. From a source checkout:

npm install
npm run smoke -- http://localhost:3444/mcp/demo "how do I re-index"
npm run smoke -- http://localhost:3444/mcp/demo "kurulum" --sse   # exercise the legacy transport

It performs a real MCP handshake, lists the tools and runs a search. It cannot send an Authorization header, so a project that requires a token answers it 401 — check that one with curl instead:

curl -s -i -X POST http://localhost:3444/mcp/demo \
  -H "Authorization: Bearer ctxm_9f3a…" \
  -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'

If it does not connect

Symptom Check
Unknown project "…" The project name in the URL, exactly as the dashboard shows it
The client connects but finds nothing The project has been indexed — the dashboard shows the document and chunk counts
“indexed with another model” Re-index the project (Embedding Models)
Works locally, not from another machine HOST, firewall, and whether you used the machine’s address rather than localhost
A browser-based client is refused Add its origin to ALLOWED_ORIGINS
401 This project requires an MCP token The project is in token required mode and the client is sending no Authorization header
401 This project requires an account-backed credential The project is in account required mode and the client is sending a static ctxm_… token, which names nobody
403 That account is not a member of this project The connector signed in as an account that is not a member of the project. This is checked in every mode, open included
A browser-based connector cannot connect at all MCP_OAUTH=0 on this instance, so there is no flow for it to use
401 Unknown or revoked MCP token The token was revoked, or belongs to another project. Mint a fresh one on the project page

More in Troubleshooting.

Arrow keys to move, Enter to open.