@avidian/mcp-openapi 0.1.2 → 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.
- package/README.md +105 -27
- package/dist/index.js +793 -252
- 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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
"
|
|
91
|
+
"openapi": {
|
|
42
92
|
"command": "mcp-openapi",
|
|
43
|
-
"args": ["
|
|
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
|
-
| `
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
142
|
+
### Security note
|
|
70
143
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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 <
|
|
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.
|
|
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
|
|