Give claude.ai a token of its own, sent as a request header
claude.ai's connector dialog does offer request headers, on its second step, after the URL has been probed, so the connector no longer needs the secret path. MCP_AUTH_TOKEN already worked there as a bearer or X-Api-Key, but it also opens /api, which can replace the Schulcloud token and stream the file mirror, and claude.ai stores the header's value. MCP_CONNECTOR_TOKEN is a second token, accepted on /mcp only and refused on /api, and rotated without touching Claude Code or the CLI. The config refuses one shorter than 32 characters, equal to MCP_AUTH_TOKEN, or set without it, and never echoes a value. Every accepted token is compared in full, so the timing does not tell which one matched. The gate also takes a bare Authorization value, because claude.ai sends a header exactly as typed and its docs warn that most servers reject a token entered without "Bearer ". It takes X-Auth-Token too, the other name its dialog offers. The docs now set up the header; the secret path stays as a fallback for clients that cannot send one. 184 tests. Smoke 79/79 and 77/77 on the local instance. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
15
README.md
15
README.md
@@ -116,11 +116,12 @@ copy is the browser's own session token**, so a Schulportal tab left open will
|
||||
auto-logout after ~2 hours and revoke this server's token with it. Copy the
|
||||
token in a private window and close it. See [docs/AUTH.md](docs/AUTH.md).
|
||||
|
||||
**claude.ai reaches it by a secret path, for now.** Its connector dialog takes
|
||||
a URL and no header, so `MCP_PATH_SECRET` serves MCP at `/<secret>/mcp` without
|
||||
the bearer token — never logged, redacted by the Caddy snippet, and a stopgap
|
||||
until the endpoint speaks OAuth. Claude Code and the CLI keep the bearer token.
|
||||
See [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md).
|
||||
**claude.ai gets a token of its own.** Its connector stores a request header,
|
||||
so `MCP_CONNECTOR_TOKEN` opens `/mcp` and nothing else — it is refused on
|
||||
`/api`, which can replace the Schulcloud token — and rotates without touching
|
||||
Claude Code or the CLI, which keep `MCP_AUTH_TOKEN`. A client that cannot send
|
||||
headers can use a secret path instead (`MCP_PATH_SECRET`). See
|
||||
[docs/DEPLOYMENT.md](docs/DEPLOYMENT.md).
|
||||
|
||||
**Read-only by construction.** Every method on the API client is a `GET`,
|
||||
including `api_get`. The endpoint is internet-facing by necessity (Claude's
|
||||
@@ -185,8 +186,8 @@ npm run typecheck
|
||||
```
|
||||
|
||||
`npm run smoke` starts the HTTP server, connects a real MCP client over
|
||||
Streamable HTTP and exercises every tool against the live account — 74 checks (76 with the index)
|
||||
covering the auth gate and the secret path, the protocol handshake, every content chain, file
|
||||
Streamable HTTP and exercises every tool against the live account — 77 checks (79 with the index)
|
||||
covering the auth gate, the connector token and the secret path, the protocol handshake, every content chain, file
|
||||
extraction, resources and prompts, token replacement, `api_get`'s guard rails and error handling.
|
||||
|
||||
## Upstream
|
||||
|
||||
Reference in New Issue
Block a user