Skip to main content
Glama

mcp-authprobe

CI License: MIT

Active authorization testing for remote MCP servers you own.

Passive scanners read what a remote Model Context Protocol server announces: its OAuth metadata, its TLS setup, its tool descriptions. Some properties can only be confirmed by actually exercising the authorization server: does it really rotate refresh tokens, does it really refuse a redirect URI it never registered, does it slow down repeated failures?

mcp-authprobe runs those active checks, against servers whose ownership you have proven, and reports the results as JSON, SARIF and Markdown.

Status: 0.1.x. All ten checks are available behind an ownership proof: OAuth discovery, refresh token rotation and replay, redirect URI strictness, token endpoint throttling, and consent CSRF (in a real browser). It works as a CLI, with an interactive login that creates the test grant, and as an MCP server so an AI assistant can run the audit. See Roadmap.

Only test servers you own or are explicitly authorized to test. Active checks change state on the target. The tool enforces an ownership proof before running them, but responsibility stays with the operator.

Contents

Related MCP server: Pentest MCP

Why another scanner?

Good tools already exist, and this one is meant to sit next to them, not replace them:

Tool

Focus

Overlap with mcp-authprobe

mcp-posture

Passive posture of remote servers: OAuth metadata per RFC, transport, tool poisoning, rug pulls

None by design: it never sends state-changing requests. Run it first.

MCPJam OAuth conformance

Runs real OAuth flows and checks conformance, with a few negative checks

Basic redirect URI rejection. No refresh token replay, throttling or consent CSRF.

Cisco mcp-scanner, Snyk agent-scan

Malicious tools, configs, local servers

None.

mcp-authprobe focuses on what only an active, authorized test can confirm, and uses check IDs (MAP-…) that do not clash with mcp-posture's (MCPP-…), so both reports can be read side by side.

Install

Requires Node.js 22.19 or later.

# run without installing
npx mcp-authprobe --help

# or install globally
npm install -g mcp-authprobe

Releases are published from GitHub Actions with npm trusted publishing; check the provenance on the package page before installing a security tool.

From source:

git clone https://github.com/Enigmacker/mcp-authprobe.git
cd mcp-authprobe
npm ci
npm run build
node dist/cli.js --help

Quick start

# 1. Create a secret and the proof to publish for your MCP host
mcp-authprobe ownership init mcp.example.com

# 2. Publish the proof (well-known file or DNS TXT), then keep the secret in your environment
export MCP_AUTHPROBE_SECRET='…'

# 3. Check the proof is visible
mcp-authprobe ownership verify mcp.example.com

# 4. Scan
mcp-authprobe scan https://mcp.example.com/mcp --sarif results.sarif --markdown summary.md

# 5. Log in once with a dedicated test account to create a test grant
mcp-authprobe login https://mcp.example.com/mcp --out ./test-grant.json

# 6. Full scan, including the refresh token checks
mcp-authprobe scan https://mcp.example.com/mcp --credentials-file ./test-grant.json

Without a valid proof the scan still runs discovery (the same read-only requests any MCP client sends before logging in), and every active check is reported as skipped.

For a local lab on your own machine:

mcp-authprobe scan http://127.0.0.1:8080/mcp --allow-private

Loopback targets with --allow-private do not need a proof.

Ownership proof

Active checks register clients, rotate tokens and send failing requests. To make sure they only ever hit servers whose operator agreed to it, the scanner requires a proof for every host it would contact: the MCP server host and, when it differs, the authorization server host.

The proof is a hash, bound to the host, of a secret that only you hold:

mcp-authprobe-verification=sha256:<hex(sha256("<host>:<secret>"))>

Publish it in one of two places:

Method

Where

Value

Well-known file

https://<host>/.well-known/mcp-authprobe.txt

one line per proof; other lines are ignored

DNS TXT

_mcp-authprobe.<host>

the proof string

