/mcp-sdk-audit
Upgrade @modelcontextprotocol/server (the MCP TypeScript SDK v2) and prove the wire contract survived. The SDK is a runtime dependency whose breakage lands on the wire, not in the type checker — so this sorts each release by which SDK source files it touched (Figwright uses only
$ npx -y skills add awdr74100/figwright --skill mcp-sdk-audit --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/mcp-sdk-audit
Context preview
The summary Claude sees to decide when to auto-load this skill.
Upgrade @modelcontextprotocol/server (the MCP TypeScript SDK v2) and prove the wire contract survived. The SDK is a runtime dependency whose breakage lands on the wire, not in the type checker — so this sorts each release by which SDK source files it touched (Figwright uses only
SKILL.md
mcp-sdk-audit.SKILL.mdname: mcp-sdk-audit
description: 'Upgrade @modelcontextprotocol/server (the MCP TypeScript SDK v2) and prove the wire contract survived. The SDK is a runtime dependency whose breakage lands on the wire, not in the type checker — so this sorts each release by which SDK source files it touched (Figwright uses only the server + stdio slice of a client/server/multi-runtime package family), then diffs what a real MCP client observes — negotiated protocol version, every tool JSON Schema, annotations, prompts — before and after the bump. Use whenever the user wants @modelcontextprotocol/server or the other @modelcontextprotocol/* packages updated or audited, asks what a new SDK version changes for the server or its clients, or lands on a Renovate bump PR for that package.'
Absorbing a `@modelcontextprotocol/server` release into Figwright, end to end: audit → upgrade → prove the wire contract is unchanged.
**Do not reason about this the way `figma-typings-audit` reasons about plugin typings.** That package is types-only, so `tsc` is a real gate. This one is a **runtime dependency**: it serializes every tool result, generates the JSON Schema for all ~112 tools, and negotiates the protocol version. A release can leave every type identical and still change what clients see. `pnpm typecheck` will stay green through it.
**Unlike every other dependency here, this one has a dedicated gate — use it.** `packages/mcp/test/e2e/mcp-wire.test.ts` spawns the built `dist` over real stdio, speaks raw JSON-RPC at it, and asserts the advertised contract against what the specs declare. It runs in `pnpm test`. That gate answers *did anything break*; it does not answer *what moved*, which is what an audit is for — Stage 5 covers the difference.
Target version: whatever the user named, otherwise the latest `@modelcontextprotocol/server` on npm.
Stage 0 — Resolve versions
grep '@modelcontextprotocol' packages/mcp/package.json # declared range
grep -m1 '@modelcontextprotocol/server@' pnpm-lock.yaml # what is installed
npm view @modelcontextprotocol/server version dist-tags --json # latest
gh api repos/modelcontextprotocol/typescript-sdk/releases --jq '.[0:15][] | "\(.tag_name)\t\(.published_at)"'
Figwright is on **v2** — the package family (`@modelcontextprotocol/server` + its transitive `/core`, with `/client`, `/node`, `/express`, `/hono`, `/fastify`, `/server-legacy`, `/codemod` alongside). It depends on exactly one of them.
Two things the releases list will show that are **not** upgrades for us:
- Bare `1.30.0`-style tags are the **v1 legacy line** (`@modelcontextprotocol/sdk`, source on the
long-lived `v1.x` branch). Figwright left it; a v1 tag is not our concern.
- `@modelcontextprotocol/{client,express,fastify,hono,node,server-legacy,codemod}@X` tags ship on
the same version number as `server` but are packages we do not install.
If installed and target are equal, say so and stop.
Stage 1 — Read the release notes as an index, not as an answer
The GitHub Releases body is an auto-generated list of PR titles, written for SDK contributors: it says *what was changed*, never *who is affected*. "stdio buffer limit" reads like it belongs to whoever runs stdio; the useful question is which package and which directory it landed in.
So use the notes only to get the PR numbers, then ask each PR what it touched:
gh api repos/modelcontextprotocol/typescript-sdk/releases --jq '.[] | select(.tag_name=="@modelcontextprotocol/server@<target>") | .body'
# then, per PR number in that body:
gh pr view <n> --repo modelcontextprotocol/typescript-sdk --json title,files \
--jq '"\(.title)\n " + (.files | map(.path) | join("\n "))'⚠️ **Read the whole file list, never just the first entry.** v2 splits one concern across packages by design — a wire change routinely lands in `packages/core-internal/src/wire/`, `packages/server/src/server/`, and `packages/client/src/` at once. Judging a PR by its first file is how the hunk that mattered gets missed.
Stage 2 — Sort by file path
Figwright imports exactly two entry points (`packages/mcp/src/index.ts`, `src/prompts/*`, `test/tool-schema.ts`, `test/e2e/mcp-wire.test.ts`): `@modelcontextprotocol/server` and `@modelcontextprotocol/server/stdio`. That narrow slice is what makes this audit cheap — most of any given release is about parts of the family this server never loads.
| SDK path | Bearing on Figwright | | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | | `packages/server/src/server/mcp.ts`, `server.ts` | **Load-bearing.** `registerTool` / `registerPrompt` / result serialization | | `packages/server/src/server/serveStdio.ts`, `stdio.ts` | **Load-bearing.** The entry point and the only transport this server runs | | `packages/server/src/fromJsonSchema.ts`, `validators/` | **Load-bearing and invisible.** Turns each spec's Zod object into the JSON Schema every client reads | | `packages/core-internal/src/wire/`, `types/` | **Load-bearing.** Protocol version constants, per-era codecs, `CallToolResult`, `ToolAnnotations` | | `packages/core/src/` | Schema constants + types. We import types only through `server`'s re-export; watch renames | | `packages/client/**` | Not ours — but it is what Claude Code / Cursor run *against* us, so a client-side limit still bites | | `packages/server/src/server/streamableHttp.ts`, `perRequestTransport.ts`, `createMcpHandler.ts` | Unused today (stdio only). Relevant only to a future HTTP transport — note, don't act |
Read more
name: mcp-sdk-audit description: 'Upgrade @modelcontextprotocol/server (the MCP TypeScript SDK v2) and prove the wire contract survived. The SDK is a runtime dependency whose breakage lands on the wire, not in the type checker — so this sorts each release by which SDK source files it touched (Figwright uses only the server + stdio slice of a client/server/multi-runtime package family), then diffs what a real MCP client observes — negotiated protocol version, every tool JSON Schema, annotations, prompts — before and after the bump. Use whenever the user wants @modelcontextprotocol/server or the other @modelcontextprotocol/* packages updated or audited, asks what a new SDK version changes for the server or its clients, or lands on a Renovate bump PR for that package.'
Absorbing a `@modelcontextprotocol/server` release into Figwright, end to end: audit → upgrade → prove the wire contract is unchanged.
**Do not reason about this the way `figma-typings-audit` reasons about plugin typings.** That package is types-only, so `tsc` is a real gate. This one is a **runtime dependency**: it serializes every tool result, generates the JSON Schema for all ~112 tools, and negotiates the protocol version. A release can leave every type identical and still change what clients see. `pnpm typecheck` will stay green through it.
**Unlike every other dependency here, this one has a dedicated gate — use it.** `packages/mcp/test/e2e/mcp-wire.test.ts` spawns the built `dist` over real stdio, speaks raw JSON-RPC at it, and asserts the advertised contract against what the specs declare. It runs in `pnpm test`. That gate answers *did anything break*; it does not answer *what moved*, which is what an audit is for — Stage 5 covers the difference.
Target version: whatever the user named, otherwise the latest `@modelcontextprotocol/server` on npm.
Stage 0 — Resolve versions
grep '@modelcontextprotocol' packages/mcp/package.json # declared range grep -m1 '@modelcontextprotocol/server@' pnpm-lock.yaml # what is installed npm view @modelcontextprotocol/server version dist-tags --json # latest gh api repos/modelcontextprotocol/typescript-sdk/releases --jq '.[0:15][] | "\(.tag_name)\t\(.published_at)"'
Figwright is on **v2** — the package family (`@modelcontextprotocol/server` + its transitive `/core`, with `/client`, `/node`, `/express`, `/hono`, `/fastify`, `/server-legacy`, `/codemod` alongside). It depends on exactly one of them.
Two things the releases list will show that are **not** upgrades for us:
- Bare `1.30.0`-style tags are the **v1 legacy line** (`@modelcontextprotocol/sdk`, source on the
long-lived `v1.x` branch). Figwright left it; a v1 tag is not our concern.
- `@modelcontextprotocol/{client,express,fastify,hono,node,server-legacy,codemod}@X` tags ship on
the same version number as `server` but are packages we do not install.
If installed and target are equal, say so and stop.
Stage 1 — Read the release notes as an index, not as an answer
The GitHub Releases body is an auto-generated list of PR titles, written for SDK contributors: it says *what was changed*, never *who is affected*. "stdio buffer limit" reads like it belongs to whoever runs stdio; the useful question is which package and which directory it landed in.
So use the notes only to get the PR numbers, then ask each PR what it touched:
gh api repos/modelcontextprotocol/typescript-sdk/releases --jq '.[] | select(.tag_name=="@modelcontextprotocol/server@<target>") | .body'
# then, per PR number in that body:
gh pr view <n> --repo modelcontextprotocol/typescript-sdk --json title,files \
--jq '"\(.title)\n " + (.files | map(.path) | join("\n "))'⚠️ **Read the whole file list, never just the first entry.** v2 splits one concern across packages by design — a wire change routinely lands in `packages/core-internal/src/wire/`, `packages/server/src/server/`, and `packages/client/src/` at once. Judging a PR by its first file is how the hunk that mattered gets missed.
Stage 2 — Sort by file path
Figwright imports exactly two entry points (`packages/mcp/src/index.ts`, `src/prompts/*`, `test/tool-schema.ts`, `test/e2e/mcp-wire.test.ts`): `@modelcontextprotocol/server` and `@modelcontextprotocol/server/stdio`. That narrow slice is what makes this audit cheap — most of any given release is about parts of the family this server never loads.
| SDK path | Bearing on Figwright | | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | | `packages/server/src/server/mcp.ts`, `server.ts` | **Load-bearing.** `registerTool` / `registerPrompt` / result serialization | | `packages/server/src/server/serveStdio.ts`, `stdio.ts` | **Load-bearing.** The entry point and the only transport this server runs | | `packages/server/src/fromJsonSchema.ts`, `validators/` | **Load-bearing and invisible.** Turns each spec's Zod object into the JSON Schema every client reads | | `packages/core-internal/src/wire/`, `types/` | **Load-bearing.** Protocol version constants, per-era codecs, `CallToolResult`, `ToolAnnotations` | | `packages/core/src/` | Schema constants + types. We import types only through `server`'s re-export; watch renames | | `packages/client/**` | Not ours — but it is what Claude Code / Cursor run *against* us, so a client-side limit still bites | | `packages/server/src/server/streamableHttp.ts`, `perRequestTransport.ts`, `createMcpHandler.ts` | Unused today (stdio only). Relevant only to a future HTTP transport — note, don't act |
Free, two-way Figma MCP server. Turn designs into framework-aware code, and push code back to the canvas. Works with Claude Code, Cursor, Codex, and any MCP client.
Repo: awdr74100/figwright
Other skills on figwright.
- /figma-typings-audit
Upgrade @figma/plugin-typings and absorb what the new version exposes. Diffs the .d.ts between the installed and the target version (that package ships no changelog), sorts the changes into breakage / new API / silently-added fields, maps each onto the sandbox handlers, the
Open skill - /figma-build
Build a Figma design from code or a description — the reverse of figma-codegen. Reuses the connected file's existing design system (components, variables, styles) instead of drawing primitives with hardcoded values. Triggers whenever the user wants something created or updated
Open skill - /figma-codegen
Generate framework-aware code from a Figma design. Reads the project's stack profile and emits code matching the existing framework (React/Vue/Svelte/Next/etc.) and styling (Tailwind/CSS/CSS-in-JS), reusing existing components and design tokens instead of regenerating from
Open skill

