Get started
This page takes you from zero to a successful spec lookup in five minutes: pick how you run tc39-mcp, wire it into your MCP client, and call your first tool.
What is MCP?
The Model Context Protocol (MCP) is an open client/server protocol for giving a language model access to external tools, resources, and prompts. Servers expose capabilities; clients (chat apps, IDEs, agents) connect over stdio or HTTP and forward typed tool calls between the model and the server. See modelcontextprotocol.io for the upstream spec.
tc39-mcp is an MCP server. It exposes 19 tools that answer structured questions about ECMA-262 + ECMA-402 — clause text, algorithm steps, cross-references, edition diffs, git history, test262 search, proposal lookup. If your client already speaks MCP, adding it is one config entry away.
Pick how you run it
tc39-mcp runs two ways, with the same wire protocol either way. Pick one:
| Local (stdio) | Hosted (HTTP) | |
|---|---|---|
| How | npx tc39-mcp as a local subprocess | point your client at a URL |
| Install | Node 20+ | none |
| Tools | all 19 | 17 — no spec.history / test262.get |
| Latency | local subprocess, fast | one network hop per call |
| Data freshness | live from the Worker on first use, then cached + revalidated ~4 h (bundled subset offline) | live, auto-refreshed every ~4 h |
| Offline use | ✓ for bundled editions (latest + main); fetched-on-first-use otherwise | ✗ |
| Rate limit | none | 30 req / min / IP |
Most people want Local for personal use — every tool, and it works offline. Choose Hosted when you can't install Node, when a team shares one endpoint, or when you want the always-current Worker pin. The only functional difference is the two tools below: they need a subprocess or the on-disk test262 corpus, so they run locally only.
Local (stdio)
Runs tc39-mcp as a subprocess of your MCP client through npx — no global install, all 19 tools, and the bundled editions answer offline. The launch command is identical across MCP clients; only the config file's location differs (check your client's MCP docs). Add the server:
{
"mcpServers": {
"tc39": {
"command": "npx",
"args": ["tc39-mcp"]
}
}
}Clients that take a bare stdio command instead of a mcpServers map (e.g. the MCP Inspector) use:
{ "command": "npx", "args": ["tc39-mcp"] }The first call for a given snapshot fetches it from the hosted Worker and caches it on disk; later calls are served locally, revalidated against the Worker only after the ~4-hour freshness window. If the Worker is unreachable, the bundled latest + main editions still answer. Restart your client after editing the config.
Hosted (HTTP)
Point your client at the hosted Cloudflare Worker — zero install, but 17 of the 19 tools: everything except spec.history (needs a git subprocess) and test262.get (needs the on-disk test262 corpus).
{
"mcpServers": {
"tc39": {
"type": "http",
"url": "https://mcp.xyzzylabs.ai/tc39/mcp"
}
}
}Requests are rate-limited to 30 / minute / IP and every call is a network hop (no offline mode). Each tool's exact availability is on the tool reference — look for the Availability line.
Make your first call
This works on either transport. A good first call is clause.get against sec-tonumber — short input, structured output, no parameters to guess at.
In a chat / agent client, the natural-language prompt:
Use
clause.getto fetchsec-tonumberfrom the latest ECMA-262. Show me the algorithm steps.
triggers a call equivalent to:
{ "tool": "clause.get", "arguments": { "id": "sec-tonumber" } }The response is a structured Clause object: meta (id, aoid, title, section number, kind), signatureRaw, algorithms[].steps, notes, crossrefs, and external_refs — outward citations to other specs (Unicode, IETF, WHATWG), present only when the clause links to them. The full field list lives on tools.md → clause.get.
Verify it's working
Once the call returns, sanity-check the response:
- The
meta.aoidfield should be"ToNumber". - The
meta.numberfield should be"7.1.4"(in es2025 and later). - The first step in
algorithms[0].stepsshould match the spec prose verbatim —"If _argument_ is a Number, return _argument_."
If you got back null instead, the clause id was probably wrong; try spec.search ({ query: "ToNumber" }) to find the right id.
If the server didn't respond at all, two things to check:
- Node version (Local): tc39-mcp targets Node 20+. Older Node refuses to start with a clear error.
- MCP transport: confirm your client logs show a
tools/listhandshake. Most MCP clients log this; if you see nothing, the stdio server probably never launched, or the hosted URL is wrong.
Workflow prompts
Beyond tools, the server advertises MCP prompts — reusable templates that steer an agent through a multi-tool workflow. In a client that supports prompts (prompts/list + prompts/get), pick one instead of hand-assembling the tool sequence:
| Prompt | What it does |
|---|---|
explain-clause | read a clause and explain its steps in plain language |
compare-editions | diff a clause across two editions |
find-and-read | search by name/symptom, then read the top hit |
trace-crossrefs | map a clause's incoming/outgoing references |
proposal-status | look up a TC39 proposal's stage + details |
test262-for-feature | find the conformance tests for a feature or clause |
cite-reproducibly | produce a SHA-pinned citation block |
Each is a pure text template — it returns guidance the model then acts on by calling tools normally; the prompt never runs anything itself. Both transports advertise the same set.
Next steps
- Tool reference — every tool, every input field, every example call, plus each tool's Availability (hosted vs stdio-only).
- Cookbook — multi-tool recipes for common workflows (cross-spec lookups, prose-drift tracking, etc.).
- Editions + specs — which editions and aliases are supported and how
latestresolves per spec. - Architecture — how the server is wired internally and the design constraints that shape the tool surface.