openapi-dynamic-mcp 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.
- package/README.md +79 -11
- package/dist/auth/env.d.ts +7 -1
- package/dist/auth/env.js +25 -12
- package/dist/auth/env.js.map +1 -1
- package/dist/auth/oauthClient.d.ts +1 -1
- package/dist/auth/oauthClient.js +13 -13
- package/dist/auth/oauthClient.js.map +1 -1
- package/dist/auth/resolveAuth.d.ts +3 -3
- package/dist/auth/resolveAuth.js +58 -19
- package/dist/auth/resolveAuth.js.map +1 -1
- package/dist/cli.js +11 -11
- package/dist/cli.js.map +1 -1
- package/dist/config/loadConfig.d.ts +1 -1
- package/dist/config/loadConfig.js +46 -34
- package/dist/config/loadConfig.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +7 -7
- package/dist/http/requestExecutor.d.ts +3 -2
- package/dist/http/requestExecutor.js +199 -67
- package/dist/http/requestExecutor.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +6 -6
- package/dist/mcp/context.d.ts +2 -2
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +83 -58
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/common.d.ts +4 -4
- package/dist/mcp/tools/common.js +14 -14
- package/dist/mcp/tools/getApiEndpoint.d.ts +2 -2
- package/dist/mcp/tools/getApiEndpoint.js +19 -15
- package/dist/mcp/tools/getApiEndpoint.js.map +1 -1
- package/dist/mcp/tools/getApiSchema.d.ts +2 -2
- package/dist/mcp/tools/getApiSchema.js +6 -6
- package/dist/mcp/tools/getApiSchema.js.map +1 -1
- package/dist/mcp/tools/index.d.ts +5 -5
- package/dist/mcp/tools/index.js +5 -5
- package/dist/mcp/tools/listApiEndpoints.d.ts +2 -2
- package/dist/mcp/tools/listApiEndpoints.js +4 -4
- package/dist/mcp/tools/listApis.d.ts +2 -2
- package/dist/mcp/tools/listApis.js +2 -2
- package/dist/mcp/tools/makeEndpointRequest.d.ts +2 -2
- package/dist/mcp/tools/makeEndpointRequest.js +21 -19
- package/dist/mcp/tools/makeEndpointRequest.js.map +1 -1
- package/dist/openapi/endpointIndex.d.ts +2 -2
- package/dist/openapi/endpointIndex.js +13 -13
- package/dist/openapi/endpointIndex.js.map +1 -1
- package/dist/openapi/jsonPointer.js +15 -12
- package/dist/openapi/jsonPointer.js.map +1 -1
- package/dist/openapi/loadSpec.d.ts +1 -1
- package/dist/openapi/loadSpec.js +44 -17
- package/dist/openapi/loadSpec.js.map +1 -1
- package/dist/types.d.ts +29 -9
- package/dist/types.js +9 -1
- package/dist/types.js.map +1 -1
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@ TypeScript MCP stdio server that loads one or more OpenAPI 3.x specs from YAML c
|
|
|
5
5
|
## What It Does
|
|
6
6
|
|
|
7
7
|
- Runs as a single MCP stdio server for multiple APIs.
|
|
8
|
-
- Supports OpenAPI `3.x`
|
|
8
|
+
- Supports OpenAPI `3.x` and Swagger `2.0` specifications.
|
|
9
|
+
- Supports local spec files via `specPath` or remote URL specs via `specUrl`.
|
|
9
10
|
- Exposes generic MCP tools:
|
|
10
11
|
- `list_apis`
|
|
11
12
|
- `list_api_endpoints`
|
|
@@ -14,6 +15,7 @@ TypeScript MCP stdio server that loads one or more OpenAPI 3.x specs from YAML c
|
|
|
14
15
|
- `make_endpoint_request`
|
|
15
16
|
- Supports auth:
|
|
16
17
|
- `apiKey`
|
|
18
|
+
- HTTP `bearer` and `basic` (`http`)
|
|
17
19
|
- OAuth2 client credentials (`oauth2`)
|
|
18
20
|
- combined OpenAPI security requirements (AND inside object, OR across array)
|
|
19
21
|
- Supports per-API environment overrides for:
|
|
@@ -88,8 +90,10 @@ version: 1
|
|
|
88
90
|
apis:
|
|
89
91
|
# Unique ID for this API
|
|
90
92
|
- name: pet-api
|
|
91
|
-
# Path to local OpenAPI spec
|
|
93
|
+
# Path to local OpenAPI spec (use specUrl for remote definitions)
|
|
92
94
|
specPath: ./pet-api.yaml
|
|
95
|
+
# Alternative: remote OpenAPI spec URL
|
|
96
|
+
# specUrl: https://api.example.com/openapi.yaml
|
|
93
97
|
# Base URL override
|
|
94
98
|
baseUrl: https://api.example.com/v1
|
|
95
99
|
# Request timeout in milliseconds
|
|
@@ -124,8 +128,8 @@ apis:
|
|
|
124
128
|
### Validation Rules
|
|
125
129
|
|
|
126
130
|
- `apis[].name` must be unique (case-insensitive after normalization).
|
|
127
|
-
- `apis[].specPath`
|
|
128
|
-
- OpenAPI
|
|
131
|
+
- Exactly one of `apis[].specPath` (local file) or `apis[].specUrl` (remote URL) must be provided.
|
|
132
|
+
- Supported specifications: OpenAPI `3.x` and Swagger `2.0`.
|
|
129
133
|
- Base URL resolution order: env -> config -> `openapi.servers[0].url`.
|
|
130
134
|
|
|
131
135
|
## Environment Variables
|
|
@@ -157,6 +161,14 @@ For each API key security scheme defined in the OpenAPI spec, the following envi
|
|
|
157
161
|
|
|
158
162
|
- `<API>_<SCHEME>_API_KEY` - The API key value for the specified security scheme.
|
|
159
163
|
|
|
164
|
+
### HTTP Authentication Variables
|
|
165
|
+
|
|
166
|
+
For each HTTP Bearer or Basic security scheme defined in the OpenAPI spec:
|
|
167
|
+
|
|
168
|
+
- `<API>_<SCHEME>_TOKEN` - The Bearer token value.
|
|
169
|
+
- `<API>_<SCHEME>_USERNAME` - The Basic auth username.
|
|
170
|
+
- `<API>_<SCHEME>_PASSWORD` - The Basic auth password.
|
|
171
|
+
|
|
160
172
|
### OAuth2 Client Credentials Variables
|
|
161
173
|
|
|
162
174
|
For each OAuth2 client credentials security scheme defined in the OpenAPI spec, the following environment variables can be set:
|
|
@@ -174,6 +186,67 @@ For each OAuth2 client credentials security scheme defined in the OpenAPI spec,
|
|
|
174
186
|
- OAuth scopes: scheme env > config scopes > OpenAPI flow scopes.
|
|
175
187
|
- Headers: config headers + env headers + tool-request headers (later wins), then auth is applied.
|
|
176
188
|
|
|
189
|
+
## Handling Binary Data and File Uploads
|
|
190
|
+
|
|
191
|
+
When your LLM needs to send a file to an endpoint (either raw `application/octet-stream`, or inside a `multipart/form-data` payload), MCP passes messages as JSON. To do this, the LLM should format the corresponding file using the **files** parameter mapping.
|
|
192
|
+
|
|
193
|
+
The `make_endpoint_request` tool intercepts the `files` argument dict and processes each entry natively (e.g., converting to Blobs and FormData for accurate multipart boundary generation).
|
|
194
|
+
|
|
195
|
+
### MCP File Descriptor format
|
|
196
|
+
|
|
197
|
+
Each key in the `files` object maps to a form field name, and the value must follow this format:
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"name": "avatar.png", // (Optional) Explicit file name
|
|
202
|
+
"contentType": "image/png", // (Optional) Explicit mime type
|
|
203
|
+
|
|
204
|
+
// You must provide EXACTLY ONE of the following content fields:
|
|
205
|
+
"base64": "iVBORw0KGgo...", // Base64 encoded bytes
|
|
206
|
+
"text": "File contents", // Raw text content
|
|
207
|
+
"filePath": "/path/to/img" // Local absolute file path to read
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Example: Multipart Form-Data
|
|
212
|
+
|
|
213
|
+
If an endpoint expects a `profileImage` file and a `description` string via `multipart/form-data`:
|
|
214
|
+
|
|
215
|
+
```json
|
|
216
|
+
{
|
|
217
|
+
"apiName": "pet-api",
|
|
218
|
+
"endpointId": "uploadProfile",
|
|
219
|
+
"contentType": "multipart/form-data",
|
|
220
|
+
"body": {
|
|
221
|
+
"description": "A photo of Fido"
|
|
222
|
+
},
|
|
223
|
+
"files": {
|
|
224
|
+
"profileImage": {
|
|
225
|
+
"name": "fido.jpg",
|
|
226
|
+
"contentType": "image/jpeg",
|
|
227
|
+
"filePath": "/Users/local/images/fido.jpg"
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Example: Raw octet stream
|
|
234
|
+
|
|
235
|
+
If an endpoint expects a raw binary PUT upload lacking form fields:
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"apiName": "pet-api",
|
|
240
|
+
"endpointId": "uploadRaw",
|
|
241
|
+
"contentType": "application/octet-stream",
|
|
242
|
+
"files": {
|
|
243
|
+
"body": {
|
|
244
|
+
"filePath": "/Users/local/data.bin"
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
177
250
|
## MCP Tools
|
|
178
251
|
|
|
179
252
|
### `list_apis`
|
|
@@ -219,12 +292,7 @@ Input fields:
|
|
|
219
292
|
- `contentType`
|
|
220
293
|
- `accept`
|
|
221
294
|
- `timeoutMs`
|
|
222
|
-
- `
|
|
223
|
-
- `maxRetries`
|
|
224
|
-
- `baseDelayMs`
|
|
225
|
-
- `maxDelayMs`
|
|
226
|
-
- `jitterRatio` (0..1)
|
|
227
|
-
- `respectRetryAfter`
|
|
295
|
+
- `maxRetries429`
|
|
228
296
|
|
|
229
297
|
Output includes:
|
|
230
298
|
|
|
@@ -242,6 +310,6 @@ npm run build
|
|
|
242
310
|
|
|
243
311
|
## Notes
|
|
244
312
|
|
|
245
|
-
- Supports local OpenAPI
|
|
313
|
+
- Supports both local files and remote URLs, including automatic conversion of Swagger 2.0 specs to OpenAPI 3.0.x in-memory.
|
|
246
314
|
- 429 retries are supported and disabled by default (`maxRetries: 0`).
|
|
247
315
|
- JSON responses are parsed first; non-JSON is returned as text or base64 binary.
|
package/dist/auth/env.d.ts
CHANGED
|
@@ -3,7 +3,12 @@ export interface OAuthClientCredentialsFromEnv {
|
|
|
3
3
|
clientSecret?: string;
|
|
4
4
|
tokenUrl?: string;
|
|
5
5
|
scopes?: string[];
|
|
6
|
-
tokenAuthMethod?:
|
|
6
|
+
tokenAuthMethod?: 'client_secret_basic' | 'client_secret_post';
|
|
7
|
+
}
|
|
8
|
+
export interface HttpAuthCredentialsFromEnv {
|
|
9
|
+
token?: string;
|
|
10
|
+
username?: string;
|
|
11
|
+
password?: string;
|
|
7
12
|
}
|
|
8
13
|
export declare function normalizeEnvSegment(value: string): string;
|
|
9
14
|
export declare function apiPrefix(apiName: string): string;
|
|
@@ -12,3 +17,4 @@ export declare function readApiBaseUrl(apiName: string, env?: NodeJS.ProcessEnv)
|
|
|
12
17
|
export declare function readApiExtraHeaders(apiName: string, env?: NodeJS.ProcessEnv): Record<string, string>;
|
|
13
18
|
export declare function readApiKeyValue(apiName: string, schemeName: string, env?: NodeJS.ProcessEnv): string | undefined;
|
|
14
19
|
export declare function readOAuthClientCredentials(apiName: string, schemeName: string, env?: NodeJS.ProcessEnv): OAuthClientCredentialsFromEnv;
|
|
20
|
+
export declare function readHttpAuthCredentials(apiName: string, schemeName: string, env?: NodeJS.ProcessEnv): HttpAuthCredentialsFromEnv;
|
package/dist/auth/env.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { OpenApiMcpError } from
|
|
1
|
+
import { OpenApiMcpError } from '../errors.js';
|
|
2
2
|
export function normalizeEnvSegment(value) {
|
|
3
3
|
return value
|
|
4
4
|
.toUpperCase()
|
|
5
|
-
.replace(/[^A-Z0-9]+/g,
|
|
6
|
-
.replace(/_+/g,
|
|
7
|
-
.replace(/^_+|_+$/g,
|
|
5
|
+
.replace(/[^A-Z0-9]+/g, '_')
|
|
6
|
+
.replace(/_+/g, '_')
|
|
7
|
+
.replace(/^_+|_+$/g, '');
|
|
8
8
|
}
|
|
9
9
|
export function apiPrefix(apiName) {
|
|
10
10
|
return normalizeEnvSegment(apiName);
|
|
@@ -25,15 +25,17 @@ export function readApiExtraHeaders(apiName, env = process.env) {
|
|
|
25
25
|
parsed = JSON.parse(raw);
|
|
26
26
|
}
|
|
27
27
|
catch {
|
|
28
|
-
throw new OpenApiMcpError(
|
|
28
|
+
throw new OpenApiMcpError('CONFIG_ERROR', `Invalid JSON in ${apiPrefix(apiName)}_HEADERS`, {
|
|
29
|
+
value: raw,
|
|
30
|
+
});
|
|
29
31
|
}
|
|
30
|
-
if (!parsed || typeof parsed !==
|
|
31
|
-
throw new OpenApiMcpError(
|
|
32
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
33
|
+
throw new OpenApiMcpError('CONFIG_ERROR', `${apiPrefix(apiName)}_HEADERS must be a JSON object`);
|
|
32
34
|
}
|
|
33
35
|
const out = {};
|
|
34
36
|
for (const [key, value] of Object.entries(parsed)) {
|
|
35
|
-
if (typeof value !==
|
|
36
|
-
throw new OpenApiMcpError(
|
|
37
|
+
if (typeof value !== 'string') {
|
|
38
|
+
throw new OpenApiMcpError('CONFIG_ERROR', `${apiPrefix(apiName)}_HEADERS values must be strings`, { key });
|
|
37
39
|
}
|
|
38
40
|
out[key] = value;
|
|
39
41
|
}
|
|
@@ -47,18 +49,29 @@ export function readOAuthClientCredentials(apiName, schemeName, env = process.en
|
|
|
47
49
|
const scopesRaw = env[`${prefix}_SCOPES`];
|
|
48
50
|
const tokenAuthMethodRaw = env[`${prefix}_TOKEN_AUTH_METHOD`];
|
|
49
51
|
let tokenAuthMethod;
|
|
50
|
-
if (tokenAuthMethodRaw ===
|
|
52
|
+
if (tokenAuthMethodRaw === 'client_secret_basic' ||
|
|
53
|
+
tokenAuthMethodRaw === 'client_secret_post') {
|
|
51
54
|
tokenAuthMethod = tokenAuthMethodRaw;
|
|
52
55
|
}
|
|
53
56
|
else if (tokenAuthMethodRaw) {
|
|
54
|
-
throw new OpenApiMcpError(
|
|
57
|
+
throw new OpenApiMcpError('CONFIG_ERROR', `Invalid ${prefix}_TOKEN_AUTH_METHOD value`, {
|
|
58
|
+
value: tokenAuthMethodRaw,
|
|
59
|
+
});
|
|
55
60
|
}
|
|
56
61
|
return {
|
|
57
62
|
clientId: env[`${prefix}_CLIENT_ID`],
|
|
58
63
|
clientSecret: env[`${prefix}_CLIENT_SECRET`],
|
|
59
64
|
tokenUrl: env[`${prefix}_TOKEN_URL`],
|
|
60
65
|
scopes: scopesRaw ? scopesRaw.split(/\s+/).filter(Boolean) : undefined,
|
|
61
|
-
tokenAuthMethod
|
|
66
|
+
tokenAuthMethod,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function readHttpAuthCredentials(apiName, schemeName, env = process.env) {
|
|
70
|
+
const prefix = schemePrefix(apiName, schemeName);
|
|
71
|
+
return {
|
|
72
|
+
token: env[`${prefix}_TOKEN`],
|
|
73
|
+
username: env[`${prefix}_USERNAME`],
|
|
74
|
+
password: env[`${prefix}_PASSWORD`],
|
|
62
75
|
};
|
|
63
76
|
}
|
|
64
77
|
//# sourceMappingURL=env.js.map
|
package/dist/auth/env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/auth/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/auth/env.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ export interface OAuthTokenRequest {
|
|
|
4
4
|
clientId: string;
|
|
5
5
|
clientSecret: string;
|
|
6
6
|
scopes: string[];
|
|
7
|
-
tokenEndpointAuthMethod:
|
|
7
|
+
tokenEndpointAuthMethod: 'client_secret_basic' | 'client_secret_post';
|
|
8
8
|
}
|
|
9
9
|
export declare class OAuthClient {
|
|
10
10
|
private readonly cache;
|
package/dist/auth/oauthClient.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as oauth from
|
|
2
|
-
import { OpenApiMcpError } from
|
|
1
|
+
import * as oauth from 'oauth4webapi';
|
|
2
|
+
import { OpenApiMcpError } from '../errors.js';
|
|
3
3
|
const TOKEN_EXPIRY_SAFETY_MS = 60_000;
|
|
4
4
|
export class OAuthClient {
|
|
5
5
|
cache = new Map();
|
|
@@ -10,44 +10,44 @@ export class OAuthClient {
|
|
|
10
10
|
}
|
|
11
11
|
const as = {
|
|
12
12
|
issuer: new URL(request.tokenUrl).origin,
|
|
13
|
-
token_endpoint: request.tokenUrl
|
|
13
|
+
token_endpoint: request.tokenUrl,
|
|
14
14
|
};
|
|
15
15
|
const client = {
|
|
16
|
-
client_id: request.clientId
|
|
16
|
+
client_id: request.clientId,
|
|
17
17
|
};
|
|
18
|
-
const clientAuth = request.tokenEndpointAuthMethod ===
|
|
18
|
+
const clientAuth = request.tokenEndpointAuthMethod === 'client_secret_post'
|
|
19
19
|
? oauth.ClientSecretPost(request.clientSecret)
|
|
20
20
|
: oauth.ClientSecretBasic(request.clientSecret);
|
|
21
21
|
const parameters = new URLSearchParams();
|
|
22
22
|
if (request.scopes.length > 0) {
|
|
23
|
-
parameters.set(
|
|
23
|
+
parameters.set('scope', request.scopes.join(' '));
|
|
24
24
|
}
|
|
25
25
|
try {
|
|
26
26
|
const tokenResponse = await oauth.clientCredentialsGrantRequest(as, client, clientAuth, parameters);
|
|
27
27
|
const tokenResult = await oauth.processClientCredentialsResponse(as, client, tokenResponse);
|
|
28
28
|
this.cache.set(request.cacheKey, {
|
|
29
29
|
accessToken: tokenResult.access_token,
|
|
30
|
-
expiresAtMs: Date.now() + Math.max(tokenResult.expires_in ?? 3600, 1) * 1000
|
|
30
|
+
expiresAtMs: Date.now() + Math.max(tokenResult.expires_in ?? 3600, 1) * 1000,
|
|
31
31
|
});
|
|
32
32
|
return tokenResult.access_token;
|
|
33
33
|
}
|
|
34
34
|
catch (error) {
|
|
35
35
|
if (error instanceof oauth.ResponseBodyError) {
|
|
36
|
-
throw new OpenApiMcpError(
|
|
36
|
+
throw new OpenApiMcpError('AUTH_ERROR', 'OAuth2 token request failed', {
|
|
37
37
|
tokenUrl: request.tokenUrl,
|
|
38
|
-
oauthError: error.cause
|
|
38
|
+
oauthError: error.cause,
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
if (error instanceof oauth.OperationProcessingError) {
|
|
42
|
-
throw new OpenApiMcpError(
|
|
42
|
+
throw new OpenApiMcpError('AUTH_ERROR', 'OAuth2 operation failed', {
|
|
43
43
|
tokenUrl: request.tokenUrl,
|
|
44
44
|
code: error.code,
|
|
45
|
-
cause: error.message
|
|
45
|
+
cause: error.message,
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
-
throw new OpenApiMcpError(
|
|
48
|
+
throw new OpenApiMcpError('AUTH_ERROR', 'OAuth2 token request failed', {
|
|
49
49
|
tokenUrl: request.tokenUrl,
|
|
50
|
-
cause: error instanceof Error ? error.message : String(error)
|
|
50
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauthClient.js","sourceRoot":"","sources":["../../src/auth/oauthClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAgB/C,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAEtC,MAAM,OAAO,WAAW;IACL,KAAK,GAAG,IAAI,GAAG,EAA2B,CAAC;IAE5D,KAAK,CAAC,yBAAyB,CAAC,OAA0B;QACxD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,MAAM,IAAI,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,sBAAsB,EAAE,CAAC;YACvE,OAAO,MAAM,CAAC,WAAW,CAAC;QAC5B,CAAC;QAED,MAAM,EAAE,GAA8B;YACpC,MAAM,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM;YACxC,cAAc,EAAE,OAAO,CAAC,QAAQ;SACjC,CAAC;QACF,MAAM,MAAM,GAAiB;YAC3B,SAAS,EAAE,OAAO,CAAC,QAAQ;SAC5B,CAAC;QACF,MAAM,UAAU,GACd,OAAO,CAAC,uBAAuB,KAAK,oBAAoB;YACtD,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,YAAY,CAAC;YAC9C,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,6BAA6B,CAC7D,EAAE,EACF,MAAM,EACN,UAAU,EACV,UAAU,CACX,CAAC;YACF,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,gCAAgC,
|
|
1
|
+
{"version":3,"file":"oauthClient.js","sourceRoot":"","sources":["../../src/auth/oauthClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { OAuthClient } from
|
|
2
|
-
import type { EndpointDefinition, LoadedApi, ResolvedAuthResult } from
|
|
1
|
+
import { OAuthClient } from './oauthClient.js';
|
|
2
|
+
import type { EndpointDefinition, LoadedApi, ResolvedAuthResult } from '../types.js';
|
|
3
3
|
interface ResolveAuthInput {
|
|
4
4
|
api: LoadedApi;
|
|
5
5
|
endpoint: EndpointDefinition;
|
|
6
6
|
oauthClient: OAuthClient;
|
|
7
7
|
env?: NodeJS.ProcessEnv;
|
|
8
8
|
}
|
|
9
|
-
export declare function resolveAuth({ api, endpoint, oauthClient, env }: ResolveAuthInput): Promise<ResolvedAuthResult>;
|
|
9
|
+
export declare function resolveAuth({ api, endpoint, oauthClient, env, }: ResolveAuthInput): Promise<ResolvedAuthResult>;
|
|
10
10
|
export {};
|
package/dist/auth/resolveAuth.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { readApiKeyValue, readOAuthClientCredentials, schemePrefix } from
|
|
2
|
-
import { OpenApiMcpError } from
|
|
3
|
-
export async function resolveAuth({ api, endpoint, oauthClient, env = process.env }) {
|
|
1
|
+
import { readApiKeyValue, readHttpAuthCredentials, readOAuthClientCredentials, schemePrefix, } from './env.js';
|
|
2
|
+
import { OpenApiMcpError } from '../errors.js';
|
|
3
|
+
export async function resolveAuth({ api, endpoint, oauthClient, env = process.env, }) {
|
|
4
4
|
const requirements = endpoint.operation.security ?? api.schema.security ?? [];
|
|
5
5
|
if (!requirements || requirements.length === 0) {
|
|
6
6
|
return { authUsed: [], schemes: [] };
|
|
@@ -16,11 +16,11 @@ export async function resolveAuth({ api, endpoint, oauthClient, env = process.en
|
|
|
16
16
|
let failedReason;
|
|
17
17
|
for (const [schemeName, requestedScopes] of Object.entries(requirementObject)) {
|
|
18
18
|
const scheme = securitySchemes[schemeName];
|
|
19
|
-
if (!scheme ||
|
|
19
|
+
if (!scheme || '$ref' in scheme) {
|
|
20
20
|
failedReason = `Security scheme '${schemeName}' not found or unresolved`;
|
|
21
21
|
break;
|
|
22
22
|
}
|
|
23
|
-
if (scheme.type ===
|
|
23
|
+
if (scheme.type === 'apiKey') {
|
|
24
24
|
const value = readApiKeyValue(api.config.name, schemeName, env);
|
|
25
25
|
if (!value) {
|
|
26
26
|
missingEnv.add(`${schemePrefix(api.config.name, schemeName)}_API_KEY`);
|
|
@@ -28,15 +28,15 @@ export async function resolveAuth({ api, endpoint, oauthClient, env = process.en
|
|
|
28
28
|
break;
|
|
29
29
|
}
|
|
30
30
|
resolved.push({
|
|
31
|
-
type:
|
|
31
|
+
type: 'apiKey',
|
|
32
32
|
schemeName,
|
|
33
33
|
in: scheme.in,
|
|
34
34
|
name: scheme.name,
|
|
35
|
-
value
|
|
35
|
+
value,
|
|
36
36
|
});
|
|
37
37
|
continue;
|
|
38
38
|
}
|
|
39
|
-
if (scheme.type ===
|
|
39
|
+
if (scheme.type === 'oauth2') {
|
|
40
40
|
const flow = scheme.flows.clientCredentials;
|
|
41
41
|
if (!flow) {
|
|
42
42
|
failedReason = `Scheme '${schemeName}' does not support clientCredentials flow`;
|
|
@@ -51,14 +51,16 @@ export async function resolveAuth({ api, endpoint, oauthClient, env = process.en
|
|
|
51
51
|
failedReason = `Missing OAuth2 client credentials for '${schemeName}'`;
|
|
52
52
|
break;
|
|
53
53
|
}
|
|
54
|
-
const tokenUrl = fromEnv.tokenUrl ??
|
|
54
|
+
const tokenUrl = fromEnv.tokenUrl ??
|
|
55
|
+
api.config.oauth2?.tokenUrlOverride ??
|
|
56
|
+
flow.tokenUrl;
|
|
55
57
|
if (!tokenUrl) {
|
|
56
58
|
failedReason = `No OAuth2 token URL resolved for scheme '${schemeName}'`;
|
|
57
59
|
break;
|
|
58
60
|
}
|
|
59
61
|
const tokenEndpointAuthMethod = fromEnv.tokenAuthMethod ??
|
|
60
62
|
api.config.oauth2?.tokenEndpointAuthMethod ??
|
|
61
|
-
|
|
63
|
+
'client_secret_basic';
|
|
62
64
|
const scopes = resolveScopes(requestedScopes, fromEnv.scopes, api.config.oauth2?.scopes, flow);
|
|
63
65
|
const cacheKey = [
|
|
64
66
|
api.config.name,
|
|
@@ -66,41 +68,78 @@ export async function resolveAuth({ api, endpoint, oauthClient, env = process.en
|
|
|
66
68
|
clientId,
|
|
67
69
|
tokenUrl,
|
|
68
70
|
tokenEndpointAuthMethod,
|
|
69
|
-
scopes.sort().join(
|
|
70
|
-
].join(
|
|
71
|
+
scopes.sort().join(','),
|
|
72
|
+
].join('|');
|
|
71
73
|
const token = await oauthClient.getClientCredentialsToken({
|
|
72
74
|
cacheKey,
|
|
73
75
|
tokenUrl,
|
|
74
76
|
clientId,
|
|
75
77
|
clientSecret,
|
|
76
78
|
scopes,
|
|
77
|
-
tokenEndpointAuthMethod
|
|
79
|
+
tokenEndpointAuthMethod,
|
|
78
80
|
});
|
|
79
81
|
resolved.push({
|
|
80
|
-
type:
|
|
82
|
+
type: 'oauth2',
|
|
81
83
|
schemeName,
|
|
82
|
-
token
|
|
84
|
+
token,
|
|
83
85
|
});
|
|
84
86
|
continue;
|
|
85
87
|
}
|
|
88
|
+
if (scheme.type === 'http') {
|
|
89
|
+
const schemeLower = scheme.scheme.toLowerCase();
|
|
90
|
+
if (schemeLower !== 'bearer' && schemeLower !== 'basic') {
|
|
91
|
+
failedReason = `HTTP auth scheme '${schemeLower}' is not supported`;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
const fromEnv = readHttpAuthCredentials(api.config.name, schemeName, env);
|
|
95
|
+
if (schemeLower === 'bearer') {
|
|
96
|
+
if (!fromEnv.token) {
|
|
97
|
+
missingEnv.add(`${schemePrefix(api.config.name, schemeName)}_TOKEN`);
|
|
98
|
+
failedReason = `Missing Bearer token for scheme '${schemeName}'`;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
resolved.push({
|
|
102
|
+
type: 'http',
|
|
103
|
+
schemeName,
|
|
104
|
+
scheme: 'bearer',
|
|
105
|
+
token: fromEnv.token,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
else if (schemeLower === 'basic') {
|
|
109
|
+
if (!fromEnv.username || !fromEnv.password) {
|
|
110
|
+
missingEnv.add(`${schemePrefix(api.config.name, schemeName)}_USERNAME`);
|
|
111
|
+
missingEnv.add(`${schemePrefix(api.config.name, schemeName)}_PASSWORD`);
|
|
112
|
+
failedReason = `Missing Basic auth credentials for scheme '${schemeName}'`;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
resolved.push({
|
|
116
|
+
type: 'http',
|
|
117
|
+
schemeName,
|
|
118
|
+
scheme: 'basic',
|
|
119
|
+
username: fromEnv.username,
|
|
120
|
+
password: fromEnv.password,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
86
125
|
failedReason = `Unsupported security scheme type '${scheme.type}' for '${schemeName}'`;
|
|
87
126
|
break;
|
|
88
127
|
}
|
|
89
128
|
if (!failedReason) {
|
|
90
129
|
return {
|
|
91
130
|
authUsed: resolved.map((item) => item.schemeName),
|
|
92
|
-
schemes: resolved
|
|
131
|
+
schemes: resolved,
|
|
93
132
|
};
|
|
94
133
|
}
|
|
95
134
|
failures.push({
|
|
96
135
|
requirement: Object.keys(requirementObject),
|
|
97
136
|
reason: failedReason,
|
|
98
|
-
missingEnv: [...missingEnv]
|
|
137
|
+
missingEnv: [...missingEnv],
|
|
99
138
|
});
|
|
100
139
|
}
|
|
101
|
-
throw new OpenApiMcpError(
|
|
140
|
+
throw new OpenApiMcpError('AUTH_ERROR', `Could not resolve authentication for '${api.config.name}'`, {
|
|
102
141
|
endpointId: endpoint.endpointId,
|
|
103
|
-
failures
|
|
142
|
+
failures,
|
|
104
143
|
});
|
|
105
144
|
}
|
|
106
145
|
function resolveScopes(requestedScopes, envScopes, configScopes, flow) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveAuth.js","sourceRoot":"","sources":["../../src/auth/resolveAuth.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"resolveAuth.js","sourceRoot":"","sources":["../../src/auth/resolveAuth.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { loadConfig } from
|
|
3
|
-
import { OAuthClient } from
|
|
4
|
-
import { OpenApiMcpError } from
|
|
5
|
-
import { startMcpServer } from
|
|
6
|
-
import { loadApiRegistry } from
|
|
2
|
+
import { loadConfig } from './config/loadConfig.js';
|
|
3
|
+
import { OAuthClient } from './auth/oauthClient.js';
|
|
4
|
+
import { OpenApiMcpError } from './errors.js';
|
|
5
|
+
import { startMcpServer } from './mcp/server.js';
|
|
6
|
+
import { loadApiRegistry } from './openapi/loadSpec.js';
|
|
7
7
|
function parseConfigPath(argv) {
|
|
8
8
|
for (let i = 0; i < argv.length; i += 1) {
|
|
9
|
-
if (argv[i] ===
|
|
9
|
+
if (argv[i] === '--config') {
|
|
10
10
|
const value = argv[i + 1];
|
|
11
11
|
if (!value) {
|
|
12
|
-
throw new OpenApiMcpError(
|
|
12
|
+
throw new OpenApiMcpError('CONFIG_ERROR', 'Missing value for --config');
|
|
13
13
|
}
|
|
14
14
|
return value;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
throw new OpenApiMcpError(
|
|
17
|
+
throw new OpenApiMcpError('CONFIG_ERROR', 'Missing required argument --config');
|
|
18
18
|
}
|
|
19
19
|
export async function runCli(argv = process.argv.slice(2)) {
|
|
20
20
|
const configPath = parseConfigPath(argv);
|
|
@@ -22,12 +22,12 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
22
22
|
const registry = await loadApiRegistry(config, process.env);
|
|
23
23
|
console.error(`[openapi-mcp] loaded ${registry.byName.size} API(s)`);
|
|
24
24
|
for (const api of registry.byName.values()) {
|
|
25
|
-
console.error(`[openapi-mcp] api=${api.config.name} endpoints=${api.endpoints.length} authSchemes=${api.authSchemeNames.join(
|
|
25
|
+
console.error(`[openapi-mcp] api=${api.config.name} endpoints=${api.endpoints.length} authSchemes=${api.authSchemeNames.join(',')}`);
|
|
26
26
|
}
|
|
27
27
|
await startMcpServer({
|
|
28
28
|
registry,
|
|
29
29
|
oauthClient: new OAuthClient(),
|
|
30
|
-
env: process.env
|
|
30
|
+
env: process.env,
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
runCli().catch((error) => {
|
|
@@ -35,7 +35,7 @@ runCli().catch((error) => {
|
|
|
35
35
|
console.error(JSON.stringify({
|
|
36
36
|
code: error.code,
|
|
37
37
|
message: error.message,
|
|
38
|
-
details: error.details
|
|
38
|
+
details: error.details,
|
|
39
39
|
}, null, 2));
|
|
40
40
|
process.exit(1);
|
|
41
41
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,SAAS,eAAe,CAAC,IAAc;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,eAAe,CAAC,cAAc,EAAE,4BAA4B,CAAC,CAAC;YAC1E,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,MAAM,IAAI,eAAe,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,SAAS,eAAe,CAAC,IAAc;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,eAAe,CAAC,cAAc,EAAE,4BAA4B,CAAC,CAAC;YAC1E,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,MAAM,IAAI,eAAe,CACvB,cAAc,EACd,oCAAoC,CACrC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAE5D,OAAO,CAAC,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,CAAC;IACrE,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QAC3C,OAAO,CAAC,KAAK,CACX,qBAAqB,GAAG,CAAC,MAAM,CAAC,IAAI,cAAc,GAAG,CAAC,SAAS,CAAC,MAAM,gBAAgB,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CACtH,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,CAAC;QACnB,QAAQ;QACR,WAAW,EAAE,IAAI,WAAW,EAAE;QAC9B,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAChC,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;QACrC,OAAO,CAAC,KAAK,CACX,IAAI,CAAC,SAAS,CACZ;YACE,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,EACD,IAAI,EACJ,CAAC,CACF,CACF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { RootConfig } from
|
|
1
|
+
import type { RootConfig } from '../types.js';
|
|
2
2
|
export declare function loadConfig(configPath: string): Promise<RootConfig>;
|