Skip to main content
Glama
furkan708

Mcpify

mcpify

Tests CI CodeQL PyPI PyPI Downloads Python License MCP Registry Dependencies

English | TΓΌrkΓ§e

Turn any OpenAPI REST API into an MCP server β€” so Claude Code, Cursor, and every other MCP client can call your API directly. One command, zero runtime dependencies:

mcpify serve https://your-company.com/openapi.json
# try it right now, nothing installed (uvx pulls from PyPI on demand)
uvx --from mcpify-openapi mcpify list examples/petstore.json --cost

Focused, production-ready, CLI-first: one job (OpenAPI β†’ MCP). Everything else β€” governance, credentials, token economics, operations β€” is opt-in and stays out of the way until you need it:

  • Safe for agents by default β€” lazy context budget (--lazy), secret masking (--redact), blast-radius limits (--read-only, per-token RBAC)

  • Ready for real deployments β€” stdio + HTTP/SSE, OAuth2 and split read/write credentials, health probes, audit trail, metrics, multi-API serving, hot reload

  • Proven, not promised β€” 520 tests across twenty-eight suites, a hostile-spec corpus, live-CI checks, zero runtime dependencies

Why you'll like it

From spec to server

  • 60 seconds to working β€” point it at any OpenAPI 3.x spec (file or URL)

  • Every operation becomes a first-class MCP tool β€” input schemas are generated from parameters + requestBody, internal $refs are resolved

  • Spec versions diffed from the tool view β€” mcpify diff old.yaml new.yaml reports added/removed/changed operations with per-change breaking verdicts and a migration guide; --fail-on-breaking is a CI gate

  • mcpify doctor β€” tells you if your spec is agent-friendly before you ship: missing operationIds, missing summaries, instruction-like tool text, overlong descriptions; --probe dials the API once β€” with your real credential (--auth-env) when you want auth proven end-to-end, and --fail-on-http-error for a strict CI gate

  • mcpify try / mcpify mock / mcpify output-server β€” call the tools without an agent client, serve a schema-shaped fake API for CI, or bake a serve command into a shareable script

Credentials & policy

  • Credentials never touch the spec or the model β€” pulled from your environment at call time; the spec's own security declarations pick the flags (bearer, basic, header, query)

  • OAuth2 client-credentials built in β€” tokens are fetched, cached, refreshed and re-fetched on a mid-flight 401 (RFC 6749, stdlib only); --write-oauth2-* gives non-GET calls a second client identity so reads and writes authenticate as different clients

  • Least-privilege by default β€” --write-auth-env splits the static credential (reads on your read key, writes on a dedicated key), --read-only filters the surface, --deny/--allow hides mutating GETs, per-token RBAC gives each bearer token its own allow/deny scopes

  • --redact password,token β€” values whose key names a secret are masked with *** at every level of every response (error bodies included, case-insensitive); the model never sees them

  • Audit trail without content exposure β€” one JSON line per call: tool, API, status, latency, an argument fingerprint (never raw arguments); --plugin loads your Python module for auth/request/result hooks

Token economics

  • See the bill before serving β€” mcpify list --cost prices the surface (~4 chars/token): what every agent pays in EVERY tools/list; multi-API configs get per-API and total prices in one run

  • --fields id,event β€” response projection that selects at every level: selected keys keep their value, non-selected containers stay transparent, emptied containers drop. Live weather.gov: 350 alerts in full inside the budget that previously truncated at ~189

  • Valid truncation β€” oversized responses are cut along JSON structure with an explicit "truncated": true marker, never mid-document

  • --lazy search-then-call β€” cut api.weather.gov's listing by 95.5%; search results now show what pulling each full schema would cost, so the agent pulls only what it needs

  • [tool-text] overrides β€” doctor flags model-facing instruction-like descriptions; you replace them per tool in config

