Skip to main content
Glama
openapi-explorer-mcp

openapi-explorer-mcp

by deadrime

openapi-explorer-mcp

An MCP server for any OpenAPI 3 spec. It lets an AI agent find endpoints, inspect request and response shapes without loading a megabyte of JSON, generate TypeScript types, and call endpoints — with credentials mapped to the security schemes the spec already declares.

Unlike servers that turn every operation into its own tool, this one stays small: a handful of tools that explore the spec and one generic caller.

Tools

Tool

What it does

api_spec_info

Spec version and age, counts, groups, security schemes with credential status, changes since the previous version.

api_search

Ranked search over paths, operationIds, summaries, descriptions, parameters and body fields. scope: "schemas" finds component schemas by name or field.

api_endpoint

One endpoint as text: description, danger, auth alternatives, URL, typed parameters with defaults and ranges, request and response shapes (compact, depth-limited), documented errors.

api_schema

A component schema by name, with drill-down into nested fields and the endpoints that use it, directly or through other schemas.

api_types

TypeScript types for an endpoint's parameters, request and response, plus every type they reference, generated with @hey-api/openapi-ts. The doc comment of a string field names its format with an @format tag. docs: false drops the comments.

api_get

Calls a GET endpoint. fields and max_items narrow the response.

api_request

Calls an endpoint with any method. Registered only with OPENAPI_ALLOW_WRITE; destructive endpoints need confirm_danger: true.

api_call_log

Journal of api_request calls with ids from responses, for cleaning up.

api_credentials

Keeps credentials for the session or forgets them; shows where the credential of each scheme comes from, never the value.

recipe

Markdown recipes for this API. Registered only with OPENAPI_RECIPES_DIR.

Related MCP server: Swagger MCP Server

Output

The exploring tools answer in plain text — an agent reads it as well as JSON and it costs a fraction of the tokens:

api_search(query: "equity history")

3 of 3 · accounts 1, admin/accounts 1, admin/hedge 1
GET /accounts/{accountId}/equity-history — Get the equity history of the trader account [bearer] (path: accountId; query: timestamp?, duration?)
GET /admin/accounts/account-equity-history — Get the equity history of the trader account [x-admin-token|bearer] (query: accountId, timestamp?, duration?, changeFraction?)
GET /admin/hedge/dashboard/user-history — User equity and OI history [x-admin-token|bearer] (query: userId, timeframe, from?, to?) · field initialEquity, currentEquity

Each line carries the auth alternatives, destructive, body and deprecated flags and the parameter names; · field … says the endpoint was found through a field of its request or response. Schemas render as a compact pseudo-type: a format or a well-known pattern is named (string (uuid)), enums are listed up to 20 values, descriptions are cut at a word.

api_get, api_request, api_credentials, api_spec_info and api_call_log answer in compact JSON.

Endpoints and schemas are indexed with MiniSearch on first use. Words are split on punctuation, camelCase and digits (closeReason also matches as a whole), stop words are dropped, and each word is stemmed by its script — English with Porter, Russian with Snowball — so no language setting is needed. Queries match whole words, prefixes and one typo; a compound identifier outweighs its parts. Results are ranked by BM25 with field weights (path and summary first, then operationId, danger reason, description, parameters, schema names and body fields) and hits scoring below 30% of the best one are dropped. An exact key, path or operationId always comes first. When nothing matches, the answer says how to search differently and lists similar words from the spec.

Narrowing responses

fields keeps only the listed paths of a response; [] stands for every element of an array, and on an array body a path applies to each element. max_items cuts every array and reports the original lengths:

api_get(endpoint: "GET /admin/markets", fields: ["id", "settings.isCloseOnly"], max_items: 3)
{"key":"GET /admin/markets",…,"arrays":{"[]":157},"body":[{"id":"…","settings":{"isCloseOnly":false}},…]}

Without max_items, a response over OPENAPI_MAX_RESPONSE_CHARS gets its arrays cut to 20, 5 or 1 items until it fits, with a note; only then is the text truncated.

Configuration

Variable

OPENAPI_SPEC_URL

Required. URL or file path of an OpenAPI 3 JSON spec. URLs are cached on disk and revalidated with ETag.

OPENAPI_BASE_URL

Base URL for calls. Required when a credential or header is configured in the environment; otherwise servers[0].url of the spec is used.

OPENAPI_AUTH_<SCHEME>