Design choices:

  • The secret never leaves your machine. Only its hash is published, so a proof found in the wild cannot be reused by someone else to scan your server.

  • Proofs are host-bound. A proof for mcp.example.com is useless for any other host.

  • The secret is read from MCP_AUTHPROBE_SECRET or --secret-file, never from the command line, so it does not land in shell history or process listings.

  • Hosted authorization servers. If your authorization server is a third-party service on its own domain, you can only publish a proof if you control that domain (for example a custom domain). Check the provider's penetration testing policy before running active checks against it.

You can remove the proof as soon as you are done testing.

Refresh token checks

MCP clients are usually public clients, so OAuth 2.1 requires their refresh tokens to be rotated, and RFC 9700 recommends revoking the whole token family when an old one is reused. These properties cannot be read from metadata; they have to be exercised.

The checks need a test grant: a client and a refresh token obtained by logging in to your own server with a dedicated test account.

The easy way is mcp-authprobe login (see Interactive login), which writes the file for you. You can also write it by hand, readable only by you (chmod 600):

{
  "client_id": "your-test-client-id",
  "refresh_token": "the-refresh-token",
  "client_secret": "only-for-confidential-clients",
  "token_endpoint_auth_method": "none"
}

token_endpoint_auth_method is none (default for public clients), client_secret_post (default when a secret is present) or client_secret_basic.

The scan sends at most three refresh_token requests to the token endpoint found by discovery:

Step

Request

Expected on a compliant server

Check

1

Refresh with the supplied token

New access token and a new refresh token

MAP-RTK01

2

Refresh again with the token from step 1's input (already used)

Rejected, typically invalid_grant

MAP-RTK02

3

