Skip to main content
Glama

MCProbe

A stdio MCP server that audits other MCP servers over the live protocol. It connects to any MCP target (stdio or HTTP), lints every tool's schema for agent-usability, then actually calls the tools with deliberately broken inputs to see how the server handles them, and returns a 0–100 conformance score with a per-dimension breakdown rendered as Markdown.

The behavioral pass is the part that matters. Static schema audits tell you that a tool exists and looks reasonable. MCProbe then picks up a phone and dials each tool with missing_required, wrong_type, out_of_enum, and extra_garbage inputs — the same mistakes a language model will make on a bad day — and classifies the response. A server that returns a clean isError: true rejected the input correctly. A server that says "OK" to garbage (silently accepted it) or crashes the JSON-RPC transport both failed to reject it — and the Error Handling score is the fraction of bad inputs the server rejected cleanly.

Problem statement

The Model Context Protocol is new. Servers proliferate. Most ship with tool schemas that an agent can call, but few ship with tool schemas that an agent can call correctly: parameters are untyped, descriptions are missing, names are not snake_case, and a quick look at the code reveals that the handler is doing Number(x) / Number(y) with no guard at all.

The convention in the wider ecosystem is to ship a static schema audit that flags the obvious smells and then declare the server ready. The smells are real, but a static audit cannot tell you whether the server behaves: it cannot tell you that divide("x", "y") silently returns NaN, or that an extra unknown key is just stripped and ignored.

MCProbe does both, on a single connection:

  1. Static lint. Twelve rules over every tool's schema: missing or thin descriptions, duplicate or unusual names, an empty or non-object schema, untyped or undocumented parameters, and a server-wide rule for "I said I had tools but I have none."

  2. Behavioral fuzz. For each tool, the generator produces one valid case and at least three malformed variants, calls the target over the live JSON-RPC transport, and classifies the outcome as ok (the tool shrugged), toolError (graceful rejection), or protocolCrash (worst case). A malformed case that comes back without isError: true is flagged as silentlyAccepted — exactly the failure mode the linter cannot see.

  3. Scoring. The findings and the fuzz results are combined into a 0–100 score on four dimensions, mapped to an A–F grade, and rendered as a Markdown report the host (or a human) can read.

Related MCP server: owasp-mcp-scan

Hosted version — mcprobe.org

Don't want to install anything? mcprobe.org is the hosted version of this engine — paste an MCP server's URL in your browser and get the same graded report, no Node or setup required.

  • Free — 2 audits/day with a soft report (score, grade, dimension scores, finding counts).

  • Pro ($9.90 once, lifetime) — the full report (per-dimension reasons, every finding, the fuzz table, recommended fixes), 30 audits/day, saved history, the public gallery, Markdown export, and shareable links.

  • Local (stdio) servers — a Pro feature: run mcprobe push --stdio "…" --token <key> to audit a server on your machine and send the report to your account (see the CLI).

This engine stays MIT-licensed and free — the hosted app only adds accounts, persistence, the gallery, and those conveniences. Run it yourself for nothing, or pay once for the hosted experience.

Install

npm install
npm run build     # tsc -p tsconfig.json && tsc -p examples/demo-target/tsconfig.json

The build emits:

  • dist/index.js — the probe (run this as a stdio MCP server).

  • examples/demo-target/dist/index.js — a deliberately flawed MCP server used by the tests and the demo.

To launch the probe as a stdio MCP server so any host can talk to it:

npm start

No port, no daemon, no config file. The probe speaks JSON-RPC on stdin/stdout and writes operator logs to stderr.

Quickstart — audit any MCP server

Two ways to point MCProbe at a target. You only ever register MCProbe; it dials the target itself, so the target needs no setup.

Option 1 — from an MCP client (Claude Desktop, Cursor, any host)

Add MCProbe to your client's MCP config (use the absolute path to the built dist/index.js):

{
  "mcpServers": {
    "mcprobe": {
      "command": "node",
      "args": ["/absolute/path/to/mcprobe/dist/index.js"]
    }
  }
}

Then ask in plain English:

Use mcprobe to audit https://docs.base.org/mcp over http — connect, then run a full report with fuzz and show me the score.

