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

@atrib/mcp-wrap

v0.3.4

Published

Generic config-driven MCP wrapper for atrib. Spawns any upstream MCP server and applies @atrib/mcp middleware so every tool call is signed and logged. Wrap any MCP via JSON config, no per-server code.

Readme

@atrib/mcp-wrap

Generic config-driven MCP wrapper. Spawns any upstream MCP server and applies the @atrib/mcp middleware so every tool call becomes a signed, chain-linked record submitted to the atrib log.

Why this exists

createAtribProxy from @atrib/mcp does the MCP plumbing: spawn an upstream, forward tool calls, apply atrib() middleware. But every wrapper that calls it ends up reinventing the same operational shell: key resolution (env / file / Keychain / 1Password), file logging, signed-record mirror persistence, autoChain seed loading from disk, secure file permissions, per-tool gating for the preCallTransform hook. That's hundreds of lines of boilerplate per upstream MCP server.

@atrib/mcp-wrap lifts the operational shell into a reusable service and exposes the upstream + per-tool behavior via a JSON config. Wrap any upstream by writing a config; no per-server code.

Install + run

The wrapper is a workspace package; build then point an MCP host at the binary:

pnpm --filter @atrib/mcp-wrap build
node ~/repos/atrib/services/mcp-wrap/dist/main.js path/to/wrap-config.json

Or set ATRIB_WRAP_CONFIG in the host's MCP server entry. With no argument and no env var, the wrapper reads ~/.atrib/wrap-config.json.

Config shape

{
  "name": "agent-bridge",
  "agent": "claude-code",
  "upstream": {
    "command": "agent-bridge",
    "args": [],
    "env": { "AGENT_BRIDGE_URL": "...", "AGENT_BRIDGE_KEY": "..." }
  },
  "serverUrl": "mcp://agent-bridge.local",
  "logEndpoint": "https://log.atrib.dev/v1/entries",
  "autoChain": true,
  "tools": {
    "post_context": { "injectReceiptId": true },
    "checkout":     { "transactionTool": true }
  }
}

| Field | Required | Default | Notes | | ----------------- | -------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | name | yes | (no default) | Logical wrapper name. Surfaced to host as McpServer name + used in default file paths. | | agent | no | claude-code | Identity hint. Picks the atrib-creator-<agent> Keychain service before falling back to atrib-creator. | | upstream.command| yes | (no default) | Binary to spawn for the upstream MCP server. | | upstream.args | no | [] | Args for the upstream binary. | | upstream.env | no | inherited | Extra env merged with the parent process env (parent wins on conflicts). | | serverUrl | yes | (no default) | Canonical URL for content_id derivation per spec §1.2.2. Path segment for agent is appended automatically. | | logEndpoint | no | https://log.atrib.dev/v1/entries | Submission endpoint. Override for local development against @atrib/log-dev or a local log-node. | | autoChain | no | true | Chain successive tool calls within this wrapper's process lifetime. Required for CHAIN_PRECEDES edges from stdio hosts. | | tools[<name>] | no | (none) | Per-tool overrides. transactionTool: true emits a transaction event_type record. injectReceiptId: true enables D057 preCallTransform. | | logFile | no | ~/.atrib/logs/<name>-<agent>.log | Wrapper debug log (jsonl). Set to "" to disable. | | recordFile | no | ~/.atrib/records/<name>-<agent>.jsonl | Signed-record mirror (jsonl). Set to "" to disable. |

Key resolution

The wrapper picks the signing key in this order (first hit wins):

  1. ATRIB_PRIVATE_KEY env var (legacy / dev path).
  2. ATRIB_KEY_FILE env var → 0600-mode file containing the base64url seed.
  3. macOS Keychain entry for the current user, services tried in order:
    • atrib-creator-<agent> (agent-scoped; matches the wrapper convention).
    • atrib-creator (generic fallback).
  4. 1Password CLI (op read) as a recovery path. Set ATRIB_OP_REFERENCE to a valid op://<vault>/<item>/<field> reference. Off by default; activates only when the env var is set.

If none yields a key, the wrapper exits non-zero. Operator misconfiguration should surface immediately rather than silently degrading.

What you get end-to-end

For each tool call through the wrapped MCP:

  1. Wrapper signs the record (Ed25519 over the JCS-canonical record).
  2. Optionally injects the §1.5.2 receipt token into the upstream args (when tools[<name>].injectReceiptId === true).
  3. Forwards to the upstream MCP server.
  4. On success, persists the signed record to the local jsonl mirror (closes the chain seed → pubkey → record signature → log inclusion verification path).
  5. Submits to the log endpoint via the priority queue.
  6. autoChain bookkeeping advances so the next call links to this one.

Records are byte-identical to those signed by @atrib/agent or any other caller of @atrib/mcp middleware. The wrapper is a transport, not a protocol participant.

Library surface

import { wrap, parseConfig } from '@atrib/mcp-wrap'

const config = parseConfig(JSON.parse(rawJson))
const { proxy } = await wrap(config)
await proxy.server.connect(transport)

Useful when you want the wrapper's plumbing but a different bootstrap (custom config source, embedded inside another long-running service, etc.).