Koskamo

tc39-mcp

Structured MCP server providing read-only access to ECMAScript (ECMA-262) and Intl (ECMA-402) specifications. It enables AI agents to perform clause lookups, search by AOID, analyze cross-spec references, view edition diffs, and access test262 data using deterministic, SHA-pinned JSON responses.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

tc39-mcp logo, by xyzzy_labsCommunity listingStreamable HTTPNo sign-inEndpoint checked 2026-11-06Published by xyzzy_labs
MCP endpoint (Streamable HTTP)
https://mcp.xyzzylabs.ai/tc39/mcp
Vendor documentation

What its tools do

17 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

17 of 17 have a description · 0 of 17 declare behavior hints · 0 of 16 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Lookup specific ECMAScript clauses by ID
  • Search specifications by AOID or text
  • Analyze differences between language editions
  • Resolve cross-references between ECMA-262 and ECMA-402

Source and maintenance

Community listingRegistry 0.6.4
Maintenance checked

Protocol and capabilities

Server
tc39-mcp 0.6.5
MCP protocol negotiated in check
2024-11-05
Tools
17 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
7 advertised
Server-advertised capabilities
{
  "tools": {},
  "prompts": {}
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

tc39-mcp serves read-only structured data from the TC39 specs (ECMA-262 + ECMA-402), tc39/test262, and tc39/proposals. Every response is deterministic over data pinned to specific upstream SHAs. Independent project — not an official Ecma International or TC39 publication. This is the hosted Cloudflare Worker deployment — 17 of the 19 tools (call tools/list for the set). The 2 stdio-only ones (spec.history, test262.get) are available via the stdio server (npx tc39-mcp). Common workflow: 1. `spec.about` — call first to see what SHAs and editions the server is serving. Returns per-snapshot pin metadata. 2. `spec.search` — find a clause from a name or symptom. Hits rank aoid-exact > aoid-substring > title > id; follow up with `clause.get { id }` to read the full clause. To find clauses by what they DO (e.g. which clauses invoke OrdinaryGetOwnProperty), pass search_steps: true to also scan algorithm step text — off by default since it is slower + noisier. 3. `clause.get { id, spec?, edition? }` — full structured clause. A clause id is also a test262 esid — test262.search { esid: <clause-id> } returns the conformance tests for that clause. Edition semantics. `latest` is spec-aware: - On 262, `latest` → current stable release (es2026 today). - On 402, `latest` → current stable release (es2026 today). - `main` is always the working draft. Historical pinning. `main` moves. Pass `at: "<sha>"` to query a specific historical snapshot (4-40 hex chars, prefix-matched). The hosted Worker retains every `main` SHA it has deployed since launch; the live snapshot is `at`-less. Released editions like `es2026` have no per-SHA history, so `at` doesn't apply — it only addresses `main`. Missing data is never an error. Tools return null, empty arrays, or a `hint:` field. `source: "none"` on `proposal.list` means the offline index isn't present in R2 — surface the hint to the user. MCP prompts (workflow templates) — prefer these when the user wants a guided multi-tool sequence. Available prompts: explain-clause, compare-editions, find-and-read, trace-crossrefs, proposal-status, test262-for-feature, cite-reproducibly. Call prompts/list for their argument shapes. All data is read-only: no tool modifies anything upstream, no tool runs user-supplied code. Safe to call freely.

Tools

17 advertised

spec.about
Advertised by the server during the last successful anonymous check.

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.about input schema
{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}
clause.get
Advertised by the server during the last successful anonymous check.

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.get input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "at": {
      "type": "string",
      "description": "Optional historical SHA pin (hex, 4-40 chars). Only valid when edition='main'; released editions have no per-SHA history to address."
    },
    "id": {
      "type": "string"
    },
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "edition": {
      "type": "string"
    }
  }
}
clause.list
Advertised by the server during the last successful anonymous check.

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.list input schema
{
  "type": "object",
  "properties": {
    "at": {
      "type": "string"
    },
    "kind": {
      "type": "string"
    },
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "limit": {
      "type": "number"
    },
    "edition": {
      "type": "string"
    },
    "section": {
      "type": "string"
    },
    "has_algorithm": {
      "type": "boolean"
    }
  }
}
spec.search
Advertised by the server during the last successful anonymous check.

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.search input schema
{
  "type": "object",
  "required": [
    "query"
  ],
  "properties": {
    "at": {
      "type": "string"
    },
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "limit": {
      "type": "number"
    },
    "query": {
      "type": "string"
    },
    "edition": {
      "type": "string"
    },
    "search_steps": {
      "type": "boolean"
    }
  }
}
proposal.list
Advertised by the server during the last successful anonymous check.

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).