The host calls probe_connect then probe_report for you. MCProbe also advertises server instructions, so the model is told the flow on connect — no need to memorise the tool names.

Option 2 — the mcprobe CLI (no host)

Get the project and build it, then audit any server straight from the terminal:

git clone https://github.com/alitiknazoglu/mcprobe
cd mcprobe && npm install && npm run build

# audit an HTTP server
node dist/index.js audit https://docs.base.org/mcp --fuzz

# audit a LOCAL stdio server (no URL — the `npx some-server` style)
node dist/index.js audit --stdio "npx @acme/my-mcp-server" --fuzz

(After npm install -g . or npm link, the command is just mcprobe audit ….)

It prints the full Markdown report to stdout — add --json for a machine-readable report (what the GitHub Action and other tooling consume). --fuzz also calls each tool with malformed input to score Error Handling & Liveness; tools the target marks destructiveHint: true are skipped unless you add --fuzz-destructive, so a default run is safe even against servers you don't control. Omit --fuzz for a read-only static audit (metadata + schema quality only).

Save an audit to your account. push runs the same audit and uploads the report to an ingest endpoint (default https://mcprobe.org/api/ingest) with a bearer token:

node dist/index.js push --stdio "npx @acme/my-mcp-server" --fuzz --token mcp_xxx

The token comes from your mcprobe.org profile; --to <url> (or MCPROBE_API) points it at a different endpoint. Run mcprobe help for all flags.

Audit in CI (GitHub Action)

Gate your MCP server on every push — audit it and fail the build if its conformance grade drops. Free and self-contained (it runs the open-source engine on your own runner; no account required):

# .github/workflows/mcprobe.yml
name: MCP audit
on: [push, pull_request]
jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: alitiknazoglu/mcprobe@v1
        with:
          url: https://your-server.example.com/mcp
          fuzz: true          # behavioral testing (call tools with bad input)
          min-score: "75"     # fail the job below this (A≥90 B≥75 C≥60 D≥40); omit to report only

The step prints the score to the job summary and exposes score / grade outputs. It also writes a full mcprobe-report.json you can upload as an artifact. Leave off min-score to report without ever failing the build.

Upload runs to your dashboard (Pro): add one line — a token: (your mcprobe.org Pro key, stored as a GitHub secret). The audit stays the same; the run is also uploaded to your history/dashboard on mcprobe.org.

      - uses: alitiknazoglu/mcprobe@v1
        with:
          url: https://your-server.example.com/mcp
          min-score: "75"
          token: ${{ secrets.MCPROBE_TOKEN }}   # ← only new line; uploads to your dashboard

The audit itself is always free and local; the hosted tracking (history, gallery, badge) is the Pro tier — see Hosted version.

Agent skill

This repo ships an agent skill so your coding agent knows how to drive MCProbe on its own — just say "audit this MCP server" and it runs the right probe_* tools or mcprobe CLI command and explains the score. To install it, copy the folder into your agent's skills directory:

# Claude Code (project- or user-level)
cp -r .agents/skills/mcp-audit /path/to/your/project/.claude/skills/

# Other agents that use the open skills format (Codex, Opencode, Cursor, …)
cp -r .agents/skills/mcp-audit /path/to/your/project/.agents/skills/

It's a single SKILL.md — the same file works in either location.

The six probe_* tools

MCProbe registers four core tools and two optional helpers. The core four cover the full lint → fuzz → score pipeline; the two helpers cover the everyday ergonomics of managing connections.

Tool

Purpose

Returns

probe_connect

Open a connection to a target.

{ connectionId, name, version, capabilities, counts, defaultConnectionId }

probe_lint

Run the 12 lint rules over the target's cached tool summaries.

{ connectionId, server, findings, summary }

probe_fuzz

Generate valid + malformed inputs per tool, call each, classify the outcome. Skips destructive tools by default.

{ connectionId, server, results, coverage, summary }

probe_report

Run lint (and fuzz when requested), score, render Markdown.

{ connectionId, server, overall, grade, dimensions, coverage, findings, fuzz, markdown }

probe_list

(optional) Enumerate the target's tools.

{ connectionId, server, tools }

probe_disconnect

(optional) Close one connection (by id) or every connection.

{ removed, remaining, defaultConnectionId }

All tools default to the most recently opened connection when connectionId is omitted, so a single-target audit is a three-call sequence: probe_connectprobe_reportprobe_disconnect.

Every tool also declares MCP annotations so a host can reason about side effects before calling: probe_lint and probe_list are readOnlyHint: true, while probe_fuzz is destructiveHint: true (it invokes the target's tools), and the tools that reach a target (probe_connect, probe_fuzz, probe_report) set openWorldHint: true. MCProbe audits other servers for agent-usability, so it declares these hints on its own tools too.

probe_connect

Two transports: stdio (spawns a child process) and http (speaks the streamable HTTP transport, with SSE fallback). For stdio, command is required; for http, url is required. The target's initialize handshake is run synchronously, the server's identity and capabilities are cached, and a stable connectionId is returned.

probe_lint

A pure pass over the connection's cached tool summaries — no extra round-trip. Each finding carries a stable code, a severity (error, warning, info), a human-readable message, a location ({ tool, param? }), and a hint with a concrete fix.

The twelve rules are:

Code

Severity

What it catches

tool.missing_description

error

A tool with no description at all.

tool.thin_description

warning

A description under 12 characters.

tool.duplicate_name

error

Two tools registered with the same name.

tool.unusual_name

warning

A name that is not snake_case or kebab-case.

tool.no_input_schema

warning

An empty or missing inputSchema.

tool.no_annotations

info

A tool that declares no MCP annotations (readOnlyHint, destructiveHint, etc.).

schema.invalid

error

A schema that fails to compile (Ajv).

schema.root_not_object

warning

A root type that is not object.

schema.no_required

info

Properties declared but no required array.

param.untyped

warning

A property with no type/enum/const/oneOf.

param.missing_description

warning

A property with no description.

server.no_tools

warning

The server claims tools but registers none.

probe_fuzz

For every tool (capped at maxTools, default 10), the generator emits one valid case and at least three malformed variants:

  • missing_required:<field> — drop each required field in turn.

  • wrong_type:<field> — replace each typed field with a value of a different primitive type.

  • out_of_enum:<field> — for enum or const fields, send a value the schema forbids.

  • extra_garbage — append a sentinel key to the valid args.

Each case is sent to the target over the live JSON-RPC transport. The classifier assigns one of three outcomes:

Outcome

Meaning

ok

The target returned a result with isError: false. For a malformed case this is silentlyAccepted: true; for a valid case with no usable content it is emptySuccess: true.

toolError

The target returned a result with isError: true (graceful rejection).

protocolCrash

The call rejected or the transport closed.

Hallucinated success (emptySuccess). A valid call that returns success but with an empty / contentless result — e.g. a write tool that answers 200 with an empty body and never persists anything. The agent reads "done" while nothing happened. MCProbe flags this on the critical line, drops Liveness credit for that call (it isn't a real success), and recommends returning a confirmation payload. This is the "the agent said done, nothing happened" bug.

Dry-run safety. By default, tools annotated destructiveHint: true are not fuzzed — so pointing MCProbe at a server you don't control can't trigger a real destructive action (e.g. a delete_file tool). Pass fuzzDestructive: true to override. probe_fuzz (and the report) return a coverage summary listing how many tools were fuzzed and which were skipped (as destructive, or over the maxTools cap).

probe_report

The convenience entry point. Calls probe_lint (always) and probe_fuzz (when fuzz: true), scores the result on the four dimensions described below, and returns the structured ConformanceReport and a rendered Markdown string. The Markdown is the canonical payload; downstream tools that need the numbers can pull them out of the structured fields.

Scoring model — four dimensions

The overall 0–100 score is the mean of the measured dimensions. Dimensions that were not measured (e.g. the two behavioral ones when fuzz: false, or when every tool was skipped) are reported as "not measured" and excluded from the average rather than penalized with a fake value. This is what lets a static audit of a clean server still score 100/100.

The two static dimensions are subtractive (start at 10, lose points per finding). The two behavioral dimensions are normalized rates, so a score is comparable across servers of different sizes — and the fuzz cases are partitioned by kind (malformed → Error Handling, valid → Liveness) so no outcome is ever counted twice.

Letter grades: A ≥ 90, B ≥ 75, C ≥ 60, D ≥ 40, F < 40.

Dimension

Always measured?

What it captures

Metadata & Documentation

yes

Server identity (name, version), advertised capabilities, presence of instructions (+1 bonus).

Schema Quality

yes

Subtractive: 1 per error, 0.5 per warning, 0.25 per info finding.

Error Handling

only with fuzz: true

Rate over malformed cases: 10 × (gracefully-rejected / total malformed). A silent accept (garbage let through) or a protocol crash both count as failed rejections.

Liveness & Performance

only with fuzz: true

Rate over valid cases: 10 × (successful / total valid), minus 0.5 per 100ms that the valid-call p50 latency exceeds a 200ms target.

The per-dimension reasons and counts are emitted in the Markdown report so the score is auditable by a human. When fuzzing runs, the report header also shows two extra lines:

  • a Coverage line (how many tools were fuzzed, and which were skipped as destructive or over the maxTools cap); and

  • a critical-issues callout — a flag, not a second score — hoisting the dangerous findings to the top, e.g. ⚠ Critical: 4 tool(s) silently accept malformed input (…); 1 protocol crash(es), or ✓ No critical behavioral issues when there are none. The normalized scores are unchanged; this just makes the scary stuff visible above the fold.

The report ends with a Recommended fixes section: a prioritized to-do list (worst severity first) that turns each finding into a concrete action — the fix hint plus the exact tools/parameters it affects — followed by behavioral fixes for tools that silently accept input or crash. So the report is a prescription, not just a diagnosis. A clean server gets "Nothing to fix — this server passes every check."

30-second demo

The probe ships with a deliberately flawed demo target at examples/demo-target/ and a smoke script that runs the full probe_report pipeline against it. From a clean clone:

npm install
npm run build
node scripts/smoke-report.mjs

The script spawns the probe as a stdio MCP server, opens a connection to the demo target, calls probe_report with fuzz: true, and prints the Markdown report to stdout. The demo target is wired to fail loudly: greet has no description, divide returns NaN on bad input, set_mode has a thin description, and well_behaved is the only tool with a clean, validated schema. The report will show a low overall score with concrete findings, a coverage line, a critical-issues callout, and a fuzz table that classifies the broken cases.

For an interactive tour, the official MCP inspector works as a host against the built probe:

npx @modelcontextprotocol/inspector node dist/index.js

The inspector UI lists the six probe_* tools; calling them manually is a good way to see the request/response shape.

External server example

For a full probe_connectprobe_reportprobe_disconnect walkthrough as an AI agent would run it (natural-language request, the JSON tool calls, and the rendered report), see examples/agent-usage.md.

The probe is not coupled to the demo target. To audit any other MCP server, swap the command/args in probe_connect:

// tool call: probe_connect
{
  "transport": "stdio",
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem@latest", "/tmp"]
}

The probe runs the initialize handshake against the spawned process, caches its tools, and is ready for probe_lint / probe_fuzz / probe_report. The same pattern works for HTTP targets: pass transport: "http" and a url instead.

A real transcript of this audit (run against @modelcontextprotocol/server-filesystem@latest and saved to examples/transcripts/external-server.md) is included in the repository. The script that produced it is scripts/external-audit.mjs. A self-audit (a second copy of the probe scoring the first) lives at examples/transcripts/self-audit.md.

Use as a library

Besides the MCP server, MCProbe exposes its audit pipeline as functions for embedding in your own backend:

import { auditUrl, auditStdio, softenReport, renderReport } from "mcprobe/audit";

// HTTP server (URL in, report out — never spawns a process):
const report = await auditUrl("https://example.com/mcp", { fuzz: false });

// Local stdio server (spawns the subprocess — only run commands you trust):
const local = await auditStdio("npx", { args: ["@acme/my-mcp-server"], fuzz: true });

console.log(report.overall, report.grade);  // structured ConformanceReport
console.log(renderReport(report));          // or the Markdown
const teaser = softenReport(report);        // a trimmed view (scores, no detail)

Both default to a static, read-only audit (fuzz: false); pass fuzz: true to also run the behavioral fuzzer (destructive tools are skipped unless fuzzDestructive: true). auditUrl is HTTP-only and side-effect-free, ideal for a hosted backend; auditStdio launches a local subprocess, so use it only for servers you trust (CLIs, your own machine). softenReport is handy for a free/preview tier — it keeps the scores and counts but withholds the reasons, full findings, fuzz table, and recommended fixes.

This is exactly how the hosted app at mcprobe.org is built on top of the engine.

Architecture

MCProbe plays two roles at once: it is a stdio MCP server to its host, and an MCP client to whatever it is auditing. The split mirrors the source layout.

+-------------------------------------------------+
| any MCP client over stdio:                      |
| Claude Code, an IDE, an agent, or a node script |
+-------------------------------------------------+
                          |
                          |  stdio JSON-RPC  (stdin / stdout)
                          v
+--------------------------------------------------+
|  MCProbe  -  one stdio MCP server                |
|                                                  |
|  src/index.ts       registers the probe_* tools  |
|      |  then calls the pure modules:             |
|      +--> src/schema-lint   (12 lint rules)      |
|      +--> src/fuzz          (case generator)     |
|      +--> src/conformance   (4-dimension score)  |
|      +--> src/report        (markdown renderer)  |
|      |                                           |
|      v                                           |
|  src/target-client  (outbound MCP client)        |
+--------------------------------------------------+
                          |
                          |  stdio / http JSON-RPC
                          v
              +---------------------+
              |  target MCP server  |
              +---------------------+

The top box is whatever drives MCProbe over stdio — a full host like Claude Code, or a plain node script (the scripts/*.mjs drivers and the Quickstart's audit.mjs are exactly this; no host required). It talks only to MCProbe; MCProbe's src/target-client then dials the audited server over stdio or http. The probe sits in the middle — a server to its caller, a client to its target.

Module

Role

I/O?

src/types.ts

Shared Finding, FuzzResult, DimensionScore, ConformanceReport types.

none

src/target-client.ts

Outbound MCP client, ConnectionRegistry, callTool wrapper that catches transport errors.

yes — spawns / dials

src/schema-lint.ts

The 12 lint rules. Pure: no I/O, deterministic ordering.

none

src/fuzz.ts

Case generator + runner + summarizeFuzz histogram. Generator is pure; runner threads through a caller-supplied call fn so it stays unit-testable.

none on the generator; the runner calls the target

src/conformance.ts

Per-dimension scoring + rollup. Pure.

none

src/report.ts

Pure Markdown renderer. Same input → same output every run.

none

src/index.ts

McpServer, registers the six probe_* tools, routes them to the pure modules.

yes — owns the stdio transport

The four pure modules (schema-lint, fuzz generator, conformance, report) are deliberately side-effect-free so the vitest suite can exercise them in milliseconds without spawning a target. The integration test in tests/demo-target.test.ts is the only piece that touches a live process; it is the smallest test that proves the build artifact loads over the real protocol.

Limitations

  • The four runtime dependencies are frozen. @modelcontextprotocol/sdk, ajv, ajv-formats, zod. The probe deliberately does not depend on any CLI framework, HTTP server, or transport library beyond what the SDK already exposes. Adding a runtime dependency is an explicit change to the spec.

  • The probe is a stdio MCP server, full stop. It does not expose an HTTP endpoint. Run it as a subprocess of your host.

  • The fuzzer is shallow, not adversarial. It exercises the surface documented by the tool's inputSchema; it does not attempt to discover server-side bugs that are out of band of the tool contract. The point of MCProbe is conformance, not general-purpose server fuzzing.

  • The scoring is dimension-local. A perfect score on one dimension does not rescue a failure on another. The static dimensions are subtractive; the behavioral dimensions are normalized rates. The four dimensions are weighted equally when measured.

  • Dry-run skips destructive tools. By default a fuzz run does not exercise tools annotated destructiveHint: true; they show up in the coverage summary as skipped. A target that doesn't annotate a destructive tool will still be fuzzed — annotations are the only signal MCProbe has. Pass fuzzDestructive: true to fuzz everything.

  • Behavioral scores need a real protocol round-trip. When fuzz: false is passed to probe_report, the Error Handling and Liveness & Performance dimensions are reported as "not measured" and excluded from the rollup. A "lint-only" audit can still score 100/100 on a clean server, but it cannot tell you whether the server would survive a bad input.

  • Tooling is four cores + two helpers, no more. The spec pins the surface area. Adding a probe_* tool is an explicit change to the spec.

  • The optional helpers are still required at startup. The McpServer is constructed with the tools capability only; it does not advertise resources or prompts. The probe itself is an audit tool, not a content server.

Available Tools

6 tools
probe_connectA

Open a connection to an MCP target server (stdio or HTTP) and return a connectionId plus the server's name, version, capabilities, and counts.

ParametersJSON Schema
NameRequiredDescriptionDefault
envNostdio: extra environment variables layered on top of the parent process env.
urlNohttp: URL of the target MCP server. Required when transport='http'.
argsNostdio: arguments passed to the spawned process.
commandNostdio: executable to spawn (e.g. 'node'). Required when transport='stdio'.
transportYesTransport to use. 'stdio' spawns a child process; 'http' speaks the streamable HTTP transport.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, so the agent knows this is not read-only. The description adds that it returns connectionId and server info, which is helpful. However, it does not disclose that the connection remains open and requires a subsequent probe_disconnect call, which is a significant behavioral detail beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that front-loads the main action and return information. Every word earns its place; there is no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 5 parameters and no output schema, the description does well by stating what it returns (connectionId, name, version, capabilities, counts). It misses the caveat that the connection persists and should be closed via probe_disconnect, which would make it more complete for an agent managing resources.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema covers 100% of the parameters, providing descriptions for transport, command, url, args, and env. The description adds no parameter-level detail beyond what the schema already gives, so it meets the baseline for high schema coverage without needing compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Open a connection'), names the resource ('MCP target server'), and specifies the transports (stdio or HTTP). It also states the return value (connectionId and server info), which clearly distinguishes it from siblings like probe_disconnect and probe_list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies when this tool is used—when you need to establish a connection to an MCP server. It doesn't explicitly mention alternatives or exclusions, but the sibling names and the action of 'probe_connect' make the context obvious, so it earns a 4 for clear context without explicit guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

probe_disconnectA
Idempotent

Close a single connection (by id) or all connections if id is omitted.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoConnection id returned by probe_connect. Omit to close every connection.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate idempotency and non-read-only behavior. The description adds useful context by stating the operation can target a single connection or all connections, and that the id comes from probe_connect. It does not go deeper into failure modes, but that is acceptable for this simple tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, tightly packed sentence that conveys both modes of operation without extra words. It is immediately readable and front-loaded with the core action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with no output schema and no nested objects, the description fully covers the essential usage semantics. It competently supports the agent in selecting and invoking the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%: the id parameter's meaning and omission behavior are already documented in the schema. The tool description adds no new parameter-level insight beyond what the schema provides, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Close') and resource ('connection'), and clearly distinguishes the tool from siblings by explaining it closes connections opened by probe_connect. The optional-id behavior is explicit, making the tool's purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear conditional usage: include an id to close one connection, omit it to close all. It does not explicitly name alternatives, but the sibling context (probe_connect) makes the intended pairing obvious.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

probe_fuzzA
Destructive

Generate one valid and several malformed inputs per target tool, call each, and record the outcome (ok, toolError, protocolCrash), whether malformed inputs were silently accepted, and call latency. Tools annotated destructiveHint:true are skipped by default (set fuzzDestructive to include them). Returns a coverage summary of which tools were fuzzed vs skipped.

ParametersJSON Schema
NameRequiredDescriptionDefault
maxToolsNoCap on the number of tools to fuzz. Defaults to 10.
connectionIdNoIdentifier returned by probe_connect. Defaults to the most recent connection.
fuzzDestructiveNoAlso fuzz tools annotated destructiveHint:true. Default false (the dry-run safety guard) so fuzzing an untrusted target can't trigger a destructive action.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as destructive and open-world, and the description adds concrete behavioral details: it records ok/toolError/protocolCrash, detects silently accepted malformed inputs, measures latency, and returns a coverage summary. The safety default of skipping destructive target tools unless fuzzDestructive is set is also disclosed, going beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences and front-loads the core action, making the tool's function immediately clear. The first sentence is somewhat long, but every detail earns its place and the safety sentence is essential.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even without an output schema, the description states it returns a coverage summary of fuzzed vs skipped tools, which covers the primary return value. Combined with full schema coverage and annotations, this is complete for the tool's complexity; the probe_connect prerequisite is handled by the schema's connectionId description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and all three parameters (maxTools, connectionId, fuzzDestructive) are already documented in the input schema. The description only restates fuzzDestructive's behavior and does not add new parameter-level meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action—generate one valid and several malformed inputs per target tool, call each, and record outcomes—which clearly defines the tool's purpose. It distinguishes probe_fuzz from siblings like probe_connect and probe_lint by emphasizing malformed-input generation and the resulting coverage summary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies this tool is for fuzzing target tools and explicitly explains the fuzzDestructive flag behavior. However, it does not name alternative tools or explicitly state when to choose this over a sibling, so usage guidance remains implicit rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

probe_lintA
Read-onlyIdempotent

Run the lint rules over the target's tool schemas and return a list of findings with stable codes, severities, locations, and fix hints.

ParametersJSON Schema
NameRequiredDescriptionDefault
connectionIdNoIdentifier returned by probe_connect. Defaults to the most recent connection if omitted.

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnly and idempotent behavior, so the description does not need to restate those. It adds useful details about the output structure (stable codes, severities, locations, fix hints) but does not disclose any other behavioral traits such as prerequisites, failure modes, or performance characteristics. The added context is helpful but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, focused sentence that front-loads the main action and outcome. Every phrase adds value: it specifies the target, the operation, and the return format. There is no waste or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with one optional parameter and no output schema, the description covers the necessary context: what it does and what the return value contains. Annotations handle safety and idempotency. The tool's simple nature means no additional details are needed for competent use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides 100% coverage for the only parameter (connectionId) with a clear description. The tool description adds no additional parameter information, so it does not exceed the baseline. The schema is sufficient; the description contributes nothing extra here.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: run lint rules over tool schemas and return findings. It names the specific action, resource, and output components (codes, severities, locations, fix hints), making it distinct from sibling tools like probe_fuzz or probe_list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not provide any guidance on when to use this tool versus alternatives among the sibling tools. It neither mentions exclusions nor suggests scenarios where probe_list or probe_report would be more appropriate. Usage context is only implied by the tool's function.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

probe_listA
Read-onlyIdempotent

Enumerate the target's tools (name, description, input schema) using the default or a specific connection.

ParametersJSON Schema
NameRequiredDescriptionDefault
connectionIdNoIdentifier returned by probe_connect. Defaults to the most recent connection.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, and the description adds useful context by specifying the default connection behavior and the exact data returned (name, description, input schema). This goes beyond the structured annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that conveys the core purpose, output contents, and connection handling without any filler. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a low-complexity tool with one optional parameter, clear annotations, and no output schema. The description adequately covers what the tool returns and how the connection is selected, making it complete for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With one parameter and 100% schema description coverage, the schema already documents connectionId well, including its source and default behavior. The description adds only a brief restatement of 'default or a specific connection,' which is helpful but not significantly beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'Enumerate' with a specific resource ('the target's tools') and explicitly lists the returned contents (name, description, input schema). It clearly distinguishes this from sibling tools like probe_connect, probe_lint, and probe_report by indicating that its purpose is listing tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: it should be used to enumerate tools after establishing a connection, with the connection optional and defaulting to the most recent one. It does not explicitly name alternatives or exclusions, but the usage context is sufficiently implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

probe_reportA

Run introspect + lint (and fuzz when requested) against the target, score the result on four dimensions, and return a Markdown report with the overall score, letter grade, per-dimension breakdown, findings, and fuzz table.

ParametersJSON Schema
NameRequiredDescriptionDefault
fuzzNoWhen true, run the behavioral fuzzer before scoring. Default false; only static dimensions are measured when omitted.
maxToolsNoForwarded to probe_fuzz when fuzz=true. Defaults to 10.
connectionIdNoIdentifier returned by probe_connect. Defaults to the most recent connection.
fuzzDestructiveNoForwarded to probe_fuzz when fuzz=true. Also fuzz tools annotated destructiveHint:true (default false — the dry-run safety guard).

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false and openWorldHint=true, which covers the possibility of side effects. The description offers additional context about the report format and that fuzz runs only when requested, which implies a safety guard. However, it does not explicitly warn about the potential destructive effects when fuzzDestructive=true, though the schema parameter description does. This is an adequate but not thorough disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, information-dense sentence. It front-loads the main verb and quickly enumerates all key output components. While it is a bit long, it contains no filler words and every clause adds useful information. The structure is acceptable for a tool that performs a multi-step process.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given moderate complexity (4 optional parameters, no output schema), the description adequately explains the tool's purpose and the content of its returned report. It covers the key aspects of what the report includes and mentions the optional fuzz component. However, it could be more explicit about preconditions like needing a connection (connectionId) and about the four dimensions being scored, but these are partially covered by schema and context. Overall, it is reasonably complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema covers 100% of parameters with descriptions, so the baseline is 3. The description does not add any parameter-specific semantics beyond what the schema already provides, such as the meaning of fuzz, maxTools, connectionId, or fuzzDestructive. It only indirectly references fuzz via 'when requested', but this adds no new meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's composite function: running introspect + lint (and optionally fuzz), scoring results on four dimensions, and returning a Markdown report with specific components (overall score, letter grade, breakdown, findings, fuzz table). The verb 'Run... score... return' is specific, and the resource is the target. This distinguishes it from siblings like probe_lint and probe_fuzz, which are individual operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use this tool: when a comprehensive scored report is needed rather than just lint or fuzz. However, it does not explicitly say 'use this instead of probe_lint when you need scoring' or mention any exclusions. The guidance is clear from the context but lacks explicit alternative differentiation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 6 tool updatesv0.1.0
    • First observedprobe_connect
    • First observedprobe_disconnect
    • First observedprobe_fuzz
    • First observedprobe_lint
    • First observedprobe_list
    • First observedprobe_report

TDQS

A4.2/5.0
Disambiguation5/5

Each tool has a clearly distinct role: connect opens connections, list enumerates tools, lint validates schemas, fuzz tests inputs, report aggregates results, and disconnect closes connections. Even though report includes lint and fuzz, its purpose as a high-level summary is unambiguous.

Naming Consistency5/5

All tools follow a consistent 'probe_' prefix with a verb-noun structure (probe_connect, probe_lint, probe_fuzz, probe_report, probe_list, probe_disconnect). No mixing of conventions or vague names.

Tool Count5/5

Six tools is well-scoped for a server that probes MCP targets. Each tool covers a necessary step in the workflow without redundancy or bloat.

Completeness5/5

The tool set covers the full probe lifecycle: connect, enumerate, lint, fuzz, report, and disconnect. There are no obvious missing operations for the stated purpose of probing and assessing MCP servers.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    A stdio MCP server that audits other MCP servers over the live protocol. It connects to any MCP target (stdio or HTTP), lints every tool's schema for agent-usability, then actually calls the tools with deliberately broken inputs to see how the server handles them, and returns a 0–100 conformance score with a per-dimension breakdown rendered as Markdown.
    6
    6
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Passive security scanner that audits a running MCP server against the OWASP MCP Top 10 and grades it A-F. Read-only static analysis of the advertised tools, prompts and resources with console/JSON/SARIF output, and it also runs as an MCP server itself.
    85
    MIT
  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    An MCP server that validates tool calls against JSON Schema, performs deterministic repair, redacts secrets, and maintains a hash-chained audit ledger.
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/actions-marketplace-validations/alitiknazoglu_mcprobe'

If you have feedback or need assistance with the MCP directory API, please join our Discord server