@mcp-layer/schema
v1.0.4
Published
Extract and normalize MCP schemas into a unified Zod-based format.
Maintainers
Readme
@mcp-layer/schema
@mcp-layer/schema extracts MCP server definitions (tools, resources, prompts, templates, and MCP Apps metadata) and normalizes them into a unified Zod-backed schema. The output is designed for downstream generators that need a single contract to build CLIs, REST endpoints, UI renderers, or additional MCP layers without re-parsing the MCP protocol surface.
Table of Contents
- Installation
- Usage
- What this package does
- Output shape (authoritative)
- MCP Apps support
- Generator guidance
- Responsibilities and lifecycle
- Error handling
- JSON Schema vs Zod
- Runtime Error Reference
Installation
pnpm add @mcp-layer/schema
# or
npm install @mcp-layer/schema
# or
yarn add @mcp-layer/schemaUsage
import { load } from '@mcp-layer/config';
import { connect } from '@mcp-layer/connect';
import { composeCatalog, extract } from '@mcp-layer/schema';
const config = await load(undefined, process.cwd());
const session = await connect(config, 'demo');
const output = await extract(session);
console.log(output.server.info);
console.log(output.items[0]);
await session.close();
const catalog = composeCatalog({
server: {
info: { name: 'demo', version: '1.0.0' },
capabilities: { tools: {} },
instructions: 'Use the local catalog.',
},
tools: [{
name: 'echo',
description: 'Echo text.',
inputSchema: {
type: 'object',
properties: {
text: { type: 'string' },
},
required: ['text'],
},
}],
});
console.log(catalog.items[0]);What this package does
- Reads the MCP server capabilities and metadata from the live client connection with
extract(session). - Calls MCP list endpoints (
tools/list,resources/list,resources/templates/list,prompts/list) using pagination. - Composes the same normalized catalog shape from raw definitions with
composeCatalog(...)when a live session is not available yet. - Normalizes everything into a unified, type-discriminated schema so generators can consume a single list.
- Wraps tool input/output JSON Schemas into Zod validators backed by Ajv, while preserving the original JSON Schema.
- Converts prompt arguments into a lightweight JSON Schema so prompts and tools share the same
detail.inputshape.
Output shape (authoritative)
The package returns:
{
server: {
info, // initialize.serverInfo
capabilities, // initialize.capabilities
instructions // initialize.instructions (optional)
},
items: [
{
type, // "tool" | "resource" | "resource-template" | "prompt"
name,
title,
description,
meta, // icons, annotations, _meta
detail // type-specific data
}
]
}Type discriminator:
tool,resource,resource-template,prompt- MCP Apps do not introduce a new
type; tools remaintooland UI resources remainresource.
detail: tools
detail: {
input: {
schema, // Zod schema (Ajv-backed)
json, // original JSON Schema
error // optional Ajv compile error message
},
output: { schema, json, error }, // only when the tool advertises outputSchema
ui: { resourceUri, csp, permissions } // when _meta.ui is present (MCP Apps)
}detail: resources
detail: {
uri,
mimeType,
size,
ui: { resourceUri, csp, permissions } // when _meta.ui is present (MCP Apps)
}detail: resource templates
detail: {
uriTemplate,
mimeType
}detail: prompts
detail: {
input: {
schema, // Zod schema derived from prompt arguments
json, // JSON Schema derived from prompt arguments
error // optional Ajv compile error message
}
}MCP Apps support
If a server exposes MCP Apps metadata:
- Tools may include
_meta.ui.resourceUripointing to aui://resource. - UI resources may include
_meta.uiwith CSP and permissions.
This package normalizes those fields into detail.ui so generators can:
- Detect which tools expect UI rendering.
- Resolve and render the
ui://resource. - Apply CSP and permissions when hosting the UI in a webview or browser sandbox.
Generator guidance
Suggested uses for the unified schema:
- CLI: Use
name,description, anddetail.inputto build flags and help text. - REST: Use
namefor endpoints,detail.input.jsonfor request validation, anddetail.outputfor response schema. - UI: Use
detail.ui.resourceUrito locate the UI and readdetail.ui.csp/permissions.
Responsibilities and lifecycle
extract(session)does not open or close connections. It expects a liveSessionfrom@mcp-layer/connector@mcp-layer/attach.- You are responsible for calling
session.close()after extraction. composeCatalog(...)is pure and does not require a connection.- If the server doesn't advertise a capability (tools/resources/prompts), extraction skips that surface.
Error handling
- Schema compilation uses Ajv under the hood. If a tool exposes an invalid JSON Schema, extraction still succeeds but
detail.input.errorordetail.output.errorwill be populated for that item. - Servers that return empty lists produce an empty
itemsarray (not an error). - Servers that support resources but not resource templates are treated as having zero templates.
JSON Schema vs Zod
Zod validators are produced to allow direct runtime validation, but the original JSON Schema is preserved in detail.input.json and detail.output.json so generators can emit OpenAPI, JSON Schema, or other schema formats without losing fidelity.
Runtime Error Reference
This section is written for high-pressure debugging moments. Each entry maps directly to schema extraction preconditions.
Expected a Session instance.
Thrown from: extract
This happens when extract(link) is called without a connected Session object (or with an object that does not expose .client). The extractor relies on MCP client capabilities and list calls.
Step-by-step resolution:
- Verify you are passing the
Sessionreturned byconnect(...)orattach(...). - Confirm session setup completed and
session.clientis available. - Avoid passing raw MCP client objects directly; wrap flows around
Session. - Add an integration test that extracts from a real connected session.
const session = await connect(config, 'local-dev');
const catalog = await extract(session);
console.log(catalog.items.length);
await session.close();License
MIT
