tc39-mcp
by xyzzylabs · remote · local (npm) · no sign-in to list tools · v0.6.4 · published by GitHub user xyzzylabs
Independent MCP server for the TC39 specs (ECMA-262 + ECMA-402): clauses, search, diffs, history.
17 tools: 5 change things and 12 only read.
Scanned Oct 21, 2026
- Deletes or cancels0Claude Code: deny
- Can't be undone0Claude Code: ask
- Changes things5Claude Code: ask: see these tools
- Only reads12Claude Code: allow: see these tools
No check matched anything in the tool definitions. No finding is not a safety guarantee. How the checks work.
claude mcp add --transport http tc39 https://mcp.xyzzylabs.ai/tc39/mcpTools
Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.
17 tools
Changes things 5Claude Code: ask
spec.aboutSelf-description of this MCP server: package name + version, per-snapshot pin metadata (sha, fetched_at, biblio_commit, clause_count) for every supported (spec, edition), plus test…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Self-description of this MCP server: package name + version, per-snapshot pin metadata (sha, fetched_at, biblio_commit, clause_count) for every supported (spec, edition), plus test262 + proposals index headers when present.
spec.crossrefsFor a clause id, return its outgoing references (clauses it cites) and/or incoming references (clauses that cite it — the back-reference index the parse alone doesn't expose).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it For a clause id, return its outgoing references (clauses it cites) and/or incoming references (clauses that cite it — the back-reference index the parse alone doesn't expose). The reverse index is AOID-densified from step text. `direction`: 'in' | 'out' | 'both' (default). Outgoing also carries an `external` category: the clause's citations to external specs (Unicode, IETF, WHATWG) as resolvable URLs. Set `include_cross_spec: true` to also resolve outgoing references from ECMA-262 → ECMA-402 (or vice versa).
spec.global_searchRun spec.search across both ECMA-262 and ECMA-402 in one call and interleave hits by score.No findings
Why it is in this group
- The name "spec.global_search" says "search": a word for reading.
- The description's first verb is "run": a word for a change.
Description, as the server wrote it Run spec.search across both ECMA-262 and ECMA-402 in one call and interleave hits by score. Each hit is tagged with the spec it came from. Use it when you don't know which spec defines a symbol. `search_steps` also matches algorithm step text.
spec.sdo_indexIndex Syntax-Directed Operations by the grammar production they're defined on.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Index Syntax-Directed Operations by the grammar production they're defined on. `by: 'production'` (default) groups SDOs under each production; `by: 'sdo'` groups productions under each SDO title. `filter` narrows to keys containing a substring (case-insensitive).
spec.well_known_intrinsicsEnumerate the well-known intrinsics in a spec with their probable defining clauses.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Enumerate the well-known intrinsics in a spec with their probable defining clauses. Driven from the canonical §6.1.7.4 WKI table when present (ECMA-262), else a `%X%` prose scan (e.g. ECMA-402). `filter` narrows by bare-name substring.
Only reads 12Claude Code: allow
clause.getFetch a parsed TC39 clause as structured JSON.No findings
Why it is in this group
- The name "clause.get" says "get": a word for reading.
Description, as the server wrote it Fetch a parsed TC39 clause as structured JSON. `spec` selects '262' (default) or '402'. `edition` defaults to 'latest'. `at: '<sha>'` pins to a historical main snapshot (only valid for edition='main'); omit to query the live snapshot.
clause.listList parsed spec clauses with optional filters (kind, section prefix, has_algorithm).No findings
Why it is in this group
- The name "clause.list" says "list": a word for reading.
Description, as the server wrote it List parsed spec clauses with optional filters (kind, section prefix, has_algorithm). `spec` selects '262' or '402'. `at: '<sha>'` queries a historical main snapshot.
clause.outlineReturn the section tree (table of contents) for a parsed (spec, edition).Reads private dataNo findings
Why it is in this group
- The description's first verb is "return": a word for reading.
What it can reach
- private-dataThe description's first sentence says "return" and "table": it reads databases.
Description, as the server wrote it Return the section tree (table of contents) for a parsed (spec, edition). `depth` caps how deep the tree descends (1 = top-level only); `under` limits the tree to descendants of one clause id.
proposal.getFetch one TC39 proposal by slug (exact) or name (case-insensitive).No findings
Why it is in this group
- The name "proposal.get" says "get": a word for reading.
Description, as the server wrote it Fetch one TC39 proposal by slug (exact) or name (case-insensitive).
proposal.listList TC39 proposals from the static index (tc39/proposals).No findings
Why it is in this group
- The name "proposal.list" says "list": a word for reading.
Description, as the server wrote it List TC39 proposals from the static index (tc39/proposals). Filter by spec ('262'|'402'), stage ('0'|'1'|'2'|'2.7'|'3'|'finished'|'inactive'|'active'), champion (substring), or contains (name/slug substring).
spec.diffClause-level diff of one clause across two editions of a spec.No findings
Why it is in this group
- The name "spec.diff" says "diff": a word for reading.
Description, as the server wrote it Clause-level diff of one clause across two editions of a spec. Reports identical / modified / added / removed plus a field-level breakdown (title, signature, step count, reworded step indices, notes, crossrefs). `from` defaults to the latest stable release, `to` to main.
spec.grammarQuery grammar productions captured from the spec's `<emu-grammar>` blocks.No findings
Why it is in this group
- The description's first verb is "query": a word for reading.
Description, as the server wrote it Query grammar productions captured from the spec's `<emu-grammar>` blocks. `{ nonterminal }` returns every production for that non-terminal (exact match); `{ contains }` filters by RHS / name substring; neither lists all non-terminals + their production counts. `include_sdo` folds in SDO-attached productions (off by default).
spec.searchSearch the parsed spec by clause id / aoid / title (+ step text with `search_steps`).No findings
Why it is in this group
- The name "spec.search" says "search": a word for reading.
Description, as the server wrote it Search the parsed spec by clause id / aoid / title (+ step text with `search_steps`). Aoid-exact ranks first. `at: '<sha>'` searches a historical main snapshot.
spec.snapshotsList the live (spec, edition, sha, fetched_at) snapshots the hosted Worker is serving from R2.No findings
Why it is in this group
- The name "spec.snapshots" says "snapshot": a word for reading.
Description, as the server wrote it List the live (spec, edition, sha, fetched_at) snapshots the hosted Worker is serving from R2. Filter by `spec` ('262'|'402') or `edition` (e.g. 'main', 'es2026'). Historical SHA-pinned copies are reachable via `at:` on clause.get / spec.search but aren't enumerated here.
spec.symbol_resolveResolve spec notation like `[[Prototype]]` (internal slot), `%Object.prototype%` (well-known intrinsic), or `~number~` (sigil enum): return clauses that mention or define it, ranke…Reads text others writeNo findings
Why it is in this group
- The name "spec.symbol_resolve" says "resolve": a word for reading.
What it can reach
- untrusted-inputThe description's first sentence says "resolve" and "mention": it reads comments, which other people can write.
Description, as the server wrote it Resolve spec notation like `[[Prototype]]` (internal slot), `%Object.prototype%` (well-known intrinsic), or `~number~` (sigil enum): return clauses that mention or define it, ranked by occurrence with a bump for definition-y sections.
spec.tablesList or fetch parsed `<emu-table>` content.Reads private dataNo findings
Why it is in this group
- The description's first verb is "list": a word for reading.
What it can reach
- private-dataThe name "spec.tables" says "table": it reads databases.
- private-dataThe description's first sentence says "list" and "table": it reads databases.
Description, as the server wrote it List or fetch parsed `<emu-table>` content. `{ id }` returns exactly that table (full columns + rows); otherwise list table summaries, optionally narrowed by a `filter` substring over the caption or id.
test262.searchSearch the tc39/test262 conformance suite from its indexed front-matter.No findings
Why it is in this group
- The name "test262.search" says "search": a word for reading.
Description, as the server wrote it Search the tc39/test262 conformance suite from its indexed front-matter. `query` AND-matches whitespace tokens (case-insensitive) across each test's description + path; `esid` prefix-matches the front-matter esid. Returns ranked hits (path, GitHub url at the indexed SHA, esid, description, features, flags), capped at `limit` (default 20). Supply at least one of `query` / `esid`.
This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.
Exfil surface
Which tools read private data, which read text someone else can write, and which can send data out. One of each is a path a prompt injection can use.
No private-data, untrusted-input, outbound path in this server alone: no tool is tagged outbound.
- Reads private data2
- Reads files, mail, messages, databases, secrets, calendars or repositories.
- Reads text others write1
- Brings in text someone else can write: web pages, inbound email, messages, issues and comments.
- Can send data out0
- Can carry data to people or systems: it sends, posts or publishes, or takes a recipient, channel or URL.
Other servers in the same agent add their own tools to these paths. Audit your whole setup to see them together.
Install
Pinned to version 0.6.4. Values in angle brackets are yours to fill in.
claude mcp add --transport http tc39 https://mcp.xyzzylabs.ai/tc39/mcpRun in a terminal.
Claude Code permissions
Allow the reads, ask before a change or a way out, deny the deletes. Paste into .claude/settings.json.
{
"permissions": {
"allow": [
"mcp__tc39__clause_get",
"mcp__tc39__clause_list",
"mcp__tc39__spec_search",
"mcp__tc39__proposal_list",
"mcp__tc39__proposal_get",
"mcp__tc39__spec_grammar",
"mcp__tc39__spec_tables",
"mcp__tc39__clause_outline",
"mcp__tc39__spec_snapshots",
"mcp__tc39__spec_symbol_resolve",
"mcp__tc39__spec_diff",
"mcp__tc39__test262_search"
],
"ask": [
"mcp__tc39__spec_about",
"mcp__tc39__spec_sdo_index",
"mcp__tc39__spec_global_search",
"mcp__tc39__spec_well_known_intrinsics",
"mcp__tc39__spec_crossrefs"
],
"deny": []
}
}Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. A read that can send data out (it takes a URL, say) asks first too. It assumes the server is installed as tc39. Review it before you use it.
Capability tags behind 3 rules
- mcp__tc39__spec_tables private-data
- mcp__tc39__clause_outline private-data
- mcp__tc39__spec_symbol_resolve untrusted-input
