mcplocal HTTP mode: project instructions fetched with pod-level client (empty token) → 401 swallowed, initialize serves no instructions #113

Closed
opened 2026-08-15 15:09:27 +00:00 by michal · 0 comments
Owner

Symptom: an MCP client connecting to /projects/<name>/mcp gets Server Instructions: N/A at initialize even when the project has a non-empty prompt. Nothing errors anywhere.

Cause: src/mcplocal/src/http/project-mcp-endpoint.ts:181 (at deployed rev 35d506d) fetches /api/v1/projects/:name/instructions with mcpdClient — the pod-level client whose token is an empty string in HTTP mode — instead of the per-request requestClient built ~100 lines earlier precisely for this reason (its own comment: "Every downstream call from this request … has to use the CALLER's McpToken … thread it everywhere"). mcpd answers 401 and the catch {} around the fetch swallows it, so router.setInstructions is never called.

Verified 2026-08-15:

curl -H "Authorization: Bearer $CHATWEB_TOKEN" https://mcpctl.ad.itaz.eu/api/v1/projects/chat-web/instructions  # 200, returns prompt
curl https://mcpctl.ad.itaz.eu/api/v1/projects/chat-web/instructions  # 401

LibreChat log: Server Instructions: N/A despite chat-web's prompt being set.

Fix: one line — mcpdClient.getrequestClient.get on that call. (Audit the rest of getOrCreateRouter for other mcpdClient stragglers while there; refreshProjectUpstreams already takes authToken.)

Workaround in place: LibreChat's serverInstructions is set to a literal string copy of the chat-web prompt in kubernetes-deployment (deployments/librechat/server.ts); flip it to true once this ships.

**Symptom:** an MCP client connecting to `/projects/<name>/mcp` gets `Server Instructions: N/A` at initialize even when the project has a non-empty `prompt`. Nothing errors anywhere. **Cause:** `src/mcplocal/src/http/project-mcp-endpoint.ts:181` (at deployed rev `35d506d`) fetches `/api/v1/projects/:name/instructions` with `mcpdClient` — the pod-level client whose token is an empty string in HTTP mode — instead of the per-request `requestClient` built ~100 lines earlier precisely for this reason (its own comment: "Every downstream call from this request … has to use the CALLER's McpToken … thread it everywhere"). mcpd answers 401 and the `catch {}` around the fetch swallows it, so `router.setInstructions` is never called. **Verified 2026-08-15:** ``` curl -H "Authorization: Bearer $CHATWEB_TOKEN" https://mcpctl.ad.itaz.eu/api/v1/projects/chat-web/instructions # 200, returns prompt curl https://mcpctl.ad.itaz.eu/api/v1/projects/chat-web/instructions # 401 ``` LibreChat log: `Server Instructions: N/A` despite chat-web's prompt being set. **Fix:** one line — `mcpdClient.get` → `requestClient.get` on that call. (Audit the rest of `getOrCreateRouter` for other `mcpdClient` stragglers while there; `refreshProjectUpstreams` already takes `authToken`.) **Workaround in place:** LibreChat's `serverInstructions` is set to a literal string copy of the chat-web prompt in kubernetes-deployment (`deployments/librechat/server.ts`); flip it to `true` once this ships.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: michal/mcpctl#113