@zvk/mcp-kit
v0.1.2
Published
Protocol-safe MCP tool and action helpers for ZVK applications.
Readme
@zvk/mcp-kit
Protocol-safe MCP action/tool helpers for ZVK applications.
import {
defineMcpAction,
defineMcpActionTool,
executeMcpActionTool
} from "@zvk/mcp-kit/actions";
import { createMcpToolHelpEntries } from "@zvk/mcp-kit/help";
import { createMcpDiscoverySchema, createMcpDiscoverySchemaFromTools } from "@zvk/mcp-kit/schemas";
import { contractErrorToMcpPayload } from "@zvk/mcp-kit/errors";This package owns protocol-safe primitives used by MCP servers:
- Action spec definitions and action-tool registration helpers.
- Structural schema helpers for action-discriminated payloads.
- MCP protocol-shaped tool results and MCP-safe error payload mapping.
- Deterministic help metadata and rendering helpers.
- Test helpers for action payloads, result assertions, and fixtures.
It is dependency-light by design. The only runtime dependency is @zvk/contracts.
executeMcpActionTool returns MCP tool result envelopes with isError,
content, and structuredContent; it does not return an ActionResult
wrapper. Action handlers still use Result<TOutput, ContractError> internally
so the protocol boundary stays separate from app action envelopes.
See ../../docs/package-boundary-matrix.md for the package-family runtime
boundary matrix. @zvk/mcp-kit stays protocol-focused and browser-safe; test
fixtures stay on the explicit @zvk/mcp-kit/test-utils subpath.
Action Input Parsing
executeMcpActionTool reads the action discriminator first and, by default,
parses only the remaining payload with the action's inputSchema:
defineMcpAction({
action: "create_project",
description: "Create a project",
inputSchema: createProjectSchema,
run: async (input, context) => {
// input does not include the action field here.
return createProject(input, context);
}
});For migrations where an existing schema already validates the original MCP
payload shape, set parseInputWithAction: true on that action:
defineMcpAction({
action: "create_project",
description: "Create a project",
inputSchema: createProjectActionSchema,
parseInputWithAction: true,
run: async (input) => {
// input includes { action: "create_project", ...payload }.
return createProject(input);
}
});Keep this opt-in action-local. Do not move app authorization, tenancy, storage,
transport sessions, or product copy into @zvk/mcp-kit.
Discovery Metadata
Action specs can expose structural metadata without depending on the MCP SDK:
defineMcpAction({
action: "search_projects",
description: "Search projects",
inputSchema: searchProjectsSchema,
inputRequiredFields: ["query"],
inputJsonSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "Search text."
}
},
required: ["query"],
additionalProperties: false
},
run: searchProjects
});createMcpDiscoverySchema uses inputJsonSchema and inputRequiredFields when
present, then adds the action discriminator to each branch. Help entries also
surface required fields and include inputSchema when an action provides JSON
schema metadata.
When you need a deterministic catalog across several action tools, use
createMcpDiscoverySchemaFromTools. It sorts by tool name, returns one
discovery schema entry per tool, and throws on duplicate tool names so adapter
code does not have to guess how to merge collisions.
Error Metadata
contractErrorToMcpPayload and unknownErrorToMcpPayload preserve the stable
code, message, and issues payload fields while optionally adding
structured kind and safe context metadata.
Keep kind and context app-owned. Use them for machine-readable classification
and non-sensitive tracing details such as tool name or action name. Do not pass
raw thrown values through context.
Migration Fixtures
@zvk/mcp-kit/test-utils includes canonical fixtures for action-wrapped input,
payload-only input, success results, validation errors, and unknown actions.
Use them when writing migration tests around parseInputWithAction so old and
new payload shapes stay explicit.
import {
createMcpActionInput,
createMcpPayloadInput,
createMcpSuccessResult,
createMcpUnknownActionResult,
createMcpValidationErrorResult
} from "@zvk/mcp-kit/test-utils";Public Imports
@zvk/mcp-kit@zvk/mcp-kit/actions@zvk/mcp-kit/schemas@zvk/mcp-kit/errors@zvk/mcp-kit/help@zvk/mcp-kit/test-utils
Package Scope
@zvk/mcp-kit stops at the protocol boundary. It can shape MCP-safe inputs and
outputs, but it does not register transports, authorize requests, or persist
application state.
| Area | @zvk/mcp-kit owns | Applications own |
| --- | --- | --- |
| Action definitions | McpActionSpec, defineMcpAction, defineMcpActionTool, action names, action-local input parsers, examples, and structural metadata. | Product action semantics, action enablement, user-facing copy, and app-specific handler composition. |
| Schemas | Action-discriminated JSON schema helpers and discovery schemas derived from action specs. | Transport registration, SDK-specific schema adapters, app route wiring, and protocol version negotiation. |
| Payloads | MCP-safe success envelopes and normalized ContractError or unknown-error payloads. | Logging, trace IDs, sensitive error redaction policy, retries, and user/session-specific response handling. |
| Help | Deterministic help entries and markdown rendering from structural action metadata. | Tool catalogs, docs placement, app-specific examples, and feature availability by deployment or user. |
| Fixtures | Test payload builders, context builders, and result guards for package and app integration tests. | Persistence fakes, service fakes, auth fixtures, seeded data, and end-to-end transport tests. |
| Runtime boundary | Dependency-light TypeScript helpers with no MCP SDK runtime dependency. | MCP SDK server/client setup, HTTP/SSE/WebSocket transport, auth, sessions, storage, persistence, and deployment configuration. |
Promptliano-Style Migration Checklist
Use this checklist when replacing app-local MCP action boilerplate without importing Promptliano or any other app code into this package:
- Inventory each app MCP tool and list its supported action names.
- Define one
McpActionSpecper action with aSchemaAdapterfor the action payload. - Keep new schemas payload-only so
executeMcpActionToolcan stripactionbefore parsing. - Set
parseInputWithAction: trueonly for existing migration schemas that intentionally validate{ action, ...payload }. - Add
inputRequiredFields,inputJsonSchema, and examples only when help or discovery needs structural metadata beyond the parser. - Replace app-local action dispatch with
executeMcpActionTool. - Replace app-local safe error shaping with
contractErrorToMcpPayloadorunknownErrorToMcpPayload. - Keep transport registration, auth, session lookup, database calls, persistence, and tool enablement in the consuming app.
- Add app integration tests around the transport boundary after the package helpers are wired in.
Verification
From the repository root:
bun run --filter @zvk/mcp-kit test
bun run --filter @zvk/mcp-kit typecheck
bun run --filter @zvk/mcp-kit validate:exportsRepository Skill
Usage guidance for maintainers and adopters is in:
.codex/skills/use-zvk-mcp-kit/SKILL.md
