mcp-from-openapi 2.5.0 → 2.6.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 +73 -67
- package/annotations.d.ts +57 -0
- package/client-targets.d.ts +55 -0
- package/errors.d.ts +7 -0
- package/esm/index.mjs +2359 -1112
- package/esm/package.json +1 -1
- package/generator.d.ts +1 -1
- package/index.d.ts +10 -2
- package/index.js +2374 -1113
- package/package.json +1 -1
- package/parameter-resolver.d.ts +23 -2
- package/request-builder.d.ts +52 -0
- package/response-builder.d.ts +1 -0
- package/schema-builder.d.ts +17 -0
- package/sdk.d.ts +22 -0
- package/ssrf.d.ts +76 -14
- package/types.d.ts +164 -19
package/package.json
CHANGED
package/parameter-resolver.d.ts
CHANGED
|
@@ -2,12 +2,23 @@ import type { JSONSchema } from 'zod/v4/core';
|
|
|
2
2
|
/** JSON Schema type from Zod v4 */
|
|
3
3
|
type JsonSchema = JSONSchema.JSONSchema;
|
|
4
4
|
import type { ParameterMapper, ParameterObject, NamingStrategy, SecurityRequirement } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Options controlling parameter resolution behavior
|
|
7
|
+
*/
|
|
8
|
+
export interface ParameterResolverOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Include parameter-level and media-type-level example(s) in the
|
|
11
|
+
* generated input schema (as JSON Schema `examples` arrays).
|
|
12
|
+
*/
|
|
13
|
+
includeExamples?: boolean;
|
|
14
|
+
}
|
|
5
15
|
/**
|
|
6
16
|
* Resolves parameters and handles naming conflicts
|
|
7
17
|
*/
|
|
8
18
|
export declare class ParameterResolver {
|
|
9
19
|
private namingStrategy;
|
|
10
|
-
|
|
20
|
+
private includeExamples;
|
|
21
|
+
constructor(namingStrategy?: NamingStrategy, options?: ParameterResolverOptions);
|
|
11
22
|
/**
|
|
12
23
|
* Default conflict resolver: prefix with location
|
|
13
24
|
*/
|
|
@@ -15,7 +26,7 @@ export declare class ParameterResolver {
|
|
|
15
26
|
/**
|
|
16
27
|
* Resolve all parameters for an operation
|
|
17
28
|
*/
|
|
18
|
-
resolve(operation: any, pathParameters?: ParameterObject[], securityRequirements?: SecurityRequirement[], includeSecurityInInput?: boolean): {
|
|
29
|
+
resolve(operation: any, pathParameters?: ParameterObject[], securityRequirements?: SecurityRequirement[], includeSecurityInInput?: boolean | string[]): {
|
|
19
30
|
inputSchema: JsonSchema;
|
|
20
31
|
mapper: ParameterMapper[];
|
|
21
32
|
};
|
|
@@ -36,4 +47,14 @@ export declare class ParameterResolver {
|
|
|
36
47
|
*/
|
|
37
48
|
private processSecurityRequirements;
|
|
38
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Collect concrete example values from OpenAPI `example` / `examples` fields
|
|
52
|
+
* (parameter or media-type level). The `examples` map wins over the singular
|
|
53
|
+
* `example` (they are mutually exclusive per OpenAPI); `$ref` entries are
|
|
54
|
+
* skipped because example refs are not dereferenced into values here.
|
|
55
|
+
* Returns undefined when nothing usable is present.
|
|
56
|
+
*
|
|
57
|
+
* Internal helper shared with ResponseBuilder (not part of the public barrel).
|
|
58
|
+
*/
|
|
59
|
+
export declare function collectExampleValues(example: unknown, examples?: Record<string, unknown> | unknown[]): unknown[] | undefined;
|
|
39
60
|
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { McpOpenAPITool } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Options for {@link buildHttpRequest}.
|
|
4
|
+
*/
|
|
5
|
+
export interface BuildHttpRequestOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Base URL for the request. Overrides the tool's `metadata.servers[0].url`.
|
|
8
|
+
* Must be empty (relative request) or an http/https URL.
|
|
9
|
+
*/
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The composed HTTP request. Pure data — nothing has been sent.
|
|
14
|
+
*/
|
|
15
|
+
export interface BuiltHttpRequest {
|
|
16
|
+
/** Fully composed URL: base + expanded path + encoded query string */
|
|
17
|
+
url: string;
|
|
18
|
+
/** Uppercase HTTP method */
|
|
19
|
+
method: string;
|
|
20
|
+
/**
|
|
21
|
+
* Request headers, including a composed `Cookie` header (when cookie
|
|
22
|
+
* parameters exist) and `content-type` (when the body is not multipart —
|
|
23
|
+
* multipart bodies must let the HTTP client set the boundary itself).
|
|
24
|
+
*/
|
|
25
|
+
headers: Record<string, string>;
|
|
26
|
+
/** Query parameters as sent (unencoded values, one array per key) */
|
|
27
|
+
query: Record<string, string[]>;
|
|
28
|
+
/** Cookie parameters (also folded into the `Cookie` header) */
|
|
29
|
+
cookies: Record<string, string>;
|
|
30
|
+
/** Selected request body content type (also in headers, except multipart) */
|
|
31
|
+
contentType?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Serialized body ready for fetch: a JSON/form-urlencoded/text string, a
|
|
34
|
+
* `FormData` for multipart, the raw value for binary bodies, or undefined.
|
|
35
|
+
*/
|
|
36
|
+
body?: unknown;
|
|
37
|
+
/** Structured body value before serialization (object/array/primitive) */
|
|
38
|
+
rawBody?: unknown;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Build an HTTP request from a generated tool and its input values — the
|
|
42
|
+
* mapper applied in full: style/explode serialization (form, spaceDelimited,
|
|
43
|
+
* pipeDelimited, deepObject, simple, label, matrix), `allowReserved`,
|
|
44
|
+
* whole-body and binary bodies, JSON / form-urlencoded / multipart / text
|
|
45
|
+
* serialization, cookies, and header-injection guards.
|
|
46
|
+
*
|
|
47
|
+
* Pure function: nothing is sent, no runtime context is consulted. Security
|
|
48
|
+
* mapper entries are applied only when their value is present in `input`
|
|
49
|
+
* (with scheme-aware formatting); missing security values never throw —
|
|
50
|
+
* frameworks resolve credentials separately (see SecurityResolver).
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildHttpRequest(tool: McpOpenAPITool, input: Record<string, unknown>, options?: BuildHttpRequestOptions): BuiltHttpRequest;
|
package/response-builder.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { GenerateOptions, ResponsesObject } from './types';
|
|
|
8
8
|
export declare class ResponseBuilder {
|
|
9
9
|
private preferredStatusCodes;
|
|
10
10
|
private includeAllResponses;
|
|
11
|
+
private includeExamples;
|
|
11
12
|
constructor(options?: GenerateOptions);
|
|
12
13
|
/**
|
|
13
14
|
* Build output schema from responses
|
package/schema-builder.d.ts
CHANGED
|
@@ -110,6 +110,23 @@ export declare class SchemaBuilder {
|
|
|
110
110
|
* Flatten nested oneOf/anyOf/allOf schemas
|
|
111
111
|
*/
|
|
112
112
|
static flatten(schema: JsonSchema, maxDepth?: number): JsonSchema;
|
|
113
|
+
/**
|
|
114
|
+
* Truncate a schema tree to a maximum nesting depth.
|
|
115
|
+
*
|
|
116
|
+
* The root sits at depth 0; descending into `properties` values, `items`,
|
|
117
|
+
* `additionalProperties`, composition members (`allOf`/`anyOf`/`oneOf`), or
|
|
118
|
+
* `not` increments the depth. Nodes at `maxDepth` keep their scalar keywords
|
|
119
|
+
* (type, description, format, ...) but have their child schemas stripped and
|
|
120
|
+
* a truncation note appended to the description.
|
|
121
|
+
*/
|
|
122
|
+
static truncateDepth(schema: JsonSchema, maxDepth: number): JsonSchema;
|
|
123
|
+
/** Keys whose value is a map of schemas (JSON Schema 2020-12) */
|
|
124
|
+
private static readonly TRUNCATE_MAP_KEYS;
|
|
125
|
+
/** Keys whose value is a single schema (or, for `items`, a tuple array) */
|
|
126
|
+
private static readonly TRUNCATE_SCHEMA_KEYS;
|
|
127
|
+
/** Keys whose value is an array of schemas */
|
|
128
|
+
private static readonly TRUNCATE_LIST_KEYS;
|
|
129
|
+
private static truncateDepthRecursive;
|
|
113
130
|
/**
|
|
114
131
|
* Simplify schema by removing unnecessary fields
|
|
115
132
|
*/
|
package/sdk.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { JsonSchema, McpOpenAPITool, ToolAnnotations } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* A `registerTool`-shaped config for the official MCP TypeScript SDK.
|
|
4
|
+
* `TSchema` is whatever the schema wrapper returns — the raw `JsonSchema`
|
|
5
|
+
* when no wrapper is used, or the SDK's wrapped schema type.
|
|
6
|
+
*/
|
|
7
|
+
export interface SdkToolConfig<TSchema = JsonSchema> {
|
|
8
|
+
title?: string;
|
|
9
|
+
description: string;
|
|
10
|
+
inputSchema: TSchema;
|
|
11
|
+
outputSchema?: TSchema;
|
|
12
|
+
annotations?: ToolAnnotations;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Schema wrapper — pass the SDK v2 `fromJsonSchema` here so schemas are
|
|
16
|
+
* advertised verbatim and validated by the SDK's JSON Schema validator.
|
|
17
|
+
*/
|
|
18
|
+
export interface SdkSchemaWrapper<TSchema> {
|
|
19
|
+
fromJsonSchema: (schema: JsonSchema) => TSchema;
|
|
20
|
+
}
|
|
21
|
+
export declare function toSdkTool(tool: McpOpenAPITool): [name: string, config: SdkToolConfig];
|
|
22
|
+
export declare function toSdkTool<TSchema>(tool: McpOpenAPITool, wrapper: SdkSchemaWrapper<TSchema>): [name: string, config: SdkToolConfig<TSchema>];
|
package/ssrf.d.ts
CHANGED
|
@@ -20,17 +20,25 @@
|
|
|
20
20
|
* multicast / unspecified / reserved ranges and cloud-metadata endpoints;
|
|
21
21
|
* - resolves the hostname (Node, via `node:dns`) and rejects if **any**
|
|
22
22
|
* resolved address is internal — closing the DNS-name-to-internal bypass;
|
|
23
|
+
* - **pins the connection to the validated IP**: on Node, {@link safeFetch}
|
|
24
|
+
* connects through `node:http`/`node:https` with a custom `lookup` that
|
|
25
|
+
* returns the exact address {@link assertUrlSafe} just validated, so the
|
|
26
|
+
* guard and the socket share one DNS resolution. This closes the
|
|
27
|
+
* DNS-rebinding TOCTOU where the client would otherwise re-resolve the
|
|
28
|
+
* hostname at connect time and reach a different (internal) address. The
|
|
29
|
+
* original hostname is preserved for the `Host` header and TLS SNI;
|
|
23
30
|
* - re-validates every redirect hop ({@link safeFetch}) instead of letting the
|
|
24
31
|
* HTTP client follow 3xx blindly.
|
|
25
32
|
*
|
|
26
|
-
* Node-aware: DNS resolution lazily imports `node:dns` and
|
|
27
|
-
* runtimes without
|
|
33
|
+
* Node-aware: DNS resolution lazily imports `node:dns` and IP pinning lazily
|
|
34
|
+
* imports `node:http`/`node:https`. On runtimes without them (Web/edge) the
|
|
35
|
+
* literal-address checks still apply and the fetch falls back to the platform
|
|
36
|
+
* `fetch` (best-effort, without connection pinning) — combine with an
|
|
37
|
+
* `allowedHosts` allow-list and network egress controls there.
|
|
28
38
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* eliminated. For fully-untrusted inputs, combine with an `allowedHosts`
|
|
33
|
-
* allow-list and network egress controls.
|
|
39
|
+
* Fails closed: a genuine resolver error rejects the URL rather than proceeding
|
|
40
|
+
* unvalidated; only a runtime that has no resolver at all (edge) skips the DNS
|
|
41
|
+
* step ({@link SsrfResolverUnavailableError}).
|
|
34
42
|
*/
|
|
35
43
|
import type { RefResolutionOptions } from './types';
|
|
36
44
|
/** The subset of {@link RefResolutionOptions} relevant to address blocking. */
|
|
@@ -75,15 +83,33 @@ export declare function isBlockedAddress(host: string): boolean;
|
|
|
75
83
|
* internal addresses are caught later, asynchronously, in {@link safeFetch}.
|
|
76
84
|
*/
|
|
77
85
|
export declare function isBlockedHostname(hostname: string, ssrf: ResolvedSsrfOptions): boolean;
|
|
78
|
-
/**
|
|
86
|
+
/**
|
|
87
|
+
* Signals that no DNS resolver is available on the current runtime (e.g. a
|
|
88
|
+
* Web/edge isolate without `node:dns`). {@link assertUrlSafe} treats this as
|
|
89
|
+
* "cannot resolve, cannot pin" and proceeds on literal-address checks only,
|
|
90
|
+
* whereas a genuine resolver failure fails closed.
|
|
91
|
+
*/
|
|
92
|
+
export declare class SsrfResolverUnavailableError extends Error {
|
|
93
|
+
}
|
|
94
|
+
/** Default DNS resolver: lazily loads `node:dns`; signals unavailability off-Node. */
|
|
79
95
|
export declare const defaultLookup: SsrfHostLookup;
|
|
80
96
|
/**
|
|
81
97
|
* Validate that `url` is safe to fetch (spec URL or `$ref` target), throwing
|
|
82
98
|
* {@link SsrfError} if not. Enforces http/https, the `allowedHosts` allow-list,
|
|
83
99
|
* the internal-address denylist, and — for DNS names — resolves and rejects if
|
|
84
100
|
* any resolved address is internal.
|
|
101
|
+
*
|
|
102
|
+
* Returns the validated resolved addresses so the caller can **pin** the
|
|
103
|
+
* connection to them ({@link safeFetch}), guaranteeing the socket connects to
|
|
104
|
+
* the exact IP that was validated rather than re-resolving the hostname. An
|
|
105
|
+
* empty array means "no pinning needed" (a literal IP, `allowInternalIPs`, or a
|
|
106
|
+
* runtime without a resolver).
|
|
107
|
+
*
|
|
108
|
+
* Fails closed: a genuine resolver error (or a name that resolves to no
|
|
109
|
+
* address) rejects the URL. Only {@link SsrfResolverUnavailableError} — no
|
|
110
|
+
* resolver on this runtime — is treated as best-effort and returns `[]`.
|
|
85
111
|
*/
|
|
86
|
-
export declare function assertUrlSafe(url: string, ssrf: ResolvedSsrfOptions, lookup?: SsrfHostLookup): Promise<
|
|
112
|
+
export declare function assertUrlSafe(url: string, ssrf: ResolvedSsrfOptions, lookup?: SsrfHostLookup): Promise<ResolvedAddress[]>;
|
|
87
113
|
/** Options for {@link safeFetch}. */
|
|
88
114
|
export interface SafeFetchOptions {
|
|
89
115
|
headers?: Record<string, string>;
|
|
@@ -92,17 +118,53 @@ export interface SafeFetchOptions {
|
|
|
92
118
|
followRedirects?: boolean;
|
|
93
119
|
/** Max redirect hops before failing. @default 5 */
|
|
94
120
|
maxRedirects?: number;
|
|
121
|
+
/** Max response body bytes before the request is aborted (Node transport). @default 10 MiB */
|
|
122
|
+
maxResponseBytes?: number;
|
|
95
123
|
ssrf: ResolvedSsrfOptions;
|
|
96
124
|
/** Injectable DNS resolver (tests). */
|
|
97
125
|
lookup?: SsrfHostLookup;
|
|
98
|
-
/**
|
|
126
|
+
/**
|
|
127
|
+
* Injectable fetch implementation (tests / custom runtimes). Providing this
|
|
128
|
+
* bypasses the Node connection-pinning transport, so the implementation is
|
|
129
|
+
* responsible for connecting to the validated address itself.
|
|
130
|
+
*/
|
|
99
131
|
fetchImpl?: typeof fetch;
|
|
100
132
|
}
|
|
133
|
+
/** Lazily-loaded `node:http`/`node:https` modules. */
|
|
134
|
+
export interface NodeHttpModules {
|
|
135
|
+
http: typeof import('node:http');
|
|
136
|
+
https: typeof import('node:https');
|
|
137
|
+
}
|
|
138
|
+
/** A transport that issues one GET and returns the raw (unfollowed) response. */
|
|
139
|
+
type SsrfTransport = (url: string, request: {
|
|
140
|
+
headers?: Record<string, string>;
|
|
141
|
+
signal: AbortSignal;
|
|
142
|
+
pinned: ResolvedAddress[];
|
|
143
|
+
maxBytes?: number;
|
|
144
|
+
}) => Promise<Response>;
|
|
145
|
+
/** Select the Node transport module for a URL protocol. Exported for tests. */
|
|
146
|
+
export declare function pickHttpModule(protocol: string, modules: NodeHttpModules): NodeHttpModules['http'] | NodeHttpModules['https'];
|
|
147
|
+
/**
|
|
148
|
+
* A `node:net` lookup that always returns the pre-validated addresses, ignoring
|
|
149
|
+
* the queried hostname — pinning the socket to the exact IP {@link assertUrlSafe}
|
|
150
|
+
* validated so the connection cannot be re-resolved to a different (internal)
|
|
151
|
+
* address. Exported for tests.
|
|
152
|
+
*/
|
|
153
|
+
export declare function makePinnedLookup(pinned: ResolvedAddress[]): (_hostname: string, options: unknown, callback?: unknown) => void;
|
|
154
|
+
/**
|
|
155
|
+
* Node transport that pins the connection to the validated address(es) via a
|
|
156
|
+
* custom `lookup`, preserving the original hostname for the `Host` header and
|
|
157
|
+
* TLS SNI. Manual redirects only (no `lookup` re-resolution between hops).
|
|
158
|
+
* Exported for tests.
|
|
159
|
+
*/
|
|
160
|
+
export declare function nodePinnedTransport(modules: NodeHttpModules): SsrfTransport;
|
|
101
161
|
/**
|
|
102
162
|
* SSRF-safe `fetch`: validates the initial URL and **every redirect hop** with
|
|
103
|
-
* {@link assertUrlSafe} before issuing the request,
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
163
|
+
* {@link assertUrlSafe} before issuing the request, then **pins** the connection
|
|
164
|
+
* to the validated IP (on Node) so the socket can't be rebound to an internal
|
|
165
|
+
* address. Uses manual redirect handling so a 3xx to an internal target can't be
|
|
166
|
+
* followed without re-validation. Returns the final {@link Response} (the caller
|
|
167
|
+
* checks `response.ok` / reads the body).
|
|
107
168
|
*/
|
|
108
169
|
export declare function safeFetch(url: string, opts: SafeFetchOptions): Promise<Response>;
|
|
170
|
+
export {};
|
package/types.d.ts
CHANGED
|
@@ -49,20 +49,68 @@ export declare function isReferenceObject(obj: any): obj is ReferenceObject;
|
|
|
49
49
|
* Convert OpenAPI schema to JsonSchema
|
|
50
50
|
* Note: OpenAPI 3.0 uses a subset of JSON Schema Draft 4
|
|
51
51
|
* OpenAPI 3.1 uses JSON Schema Draft 2020-12
|
|
52
|
+
*
|
|
53
|
+
* Normalizations applied for clean JSON Schema 2020-12 output (MCP's default
|
|
54
|
+
* dialect since spec revision 2025-11-25):
|
|
55
|
+
* - OpenAPI 3.0 `nullable: true` -> `type: [..., 'null']` union
|
|
56
|
+
* - OpenAPI 3.0 boolean `exclusiveMinimum`/`exclusiveMaximum` -> numeric form
|
|
57
|
+
* - OpenAPI `example` (singular) -> `examples` array (2020-12 keyword)
|
|
58
|
+
* - OpenAPI-only `xml` metadata is dropped
|
|
52
59
|
*/
|
|
53
60
|
export declare function toJsonSchema(schema: SchemaObject | ReferenceObject): JsonSchema;
|
|
54
61
|
/**
|
|
55
|
-
*
|
|
62
|
+
* MCP tool annotations — behavior hints for clients (MCP spec 2025-03-26).
|
|
63
|
+
* Hints are advisory: clients must not treat them as security guarantees.
|
|
64
|
+
*/
|
|
65
|
+
export interface ToolAnnotations {
|
|
66
|
+
/**
|
|
67
|
+
* Legacy display-name slot inside annotations. Prefer the tool-level `title`.
|
|
68
|
+
*/
|
|
69
|
+
title?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Tool only reads data, never modifies state.
|
|
72
|
+
*/
|
|
73
|
+
readOnlyHint?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Tool may perform destructive updates (delete, overwrite).
|
|
76
|
+
*/
|
|
77
|
+
destructiveHint?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Calling repeatedly with the same arguments has no additional effect.
|
|
80
|
+
*/
|
|
81
|
+
idempotentHint?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Tool interacts with an open world of external entities.
|
|
84
|
+
*/
|
|
85
|
+
openWorldHint?: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Main MCP Tool definition generated from OpenAPI.
|
|
89
|
+
*
|
|
90
|
+
* `TMeta` lets embedding frameworks extend the metadata contract without
|
|
91
|
+
* casting — e.g. `McpOpenAPITool<ToolMetadata & { adapter: AdapterState }>`.
|
|
56
92
|
*/
|
|
57
|
-
export interface McpOpenAPITool {
|
|
93
|
+
export interface McpOpenAPITool<TMeta extends ToolMetadata = ToolMetadata> {
|
|
58
94
|
/**
|
|
59
95
|
* Unique tool name (from operationId or generated)
|
|
60
96
|
*/
|
|
61
97
|
name: string;
|
|
98
|
+
/**
|
|
99
|
+
* Human-readable display name (MCP `Tool.title`, spec 2025-06-18).
|
|
100
|
+
* From extension overrides or the operation summary.
|
|
101
|
+
*/
|
|
102
|
+
title?: string;
|
|
62
103
|
/**
|
|
63
104
|
* Tool description (from operation summary/description)
|
|
64
105
|
*/
|
|
65
106
|
description: string;
|
|
107
|
+
/**
|
|
108
|
+
* MCP tool annotations. Inferred from HTTP method semantics by default
|
|
109
|
+
* (see `GenerateOptions.inferAnnotations`) and overridable via the
|
|
110
|
+
* `x-speakeasy-mcp` / `x-mcp` / `x-frontmcp` extensions (in ascending
|
|
111
|
+
* precedence).
|
|
112
|
+
*/
|
|
113
|
+
annotations?: ToolAnnotations;
|
|
66
114
|
/**
|
|
67
115
|
* Combined input schema including all parameters
|
|
68
116
|
* (path, query, header, cookie, body)
|
|
@@ -80,7 +128,7 @@ export interface McpOpenAPITool {
|
|
|
80
128
|
/**
|
|
81
129
|
* Additional metadata about the tool
|
|
82
130
|
*/
|
|
83
|
-
metadata:
|
|
131
|
+
metadata: TMeta;
|
|
84
132
|
}
|
|
85
133
|
/**
|
|
86
134
|
* Maps input schema properties to their actual request locations
|
|
@@ -110,10 +158,23 @@ export interface ParameterMapper {
|
|
|
110
158
|
* Whether to explode arrays/objects
|
|
111
159
|
*/
|
|
112
160
|
explode?: boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Whether RFC 3986 reserved characters may appear unencoded in the value
|
|
163
|
+
* (query parameters only, OpenAPI `allowReserved`)
|
|
164
|
+
*/
|
|
165
|
+
allowReserved?: boolean;
|
|
113
166
|
/**
|
|
114
167
|
* Custom serialization info
|
|
115
168
|
*/
|
|
116
169
|
serialization?: SerializationInfo;
|
|
170
|
+
/**
|
|
171
|
+
* When true, this input value IS the entire request body — set for
|
|
172
|
+
* non-object bodies (arrays, primitives, binary) and for `oneOf`/`anyOf`
|
|
173
|
+
* union bodies that cannot be flattened into named properties. Consumers
|
|
174
|
+
* building requests must send the value directly as the body instead of
|
|
175
|
+
* wrapping it in an object keyed by `key`.
|
|
176
|
+
*/
|
|
177
|
+
wholeBody?: boolean;
|
|
117
178
|
/**
|
|
118
179
|
* Security scheme information (if this is an auth parameter)
|
|
119
180
|
* This allows frameworks to resolve auth from context, env vars, etc.
|
|
@@ -129,9 +190,16 @@ export interface SerializationInfo {
|
|
|
129
190
|
*/
|
|
130
191
|
contentType?: string;
|
|
131
192
|
/**
|
|
132
|
-
* Encoding rules
|
|
193
|
+
* Encoding rules from the request body's media type (OpenAPI `encoding`).
|
|
194
|
+
* For a flattened body-property parameter this contains only that
|
|
195
|
+
* property's entry; for a whole-body parameter it is the full map.
|
|
133
196
|
*/
|
|
134
197
|
encoding?: Record<string, EncodingObject>;
|
|
198
|
+
/**
|
|
199
|
+
* File-upload marker: the parameter schema declares binary content
|
|
200
|
+
* (`format: binary`), e.g. a multipart file part or a raw binary body.
|
|
201
|
+
*/
|
|
202
|
+
binary?: boolean;
|
|
135
203
|
}
|
|
136
204
|
/**
|
|
137
205
|
* Security parameter information for framework-agnostic auth resolution
|
|
@@ -231,15 +299,10 @@ export interface ToolMetadata {
|
|
|
231
299
|
*/
|
|
232
300
|
export interface FrontMcpExtensionData {
|
|
233
301
|
/**
|
|
234
|
-
* Tool annotations for AI behavior hints
|
|
302
|
+
* Tool annotations for AI behavior hints (same contract as the tool-level
|
|
303
|
+
* `annotations` field).
|
|
235
304
|
*/
|
|
236
|
-
annotations?:
|
|
237
|
-
title?: string;
|
|
238
|
-
readOnlyHint?: boolean;
|
|
239
|
-
destructiveHint?: boolean;
|
|
240
|
-
idempotentHint?: boolean;
|
|
241
|
-
openWorldHint?: boolean;
|
|
242
|
-
};
|
|
305
|
+
annotations?: ToolAnnotations;
|
|
243
306
|
/**
|
|
244
307
|
* Cache configuration for response caching.
|
|
245
308
|
*/
|
|
@@ -395,9 +458,18 @@ export interface LoadOptions {
|
|
|
395
458
|
* Whether to follow HTTP redirects when fetching the spec URL. Each redirect
|
|
396
459
|
* hop is re-validated against the SSRF guard before being followed (a 3xx to
|
|
397
460
|
* an internal target is refused), so following is safe by default.
|
|
398
|
-
* @default true
|
|
461
|
+
* @default true (false when `secureDefaults` is set)
|
|
399
462
|
*/
|
|
400
463
|
followRedirects?: boolean;
|
|
464
|
+
/**
|
|
465
|
+
* Opt into the strictest loading posture in one flag: redirects are not
|
|
466
|
+
* followed and external `$ref` resolution is disabled entirely
|
|
467
|
+
* (`refResolution.allowedProtocols: []`) — the right default when loading
|
|
468
|
+
* untrusted specs. Explicitly-set `followRedirects`/`refResolution` values
|
|
469
|
+
* still win over the preset.
|
|
470
|
+
* @default false
|
|
471
|
+
*/
|
|
472
|
+
secureDefaults?: boolean;
|
|
401
473
|
/**
|
|
402
474
|
* Controls spec-loading security: external `$ref` resolution AND the host
|
|
403
475
|
* policy for the initial spec-URL fetch. By default `file://` is blocked,
|
|
@@ -430,6 +502,38 @@ export interface GenerateOptions {
|
|
|
430
502
|
* Custom filter function
|
|
431
503
|
*/
|
|
432
504
|
filterFn?: (operation: OperationWithContext) => boolean;
|
|
505
|
+
/**
|
|
506
|
+
* Include only operations carrying at least one of these OpenAPI tags
|
|
507
|
+
*/
|
|
508
|
+
includeTags?: string[];
|
|
509
|
+
/**
|
|
510
|
+
* Exclude operations carrying any of these OpenAPI tags
|
|
511
|
+
*/
|
|
512
|
+
excludeTags?: string[];
|
|
513
|
+
/**
|
|
514
|
+
* Include only these HTTP methods
|
|
515
|
+
*/
|
|
516
|
+
includeMethods?: HTTPMethod[];
|
|
517
|
+
/**
|
|
518
|
+
* Exclude these HTTP methods
|
|
519
|
+
*/
|
|
520
|
+
excludeMethods?: HTTPMethod[];
|
|
521
|
+
/**
|
|
522
|
+
* Include only paths matching at least one of these globs.
|
|
523
|
+
* `*` matches within a path segment, `**` across segments, `?` one character
|
|
524
|
+
* (e.g. `/users/*`, `/admin/**`).
|
|
525
|
+
*/
|
|
526
|
+
includePaths?: string[];
|
|
527
|
+
/**
|
|
528
|
+
* Exclude paths matching any of these globs
|
|
529
|
+
*/
|
|
530
|
+
excludePaths?: string[];
|
|
531
|
+
/**
|
|
532
|
+
* Safety switch: include only operations whose effective annotations say
|
|
533
|
+
* `readOnlyHint: true` (HTTP-method inference merged with extension
|
|
534
|
+
* overrides, regardless of `inferAnnotations`).
|
|
535
|
+
*/
|
|
536
|
+
readOnlyOnly?: boolean;
|
|
433
537
|
/**
|
|
434
538
|
* Naming strategy for resolving conflicts
|
|
435
539
|
*/
|
|
@@ -451,22 +555,63 @@ export interface GenerateOptions {
|
|
|
451
555
|
*/
|
|
452
556
|
includeAllResponses?: boolean;
|
|
453
557
|
/**
|
|
454
|
-
* Maximum depth
|
|
558
|
+
* Maximum schema nesting depth retained in generated input/output schemas.
|
|
559
|
+
* Structures nested deeper than this are truncated: child schemas are
|
|
560
|
+
* stripped and a truncation note is appended to the node's description.
|
|
561
|
+
* Clamped to a minimum of 1 so the root schema always keeps its properties.
|
|
455
562
|
* @default 10
|
|
456
563
|
*/
|
|
457
564
|
maxSchemaDepth?: number;
|
|
458
565
|
/**
|
|
459
|
-
*
|
|
566
|
+
* Include OpenAPI parameter-level and media-type-level `example`/`examples`
|
|
567
|
+
* values in generated schemas (as JSON Schema `examples` arrays). These
|
|
568
|
+
* override schema-level examples where present. Schema-level `example`
|
|
569
|
+
* keywords are always normalized to `examples` regardless of this option.
|
|
460
570
|
* @default false
|
|
461
571
|
*/
|
|
462
572
|
includeExamples?: boolean;
|
|
463
573
|
/**
|
|
464
|
-
* Whether to include security requirements as input parameters
|
|
465
|
-
*
|
|
466
|
-
*
|
|
574
|
+
* Whether to include security requirements as input parameters.
|
|
575
|
+
* - `false` (default): security lives only in the mapper (frameworks
|
|
576
|
+
* resolve credentials from context/env/vaults)
|
|
577
|
+
* - `true`: every security scheme is added to inputSchema as a required
|
|
578
|
+
* string property
|
|
579
|
+
* - `string[]`: only the named schemes appear in inputSchema; the rest stay
|
|
580
|
+
* mapper-only (all schemes are always present in the mapper)
|
|
467
581
|
* @default false
|
|
468
582
|
*/
|
|
469
|
-
includeSecurityInInput?: boolean;
|
|
583
|
+
includeSecurityInInput?: boolean | string[];
|
|
584
|
+
/**
|
|
585
|
+
* Target client schema dialect. Every MCP client accepts a different JSON
|
|
586
|
+
* Schema subset; setting a target applies the transforms that make the
|
|
587
|
+
* generated input/output schemas valid for it: `strict` (safe baseline —
|
|
588
|
+
* local $refs inlined, arrays get `items`, root compositions collapsed),
|
|
589
|
+
* `claude` (= strict), `openai` (strict + closed objects), `gemini`
|
|
590
|
+
* (strict + all unions collapsed + unsupported formats demoted).
|
|
591
|
+
* See `applyClientTarget` for standalone use.
|
|
592
|
+
*/
|
|
593
|
+
target?: import('./client-targets').ClientTarget;
|
|
594
|
+
/**
|
|
595
|
+
* Infer MCP tool annotations from HTTP method semantics:
|
|
596
|
+
* GET/HEAD/OPTIONS/TRACE -> read-only + idempotent; PUT/DELETE ->
|
|
597
|
+
* destructive + idempotent; POST/PATCH -> destructive, not idempotent.
|
|
598
|
+
* `openWorldHint` defaults to false (a known API backend is a closed world).
|
|
599
|
+
* Extension overrides (`x-speakeasy-mcp`, `x-mcp`, `x-frontmcp`) are applied
|
|
600
|
+
* on top of the inferred values regardless of this flag.
|
|
601
|
+
* @default true
|
|
602
|
+
*/
|
|
603
|
+
inferAnnotations?: boolean;
|
|
604
|
+
/**
|
|
605
|
+
* Maximum length for generated tool names. Names longer than this are
|
|
606
|
+
* truncated and given a short hash suffix derived from the full name, so
|
|
607
|
+
* truncated names stay unique and stable across regenerations.
|
|
608
|
+
*
|
|
609
|
+
* MCP tool names may be 1-128 characters of `[A-Za-z0-9_.-]` (values above
|
|
610
|
+
* 128 are clamped to 128). The default of 64 matches the strictest common
|
|
611
|
+
* client limits (Claude / Bedrock cap tool names at 64 characters).
|
|
612
|
+
* @default 64
|
|
613
|
+
*/
|
|
614
|
+
maxToolNameLength?: number;
|
|
470
615
|
/**
|
|
471
616
|
* Enable built-in format-to-schema resolution.
|
|
472
617
|
* Enriches schemas with concrete constraints (patterns, descriptions, min/max)
|