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-works

v0.4.0

Published

Mock, contract-test and guard MCP (Model Context Protocol) tool servers in Vitest with zero hassle

Readme

mcp-works

Mock, contract-test, validate and guard MCP (Model Context Protocol) tool servers in Vitest with zero hassle.

npm version docs CI license

📚 Full docs: https://ravandevil25.github.io/mcp-works/ — guides, API reference, migration, FAQ.

The official MCP SDK ships transport but no testing story. mcp-works fills that gap with four small tools: an in-process mock server, a contract checker, an arg validator, and a safety guard.

Install in 15 seconds

npm install mcp-works
import { contractTest, createMockServer, guard, validateArgs } from 'mcp-works';

const mock = createMockServer(
  {
    tools: [
      {
        name: 'get_time',
        description: 'Returns the current time.',
        inputSchema: { type: 'object', properties: {} },
      },
    ],
  },
  { get_time: () => new Date().toISOString() },
);

const report = await contractTest(mock.definition);
console.log(report.passed); // true

const safe = guard(mock, { timeoutMs: 5000, allowTools: ['get_time'] });
const res = await safe.callTool('get_time', {});
console.log(res.content[0]?.text);

Before / after

| Hand-rolled | With mcp-works | |---|---| | Spin up a real server per test (slow, flaky) | createMockServer in-process, 2 lines | | Wrong input crashes the agent at runtime | contractTest catches missing description/schema upfront | | Agent calls the wrong tool or hangs | guard allowlists tools, enforces timeout + output cap |

API

createMockServer(definition, handlers, options?)

In-process mock. callTool returns { content, isError } — unknown tools and thrown handler errors come back as isError: true instead of crashing. options.latencyMs simulates slow tools. Respects AbortSignal.

contractTest(definition)

Returns { passed, failures[] }. Checks: tools array shape, non-empty name/description, inputSchema object with type: 'object', unique names.

validateArgs(tool, args)

Zero-dependency runtime check of args against the tool's inputSchema. Returns { valid, failures[] } with dotted paths (filter.tag, tags[1]). Checks: required, type (string/number/integer/boolean/array/object), enum, string constraints (minLength, maxLength, pattern), number constraints (minimum, maximum), arrays (items type, minItems, maxItems), and nested objects.

const check = validateArgs(tool, { id: '42' });
if (!check.valid) console.log(check.failures);

guard(server, options?)

Wraps any server with a callTool method (mocks, SDK adapters — not just createMockServer output).

| Option | Default | Meaning | |---|---|---| | timeoutMs | 5000 | Abort slow calls; throws TIMEOUT | | allowTools | all | Deny-list everything else; throws TOOL_DENIED | | maxBytes | 1048576 (1MB) | Cap output size; throws OUTPUT_TOO_LARGE | | redact | off | true = redact emails, API keys, card-like numbers; RegExp[] = custom patterns (replaced with [redacted]) |

All errors are McpWorksError with a .code (TOOL_DENIED, TIMEOUT, OUTPUT_TOO_LARGE, ABORTED, INVALID_TOOL). McpTestkitError remains as a deprecated alias.

Migrating from @sauravsk2507/mcp-testkit

npm uninstall @sauravsk2507/mcp-testkit && npm install mcp-works

Then replace the import specifier: @sauravsk2507/mcp-testkit → mcp-works. API is identical; optionally rename McpTestkitError → McpWorksError.

Examples

node examples/vitest-mock.mjs
node examples/guard-express.mjs
node examples/sdk-compat.mjs

Roadmap

  • v0.3: PII-redact guard option, richer validateArgs (arrays, string/number constraints), McpWorksError branding
  • v0.4: npm create scaffolder, OTel tracing, registry audit metadata

FAQ

Does this replace the official MCP SDK? No. The SDK owns transport (stdio/SSE, protocol messages). This package owns the testing layer: mock, contract checks, arg validation, guard.

How do I use it with a real SDK server? Pull the tool definitions out of your SDK Server and feed them to contractTest / validateArgs. See examples/sdk-compat.mjs.

Does it work with plain Node test runner or Jest? Yes. Only the docs use Vitest. createMockServer, contractTest, validateArgs and guard are plain async functions with zero runtime deps.

How do I import from CommonJS? const { createMockServer } = require('mcp-works'); — dual ESM+CJS, verified by attw and a CJS smoke test in CI.

How do I catch guard errors? All guard errors are McpTestkitError with a .code: TOOL_DENIED, TIMEOUT, OUTPUT_TOO_LARGE. Switch on code for retries.

Troubleshooting

| Symptom | Cause | Fix | |---|---|---| | contractTest passes but bad args crash at runtime | Contract checks shape, not values | Add validateArgs(tool, args) before callTool | | TIMEOUT on every call | timeoutMs lower than handler latency | Raise timeoutMs or pass an AbortSignal with a longer deadline | | OUTPUT_TOO_LARGE | Default 1MB cap exceeded | Set maxBytes explicitly | | Types resolve to ESM under require | Stale 0.1.0 install | Upgrade to latest; require types ship as .d.cts |

License

MIT