proposal.list input schema
{
  "type": "object",
  "properties": {
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "limit": {
      "type": "number"
    },
    "stage": {
      "type": "string"
    },
    "champion": {
      "type": "string"
    },
    "contains": {
      "type": "string"
    }
  }
}
proposal.get
Advertised by the server during the last successful anonymous check.

Fetch one TC39 proposal by slug (exact) or name (case-insensitive).

proposal.get input schema
{
  "type": "object",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "type": "string"
    }
  }
}
spec.grammar
Advertised by the server during the last successful anonymous check.

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.grammar input schema
{
  "type": "object",
  "properties": {
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "limit": {
      "type": "number"
    },
    "edition": {
      "type": "string"
    },
    "contains": {
      "type": "string"
    },
    "include_sdo": {
      "type": "boolean"
    },
    "nonterminal": {
      "type": "string"
    }
  }
}
spec.tables
Advertised by the server during the last successful anonymous check.

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.

spec.tables input schema
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "limit": {
      "type": "number"
    },
    "filter": {
      "type": "string"
    },
    "edition": {
      "type": "string"
    }
  }
}
spec.sdo_index
Advertised by the server during the last successful anonymous check.

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.sdo_index input schema
{
  "type": "object",
  "properties": {
    "by": {
      "enum": [
        "production",
        "sdo"
      ],
      "type": "string"
    },
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "limit": {
      "type": "number"
    },
    "filter": {
      "type": "string"
    },
    "edition": {
      "type": "string"
    }
  }
}
clause.outline
Advertised by the server during the last successful anonymous check.

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.

clause.outline input schema
{
  "type": "object",
  "properties": {
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "depth": {
      "type": "number"
    },
    "under": {
      "type": "string"
    },
    "edition": {
      "type": "string"
    }
  }
}
spec.global_search
Advertised by the server during the last successful anonymous check.

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.global_search input schema
{
  "type": "object",
  "required": [
    "query"
  ],
  "properties": {
    "limit": {
      "type": "number"
    },
    "query": {
      "type": "string"
    },
    "search_steps": {
      "type": "boolean"
    }
  }
}
spec.snapshots
Advertised by the server during the last successful anonymous check.

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.snapshots input schema
{
  "type": "object",
  "properties": {
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "edition": {
      "type": "string"
    }
  }
}
spec.symbol_resolve
Advertised by the server during the last successful anonymous check.

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.symbol_resolve input schema
{
  "type": "object",
  "required": [
    "notation"
  ],
  "properties": {
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "limit": {
      "type": "number"
    },
    "edition": {
      "type": "string"
    },
    "notation": {
      "type": "string"
    }
  }
}
spec.well_known_intrinsics
Advertised by the server during the last successful anonymous check.

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.