A permanent credential for a security scheme — see Authentication.

OPENAPI_HEADER_<NAME>

A header sent with every call, whatever the spec says. OPENAPI_HEADER_X_API_KEY sends x-api-key.

OPENAPI_ENV_FILE

Env file merged into the environment at startup; variables already set win.

OPENAPI_ALLOW_WRITE

1, true or yes registers api_request. Off by default.

OPENAPI_DANGER_FILE

JSON with danger overrides — see Danger rules.

OPENAPI_RECIPES_DIR

Directory of markdown recipes (with a description: line) served by recipe.

OPENAPI_INSTRUCTIONS_FILE

Markdown appended to the instructions the server gives the model.

OPENAPI_SERVER_NAME

Server name reported to the client. Default openapi.

OPENAPI_CACHE_DIR

Spec cache and generated types. Default ~/.cache/openapi-explorer-mcp/<hash of the spec source>.

OPENAPI_CALL_LOG

Journal of api_request calls. Default <cache dir>/calls.jsonl.

OPENAPI_SPEC_TTL_S

How often a URL spec is revalidated, in the background: calls are served from memory or the disk cache meanwhile. Default 900.

OPENAPI_TIMEOUT_MS

Timeout of spec fetches and calls. Default 20000.

OPENAPI_MAX_RESPONSE_CHARS

Cap on a tool response. Default 40000.

{
  "mcpServers": {
    "my-api": {
      "command": "npx",
      "args": ["-y", "openapi-explorer-mcp"],
      "env": {
        "OPENAPI_SPEC_URL": "https://api.example.com/openapi.json",
        "OPENAPI_BASE_URL": "https://api.example.com",
        "OPENAPI_AUTH_X_API_KEY": "${MY_API_KEY}",
        "OPENAPI_SERVER_NAME": "my-api"
      }
    }
  }
}

Authentication

The server doesn't invent headers — it reads them from the spec. components.securitySchemes says where a secret goes, and each operation's security says which schemes it accepts. A scheme takes its value from the first of three places that has one:

Source

Lives

How

the call

one call

credentials argument of api_get and api_request

the session

until the server restarts

api_credentials with set and clear

the environment

as long as the configuration

OPENAPI_AUTH_<SCHEME>

Permanent credentials — a static admin token, a service API key — belong in the environment: they stay out of the conversation. The variable name is the scheme name upper-cased with every other character replaced by _: x-admin-token → OPENAPI_AUTH_X_ADMIN_TOKEN, bearer → OPENAPI_AUTH_BEARER. A header every call must carry, whatever the spec says, goes to OPENAPI_HEADER_<NAME>.

Credentials the model supplies — a token it just obtained, a key the user pasted into the chat — go through credentials or api_credentials. Keys are scheme names as api_spec_info lists them; an apiKey scheme also accepts its header, query or cookie name, so X-Api-Key finds a scheme named ApiKeyAuth. When the spec declares no security schemes at all, the keys are sent as plain headers.

api_request(method: "POST", endpoint: "POST /auth/login", body: { … })
api_credentials(set: { "bearer": "<accessToken from the response>" })
api_get(endpoint: "GET /me")

When a call with a credential gets 401, the response says so in note.auth: obtain a fresh value and set it again.

Placement. Whatever the source, the value goes where the scheme says:

Scheme

Placement

apiKey in header / query / cookie

the named header, query parameter or cookie

http bearer, oauth2, openIdConnect

Authorization: Bearer <value>

http basic

Authorization: Basic … — give user:password or an already encoded value

Which scheme a call uses. security is a list of alternatives. With as: "auto" (the default) the server takes the first alternative whose schemes all have credentials, from any source. as can also name a scheme to force it, or be "anonymous". When nothing is available, a GET is sent anonymously with a note (many GET endpoints declare auth but also answer without it); any other method fails and names every way to supply the credential.

What keeps credentials safe

  • Credentials go only to the base URL. The origin of every request is checked against it before sending, and path parameters are URL-encoded, so a path can't redirect a request elsewhere.

  • Credentials from the environment need OPENAPI_BASE_URL set explicitly: a server configuration is long-lived and often shared, while the spec's servers comes over the network. Credentials the model supplies go to the base URL that api_spec_info and api_credentials report — OPENAPI_BASE_URL, or the first server of the spec.

  • Tool output and the call journal never contain values: they name the scheme and where its credential came from, e.g. bearer (session). A value the model supplies is part of the conversation by nature — keep secrets that must not be there in the environment.

