@powerduck/openapi-mcp-server 1.1.0 → 1.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 (2) hide show
  1. package/README.md +336 -191
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,278 +1,423 @@
1
1
  # @powerduck/openapi-mcp-server
2
2
 
3
- A production-oriented TypeScript library and runtime that converts OpenAPI documents into MCP (Model Context Protocol) services. Built on top of `@powerduck/openapi-parser` for robust OpenAPI validation and dereferencing.
3
+ Turn any OpenAPI 3.2 document into a fully functional MCP (Model Context Protocol) server. Automatically generates tools, prompts, and resources from your API spec. Supports both stdio and HTTP (SSE) transports.
4
4
 
5
- ## Features
5
+ [![npm version](https://img.shields.io/npm/v/@powerduck/openapi-mcp-server)](https://www.npmjs.com/package/@powerduck/openapi-mcp-server)
6
+ [![license](https://img.shields.io/npm/l/@powerduck/openapi-mcp-server)](https://github.com/PowerDuckie/openapi-mcp-server/blob/main/LICENSE)
7
+
8
+ ## Links
9
+
10
+ - [Official Website](https://www.powerduck.com/opensource/openapi-mcp-server.html)
11
+ - [Documentation](https://www.powerduck.com/docs/openapi-mcp-server/introduction)
12
+ - [Live Demo](https://www.powerduck.com/demo/openapi-mcp-server.html)
13
+ - [GitHub](https://github.com/PowerDuckie/openapi-mcp-server)
14
+ - [npm](https://www.npmjs.com/package/@powerduck/openapi-mcp-server)
6
15
 
7
- - **Tools** generated from OpenAPI operations with full parameter serialization
8
- - **Prompts** generated from API metadata and operations
9
- - **Resources** generated from the OpenAPI catalog
10
- - **HTTP (SSE)** and **STDIO** MCP transports
11
- - **Admin Web UI** for managing specs and services
12
- - **Persistent runtime state** with config storage
13
- - **Strong validation** and safer request execution
14
- - **Dual module support**: ESM and CommonJS
15
- - **TypeScript-first** with full type definitions
16
- - **91+ tests** covering core utilities, spec loading, and module exports
16
+ ---
17
17
 
18
- ## Install
18
+ ## Quick Start
19
+
20
+ ### Install
19
21
 
20
22
  ```bash
21
23
  npm install @powerduck/openapi-mcp-server
22
24
  ```
23
25
 
24
- ## Quick Start
26
+ ### Run as a stdio server (CLI)
25
27
 
26
- ### CLI Usage
28
+ ```bash
29
+ npx @powerduck/openapi-mcp-server serve --spec ./openapi.json
30
+ ```
27
31
 
28
- #### Web Mode (with Admin UI)
32
+ ### Run as an HTTP server (CLI)
29
33
 
30
34
  ```bash
31
- openapi-mcp serve \
32
- --transport web \
35
+ npx @powerduck/openapi-mcp-server serve \
36
+ --spec ./openapi.json \
37
+ --transport http \
33
38
  --port 3000 \
34
- --host 127.0.0.1 \
35
- --api-key your-admin-key
39
+ --route-prefix /mcp
36
40
  ```
37
41
 
38
- #### STDIO Mode
42
+ ### Programmatic stdio server
39
43
 
40
- ```bash
41
- openapi-mcp serve \
42
- --transport stdio \
43
- --spec ./openapi.yaml \
44
- --base-url https://api.example.com
45
- ```
44
+ ```typescript
45
+ import { startStdioServer } from "@powerduck/openapi-mcp-server";
46
46
 
47
- ### Programmatic API
47
+ await startStdioServer({
48
+ specPath: "./openapi.json",
49
+ serverName: "My API MCP Server",
50
+ serverVersion: "1.0.0",
51
+ });
52
+ ```
48
53
 
49
- #### Load and Validate an OpenAPI Document
54
+ ### Programmatic HTTP server (Express)
50
55
 
51
56
  ```typescript
52
- import { loadOpenApiSpec, parseSpecContent } from "@powerduck/openapi-mcp-server";
57
+ import express from "express";
58
+ import { attachSseRoutes } from "@powerduck/openapi-mcp-server";
53
59
 
54
- // Load from file (JSON or YAML)
55
- const spec = await loadOpenApiSpec("./openapi.yaml");
60
+ const app = express();
56
61
 
57
- // Parse from string content
58
- const specFromText = await parseSpecContent(
59
- '{"openapi": "3.1.0", "info": {...}, "paths": {...}}',
60
- false, // isYaml
62
+ attachSseRoutes(
63
+ app,
64
+ () => "./openapi.json", // spec provider: path, URL, or parsed document
65
+ () => ({ userId: "user-123" }), // context provider (optional)
66
+ (req) => req.headers["x-api-key"] === "secret", // route guard (optional)
61
67
  );
68
+
69
+ app.listen(3000, () => {
70
+ console.log("MCP SSE server running at http://localhost:3000/mcp");
71
+ });
62
72
  ```
63
73
 
64
- #### Generate MCP Tools
74
+ ### Generate tools from a spec
65
75
 
66
76
  ```typescript
67
- import { generateTools, buildBindingIndex } from "@powerduck/openapi-mcp-server";
77
+ import { loadOpenApiSpec, generateTools } from "@powerduck/openapi-mcp-server";
68
78
 
79
+ const spec = await loadOpenApiSpec("./openapi.json");
69
80
  const tools = generateTools(spec);
70
- const bindingIndex = buildBindingIndex(spec);
71
81
 
72
- // tools is an array of MCP Tool definitions
73
- // bindingIndex maps operationIds to tool names
82
+ console.log(`Generated ${tools.length} tools:`);
83
+ for (const tool of tools) {
84
+ console.log(`- ${tool.name}: ${tool.description}`);
85
+ }
74
86
  ```
75
87
 
76
- #### Generate Prompts and Resources
88
+ ---
77
89
 
78
- ```typescript
79
- import { generatePrompts, generateResources } from "@powerduck/openapi-mcp-server";
90
+ ## Features
91
+
92
+ - **Automatic tool generation** — every operation becomes an MCP tool with a JSON Schema input schema derived from parameters and request body
93
+ - **Prompt generation** — operations with `x-mcp-prompt` become MCP prompts with templated messages
94
+ - **Resource generation** — operations marked with `x-mcp-resource` become readable MCP resources
95
+ - **Two transports** — stdio for local CLI tools and IDEs, HTTP (SSE) for remote servers and web clients
96
+ - **Authentication** — Bearer token, API key, and custom auth middleware for HTTP transport
97
+ - **Admin server** — optional REST admin API for health checks, spec reload, and diagnostics
98
+ - **Context injection** — per-request context provider for user IDs, tenant info, etc.
99
+ - **Route guards** — custom authorization function for HTTP transport
100
+ - **Spec loading** — load from file path, URL, or parsed object; JSON and YAML supported
101
+ - **Built on `@powerduck/openapi-request`** — full OpenAPI parameter serialization for tool execution
102
+ - **Dual ESM/CJS builds** — works with `import` and `require`
80
103
 
81
- const prompts = generatePrompts(spec);
82
- const resources = generateResources(spec);
104
+ ---
105
+
106
+ ## CLI Usage
107
+
108
+ ```
109
+ openapi-mcp serve [options]
110
+
111
+ Options:
112
+ --spec <path> Path or URL to OpenAPI 3.2 spec (required)
113
+ --transport <mode> Transport mode: stdio or http (default: stdio)
114
+ --port <number> HTTP server port (default: 3000)
115
+ --host <string> HTTP server host (default: 0.0.0.0)
116
+ --route-prefix <path> HTTP route prefix for MCP endpoints (default: /mcp)
117
+ --server-name <name> MCP server name (default: OpenAPI MCP Server)
118
+ --server-version <ver> MCP server version (default: 1.0.0)
119
+ --admin Enable admin REST API
120
+ --admin-port <number> Admin server port (default: 3001)
121
+ --auth-type <type> Auth type: bearer, apikey, or none (default: none)
122
+ --auth-token <token> Bearer token or API key value
123
+ --auth-header <name> API key header name (default: x-api-key)
124
+ -h, --help Show help
125
+ -v, --version Show version
83
126
  ```
84
127
 
85
- #### Build an MCP Server
128
+ ---
86
129
 
87
- ```typescript
88
- import { buildMcpServer, startStdioServer, attachSseRoutes } from "@powerduck/openapi-mcp-server";
89
- import express from "express";
130
+ ## MCP Extensions
90
131
 
91
- // Build a server with custom spec and context providers
92
- const server = buildMcpServer({
93
- specProvider: async () => spec,
94
- contextProvider: async () => ({ baseUrl: "https://api.example.com" }),
95
- });
132
+ Control how operations are exposed to MCP clients using OpenAPI extensions:
96
133
 
97
- // STDIO transport
98
- await startStdioServer(server);
134
+ ### `x-mcp-tool`
99
135
 
100
- // HTTP/SSE transport
101
- const app = express();
102
- attachSseRoutes(app, server, { path: "/mcp" });
103
- app.listen(3000);
136
+ Mark an operation as an MCP tool (all operations are tools by default):
137
+
138
+ ```json
139
+ {
140
+ "paths": {
141
+ "/users/{id}": {
142
+ "get": {
143
+ "operationId": "getUser",
144
+ "x-mcp-tool": {
145
+ "name": "get_user",
146
+ "description": "Fetch a user by ID"
147
+ }
148
+ }
149
+ }
150
+ }
151
+ }
104
152
  ```
105
153
 
106
- #### Execute Tool Calls
154
+ ### `x-mcp-prompt`
155
+
156
+ Mark an operation as an MCP prompt:
157
+
158
+ ```json
159
+ {
160
+ "paths": {
161
+ "/search": {
162
+ "get": {
163
+ "operationId": "search",
164
+ "x-mcp-prompt": {
165
+ "name": "search_docs",
166
+ "description": "Search the documentation",
167
+ "arguments": [
168
+ { "name": "query", "description": "Search query", "required": true }
169
+ ],
170
+ "messages": [
171
+ { "role": "user", "content": "Search for: {{query}}" }
172
+ ]
173
+ }
174
+ }
175
+ }
176
+ }
177
+ }
178
+ ```
107
179
 
108
- ```typescript
109
- import { executeToolCall } from "@powerduck/openapi-mcp-server";
110
-
111
- const result = await executeToolCall({
112
- toolName: "get_user",
113
- arguments: { id: "123" },
114
- spec,
115
- baseUrl: "https://api.example.com",
116
- headers: { Authorization: "Bearer token" },
117
- });
180
+ ### `x-mcp-resource`
181
+
182
+ Mark an operation as a readable MCP resource:
183
+
184
+ ```json
185
+ {
186
+ "paths": {
187
+ "/docs/{slug}": {
188
+ "get": {
189
+ "operationId": "getDoc",
190
+ "x-mcp-resource": {
191
+ "uriTemplate": "docs://{slug}",
192
+ "name": "Documentation page",
193
+ "mimeType": "text/markdown"
194
+ }
195
+ }
196
+ }
197
+ }
198
+ }
118
199
  ```
119
200
 
120
- #### Spec Utility Functions
201
+ ### `x-mcp-ignore`
121
202
 
122
- ```typescript
123
- import {
124
- iterateOperations,
125
- findOperationById,
126
- findDuplicateOperationIds,
127
- assertUniqueOperationIds,
128
- extractPathTemplateVariables,
129
- synthesizeOperationId,
130
- ensureUniqueName,
131
- collectOperationParameters,
132
- effectiveStyle,
133
- effectiveExplode,
134
- } from "@powerduck/openapi-mcp-server";
135
-
136
- // Iterate all operations
137
- for (const op of iterateOperations(spec)) {
138
- console.log(op.method, op.path, op.operation?.operationId);
203
+ Exclude an operation from MCP entirely:
204
+
205
+ ```json
206
+ {
207
+ "paths": {
208
+ "/internal/debug": {
209
+ "get": {
210
+ "x-mcp-ignore": true
211
+ }
212
+ }
213
+ }
139
214
  }
215
+ ```
140
216
 
141
- // Find operation by ID
142
- const operation = findOperationById(spec, "getUser");
217
+ ---
143
218
 
144
- // Check for duplicate operation IDs
145
- const duplicates = findDuplicateOperationIds(spec);
219
+ ## Programmatic API
146
220
 
147
- // Extract path variables
148
- const vars = extractPathTemplateVariables("/users/{userId}/posts/{postId}");
149
- // => ["userId", "postId"]
150
- ```
221
+ ### `loadOpenApiSpec(input)`
151
222
 
152
- #### Build HTTP Requests
223
+ Loads an OpenAPI spec from a file path, URL, or parsed object. Returns the parsed document.
153
224
 
154
225
  ```typescript
155
- import { buildRequest } from "@powerduck/openapi-mcp-server";
226
+ const spec = await loadOpenApiSpec("./openapi.json");
227
+ const specFromUrl = await loadOpenApiSpec("https://api.example.com/openapi.json");
228
+ const specFromObject = await loadOpenApiSpec({ openapi: "3.2.0", ... });
229
+ ```
156
230
 
157
- const request = buildRequest({
158
- operation,
159
- pathItem,
160
- arguments: { id: "123", include: ["profile", "posts"] },
161
- baseUrl: "https://api.example.com",
162
- });
231
+ ### `generateTools(spec)`
232
+
233
+ Generates an array of MCP tool definitions from the spec.
234
+
235
+ ### `generateToolsDetailed(spec)`
236
+
237
+ Generates tools with additional metadata (operationId, path, method).
238
+
239
+ ### `generatePrompts(spec)`
240
+
241
+ Generates MCP prompt definitions from operations with `x-mcp-prompt`.
242
+
243
+ ### `generateResources(spec)`
244
+
245
+ Generates MCP resource definitions from operations with `x-mcp-resource`.
163
246
 
164
- // request contains: method, url, headers, body
247
+ ### `executeToolCall(spec, toolName, arguments, context?)`
248
+
249
+ Executes a tool by name, passing the arguments and optional context. Returns the tool result.
250
+
251
+ ### `buildMcpServer(options)`
252
+
253
+ Builds an MCP server instance (transport-agnostic).
254
+
255
+ ### `startStdioServer(options)`
256
+
257
+ Starts a stdio MCP server. Blocks until the server is closed.
258
+
259
+ ### `attachSseRoutes(app, specProvider, contextProvider?, routeGuard?)`
260
+
261
+ Attaches MCP SSE routes to an Express-compatible app. This is the public API for HTTP transport.
262
+
263
+ | Parameter | Type | Description |
264
+ |---|---|---|
265
+ | `app` | `Express` | Express app instance |
266
+ | `specProvider` | `() => string \| object \| Promise<string \| object>` | Returns spec path, URL, or parsed document |
267
+ | `contextProvider` | `(req) => Record<string, unknown> \| Promise<Record<string, unknown>>` | Optional. Returns per-request context |
268
+ | `routeGuard` | `(req) => boolean \| Promise<boolean>` | Optional. Returns true if the request is authorized |
269
+
270
+ ### `startAdminServer(options)`
271
+
272
+ Starts an optional admin REST API server for health checks and diagnostics.
273
+
274
+ ---
275
+
276
+ ## Authentication
277
+
278
+ ### Bearer token (HTTP)
279
+
280
+ ```typescript
281
+ import { createAuthMiddleware } from "@powerduck/openapi-mcp-server";
282
+
283
+ app.use("/mcp", createAuthMiddleware({
284
+ type: "bearer",
285
+ token: "your-secret-token",
286
+ }));
165
287
  ```
166
288
 
167
- #### Admin Server and Auth
289
+ ### API key (HTTP)
168
290
 
169
291
  ```typescript
170
- import { startAdminServer, createAuthMiddleware } from "@powerduck/openapi-mcp-server";
292
+ app.use("/mcp", createAuthMiddleware({
293
+ type: "apikey",
294
+ token: "your-api-key",
295
+ headerName: "x-api-key",
296
+ }));
297
+ ```
171
298
 
172
- const app = await startAdminServer({
173
- port: 3000,
174
- host: "127.0.0.1",
175
- apiKey: "your-admin-key",
176
- });
299
+ ### Custom auth
177
300
 
178
- // Or use auth middleware in your own Express app
179
- import express from "express";
180
- const myApp = express();
181
- myApp.use("/admin", createAuthMiddleware({ apiKey: "secret" }));
301
+ Use the `routeGuard` parameter of `attachSseRoutes`:
302
+
303
+ ```typescript
304
+ attachSseRoutes(
305
+ app,
306
+ specProvider,
307
+ contextProvider,
308
+ (req) => {
309
+ return verifyJwt(req.headers.authorization);
310
+ },
311
+ );
182
312
  ```
183
313
 
184
- ## Project Structure
314
+ ---
315
+
316
+ ## Context Injection
317
+
318
+ Pass per-request context (user ID, tenant, etc.) to tool executions:
185
319
 
320
+ ```typescript
321
+ attachSseRoutes(
322
+ app,
323
+ () => "./openapi.json",
324
+ (req) => ({
325
+ userId: req.headers["x-user-id"],
326
+ tenantId: req.headers["x-tenant-id"],
327
+ }),
328
+ );
186
329
  ```
187
- src/
188
- ├── core/
189
- │ ├── openapi-loader.ts # Spec loading, validation, dereferencing
190
- │ ├── spec-utils.ts # Operation traversal, parameter normalization
191
- │ ├── tool-generator.ts # MCP tool generation from operations
192
- │ ├── request-builder.ts # HTTP request construction with serialization
193
- │ ├── http-executor.ts # Safe HTTP request execution
194
- │ └── global-utils.ts # Shared utilities (IDs, error detection)
195
- ├── mcp/
196
- │ ├── create-server.ts # MCP server construction
197
- │ ├── transport-stdio.ts # STDIO transport
198
- │ └── transport-http.ts # HTTP/SSE transport
199
- ├── registry/
200
- │ ├── prompt-registry.ts # Prompt generation and resolution
201
- │ └── resource-registry.ts # Resource generation and reading
202
- ├── runtime/
203
- │ └── service-registry.ts # Runtime service management
204
- ├── server/
205
- │ ├── admin-server.ts # Admin HTTP server with Web UI
206
- │ └── auth.ts # Authentication middleware
207
- ├── config/
208
- │ └── config-store.ts # Persistent configuration storage
209
- ├── webui/
210
- │ └── index.html # Admin Web UI
211
- ├── types.ts # Shared TypeScript types
212
- ├── cli.ts # CLI entry point
213
- └── index.ts # Library exports
330
+
331
+ The context is available in tool execution and can be used for authorization or data scoping.
332
+
333
+ ---
334
+
335
+ ## Admin Server
336
+
337
+ Enable the admin REST API with `--admin` or programmatically:
338
+
339
+ ```typescript
340
+ import { startAdminServer } from "@powerduck/openapi-mcp-server";
341
+
342
+ await startAdminServer({
343
+ port: 3001,
344
+ specPath: "./openapi.json",
345
+ });
214
346
  ```
215
347
 
216
- ## Web UI
348
+ ### Endpoints
217
349
 
218
- The admin UI supports:
350
+ | Method | Path | Description |
351
+ |---|---|---|
352
+ | `GET` | `/health` | Health check |
353
+ | `GET` | `/spec` | Current loaded spec info |
354
+ | `POST` | `/reload` | Reload the spec from disk |
355
+ | `GET` | `/tools` | List generated tools |
356
+ | `GET` | `/prompts` | List generated prompts |
357
+ | `GET` | `/resources` | List generated resources |
219
358
 
220
- - Upload and paste OpenAPI documents (JSON or YAML)
221
- - View generated tools, prompts, and resources
222
- - Inspect running runtime services
223
- - Stop services
224
- - Basic MCP debugging hints
225
- - SSE endpoint discovery
226
- - STDIO configuration guidance
359
+ ---
227
360
 
228
- ## Testing
361
+ ## MCP Client Configuration (Claude Desktop)
229
362
 
230
- ```bash
231
- # Run all tests
232
- npm test
363
+ Add to your `claude_desktop_config.json`:
233
364
 
234
- # Run tests in watch mode
235
- npm run test:watch
365
+ ```json
366
+ {
367
+ "mcpServers": {
368
+ "my-api": {
369
+ "command": "npx",
370
+ "args": ["@powerduck/openapi-mcp-server", "serve", "--spec", "/path/to/openapi.json"]
371
+ }
372
+ }
373
+ }
374
+ ```
375
+
376
+ For HTTP transport:
236
377
 
237
- # Run tests with coverage
238
- npm run test:coverage
378
+ ```json
379
+ {
380
+ "mcpServers": {
381
+ "my-api": {
382
+ "url": "http://localhost:3000/mcp"
383
+ }
384
+ }
385
+ }
239
386
  ```
240
387
 
241
- Test coverage includes:
388
+ ---
242
389
 
243
- - **Global utilities**: ID generation, abort error detection
244
- - **Spec utilities**: operation iteration, parameter normalization, name uniqueness
245
- - **OpenAPI loader**: JSON/YAML parsing, validation, dereferencing, error handling
246
- - **Module exports**: all public API surface verification
390
+ ## Development
247
391
 
248
- ## Production Notes
392
+ ```bash
393
+ # Install dependencies
394
+ npm install
249
395
 
250
- This version is production-oriented. For full SaaS deployment, consider adding:
396
+ # Type check
397
+ npm run typecheck
251
398
 
252
- - Tenant isolation
253
- - Database-backed project registry
254
- - Rate limits
255
- - Audit logs
256
- - Role-based access control (RBAC)
257
- - Secure secret storage
258
- - Upstream host allowlists
399
+ # Build (ESM + CJS + type declarations)
400
+ npm run build
259
401
 
260
- ## Dependencies
402
+ # Run tests
403
+ npm test
261
404
 
262
- - `@powerduck/openapi-parser` — OpenAPI validation, dereferencing, and upgrade (replaces `@scalar/openapi-parser`)
263
- - `@modelcontextprotocol/sdk` — MCP protocol implementation
264
- - `express` — HTTP server for admin UI and SSE transport
265
- - `axios` — HTTP client for tool execution
266
- - `commander` — CLI framework
267
- - `js-yaml` — YAML parsing
268
- - `multer` — File upload handling
269
- - `cors` — CORS middleware
270
- - `terser` — Minification for embedded assets
405
+ # Watch mode
406
+ npx vitest watch
407
+ ```
271
408
 
272
- ## License
409
+ ---
410
+
411
+ ## Related Packages
273
412
 
274
- MIT © Powerduck limited
413
+ - [`@powerduck/openapi-parser`](https://www.npmjs.com/package/@powerduck/openapi-parser) OpenAPI 3.2 parser, validator, and upgrader
414
+ - [`@powerduck/openapi-request`](https://www.npmjs.com/package/@powerduck/openapi-request) — Execute OpenAPI operations with full parameter serialization
415
+ - [`@powerduck/openapi-codegen`](https://www.npmjs.com/package/@powerduck/openapi-codegen) — Generate runnable request examples in 21 languages
416
+ - [`@powerduck/openapi-cli`](https://www.npmjs.com/package/@powerduck/openapi-cli) — CI-ready batch testing for OpenAPI documents
417
+ - [`@powerduck/x-to-openapi`](https://www.npmjs.com/package/@powerduck/x-to-openapi) — Convert curl commands and Postman Collections to OpenAPI 3.2
275
418
 
276
- ## Important Implementation Policy
419
+ ---
420
+
421
+ ## License
277
422
 
278
- All source comments are written in American English. No Chinese characters are permitted in the codebase.
423
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerduck/openapi-mcp-server",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Production-oriented OpenAPI to MCP server library with Tools, Prompts, Resources, Web UI, and admin runtime.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",