Operations

  • Two transports, one tool surface β€” stdio for local agents; serve --http 8080 speaks MCP Streamable HTTP (SSE responses for clients that ask, JSON otherwise) so a whole team shares one server, with optional bearer tokens

  • Several APIs, one MCP server β€” [apis.NAME] sections in .mcpify.toml: per-API auth, caching, retries, filters and rate limits; collision-safe renames; aggregated health; mcpify status probes every API in parallel

  • Upstream courtesy built in β€” ETag-aware caching, idempotent-only retries (502/503/504), --wait-on-429 honors Retry-After, --rate-limit RPS caps requests/second (per upstream in multi-API, retries included)

  • Observability, opt-in only β€” Prometheus --metrics (call counters, latencies, cache, health β€” plus projection/redaction counters when those run), --otel spans, --reload hot swap, mcpify ui local dashboard

  • Host it yourself for free β€” docker-compose with automatic-HTTPS Caddy plus a hardened systemd unit: Self-hosting guide

  • Zero runtime dependencies β€” the entire tree is auditable stdlib Python; YAML specs need an optional pip install 'mcpify[yaml]'

Related MCP server: @spec2tools/stdio-mcp

Quick start

# install (installs the `mcpify` command)
pipx install mcpify-openapi

# run without installing (uvx β€” pulls from PyPI on demand)
uvx --from mcpify-openapi mcpify list ./openapi.json --read-only

# first time? the wizard writes a config for you
uvx --from mcpify-openapi mcpify init

# ...as a container (GHCR, published on every release)
docker run -i ghcr.io/furkan708/mcpify:latest serve ./openapi.json --read-only

# ...or from source
git clone https://github.com/furkan708/mcpify.git
cd mcpify && pip install .

# 1. preview the tools that will be generated (add --cost for the context price)
mcpify list examples/petstore.json

# 2. validate the spec is agent-friendly (+ --probe for a live pre-flight)
mcpify doctor examples/petstore.json

# 3. serve it over MCP
mcpify serve examples/petstore.json --base-url https://petstore.example.com/v1

# 4. no agent client at hand? try the tools in your terminal
mcpify try examples/petstore.json --base-url https://petstore.example.com/v1

# 5. or share it over HTTP with the whole team
mcpify serve examples/petstore.json --http 8080 --http-token $SHARED_TOKEN

With authentication

# Bearer token read from the environment (never hardcoded)
export PETSTORE_KEY="sk-..."
mcpify serve petstore.json \
  --base-url https://petstore.example.com/v1 \
  --auth-env PETSTORE_KEY \
  --auth-style bearer \            # optional: auto-detected from the spec
  --read-only

No explicit style needed in the common case β€” the spec's security declarations pick bearer/basic/header/query (with the right name) for you. For HTTP Basic, the env variable holds username:password: --auth-style basic --auth-env CREDS.

Flag

Meaning

--auth-env VAR

environment variable holding the credential

--auth-style bearer|basic|header|query

how it is sent (default: auto-detected from the spec)

--auth-name NAME

header / query name for non-bearer styles (e.g. X-API-Key)

With OAuth2 (client credentials)

For APIs behind an OAuth2 identity provider (RFC 6749 Β§4.4). Credentials live in the environment; the access token is fetched, cached until its expires_in, refreshed transparently, and re-fetched automatically once if the API answers 401 mid-flight:

export OAUTH2_CLIENT_ID="..."
export OAUTH2_CLIENT_SECRET="..."
mcpify serve api.json \
  --oauth2-token-url https://idp.example.com/oauth2/token \
  --oauth2-client-id-env OAUTH2_CLIENT_ID \
  --oauth2-client-secret-env OAUTH2_CLIENT_SECRET \
  --oauth2-scope "read write"        # optional; --oauth2-client-auth body for token endpoints that reject Basic

Split write identities too: --write-oauth2-token-url (+ client/scope flags) runs a second client-credentials flow for non-GET calls β€” reads authenticate as the read client, writes as the write client, each with its own token cache and the same 401 self-heal. Mutually exclusive with --write-auth-env (pick one credential kind for writes).

Multiple APIs in one server

