Troubleshooting
Ten things that go wrong between an agent and this server, and the check that tells each one apart.
Start by proving the server answers from your machine. This request is not metered, so it costs nothing:
curl -sS -X POST https://mcp.wellworn.dev/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'A working reply begins event: message and lists eight tools. If that works and your agent still does not, the problem is in the client's config, not in the server.
The client lists no tools
Adding a server and never restarting the client is the usual cause; most clients read their MCP config at startup. In Claude Code, claude mcp list shows what is configured and /mcp shows the connection status of each one.
Verified 2026-09-08 against code.claude.com
Check the URL ends in /mcp. Opening it in a browser is not a test: a GET returns 405 by design, because the endpoint answers POST only.
The limit-reached line
Not an error. The tool returned this line as its answer:
limit reached: no-key 60/60 today (resets 2026-09-09T00:00:00.000Z). Free key or plans: https://wellworn.dev/pricingno-key counts per IP, so a shared office address or a CI runner pool spends one allowance between everyone. A free key moves the count to your organization and raises it to 2,000 a month. See plans and credits.
Invalid key
{"jsonrpc":"2.0","error":{"code":-32001,"message":"invalid key"},"id":null}The token was sent but did not verify. Copy it again from /app/keys, check for a trailing space or a wrapping quote, and check the header reads Authorization: Bearer ww_... with the word Bearer and one space. A revoked key gives the same answer, and so does a key from a different environment. The server never downgrades a bad key to the anonymous tier, so this always means the key itself.
Answers carry a RECHECK flag
The verdict is still served, with the flag in its first line:
VERDICT [RECHECK] auth for a Next.js app, solo dev, free tierA nightly job re-reads the package registries and marks a verdict whose pinned version has moved, so the flag means a person has not looked since that version changed, not that the advice is wrong. The VERIFIED line at the bottom carries the date and the version that was actually tested; decide from those.
No verified verdict yet
no verified verdict yet for "…". Browse https://wellworn.dev/verdicts or request one at https://wellworn.dev/requestThe corpus has nothing published for that question. Rephrasing towards the shape of a decision helps, since verdicts are indexed by the question they answer: "auth for a Next.js app, solo dev, free tier" hits, "authentication" does not. If nothing fits, the request form is the route, and it is read by the same people who publish.
The client only speaks stdio
Some clients cannot open a remote HTTP MCP server at all. Bridge with the standard proxy:
npx mcp-remote https://mcp.wellworn.dev/mcpPoint the client at that command as a stdio server. The bridge is a separate process on your machine; a key goes to it as an argument or an environment variable, depending on the client, and the Clients pages show which.
A corporate proxy in the way
A TLS-inspecting proxy makes the client fail at connect time rather than at the tool call. Run the curl above from the same shell the agent runs in. A certificate error there is the proxy, and the fix is your organization's root certificate in the trust store the client uses, which for a Node client means NODE_EXTRA_CA_CERTS. Allowlist mcp.wellworn.dev on 443; the server needs no other host.
Headers are stripped
Some proxies and some client wrappers drop unknown request headers. The symptom is specific: calls work, but they are being counted as anonymous. Every tool answer ends with a remaining: line, and that number gives it away. A keyed caller on the free tier counts down from 1,999; an anonymous one can never show more than 59. Confirm on the usage chart at /app/usage, where a keyed call appears within an hour and an anonymous one never does.
The wrong transport field
Every config field name is client-specific and they are not interchangeable. Claude Code takes --transport http, Cursor and VS Code take a JSON object with "url", Windsurf and Gemini CLI use their own key names. A server configured with the wrong shape usually shows as configured and never connects. The page for your client in the Clients section has the exact file and the exact keys, checked against that client's own documentation on the date shown.
Two mistakes account for most of these: writing "type": "sse" for an endpoint that speaks Streamable HTTP, and omitting accept: application/json, text/event-stream when calling by hand. The second answers:
{"jsonrpc":"2.0","error":{"code":-32000,"message":"Not Acceptable: Client must accept both application/json and text/event-stream"},"id":null}An old config is still loaded
Editing the file while the agent runs changes nothing until it re-reads it. Worse, several clients keep more than one config: Claude Code stores a local, a project and a user scope, so a stale entry in one can shadow the one you just edited. List what is actually loaded rather than reading the file you think is in use, remove duplicates, then restart the client.
Still stuck
Mail support@wellworn.dev with the client and its version, the exact config block with the key redacted, and the output of the curl above. A vulnerability goes to security@wellworn.dev instead; see reporting.