Refresh with the newest token (from step 1's output)

Rejected: reuse revoked the whole family

MAP-RTK03

Important:

  • The grant is consumed. On a compliant server, step 3 revokes it. Never use a grant you still need.

  • If tokens are not rotated, MAP-RTK01 fails and the two replay checks are reported as not applicable.

  • A throttled or unexpected response is reported as error (inconclusive), never as a pass.

  • Token values never appear in output or reports; evidence only shows status codes and OAuth error codes.

Interactive login

mcp-authprobe login https://mcp.example.com/mcp --out ./test-grant.json

login behaves like a careful native MCP client (RFC 8252):

  • It registers a client through dynamic client registration, with a loopback redirect URI on 127.0.0.1 and a random port.

  • It opens your browser on the discovered authorization endpoint only (or prints the URL with --no-browser). Log in with your test account.

  • The loopback listener accepts a single GET /callback carrying the expected state, and echoes nothing back.

  • It uses PKCE S256, a random state, the RFC 8707 resource, and checks the RFC 9207 iss parameter against the discovered issuer.

  • It writes the grant with mode 600, never through a symbolic link, and never over an existing file unless you pass --force. Tokens are never printed.

  • The grant records the target and token endpoint it belongs to. A scan of any other target, or a server announcing another token endpoint, will not use it.

  • login itself does not require an ownership proof: it only does what any MCP client does when you connect it (one registration, your own browser login, one code exchange). Only the extra MAP-RDR03 probe requires the proof.

  • If login fails, the client it registered is deleted when the server allows it.

MAP-RDR03 is observed during login, because it needs a fresh authorization code. When ownership of every contacted host is proven, login first presents the code with a different redirect_uri, which a compliant token endpoint must refuse, then exchanges it normally. The result is stored in the grant file and reported by the next scan of the same target. Use --no-probe to skip it.

Some strict servers invalidate a code after any failed attempt. That is acceptable behaviour: MAP-RDR03 passes, and login asks you to run it again with --no-probe to obtain the grant.

Redirect URI checks

If an authorization server redirects to a URI the client never registered, authorization codes can end up with an attacker. OAuth 2.1 requires exact string matching. These checks need dynamic client registration on your server; no test grant and no login are required.

How they work:

  1. The scanner registers a temporary client whose only redirect URI is https://client.mcp-authprobe.invalid/callback.

  2. It sends a baseline authorization request with that registered URI (PKCE S256, random state, RFC 8707 resource), then one request per variant, and compares the answers. Redirects are never followed.

  3. It deletes every client it created (RFC 7592). Clients it could not delete are listed in the report, named mcp-authprobe test client (safe to delete).

Check

What is sent

Fails when

MAP-RDR01

A completely different host

The server redirects to it

MAP-RDR02

7 near misses: extra path segment, trailing slash, added query, different port, subdomain, userinfo trick, http downgrade

The server redirects to any of them

MAP-RDR04

Registrations with plain HTTP on a non-loopback host, javascript:, data:, and a fragment

The registration endpoint accepts any of them

Safety by design: every host used lives under the reserved .invalid top-level domain (RFC 2606), which can never resolve. Even a vulnerable server could not deliver a code anywhere.

Reading the results: a variant answered exactly like the baseline (for example both redirected to the login page) is reported as inconclusive (error), never as a pass, because some servers only check redirect_uri after the user logs in. MAP-RDR03 (token endpoint enforcement) is observed during interactive login.

Throttling check

Without rate limiting, refresh tokens, authorization codes and client secrets can be guessed at line speed. MAP-THR01 checks that the token endpoint slows down repeated failures, with strict bounds:

  • It sends 10 token requests by default (--throttle-attempts, between 5 and 20, hard-capped), one at a time.

  • Each request carries a freshly generated random refresh token that cannot be valid. Nothing is guessed, and user passwords and login forms are never involved.

  • It uses your test client when a grant is supplied (your real refresh token is not sent), otherwise a temporary client that is deleted afterwards.

  • It stops at the first sign of throttling: HTTP 429, a Retry-After header, or an OAuth slow_down / temporarily_unavailable error.

  • It runs last in a scan, so a throttled token endpoint cannot disturb the other checks.

A failure means no throttling was seen within the cap. Your limit may simply be higher than 20; the finding asks you to confirm that one exists.

If a third-party website can submit your consent page on behalf of a logged-in user, it can make them grant access without noticing (the confused deputy described in the MCP security best practices). MAP-CSR01 checks that the consent decision is protected, in a real browser with your test account:

npx -p mcp-authprobe -p playwright-core mcp-authprobe consent-check https://mcp.example.com/mcp
  1. The ownership of every contacted host must be proven first.

  2. It registers a temporary client and opens your installed Chrome (or --browser msedge, or --browser-path <executable>) on the authorization page. No browser is downloaded; playwright-core is an optional dependency used only by this command.

  3. You log in with the test account. When the consent page is shown, do not click anything: go back to the terminal and press Enter.

  4. The tool reads the consent form and the cookie attributes as the browser sees them, closes the browser, then sends at most three form submissions with the session cookies and a foreign Origin:

    • without any anti-CSRF field: must be refused;

    • with the anti-CSRF field altered: must be refused;

    • the untouched form: informational, shows whether the server also checks Origin.

  5. It deletes the temporary client. The loopback redirect URI is served by the tool itself, so even an accidental approval delivers the code nowhere else.

The check fails when consent is granted without a valid anti-CSRF token. The finding also reports whether the session cookies are SameSite=Lax/Strict, which blocks the attack from other sites in modern browsers, but not from same-site subdomains or older clients. It is not available in MCP server mode, because it needs you to log in.

Use it from an MCP client

mcp-authprobe mcp runs the same engine as an MCP server over stdio, so an AI assistant in any MCP client can audit your servers for you.

Add it to your client's MCP configuration (most clients use this mcpServers format):

{
  "mcpServers": {
    "mcp-authprobe": {
      "command": "npx",
      "args": ["-y", "mcp-authprobe", "mcp"],
      "env": {
        "MCP_AUTHPROBE_SECRET_FILE": "/home/you/.config/mcp-authprobe/secret",
        "MCP_AUTHPROBE_CREDENTIALS_FILE": "/home/you/.config/mcp-authprobe/test-grant.json"
      }
    }
  }
}

The server is also listed in the official MCP Registry as io.github.Enigmacker/mcp-authprobe, so registry-aware clients can install it directly.

From a source checkout, use "command": "node" with "args": ["/path/to/mcp-authprobe/dist/cli.js", "mcp"].

Tool

What it does

Annotations

list_checks

Lists the catalogue

read-only

explain_check

Explains one check

read-only

ownership_proof

Returns the proof to publish for a host (never the secret)

read-only

verify_ownership

Checks that the proof is published

read-only, open world

scan

Runs discovery and the active checks; returns a Markdown summary and the full report as structured content

destructive, open world

The server is built so that the assistant, or a prompt injection reaching it, cannot widen what the scanner may do:

  • Everything sensitive is set by you in the configuration, never by tool arguments: the ownership secret, the test grant, and private-address access. The scan tool takes a URL and nothing else.

  • scan is annotated as destructive, so well-behaved clients ask for your confirmation before each call. It consumes the test grant and registers temporary clients.

  • Only https targets are accepted; plain http only for loopback or private-address labs with MCP_AUTHPROBE_ALLOW_PRIVATE=1. URLs with embedded credentials are refused, and only one scan runs at a time.

  • Loopback targets still need a proof in MCP mode, unless you list their origin in MCP_AUTHPROBE_LAB_ORIGINS. An assistant cannot point active requests at arbitrary local services.

  • The test grant is only used if it names the scanned target (grants created by login do), so it cannot be spent on another server.

  • Reports are marked as data: every scan result ends with a notice that server-controlled text in it must not be treated as instructions.

Environment variable

Purpose

MCP_AUTHPROBE_SECRET or MCP_AUTHPROBE_SECRET_FILE

Ownership secret (prefer the file)

MCP_AUTHPROBE_CREDENTIALS_FILE

Test grant for the refresh token checks

MCP_AUTHPROBE_ALLOW_PRIVATE=1

Allow loopback and private targets (local labs only)

MCP_AUTHPROBE_LAB_ORIGINS

Comma-separated lab origins (e.g. http://127.0.0.1:8080) exempt from the ownership proof

MCP_AUTHPROBE_TIMEOUT_MS

Per-request timeout

What it checks

mcp-authprobe checks list prints the catalogue, and mcp-authprobe checks show <ID> explains a check: why it matters, how to fix it, and references. IDs are stable and never reused.

ID

Mode

Status

Check

MAP-DSC01

passive

available

Authorization endpoints are discoverable (401 challenge, RFC 9728, RFC 8414)

MAP-RTK01

active

available

Refresh tokens for public clients are rotated

MAP-RTK02

active

available

A rotated refresh token cannot be replayed

MAP-RTK03

active

available

Refresh token replay revokes the token family

MAP-RDR01

active

available

Unregistered redirect_uri is refused at the authorization endpoint

MAP-RDR02

active

available

redirect_uri matching is exact, not prefix or pattern based

MAP-RDR03

active

available (via login)

Token endpoint enforces the redirect_uri used at authorization

MAP-RDR04

active

available

Dynamic client registration refuses unsafe redirect URIs

MAP-THR01

active

available

Repeated failed token requests are throttled (5 to 20 sequential requests with random values)

MAP-CSR01

active

available (via consent-check)

Consent decision is protected against CSRF

Families: DSC discovery, RTK refresh tokens, RDR redirect URIs, THR throttling, CSR consent CSRF.

Reports and exit codes

Option

Output

(always)

Human-readable table on stdout

--json <file>

Full report, schema mcp-authprobe/report/v1

--sarif <file>

SARIF 2.1.0, for GitHub code scanning; only failing checks become results

--markdown <file>

Table for a pull request comment or a CI job summary

--credentials-file <file>

Test grant for the refresh token checks (input)

Exit code

Meaning

0

No failing check at or above --fail-on (default high)

1

At least one failing check at or above --fail-on (or ownership verify failed)

2

Usage error

3

A check errored or the target was unreachable

All server-controlled text is neutralized before it reaches a report: terminal escape sequences, bidi overrides and invisible characters are escaped, and token-shaped values are redacted.

CI usage

- uses: actions/setup-node@v4
  with:
    node-version: 22
- run: npx mcp-authprobe scan "$MCP_URL" --sarif results.sarif --markdown summary.md
  env:
    MCP_URL: https://mcp.example.com/mcp
    MCP_AUTHPROBE_SECRET: ${{ secrets.MCP_AUTHPROBE_SECRET }}
- run: cat summary.md >> "$GITHUB_STEP_SUMMARY"
  if: always()
- uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: results.sarif

Run active scans against a staging environment rather than production whenever you can.

Safety of the scanner

The scanner talks to servers that may be hostile, and it may be driven by an AI agent. It protects both you and third parties:

  • Ownership gate: no active request without a valid proof for every contacted host (the only exception is login, which behaves like an ordinary MCP client; see above).

  • HTTPS only: every request, including endpoints announced by a server's metadata, must use HTTPS. Plain HTTP is accepted only for loopback or private-address labs with --allow-private, so tokens and secrets never travel in cleartext over the internet.

  • Inconclusive is never a pass: rate limits (429, Retry-After) and server errors (5xx) make a check report error, never pass.

  • SSRF protection: loopback, private, link-local, CGNAT, multicast, reserved and cloud-metadata addresses are refused at connect time, after DNS resolution, unless --allow-private is passed.

  • No automatic redirects: every redirect is inspected, never followed blindly.

  • Bounded resources: per-request timeouts, response bodies capped at 1 MiB, no compression requested.

  • Secrets stay secret: tokens and the ownership secret are never printed, and are redacted from every report.

  • No telemetry.

Roadmap

0.1.0

  • Refresh token checks (RTK01-03) done, from a test grant file.

  • Interactive login creating the test grant done.

  • Redirect URI checks (RDR01, RDR02, RDR04) done.

  • MAP-RDR03 done, observed during login.

  • Throttling check (THR01) done.

  • MCP server mode (stdio) done.

  • npm release done.

0.2.0

  • Consent CSRF check (CSR01), driven through a browser session done.

  • Optional integration with mcp-posture: run it alongside, or import its JSON report, and merge both into one report where active results confirm or refute what the metadata announces.

Development

npm ci
npm run typecheck
npm test          # unit and integration tests against a local fixture server
npm run build
npm run check     # all of the above

Tests never leave the machine: integration tests run against a fixture server bound to 127.0.0.1.

Contributing and security

License

MIT © 2026 Enigmacker

Available Tools

5 tools
explain_checkExplain a checkB
Read-only

Explain one check: why it matters, how to fix a failure, and references.

NameRequiredDescriptionDefault
idYes

TDQS

B3.3/5.0
Behavior3/5

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

The annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds useful context about what the explanation contains: relevance, remediation, and references. However, it does not disclose lookup failure behavior, ID source requirements, or other operational details beyond the output content.

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 with no wasted words. It communicates the action and the key outputs efficiently.

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

Completeness3/5

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

For a simple read-only tool with one parameter, the description covers the purpose and general output content. However, with no output schema and zero schema description coverage for the required id parameter, it should say more about the expected ID format or source and any lookup failure behavior. It is minimally adequate but has clear gaps.

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

Parameters2/5

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

There is one required parameter, id, and schema description coverage is 0%. The schema supplies a regex pattern but no semantic description. The description only implies that the parameter identifies 'one check' and does not explain the ID format, where to obtain it, or what happens if it is invalid.

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

Purpose4/5

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

The description states a specific verb and resource: explain one check. It also outlines the content of the explanation: why the check matters, how to fix a failure, and references. It implicitly distinguishes itself from list_checks by focusing on a single check, but it does not explicitly contrast with sibling tools.

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?

Usage is implied: call this when you need an explanation for a specific check. There is no explicit guidance on when to use it versus list_checks or ownership-related siblings, nor any stated prerequisites such as obtaining the check ID first. The guidance is adequate but minimal.

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

list_checksList checksA
Read-only

List every check with its ID, severity, mode (active or passive) and availability.

NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior4/5

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

The description is highly valuable because it explicitly states the data elements (ID, severity, mode, availability) returned by the function. This adds crucial behavioral context regarding the output format that annotations alone do not 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 extremely concise, using a single, declarative sentence to define the tool's entire function and scope without any unnecessary words or fluff.

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?

Given that there are no input parameters, providing a complete list of the attributes returned by the check is sufficient to make the tool's output predictable and useful for an AI agent.

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

Parameters4/5

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

Since the input schema is empty (0 parameters), the baseline for this dimension is high. The description adds no required input semantics, and the schema coverage is 100% as it requires no parameters.

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

Purpose4/5

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

The description clearly identifies the resource being manipulated ('check') and the action being taken ('List'), which is clear and distinguishable from sibling tools like 'scan' or 'explain_check'. It successfully defines the scope of the listing.

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 should be used when a general overview of checks is needed but does not provide explicit instructions on when to use it over a specific alternative like 'explain_check' which offers deeper detail.

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

ownership_proofOwnership proof to publishA
Read-only

Return the ownership proof the user must publish for a host (well-known file or DNS TXT record) before active tests can run. The secret itself is never returned.

NameRequiredDescriptionDefault
hostYes

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnlyHint=true, openWorldHint=false), and the description adds a genuinely useful disclosure beyond them: the secret itself is never returned. It also enumerates the two acceptable publication mechanisms. It omits whether proofs expire or are regenerated per host, which would complete the behavioral picture.

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?

Two sentences, both load-bearing, with the action and its prerequisite front-loaded and the security caveat trailing. No filler or redundancy.

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

Completeness3/5

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

There is no output schema, so the description must describe what comes back, and it only says the proof is for a well-known file or DNS TXT record. It does not indicate whether the response returns a record name and value pair, a URL, or a formatted instruction block — a real gap for a tool whose entire output is the payload the user must publish.

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 0%, so the description carries the burden for the single 'host' parameter. It says the proof is 'for a host', clarifying intent, but never specifies whether host is a bare domain, FQDN, or must already be registered — leaving the pattern-only schema to do the rest.

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

Purpose4/5

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

States a specific verb and resource ('Return the ownership proof') scoped to a host, and names the two publication formats (well-known file or DNS TXT record). It is clear this is the retrieval step of an ownership flow rather than the verification step, though it never names verify_ownership explicitly.

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 phrase 'before active tests can run' gives a concrete precondition that tells the agent when this tool is needed. It stops short of naming verify_ownership as the follow-up step or stating any exclusions, so routing is implied rather than explicit.

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

scanScan a remote MCP serverA
Destructive

Run discovery and, on hosts with a valid ownership proof, the active authorization tests against a remote MCP server URL. Active tests register and delete temporary OAuth clients and CONSUME the configured test grant. Only use on servers the user owns or is authorized to test, after the user confirmed.

NameRequiredDescriptionDefault
urlYesThe MCP endpoint URL, e.g. https://mcp.example.com/mcp

TDQS

A4.4/5.0
Behavior5/5

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

Annotations already flag destructiveHint=true and openWorldHint=true, but the description goes well beyond them by disclosing the concrete side effects: temporary OAuth clients are registered and deleted, and the configured test grant is consumed. It also states the ownership-proof precondition and the human-confirmation requirement, which no annotation conveys.

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?

Three dense sentences: capability first, side effects second, safety gate last — a natural decision order for an agent. Nothing is repeated from the schema or annotations verbatim and no sentence is 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?

For a single-parameter destructive tool with no output schema, the description covers effects, preconditions, and authorization. What it leaves out is what a successful scan returns (findings, check results, references to list_checks/explain_check), which would help an agent plan the follow-up call.

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?

Only one parameter (url) with 100% schema coverage and an inline example, so the schema carries the semantics. The description reinforces that the target must be a remote MCP server URL, but adds no format or validation detail 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?

States a specific verb (discovery scan + active authorization tests) against a specific resource (a remote MCP server URL), and distinguishes the two modes of operation (discovery always, active tests only with a valid ownership proof). An agent can tell what it does and under what condition without opening the schema.

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?

Explicitly restricts use to servers the user owns or is authorized to test and requires prior user confirmation, which is exactly the when-to-use gating an agent needs. It also implies the ownership_proof/verify_ownership prerequisite via 'on hosts with a valid ownership proof,' but never names those sibling tools, so the routing is inferred rather than stated.

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

verify_ownershipVerify ownership proofB
Read-only

Check whether the ownership proof for a host is published and matches the configured secret.

NameRequiredDescriptionDefault
hostYes

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety and network-reach profile is covered. The description adds useful context beyond that — it fetches a published proof and compares it against a configured secret — but says nothing about behavior on network failure, missing configuration, or whether a successful check is cached.

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?

A single front-loaded sentence with the resource and both check conditions stated up front. No filler, nothing to trim.

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

Completeness3/5

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

No output schema exists, so the description should convey what a result looks like; 'check whether' implies a boolean verdict but leaves ambiguity — is it a boolean, a status enum, or details on which of the two conditions failed? For a one-parameter verification tool this is about the minimum an agent needs to call it, but the return shape and failure semantics remain unspecified.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate, but it only echoes 'for a host'. The schema carries the pattern and length constraints but no human-readable meaning; the description adds nothing about whether host is a bare domain, a URL, or how it relates to the proof lookup location.

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

Purpose4/5

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

States a specific verb ('Check whether') and resource ('the ownership proof for a host') with the two concrete conditions evaluated: published and matching the configured secret. This is distinguishable from the sibling ownership_proof (which presumably produces a proof rather than verifying it), though the description does not name that sibling explicitly.

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?

Usage is only implied: the phrasing suggests a post-setup verification step after a proof has been published. It never says when to call this versus ownership_proof, nor states prerequisites such as a configured secret or DNS/TXT publication having been done.

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.

  1. 5 tool updatesv0.1.0
    • First observedexplain_check
    • First observedlist_checks
    • First observedownership_proof
    • First observedscan
    • First observedverify_ownership

TDQS

A3.9/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: listing checks, explaining a check, retrieving an ownership proof, verifying ownership, and running a scan. The two ownership-related tools are complementary rather than overlapping—one returns the proof to publish, the other verifies it.

Naming Consistency4/5

Most names follow a verb_noun or verb_object pattern (list_checks, explain_check, verify_ownership), but ownership_proof is a noun phrase and scan is a bare verb. The minor deviations are still readable and predictable.

Tool Count5/5

Five tools is well-scoped for an auth-probing MCP server. Each tool earns its place in the workflow: discovery, explanation, proof generation, verification, and scanning.

Completeness4/5

The surface covers the full ownership-proof and scan lifecycle. Minor gaps exist, such as no explicit tool to retrieve past scan results or filter checks, but core workflows are covered.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    A specialized testing harness that enables AI assistants to thoroughly test other MCP servers by connecting to them, discovering their tools/resources/prompts, executing test calls, and performing end-to-end validation with LLM integration.
    14
    4
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI clients to drive professional penetration-testing workflows—subdomain enumeration, host probing, content fuzzing, vulnerability scanning, brute-force, traffic capture, and exploitation sweeps—through a single MCP interface with stdio, Streamable HTTP, and legacy SSE transports plus bearer/OIDC auth. It also records engagement artifacts and generates client-ready reports with scope handling, cutting manual pentest administration.
    298 npm
    GPL 3.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Lets any MCP client, such as Claude, browse attack suites and probes, run a full assurance assessment with all reports written out, send custom prompts or multi-turn histories and get leak, PII and refusal checks back for adaptive attacks, and read findings from an earlier assessment. This enables agent-driven red-teaming of a chatbot, RAG app or AI agent without leaving the chat client.
    MIT