spec.well_known_intrinsics input schema
{
  "type": "object",
  "properties": {
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "limit": {
      "type": "number"
    },
    "filter": {
      "type": "string"
    },
    "edition": {
      "type": "string"
    }
  }
}
spec.diff
Advertised by the server during the last successful anonymous check.

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.diff input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "to": {
      "type": "string"
    },
    "from": {
      "type": "string"
    },
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    }
  }
}
spec.crossrefs
Advertised by the server during the last successful anonymous check.

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.crossrefs input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "spec": {
      "enum": [
        "262",
        "402"
      ],
      "type": "string"
    },
    "limit": {
      "type": "number"
    },
    "edition": {
      "type": "string"
    },
    "direction": {
      "enum": [
        "in",
        "out",
        "both"
      ],
      "type": "string"
    },
    "include_cross_spec": {
      "type": "boolean"
    }
  }
}
test262.search
Advertised by the server during the last successful anonymous check.

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`.

test262.search input schema
{
  "type": "object",
  "properties": {
    "esid": {
      "type": "string"
    },
    "limit": {
      "type": "number"
    },
    "query": {
      "type": "string"
    }
  }
}

Prompts

7 advertised

explain-clause — Explain a clause

Advertised by the server during the last successful anonymous check.

Walk through a TC39 clause: call spec.about for pins, clause.get for the full clause, then explain the algorithm steps in plain language with citations.

id
Clause id, e.g. sec-tonumber or sec-intl.numberformat (required)
spec
Spec to read: '262' (default) or '402'
edition
Edition alias or concrete edition (latest, main, es2026, …)
compare-editions — Compare editions

Advertised by the server during the last successful anonymous check.

Diff one clause across two editions via spec.diff, then optionally clause.get on each side for full step text. Summarize what changed and why it might matter.

id
Clause id to compare (required)
spec
Spec: '262' (default) or '402'
from
Before edition (default: latest)
to
After edition (default: main)
find-and-read — Find and read

Advertised by the server during the last successful anonymous check.

Search for a clause by name/symptom (spec.search or spec.global_search), pick the best hit, then clause.get and summarize.

query
Search string (AOID, title fragment, or symptom) (required)
spec
Limit to one spec ('262' or '402'). Omit to search both via spec.global_search.
edition
Edition for the search/read (default: latest)
search_steps
If 'true', also match algorithm step text (slower, broader)
trace-crossrefs — Trace cross-references

Advertised by the server during the last successful anonymous check.

Map who a clause cites and who cites it via spec.crossrefs, then spot-check key neighbors with clause.get.

id
Clause id to start from (required)
spec
Spec: '262' (default) or '402'
edition
Edition (default: latest)
direction
in | out | both (default: both)
include_cross_spec
If 'true', also resolve 262↔402 outgoing refs
proposal-status — Proposal status

Advertised by the server during the last successful anonymous check.

Look up TC39 proposal stage/champions via proposal.list and/or proposal.get, then summarize maturity and where to read more.

query
Proposal slug (preferred) or name/substring, e.g. temporal or 'pipeline operator' (required)
stage
Optional stage filter for list: 0|1|2|2.7|3|finished|inactive|active
test262-for-feature — test262 for a feature

Advertised by the server during the last successful anonymous check.

Find test262 coverage via test262.search (and test262.get on stdio for full source). Summarize how the feature is tested.

query
Free-text search (feature name, path fragment, …)
esid
Clause id / esid prefix (e.g. sec-tonumber)
cite-reproducibly — Cite reproducibly

Advertised by the server during the last successful anonymous check.

Produce a citation block with SHA pins: call spec.about, then clause.get, and format a reproducible reference (spec, edition, sha, clause id/number/title).

id
Clause id to cite (required)
spec
Spec: '262' (default) or '402'
edition
Edition (default: latest)

Resources

Not advertised

No resource definitions available.

90-day uptime

A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.

Too few checks for a percentage yet (1 of 1 answered).

  1. 2026-11-07: 1 of 1 checks answered

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
396 ms
95th percentile latency
396 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 396 ms · metadata changed · 17 tool(s), 7 prompt(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http tc39-mcp-xyzzylabs https://mcp.xyzzylabs.ai/tc39/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add tc39-mcp-xyzzylabs --url https://mcp.xyzzylabs.ai/tc39/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable tc39-mcp-xyzzylabs in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "tc39-mcp-xyzzylabs": {
      "url": "https://mcp.xyzzylabs.ai/tc39/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "tc39-mcp-xyzzylabs": {
      "type": "streamableHttp",
      "url": "https://mcp.xyzzylabs.ai/tc39/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start tc39-mcp-xyzzylabs and inspect its tools.
VS Code configuration
{
  "servers": {
    "tc39-mcp-xyzzylabs": {
      "type": "http",
      "url": "https://mcp.xyzzylabs.ai/tc39/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http tc39-mcp-xyzzylabs https://mcp.xyzzylabs.ai/tc39/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://mcp.xyzzylabs.ai/tc39/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "tc39-mcp-xyzzylabs": {
      "serverUrl": "https://mcp.xyzzylabs.ai/tc39/mcp"
    }
  }
}

Let your agent find its tools

Find servers like tc39-mcp from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.