npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mcp-layer/schema

v1.0.4

Published

Extract and normalize MCP schemas into a unified Zod-based format.

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

pnpm add @mcp-layer/schema
# or
npm install @mcp-layer/schema
# or
yarn add @mcp-layer/schema

Usage

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

  1. Reads the MCP server capabilities and metadata from the live client connection with extract(session).
  2. Calls MCP list endpoints (tools/list, resources/list, resources/templates/list, prompts/list) using pagination.
  3. Composes the same normalized catalog shape from raw definitions with composeCatalog(...) when a live session is not available yet.
  4. Normalizes everything into a unified, type-discriminated schema so generators can consume a single list.
  5. Wraps tool input/output JSON Schemas into Zod validators backed by Ajv, while preserving the original JSON Schema.
  6. Converts prompt arguments into a lightweight JSON Schema so prompts and tools share the same detail.input shape.

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 remain tool and UI resources remain resource.

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.resourceUri pointing to a ui:// resource.
  • UI resources may include _meta.ui with 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, and detail.input to build flags and help text.
  • REST: Use name for endpoints, detail.input.json for request validation, and detail.output for response schema.
  • UI: Use detail.ui.resourceUri to locate the UI and read detail.ui.csp / permissions.

Responsibilities and lifecycle

  • extract(session) does not open or close connections. It expects a live Session from @mcp-layer/connect or @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.error or detail.output.error will be populated for that item.
  • Servers that return empty lists produce an empty items array (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:

  1. Verify you are passing the Session returned by connect(...) or attach(...).
  2. Confirm session setup completed and session.client is available.
  3. Avoid passing raw MCP client objects directly; wrap flows around Session.
  4. 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