wasm-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/LICENSE +21 -0
- package/README.md +108 -0
- package/build/wasm-proposals-main.json +1 -0
- package/build/wasm-sections-js-api-main.json +1 -0
- package/build/wasm-sections-web-api-main.json +1 -0
- package/build/wasm-spec-core-main.json +1 -0
- package/dist/mcp/_args.d.ts +22 -0
- package/dist/mcp/_args.js +25 -0
- package/dist/mcp/instructions.d.ts +1 -0
- package/dist/mcp/instructions.js +67 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +63 -0
- package/dist/mcp/tool_meta.d.ts +32 -0
- package/dist/mcp/tool_meta.js +100 -0
- package/dist/mcp/tools/instruction_get.d.ts +32 -0
- package/dist/mcp/tools/instruction_get.js +39 -0
- package/dist/mcp/tools/instruction_list.d.ts +67 -0
- package/dist/mcp/tools/instruction_list.js +52 -0
- package/dist/mcp/tools/instruction_search.d.ts +28 -0
- package/dist/mcp/tools/instruction_search.js +33 -0
- package/dist/mcp/tools/proposal_list.d.ts +51 -0
- package/dist/mcp/tools/proposal_list.js +44 -0
- package/dist/mcp/tools/section_get.d.ts +29 -0
- package/dist/mcp/tools/section_get.js +32 -0
- package/dist/mcp/tools/section_list.d.ts +49 -0
- package/dist/mcp/tools/section_list.js +56 -0
- package/dist/mcp/tools/spec_search.d.ts +35 -0
- package/dist/mcp/tools/spec_search.js +34 -0
- package/dist/mcp/tools/spec_version.d.ts +28 -0
- package/dist/mcp/tools/spec_version.js +30 -0
- package/dist/mcp/tools/type_get.d.ts +22 -0
- package/dist/mcp/tools/type_get.js +31 -0
- package/dist/parser/bikeshed.d.ts +8 -0
- package/dist/parser/bikeshed.js +106 -0
- package/dist/parser/instructions.d.ts +171 -0
- package/dist/parser/instructions.js +241 -0
- package/dist/parser/proposals.d.ts +30 -0
- package/dist/parser/proposals.js +188 -0
- package/dist/parser/sections.d.ts +27 -0
- package/dist/parser/sections.js +213 -0
- package/dist/parser/types.d.ts +37 -0
- package/dist/parser/types.js +116 -0
- package/dist/parser/upstream.d.ts +7 -0
- package/dist/parser/upstream.js +230 -0
- package/dist/paths.d.ts +3 -0
- package/dist/paths.js +12 -0
- package/dist/spec/catalog.d.ts +10 -0
- package/dist/spec/catalog.js +20 -0
- package/dist/spec/instructions_query.d.ts +46 -0
- package/dist/spec/instructions_query.js +120 -0
- package/dist/spec/pin.d.ts +13 -0
- package/dist/spec/pin.js +39 -0
- package/dist/spec/proposals_query.d.ts +15 -0
- package/dist/spec/proposals_query.js +23 -0
- package/dist/spec/sections_query.d.ts +43 -0
- package/dist/spec/sections_query.js +89 -0
- package/dist/spec/spec_data.d.ts +46 -0
- package/dist/spec/spec_data.js +92 -0
- package/dist/spec/tool_inventory.d.ts +5 -0
- package/dist/spec/tool_inventory.js +17 -0
- package/dist/versions.d.ts +12 -0
- package/dist/versions.js +22 -0
- package/package.json +76 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Which WebAssembly specification to query. `core` (default) is the
|
|
4
|
+
* instruction set / validation / execution / formats; `js-api` and
|
|
5
|
+
* `web-api` are the JavaScript + Web embedding specs. Only the
|
|
6
|
+
* section/search tools are spec-aware — instruction and type tools are
|
|
7
|
+
* `core`-only.
|
|
8
|
+
*/
|
|
9
|
+
export declare const specArg: z.ZodDefault<z.ZodEnum<{
|
|
10
|
+
core: "core";
|
|
11
|
+
"js-api": "js-api";
|
|
12
|
+
"web-api": "web-api";
|
|
13
|
+
}>>;
|
|
14
|
+
/**
|
|
15
|
+
* The spec version selector. `latest` (default) resolves to the
|
|
16
|
+
* current served version; `main` is the working draft. More release
|
|
17
|
+
* labels (e.g. `3.0`) can be added without changing tool code.
|
|
18
|
+
*/
|
|
19
|
+
export declare const versionArg: z.ZodDefault<z.ZodEnum<{
|
|
20
|
+
main: "main";
|
|
21
|
+
latest: "latest";
|
|
22
|
+
}>>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Shared Zod argument fragments reused across tool input schemas, so
|
|
2
|
+
// every tool describes the `version` selector identically.
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { VERSION_VALUES } from "../versions.js";
|
|
5
|
+
import { SPEC_NAMES } from "../spec/catalog.js";
|
|
6
|
+
/**
|
|
7
|
+
* Which WebAssembly specification to query. `core` (default) is the
|
|
8
|
+
* instruction set / validation / execution / formats; `js-api` and
|
|
9
|
+
* `web-api` are the JavaScript + Web embedding specs. Only the
|
|
10
|
+
* section/search tools are spec-aware — instruction and type tools are
|
|
11
|
+
* `core`-only.
|
|
12
|
+
*/
|
|
13
|
+
export const specArg = z
|
|
14
|
+
.enum(SPEC_NAMES)
|
|
15
|
+
.default("core")
|
|
16
|
+
.describe("Which WebAssembly spec to query: `core` (default; instructions, types, validation, execution, formats), `js-api` (JavaScript embedding), or `web-api` (Web platform integration).");
|
|
17
|
+
/**
|
|
18
|
+
* The spec version selector. `latest` (default) resolves to the
|
|
19
|
+
* current served version; `main` is the working draft. More release
|
|
20
|
+
* labels (e.g. `3.0`) can be added without changing tool code.
|
|
21
|
+
*/
|
|
22
|
+
export const versionArg = z
|
|
23
|
+
.enum(VERSION_VALUES)
|
|
24
|
+
.default("latest")
|
|
25
|
+
.describe("WebAssembly spec version to query. `latest` (default) is the current served version; `main` is the upstream working draft.");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SERVER_INSTRUCTIONS: string;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Server-level instructions surfaced to MCP clients during the
|
|
2
|
+
// initialize handshake. Clients that forward `instructions` into the
|
|
3
|
+
// LLM's system prompt give the agent this guidance automatically.
|
|
4
|
+
//
|
|
5
|
+
// Keep it focused on workflows and invariants; per-tool detail lives
|
|
6
|
+
// in each tool's `description`.
|
|
7
|
+
import { HOSTED_TOOLS, STDIO_ONLY_TOOLS, TOTAL_TOOL_COUNT } from "../spec/tool_inventory.js";
|
|
8
|
+
export const SERVER_INSTRUCTIONS = `
|
|
9
|
+
wasm-mcp serves read-only structured data from the WebAssembly core
|
|
10
|
+
specification (https://github.com/WebAssembly/spec). Every response
|
|
11
|
+
is deterministic over data pinned to a specific upstream commit and
|
|
12
|
+
baked into the package at build time.
|
|
13
|
+
|
|
14
|
+
Unofficial, community-maintained — not affiliated with, endorsed by,
|
|
15
|
+
or sponsored by the W3C WebAssembly Community Group or Working Group.
|
|
16
|
+
|
|
17
|
+
Common workflow:
|
|
18
|
+
1. \`spec_version\` — call first when you need to cite the spec or
|
|
19
|
+
report what you're reading. Returns the pinned upstream commit.
|
|
20
|
+
2. \`instruction_search\` — find an instruction from a partial name
|
|
21
|
+
or symptom ("extend", "trunc", "0x6a") when you don't know the
|
|
22
|
+
exact mnemonic. Returns ranked lightweight hits.
|
|
23
|
+
3. \`instruction_get { mnemonic }\` or \`{ opcode }\` — the full
|
|
24
|
+
record for one instruction: opcode bytes, category, stack type
|
|
25
|
+
signature, and validation/execution prose anchors + URLs.
|
|
26
|
+
4. \`instruction_list { category? }\` — enumerate instructions,
|
|
27
|
+
filterable by category, introducing version, or mnemonic prefix.
|
|
28
|
+
5. \`type_get { name }\` — a value type or type form ('i32',
|
|
29
|
+
'funcref', 'functype', 'limits') with its defining clause prose.
|
|
30
|
+
6. \`spec_search { query }\` — full-text search across clause
|
|
31
|
+
anchors, titles, and prose when you don't know the anchor.
|
|
32
|
+
7. \`section_get { id, spec? }\` — one spec clause by anchor (e.g.
|
|
33
|
+
'syntax-numtype', 'valid-unreachable'): prose, cross-refs,
|
|
34
|
+
SpecTec formal-rule references, and the rendered URL.
|
|
35
|
+
8. \`section_list { spec?, path? }\` — navigate the clause tree,
|
|
36
|
+
scoped to an area ('syntax', 'valid', 'exec', 'binary', 'text',
|
|
37
|
+
'appendix').
|
|
38
|
+
|
|
39
|
+
The section tools (section_get / section_list / spec_search) cover
|
|
40
|
+
three specs via a 'spec' argument: 'core' (default — the instruction
|
|
41
|
+
set, validation, execution, binary + text formats), 'js-api' (the
|
|
42
|
+
JavaScript embedding API), and 'web-api' (Web-platform integration).
|
|
43
|
+
The instruction and type tools are 'core'-only.
|
|
44
|
+
9. \`proposal_list { status? }\` — WebAssembly proposals and their
|
|
45
|
+
phases, from the pinned WebAssembly/proposals repo.
|
|
46
|
+
|
|
47
|
+
Note on formal notation. Since 2025 the spec is authored in SpecTec;
|
|
48
|
+
validation / execution clauses are generated from formal rules. This
|
|
49
|
+
server keeps the hand-written prose and records each clause's SpecTec
|
|
50
|
+
rule names in 'formal_refs', with 'url' linking the rendered
|
|
51
|
+
notation. It does not itself render the formal grammar / reduction
|
|
52
|
+
rules — follow the URL for those.
|
|
53
|
+
|
|
54
|
+
The tool surface is intentionally narrow:
|
|
55
|
+
- Read-only. No tool mutates state or writes to disk / the network.
|
|
56
|
+
- Deterministic. Same input → same output, over the pinned commit.
|
|
57
|
+
- No execution. Tools never compile, validate-by-running,
|
|
58
|
+
instantiate, or run any WebAssembly or arbitrary code. Validation
|
|
59
|
+
and reduction rules are returned as data (the prose / typing
|
|
60
|
+
judgement), not by applying them.
|
|
61
|
+
|
|
62
|
+
Transport differences:
|
|
63
|
+
- The stdio server (npx wasm-mcp) exposes all ${TOTAL_TOOL_COUNT} tools.
|
|
64
|
+
- The hosted Cloudflare Worker exposes ${HOSTED_TOOLS.length} of them.
|
|
65
|
+
- Tools that need a subprocess or filesystem (${STDIO_ONLY_TOOLS.length} today)
|
|
66
|
+
are stdio-only.
|
|
67
|
+
`.trim();
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// wasm-mcp — Model Context Protocol server for the WebAssembly core
|
|
3
|
+
// specification.
|
|
4
|
+
//
|
|
5
|
+
// Read-only, SHA-pinned, structured lookup. Runs as a stdio MCP
|
|
6
|
+
// server (for local Claude Code use). A hosted Cloudflare Worker
|
|
7
|
+
// deployment will reuse the same tool implementations behind a
|
|
8
|
+
// streamable-HTTP transport (see `worker/`).
|
|
9
|
+
//
|
|
10
|
+
// Every tool is registered from the shared TOOLS registry in
|
|
11
|
+
// ./tool_meta.ts — the same array the docs generator reads, so the
|
|
12
|
+
// server and its documentation can't drift.
|
|
13
|
+
//
|
|
14
|
+
// Wire into Claude Code by adding to your project's `.mcp.json`:
|
|
15
|
+
//
|
|
16
|
+
// {
|
|
17
|
+
// "mcpServers": {
|
|
18
|
+
// "wasm": {
|
|
19
|
+
// "type": "stdio",
|
|
20
|
+
// "command": "npx",
|
|
21
|
+
// "args": ["wasm-mcp"]
|
|
22
|
+
// }
|
|
23
|
+
// }
|
|
24
|
+
// }
|
|
25
|
+
import { readFileSync } from "node:fs";
|
|
26
|
+
import { createRequire } from "node:module";
|
|
27
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
28
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
29
|
+
import { SERVER_INSTRUCTIONS } from "./instructions.js";
|
|
30
|
+
import { TOOLS, setPackageInfo } from "./tool_meta.js";
|
|
31
|
+
function readPackageInfo() {
|
|
32
|
+
try {
|
|
33
|
+
const req = createRequire(import.meta.url);
|
|
34
|
+
const path = req.resolve("../../package.json");
|
|
35
|
+
const pkg = JSON.parse(readFileSync(path, "utf8"));
|
|
36
|
+
return { name: pkg.name ?? "wasm-mcp", version: pkg.version ?? "unknown" };
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return { name: "wasm-mcp", version: "unknown" };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const PACKAGE = readPackageInfo();
|
|
43
|
+
setPackageInfo(PACKAGE);
|
|
44
|
+
const server = new McpServer({ name: PACKAGE.name, version: PACKAGE.version }, { instructions: SERVER_INSTRUCTIONS });
|
|
45
|
+
for (const tool of TOOLS) {
|
|
46
|
+
server.registerTool(tool.name, {
|
|
47
|
+
title: tool.title,
|
|
48
|
+
description: tool.description,
|
|
49
|
+
inputSchema: tool.inputSchema,
|
|
50
|
+
annotations: { readOnlyHint: true },
|
|
51
|
+
}, async (args) => {
|
|
52
|
+
const result = tool.handler(args ?? {});
|
|
53
|
+
if (result === null || result === undefined) {
|
|
54
|
+
return {
|
|
55
|
+
content: [{ type: "text", text: `No result for ${tool.name}. Try a search tool.` }],
|
|
56
|
+
isError: true,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const transport = new StdioServerTransport();
|
|
63
|
+
await server.connect(transport);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ZodRawShape } from "zod";
|
|
2
|
+
/** One usage example shown in the docs tool reference. */
|
|
3
|
+
export interface ToolExample {
|
|
4
|
+
/** Plain-language question this call answers. */
|
|
5
|
+
q: string;
|
|
6
|
+
/** The `arguments` object passed to the tool. */
|
|
7
|
+
input: Record<string, unknown>;
|
|
8
|
+
/** Optional note on what the result looks like / why. */
|
|
9
|
+
note?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A tool's complete public definition. `handler` returns either the
|
|
13
|
+
* result payload (serialised as JSON text) or null. Returning null
|
|
14
|
+
* is rendered as an isError response by the server.
|
|
15
|
+
*/
|
|
16
|
+
export interface ToolMeta {
|
|
17
|
+
name: string;
|
|
18
|
+
title: string;
|
|
19
|
+
description: string;
|
|
20
|
+
inputSchema: ZodRawShape;
|
|
21
|
+
examples: ToolExample[];
|
|
22
|
+
handler: (args: Record<string, unknown>) => unknown;
|
|
23
|
+
}
|
|
24
|
+
export declare const TOOLS: ToolMeta[];
|
|
25
|
+
export declare let PACKAGE_INFO: {
|
|
26
|
+
name: string;
|
|
27
|
+
version: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function setPackageInfo(info: {
|
|
30
|
+
name: string;
|
|
31
|
+
version: string;
|
|
32
|
+
}): void;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Single source of truth for the tool surface: name, title,
|
|
2
|
+
// description, Zod input schema, handler, and usage examples for
|
|
3
|
+
// every tool. Both the stdio server (src/mcp/server.ts) and the docs
|
|
4
|
+
// generator (src/docs/build_docs.ts) consume this array, so a tool's
|
|
5
|
+
// description and examples live in exactly one place and can't drift
|
|
6
|
+
// between the running server and its documentation.
|
|
7
|
+
import { specVersion, specVersionSchema } from "./tools/spec_version.js";
|
|
8
|
+
import { instructionGet, instructionGetSchema, instructionGetExamples, } from "./tools/instruction_get.js";
|
|
9
|
+
import { instructionList, instructionListSchema, instructionListExamples, } from "./tools/instruction_list.js";
|
|
10
|
+
import { instructionSearch, instructionSearchSchema, instructionSearchExamples, } from "./tools/instruction_search.js";
|
|
11
|
+
import { typeGet, typeGetSchema, typeGetExamples } from "./tools/type_get.js";
|
|
12
|
+
import { sectionGet, sectionGetSchema, sectionGetExamples } from "./tools/section_get.js";
|
|
13
|
+
import { sectionList, sectionListSchema, sectionListExamples } from "./tools/section_list.js";
|
|
14
|
+
import { specSearch, specSearchSchema, specSearchExamples } from "./tools/spec_search.js";
|
|
15
|
+
import { proposalList, proposalListSchema, proposalListExamples } from "./tools/proposal_list.js";
|
|
16
|
+
export const TOOLS = [
|
|
17
|
+
{
|
|
18
|
+
name: "spec_version",
|
|
19
|
+
title: "Pinned spec version",
|
|
20
|
+
description: "Return self-description of this MCP server: package name + version, plus the pinned upstream commit SHA for every spec snapshot baked into the package. Use this first when citing the spec, or to verify the server's freshness and reproducibility.",
|
|
21
|
+
inputSchema: specVersionSchema,
|
|
22
|
+
examples: [],
|
|
23
|
+
handler: () => specVersion(PACKAGE_INFO),
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "instruction_get",
|
|
27
|
+
title: "Get instruction",
|
|
28
|
+
description: "Fetch one WebAssembly instruction by mnemonic (`i32.add`, `br_if`) or binary opcode (`0x6a`, `0xfd 0x89 0x02`) as structured JSON: opcode bytes, category, introducing version, stack type signature, and validation/execution prose anchors + spec URLs. Provide `mnemonic` or `opcode` (mnemonic wins if both match).",
|
|
29
|
+
inputSchema: instructionGetSchema,
|
|
30
|
+
examples: instructionGetExamples,
|
|
31
|
+
handler: (a) => instructionGet(a),
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "instruction_list",
|
|
35
|
+
title: "List instructions",
|
|
36
|
+
description: "Enumerate WebAssembly instructions with optional filters: `category` (control, numeric, parametric, variable, table, memory, ref, i31, struct, array, extern, vec), `introduced_in` (1.0 | 2.0 | 3.0), and `prefix` (mnemonic prefix like `i32.`). Returns lightweight rows sorted by opcode; follow up with instruction_get for full detail.",
|
|
37
|
+
inputSchema: instructionListSchema,
|
|
38
|
+
examples: instructionListExamples,
|
|
39
|
+
handler: (a) => instructionList(a),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "instruction_search",
|
|
43
|
+
title: "Search instructions",
|
|
44
|
+
description: "Search WebAssembly instructions by free-text query, matched against mnemonic (exact > substring), category name, and opcode hex. The entry point when you don't know the exact mnemonic. Returns ranked lightweight hits with a `matched_on` field; follow up with instruction_get.",
|
|
45
|
+
inputSchema: instructionSearchSchema,
|
|
46
|
+
examples: instructionSearchExamples,
|
|
47
|
+
handler: (a) => instructionSearch(a),
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "type_get",
|
|
51
|
+
title: "Get type",
|
|
52
|
+
description: "Look up a WebAssembly type or type form by name: concrete value types (`i32`, `i64`, `f32`, `f64`, `v128`, `funcref`, `externref`, …) or type forms (`functype`, `limits`, `memtype`, `tabletype`, `globaltype`, `reftype`, `valtype`, `rectype`, `heaptype`, …). Returns its classification, sibling members for category types, defining clause prose, SpecTec formal-rule references, and the rendered spec URL.",
|
|
53
|
+
inputSchema: typeGetSchema,
|
|
54
|
+
examples: typeGetExamples,
|
|
55
|
+
handler: (a) => typeGet(a),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "section_get",
|
|
59
|
+
title: "Get spec section",
|
|
60
|
+
description: "Fetch one spec clause by id or anchor, across `core` / `js-api` / `web-api` (set `spec`). For core: `syntax-numtype`, `valid-unreachable`, `binary-instr`, … For the embedding specs: `modules`, `memories`, `streaming-modules`, … Matches the rendered spec's stable fragment ids. Returns the clause title, cleaned prose, cross-references, the SpecTec `formal_refs` it cites (core), and the rendered URL. Core validation/execution clauses are SpecTec-generated: prose may be terse, but formal_refs + url point to the formal rule.",
|
|
61
|
+
inputSchema: sectionGetSchema,
|
|
62
|
+
examples: sectionGetExamples,
|
|
63
|
+
handler: (a) => sectionGet(a),
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "section_list",
|
|
67
|
+
title: "List spec sections",
|
|
68
|
+
description: "Enumerate spec clauses for navigation, across `core` / `js-api` / `web-api` (set `spec`). Filter by source `path` (core: `intro`, `syntax`, `valid`, `exec`, `binary`, `text`, `appendix`, or sub-paths like `syntax/types`), `anchor_prefix`, `titled_only`, and `max_level`. Returns lightweight rows {id, anchors, title, level, path, url}; follow up with section_get.",
|
|
69
|
+
inputSchema: sectionListSchema,
|
|
70
|
+
examples: sectionListExamples,
|
|
71
|
+
handler: (a) => sectionList(a),
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: "spec_search",
|
|
75
|
+
title: "Search spec",
|
|
76
|
+
description: "Full-text search across the section index of a spec (`core` / `js-api` / `web-api`, set `spec`) — clause anchors/ids, titles, and prose. The entry point when you don't know the exact anchor. Returns ranked hits with a `matched_on` field (anchor-exact > title > anchor > prose) and a prose snippet for body matches; follow up with section_get.",
|
|
77
|
+
inputSchema: specSearchSchema,
|
|
78
|
+
examples: specSearchExamples,
|
|
79
|
+
handler: (a) => specSearch(a),
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "proposal_list",
|
|
83
|
+
title: "List WebAssembly proposals",
|
|
84
|
+
description: "List WebAssembly proposals and their phases from the pinned WebAssembly/proposals repository. Filter by `status` (phase-0…phase-5, finished, inactive), `phase` (0–5), `champion` substring, `affects` (finished proposals touching core / js-api / web-api), or `contains` (name/champion substring). Each row carries name, status, phase, champion, affected_specs, spec_version, and the proposal URL.",
|
|
85
|
+
inputSchema: proposalListSchema,
|
|
86
|
+
examples: proposalListExamples,
|
|
87
|
+
handler: (a) => proposalList(a),
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
// The server injects the real package info before registering tools;
|
|
91
|
+
// the docs generator never calls the spec_version handler, so a
|
|
92
|
+
// placeholder is fine there. Kept module-scoped so the TOOLS array
|
|
93
|
+
// stays a plain literal.
|
|
94
|
+
export let PACKAGE_INFO = {
|
|
95
|
+
name: "wasm-mcp",
|
|
96
|
+
version: "0.0.0",
|
|
97
|
+
};
|
|
98
|
+
export function setPackageInfo(info) {
|
|
99
|
+
PACKAGE_INFO = info;
|
|
100
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { InstructionRecord } from "../../parser/instructions.js";
|
|
3
|
+
import type { VersionValue } from "../../versions.js";
|
|
4
|
+
export declare const instructionGetSchema: {
|
|
5
|
+
mnemonic: z.ZodOptional<z.ZodString>;
|
|
6
|
+
opcode: z.ZodOptional<z.ZodString>;
|
|
7
|
+
version: z.ZodDefault<z.ZodEnum<{
|
|
8
|
+
main: "main";
|
|
9
|
+
latest: "latest";
|
|
10
|
+
}>>;
|
|
11
|
+
};
|
|
12
|
+
export type InstructionGetArgs = {
|
|
13
|
+
mnemonic?: string;
|
|
14
|
+
opcode?: string;
|
|
15
|
+
version?: VersionValue;
|
|
16
|
+
};
|
|
17
|
+
export declare const instructionGetExamples: ({
|
|
18
|
+
q: string;
|
|
19
|
+
input: {
|
|
20
|
+
mnemonic: string;
|
|
21
|
+
opcode?: undefined;
|
|
22
|
+
};
|
|
23
|
+
note: string;
|
|
24
|
+
} | {
|
|
25
|
+
q: string;
|
|
26
|
+
input: {
|
|
27
|
+
opcode: string;
|
|
28
|
+
mnemonic?: undefined;
|
|
29
|
+
};
|
|
30
|
+
note: string;
|
|
31
|
+
})[];
|
|
32
|
+
export declare function instructionGet(args: InstructionGetArgs): InstructionRecord | null;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// MCP tool: instruction_get — fetch one WebAssembly instruction by
|
|
2
|
+
// mnemonic (`i32.add`) or binary opcode (`0x6a`). Returns the full
|
|
3
|
+
// structured record: opcode bytes, category, version, stack type
|
|
4
|
+
// signature, and validation/execution prose anchors + URLs.
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { versionArg } from "../_args.js";
|
|
7
|
+
import { loadInstructions } from "../../spec/spec_data.js";
|
|
8
|
+
import { getInstruction } from "../../spec/instructions_query.js";
|
|
9
|
+
export const instructionGetSchema = {
|
|
10
|
+
mnemonic: z
|
|
11
|
+
.string()
|
|
12
|
+
.min(1)
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Instruction mnemonic, e.g. `i32.add`, `br_if`, `local.get`. Case-insensitive. Exact match."),
|
|
15
|
+
opcode: z
|
|
16
|
+
.string()
|
|
17
|
+
.min(1)
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Binary opcode as hex bytes, e.g. `0x6a`, `6a`, or multi-byte `0xfd 0x89 0x02`. Exact match. Used when `mnemonic` is absent or doesn't match."),
|
|
20
|
+
version: versionArg,
|
|
21
|
+
};
|
|
22
|
+
export const instructionGetExamples = [
|
|
23
|
+
{
|
|
24
|
+
q: "Get the i32.add instruction",
|
|
25
|
+
input: { mnemonic: "i32.add" },
|
|
26
|
+
note: "Returns opcode 0x6a, the [i32 i32] → [i32] signature, and validation/execution anchors.",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
q: "What instruction is opcode 0x0d?",
|
|
30
|
+
input: { opcode: "0x0d" },
|
|
31
|
+
note: "Reverse lookup by binary opcode — resolves to br_if.",
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
export function instructionGet(args) {
|
|
35
|
+
if (args.mnemonic === undefined && args.opcode === undefined)
|
|
36
|
+
return null;
|
|
37
|
+
const records = loadInstructions(args.version);
|
|
38
|
+
return getInstruction(records, { mnemonic: args.mnemonic, opcode: args.opcode });
|
|
39
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type InstructionSummary } from "../../spec/instructions_query.js";
|
|
3
|
+
import type { InstructionCategory } from "../../parser/instructions.js";
|
|
4
|
+
import { WASM_VERSIONS } from "../../parser/instructions.js";
|
|
5
|
+
import type { VersionValue } from "../../versions.js";
|
|
6
|
+
export declare const instructionListSchema: {
|
|
7
|
+
category: z.ZodOptional<z.ZodEnum<{
|
|
8
|
+
control: "control";
|
|
9
|
+
numeric: "numeric";
|
|
10
|
+
parametric: "parametric";
|
|
11
|
+
variable: "variable";
|
|
12
|
+
table: "table";
|
|
13
|
+
memory: "memory";
|
|
14
|
+
ref: "ref";
|
|
15
|
+
i31: "i31";
|
|
16
|
+
struct: "struct";
|
|
17
|
+
array: "array";
|
|
18
|
+
extern: "extern";
|
|
19
|
+
vec: "vec";
|
|
20
|
+
}>>;
|
|
21
|
+
introduced_in: z.ZodOptional<z.ZodEnum<{
|
|
22
|
+
"1.0": "1.0";
|
|
23
|
+
"2.0": "2.0";
|
|
24
|
+
"3.0": "3.0";
|
|
25
|
+
}>>;
|
|
26
|
+
prefix: z.ZodOptional<z.ZodString>;
|
|
27
|
+
version: z.ZodDefault<z.ZodEnum<{
|
|
28
|
+
main: "main";
|
|
29
|
+
latest: "latest";
|
|
30
|
+
}>>;
|
|
31
|
+
};
|
|
32
|
+
export type InstructionListArgs = {
|
|
33
|
+
category?: InstructionCategory;
|
|
34
|
+
introduced_in?: (typeof WASM_VERSIONS)[number];
|
|
35
|
+
prefix?: string;
|
|
36
|
+
version?: VersionValue;
|
|
37
|
+
};
|
|
38
|
+
export declare const instructionListExamples: ({
|
|
39
|
+
q: string;
|
|
40
|
+
input: {
|
|
41
|
+
category: string;
|
|
42
|
+
introduced_in?: undefined;
|
|
43
|
+
prefix?: undefined;
|
|
44
|
+
};
|
|
45
|
+
note: string;
|
|
46
|
+
} | {
|
|
47
|
+
q: string;
|
|
48
|
+
input: {
|
|
49
|
+
category: string;
|
|
50
|
+
introduced_in: string;
|
|
51
|
+
prefix?: undefined;
|
|
52
|
+
};
|
|
53
|
+
note: string;
|
|
54
|
+
} | {
|
|
55
|
+
q: string;
|
|
56
|
+
input: {
|
|
57
|
+
prefix: string;
|
|
58
|
+
category?: undefined;
|
|
59
|
+
introduced_in?: undefined;
|
|
60
|
+
};
|
|
61
|
+
note: string;
|
|
62
|
+
})[];
|
|
63
|
+
export interface InstructionListResult {
|
|
64
|
+
count: number;
|
|
65
|
+
instructions: InstructionSummary[];
|
|
66
|
+
}
|
|
67
|
+
export declare function instructionList(args: InstructionListArgs): InstructionListResult;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// MCP tool: instruction_list — enumerate WebAssembly instructions,
|
|
2
|
+
// optionally filtered by category, version, or mnemonic prefix.
|
|
3
|
+
// Returns lightweight rows (mnemonic, opcode bytes, category,
|
|
4
|
+
// version); follow up with instruction_get for the full record.
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { versionArg } from "../_args.js";
|
|
7
|
+
import { loadInstructions } from "../../spec/spec_data.js";
|
|
8
|
+
import { listInstructions } from "../../spec/instructions_query.js";
|
|
9
|
+
import { INSTRUCTION_CATEGORIES } from "../../parser/instructions.js";
|
|
10
|
+
import { WASM_VERSIONS } from "../../parser/instructions.js";
|
|
11
|
+
export const instructionListSchema = {
|
|
12
|
+
category: z
|
|
13
|
+
.enum(INSTRUCTION_CATEGORIES)
|
|
14
|
+
.optional()
|
|
15
|
+
.describe("Filter by instruction category: control, numeric, parametric, variable, table, memory, ref, i31, struct, array, extern, vec (vector/SIMD)."),
|
|
16
|
+
introduced_in: z
|
|
17
|
+
.enum(WASM_VERSIONS)
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Filter to instructions introduced in this WebAssembly version: `1.0`, `2.0`, or `3.0`."),
|
|
20
|
+
prefix: z
|
|
21
|
+
.string()
|
|
22
|
+
.min(1)
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("Filter to mnemonics starting with this prefix, e.g. `i32.` or `v128.`. Case-insensitive."),
|
|
25
|
+
version: versionArg,
|
|
26
|
+
};
|
|
27
|
+
export const instructionListExamples = [
|
|
28
|
+
{
|
|
29
|
+
q: "List all control-flow instructions",
|
|
30
|
+
input: { category: "control" },
|
|
31
|
+
note: "Filters to the control category; rows are sorted by opcode.",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
q: "What memory instructions did Wasm 3.0 add?",
|
|
35
|
+
input: { category: "memory", introduced_in: "3.0" },
|
|
36
|
+
note: "Combine category + introduced_in to see what a release contributed.",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
q: "List the i32 numeric instructions",
|
|
40
|
+
input: { prefix: "i32." },
|
|
41
|
+
note: "Prefix filter is the quickest way to scope to one type family.",
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
export function instructionList(args) {
|
|
45
|
+
const records = loadInstructions(args.version);
|
|
46
|
+
const instructions = listInstructions(records, {
|
|
47
|
+
category: args.category,
|
|
48
|
+
version: args.introduced_in,
|
|
49
|
+
prefix: args.prefix,
|
|
50
|
+
});
|
|
51
|
+
return { count: instructions.length, instructions };
|
|
52
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type InstructionSearchHit } from "../../spec/instructions_query.js";
|
|
3
|
+
import type { VersionValue } from "../../versions.js";
|
|
4
|
+
export declare const instructionSearchSchema: {
|
|
5
|
+
query: z.ZodString;
|
|
6
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
7
|
+
version: z.ZodDefault<z.ZodEnum<{
|
|
8
|
+
main: "main";
|
|
9
|
+
latest: "latest";
|
|
10
|
+
}>>;
|
|
11
|
+
};
|
|
12
|
+
export type InstructionSearchArgs = {
|
|
13
|
+
query: string;
|
|
14
|
+
limit?: number;
|
|
15
|
+
version?: VersionValue;
|
|
16
|
+
};
|
|
17
|
+
export declare const instructionSearchExamples: {
|
|
18
|
+
q: string;
|
|
19
|
+
input: {
|
|
20
|
+
query: string;
|
|
21
|
+
};
|
|
22
|
+
note: string;
|
|
23
|
+
}[];
|
|
24
|
+
export interface InstructionSearchResult {
|
|
25
|
+
count: number;
|
|
26
|
+
hits: InstructionSearchHit[];
|
|
27
|
+
}
|
|
28
|
+
export declare function instructionSearch(args: InstructionSearchArgs): InstructionSearchResult;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// MCP tool: instruction_search — free-text search across instruction
|
|
2
|
+
// mnemonics, categories, and opcodes. The entry point when you don't
|
|
3
|
+
// know the exact mnemonic. Returns ranked lightweight hits; follow
|
|
4
|
+
// up with instruction_get for the full record.
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { versionArg } from "../_args.js";
|
|
7
|
+
import { loadInstructions } from "../../spec/spec_data.js";
|
|
8
|
+
import { searchInstructions } from "../../spec/instructions_query.js";
|
|
9
|
+
export const instructionSearchSchema = {
|
|
10
|
+
query: z
|
|
11
|
+
.string()
|
|
12
|
+
.min(1)
|
|
13
|
+
.describe("Search text. Matched against mnemonic (exact > substring), category name, and opcode hex. E.g. `extend`, `trunc`, `vec`, `0x6a`."),
|
|
14
|
+
limit: z.number().int().min(1).max(100).default(20).describe("Max ranked hits returned."),
|
|
15
|
+
version: versionArg,
|
|
16
|
+
};
|
|
17
|
+
export const instructionSearchExamples = [
|
|
18
|
+
{
|
|
19
|
+
q: "Find all the extend instructions",
|
|
20
|
+
input: { query: "extend" },
|
|
21
|
+
note: "Substring match across mnemonics surfaces i32.extend8_s, i64.extend_i32_u, etc.",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
q: "Which instruction has opcode 0x6a?",
|
|
25
|
+
input: { query: "0x6a" },
|
|
26
|
+
note: "A hex query also matches by opcode — resolves i32.add at the top.",
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
export function instructionSearch(args) {
|
|
30
|
+
const records = loadInstructions(args.version);
|
|
31
|
+
const hits = searchInstructions(records, args.query, args.limit ?? 20);
|
|
32
|
+
return { count: hits.length, hits };
|
|
33
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { PROPOSAL_STATUSES, type Proposal } from "../../parser/proposals.js";
|
|
3
|
+
export declare const proposalListSchema: {
|
|
4
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
5
|
+
"phase-0": "phase-0";
|
|
6
|
+
"phase-1": "phase-1";
|
|
7
|
+
"phase-2": "phase-2";
|
|
8
|
+
"phase-3": "phase-3";
|
|
9
|
+
"phase-4": "phase-4";
|
|
10
|
+
"phase-5": "phase-5";
|
|
11
|
+
finished: "finished";
|
|
12
|
+
inactive: "inactive";
|
|
13
|
+
}>>;
|
|
14
|
+
phase: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
champion: z.ZodOptional<z.ZodString>;
|
|
16
|
+
affects: z.ZodOptional<z.ZodString>;
|
|
17
|
+
contains: z.ZodOptional<z.ZodString>;
|
|
18
|
+
};
|
|
19
|
+
export type ProposalListArgs = {
|
|
20
|
+
status?: (typeof PROPOSAL_STATUSES)[number];
|
|
21
|
+
phase?: number;
|
|
22
|
+
champion?: string;
|
|
23
|
+
affects?: string;
|
|
24
|
+
contains?: string;
|
|
25
|
+
};
|
|
26
|
+
export declare const proposalListExamples: ({
|
|
27
|
+
q: string;
|
|
28
|
+
input: {
|
|
29
|
+
status: string;
|
|
30
|
+
affects: string;
|
|
31
|
+
phase?: undefined;
|
|
32
|
+
};
|
|
33
|
+
note: string;
|
|
34
|
+
} | {
|
|
35
|
+
q: string;
|
|
36
|
+
input: {
|
|
37
|
+
phase: number;
|
|
38
|
+
status?: undefined;
|
|
39
|
+
affects?: undefined;
|
|
40
|
+
};
|
|
41
|
+
note: string;
|
|
42
|
+
})[];
|
|
43
|
+
export interface ProposalListResult {
|
|
44
|
+
/** Pinned WebAssembly/proposals commit the list was indexed from. */
|
|
45
|
+
pin: {
|
|
46
|
+
sha: string;
|
|
47
|
+
};
|
|
48
|
+
count: number;
|
|
49
|
+
proposals: Proposal[];
|
|
50
|
+
}
|
|
51
|
+
export declare function proposalList(args: ProposalListArgs): ProposalListResult;
|