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

@olaservo/mcp-wrappers

v0.2.0

Published

Generate typed TypeScript wrappers for MCP tools so agents can call them as code (the "MCP as code" pattern), plus the runtime bridge and a staleness-aware lifecycle.

Downloads

234

Readme

@olaservo/mcp-wrappers

Generate typed TypeScript wrappers for MCP tools so an agent can call them as code instead of over the protocol — the "MCP as code" / code-execution pattern. Ships the generator, the runtime bridge generated code calls, and a staleness-aware lifecycle helper.

What it does

Given an .mcp.json listing one or more MCP servers, the generator:

  1. connects to each server and lists its tools,
  2. compiles every tool's input/output JSON Schema into TypeScript interfaces,
  3. emits one wrapper function per tool under ./servers/<server>/, plus an index.ts, a pointer README.md, and a .metadata.json, and
  4. emits a per-server skill under ./.claude/skills/<server>-server/ — a SKILL.md seed (curated by hand thereafter) and an always-regenerated references/tools.md catalog with descriptions and behavior hints.

Each generated wrapper imports callMCPTool from this package's /runtime export, which maintains a per-server client connection pool and unwraps results (structuredContent preferred, text/JSON fallback, isError → thrown Error).

Both the generator and the runtime support stdio, static-credential HTTP (headers in config), and OAuth 2.1 HTTP servers (see below).

Install

npm install @olaservo/mcp-wrappers @modelcontextprotocol/sdk

@modelcontextprotocol/sdk is a peer dependency.

CLI

# generate wrappers + skills for every server in ./.mcp.json
npx mcp-wrappers generate

# check freshness and regenerate missing/stale wrappers (in-process)
npx mcp-wrappers ensure

Common options: --config=<path>, --output=<dir>, --skills=<dir>, --timeout=<ms>, --runtime-import=<id>, --no-skill, --no-regenerate, --quiet. OAuth options: --no-interactive, --callback-port=<n>, --oauth-store=<dir>. The CLI loads .env from the working directory so ${VAR} substitution in .mcp.json (e.g. Authorization: Bearer ${GITHUB_PAT}) works.

Server configuration

Each entry under mcpServers in .mcp.json is one of three shapes:

{
  "mcpServers": {
    // stdio — local subprocess
    "local": { "type": "stdio", "command": "my-server", "args": ["--flag"] },

    // HTTP with a static credential (PAT/API key)
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/",
      "headers": { "Authorization": "Bearer ${GITHUB_PAT}" }
    },

    // HTTP behind OAuth 2.1
    "guildbridge": {
      "type": "http",
      "url": "https://guildbridge.modelcontextprotocol.io/mcp",
      "auth": "oauth"
    }
  }
}

OAuth 2.1 servers

Set "auth": "oauth" on an HTTP server and the library runs the full authorization-code + PKCE flow, with dynamic client registration — no client ID/secret to configure. On first use it:

  1. registers a client and starts a localhost callback server,
  2. opens your browser to the authorization page (the URL is also printed, in case the browser doesn't open),
  3. exchanges the returned code for tokens, and
  4. caches the client registration + tokens under ~/.mcp-wrappers/oauth/<host>.json.

Subsequent runs are non-interactive — cached tokens are reused and refreshed automatically via the refresh token, so no browser is needed. This applies to both generate/ensure (at generation time) and the runtime bridge (at call time).

For headless environments, pass --no-interactive (CLI) or interactive: false (API) to fail fast instead of attempting a browser flow. Tune the flow with --callback-port / --oauth-store (CLI) or the oauth option (API).

Security note: OAuth tokens are cached unencrypted on disk under ~/.mcp-wrappers/oauth/. Treat that directory like any other credential store. Delete a server's file there to force re-authorization.

Programmatic API

import { generateWrappers, ensureWrappers } from "@olaservo/mcp-wrappers";

await generateWrappers({ configPath: "./.mcp.json", outputDir: "./servers" });

const status = await ensureWrappers({ regenerate: true, timeoutMs: 10000 });
if (!status.success) throw new Error(status.errors.join("; "));

Generated wrappers import the runtime by a stable specifier:

import { callMCPTool } from "@olaservo/mcp-wrappers/runtime";

Override it with runtimeImport (e.g. "../client.js") if you vendor a client. If your config lives somewhere other than ./.mcp.json, call configureRuntime({ configPath }) once at startup.

License

Apache-2.0