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

@bolyra/mcp

v0.6.5

Published

Gate MCP tool calls so only authorized agents can call sensitive tools — Bolyra ZKP authentication middleware for Model Context Protocol servers, over stdio or HTTP.

Readme

@bolyra/mcp

Gate MCP tool calls so only authorized agents can call sensitive tools.

Quick Start (60 seconds)

npm install @bolyra/mcp @bolyra/sdk @modelcontextprotocol/sdk
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { withBolyraAuthStdio } from '@bolyra/mcp';

const server = new McpServer({ name: 'my-server', version: '1.0.0' });

server.tool('read_file', { path: { type: 'string' } }, async (args) => ({
  content: [{ type: 'text', text: `Reading ${args.path}` }],
}));

withBolyraAuthStdio(server.server, {
  devMode: true,
  toolPolicy: {
    // 1n = READ_DATA, 2n = WRITE_DATA (BigInt — add 'n' suffix)
    read_file: 1n,
  },
});

That's it. Every tools/call now requires a valid Bolyra proof bundle.

Dev mode (full example)

Dev mode uses mock proofs — no circuit artifacts, no trusted setup, instant startup. Use it to build and test your server before wiring real ZKP verification.

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { withBolyraAuthStdio } from '@bolyra/mcp';

// Server
const server = new McpServer({ name: 'my-server', version: '1.0.0' });

server.tool('read_file', { path: { type: 'string' } }, async (args) => ({
  content: [{ type: 'text', text: 'file contents...' }],
}));

withBolyraAuthStdio(server.server, {
  devMode: true,
  toolPolicy: {
    // 1n = READ_DATA, 2n = WRITE_DATA (BigInt — add 'n' suffix)
    read_file: 1n,
    write_file: 2n,
  },
});

await server.connect(new StdioServerTransport());

Client side:

import { createDevIdentities, attachBolyraProof } from '@bolyra/sdk';

const { human, agent } = await createDevIdentities();
const auth = await attachBolyraProof(human, agent, { devMode: true });

// stdio
await client.callTool({ name: 'read_file', arguments: { path: '/tmp/x' }, _meta: auth.meta });
// HTTP
await fetch('/mcp', { headers: { ...auth.headers }, ... });

How it works

Every tools/call request must carry a proof bundle: a pair of Groth16 proofs (one from the human's circuit, one from the agent's) bound to a shared session nonce.

The server side:

  1. Extracts the bundle from params._meta.bolyra (stdio) or the Authorization: Bolyra <base64> header (HTTP).
  2. Verifies the handshake — both proofs, nonce freshness, score floor.
  3. Checks the tool's permission policy against the agent's effective bitmask.
  4. Attaches a BolyraAuthContext to the request for downstream handlers.
  5. Rejects with an MCP error if any step fails.

Discovery calls (initialize, tools/list) pass through unauthenticated.

Delegation chains (v=2 bundles) narrow scope from root credential to leaf agent across multiple hops. The effective bitmask seen by tool policies is always the leaf's — the most-restricted scope.

API reference

Server — stdio

withBolyraAuthStdio(server: McpServer, config: BolyraMcpConfig): void

Wraps an McpServer instance. Must be called before server.connect(transport).

Server — HTTP

bolyraAuthMiddleware(config: BolyraMcpHttpConfig): express.RequestHandler

Express middleware. Mount before your MCP HTTP handler. Rejects unauthenticated tools/call requests with HTTP 401.

Client helpers

attachBolyraProof(
  human: HumanIdentity,
  agent: AgentCredential,
  options?: AttachProofOptions,
): Promise<BolyraClientAuth>

Runs a handshake and returns { headers, meta, bundle }. Pass options.devMode = true to skip real proving and emit a mock bundle.

attachDelegatedBolyraProof(
  human: HumanIdentity,
  rootCred: AgentCredential,
  hops: DelegationHopSpec[],
  options?: AttachProofOptions,
): Promise<BolyraClientAuth>

Like attachBolyraProof but walks a delegation chain and returns a v=2 bundle.

Verification

verifyBundle(bundle: BolyraProofBundle, config: BolyraMcpConfig): Promise<BolyraAuthContext>

Verify a bundle directly — useful for custom transports or offline verification.

checkToolPolicy(
  toolName: string,
  ctx: BolyraAuthContext,
  policy: ToolPermissionPolicy,
): { allowed: boolean; reason?: string }

Check a BolyraAuthContext against a tool's required bitmask.

Dev identities (re-exported from SDK)

createDevIdentities(options?: DevIdentityOptions): Promise<DevIdentities>

Returns fixed-seed { human, agent, operatorKey } — deterministic, no circuit artifacts required. Logs a warning on first call. Never use in production.

Production configuration

Swap devMode: true for a real resolveCredential resolver and point the SDK at your circuit artifacts:

withBolyraAuthStdio(server, {
  resolveCredential: async (commitment) => myRegistry.get(commitment),
  toolPolicy: {
    // 1n = READ_DATA, 2n = WRITE_DATA (BigInt — add 'n' suffix)
    read_file: 1n,
    write_file: 2n,
  },
  sdkConfig: {
    circuitDir: '/path/to/circuits/build',
    rpcUrl: 'https://sepolia.base.org',
    registryAddress: '0x2781dF8b6381462d881C833Fb703d68c661c9577',
  },
});

Full config interface:

interface BolyraMcpConfig {
  network?: string;          // DID network label (default: 'base-sepolia')
  minScore?: number;         // Minimum score floor 0–100 (default: 70)
  maxProofAge?: number;      // Nonce freshness window in seconds (default: 300)
  toolPolicy?: ToolPermissionPolicy;
  devMode?: boolean;         // Mock verification — dev/test only
  resolveCredential?: (commitment: string) => Promise<AgentCredential | null>;
  sdkConfig?: BolyraConfig;
}

The HTTP variant adds authScheme?: string (default "Bolyra").

Transport guide

| Transport | Bundle location | Notes | |---|---|---| | stdio (Claude Desktop, Cursor, Cline) | params._meta.bolyra | MCP spec defines no stdio auth surface; _meta is the only protocol-level field | | HTTP / SSE / Streamable-HTTP | Authorization: Bolyra <base64-bundle> | Custom auth scheme per RFC 7235; aligns with OAuth 2.1 resource-server pattern |

Both produce the same BolyraAuthContext on the server side. Tool handlers don't need to know which transport was used.

Example

See examples/protected-file-server/ for a complete stdio server + client pair using dev mode. Run it with:

cd integrations/mcp
npm run example:protected-file-server