Support per-user identity via request headers

Add multi-user auth: _config reads X-Freshservice-Domain/X-Freshservice-Key
from the per-request headers (via the SDK request_ctx, set inside the tool's
task) and prefers them over the container env. One shared server can now act as
each caller's own Freshservice identity — actions attributed to them, their
permissions, their rate limit — while the env vars remain a single-user
fallback. Verified end-to-end that concurrent clients don't cross-wire and that
a client with no creds errors instead of falling back silently.

Docs/.env.example updated with the multi-user client config and the guidance to
omit env FS creds on a shared deployment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 08:23:52 -06:00
parent ff627b5620
commit 4f9a862c25
3 changed files with 99 additions and 10 deletions

View File

@@ -56,6 +56,50 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` under
Restart Claude Desktop. The Freshservice tools then appear in chat and Cowork.
## Multiple users
The server can act as **each caller's own Freshservice identity** instead of a
single shared one. Each client sends its own credentials as headers on every
request; the server uses them per-call (they take precedence over the env
vars). Actions are then attributed to each person, with their own permissions
and rate limits.
To run the server multi-user:
1. **Omit `FRESHSERVICE_DOMAIN` / `FRESHSERVICE_API_KEY` from `.env`** (keep only
`MCP_AUTH_TOKEN`). With no env fallback, a client that forgets its headers
gets a clean "Missing credentials" error rather than silently acting as
whoever owns the env key.
2. Each user adds the extra headers to **their own** `claude_desktop_config.json`,
with **their own** Freshservice API key (Profile settings → API key):
```json
"freshservice": {
"command": "/opt/homebrew/bin/npx",
"args": [
"-y", "mcp-remote",
"http://192.168.101.12:3839/mcp",
"--allow-http",
"--header", "Authorization:${MCP_AUTH_HEADER}",
"--header", "X-Freshservice-Domain:${FS_DOMAIN}",
"--header", "X-Freshservice-Key:${FS_KEY}"
],
"env": {
"MCP_AUTH_HEADER": "Bearer <shared MCP_AUTH_TOKEN>",
"FS_DOMAIN": "pesco.freshservice.com",
"FS_KEY": "<that user's own Freshservice API key>"
}
}
```
`MCP_AUTH_TOKEN` is the same shared value for everyone (it only gates *reaching*
the server); `FS_KEY` is each person's own identity. The key stays on the
user's machine and travels per-request — the server never stores it.
> Note: the LAN transport is plain HTTP, so these headers travel unencrypted.
> Fine on a trusted network; put a TLS-terminating reverse proxy in front if
> this ever leaves it.
## Tools
Tickets (`list_tickets`, `get_ticket`, `create_ticket`, `update_ticket`,