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

@strixgov/mcp-adapter

v0.1.0

Published

One-call governance for any MCP server. Wraps every tool.call() with policy evaluation, signed execution receipts, and an optional approval gate — no changes to your tool implementations required.

Downloads

91

Readme

@strixgov/mcp-adapter

Governance for every MCP tool call — at the action boundary, in five lines of code.

Most AI governance tools operate upstream of the action (prompt filters, evals) or downstream (audit logs, observability). The MCP adapter operates at the action itself: every callTool your MCP server receives is classified, evaluated against policy, and either allowed, denied, or held for approval before it runs. Same enforcement applies regardless of whether the actor is the agent, a human, or an automation. No changes to your tool implementations required.

npm install @strixgov/mcp-adapter

Every call produces an Ed25519-signed receipt that anyone can verify with @strixgov/verifier. Strix is not on the trust path of those receipts — the verifier depends only on public JWKS (RFC 7517) and standard cryptographic primitives.

See it in 20 seconds

npx @strixgov/mcp-adapter demo

One command. No clone, no install, no env vars. Spins up an in-process stub MCP server, drives three governed tool calls covering all three policy outcomes (ALLOW / APPROVAL_REQUIRED / DENY), prints three Ed25519-signed receipts, then hands the chain to @strixgov/verifier — an independent package with zero Strix dependencies — and prints ✓ VERIFIED.

Same code path every production deployment runs. No demo-only signing shortcut. The receipts the demo produces would verify under any third-party verifier that speaks the public JWKS contract.

What it does

Wraps your MCP server's callTool path with:

  • Policy enforcement — ALLOW / DENY / APPROVAL_REQUIRED per tool
  • Signed execution receipts — Ed25519 signature on every call (allowed or denied)
  • Companion-pack classification — pre-classified risk levels for 40+ common tools (GitHub, Slack, Notion, Linear)
  • Heuristic fallback — auto-classifies any unknown tool by name pattern (get_* → LOW READ, delete_* → CRITICAL WRITE, etc.)
  • Fail-closed guarantee — unknown tools default to CRITICAL EXECUTE → DENY unless explicitly allowed

5-line integration

import { governMCPServer } from "@strixgov/mcp-adapter";
import { githubCapabilities } from "@strixgov/capabilities-mcp-common/github";

const governed = governMCPServer(myToolHandlers, {
  serverId: "github",
  capabilities: githubCapabilities,
  policy: {
    rules: {
      "mcp.github.get_file_contents":   "ALLOW",
      "mcp.github.merge_pull_request":  "APPROVAL_REQUIRED",
      "mcp.github.delete_repository":   "DENY",
    },
    default: "DENY",
  },
});

// Drop-in for your MCP request handler:
const result = await governed.callTool(name, args, { actorId: "agent-1" });

myToolHandlers is your existing tool map — no changes required.

API

governMCPServer(tools, opts)

tools — either:

  • Record<string, async (args) => result> — plain handler map (most common)
  • { handler(name, args), listTools() } — MCP server interface

opts: | Field | Type | Description | |-------|------|-------------| | serverId | string | Namespace prefix for capability IDs (mcp.<serverId>.<toolName>) | | capabilities | McpCapability[] | Companion-pack capability list (optional — heuristics used if omitted) | | policy.rules | Record<string, "ALLOW"\|"DENY"\|"APPROVAL_REQUIRED"> | Per-capability overrides | | policy.riskOverrides | Record<string, "ALLOW"\|"DENY"\|"APPROVAL_REQUIRED"> | Policy by risk level | | policy.default | "ALLOW"\|"DENY" | Catch-all (default: "DENY") | | signingKey | object | Ed25519 key for receipts (auto-generated if omitted) | | storagePath | string | Persist receipts to JSONL on disk (in-memory if omitted) | | connectedMode | object | Sync receipts to strixgov.com (opt-in) | | rateLimits | object | Per-capability rate limits |

Returns:

{
  callTool(name, args, ctx?): Promise<unknown>
  listTools(): Promise<Array<{ name: string }>>
  gateway: Gateway  // emit "receipt" events here
  signingKey: object
}

createGovernedServer(opts)

Convenience alias — pass tools alongside the other opts in a single object:

const server = createGovernedServer({
  serverId: "github",
  capabilities: githubCapabilities,
  policy: { default: "DENY" },
  tools: {
    get_file_contents: async (args) => octokit.repos.getContent(args),
    merge_pull_request: async (args) => octokit.pulls.merge(args),
  },
});

Listening to receipts

Every call (allowed or denied) emits a signed receipt:

governed.gateway.on("receipt", (receipt) => {
  console.log(receipt.decision);    // "ALLOW" | "DENY"
  console.log(receipt.signature);   // Ed25519 hex
  console.log(receipt.actorId);     // forwarded from ctx
  console.log(receipt.capabilityId); // e.g. "mcp.github.get_file_contents"
});

Risk classification

Without a companion pack, tools are classified by name:

| Pattern | Risk | Mode | |---------|------|------| | get_*, list_*, read_*, fetch_*, search_* | LOW | READ | | create_*, update_*, edit_*, post_*, send_* | HIGH | WRITE | | delete_*, remove_*, destroy_* | CRITICAL | WRITE | | exec_*, run_*, execute_* | CRITICAL | EXECUTE | | (anything else) | CRITICAL | EXECUTE |

Unknown tools default CRITICAL EXECUTE — policy default: "DENY" blocks them.

Companion packs

Pre-classified capability lists are available in @strixgov/capabilities-mcp-common:

import { githubCapabilities } from "@strixgov/capabilities-mcp-common/github";
import { slackCapabilities }  from "@strixgov/capabilities-mcp-common/slack";
import { notionCapabilities } from "@strixgov/capabilities-mcp-common/notion";
import { linearCapabilities } from "@strixgov/capabilities-mcp-common/linear";

Scaffold a governed server for your own MCP — one command

npx @strixgov/mcp-adapter init <server-name> writes a runnable single-file governed server into your current directory. It runs immediately in offline stub mode (3 sample calls → 3 signed receipts) and marks the 5 blocks you need to fill in with TODO(strix): so you can grep your way to production.

# A known companion pack — auto-imports @strixgov/capabilities-mcp-common/notion
npx @strixgov/mcp-adapter init notion

# Your own server — inlines a starter capabilities array you fill in
npx @strixgov/mcp-adapter init my-internal-server

# With the connected-mode env-var block scaffolded in
npx @strixgov/mcp-adapter init github --with-connected-mode

Known packs: notion, github, slack, linear, filesystem, postgres, email. Anything else gets the "starter inline" branch with two placeholder capability entries.

The generated file is the same shape as the seven examples below — your own MCP server, governed at the action boundary, in five lines of code.

Try it

Seven runnable end-to-end examples ship with the package; each defaults to an offline stub (zero config) and auto-promotes to the real MCP server over stdio when the optional peers are present. Pick the one that matches the MCP your prospect already uses.

| Example | What it demonstrates | |---|---| | examples/notion.mjs | Server-prefixed tool names (notion-fetch, notion-create-comment); MEDIUM-write approval flow; explicit notion-create-database DENY | | examples/filesystem.mjs | Highest blast radius; LOW/MEDIUM/HIGH outcomes plus a heuristic-CRITICAL DENY for out-of-pack delete_file | | examples/github.mjs | The marquee procurement story — merge_pull_request (CRITICAL irreversible) held for approval, bound cryptographically to the signed receipt | | examples/slack.mjs | CISO-legible "agent posted to a channel" story; also exercises the cap.name lookup path for hyphen/underscore server-prefixed names | | examples/postgres.mjs | Enterprise-depth story — MEDIUM-classified SELECTs (exfiltration discipline) gated for approval; query preview surfaced to the approver; out-of-pack drop_table DENY'd via heuristic | | examples/email.mjs | High-adoption story — send_email / reply_all / forward are HIGH WRITE (irreversible once delivered); to/subject surfaced to the approver; out-of-pack purge_mailbox blocked | | examples/linear.mjs | Team-operations wrap rounding out Notion + Slack — delete_issue HIGH, out-of-pack archive_team heuristic-CRITICAL DENY |

