Reference

Usage

The same rule set runs from the command line or from TypeScript. Both accept a list of tool definitions and return the same result object.

Install

install
# run once, without installing$ bunx github:srivtx/mcplint#main --tools tools.json# one-line install (installs the `mcplint` binary)$ curl -fsSL https://raw.githubusercontent.com/srivtx/mcplint/main/install.sh | sh# add as a project dev dependency$ bun add -d github:srivtx/mcplint

Inputs

mcplint takes exactly one of three inputs. A saved payload or config never starts a process; a server command is started over stdio, asked for tools/list, and then closed.

The three input modes.
InputDescription
--tools <tools.json>Audit a saved tools/list payload: an array, a {"tools":[...]} object, or a raw response.
--config <mcp.json>Audit every local stdio server in an MCP config with an mcpServers or servers object.
<server-command...>Start a server, request tools/list, then audit the tools it returns.

Flags

Every flag mcplint accepts.
FlagDescription
--tools <path>Audit a saved tools/list payload. Does not start a server.
--config <path>Audit every local stdio server in an MCP config file.
--client <name>Client profile to lint against: claude (default), openai, gemini, foundry, copilot, generic.
--costPrint a per-tool context-cost table.
--budget <tokens>Warn when a server's tool definitions exceed this many tokens (default: 8000).
--timeout <ms>How long to wait for a server to answer tools/list (default: 10000).
--jsonPrint machine-readable JSON: one object, or an array when more than one server is audited.
--quiet, -qPrint a single summary line per target.
--sarif <path>Write a SARIF 2.1.0 report for GitHub code scanning.
--fail-on <level>error (default), warning, info, or none — the exit-code threshold.
-h, --help / -v, --versionPrint help or the version and exit.
--End option parsing; treat the rest as the server command.

Examples

examples
# audit a saved payload$ mcplint --tools tools.json# lint against a client profile$ mcplint --tools tools.json --client claude# audit every server in a config, with a token budget$ mcplint --config mcp.json --cost --budget 20000# machine-readable output$ mcplint --tools tools.json --json# fail CI on warnings and write SARIF$ mcplint --tools tools.json --fail-on warning --sarif mcplint.sarif

Exit codes

The exit code is the CI gate.
CodeMeaning
0No findings at or above --fail-on.
1At least one finding at or above --fail-on.
2Invalid usage, or input that could not be parsed.
3I/O error: a file could not be read, or a server could not be started or did not answer.

--fail-on affects only the exit code. Every finding is still reported and included in JSON and SARIF output.

JSON output

With --json, a single target produces one object; more than one produces an array. Field order is stable, so a diff means a real change.

{
  "file": "tools.json",
  "tools": 3,
  "counts": { "error": 3, "warning": 5, "info": 0 },
  "cost": {
    "tokens": 113,
    "window": 200000,
    "fraction": 0.000565,
    "perTool": [
      { "name": "search_docs", "tokens": 34 }
    ]
  },
  "issues": [
    {
      "code": "MCP-001",
      "severity": "error",
      "location": "read file:name",
      "message": "Tool name \"read file\" is not valid for claude (use letters, digits, \"_\" and \"-\", 1-64 characters)."
    }
  ]
}

Library

The same rules power the CLI and the library. Import them directly when you are already in TypeScript.

import {
  auditTools,
  formatCost,
  formatText,
  parseToolsJson,
  resolveProfile,
} from "mcplint";

const tools = parseToolsJson(source);

const result = auditTools(tools, "tools.json", {
  profile: resolveProfile("claude"),
  budget: 8000,
});

console.log(formatText(result));
console.log(formatCost(result));