@avidian/mcp-openapi 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +105 -27
  2. package/dist/index.js +793 -253
  3. package/package.json +3 -1
package/README.md CHANGED
@@ -1,16 +1,14 @@
1
1
  # @avidian/mcp-openapi
2
2
 
3
- MCP server for OpenAPI/Swagger — gives AI agents the ability to discover, search, and call any REST API described by an OpenAPI or Swagger document.
3
+ MCP server for OpenAPI/Swagger.
4
+ It lets an AI agent discover, inspect, and call any REST API described by an OpenAPI or Swagger document, while keeping the agent's context footprint small.
4
5
 
5
- Point it at a single OpenAPI/Swagger document (URL or local file, 2.0/3.0/3.1) and it exposes:
6
-
7
- - The full, dereferenced document as a readable MCP resource
8
- - A keyword search tool for finding the right operation when a spec defines many of them
9
- - One MCP tool per operation, which proxies a real HTTP request to the underlying API
6
+ Instead of registering one MCP tool per API operation (which pushes every operation's schema into the agent's context up front), this server exposes a small, fixed set of generic **meta-tools**.
7
+ The agent loads one or more specs at runtime, searches and inspects their operations on demand, and executes them - all through the same six tools, no matter how large or how many specs are loaded.
10
8
 
11
9
  ## Installation
12
10
 
13
- ### npm (requires Node.js 20)
11
+ ### npm (requires Node.js >= 20)
14
12
 
15
13
  ```bash
16
14
  npm install -g @avidian/mcp-openapi
@@ -20,27 +18,79 @@ npm install -g @avidian/mcp-openapi
20
18
 
21
19
  Download from [GitHub Releases](https://github.com/avidianity/mcp-openapi/releases).
22
20
 
21
+ ## How it works
22
+
23
+ The server holds an in-memory registry of loaded **specs**.
24
+ Each loaded spec is a single OpenAPI/Swagger document (2.0, 3.0, or 3.1) together with its parsed operations, and is identified by a **spec id** - a lowercase [ULID](https://github.com/ulid/spec) the server generates automatically.
25
+ The agent discovers spec ids by listing what is loaded, then passes an id to the other tools.
26
+ Nothing is persisted: a restart starts fresh and re-runs any startup preloads.
27
+
28
+ ### Meta-tools
29
+
30
+ The server registers exactly these six tools, and never one tool per operation:
31
+
32
+ | Tool | What it does |
33
+ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
34
+ | `load_spec` | Load a spec from a URL, a local file path, or inline JSON/YAML content. Returns a generated spec id and a compact summary. |
35
+ | `list_specs` | List every loaded spec with its id and summary. |
36
+ | `unload_spec` | Remove a loaded spec, freeing its operations and cached search index. |
37
+ | `search_operations` | Search (or, with no query, browse) a spec's operations. Returns compact one-liners; use `describe_operation` for full detail. |
38
+ | `describe_operation` | Return one operation's parameters and request-body schema in full, plus a summarized view of its responses. |
39
+ | `execute_operation` | Perform the real HTTP request for one operation, with arguments grouped by location (path, query, headers, body). |
40
+
41
+ Operations are referenced by their `method` and `path` (for example `get` and `/pets/{petId}`), exactly as `search_operations` reports them.
42
+
23
43
  ## Usage
24
44
 
25
- ```bash
26
- mcp-openapi <openapi-url-or-path> [--base-url <url>] [--timeout <ms>]
27
- ```
45
+ The server can start empty and let the agent load everything at runtime, or preload one or more specs at startup.
28
46
 
29
47
  ```bash
48
+ # Start empty; the agent calls load_spec at runtime.
49
+ mcp-openapi
50
+
51
+ # Preload a single spec (the common case).
30
52
  mcp-openapi https://petstore3.swagger.io/api/v3/openapi.json
31
53
  mcp-openapi ./openapi.yaml --base-url https://api.internal.example.com --timeout 10000
54
+
55
+ # Preload several specs, each with its own settings, from a config file.
56
+ mcp-openapi --config ./specs.json
57
+ ```
58
+
59
+ CLI shape:
60
+
61
+ ```
62
+ mcp-openapi [<source>] [--base-url <url>] [--credential <name>] [--timeout <ms>] [--config <path>]
32
63
  ```
33
64
 
34
- The source may also come from `OPENAPI_URL` instead of the positional argument, which is convenient for MCP client configs.
65
+ The single positional `<source>` may also come from `OPENAPI_URL`, which is convenient for MCP client configs.
66
+
67
+ ### Config file
68
+
69
+ A JSON config file preloads any number of specs, each with an optional per-spec base URL and credential reference:
70
+
71
+ ```json
72
+ {
73
+ "specs": [
74
+ { "source": "https://api.example.com/openapi.json", "credential": "example" },
75
+ { "source": "./internal.yaml", "base_url": "https://api.internal.example.com" }
76
+ ],
77
+ "max_specs": 20,
78
+ "request_timeout_ms": 30000,
79
+ "max_response_bytes": 100000
80
+ }
81
+ ```
82
+
83
+ Unknown keys are rejected so typos surface.
84
+ A preload that fails to load is logged to stderr and skipped; the server still starts, and the agent can load specs at runtime.
35
85
 
36
86
  ### MCP client configuration
37
87
 
38
88
  ```json
39
89
  {
40
90
  "mcpServers": {
41
- "my-api": {
91
+ "openapi": {
42
92
  "command": "mcp-openapi",
43
- "args": ["https://api.example.com/openapi.json"]
93
+ "args": ["--config", "/path/to/specs.json"]
44
94
  }
45
95
  }
46
96
  }
@@ -48,29 +98,52 @@ The source may also come from `OPENAPI_URL` instead of the positional argument,
48
98
 
49
99
  ## Configuration
50
100
 
51
- | Variable | Description |
52
- | ---------------------------- | ----------------------------------------------------------------------------- |
53
- | `OPENAPI_URL` | OpenAPI/Swagger source (URL or local path), if not passed as the CLI argument |
54
- | `OPENAPI_BASE_URL` | Overrides every server URL declared in the spec |
55
- | `OPENAPI_REQUEST_TIMEOUT_MS` | Per-request timeout in milliseconds (default `30000`) |
101
+ | Variable | Description |
102
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------- |
103
+ | `OPENAPI_CONFIG` | Path to a JSON config file listing specs to preload |
104
+ | `OPENAPI_URL` | Single spec source (URL, local path, or inline content) to preload, if not passed as the CLI argument |
105
+ | `OPENAPI_BASE_URL` | Base URL override for the `OPENAPI_URL` / positional spec |
106
+ | `OPENAPI_CREDENTIAL` | Credential reference name for the `OPENAPI_URL` / positional spec |
107
+ | `OPENAPI_REQUEST_TIMEOUT_MS` | Per-request timeout in milliseconds (default `30000`) |
108
+ | `OPENAPI_MAX_RESPONSE_BYTES` | Cap on response bytes read from an upstream API (default `100000`) |
109
+ | `OPENAPI_MAX_SPECS` | Maximum number of specs that may be loaded at once (default `20`) |
110
+
111
+ Precedence for these knobs is: environment variable > config file > default.
112
+ The request timeout additionally accepts the `--timeout` CLI flag, which wins over the environment variable; the response cap and max-specs knobs have no CLI flag.
56
113
 
57
114
  ### Authentication
58
115
 
59
- For each security scheme declared in the OpenAPI document, credentials are read from environment variables named after the scheme (converted to `SCREAMING_SNAKE_CASE`) — e.g. a scheme called `apiKeyAuth` reads `OPENAPI_AUTH_API_KEY_AUTH`.
116
+ Credentials are always provisioned by the operator in the environment and resolved server-side; a secret value never passes through the agent.
117
+
118
+ The recommended approach is **credential references**.
119
+ The operator provisions a secret under a reference name, and the agent (or config file) passes only that name to `load_spec`:
120
+
121
+ | Scheme type | Environment variables (for reference name `<REF>`) |
122
+ | ------------------------------ | --------------------------------------------------------------- |
123
+ | HTTP bearer | `OPENAPI_CRED_<REF>_TOKEN` (or bare `OPENAPI_CRED_<REF>`) |
124
+ | HTTP basic | `OPENAPI_CRED_<REF>_USERNAME` and `OPENAPI_CRED_<REF>_PASSWORD` |
125
+ | apiKey (header, query, cookie) | `OPENAPI_CRED_<REF>` |
60
126
 
61
- | Scheme type | Environment variables |
127
+ For example, provisioning `OPENAPI_CRED_GITHUB_TOKEN` and loading with `credential: "github"` applies that token to the spec's security scheme(s).
128
+ A reference is applied only to the schemes named in the document's `security` requirement, so one secret is not sprayed across unrelated schemes.
129
+ (When the document declares no top-level `security`, the reference is applied to every scheme it defines.)
130
+
131
+ When no `credential` is given, the server falls back to matching each of the document's security schemes by name (converted to `SCREAMING_SNAKE_CASE`):
132
+
133
+ | Scheme type | Environment variables (for scheme `<SCHEME>`) |
62
134
  | ------------------------------ | --------------------------------------------------------------------- |
63
135
  | HTTP bearer | `OPENAPI_AUTH_<SCHEME>_TOKEN` (or bare `OPENAPI_AUTH_<SCHEME>`) |
64
136
  | HTTP basic | `OPENAPI_AUTH_<SCHEME>_USERNAME` and `OPENAPI_AUTH_<SCHEME>_PASSWORD` |
65
137
  | apiKey (header, query, cookie) | `OPENAPI_AUTH_<SCHEME>` |
66
138
 
67
- Schemes with no matching environment variable, and unsupported types (OAuth2, OpenID Connect), are skipped with a warning rather than failing startup.
139
+ Schemes with no matching environment variable are skipped silently; unsupported types (OAuth2, OpenID Connect) are skipped with a warning.
140
+ Neither case fails startup.
68
141
 
69
- ## What it exposes
142
+ ### Security note
70
143
 
71
- - **Resource** `openapi://spec` the full, dereferenced OpenAPI/Swagger document.
72
- - **Tool** `search_operations` keyword search across every operation's name, summary, description, tags, and path. Use this first when a spec defines many operations.
73
- - **One tool per operation** named after its `operationId` (sanitized and deduplicated), taking the operation's path/query/header parameters and request body as arguments.
144
+ `load_spec` fetches whatever URL or reads whatever local file the agent asks it to, and `execute_operation` calls the base URL declared by (or overridden for) a loaded spec, attaching the operator-provisioned credentials.
145
+ This is intrinsic to the tool's purpose, but it means a spec pointing at an internal or metadata endpoint would be fetched and called from wherever the server runs.
146
+ Run the server in an environment where that request surface is acceptable, and only provision credentials for APIs you intend the agent to call.
74
147
 
75
148
  ## Development
76
149
 
@@ -79,7 +152,7 @@ Schemes with no matching environment variable, and unsupported types (OAuth2, Op
79
152
  bun install
80
153
 
81
154
  # Run in dev mode
82
- bun run dev <openapi-url-or-path>
155
+ bun run dev [<source>]
83
156
 
84
157
  # Type check
85
158
  bun run typecheck
@@ -93,6 +166,9 @@ bun run format
93
166
  # Test
94
167
  bun run test
95
168
 
169
+ # Everything the CI gate runs
170
+ bun run check
171
+
96
172
  # Build for npm
97
173
  bun run build
98
174
 
@@ -100,7 +176,9 @@ bun run build
100
176
  bun run compile
101
177
  ```
102
178
 
103
- `ajv` is listed as a direct devDependency even though nothing in `src/` imports it. It's a workaround: `@apidevtools/swagger-parser` depends on `ajv-draft-04`, which only declares `ajv` as a peer dependency, and Bun's bundler fails to statically resolve that peer dependency when producing standalone binaries (`bun run compile`) unless `ajv` is also resolvable as a direct dependency somewhere in the root of the tree. Not needed for `bun run build` (the npm-published bundle), which keeps `@apidevtools/swagger-parser` external and lets Node resolve it normally at install time.
179
+ `ajv` is listed as a direct devDependency even though nothing in `src/` imports it.
180
+ It's a workaround: `@apidevtools/swagger-parser` depends on `ajv-draft-04`, which only declares `ajv` as a peer dependency, and Bun's bundler fails to statically resolve that peer dependency when producing standalone binaries (`bun run compile`) unless `ajv` is also resolvable as a direct dependency somewhere in the root of the tree.
181
+ Not needed for `bun run build` (the npm-published bundle), which keeps `@apidevtools/swagger-parser` external and lets Node resolve it normally at install time.
104
182
 
105
183
  ## License
106
184