Notion — examples/notion.mjs

node examples/notion.mjs            # offline stub — zero config

# Live mode against the real Notion MCP server (optional peers):
npm install --no-save @modelcontextprotocol/sdk @notionhq/notion-mcp-server
NOTION_TOKEN=secret_… node examples/notion.mjs

Wraps Notion's full tool surface, allows every read, gates every write behind an approval prompt (auto-approved for the demo), and hard-denies notion-create-database. Every call — allowed or denied — produces a signed receipt printed at the end.

Filesystem — examples/filesystem.mjs

node examples/filesystem.mjs        # offline stub — zero config

# Live mode against the reference @modelcontextprotocol/server-filesystem:
npm install --no-save @modelcontextprotocol/sdk @modelcontextprotocol/server-filesystem
mkdir -p /tmp/strix-fs-demo
STRIX_FS_LIVE_ROOT=/tmp/strix-fs-demo node examples/filesystem.mjs

Highest-blast-radius wrap in the bundle. Demonstrates four policy outcomes against real filesystem ops — LOW READ ALLOW (list_directory, read_file), MEDIUM WRITE APPROVAL_REQUIRED (write_file), HIGH WRITE APPROVAL_REQUIRED (move_file), and a heuristic-classified CRITICAL DENY for an unknown delete_file tool that isn't in the pack — proving the fail-closed default works for out-of-pack tools.

GitHub — examples/github.mjs

node examples/github.mjs            # offline stub — zero config

# Live mode against the official @modelcontextprotocol/server-github:
npm install --no-save @modelcontextprotocol/sdk @modelcontextprotocol/server-github
export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_…
node examples/github.mjs