Put several OpenAPI documents in one config and serve them as a single tool surface β€” no gateway, no per-API process:

# .mcpify.toml
[apis.catalog]
spec = "https://shop.example.com/openapi.json"
auth-env = "CATALOG_TOKEN"          # per-API credential
cache-ttl = 60
rate-limit = 5                      # per-API courtesy throttle (req/s)
redact = "password,client_secret"   # per-API response masking

[apis.crm]
spec = "./crm.yaml"
read-only = true                    # per-API policy
base-url = "https://crm.internal/v2"
fields = "id,name"                  # per-API response projection

[apis.weather]
spec = "https://api.weather.gov/openapi.json"
timeout = 10

Surface switches (--lazy, --enable-preview, --http, --format) are server-wide flags; credentials, policies, caching and retries are per-API.

mcpify list --cost      # preview every API and price each surface
mcpify serve            # stdio, all three APIs, prefixed on collisions
mcpify serve --http 8080
mcpify try              # REPL across every API
mcpify status           # probes each API concurrently

mcpify status reports per API β€” [catalog] reachable (status 200, 0.03s) β€” https://shop.example.com β€” 31 tools β€” and exits non-zero if any API is unreachable. When two APIs expose the same tool name (list_pets), both get renamed with their label (catalog_list_pets, crm_list_pets) so nothing silently wins; non-conflicting names stay untouched. The mcpify_health tool returns one report covering every API. Precedence per key: CLI flags > [apis.NAME] > [serve]. Pass a positional spec or [apis.*] sections β€” never both.

Plug it into your agent

Claude Code:

claude mcp add my-api -- mcpify serve openapi.json --read-only

Claude Desktop / Cursor / any MCP client (claude_desktop_config.json):

{
  "mcpServers": {
    "petstore": {
      "command": "mcpify",
      "args": ["serve", "~/specs/petstore.json", "--auth-env", "PETSTORE_KEY"]
    }
  }
}

HTTP transport (team-shared server) β€” run mcpify serve api.json --http 0.0.0.0:8080 --http-token $TOKEN once, then point HTTP-capable clients at it:

{
  "mcpServers": {
    "petstore": {
      "type": "http",
      "url": "http://your-host:8080",
      "headers": { "Authorization": "Bearer <token>" }
    }
  }
}

Now ask your agent: "list the pets, then create one named Milo" β€” it discovers list_pets and create_pet, fills the arguments, and performs real HTTP calls.

How operations become tools

OpenAPI

mcpify

operationId

tool name (sanitized; falls back to method_path)

summary / description

tool description the agent reads

deprecated: true

shown by mcpify list before you expose old endpoints

parameters (path/query/header)

individual typed arguments with enums

requestBody (JSON)

a body object argument

$ref pointers

resolved inline (components β†’ real schemas)

servers[0].url

default base URL (override: --base-url)

The agent only ever sees the tool list and your API's JSON responses β€” mcpify adds no middleware, caches nothing you did not ask for, and sends credentials nowhere except your API.

Doctor

$ mcpify doctor my-api.json
openapi: 3.0.3
title:   Acme API
paths:   23
tools:   41 operations
servers: https://api.acme.com
warning: 12/41 operations have no operationId (names fall back to method_path)
warning: 30/41 operations have no summary (agents see no description)

Add --probe for a live pre-flight β€” after the static report, mcpify dials one argument-free GET (or the base URL) and reports reachability; a connection failure exits non-zero so CI and shell scripts stop before serving:

$ mcpify doctor https://api.weather.gov/openapi.json --probe
...
probe:    GET /alerts β†’ 200 reachable (2.80s)

CLI reference

