{"slug": "i-set-a-500ms-timeout-and-got-28-hours", "title": "I Set a 500ms Timeout and Got 28 Hours", "summary": "A developer documented a Claude Code MCP configuration pitfall in which a `timeout: 500` value (milliseconds) is silently ignored because values below 1000 fall through to the MCP_TOOL_TIMEOUT default of roughly 28 hours, rather than the one-second floor used before v2.1.162. The writeup also covers two related traps: entries with a `url` but no `type` are treated as stdio servers and skipped as configuration errors, and project-level MCP server approvals in `.mcp.json` are ignored in untrusted folders. The developer released an open-source configuration checker, ccheck, plus an MIT-licensed multi-persona Claude Code workflow.", "body_md": "I had an MCP server that occasionally hung, so I gave it a short leash:\n\n```\n{ \"mcpServers\": { \"flaky\": { \"type\": \"http\", \"url\": \"...\", \"timeout\": 500 } } }\n```\n\n`timeout` is in milliseconds, so that reads as half a second.\n\n**Values below 1000 are ignored.** The call falls through to\n\n`MCP_TOOL_TIMEOUT`, and if that is unset, to its default — **about 28 hours.**\n\nI had written the tightest limit I could and produced the loosest one available.\n\nBefore v2.1.162 a value under 1000 was floored to one second, which is the\n\nbehaviour I had in my head. **It changed, and nothing in my configuration changed with it.**\n\nThree related things I only learned by reading the whole section:\n\n`timeout` is a `url` with no `type` is read as a stdio server\n\n```\n{ \"mcpServers\": { \"example\": { \"url\": \"https://mcp.example.com/mcp\" } } }\n```\n\nThere is no defaulting to http. **An entry with no `type` is a stdio server**,\n\nstdio requires `command`, and so the server is skipped as a configuration error:\n\n```\nMCP server \"example\" has a \"url\" but no \"type\"; add \"type\": \"http\" (or \"sse\" / \"ws\") to this entry\n```\n\nThat message exists from v2.1.202. Before it, the same mistake reported\n\n`command: expected string, received undefined` — **you wrote a url and were told about a command**, which is a long way from the cause.\n\nUnder `--output-format stream-json` it also appears in the `system/init` event's\n\n`mcp_server_errors`, so a script can detect that a server never loaded. That is\n\nthe only machine-readable path I have found for it.\n\nThis one cost me the most time, because it looks like a permissions bug.\n\nServers from `.mcp.json` need approval. You can commit\n\n`enableAllProjectMcpServers` or `enabledMcpjsonServers` to the project's\n\n`.claude/settings.json` — and in an **untrusted folder they are ignored.** The\n\nserver sits at `⏸ Pending approval`, never connected, never health-checked.\n\nWhich is correct, and obvious once stated: **a repository that could approve its own MCP servers would be a way to run code on anyone who clones it.**\n\nThree sources of approval still apply in an untrusted folder: your own\n\n`~/.claude/settings.json`, managed settings, and settings passed with\n\n`--settings`.\n\nEvery one of them is a configuration that **loads**. No error, no warning you\n\nwould notice, and a running system that is doing something other than what the\n\nfile says.\n\n`timeout: 500` is the sharpest example: the file says half a second, the system\n\nsays a day and change, and **both are working as designed.**\n\nWhat I want from a configuration checker, having been on the wrong end of these,\n\nis not more rules. It is that the ones it does have never fire on something\n\ncorrect — because the reason I stopped reading startup output in the first place\n\nwas that nothing there had ever mattered, and by the time something did, I had\n\nalready trained myself past it.\n\n```\nnpx @quintetkit/ccheck\nerror .mcp.json:3\n      Server \"example\" has a `url` but no `type`. Add `\"type\": \"http\"` (or \"sse\" / \"ws\").\nwarn  .mcp.json:9\n      Server \"flaky\": `timeout: 500` is in milliseconds; values below 1000 are ignored.\n```\n\nThe full set, including the required field per transport:\n\n[https://quintetkit.github.io/en/reference/claude-code-mcp-json.html](https://quintetkit.github.io/en/reference/claude-code-mcp-json.html)\n\nI publish the configuration for splitting Claude Code into separate personas —\n\nArchitect, Coder, Reviewer, Conflict Resolver — under MIT. Copy it, run\n\n`./setup.sh`, and it works. It does not depend on your tech stack.\n\n[https://github.com/quintetkit/quartet](https://github.com/quintetkit/quartet)\n\nI built one real tool using nothing but this workflow. Every Issue, PR, review\n\nand merge is still there. **The parts that went wrong were not deleted.**\n\n[https://github.com/quintetkit/mdlinkcheck](https://github.com/quintetkit/mdlinkcheck)\n\nThe version that adds a UI Designer persona, review criteria, a per-Issue\n\nparallel execution script and a 11-chapter guide is on the\n\n[product page](https://quintetkit.github.io/index.en.html).\n\nThe full kit — five personas, the scripts and the complete guide — is available here.", "url": "https://wpnews.pro/news/i-set-a-500ms-timeout-and-got-28-hours", "canonical_source": "https://dev.to/quintetkit/i-set-a-500ms-timeout-and-got-28-hours-20p3", "published_at": "2026-09-12 01:16:42+00:00", "updated_at": "2026-09-12 01:56:18.769618+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-agents", "ai-products"], "entities": ["Claude Code", "MCP", "quintetkit", "ccheck", "quartet", "mdlinkcheck"], "alternates": {"html": "https://wpnews.pro/news/i-set-a-500ms-timeout-and-got-28-hours", "markdown": "https://wpnews.pro/news/i-set-a-500ms-timeout-and-got-28-hours.md", "text": "https://wpnews.pro/news/i-set-a-500ms-timeout-and-got-28-hours.txt", "jsonld": "https://wpnews.pro/news/i-set-a-500ms-timeout-and-got-28-hours.jsonld"}}