TC39 Specs (ECMA-262 + ECMA-402) MCP Server
Parsed ECMA-262 and ECMA-402 specs over MCP โ clauses, algorithm steps, cross-references, edition diffs, test262 and proposal search.
Documentation
tc39-mcp
๐ Docs: tc39-mcp.chicoxyzzy.workers.dev โ Get started ยท Tools ยท Cookbook ยท Editions ยท Architecture ยท Hosting ยท Sponsor
Give MCP-speaking AI agents structural access to the JS spec.
Claude Code, Claude Desktop, Cursor, MCP Inspector, and anything
else that speaks the Model Context Protocol can now call
clause.get sec-tonumber and get back parsed JSON (algorithm
steps as discrete arrays, cross-references as ids, signatures as
typed values) instead of being handed a 4 MB spec.html to grep
through. Tools cover ECMA-262
(the core language) and ECMA-402
(the Intl API): clauses, algorithm steps, cross-references both
ways, edition diffs, upstream git history, test262 search,
proposal lookup. Every response is SHA-pinned to a specific
upstream commit so anything an agent cites stays reproducible.
Offline-first by default: the stdio transport (npx tc39-mcp)
ships every parsed snapshot in the tarball, so once installed it
runs entirely offline โ no network call per agent query, no
leakage of which clause the agent is reading. The hosted
Cloudflare Worker is the HTTP alternative when you want a shared
network endpoint; it auto-refreshes from upstream every ~4 hours.
Install + first call
Wire into Claude Code, Claude Desktop, Cursor, or any MCP-speaking
client via .mcp.json:
{
"mcpServers": {
"tc39": { "command": "npx", "args": ["tc39-mcp"] }
}
}
The first run downloads ~50 MB (the parsed snapshots ship in the tarball โ no separate fetch step needed, and every subsequent call is served from local disk with no network round-trip). Then in your client:
use
clause.getto readsec-tonumberand show me the steps
You should see structured JSON back:
{
"meta": {
"id": "sec-tonumber",
"aoid": "ToNumber",
"title": "ToNumber ( argument )",
"number": "7.1.4",
"kind": "op"
},
"signatureRaw": "ToNumber ( _argument_: an ECMAScript language value, ): either a normal completion containing a Number or a throw completion",
"algorithms": [
{ "steps": [
{ "text": "If _argument_ is a Number, return _argument_." },
{ "text": "If _argument_ is either *undefined* or a Symbol, throw a *TypeError* exception." },
{ "text": "If _argument_ is *null*, return *+0*<sub>๐ฝ</sub>." },
"..."
]}
],
"crossrefs": ["sec-tonumber-applied-to-the-string-type", "..."]
}
Five-minute walkthrough: docs/getting-started.md.
Other transports
Hosted Cloudflare Worker (HTTP)
{
"mcpServers": {
"tc39": {
"type": "http",
"url": "https://tc39-mcp.chicoxyzzy.workers.dev/mcp"
}
}
}
Anonymous traffic is rate-limited to 30 req/min per IP.
Sponsors get 300 req/min per key by adding an
Authorization: Bearer tcms_โฆ header.
Global CLI
npm i -g tc39-mcp
tc39-mcp # reads stdio
What it's good at
- Letting an agent reason about the spec without hallucinating. Structured JSON answers ground the model on real spec text: step numbering, cross-reference targets, signature shapes, edition deltas, conformance tests. Anything cited resolves to a specific clause id at a specific SHA โ easy to verify, easy to reproduce.
- Finding the clause you want from a hint.
spec.searchranks AOID-exact matches first;spec.symbol_resolvedecodes[[Prototype]]/%Object.prototype%/~enumerate~. - Following references both ways.
spec.crossrefsreturns what a clause cites AND who cites it. AOID-densified so bare mentions in step text count, not just<emu-xref>hrefs.include_cross_specresolves 262 โ 402 hops. (Cookbook recipe 1.) - Comparing editions and tracking prose drift.
spec.diffbetween any two editions back to ES2016;spec.historywalks the upstream git log via pickaxe search. (Cookbook recipe 2.) - Finding test262 coverage for a clause.
test262.searchwith prefix-matchedesid:catchessec-tonumberANDsec-tonumber-applied-to-the-string-typein one call. - Mapping proposals to the spec.
proposal.list/proposal.getfrom a structured index oftc39/proposals, refreshed on the same 4-hour cadence as the specs. - Running entirely offline (stdio). Once
npx tc39-mcphas installed, every tool call is served from on-disk snapshots โ no network round-trip per query, no leakage of which clause the agent is reading, no upstream rate limit. The hosted Worker is the HTTP alternative for shared / multi-tenant use.
Tools (19 across 5 namespaces)
| Goal | Tool(s) |
|---|---|
| Verify what's being served | spec.about ยท spec.snapshots |
| Read a specific clause | clause.get |
| Find a clause from a name / symptom | spec.search ยท spec.global_search |
Resolve [[X]] / %X% / ~X~ notation | spec.symbol_resolve |
| Browse / outline | clause.list ยท clause.outline |
| Compare editions / commit history | spec.diff ยท spec.history |
| Walk references (in + out) | spec.crossrefs |
| Read structured tables | spec.tables |
| Inspect the grammar | spec.grammar ยท spec.sdo_index |
| Enumerate well-known intrinsics | spec.well_known_intrinsics |
| Find conformance tests | test262.search ยท test262.get |
| Look up a proposal | proposal.list ยท proposal.get |
Full reference (input schemas, output types, example calls per
tool): docs/tools.md โ auto-generated from
the schemas so it never drifts.
Specs + editions
Every spec-reading tool accepts spec ("262" or "402", default
"262") and edition (default "latest").
- ECMA-262:
es2016โes2025,main. (ES5 / ES5.1 / ES6 have no upstream tags and aren't supported.) - ECMA-402:
es2025-candidate,main. (No annual final-release tagging upstream.) - Aliases:
latestis spec-aware (262 โ current stable release; 402 โmain).draft/nextโmainon both.
Full table + how to add new releases: docs/editions.md.
Sponsorship
The free anonymous tier of the hosted Worker stays free โ 30 req/min per IP, no signup, no key. Sponsorship is optional and goes toward keeping the hosted Worker running comfortably as usage grows.
Sponsors at any tier โฅ $5/mo get an API key (tcms_โฆ) that gives
them 300 req/min bucketed per-key instead of per-IP, so the
same key can drive an interactive chat, a CI pipeline, and a
batch agent without those processes competing for budget.
To sponsor: https://github.com/sponsors/xyzzylabs. The maintainer
DMs you the key via GitHub Sponsors. Full tier setup +
client-side wiring instructions: docs/sponsor.md.
Build from source (contributors)
End users don't need this โ the npm package and the hosted Worker are the supported surfaces above. This is for working on the server itself.
git clone https://github.com/xyzzylabs/tc39-mcp
cd tc39-mcp
npm install
npm run fetch-spec # ~2 min, ~150 MB โ both specs at every supported edition
npm run parse # spec.html โ build/spec-<spec>-<edition>.json
npm run fetch-test262 # optional, enables test262.* (~300 MB)
npm run build-test262-index
npm run fetch-proposals # optional, enables proposal.* (~50 MB)
npm run build-proposals-index
npm run mcp # start the stdio MCP server against your source
Point Claude Code at your local source instead of the published bin:
{
"mcpServers": {
"tc39": {
"type": "stdio",
"command": "npm",
"args": ["run", "mcp"],
"cwd": "/abs/path/to/tc39-mcp"
}
}
}
Docs
Hosted at tc39-mcp.chicoxyzzy.workers.dev
โ searchable, dark-mode-friendly, auto-rebuilt on every refresh so
/snapshots always reflects the live SHAs.
In-repo (also browseable on GitHub):
docs/getting-started.mdโ install โ wire โ first call โ verify. Five minutes.docs/tools.mdโ every tool, every field, every example. Auto-generated from source.docs/cookbook.mdโ multi-tool recipes: cross-spec lookups, prose-drift tracking, grammar/SDO cross-references, test262 coverage, proposal-to-clause mapping.docs/editions.mdโ supported editions + alias resolution.docs/architecture.mdโ data pipeline, parser, cache, memory model.docs/deployment.mdโ local stdio, npm CLI, hosted Cloudflare Worker, refresh model, observability, sponsor lifecycle.docs/sponsor.mdโ sponsorship tiers, key setup, security model.CONTRIBUTING.mdโ what kinds of changes land easily, what won't.SECURITY.mdโ threat model + responsible disclosure.CHANGELOG.mdโ version history + auto-refresh convention.
Privacy Policy
tc39-mcp is a read-only spec lookup service. The stdio transport
(npx tc39-mcp) collects nothing โ every spec snapshot ships
in the npm tarball and the server runs entirely offline. The
hosted Cloudflare Worker collects only standard request metadata
(IP for rate limiting, timestamps, request headers); it does not
log request bodies, set cookies, or share data with third parties.
Full policy: tc39-mcp.chicoxyzzy.workers.dev/privacy
For privacy questions, open an issue with the privacy label on
GitHub.
License
MIT