mcpify list <spec> [--tag T] [--include P] [--exclude P] [--read-only] [--json]
mcpify list --cost                        # price the surface (~4 chars/token)
mcpify list --cost --lazy                 # ...and the 3-meta-tool lazy surface
mcpify list --config .mcpify.toml --cost  # multi-API: every surface priced
mcpify serve <spec> [--base-url URL] [--server INDEX|NAME] [--name N] [--auth-env VAR]
                    [--auth-style bearer|header|query] [--auth-name NAME]
                    [--oauth2-token-url URL --oauth2-client-id-env VAR
                     --oauth2-client-secret-env VAR] [--timeout S]
                    [--read-only] [--tag T] [--include P] [--exclude P]
                    [--http [HOST:]PORT] [--http-token TOKEN] [--wait-on-429 SEC]
mcpify try <spec> [same serve flags]        # interactive REPL, no agent needed
mcpify output-server <spec> -o FILE [-- <any serve flags>]
mcpify ui <spec> [same serve flags]         # local dashboard (tool explorer, health, config)
mcpify mock <spec> [--http 8000] [--delay-ms N]
mcpify diff OLD NEW [--json] [--fail-on-breaking]        # upgrade report + CI gate
mcpify diff OLD NEW --probe [--auth-env V]               # ...+ live check of the NEW API + cost delta
mcpify config-schema                        # JSON Schema for .mcpify.toml (editor wiring)
mcpify doctor <spec> [--probe --auth-env V --fail-on-http-error]   # static audit + live pre-flight / CI gate

# token economics: --fields id,name (projection), --redact password,token (masking),
#   --rate-limit RPS (upstream courtesy, retries included)
# credential split: --write-auth-env WRITE_KEY_ENV or --write-oauth2-token-url (reads keep --auth-env)
# tool-text overrides: [tool-text.TOOL] description = "..." in .mcpify.toml

# multi-API: define [apis.NAME] sections in .mcpify.toml, then run
#   mcpify list|serve|try|status|ui (no positional spec) β€” one process, every API
# ops add-ons for serve/ui: --metrics [HOST:]PORT   --reload   --cache-warm
#   --audit-log FILE   --http-token-file FILE   --plugin FILE (repeatable)   --otel [ENDPOINT]

Notes & limitations

  • JSON specs work out of the box; YAML specs need pip install 'mcpify[yaml]'

  • External $ref targets (files or URLs) are bundled automatically at load; circular cross-file refs are left in place rather than unwound (surface skips what it cannot resolve)

  • Oversized JSON responses truncate to valid JSON (first items + a truncation marker); non-JSON bodies cut at a character boundary

  • --fields selects at every level by documented rule (selected keys verbatim, non-selected containers transparent); it is a projection, not a security boundary β€” use --redact when a field must never reach the model

  • Request bodies are exposed as a single body object argument β€” predictable over clever

  • HTTP transport serves one JSON-RPC response per request (batching was removed from the MCP spec); clients that send Accept: text/event-stream get it framed as a single SSE message event. Server-initiated streams (a GET stream with sessions) stay deliberately out of scope for a stateless server

  • Spec versions: OpenAPI 3.x and Swagger 2.x roots are accepted; 3.x is the happy path

Hardened against the real world

mcpify is audited on every release against a 10-category checklist of MCP best practices and published production failure modes β€” not just our own examples:

  • Hostile-spec corpus (12/12): circular $refs, multipart uploads, allOf schemas, server URL variables, relative base URLs, oversized responses β€” every scenario derived from a documented real-world failure, fixed, and locked in by a regression test. Sources include the arXiv study of RESTβ†’MCP generation across 18 real APIs.

  • Live integration: the real api.weather.gov spec loads in CI β€” and the live checks found the last two real bugs (nested-truncation envelope splits, top-level-only projection) before any user did.

  • MCP lifecycle enforced: tools are unreachable until the client completes the initialize handshake.

  • Session survives upstream failures: a slow upstream (read timeout), a mid-response disconnect, or even an unexpected exception inside one tool becomes a clean isError tool result with remediation β€” never a dead stdio connection (the failure mode reported against other OpenAPI-to-MCP servers, replayed here and locked in by regression tests).

  • Blast-radius controls: read-only mode, deny/allow policy layer, per-token RBAC, response projection + secret masking, rate limiting, 40k-char valid truncation, --timeout, credentials never logged.

Full checklist with per-item status: docs/AUDIT-CHECKLIST.md

Tests

520 passing, plus one live-integration test that loads the real api.weather.gov document (auto-skipped when offline) and an OTel positive test that runs wherever the optional tracing extra is installed. Every suite runs on Python 3.10–3.12 across Linux and Windows; ruff, strict mypy and CodeQL gate every push.

Suite

Tests

What it pins down

Spec parsing & resolution

13

OpenAPI 3.x + YAML loading, $ref chains, allOf merge, server variables, malformed input

Tool translation

19

operationId naming with collision suffixing, input schemas, enums, body handling, annotation & output-schema derivation

Agent surface

32

HTTP-derived annotations, structured output contract, remediation errors, --lazy search, dry-run previews

CLI

15

list / doctor / serve flags, --json output, deprecated badges

Hostile corpus

11

circular $refs, multipart bodies, relative base URLs, 300 KB truncation, 500-op performance β€” each traced to a documented real-world failure

Lifecycle & hygiene

8

initialize handshake (-32002), byte-pure stdio, credentials never logged

Protocol end-to-end

9

real JSON-RPC over stdio against a live local HTTP API, wire-level assertions

Policy layer

7

--read-only, --allow / --deny precedence, mutating-GET protection

$ref parameters

4

parameter schemas resolved against the full spec β€” the weather.gov bug class (one test hits the live document)

Ops & configuration

47

config files + env precedence, init wizard, cache TTL & bounds, retry safety, XML conversion, discovery, batching, status/health

Protocol version compat

5

2026-07-28 stateless _meta requests and the legacy 2025-06-18 handshake, on the same wire

HTTP transport

19

Streamable HTTP: lifecycle over POST, 405/411/413/415 error ladder, parse/batch rejections, bearer enforcement, bind-string parser

OAuth2 client-credentials

18

token fetch/cache/refresh with a fake clock, Basic vs body client auth, public clients, every failure mode, 401 self-heal end-to-end

try REPL

26

piped-stdin sessions: selection by number/name, typed prompts, re-prompt on bad input, :raw/:info, clean EOF/Ctrl+C exits, read-only surface

output-server

11

embedded spec integrity, guard rails (existing file, bad spec, unknown flags), secret warnings, and a real subprocess E2E handshake

Server selection

17

`--server INDEX

Auth auto-detection & Basic

22

securitySchemes β†’ style/name resolution (OpenAPI + Swagger 2.0), requirement-order precedence, operation-level security, exact hint text, HTTP Basic header encoding, CLI/try/doctor wiring, explicit-style override

Rate-limit courtesy (--wait-on-429)

9

Retry-After honored once within cap, cap exceeded returns 429 untouched, missing header falls back to retry delay, HTTP-date form never waits, POST never auto-waited, CLI wiring

Multi-API aggregation

26

[apis.*] merge with two-sided collision prefixes and _2 suffixes, per-API routing/auth/cache isolation, concurrent aggregated health (dead-API named in hint), lazy search across APIs incl. label match, preview routing, status exit codes, --env inheritance, both-rejected flag combos

Ops: dashboard, metrics, mock, reload

25

/metrics text format (counters/histograms/cache hit-miss/health gauges), token'd UI routes, masked preview API, config-form writer (+unknown-key 400), schema-shaped mock responses with template routing, hot-reload rebuild incl. broken-spec survival

CLI connectivity glue

10

--http wiring, MCPIFY_HTTP_TOKEN fallback, OAuth2 flag rules, config-file keys, wizard option 5, try smoke test

Spec diff (mcpify diff)

14

added/removed/changed ops, breaking verdicts (required param added/became, body became required, op removal), deprecation & operationId warnings, migration guide, document-level diff, CLI exit contract 0/1/2, --json

v1.11 serving: audit, cache, RBAC, plugins

17

JSONL audit trail with argument fingerprints + fail-safe on unwritable files, ETag 304 revalidation on stale entries, mcpify_cache_invalidate (scoped + full), --cache-warm pre-calls argument-free GETs only, token-file scoping end-to-end (401 / filtered lists / refused calls, deny wins, duplicate-token rejection), plugin hooks on real requests, mcpify ui dispatch (dead-command regression), config-schema matches the config module, OTel guard

External $ref bundling

6

file + URL-base targets inlined, component-only target files, nested refs resolved relative to their own file, missing targets skipped, circular refs survive, same-document refs untouched

Governance: split keys, tool text, valid truncation

21

read-key/write-key per method over a live upstream (shared-identity default unchanged), style/name inheritance + explicit override, config write-auth-* keys in serve/envs/apis, [tool-text] override through list --json, unknown-tool warnings, validator errors, schema/keys parity, doctor instruction-like + overlong-description counts, oversized array β†’ valid JSON with marker, object key-keeping, non-JSON fallback, error-prefix survival

v1.13: cost, projection, SSE, OAuth2 write

20

surface pricing in JSON + human output, recursive projection with transparent envelopes (both rules pinned: the top-level-only first rule failed live), selected keys keep their arrays, SSE framing vs JSON clients, write-flow resolution + mutual exclusion with --write-auth-env

v1.16: status policy, REPL session controls, diff probe + cost delta

12

policy (fields/redact/rate-limit) in multi-API JSON+human status and single-spec policy: line, :redact/:fields session set/show/clear over a live upstream (masking verified on the wire), diff surface-cost delta in JSON+human, --probe reachable/unreachable exit contract (2 on probe failure), form retry-delay float

v1.15: auth-probe, strict gate, metrics, lazy pricing

16

probe with a real credential (401-without vs 200-with over a live local upstream), strict-mode verdicts, doctor CLI exit contract, projection/redaction Prometheus counters (values counted, fresh-session enable), count_redact_targets, lazy-surface pricing lines, init --probe reachable/unreachable, dashboard-form token keys (float coercion, unknown-key rejection)

v1.14: redact, rate-limit, probe, multi list

29

masking at every level incl. error bodies and selected-key overlap, arrays masked in place, limiter slots with a fake clock, retry throttling, probe target selection + reachability exit contract, config redact/rate-limit in serve/apis/envs, per-upstream limiters, multi-API list + pricing

Policy on failures: every bug found in the wild becomes a pinned regression test before the fix ships β€” the suite only grows.

Run it locally:

pip install pytest pyyaml
pytest -v

Roadmap

The v1.6–1.16 roadmap is fully shipped. Possible future work (not promised): server-initiated SSE (a GET stream with sessions β€” deliberately out for a stateless transport).

  • status policy visibility, REPL :redact/:fields, diff --probe + cost delta, form examples β€” shipped in v1.16.0

  • Authenticated doctor --probe + --fail-on-http-error CI gate, init --probe, projection/redaction metrics, lazy-surface pricing β€” shipped in v1.15.0

  • --redact, --rate-limit, doctor --probe, lazy-search costs, multi-API list β€” shipped in v1.14.0

  • OAuth2 write flow (--write-oauth2-*), list --cost, --fields projection, SSE POST responses β€” shipped in v1.13.0

  • Read/write credential split, tool-text overrides, doctor prompt-hygiene audit, structure-aware truncation β€” shipped in v1.12.0

  • Spec diff + audit log + per-token RBAC + plugin hooks + config JSON Schema + external $ref bundling + OTel extra β€” shipped in v1.11.0

  • Web dashboard, Prometheus metrics, mock server, hot reload β€” shipped in v1.10.0

  • Multi-API aggregation: one serve process fronting several OpenAPI documents β€” shipped in v1.9.0

  • HTTP transport, OAuth2 client-credentials, mcpify try REPL, --output-server β€” shipped in v1.6.0

License

MIT β€” see the LICENSE file for details.

Available Tools

5 tools
get_petB
Read-onlyIdempotent

[GET] Get a single pet

ParametersJSON Schema
NameRequiredDescriptionDefault
petIdYes

TDQS

B3.1/5.0
Behavior2/5

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

The description adds only '[GET]', which mostly duplicates the safety information already provided by annotations such as readOnlyHint=true, idempotentHint=true, and destructiveHint=false. It does not disclose additional behavioral details like missing-ID handling, authentication requirements, rate limits, or response shape; the annotations do the heavy lifting.

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 filler or redundant elaboration. For a simple one-parameter read operation, this is appropriately compact and easy to scan.

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 one-parameter, read-only get operation, the description plus annotations may be minimally sufficient, but the agent is left to infer too much from the tool name and parameter name. Missing guidance on what petId represents, how to handle nonexistent pets, and what a successful response looks like keeps this from being fully complete.

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?

The sole required parameter petId has an empty schema description (0% coverage), and the tool description does not explain that petId identifies which pet to fetch or how it should be interpreted. The parameter name is suggestive, but the description adds no semantic value beyond what the schema already exposes.

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 clear verb ('Get') and resource ('a single pet'), which unambiguously conveys the operation and distinguishes it from list_pets by emphasizing singular retrieval. It does not explicitly contrast with siblings or mention the petId parameter, but the core purpose is clear.

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 word 'single' implies this tool is for retrieving one specific pet rather than listing pets or vaccinations, so usage context is indirectly suggested. However, there is no explicit statement of when to use this tool versus list_pets, no prerequisites, and no mention of alternatives.

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

get_statsC
Read-onlyIdempotent

[GET] Store statistics

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

C2.3/5.0
Behavior2/5

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

The annotations already convey readOnlyHint, idempotentHint, openWorldHint, and destructiveHint. The description adds no behavioral context beyond the redundant "[GET]" marker, such as whether results are aggregated, paginated, or time-bound.

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

Conciseness2/5

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

Although the description is short, it is under-specified rather than usefully concise. It only repeats the title and adds an HTTP-verb hint that is already available in the annotations, so the brevity buys the agent no added insight.

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

Completeness2/5

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

With no output schema and no clarification of what "statistics" means, the description is incomplete for an agent deciding whether this tool meets a user's request. It also fails to clarify how this endpoint relates to the sibling pet/vaccination tools.

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?

The tool has zero parameters and the input schema is an empty object with no required fields. There is no parameter burden for the description to carry, so the baseline of 4 is appropriate.

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

Purpose2/5

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

The description "[GET] Store statistics" restates the tool title and name almost verbatim. It identifies the resource at a high level but does not specify what statistics are included, so an agent cannot tell whether this returns sales totals, visit counts, or something else.

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?

No guidance is provided about when to use get_stats instead of list_pets, get_pet, list_vaccinations, or mcpify_health. There is no mention of typical use cases, exclusions, or alternatives, so the agent must guess based on the name alone.

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

list_petsB
Read-onlyIdempotent

[GET] List all pets

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoFilter by kind
limitNoHow many pets to return

TDQS

B3.3/5.0
Behavior2/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the description adds only the '[GET]' method and list scope. It does't disclose pagination/default limit/response shape or filtering behavior, so contextual transparency is thin.

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?

One short sentence with no filler, method prefix ('[GET]') front-loaded. Every token earns its place; it is appropriately sized for a simple list endpoint.

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 list with two optional params and no output schema, the description is mostly sufficient to invoke it. However, it leaves ambiguity about whether 'all' is exhaustive or paginated, and gives no hint of the return shape – a real but minor gap.

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%, and both parameters already have meaningful descriptions ('Filter by kind', 'How many pets to return'). The description adds nothing beyond the schema, so the baseline of 3 is appropriate.

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 ('List all pets'), making the operation clear. It distinguishes from sibling get_pet (singular object vs. collection) and other siblings by resource/scope, though it doesn't explicitly name them.

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?

No explicit when-to-use or alternative routing. The word 'all' implies collection-level fetching, and siblings like get_pet imply single-item lookup, but the description leaves the choice to inference.

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

list_vaccinationsB
Read-onlyIdempotent

[GET] List vaccinations of a pet

ParametersJSON Schema
NameRequiredDescriptionDefault
petIdYes

TDQS

B3.3/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructveHint=false. The description adds only '[GET]', which mostly duplicates the read-only annotation, and provides no additional behavioral context such as empty results, 404 behavior, or authentication requirements.

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 sentence with no filler or redundant elaboration. It is front-loaded and easy to parse, though extremely minimal.

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 one-parameter read-only endpoint with rich annotations, a short description can be sufficient. However, it omits any mention of response shape, parameter semantics, or conditions for use, making it only minimally complete for guiding a correct call.

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% for the only parameter petId, and the description does not explicitly map 'petId' to its role beyond saying 'of a pet'. This gives a weak hint that petId identifies the pet but does not compensate for the undocumented parameter.

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 states a specific verb ('List') and resource ('vaccinations of a pet'), which clearly distinguishes it from siblings like list_pets and get_pet. No ambiguity about what operation this tool performs.

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 phrase 'of a pet' implies the tool is for retrieving vaccination records for one pet, but it does not explicitly state when to use it over alternatives or mention any exclusions. Usage is implied rather than directly guided.

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

mcpify_healthA
Read-onlyIdempotent

Check that the upstream API is reachable and report this server's own configuration (tool count, cache, retry, auth).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already indicate a safe, read-only, idempotent operation. The description adds valuable context beyond annotations by disclosing that the tool reaches out to the upstream API and reports specific configuration details (tool count, cache, retry, auth). No contradictions.

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?

One sentence, no filler, and the main purpose is front-loaded before the specific reported fields. Every part of the sentence earns its place.

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's simplicity, no parameters, and strong annotations, the description sufficiently covers what the tool does and what it reports. It could specify the response format, but for a health-check tool with no inputs this is a minor omission.

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?

With zero parameters, there is nothing for the description to clarify about inputs. The baseline of 4 applies since the schema is trivially complete and no param-level guidance is needed.

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 'Check' and names the exact resources: upstream API reachability and the server's own configuration. It clearly differentiates this health/config tool from the data-oriented siblings like list_pets and get_stats.

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 context is clear: use this when you need to verify upstream connectivity or inspect server configuration. It does not explicitly mention exclusions or when to prefer a sibling, but the described purpose strongly implies the appropriate usage scenario.

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 updatesv1.0.0
    • First observedget_pet
    • First observedget_stats
    • First observedlist_pets
    • First observedlist_vaccinations
    • First observedmcpify_health

TDQS

B3.2/5.0

Scored across 5 tools

Disambiguation4/5

The four data tools are mostly distinct: list_pets/get_pet follow a standard list/detail pattern, and list_vaccinations clearly targets a subresource. get_stats and mcpify_health are also separate, though get_stats is vague enough that an agent might briefly confuse it with a health/status report.

Naming Consistency4/5

list_pets, get_pet, list_vaccinations, and get_stats all use the snake_case verb_noun pattern. mcpify_health breaks that pattern structurally, and get_stats is less descriptive than a name like get_store_statistics would be.

Tool Count5/5

Five tools is a compact, well-scoped set for this server. Each tool covers a distinct function: pet collection, pet detail, vaccination lookup, statistics, and health/configuration.

Completeness3/5

The read-oriented workflow is covered: list pets, get a specific pet, list vaccinations, retrieve stats, and check health. However, there are no create/update/delete tools for pets or vaccinations, which is a notable lifecycle gap unless the server is intentionally read-only.

Maintenance

ActivityMaintained
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Turn any OpenAPI/Swagger spec into MCP tools. Zero config, zero code. Supports Swagger 2.0, OpenAPI 3.x, Bearer/API-key/OAuth2 auth, flat parameter schemas for better LLM accuracy, and smart response truncation.
    128 npm
    3
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Auto-generates MCP tools from your OpenAPI spec, allowing natural language interaction with any API via configurable headers and serverless deployment.
    19 npm
    MIT