Danger rules

Every non-GET operation is write, and destructive when it is a DELETE or its path contains drop, purge, reset, destroy, bulk or broadcast. api_request refuses destructive operations without confirm_danger: true. OPENAPI_DANGER_FILE adds exact operations and path words:

{
  "operations": {
    "POST /orders": "creates a real order"
  },
  "pathPatterns": ["close", "withdraw"]
}

Development

npm install
npm run typecheck
npm run build      # tsc into dist/
npm run smoke      # stdio checks against scripts/fixtures/pets.json and a local HTTP server, no internet
npm run check      # all three
npm run smoke:package  # packs the tarball, installs it in a clean directory and runs the smoke there

npm publish runs check and smoke:package first. The package depends on TypeScript 5.9 directly: the type generator declares TypeScript as a peer dependency, and without the pin npm installs TypeScript 7, whose JavaScript API the generator can't use.

Bench

npm run bench -- <queries.json> runs a server against a query file and reports search quality (top-1/5/10 and MRR by kind of query), latency, and the tokens of every response and of the tool list (o200k, as a proxy for comparing formats). The file holds env for the server, queries with the endpoints each should find, and calls to measure:

{
  "env": { "OPENAPI_SPEC_URL": "../../fixtures/pets.json" },
  "queries": [{ "q": "list pets", "expect": ["GET /pets"], "kind": "plain" }],
  "calls": [{ "label": "endpoint", "tool": "api_endpoint", "args": { "endpoint": "GET /pets" } }]
}

Relative paths resolve against the file and ${VAR} expands from the environment. --spec overrides the spec — use a saved snapshot to compare runs; --server "npx -y openapi-explorer-mcp@0.1.0" measures another version; --json saves the report and --compare prints the difference with a saved one. scripts/bench/queries/pets.json is the example.

License

MIT — see LICENSE.

Available Tools

7 tools
api_call_logCall journalA
Read-only

What api_request has called: endpoint, status and ids from responses — use it to clean up what was created.

Inputs: limit.

api_endpointDescribe an endpointB
Read-only

Parameters, request and response shapes (compact, depth-limited), danger level, security alternatives and URL of one endpoint.

Inputs: endpoint (required), mode, depth.

api_getCall a GET endpointA
Read-only

Calls a GET endpoint and returns the response. Read-only: the method is fixed.

Inputs: endpoint (required), as, query, identity, +1 more.

api_schemaDescribe a schemaA
Read-only

A schema from components by name, compact and depth-limited. path drills into a nested field; usedBy lists the endpoints that reference it.

Inputs: name (required), mode, path, depth.

api_spec_infoSpec infoB
Read-only

Spec version and age, counts, groups, security schemes with credential status, and changes since the previous version.

Inputs: refresh.

api_typesTypeScript types of an endpointA
Read-only

Ready-to-paste TypeScript types for the request, response and parameters of an endpoint, generated from the spec with @hey-api/openapi-ts.

Inputs: endpoint (required), include, name_prefix.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 7 tools

    Disambiguation4/5

    Tools are mostly distinct: api_spec_info, api_search, api_endpoint, api_schema, api_types, api_get, and api_call_log each target a different aspect of API exploration. Slight overlap between api_endpoint (details) and api_types (types) but descriptions clarify their purpose. The reference to api_request in api_call_log hints at a missing tool, but the set itself is clear.

    Naming Consistency3/5

    Naming follows a consistent 'api_' prefix but the suffix style is mixed: some are nouns (api_spec_info, api_endpoint, api_schema, api_types, api_call_log) while others are verbs (api_search, api_get). This hybrid is readable but not a uniform verb_noun pattern. The inconsistency is mild but noticeable.

    Tool Count4/5

    With 7 tools, the count is well within the ideal range (3-15). Each tool addresses a distinct need for exploring an OpenAPI spec. However, the mention of api_request in api_call_log suggests there might be an additional tool not listed, which could slightly grow the set but still remain appropriate.

    Completeness3/5

    The set covers spec overview, endpoint discovery, detail retrieval, schema inspection, type generation, and safe GET execution. It notably lacks a POST/PUT/PATCH tool for actually creating or modifying resources, only supporting read-only GET. Also, api_call_log implies a separate api_request tool that is missing, leaving a gap between logging and executing non-GET calls.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers