openapi-lookup-mcp
Provides tools for looking up individual endpoints from an OpenAPI/Swagger specification, enabling agents to search endpoints and retrieve compact summaries of a single endpoint—including auth, parameters, request body, responses, and resolved referenced schemas—without loading the whole spec.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@openapi-lookup-mcp look up the GET /users/{id} endpoint in our API spec and show its parameters"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
openapi-lookup-mcp
MCP server that lets AI coding agents such as Claude Code and Cursor read one endpoint or schema of an OpenAPI or Swagger spec instead of the whole file. Real-world specs often run to millions of tokens and do not fit in a context window; with this server the agent searches the spec, gets back a compact summary with every $ref already resolved, and keeps working.
Over 99% fewer tokens than reading the spec: finding and reading one endpoint costs about 2,000 tokens on the 2.8-million-token GitHub spec.
57–68% smaller than the same endpoint in YAML, with nested schemas resolved in a single call.
Built-in search that handles typos, word forms and identifiers such as
listJobMatches, with no model or embeddings.Local files or remote URLs, OpenAPI 3.x and Swagger 2.0, with caching and automatic refresh.
Installation
Requires Node.js 18 or newer. From the root of your project:
npx -y @harborkit/openapi-lookup-mcp init https://example.com/api-docs/swagger.yamlThen open the project in Claude Code or Cursor and approve the new api-spec server when prompted.
The command writes .mcp.json (Claude Code) and .cursor/mcp.json (Cursor), keeping any servers already configured there. Running it again updates the entry, for example with a new URL. If a different server is already registered as api-spec, nothing is changed: add --name <other name> to keep both, or --force to replace it.
npx -y @harborkit/openapi-lookup-mcp init https://example.com/api-docs/swagger.yaml --name billing-apiManual configuration
If you prefer to configure the server yourself, add a block like this to .mcp.json (or the equivalent file for your editor):
{
"mcpServers": {
"api-spec": {
"command": "npx",
"args": ["-y", "@harborkit/openapi-lookup-mcp@0.2.0"],
"env": {
"OPENAPI_SPEC_URL": "https://example.com/api-docs/swagger.yaml"
}
}
}
}The same server can also be launched directly, with the spec as an argument or in OPENAPI_SPEC_URL:
npx -y @harborkit/openapi-lookup-mcp https://example.com/api-docs/swagger.yamlEnvironment variables
Variable | Purpose |
| URL or file path of the spec, when it is not given as an argument |
| Extra hosts that referenced documents may be loaded from (comma-separated, or |
| Folder that a local spec may read referenced files from, instead of the folder the server runs in |
| Where the cache of remote specs is kept; defaults to |
Related MCP server: code-context
Example
GET /users/{id} — Get a user
auth: bearerAuth (http bearer JWT)
path:
id: string
query:
view?: "short" | "full" (default: "short") — level of detail
responses:
200 — success: user
header X-RateLimit-Remaining?: integer
404 — not found
user = {
id: integer (readOnly)
nickname?: string | null (maxLength: 30)
team?: team
}
team = {
name: string
members?: user[]
}
spec read just now from spec.yamlSee Token cost for how this compares to reading the spec.
Token cost
Measured on the GitHub REST and Stripe specs with the 111 queries of the search benchmark. Tokens are estimated as characters / 4; no agent was involved, so the agent's own reasoning is not counted.
GitHub REST | Stripe | |
Whole spec | 2,802,448 | 1,622,072 |
Tool definitions and instructions, once per session | ~820 | ~820 |
One search (median) | ~220 | ~180 |
Reading the endpoint that was found (median) | ~1,650 | ~6,340 |
Search and read one endpoint (median) | ~1,900 | ~6,550 |
Without the tool, an agent has three options, all worse on a large spec:
Read the whole spec. Neither of these specs fits in a context window.
Grep a local file and read pieces of YAML. The same endpoint with its schemas is about three times larger in YAML than in the compact summary, and following each
$refby hand takes several turns.Fetch a remote spec. A URL cannot be grepped, so the agent downloads everything or works from a lossy summary.
The queries above target popular, large endpoints. Across every endpoint of the GitHub spec the median summary is about 490 tokens.
When it does not pay off: on a small spec such as Petstore (about 5,000 tokens in full), reading the file once is affordable. The tool still wins for a handful of lookups, but an agent that needs most of the endpoints spends about the same either way.
Supported inputs
OpenAPI 3.x
Swagger 2.0
Local files (
.yaml,.yml,.json)Remote URLs
$refimports from other files and local fragments, within the limits in Referenced documentsSchema resolution for nested objects and arrays
Tool reference
Tool | Input | Returns |
|
| The 10 most relevant endpoints, one line each; understands word forms, identifiers and typos |
|
| Compact endpoint summary with auth, params, request body, responses, and resolved schemas |
|
| One schema and its related schemas, plus the endpoints that use it |
search_endpoints
Ranked keyword search over every endpoint of the spec. It needs no model, embeddings or extra dependency: the index is built in memory the first time the spec is searched (about 0.2 s for the GitHub spec) and a query takes a few milliseconds.
What is searched, from most to least important:
path, summary and operation id
HTTP method, tags, parameter names and the schemas the endpoint uses
description, and the property names of its request and response bodies
schemas nested one level deeper, path parameters and parameter descriptions
How a query is read:
Filler words such as
I,need,howortheare ignored.Word forms match each other:
create,creates,createdandcreating;repositoryandrepositories.Identifiers are split into their words, so
listJobMatches,job_matchesandjob matchesare the same query.Action words match the HTTP method and their synonyms:
retrieveorshow→GET,addornew→POST/create,editormodify→PATCH/PUT/update,remove→DELETE.Abbreviations match the words they start:
repofindsrepository.Typos are corrected when a word is not in the spec at all, and the answer says so. Only words of five letters or more are corrected, and never by changing the first letter.
How results are ranked:
A word that is rare in the spec counts for more than one that appears in most endpoints.
A match in a short, specific text counts for more than one in a long text, so
create issueranksPOST …/issuesabovePOST …/issues/{issue_number}/assignees.An endpoint that misses a word of the query is ranked lower, and more so when the missing word is a rare one. When not even the best result has every word, the answer starts with a line that says so.
Endpoints that score far below the best one are left out, so a precise query gets a short answer.
At most 10 endpoints are returned, about 200 tokens. When more are relevant the answer ends with
… N more; passlimit(up to 50) to list everything about a resource.
> search_endpoints { "query": "create teams" }
POST /teams — Create a team
> search_endpoints { "query": "creating a tema" }
Read "tema" as "team".
POST /teams — Create a team
> search_endpoints { "query": "nickname invoices" }
Nothing in the spec mentions "invoices"; searched for the other words.
GET /users/{id} — Get a user
POST /teams — Create a teamKeywords still work better than long sentences, and the search matches words, not meanings: it does not know that "bookmark" means "star". The tool description tells the agent to search again with the API's own terms when the endpoint it needs is not listed; with short answers, a second search costs less than one long answer. See Search quality for measurements.
get_endpoint
Accepts:
a template such as
/users/{id}a concrete path such as
/users/42a full URL such as
https://example.test/api/users/42?x=1
The server removes the API base path when present before matching. raw: true returns the original spec YAML for that endpoint, while refresh: true forces a fresh fetch before answering.
get_schema
Looks up a schema by name case-insensitively and suggests similar names when no exact match exists. It returns:
the schema definition
referenced nested schemas
the endpoints that use the schema directly or transitively
Schemas that live in referenced documents can be looked up the same way. raw and refresh behave as in get_endpoint.
> get_schema { "name": "team" }
team = {
name: string
members?: user[]
}
user = {
id: integer (readOnly)
nickname?: string | null (maxLength: 30)
team?: team
}
team is used directly by:
POST /teams — Create a team
used through other schemas by:
GET /users/{id} — Get a userReading the output
name?marks an optional property or parameter;namewithout?is required. As in OpenAPI, a property is optional unless the schema lists it inrequired.Constraints and flags appear in parentheses after the type, for example
limit?: integer (minimum: 1, default: 20) — rows per page.Supported keywords include
default,readOnly,writeOnly,deprecated,minimum,maximum,minLength,maxLength,pattern,minItems,maxItemsanduniqueItems. Examples are not shown; useraw: trueto see them.A line starting with
//above a schema is that schema's description.discriminatorshows the discriminator property and its mapping, for examplediscriminator: kind (dog → dog, cat → cat).A | Bis a union,A & Bis an intersection, andT | nullis a nullable type.Unresolvable references are reported as
unresolved reference …instead of being silently dropped.auth:shows how each scheme is sent, for examplebearerAuth (http bearer JWT)orapiKey (apiKey in header "X-API-Key").a + bmeans both are required,a | bmeans either one, andnonemeans the endpoint can be called without credentials.Response headers appear under each response as
header Name?: type.Schemas the endpoint references directly are always shown. Schemas nested inside them are expanded until they add up to about 4,000 tokens; the rest are named in a
Not expanded …line and can be read withget_schema.Every answer ends with the age and source of the spec, and with a warning when a referenced document could not be loaded.
Referenced documents
A spec decides which other documents get loaded, so those references are restricted by default:
A remote spec can only load documents from its own origin (same scheme, host and port). To allow other hosts, list them in
OPENAPI_ALLOWED_REF_HOSTS(comma-separated, or*for any). A remote spec can never read local files.A local spec can only load files inside the folder the server runs in or the spec's own folder, after resolving symlinks. Set
OPENAPI_REF_ROOTto allow a different folder. Remote documents also needOPENAPI_ALLOWED_REF_HOSTS.Referenced documents are limited to 10 MB each, 15 seconds per download and 50 documents in total. They are read four at a time and redirects are not followed.
The spec itself is limited to 50 MB and 30 seconds.
A document that is not loaded does not stop the server. Its references are shown as unresolved reference … and every answer ends with the reason, for example referenced documents not loaded: https://other.test/models.yaml (host other.test is not allowed; …).
Caching and freshness
Remote specs are cached for 6 hours in memory and in
~/.cache/openapi-lookup-mcp.When a search or endpoint lookup returns no match, the server refreshes the spec before answering, with a cooldown of at most 5 minutes.
Local files are re-read whenever they change.
Referenced files are re-read only when the main spec changes.
Every result includes the age of the spec it was read from.
Benchmark
The project includes a benchmark script:
npm run benchmarkThis renders every endpoint and schema for a set of public specs, fails if any render throws, and compares the compact summary against the raw YAML for the same endpoint. You can also pass your own spec URLs or local files to benchmark those instead.
Spec | Endpoints | Schemas | Render failures | Unresolved refs | Whole spec (tokens) | Median endpoint, raw YAML | Median endpoint, compact | Compact / raw |
Petstore (Swagger 2.0) | 20 | 6 | 0 | 0 | 4,404 | 265 | 99 | 35% |
Petstore (OpenAPI 3.0) | 19 | 6 | 0 | 0 | 5,622 | 365 | 136 | 37% |
Stripe | 612 | 1,538 | 0 | 0 | 1,622,072 | 12,753 | 5,387 | 43% |
GitHub REST | 1,272 | 1,011 | 0 | 0 | 2,802,448 | 1,407 | 490 | 32% |
Measured on 2026-11-10. Tokens are estimated as characters / 4. The Compact / raw ratio compares the total size of all endpoints in both formats.
Search quality
npm run benchmark:search # add "-- --misses" to list the queries that failThis runs the 111 queries in scripts/search-queries.js against the GitHub and Stripe specs. Each query names the endpoint an agent would want back. The report gives, per query type, how often that endpoint is among the first 1, 5 and 10 results (Top-1, Top-5, Top-10), the mean reciprocal rank (MRR, the mean of 1 / rank) and the mean number of endpoints in an answer.
Query type | Example | Queries | Top-1 | Top-5 | Top-10 | MRR | Results shown |
keyword |
| 18 | 78% | 100% | 100% | 0.87 | 9.3 |
sentence |
| 14 | 36% | 71% | 86% | 0.49 | 9.6 |
paraphrase |
| 37 | 32% | 46% | 57% | 0.39 | 9.5 |
inflection |
| 11 | 64% | 91% | 100% | 0.75 | 10.0 |
compound |
| 11 | 64% | 100% | 100% | 0.78 | 9.5 |
field |
| 10 | 40% | 90% | 100% | 0.59 | 9.4 |
typo |
| 10 | 80% | 100% | 100% | 0.90 | 9.2 |
all | 111 | 51% | 77% | 84% | 0.62 | 9.5 |
Measured on 2026-11-10 with version 0.2.0. A search answer is about 220 tokens on the GitHub spec and 180 on Stripe (median).
Paraphrases remain the weak spot: a query whose words are not in the spec ("bookmark a repository", "tag an issue" for labels, "reverse a payment" for refunds) cannot be found by matching words. The query set is hand-written and was also used to tune the ranking, so these figures are optimistic; one query moves a row by 3 to 10 points.
Limitations
Search matches words, not meanings. A query with none of the API's own terms ("bookmark" for star, "chargeback" for dispute) will not find the endpoint; the agent has to search again.
Search understands English only. Filler words, word forms and action synonyms are English.
Large schema graphs are cut. Nested schemas beyond about 4,000 tokens are named, not expanded, so reading a deeply linked model can take several
get_schemacalls.Examples are not shown in the compact summary;
raw: truereturns them.Constraints of array items (for example the
minLengthof each element) are not shown; only those of the array itself are.Referenced documents behind a redirect are not loaded, and a referenced file that changes is only re-read when the main spec changes.
Not covered: callbacks, links, webhooks and the
style/explodeserialization of parameters.
Development
npm install
npm test
npm run benchmark
npm run benchmark:search
node src/server.js path/to/spec.yamlSource layout:
File | Responsibility |
| Command line, |
| The three tools: lookup, error messages and answer text |
| Loading, caching and refreshing the spec |
| Loading referenced documents and the rules for what may be loaded |
| HTTP download with timeout and size limit |
| Compact TypeScript-like and raw YAML rendering |
| Matching a requested path to a path of the spec |
| Search index, stemming and ranking |
| Schema index and which endpoints use each schema |
| Writing the MCP configuration files |
| Benchmarks; not part of the published package |
Tests use Node's built-in runner and need no network, except test/references.test.js, which starts local HTTP servers. The benchmarks download public specs. Changes are listed in CHANGELOG.md.
Notes
The server expects Node.js 18 or newer.
The package name is
@harborkit/openapi-lookup-mcp.The generated MCP server name is
api-specunless--nameis given.OPENAPI_SPEC_URLis the environment variable used when launching the server directly.
Available Tools
3 toolsget_endpointGet API endpoint detailsARead-only
Show the auth, parameters, request body and responses of one API endpoint as a compact summary with referenced schemas resolved. The path may be a template (/users/{id}), a concrete path (/users/42) or a full URL.
Inputs: path (required), raw, method, refresh.
get_schemaGet API schema detailsARead-only
Show one schema (data model) of the API by name as a compact summary with the schemas it references, followed by the endpoints that use it. Use it to read a model without going through an endpoint, or to find which endpoints accept or return it.
Inputs: name (required), raw, refresh.
search_endpointsSearch API endpointsARead-only
Find API endpoints by keywords, best match first. Looks in the path, method, operation id, summary, tags, description, parameter names, schema names and the property names of request and response bodies. Word forms, camelCase or snake_case identifiers and small typos are understood. Returns one line per endpoint, the 10 most relevant by default. The search matches words, not meanings: if the endpoint you need is not listed, search again with the terms this API uses (the results show its vocabulary) or with a synonym.
Inputs: query (required), limit.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 3 tools
Each tool has a clearly distinct role: search finds endpoints, get_endpoint retrieves one endpoint's details, and get_schema retrieves one schema. There is no meaningful overlap between searching, endpoint inspection, and schema inspection.
All three names follow a consistent verb_noun pattern: search_endpoints, get_endpoint, get_schema. The singular/plural distinction is natural and predictable for the resources involved.
Three tools is well-scoped for a focused OpenAPI lookup server. Each tool covers a distinct lookup operation and none feels redundant or extraneous.
The surface covers the core lookup workflow: discover endpoints via search, inspect endpoint details, and inspect schemas. Minor gaps exist, such as no explicit list-all-endpoints or list-all-schemas operation, but search and schema lookups allow agents to work around this.
Maintenance
Related MCP Connectors
Scores how well AI agents will use your API, 0-100, from its OpenAPI spec. Free and read-only.
Provide your AI coding tools with token-efficient access to up-to-date technical documentation for…
Publish your API docs so AI assistants can look up endpoints and call your API correctly.
Turn any task into the right API calls: discover, evaluate, and integrate public APIs.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to explore and query OpenAPI specifications, allowing natural language interaction with API endpoints, parameters, request bodies, and response schemas from any OpenAPI 3.x spec.23 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI coding assistants to automatically scan, store, and query API endpoints from codebases, providing instant lookup and semantic search to reduce context switching and token consumption.1MIT
- FlicenseNot gradedqualityDmaintenanceTurns any OpenAPI/Swagger spec into queryable tools for LLMs, enabling endpoint search, detail retrieval, and schema exploration.1-
- AlicenseNot gradedqualityCmaintenanceProvides AI coding agents with accurate OpenAPI contract details to prevent hallucinated API calls, supporting multi-version pinning, endpoint discovery, and request validation.42 npmApache 2.0