Skip to content

Repository files navigation

mcp-audit

Security scanner and linter for Model Context Protocol (MCP) servers. Like npm audit and eslint, but for the tools you hand your AI agents.

CI npm License: MIT Node

npm: https://www.npmjs.com/package/@royalpinto007/mcp-audit

npm install -g @royalpinto007/mcp-audit
# or run it directly
npx @royalpinto007/mcp-audit stdio "node my-mcp-server.js"

Why

MCP servers give language models real capabilities: run commands, read files, hit internal URLs, mutate databases. A single over-scoped tool or a .env exposed as a resource turns a helpful agent into a remote code execution or data-exfiltration path. Yet most MCP servers ship with no security review at all.

mcp-audit connects to an MCP server (or lints its manifest), enumerates every tool, resource, and prompt, and runs a catalog of security rules over that surface. It finds the dangerous stuff before your agent does:

  • arbitrary command / shell execution tools,
  • destructive actions with no confirmation or scoping,
  • prompt-injection sinks planted in tool descriptions,
  • secrets and system paths exposed as resources,
  • SSRF-prone URL arguments and unauthenticated HTTP transports,
  • unconstrained input schemas that let the model pass anything, anywhere.

It runs offline, is fully deterministic, and drops straight into CI with JSON and SARIF output for GitHub code scanning.

Quickstart

# Audit a server you spawn over stdio
npx @royalpinto007/mcp-audit stdio "node my-mcp-server.js"

# Audit a remote server over HTTP (with a bearer token)
npx @royalpinto007/mcp-audit http https://mcp.example.com/mcp --token "$MCP_TOKEN"

# Lint a server's declared surface from a manifest, without running it
npx @royalpinto007/mcp-audit static ./mcp-manifest.json

# List every built-in rule
npx @royalpinto007/mcp-audit rules

Example output

mcp-audit — stdio target node my-mcp-server.js
server: insecure-demo-server v0.0.0-internal
surface: 5 tools, 2 resources, 1 prompts

 CRITICAL   (3)
  ✖ MCP002 Arbitrary execution tool detected  @ run_shell
      Tool "run_shell" appears to execute commands or code (matched "shell").
      fix: Avoid exposing raw exec. If unavoidable, allowlist commands, drop privileges, sandbox execution, and require human approval.
  ✖ MCP030 Resource surfaces sensitive material  @ file:///home/app/.env
      Resource "file:///home/app/.env" references ".env", which commonly holds secrets or system credentials.
      fix: Remove the resource or restrict it to non-sensitive content.

 HIGH  (4)
  ✖ MCP001 Destructive tool has no confirmation argument  @ delete_file
  ✖ MCP031 Unconstrained filesystem path argument  @ delete_file.path
  ...

20 findings   3 critical, 4 high, 5 medium, 6 low, 2 info

The process exits 1 when any finding reaches the --fail-on threshold (default high), so a failing audit breaks the build.

Rule catalog

18 built-in rules, each with a stable id, severity, and remediation. Toggle any of them via config.

Rule Severity Category Description
MCP001 high permissions Destructive tool lacks scoping or confirmation
MCP002 critical permissions Tool exposes arbitrary command execution
MCP003 medium permissions Mutating tool has an unscoped input surface
MCP010 medium schema Tool is missing an input schema
MCP011 low schema Schema allows unbounded additional properties
MCP012 low schema Unconstrained string argument
MCP013 info schema Object schema has no required properties
MCP020 high injection Description contains probable prompt-injection text
MCP021 medium injection Tool advertises overly broad capability
MCP030 critical secrets Resource exposes secrets or sensitive paths
MCP031 high secrets Path argument is vulnerable to traversal
MCP040 high transport HTTP transport has no authentication
MCP041 medium transport Tool accepts a caller-controlled URL (SSRF risk)
MCP050 medium metadata Server metadata leaks internal information
MCP051 info metadata Server does not report a version
MCP060 high hygiene Duplicate tool names
MCP061 low hygiene Excessive number of tools
MCP062 info hygiene Tool has no description

Configuration

Drop a .mcpauditrc (or .mcpauditrc.json / mcpaudit.config.json) in your repo. mcp-audit discovers the nearest one walking up from the working directory.

{
  "failOn": "high",
  "disabledRules": ["MCP013"],
  "severityOverrides": {
    "MCP011": "info"
  },
  "ignore": ["fetch_url.note"]
}
Key Meaning
failOn Findings at or above this severity cause a non-zero exit. Default high.
disabledRules Rule ids to skip entirely.
enabledRules If set, run only these rule ids.
severityOverrides Remap a rule's severity, e.g. downgrade a noisy check.
ignore Substrings matched against a finding's location to suppress it.

Severities, lowest to highest: info, low, medium, high, critical.

CLI flags

--json                 Emit JSON instead of terminal output
--sarif                Emit SARIF 2.1.0 (for GitHub code scanning)
--output <file>        Write the report to a file instead of stdout
--config <file>        Use a specific config file
--fail-on <severity>   Exit non-zero at/above this severity
--disable <ids>        Comma-separated rule ids to disable
--only <ids>           Comma-separated rule ids to run exclusively
--token <token>        Bearer token for http transport
--header <k:v>         Extra header for http transport (repeatable)
--sse                  Use the legacy SSE transport for http
--no-color             Disable colored output

SARIF and CI usage

mcp-audit emits SARIF 2.1.0 so findings show up as annotations in GitHub code scanning.

- run: npx @royalpinto007/mcp-audit static ./mcp-manifest.json --sarif --output mcp-audit.sarif --fail-on critical
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: mcp-audit.sarif

Exit codes:

Code Meaning
0 No findings at or above --fail-on.
1 Findings at or above --fail-on.
2 Usage or runtime error.

Static mode

Static mode lints a server's declared surface from a JSON manifest without ever executing it, which is ideal for scanning untrusted servers in code review. A manifest is just the tools/resources/prompts the server would advertise:

{
  "transport": "http",
  "url": "https://mcp.example.com/mcp",
  "authProvided": false,
  "server": { "name": "billing-mcp", "version": "1.0.0" },
  "tools": [
    {
      "name": "charge_card",
      "description": "Charge a saved payment method.",
      "inputSchema": {
        "type": "object",
        "properties": { "amount": { "type": "number" } },
        "required": ["amount"],
        "additionalProperties": false
      }
    }
  ]
}

A bare JSON array of tools is also accepted.

Programmatic API

import { connectStdio, runAudit, DEFAULT_CONFIG, renderJson } from "mcp-audit";

const target = await connectStdio({ command: "node", args: ["server.js"] });
const result = runAudit(target, DEFAULT_CONFIG);
console.log(renderJson(result));

Development

npm install
npm run build      # compile TypeScript to dist/
npm test           # run the vitest suite (includes a live mock server)
npm run typecheck  # type-only check

The repo ships a real mock MCP server (fixtures/mock-server.mjs) so the test suite is hermetic and reproducible.

Contributing

Contributions are welcome. A good new rule is: independently coded, has a stable MCPxxx id, a clear severity and remediation, and a test that fires it against a fixture (plus one that proves it stays quiet on a clean surface). Add the rule module under src/rules/, register it in src/rules/index.ts, and cover it in test/rules.test.ts.

License

MIT © royalpinto007

About

Security scanner and linter for MCP servers. npx mcp-audit <target>: 18 rules, SARIF output for GitHub code scanning.

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages