Skip to content

For MCP server authors

Test your MCP server

Toolscore spins your server up over stdio, generates happy-path and adversarial edge-case scenarios from each tool's schema, lints the definitions, measures token cost, and returns an A–F grade — before you publish.

Step 1 — see it in 10 seconds

Zero setup, then point it at your server

The fastest way to see the scorecard is the bundled demo — no install, no API key, no config. Then swap in your own server's launch command.

Grade a bundled sample server

$ toolscore demo

Then grade your own

$ toolscore mcp test "python my_server.py"

Already in Claude Desktop? Point Toolscore straight at your config — zero install:

$ uvx tool-scorer mcp test --config claude_desktop_config.json --server my-server

Live demo

zsh — toolscore live demo
$
B
MCP Scorecard
notes-server 1.0.0
Grade B · Score 87%
happy 80%
edge 100%
lint 93%
Tools
Tool Scenarios Def. tokens
create_note 6/6 80
list_notes 6/6 59
search_notes 6/6 48
delete_note 6/6 52
export_notes 3/6 64
Tool definitions cost ~303 estimated tokens of context across 5 tool(s).
Top issues to fix
  1. 1. export_notes fails on valid input (export failed: storage backend not configured)
    -> The tool errors on well-formed arguments — check the handler and the input schema.
  2. 2. delete_note property 'note_id' is missing a 'type'
    -> Give the property a JSON-schema type (and an enum where values are fixed).
  3. 3. search_notes description is very short (< 10 chars)
    -> Describe what the tool does and when to use it.

The scorecard, explained

Four dimensions, one A–F grade

The score blends happy-path pass rate, edge-case resilience, and lint cleanliness; token cost rides along as a signal. ≥ 90% is an A.

A

Happy path

60%

For each tool, Toolscore synthesizes well-formed arguments from the schema and checks the call succeeds. The single biggest signal that a tool actually works.

B

Edge-case resilience

20%

Adversarial inputs — missing required fields, wrong types, empty values, boundaries — probe whether the server fails gracefully instead of crashing or returning garbage.

C

Lint

20%

Static checks on the tool definitions and server instructions: missing types and descriptions, references to tools the server does not expose, and tool-poisoning patterns such as hidden Unicode.

D

Token cost

signal

Every tool definition is part of the prompt on every request. Toolscore estimates the per-tool token footprint so you can spot context bloat early.

score = happy 60% + edge 20% + lint 20%  ·  token cost reported per-tool

Lint that reads like a model

Catch broken and hostile tool descriptions

Models follow what your tool descriptions say. Toolscore flags text that sends them to a tool the server does not expose, in descriptions, parameter descriptions and the server's own instructions — and the patterns used to smuggle instructions through tool metadata: hidden Unicode, <IMPORTANT>-style blocks, and text that tells the model to hide something from the user.

On GitHub's official MCP server (v1.12.2), label_write told models to use an update_issue tool that did not exist. The lint found exactly the two real stale references in that server, with no false positives across 254 tool definitions.

GitHub MCP server v1.12.2 — real output
text
$ toolscore mcp lint "github-mcp-server stdio --toolsets all"

warning  label_write
         refers to tool 'update_issue',
         which this server does not expose
a deliberately poisoned test server
text
$ toolscore mcp lint "python poisoned_server.py"

error    add
         tells the model to hide something from the user:
         a tool-poisoning instruction pattern
warning  add
         contains an <IMPORTANT>-style instruction block,
         a pattern used to hide instructions

Beyond generated tests

Record what real agents do with your server

Put toolscore mcp record where your MCP client starts the server. It relays every message unchanged and saves each tool call with its arguments, result, error and duration. Then toolscore eval scores the session and lists failed calls, blind retries and leaked credentials.

$ toolscore eval gold.json session.json
claude_desktop_config.json (any MCP client)
json
{
  "mcpServers": {
    "filesystem": {
      "command": "toolscore",
      "args": ["mcp", "record", "-o", "session.json", "--",
               "npx", "-y", "@modelcontextprotocol/server-filesystem",
               "./project"]
    }
  }
}

The verdict

"Top issues to fix" — not just a number

Every run ends with a ranked, plain-English list of what is wrong and how to fix it: a handler that errors on valid input, a property with no type, a description too thin for a model to choose by. Concrete problems, concrete fixes.

Top issues to fix
  1. 1. export_notes fails on valid input (export failed: storage backend not configured)
    -> The tool errors on well-formed arguments — check the handler and the input schema.
  2. 2. delete_note property 'note_id' is missing a 'type'
    -> Give the property a JSON-schema type (and an enum where values are fixed).
  3. 3. search_notes description is very short (< 10 chars)
    -> Describe what the tool does and when to use it.

The CLI

Every command you need

$ toolscore demo Grade a bundled sample MCP server — zero setup, no API key.
$ toolscore mcp test "python my_server.py" Grade your own server by launch command.
$ uvx tool-scorer mcp test --config claude_desktop_config.json --server my-server Straight from a Claude Desktop config, zero install.
$ toolscore mcp list "python my_server.py" Show the advertised tools.
$ toolscore mcp lint "python my_server.py" Lint only: schemas, missing tools, tool poisoning (exit 1 on errors).
$ toolscore mcp record -o session.json -- python my_server.py Record a real client session, then score it with toolscore eval.
$ toolscore mcp test "python my_server.py" --report md --output SCORECARD.md Export a Markdown report for a PR or README.
$ toolscore mcp test "python my_server.py" --fail-under B CI gate: exit 1 below a B.
$ toolscore mcp test "python my_server.py" --ci Write the verdict to $GITHUB_STEP_SUMMARY, fail on blocking issues.

Gate your build

CI that fails on a bad grade

--fail-under B exits non-zero below the bar. --ci writes the verdict straight to your GitHub Actions job summary and fails on blocking issues — so the scorecard shows up right in the run.

.github/workflows/scorecard.yml
yaml
# Grade your MCP server on every PR — fail the build below a B
- run: pip install tool-scorer
- run: toolscore mcp test "python my_server.py" --fail-under B --ci
#        --ci writes the verdict to $GITHUB_STEP_SUMMARY

Export it

A Markdown report for any PR or README

--report md --output SCORECARD.md renders the whole verdict — grade, per-tool table, and top issues — as Markdown designed to paste into your server's README or a PR comment.

SCORECARD.md
markdown
# MCP Scorecard: notes-server 1.0.0

**Grade: B** · Score 87%

- Happy-path pass rate: 80%
- Edge-case resilience: 100%
- Lint score: 93% (1 errors, 1 warnings)
- Tool-definition tokens: ~303 across 5 tool(s)

## Top issues to fix

- **export_notes** — fails on valid input.
- **delete_note** — property 'note_id' is missing a 'type'.
- **search_notes** — description is very short (< 10 chars).

Grade your MCP server now

No install required. uvx tool-scorer demo to see it, then point it at your own server.

$ pip install tool-scorer
$ uvx tool-scorer demo