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

toolgate-mcp

v1.3.0

Published

Policy, approval, redaction, timeout, and audit middleware for MCP server tools.

Readme

ToolGateKit

Put guardrails around your MCP tools.

toolgate-mcp is a TypeScript middleware package for Model Context Protocol server authors. It wraps existing tool handlers and enforces a declared policy before an AI agent can use that handler.

npm install toolgate-mcp

What It Does

ToolGateKit protects tool handlers at the point where they are registered. A policy can say:

  • this tool is read, write, external, or destructive
  • this tool requires approval before execution
  • this tool can ask the host for an explicit async approval decision
  • this tool may only access specific file paths
  • this tool may only call specific network domains
  • this tool may only run specific command strings
  • this tool must pass application-specific sync or async policy rules
  • this tool can be rate limited in memory
  • this tool must time out after a fixed duration
  • this tool output and audit logs should redact secrets
  • this tool call should be written to a JSONL audit log, optionally with hash-chain verification
  • shared policy profiles should be applied consistently across many tools
  • this tool should emit privacy-conscious lifecycle events to a telemetry adapter

It returns structured results instead of throwing for expected policy failures. Denials are machine-readable and do not echo denied paths, URLs, commands, or secret rule names unless the policy explicitly opts in to exposing those details.

Policies are validated when gate() is created, so invalid timeouts, rate limits, risks, and policy lists fail before a handler is exposed.

Set audit: true to write to .toolgate/audit.jsonl, or pass createAuditLogger({ file, hashChain: true }) for a custom tamper-evident path.

Quick Start

import { createAuditLogger, gate } from "toolgate-mcp";

const audit = createAuditLogger({
  file: ".toolgate/audit.jsonl"
});

const deleteFileTool = gate(
  {
    name: "delete_file",
    risk: "destructive",
    requireApproval: true,
    pathRoot: process.cwd(),
    allowedPaths: ["src/**", "docs/**"],
    deniedPaths: [".env", "secrets/**", "node_modules/**"],
    timeoutMs: 10_000,
    redact: true,
    audit
  },
  async ({ path }) => {
    await fs.rm(path);
    return { ok: true };
  }
);

For servers with multiple tools, createToolGate() applies shared defaults, rejects duplicate tool names, applies named profiles, and generates a manifest from registered policies.

Because this policy requires approval, the handler is not executed:

{
  "ok": false,
  "error": {
    "type": "approval_required",
    "code": "APPROVAL_REQUIRED",
    "message": "Tool 'delete_file' requires user approval before execution."
  }
}

Execution Flow

For every protected call, ToolGateKit:

  1. Normalizes and evaluates policy inputs.
  2. Blocks policy violations or obtains a host approval decision when configured.
  3. Creates a handler context with requestId, risk, startedAt, and AbortSignal.
  4. Runs the handler with timeout protection.
  5. Redacts output when enabled.
  6. Writes an audit log entry when configured.
  7. Returns { ok: true, data, meta } or { ok: false, error, meta }.

Path Policy

ToolGateKit detects common input keys: path, filePath, filepath, and targetPath.

Rules:

  • deny rules win over allow rules
  • paths are normalized before matching
  • when pathRoot is set, paths and glob patterns are canonicalized before matching so symlink escapes are denied
  • without pathRoot, traversal and absolute paths are blocked
  • with pathRoot, the canonical target must remain inside the root
  • if allowedPaths is set, paths outside it are denied

Network Policy

gate(
  {
    name: "fetch_url",
    risk: "external",
    allowedDomains: ["api.github.com"],
    deniedDomains: ["metadata.google.internal"]
  },
  async ({ url }) => fetch(url)
);

Supported default URL input keys are url, uri, href, endpoint, and targetUrl. Use extractUrls for custom input shapes.

Command Policy

gate(
  {
    name: "run_command",
    risk: "destructive",
    allowedCommands: ["npm test", "npm run build"],
    deniedCommands: ["npm publish*"]
  },
  async ({ command }) => runCommand(command)
);

Supported default command input keys are command, cmd, script, and shellCommand. Use extractCommands for custom input shapes.

Rate Limit

gate(
  {
    name: "search_docs",
    rateLimit: {
      max: 20,
      windowMs: 60_000
    }
  },
  handler
);

Rate limiting defaults to an in-memory store. Add key for per-user or per-tenant quotas. Share a store and namespace across handlers, or implement RateLimitStore for an atomic external backend.

Public API

export {
  gate,
  gateMcp,
  gateMcpHandler,
  toMcpToolResult,
  createOpenTelemetryObserver,
  evaluateCustomRules,
  emitToolGateEvent,
  createAuditLogger,
  readAuditLog,
  summarizeAudit,
  createManifest,
  migrateManifest,
  compareManifests,
  createToolGate,
  createMemoryRateLimitStore,
  destructiveFilesystemPolicy,
  externalApiPolicy,
  readOnlyFilesystemPolicy,
  policyManifestSchema,
  policyConfigSchema,
  validatePolicyConfig,
  migratePolicyConfig,
  validatePolicy,
  validatePolicies,
  validateManifest,
  redact,
  evaluatePolicy
};

CLI

toolgate manifest --config toolgate.config.json --out policy-manifest.json
toolgate validate-config --file toolgate.config.json
toolgate validate-manifest --file policy-manifest.json
toolgate audit --file .toolgate/audit.jsonl --decision blocked
toolgate check-manifest --base policy-main.json --head policy-pr.json
toolgate migrate-config --file old.json --out toolgate.config.json
toolgate schema --type config --out toolgate-config.schema.json

The config file for toolgate manifest is JSON:

{
  "schemaVersion": "1.0",
  "name": "filesystem-mcp",
  "tools": [
    {
      "name": "read_file",
      "risk": "read",
      "allowedPaths": ["src/**"],
      "deniedPaths": [".env"],
      "audit": true
    }
  ]
}

Security Boundary

ToolGateKit is not an MCP server, MCP client, gateway, proxy, sandbox, approval UI, agent framework, or authentication system. It reduces risk around tool handlers, but it does not make unsafe handler code safe by itself.

Important limitations:

  • It cannot stop unsafe behavior inside a handler if the handler ignores policy inputs.
  • It cannot fully prevent prompt injection.
  • Timeout cannot always kill underlying work if the handler ignores AbortSignal.
  • Approval UI must be implemented by the host application.

Status

Stable v1 for TypeScript MCP servers. ESM-first, Node.js 18+.