Development¶
This page covers running the MCP Worker locally, testing it, its configuration, deploying it, and registering it in an MCP client. For what the tools do see the Tools reference; for how it is wired see the Architecture.
Prerequisites¶
- Node.js (20+ recommended) and npm.
wrangler(installed as a dev dependency; run vianpm run).- For deploys: a Cloudflare account with access to the configured
account_id.
Local development¶
npm install
cp .dev.vars.example .dev.vars # fill in SWAPPS_API_TOKEN and EDGE_TOKENS
npm run dev # wrangler dev on http://127.0.0.1:8787
.dev.vars is gitignored and holds the local secrets:
# Single read-only service DRF token used for all downstream API calls.
SWAPPS_API_TOKEN=
# JSON map of per-user edge token -> username. Generate tokens with `openssl rand -hex 32`.
EDGE_TOKENS={"localtoken":"dev@swapps.com"}
The dev script runs wrangler dev --ip 0.0.0.0, so the server is reachable on the LAN as well as 127.0.0.1:8787.
Smoke test¶
The MCP Streamable HTTP transport requires the Accept header to include text/event-stream:
# tools/list
curl -sS -X POST http://127.0.0.1:8787/mcp \
-H "Authorization: token localtoken" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
A health check needs no token:
curl -sS http://127.0.0.1:8787/health
# {"status":"OK","ts":"..."}
Quality checks¶
| Command | What it does |
|---|---|
npm run typecheck |
tsc --noEmit — type-checks the project. |
npm run lint |
eslint . — lints with typescript-eslint. |
npm test |
vitest — runs the unit tests. |
Tests (Vitest)¶
Tests live in tests/ and run in the node environment (vitest.config.ts), with the @/* alias resolving to src/*:
tests/auth.test.ts—extractToken(AuthorizationToken/Bearer,X-MCP-Tokenfallback, empty) andvalidateEdgeToken(valid/unknown/empty token, malformed/emptyEDGE_TOKENS).tests/api-client.test.ts—apiGetURL building, auth +User-Agentheaders, pretty-printed JSON, leading-slash stripping, non-2xx error formatting, empty body →"null", and thrown-error formatting.
Run a single file:
npx vitest run tests/auth.test.ts
Configuration¶
Secrets are set with wrangler secret put (never committed); vars live in wrangler.toml. Names only — never store secret values in the repo.
| Name | Kind | Where | Purpose |
|---|---|---|---|
SWAPPS_API_TOKEN |
Secret | wrangler secret put / .dev.vars |
Read-only service DRF token for all downstream calls. |
EDGE_TOKENS |
Secret | wrangler secret put / .dev.vars |
JSON map of per-user edge token → username. |
SWAPPS_API_BASE_URL |
Var | wrangler.toml [vars] |
Downstream API base URL (default https://app.swapps.com/api). |
SWAPPS_API_USER_AGENT |
Var | wrangler.toml [vars] |
Downstream User-Agent (default swapps-mcp/1.0). |
Deployment¶
# Secrets (never committed):
wrangler secret put SWAPPS_API_TOKEN # service DRF token (read-only user)
wrangler secret put EDGE_TOKENS # JSON: {"<token>":"<username>", ...}
npm run deploy # wrangler deploy
- The first deploy lands at
https://swapps-mcp-worker.<account>.workers.dev/mcp. - The (currently commented)
[[routes]]block inwrangler.tomlprovisions the custom domainhttps://mcp.swapps.com/mcp(DNS + cert automatic; theswapps.comzone is already in the account). Re-enable it once the wrangler token has zone permissions forswapps.com.
Deploy via the platform skill
Within the platform workspace, the deploy-worker skill knows the correct per-project command (preview vs production, secrets, rollback) for swapps-mcp-worker.
Managing edge tokens¶
EDGE_TOKENS is a secret holding a JSON token -> username map:
{ "a1b2c3...": "dev@swapps.com", "d4e5f6...": "lcuevas@swapps.com" }
- Generate a token:
openssl rand -hex 32. - Revoke a user: remove their entry and re-run
wrangler secret put EDGE_TOKENS.
Registering it in an MCP client¶
Claude Code¶
claude mcp add --transport http swapps-app https://mcp.swapps.com/mcp \
--header "Authorization: token <YOUR_EDGE_TOKEN>"
If your Claude version does not forward the Authorization header correctly, use the fallback header:
claude mcp add --transport http swapps-app https://mcp.swapps.com/mcp \
--header "X-MCP-Token: <YOUR_EDGE_TOKEN>"
Claude Desktop¶
claude_desktop_config.json:
{
"mcpServers": {
"swapps-app": {
"type": "http",
"url": "https://mcp.swapps.com/mcp",
"headers": { "Authorization": "token <YOUR_EDGE_TOKEN>" }
}
}
}
For local development point the client at http://127.0.0.1:8787/mcp and use a token present in your .dev.vars EDGE_TOKENS map (e.g. localtoken).