mcp-parser

mcp-parser

Static spec format and toolkit for MCP servers. Snapshot any running server, validate the result, and generate docs from a single artifact.

An MCP server describes itself at runtime: connect, call tools/list, get JSON. The protocol’s introspection model is genuinely useful, but it also means every reader has to talk to a live process to know what the server exposes. CI checks, documentation builds, offline review, and MCP clients planning against a server all depend on the server being reachable at the moment they ask.

mcp.json is the static format that closes that gap. A versioned, on-disk snapshot of the server: tools, resources, prompts, capabilities, transport hints. The same job openapi.json already does for HTTP APIs. mcp-schema defines the format. mcp-parser snapshots live servers into that format, validates the result, and renders documentation from it.

Snapshot

Point it at any of the three MCP transports and it captures the spec:

import { snapshot } from "mcp-parser";
import { writeFile } from "node:fs/promises";

const spec = await snapshot({
  transport: { type: "stdio", command: "node", args: ["server.js"] },
});

await writeFile("mcp.json", JSON.stringify(spec, null, 2));

The transport object is the only difference between stdio, SSE, and streamable HTTP. SSE and HTTP take a headers object if your server is gated. The default 30-second timeout is generous for a normal tools/list round trip but worth bumping if your server lazy-loads its tool list from a remote source the first time it’s asked.

After capture, the spec is just a file. You can diff it on a PR, ship it next to the README, hand it to someone who hasn’t installed your server, or load it from a docs build without spawning the server.

Validate

const result = validate(spec);
if (!result.valid) {
  for (const d of result.diagnostics) {
    console.error(`${d.severity}: ${d.path} - ${d.message}`);
  }
}

It catches the obvious things: required fields, duplicate tool names, an inputSchema that isn’t actually a JSON Schema object. It also catches the less obvious things; a tool with no description, for instance, gets flagged as a warning rather than an error because MCP clients can still load the server, but the resulting documentation and tool selection context are weaker.

Errors block. Warnings are advisory. Diagnostics include the JSON path of the offending field, which matters more than it sounds; real specs run hundreds of lines and a tool name on its own often isn’t unique enough to find the issue.

Generate

A parsed spec produces three rendered outputs from the same source. generateMarkdown writes a human-readable reference suited to a docs site or README, and it is the default CLI output. generateLlmsTxt writes a compact llms.txt-style index for tools that already consume that convention. generateLlmsFullTxt writes the long-form reference with every tool schema inline, useful when you explicitly hand a model or retrieval system the server context.

CLI

mcp-parser snapshot --stdio "node server.js" -o mcp.json
mcp-parser snapshot --sse http://localhost:3000/sse -o mcp.json
mcp-parser snapshot --http http://localhost:3000/mcp -o mcp.json
mcp-parser validate ./mcp.json
mcp-parser generate ./mcp.json -o mcp.md
mcp-parser generate ./mcp.json --format llms-txt -o llms.txt

--header "Authorization:Bearer ..." for gated servers. The CLI is a thin wrapper over the library, useful when a one-line command is enough.

mcp-schema

mcp-schema is the format on its own. TypeScript types if you want IDE help, a JSON Schema if you want to hand validation off to ajv or your existing validation stack. No parser, no transport code, no opinion about how you load the file.

import type { McpSpec, McpTool } from "mcp-schema";
import { mcpSpecSchema } from "mcp-schema/schema";

Worth installing on its own if you’re writing your own tooling around mcp.json and don’t need the snapshot logic.

Both packages track every released MCP protocol version: 2024-11-05, 2025-03-26, 2025-06-18, and 2025-11-25. Each spec carries an explicit mcpVersion field, so a snapshot made today still tells you exactly which wire protocol it described in two years’ time.

The types cover tools (with inputSchema, outputSchema, and annotation hints like readOnlyHint and destructiveHint), resources, resource templates, prompts, server capabilities, and the three transports.

Through Sourcey

Sourcey reads mcp.json directly:

{
  tab: "MCP Server",
  mcp: "./mcp.json",
}

Tools, resources, and prompts render as first-class reference documentation in the same site as the OpenAPI tabs and markdown guides. Annotation badges surface the read-only / destructive / idempotent hints visually so a reader can see at a glance which tools mutate state. Code samples auto-generate in JSON-RPC, TypeScript SDK, and Python SDK. Sourcey also includes the same compact and full-text context exports that mcp-parser can write on its own.

Sourcey is optional. The output is plain JSON; the same workflows that work with openapi.json can work with mcp.json.