The strongest narrative wrap. The companion pack classifies ~30 GitHub tools including merge_pull_request (CRITICAL — irreversible from the gate's perspective; revert is a new commit). The demo holds the merge for approval rather than denying it outright, and binds the approver's identity cryptographically to the signed receipt. This is the cleanest "Strix held the irreversible action for a known approver" demo for procurement conversations. Also shows an out-of-pack delete_repository failing closed via heuristic CRITICAL → DENY.

Slack — examples/slack.mjs

node examples/slack.mjs             # offline stub — zero config

# Live mode requires a Slack MCP server + a workspace token:
npm install --no-save @modelcontextprotocol/sdk @modelcontextprotocol/server-slack
export SLACK_MCP_XOXP_TOKEN=xoxp-…
node examples/slack.mjs

CISO-legible governance story. The Slack pack uses server-prefixed tool names (slack_send_message, slack_read_channel) — different from GitHub's bare convention. The example also includes an in-line regression check: if any in-pack Slack tool produces a heuristic-derived receipt id instead of the pack-canonical id, the demo exits non-zero. That pins the cap.name lookup path against accidental regression.

Policy examples

Allow reads, block writes

policy: {
  riskOverrides: { LOW: "ALLOW" },
  default: "DENY",
}

Allowlist specific tools

policy: {
  rules: {
    "mcp.github.get_file_contents": "ALLOW",
    "mcp.github.list_pull_requests": "ALLOW",
  },
  default: "DENY",
}

Require approval for destructive actions

policy: {
  rules: {
    "mcp.github.delete_repository": "APPROVAL_REQUIRED",
    "mcp.github.merge_pull_request": "APPROVAL_REQUIRED",
  },
  riskOverrides: { LOW: "ALLOW" },
  default: "DENY",
}

Connected Mode (Commercial)

By default the adapter operates locally — receipts go to memory or JSONL on disk via storagePath. For production deployments that need centralized approvals, multi-tenant isolation, 2-year retention (EU AI Act Article 12), or compliance evidence packs, Strix offers Connected Mode via the strixgov.com platform.

Connected Mode requires a commercial license. Once provisioned, the adapter detects two env vars and starts forwarding signed receipts to the platform in the background:

export STRIX_API_KEY="<from your strixgov.com tenant settings>"
export STRIX_TENANT_ID="<your tenant slug>"
# STRIX_KERNEL_URL defaults to https://www.strixgov.com

To obtain a commercial license + API key, see COMMERCIAL.md or email [email protected].

Local execution is never blocked by network availability — Connected Mode is a forward of locally-signed receipts, not a gate on them. To opt out of auto-detection (even with the env vars set), pass connectedMode: false explicitly.

import { governMCPServer, loadConnectedModeFromEnv } from "@strixgov/mcp-adapter";

const srv = governMCPServer(tools, {
  serverId: "github",
  policy: { default: "DENY" },
  connectedMode: loadConnectedModeFromEnv(), // null → stays local
});

Verifying receipts

The receipts this adapter produces are byte-compatible with @strixgov/verifier:

# Offline — export the JWKS from your local gateway, verify a receipt file
npx strix-gateway keys jwks > ./public-jwks.json
npx @strixgov/verifier receipt path/to/receipt.json --jwks ./public-jwks.json

# Whole chain
npx @strixgov/verifier chain ~/.strix-mcp-adapter/receipts.jsonl --jwks ./public-jwks.json

The verifier has zero Strix dependencies — just Ed25519 + SHA-256 from node:crypto and the public JWKS contract. Strix is not on the trust path of receipt verification: any third party can confirm an action was authorized at execution time without trusting Strix at all.

Standards alignment

Strix is listed in the Cloud Security Alliance AARM Builders Registry with status Aligned. AARM (Autonomous Action Runtime Management) is the CSA-led specification for runtime governance of autonomous AI actions.

This adapter is the MCP-specific drop-in for Strix's AARM coverage. It implements AARM Core R1–R3 (runtime authorization, deterministic policy evaluation, fail-closed enforcement) at the MCP boundary, on top of @strixgov/tool-gateway. The signed receipts it produces are tamper-evident under @strixgov/verifier — the public reference implementation of AARM Core R6.

See the strixgov.com AARM mapping for the per-requirement breakdown.

Requirements

  • Node.js ≥ 18
  • @strixgov/tool-gateway ≥ 0.4.1 (peer dependency)

Security posture

See SECURITY.md for the security-team-facing posture, including:

  • Credential boundary — three deployment positions (host holds / per-call passthrough / never crosses the host) with the audit- posture trade-off of each.
  • What the adapter stores — only signed receipts (with invocationHash, NOT raw args), the gateway signing key, and policy config. Never auth credentials. Never raw tool args.
  • Runtime model — what happens on host crash / mid-approval / disk full. Fail-closed at every boundary; governMCPServer(...) throws at construction if the signing key isn't loadable.
  • Multi-tenant boundary — single-tenant per governMCPServer(...) instance in v0.1.0; instantiate once per tenant for isolation.
  • What the adapter does NOT govern — direct handler calls that bypass the gateway, the agent's internal state, the upstream tool's own argument handling (SQL/command injection inside the upstream is the upstream's responsibility).

Report security issues via GitHub Security Advisory on github.com/Strixgov/strix.

License

@strixgov/mcp-adapter is distributed under the Elastic License 2.0. You may use, modify, and self-host the adapter internally — including in production — provided you do not offer it as a hosted or managed service to third parties.

If you run the adapter in a commercial product or want hosted Connected Mode, retention, approvals, or compliance evidence packs, see COMMERCIAL.md or email [email protected].

The trust primitives the adapter depends on (@strixgov/verifier, @strixgov/tool-gateway, @strixgov/mcp-token-validator) remain MIT-licensed. Strix is not on the trust path of receipt verification or token validation — that property is unchanged by this license boundary.