@ttoss/http-server-mcp-openapi 0.7.3 → 0.8.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/MIGRATIONS.md ADDED
@@ -0,0 +1,35 @@
1
+ # Migrations
2
+
3
+ ## `openApiToTools` replaces `registerOpenApiTools`
4
+
5
+ The package now derives tools and leaves registering them to `registerTools`
6
+ from `@ttoss/http-server-mcp`, which can also
7
+ [defer](./README.md#deferring-the-tools-of-a-large-api) them behind
8
+ `search` / `describe` / `call`.
9
+
10
+ ```diff
11
+ -import { registerOpenApiTools } from '@ttoss/http-server-mcp-openapi';
12
+ +import { registerTools } from '@ttoss/http-server-mcp';
13
+ +import { openApiToTools } from '@ttoss/http-server-mcp-openapi';
14
+
15
+ -registerOpenApiTools({ server, spec, callApi, serverParameters });
16
+ +registerTools({
17
+ + server,
18
+ + tools: openApiToTools({ spec, callApi, serverParameters }),
19
+ +});
20
+ ```
21
+
22
+ Every other argument keeps its name and meaning; only `server` moves to
23
+ `registerTools`. `RegisterOpenApiToolsArgs` is now `OpenApiToToolsArgs`,
24
+ without `server`.
25
+
26
+ The return value changed: `registerOpenApiTools` answered the
27
+ `ToolDefinition`s, `openApiToTools` answers `OpenApiTool`s, each carrying its
28
+ `ToolDefinition` as `definition`. Replace `tool.method` with
29
+ `tool.definition.method`, and so on, wherever you read the result.
30
+
31
+ `ToolDefinition` gained `tags`, copied from the operation. A consumer that
32
+ builds `ToolDefinition` objects by hand must add it.
33
+
34
+ **What you will observe if you miss this.** The build fails on the missing
35
+ `registerOpenApiTools` import. Generated tools answer exactly as before.
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # @ttoss/http-server-mcp-openapi
2
2
 
3
3
  Generate [Model Context Protocol (MCP)](https://modelcontextprotocol.io) tools
4
- from an [OpenAPI](https://www.openapis.org/) specification and register them on
5
- a [@ttoss/http-server-mcp](https://ttoss.dev/docs/modules/packages/http-server-mcp)
6
- server.
4
+ from an [OpenAPI](https://www.openapis.org/) specification, ready for
5
+ [@ttoss/http-server-mcp](https://ttoss.dev/docs/modules/packages/http-server-mcp)'s
6
+ `registerTools`.
7
7
 
8
8
  Point it at your existing OpenAPI document and every operation becomes an MCP
9
9
  tool whose handler resolves the incoming arguments into an HTTP request against
@@ -20,15 +20,18 @@ pnpm add @ttoss/http-server-mcp-openapi @ttoss/http-server-mcp
20
20
 
21
21
  ```typescript
22
22
  import { App, bodyParser } from '@ttoss/http-server';
23
- import { createMcpRouter, McpServer } from '@ttoss/http-server-mcp';
24
- import { registerOpenApiTools } from '@ttoss/http-server-mcp-openapi';
23
+ import {
24
+ createMcpRouter,
25
+ McpServer,
26
+ registerTools,
27
+ } from '@ttoss/http-server-mcp';
28
+ import { openApiToTools } from '@ttoss/http-server-mcp-openapi';
25
29
 
26
30
  import openApiDocument from './openapi.json' with { type: 'json' };
27
31
 
28
32
  const server = new McpServer({ name: 'my-api', version: '1.0.0' });
29
33
 
30
- registerOpenApiTools({
31
- server,
34
+ const tools = openApiToTools({
32
35
  spec: openApiDocument,
33
36
  // You own how the request is executed — base URL, auth, fetch impl.
34
37
  // `headers` is what createMcpRouter's `getApiHeaders` produced for this
@@ -44,6 +47,8 @@ registerOpenApiTools({
44
47
  },
45
48
  });
46
49
 
50
+ registerTools({ server, tools });
51
+
47
52
  const app = new App();
48
53
  app.use(bodyParser());
49
54
  app.use(createMcpRouter(server).routes());
@@ -55,13 +60,14 @@ app.listen(3000);
55
60
  Each OpenAPI operation with an `operationId` and a supported HTTP method
56
61
  (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`) becomes one tool:
57
62
 
58
- | OpenAPI | MCP tool |
59
- | ------------------------- | -------------------------------------------- |
60
- | `operationId: listAgents` | tool name `list-agents` (kebab-case) |
61
- | path/query/body params | a single `inputSchema` object |
62
- | `$ref`, `oneOf`, `anyOf` | dereferenced and merged into a flat schema |
63
- | snake_case names | camelCase tool inputs, mapped back on call |
64
- | operation `description` | tool description (quotes/newlines sanitised) |
63
+ | OpenAPI | MCP tool |
64
+ | ------------------------- | --------------------------------------------- |
65
+ | `operationId: listAgents` | tool name `list-agents` (kebab-case) |
66
+ | path/query/body params | a single `inputSchema` object |
67
+ | `$ref`, `oneOf`, `anyOf` | dereferenced and merged into a flat schema |
68
+ | snake_case names | camelCase tool inputs, mapped back on call |
69
+ | operation `description` | tool description (quotes/newlines sanitised) |
70
+ | operation `tags` | tool `tags`, for the deferred `search` filter |
65
71
 
66
72
  Path params are always required strings. Query and body params carry their
67
73
  declared type and `required` flag. Array params keep their `items` schema. A
@@ -87,24 +93,63 @@ repeats array values, `spaceDelimited`/`pipeDelimited` join them, and
87
93
  `deepObject` emits bracketed keys — including nested objects and arrays, so
88
94
  `{ documentId: { $eq: 'doc_1' } }` becomes `filters[documentId][$eq]=doc_1`.
89
95
 
90
- ## `registerOpenApiTools`
96
+ ## `openApiToTools`
91
97
 
92
98
  | Field | Description |
93
99
  | ---------------------- | ------------------------------------------------------------------------------------------------------------- |
94
- | `server` | The `McpServer` to register tools on. |
95
100
  | `spec` | One OpenAPI document, or an array of them (tools are flattened). |
96
101
  | `callApi` | Runs the resolved `{ method, url, body, tool, headers }` request and returns the raw data. |
97
102
  | `toText?` | Serialises the raw data into the tool's text payload. Defaults to pretty JSON; strings pass through verbatim. |
98
103
  | `serverParameters?` | Supplies server-managed path/query parameter values. See [Server-managed values](#server-managed-values). |
99
104
  | `toStructuredContent?` | `({ data, tool })` → the result's `structuredContent`, sent beside the text. `undefined` keeps it text-only. |
100
105
  | `toolMeta?` | `({ tool })` → the tool's `_meta` on `tools/list`. See [MCP Apps views](#mcp-apps-views). |
106
+ | `validateArguments?` | Enforce each generated `inputSchema` before `callApi` runs. Default `false`; see the caveat below. |
101
107
  | `options?` | See [Options](#options). |
102
108
 
103
109
  The default `toText` answers `NO_CONTENT_TEXT` (`Succeeded. The operation
104
110
  returned no content.`) when `callApi` resolves `undefined` or `''`, so a `204`
105
111
  reaches the client as a success.
106
112
 
107
- Returns the list of `ToolDefinition`s that were registered.
113
+ Returns one `OpenApiTool` per operation: a `Tool` with the operation's `tags`,
114
+ a `summary` of `METHOD /path — description`, and the `definition` it was
115
+ derived from. Enable `validateArguments` only when the spec describes every
116
+ value the API accepts: a generated schema is easily narrower than the API, and
117
+ validating against it rejects calls the API would have taken.
118
+
119
+ ### Deferring the tools of a large API
120
+
121
+ Every tool definition ships to the model on every turn, so a large API
122
+ overflows the client's context. [Defer](https://github.com/ttoss/ttoss/tree/main/packages/http-server-mcp#deferring-tools-for-large-tool-sets)
123
+ the same tools behind `search` / `describe` / `call`, for example on a second
124
+ endpoint next to the full one:
125
+
126
+ ```typescript
127
+ registerTools({ server: fullServer, tools });
128
+ registerTools({ server: deferredServer, tools, defer: true });
129
+ ```
130
+
131
+ `search` filters by the operations' tags and shows each tool's route; tools
132
+ linked to an MCP Apps view stay registered directly.
133
+
134
+ ### Gating generated tools
135
+
136
+ A generated tool is an ordinary `Tool`, so a gate wraps it like any other.
137
+ `definition` carries what the operation declares, such as a custom extension
138
+ naming the scope:
139
+
140
+ ```typescript
141
+ const gate = createToolGate({ gates: [subscriptionGate] });
142
+
143
+ registerTools({
144
+ server,
145
+ tools: tools.map((tool) => {
146
+ return gate({
147
+ tool,
148
+ requiredScope: tool.definition.extensions['x-required-scope'] as string,
149
+ });
150
+ }),
151
+ });
152
+ ```
108
153
 
109
154
  ### MCP Apps views
110
155
 
@@ -112,7 +157,7 @@ A generated tool links to a view through `toolMeta`, and the view reads the
112
157
  result from `structuredContent`:
113
158
 
114
159
  ```typescript
115
- import { registerAppResource } from '@ttoss/http-server-mcp';
160
+ import { registerAppResource, registerTools } from '@ttoss/http-server-mcp';
116
161
 
117
162
  const agentCard = registerAppResource({
118
163
  server,
@@ -121,8 +166,7 @@ const agentCard = registerAppResource({
121
166
  html: agentCardHtml,
122
167
  });
123
168
 
124
- registerOpenApiTools({
125
- server,
169
+ const tools = openApiToTools({
126
170
  spec,
127
171
  callApi,
128
172
  toolMeta: ({ tool }) => {
@@ -134,6 +178,8 @@ registerOpenApiTools({
134
178
  : undefined;
135
179
  },
136
180
  });
181
+
182
+ registerTools({ server, tools });
137
183
  ```
138
184
 
139
185
  Keep the text payload: a host without MCP Apps support renders only that.
@@ -151,11 +197,10 @@ forwarded onto the dispatched request.
151
197
  ```typescript
152
198
  import {
153
199
  createInProcessCallApi,
154
- registerOpenApiTools,
200
+ openApiToTools,
155
201
  } from '@ttoss/http-server-mcp-openapi';
156
202
 
157
- registerOpenApiTools({
158
- server,
203
+ const tools = openApiToTools({
159
204
  spec,
160
205
  callApi: createInProcessCallApi({
161
206
  app, // or () => app, when the app is built after the tools
@@ -163,6 +208,8 @@ registerOpenApiTools({
163
208
  }),
164
209
  });
165
210
 
211
+ registerTools({ server, tools });
212
+
166
213
  const router = createMcpRouter(server, {
167
214
  getApiHeaders: (ctx) => ({ authorization: ctx.headers.authorization ?? '' }),
168
215
  });
@@ -178,7 +225,7 @@ back to `HTTP <status>`. Pass `toError` to build the error yourself.
178
225
  ## `openApiToToolDefinitions`
179
226
 
180
227
  Use the lower-level function when you want the tool definitions without
181
- registering them — to inspect, filter, or wire handlers yourself:
228
+ handlers — to inspect, filter, or wire handlers yourself:
182
229
 
183
230
  ```typescript
184
231
  import { openApiToToolDefinitions } from '@ttoss/http-server-mcp-openapi';
@@ -193,14 +240,13 @@ for (const tool of tools) {
193
240
  ```
194
241
 
195
242
  Each `ToolDefinition` exposes `name`, `description`, `inputSchema`, `method`,
196
- `pathTemplate`, `operationId`, the `path`/`query`/`body` builders,
243
+ `pathTemplate`, `operationId`, `tags`, the `path`/`query`/`body` builders,
197
244
  `acceptedBodyFields`, `extensions`, and `serverManagedParameters`.
198
245
 
199
246
  ## Options
200
247
 
201
248
  ```typescript
202
- registerOpenApiTools({
203
- server,
249
+ openApiToTools({
204
250
  spec,
205
251
  callApi,
206
252
  options: {
@@ -259,12 +305,11 @@ A value flagged with `serverManagedExtension` is never offered to the model:
259
305
  never sent (the API sets it itself). It still appears in
260
306
  `acceptedBodyFields`.
261
307
  - A **path or query parameter** is hidden from `inputSchema` and listed in
262
- `tool.serverManagedParameters`. `registerOpenApiTools` discards anything the
308
+ `tool.serverManagedParameters`. `openApiToTools` discards anything the
263
309
  model sent for it and fills it from `serverParameters`, keyed by spec name:
264
310
 
265
311
  ```typescript
266
- registerOpenApiTools({
267
- server,
312
+ openApiToTools({
268
313
  spec,
269
314
  callApi,
270
315
  serverParameters: ({ tool, headers }) => ({
@@ -299,6 +344,12 @@ const tools = openApiToToolDefinitions({ spec: openApiDocument });
299
344
  const iamAction = tools[0].extensions['x-iam-action'];
300
345
  ```
301
346
 
347
+ ## Migrations
348
+
349
+ Breaking changes and what they require of consumers are listed in
350
+ [MIGRATIONS.md](https://github.com/ttoss/ttoss/blob/main/packages/http-server-mcp-openapi/MIGRATIONS.md),
351
+ newest first.
352
+
302
353
  ## Related Packages
303
354
 
304
355
  - [@ttoss/http-server-mcp](https://ttoss.dev/docs/modules/packages/http-server-mcp) - MCP server integration for @ttoss/http-server
package/dist/index.cjs CHANGED
@@ -354,7 +354,7 @@ var pinnedArgs = parameters => {
354
354
  /**
355
355
  * Wraps a `path` / `query` builder so pinned values replace whatever the args
356
356
  * carry. Applied in the builder itself, so every consumer of the tool
357
- * definition sends them, not only `registerOpenApiTools`.
357
+ * definition sends them, not only `openApiToTools`.
358
358
  */
359
359
  var withPinned = args => {
360
360
  const {
@@ -812,7 +812,7 @@ var defaultToError = response => {
812
812
  return new Error(errorMessageOf(response.body) ?? `HTTP ${response.status}`);
813
813
  };
814
814
  /**
815
- * A `callApi` for {@link registerOpenApiTools} that serves each tool call
815
+ * A `callApi` for {@link openApiToTools} that serves each tool call
816
816
  * against the REST app in this same process, with no socket: validation,
817
817
  * authorization and error handling run once, in the routes, for both
818
818
  * surfaces.
@@ -824,10 +824,9 @@ var defaultToError = response => {
824
824
  *
825
825
  * @example
826
826
  * ```typescript
827
- * registerOpenApiTools({
827
+ * registerTools({
828
828
  * server,
829
- * spec,
830
- * callApi: createInProcessCallApi({ app }),
829
+ * tools: openApiToTools({ spec, callApi: createInProcessCallApi({ app }) }),
831
830
  * });
832
831
  * ```
833
832
  */
@@ -992,6 +991,12 @@ var extractExtensions = operation => {
992
991
  for (const [key, value] of Object.entries(operation)) if (key.startsWith("x-")) extensions[key] = value;
993
992
  return extensions;
994
993
  };
994
+ /** The operation's tags, ignoring entries a malformed spec typed otherwise. */
995
+ var operationTags = operation => {
996
+ return (operation.tags ?? []).filter(tag => {
997
+ return typeof tag === "string";
998
+ });
999
+ };
995
1000
  var processOperation = args => {
996
1001
  const httpMethod = args.method.toUpperCase();
997
1002
  if (!SUPPORTED_METHODS.includes(httpMethod) || !args.operation.operationId || args.operation[args.options.excludeExtension]) return null;
@@ -1042,6 +1047,7 @@ var processOperation = args => {
1042
1047
  method: httpMethod,
1043
1048
  pathTemplate: args.pathTemplate,
1044
1049
  operationId: args.operation.operationId,
1050
+ tags: operationTags(args.operation),
1045
1051
  path: withPinned({
1046
1052
  build: buildPathFn(args.pathTemplate, pathParams),
1047
1053
  pinned
@@ -1120,7 +1126,7 @@ var openApiToToolDefinitions = args => {
1120
1126
  };
1121
1127
 
1122
1128
  //#endregion
1123
- //#region src/registerOpenApiTools.ts
1129
+ //#region src/openApiToTools.ts
1124
1130
  /** The text the default `toText` answers when the API returned no body. */
1125
1131
  var NO_CONTENT_TEXT = "Succeeded. The operation returned no content.";
1126
1132
  var defaultToText = data => {
@@ -1146,21 +1152,21 @@ var applyServerParameters = async args => {
1146
1152
  return result;
1147
1153
  };
1148
1154
  /**
1149
- * Derives MCP tools from OpenAPI document(s) and registers each on the given
1150
- * MCP server. Every tool's handler resolves the incoming args into a concrete
1151
- * HTTP request and delegates execution to `callApi`.
1155
+ * Derives MCP tools from OpenAPI document(s). Each tool's handler resolves
1156
+ * the incoming args into a concrete HTTP request and delegates execution to
1157
+ * `callApi`. Register the result with `registerTools` from
1158
+ * `@ttoss/http-server-mcp` — one MCP tool each, or deferred.
1152
1159
  *
1153
- * @returns The list of {@link ToolDefinition} that were registered.
1160
+ * @returns One {@link OpenApiTool} per translatable operation.
1154
1161
  *
1155
1162
  * @example
1156
1163
  * ```typescript
1157
- * import { McpServer } from '@ttoss/http-server-mcp';
1158
- * import { registerOpenApiTools } from '@ttoss/http-server-mcp-openapi';
1164
+ * import { McpServer, registerTools } from '@ttoss/http-server-mcp';
1165
+ * import { openApiToTools } from '@ttoss/http-server-mcp-openapi';
1159
1166
  *
1160
1167
  * const server = new McpServer({ name: 'my-api', version: '1.0.0' });
1161
1168
  *
1162
- * registerOpenApiTools({
1163
- * server,
1169
+ * const tools = openApiToTools({
1164
1170
  * spec: myOpenApiDocument,
1165
1171
  * callApi: async ({ method, url, body, headers }) => {
1166
1172
  * const res = await fetch(`https://api.example.com${url}`, {
@@ -1171,53 +1177,62 @@ var applyServerParameters = async args => {
1171
1177
  * return res.json();
1172
1178
  * },
1173
1179
  * });
1180
+ *
1181
+ * registerTools({ server, tools });
1174
1182
  * ```
1175
1183
  */
1176
- var registerOpenApiTools = args => {
1184
+ var openApiToTools = args => {
1177
1185
  const toText = args.toText ?? defaultToText;
1178
- const tools = openApiToToolDefinitions({
1186
+ return openApiToToolDefinitions({
1179
1187
  spec: args.spec,
1180
1188
  options: args.options
1189
+ }).map(definition => {
1190
+ const route = `${definition.method} ${definition.pathTemplate}`;
1191
+ return {
1192
+ name: definition.name,
1193
+ description: definition.description,
1194
+ inputSchema: definition.inputSchema,
1195
+ validateArguments: args.validateArguments ?? false,
1196
+ ...(definition.tags.length > 0 ? {
1197
+ tags: definition.tags
1198
+ } : {}),
1199
+ summary: definition.description ? `${route} — ${definition.description}` : route,
1200
+ _meta: args.toolMeta?.({
1201
+ tool: definition
1202
+ }),
1203
+ definition,
1204
+ handler: async rawArgs => {
1205
+ const headers = (0, _ttoss_http_server_mcp.getApiHeaders)();
1206
+ const handlerArgs = await applyServerParameters({
1207
+ tool: definition,
1208
+ handlerArgs: rawArgs,
1209
+ headers,
1210
+ serverParameters: args.serverParameters
1211
+ });
1212
+ const url = definition.path(handlerArgs) + (definition.query ? definition.query(handlerArgs) : "");
1213
+ const data = await args.callApi({
1214
+ method: definition.method,
1215
+ url,
1216
+ body: definition.body ? definition.body(handlerArgs) : void 0,
1217
+ tool: definition,
1218
+ headers
1219
+ });
1220
+ const structuredContent = args.toStructuredContent?.({
1221
+ data,
1222
+ tool: definition
1223
+ });
1224
+ return {
1225
+ content: [{
1226
+ type: "text",
1227
+ text: toText(data)
1228
+ }],
1229
+ ...(structuredContent === void 0 ? {} : {
1230
+ structuredContent
1231
+ })
1232
+ };
1233
+ }
1234
+ };
1181
1235
  });
1182
- for (const tool of tools) (0, _ttoss_http_server_mcp.registerToolFromSchema)(args.server, {
1183
- name: tool.name,
1184
- description: tool.description,
1185
- inputSchema: tool.inputSchema,
1186
- _meta: args.toolMeta?.({
1187
- tool
1188
- }),
1189
- handler: async rawArgs => {
1190
- const headers = (0, _ttoss_http_server_mcp.getApiHeaders)();
1191
- const handlerArgs = await applyServerParameters({
1192
- tool,
1193
- handlerArgs: rawArgs,
1194
- headers,
1195
- serverParameters: args.serverParameters
1196
- });
1197
- const url = tool.path(handlerArgs) + (tool.query ? tool.query(handlerArgs) : "");
1198
- const data = await args.callApi({
1199
- method: tool.method,
1200
- url,
1201
- body: tool.body ? tool.body(handlerArgs) : void 0,
1202
- tool,
1203
- headers
1204
- });
1205
- const structuredContent = args.toStructuredContent?.({
1206
- data,
1207
- tool
1208
- });
1209
- return {
1210
- content: [{
1211
- type: "text",
1212
- text: toText(data)
1213
- }],
1214
- ...(structuredContent === void 0 ? {} : {
1215
- structuredContent
1216
- })
1217
- };
1218
- }
1219
- });
1220
- return tools;
1221
1236
  };
1222
1237
 
1223
1238
  //#endregion
@@ -1239,10 +1254,10 @@ exports.extractPinnedBody = extractPinnedBody;
1239
1254
  exports.extractQueryParams = extractQueryParams;
1240
1255
  exports.getJsonSchemaType = getJsonSchemaType;
1241
1256
  exports.openApiToToolDefinitions = openApiToToolDefinitions;
1257
+ exports.openApiToTools = openApiToTools;
1242
1258
  exports.operationIdToToolName = operationIdToToolName;
1243
1259
  exports.processOperation = processOperation;
1244
1260
  exports.processPath = processPath;
1245
- exports.registerOpenApiTools = registerOpenApiTools;
1246
1261
  exports.resolveParameter = resolveParameter;
1247
1262
  exports.resolveSchema = resolveSchema;
1248
1263
  exports.snakeToCamel = snakeToCamel;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- import { JsonObjectSchema, McpServer } from "@ttoss/http-server-mcp";
2
+ import { JsonObjectSchema, Tool } from "@ttoss/http-server-mcp";
3
3
  import { App, InProcessResponse } from "@ttoss/http-server";
4
4
 
5
5
  //#region src/types.d.ts
@@ -49,6 +49,8 @@ interface ToolDefinition {
49
49
  pathTemplate: string;
50
50
  /** The operation's `operationId`. */
51
51
  operationId: string;
52
+ /** The operation's `tags`, e.g. to filter the deferred `search` by module. */
53
+ tags: string[];
52
54
  /** Builds the request path, substituting path params from the args. */
53
55
  path: (args: Record<string, unknown>) => string;
54
56
  /** Builds the query string (including leading `?`), or `undefined` if none. */
@@ -73,7 +75,7 @@ interface ToolDefinition {
73
75
  * Path and query parameters flagged with the server-managed extension. They
74
76
  * are absent from `inputSchema`, but `path` / `query` still read them from
75
77
  * the args under `argName`, so the consumer fills them before building the
76
- * request — `registerOpenApiTools` does it through `serverParameters`.
78
+ * request — `openApiToTools` does it through `serverParameters`.
77
79
  */
78
80
  serverManagedParameters: ServerManagedParameter[];
79
81
  }
@@ -122,6 +124,7 @@ type RequestBodySpec = {
122
124
  };
123
125
  interface OperationSpec {
124
126
  operationId?: string;
127
+ tags?: string[];
125
128
  summary?: string;
126
129
  description?: string;
127
130
  parameters?: Array<{
@@ -342,7 +345,7 @@ declare const buildFullInputSchema: (args: {
342
345
  bodyProps: FullBodyProp[];
343
346
  }) => JsonObjectSchema;
344
347
  //#endregion
345
- //#region src/registerOpenApiTools.d.ts
348
+ //#region src/openApiToTools.d.ts
346
349
  /** The resolved HTTP request a tool call maps to, before transport concerns. */
347
350
  interface ResolvedRequest {
348
351
  /** Uppercase HTTP method. */
@@ -360,9 +363,7 @@ interface ResolvedRequest {
360
363
  */
361
364
  headers: Record<string, string>;
362
365
  }
363
- interface RegisterOpenApiToolsArgs {
364
- /** The MCP server the generated tools are registered on. */
365
- server: McpServer;
366
+ interface OpenApiToToolsArgs {
366
367
  /** One or more OpenAPI documents to derive tools from. */
367
368
  spec: OpenApiSpec | OpenApiSpec[];
368
369
  /** Tuning options forwarded to {@link openApiToToolDefinitions}. */
@@ -399,7 +400,7 @@ interface RegisterOpenApiToolsArgs {
399
400
  /**
400
401
  * Builds each tool's `_meta`, advertised on `tools/list`. This is how a
401
402
  * generated tool links to an MCP Apps view: return the bag from
402
- * `registerAppResource(...).toolMeta()`. `undefined` registers no `_meta`.
403
+ * `registerAppResource(...).toolMeta()`. `undefined` sets no `_meta`.
403
404
  *
404
405
  * @example
405
406
  * ```typescript
@@ -427,25 +428,41 @@ interface RegisterOpenApiToolsArgs {
427
428
  tool: ToolDefinition;
428
429
  headers: Record<string, string>;
429
430
  }) => Record<string, unknown> | Promise<Record<string, unknown>>;
431
+ /**
432
+ * Sets every tool's `validateArguments`: enforce the generated
433
+ * `inputSchema` before `callApi` runs. Leave it off unless the spec
434
+ * describes every value the API accepts — see `Tool.validateArguments`.
435
+ * @default false
436
+ */
437
+ validateArguments?: boolean;
438
+ }
439
+ /** A {@link Tool} derived from one OpenAPI operation. */
440
+ interface OpenApiTool extends Tool {
441
+ /**
442
+ * The operation it was derived from — method, path, extensions — for
443
+ * decisions that key on the API rather than the tool name, such as which
444
+ * scope a gate requires.
445
+ */
446
+ definition: ToolDefinition;
430
447
  }
431
448
  /** The text the default `toText` answers when the API returned no body. */
432
449
  declare const NO_CONTENT_TEXT = "Succeeded. The operation returned no content.";
433
450
  /**
434
- * Derives MCP tools from OpenAPI document(s) and registers each on the given
435
- * MCP server. Every tool's handler resolves the incoming args into a concrete
436
- * HTTP request and delegates execution to `callApi`.
451
+ * Derives MCP tools from OpenAPI document(s). Each tool's handler resolves
452
+ * the incoming args into a concrete HTTP request and delegates execution to
453
+ * `callApi`. Register the result with `registerTools` from
454
+ * `@ttoss/http-server-mcp` — one MCP tool each, or deferred.
437
455
  *
438
- * @returns The list of {@link ToolDefinition} that were registered.
456
+ * @returns One {@link OpenApiTool} per translatable operation.
439
457
  *
440
458
  * @example
441
459
  * ```typescript
442
- * import { McpServer } from '@ttoss/http-server-mcp';
443
- * import { registerOpenApiTools } from '@ttoss/http-server-mcp-openapi';
460
+ * import { McpServer, registerTools } from '@ttoss/http-server-mcp';
461
+ * import { openApiToTools } from '@ttoss/http-server-mcp-openapi';
444
462
  *
445
463
  * const server = new McpServer({ name: 'my-api', version: '1.0.0' });
446
464
  *
447
- * registerOpenApiTools({
448
- * server,
465
+ * const tools = openApiToTools({
449
466
  * spec: myOpenApiDocument,
450
467
  * callApi: async ({ method, url, body, headers }) => {
451
468
  * const res = await fetch(`https://api.example.com${url}`, {
@@ -456,9 +473,11 @@ declare const NO_CONTENT_TEXT = "Succeeded. The operation returned no content.";
456
473
  * return res.json();
457
474
  * },
458
475
  * });
476
+ *
477
+ * registerTools({ server, tools });
459
478
  * ```
460
479
  */
461
- declare const registerOpenApiTools: (args: RegisterOpenApiToolsArgs) => ToolDefinition[];
480
+ declare const openApiToTools: (args: OpenApiToToolsArgs) => OpenApiTool[];
462
481
  //#endregion
463
482
  //#region src/inProcessCallApi.d.ts
464
483
  interface CreateInProcessCallApiArgs {
@@ -487,7 +506,7 @@ interface CreateInProcessCallApiArgs {
487
506
  */
488
507
  declare const errorMessageOf: (body: unknown) => string | null;
489
508
  /**
490
- * A `callApi` for {@link registerOpenApiTools} that serves each tool call
509
+ * A `callApi` for {@link openApiToTools} that serves each tool call
491
510
  * against the REST app in this same process, with no socket: validation,
492
511
  * authorization and error handling run once, in the routes, for both
493
512
  * surfaces.
@@ -499,10 +518,9 @@ declare const errorMessageOf: (body: unknown) => string | null;
499
518
  *
500
519
  * @example
501
520
  * ```typescript
502
- * registerOpenApiTools({
521
+ * registerTools({
503
522
  * server,
504
- * spec,
505
- * callApi: createInProcessCallApi({ app }),
523
+ * tools: openApiToTools({ spec, callApi: createInProcessCallApi({ app }) }),
506
524
  * });
507
525
  * ```
508
526
  */
@@ -650,4 +668,4 @@ declare const openApiToToolDefinitions: (args: {
650
668
  options?: OpenApiToToolsOptions;
651
669
  }) => ToolDefinition[];
652
670
  //#endregion
653
- export { type CreateInProcessCallApiArgs, DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, type JsonSchemaProperty, NO_CONTENT_TEXT, type OpenApiDocuments, type OpenApiSpec, type OpenApiToToolsOptions, type OperationSpec, type QueryParamSerialization, type RegisterOpenApiToolsArgs, type RequestBodySpec, type ResolvedParameter, type ResolvedRequest, type ResolvedToolOptions, type ServerManagedParameter, type ToolDefinition, buildBodyFn, buildFullInputSchema, buildInputSchema, buildPathFn, buildQueryFn, createInProcessCallApi, dereferenceSchema, errorMessageOf, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractPinnedBody, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, operationIdToToolName, processOperation, processPath, registerOpenApiTools, resolveParameter, resolveSchema, snakeToCamel, toToolSchema };
671
+ export { type CreateInProcessCallApiArgs, DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, type JsonSchemaProperty, NO_CONTENT_TEXT, type OpenApiDocuments, type OpenApiSpec, type OpenApiToToolsArgs, type OpenApiToToolsOptions, type OpenApiTool, type OperationSpec, type QueryParamSerialization, type RequestBodySpec, type ResolvedParameter, type ResolvedRequest, type ResolvedToolOptions, type ServerManagedParameter, type ToolDefinition, buildBodyFn, buildFullInputSchema, buildInputSchema, buildPathFn, buildQueryFn, createInProcessCallApi, dereferenceSchema, errorMessageOf, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractPinnedBody, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, openApiToTools, operationIdToToolName, processOperation, processPath, resolveParameter, resolveSchema, snakeToCamel, toToolSchema };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
 
2
2
  import { App, InProcessResponse } from "@ttoss/http-server";
3
- import { JsonObjectSchema, McpServer } from "@ttoss/http-server-mcp";
3
+ import { JsonObjectSchema, Tool } from "@ttoss/http-server-mcp";
4
4
 
5
5
  //#region src/types.d.ts
6
6
  /** The JSON Schema primitive types this generator can derive from an OpenAPI `type`. */
@@ -49,6 +49,8 @@ interface ToolDefinition {
49
49
  pathTemplate: string;
50
50
  /** The operation's `operationId`. */
51
51
  operationId: string;
52
+ /** The operation's `tags`, e.g. to filter the deferred `search` by module. */
53
+ tags: string[];
52
54
  /** Builds the request path, substituting path params from the args. */
53
55
  path: (args: Record<string, unknown>) => string;
54
56
  /** Builds the query string (including leading `?`), or `undefined` if none. */
@@ -73,7 +75,7 @@ interface ToolDefinition {
73
75
  * Path and query parameters flagged with the server-managed extension. They
74
76
  * are absent from `inputSchema`, but `path` / `query` still read them from
75
77
  * the args under `argName`, so the consumer fills them before building the
76
- * request — `registerOpenApiTools` does it through `serverParameters`.
78
+ * request — `openApiToTools` does it through `serverParameters`.
77
79
  */
78
80
  serverManagedParameters: ServerManagedParameter[];
79
81
  }
@@ -122,6 +124,7 @@ type RequestBodySpec = {
122
124
  };
123
125
  interface OperationSpec {
124
126
  operationId?: string;
127
+ tags?: string[];
125
128
  summary?: string;
126
129
  description?: string;
127
130
  parameters?: Array<{
@@ -342,7 +345,7 @@ declare const buildFullInputSchema: (args: {
342
345
  bodyProps: FullBodyProp[];
343
346
  }) => JsonObjectSchema;
344
347
  //#endregion
345
- //#region src/registerOpenApiTools.d.ts
348
+ //#region src/openApiToTools.d.ts
346
349
  /** The resolved HTTP request a tool call maps to, before transport concerns. */
347
350
  interface ResolvedRequest {
348
351
  /** Uppercase HTTP method. */
@@ -360,9 +363,7 @@ interface ResolvedRequest {
360
363
  */
361
364
  headers: Record<string, string>;
362
365
  }
363
- interface RegisterOpenApiToolsArgs {
364
- /** The MCP server the generated tools are registered on. */
365
- server: McpServer;
366
+ interface OpenApiToToolsArgs {
366
367
  /** One or more OpenAPI documents to derive tools from. */
367
368
  spec: OpenApiSpec | OpenApiSpec[];
368
369
  /** Tuning options forwarded to {@link openApiToToolDefinitions}. */
@@ -399,7 +400,7 @@ interface RegisterOpenApiToolsArgs {
399
400
  /**
400
401
  * Builds each tool's `_meta`, advertised on `tools/list`. This is how a
401
402
  * generated tool links to an MCP Apps view: return the bag from
402
- * `registerAppResource(...).toolMeta()`. `undefined` registers no `_meta`.
403
+ * `registerAppResource(...).toolMeta()`. `undefined` sets no `_meta`.
403
404
  *
404
405
  * @example
405
406
  * ```typescript
@@ -427,25 +428,41 @@ interface RegisterOpenApiToolsArgs {
427
428
  tool: ToolDefinition;
428
429
  headers: Record<string, string>;
429
430
  }) => Record<string, unknown> | Promise<Record<string, unknown>>;
431
+ /**
432
+ * Sets every tool's `validateArguments`: enforce the generated
433
+ * `inputSchema` before `callApi` runs. Leave it off unless the spec
434
+ * describes every value the API accepts — see `Tool.validateArguments`.
435
+ * @default false
436
+ */
437
+ validateArguments?: boolean;
438
+ }
439
+ /** A {@link Tool} derived from one OpenAPI operation. */
440
+ interface OpenApiTool extends Tool {
441
+ /**
442
+ * The operation it was derived from — method, path, extensions — for
443
+ * decisions that key on the API rather than the tool name, such as which
444
+ * scope a gate requires.
445
+ */
446
+ definition: ToolDefinition;
430
447
  }
431
448
  /** The text the default `toText` answers when the API returned no body. */
432
449
  declare const NO_CONTENT_TEXT = "Succeeded. The operation returned no content.";
433
450
  /**
434
- * Derives MCP tools from OpenAPI document(s) and registers each on the given
435
- * MCP server. Every tool's handler resolves the incoming args into a concrete
436
- * HTTP request and delegates execution to `callApi`.
451
+ * Derives MCP tools from OpenAPI document(s). Each tool's handler resolves
452
+ * the incoming args into a concrete HTTP request and delegates execution to
453
+ * `callApi`. Register the result with `registerTools` from
454
+ * `@ttoss/http-server-mcp` — one MCP tool each, or deferred.
437
455
  *
438
- * @returns The list of {@link ToolDefinition} that were registered.
456
+ * @returns One {@link OpenApiTool} per translatable operation.
439
457
  *
440
458
  * @example
441
459
  * ```typescript
442
- * import { McpServer } from '@ttoss/http-server-mcp';
443
- * import { registerOpenApiTools } from '@ttoss/http-server-mcp-openapi';
460
+ * import { McpServer, registerTools } from '@ttoss/http-server-mcp';
461
+ * import { openApiToTools } from '@ttoss/http-server-mcp-openapi';
444
462
  *
445
463
  * const server = new McpServer({ name: 'my-api', version: '1.0.0' });
446
464
  *
447
- * registerOpenApiTools({
448
- * server,
465
+ * const tools = openApiToTools({
449
466
  * spec: myOpenApiDocument,
450
467
  * callApi: async ({ method, url, body, headers }) => {
451
468
  * const res = await fetch(`https://api.example.com${url}`, {
@@ -456,9 +473,11 @@ declare const NO_CONTENT_TEXT = "Succeeded. The operation returned no content.";
456
473
  * return res.json();
457
474
  * },
458
475
  * });
476
+ *
477
+ * registerTools({ server, tools });
459
478
  * ```
460
479
  */
461
- declare const registerOpenApiTools: (args: RegisterOpenApiToolsArgs) => ToolDefinition[];
480
+ declare const openApiToTools: (args: OpenApiToToolsArgs) => OpenApiTool[];
462
481
  //#endregion
463
482
  //#region src/inProcessCallApi.d.ts
464
483
  interface CreateInProcessCallApiArgs {
@@ -487,7 +506,7 @@ interface CreateInProcessCallApiArgs {
487
506
  */
488
507
  declare const errorMessageOf: (body: unknown) => string | null;
489
508
  /**
490
- * A `callApi` for {@link registerOpenApiTools} that serves each tool call
509
+ * A `callApi` for {@link openApiToTools} that serves each tool call
491
510
  * against the REST app in this same process, with no socket: validation,
492
511
  * authorization and error handling run once, in the routes, for both
493
512
  * surfaces.
@@ -499,10 +518,9 @@ declare const errorMessageOf: (body: unknown) => string | null;
499
518
  *
500
519
  * @example
501
520
  * ```typescript
502
- * registerOpenApiTools({
521
+ * registerTools({
503
522
  * server,
504
- * spec,
505
- * callApi: createInProcessCallApi({ app }),
523
+ * tools: openApiToTools({ spec, callApi: createInProcessCallApi({ app }) }),
506
524
  * });
507
525
  * ```
508
526
  */
@@ -650,4 +668,4 @@ declare const openApiToToolDefinitions: (args: {
650
668
  options?: OpenApiToToolsOptions;
651
669
  }) => ToolDefinition[];
652
670
  //#endregion
653
- export { type CreateInProcessCallApiArgs, DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, type JsonSchemaProperty, NO_CONTENT_TEXT, type OpenApiDocuments, type OpenApiSpec, type OpenApiToToolsOptions, type OperationSpec, type QueryParamSerialization, type RegisterOpenApiToolsArgs, type RequestBodySpec, type ResolvedParameter, type ResolvedRequest, type ResolvedToolOptions, type ServerManagedParameter, type ToolDefinition, buildBodyFn, buildFullInputSchema, buildInputSchema, buildPathFn, buildQueryFn, createInProcessCallApi, dereferenceSchema, errorMessageOf, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractPinnedBody, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, operationIdToToolName, processOperation, processPath, registerOpenApiTools, resolveParameter, resolveSchema, snakeToCamel, toToolSchema };
671
+ export { type CreateInProcessCallApiArgs, DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, type JsonSchemaProperty, NO_CONTENT_TEXT, type OpenApiDocuments, type OpenApiSpec, type OpenApiToToolsArgs, type OpenApiToToolsOptions, type OpenApiTool, type OperationSpec, type QueryParamSerialization, type RequestBodySpec, type ResolvedParameter, type ResolvedRequest, type ResolvedToolOptions, type ServerManagedParameter, type ToolDefinition, buildBodyFn, buildFullInputSchema, buildInputSchema, buildPathFn, buildQueryFn, createInProcessCallApi, dereferenceSchema, errorMessageOf, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractPinnedBody, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, openApiToTools, operationIdToToolName, processOperation, processPath, resolveParameter, resolveSchema, snakeToCamel, toToolSchema };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
2
  import { dispatchInProcess } from "@ttoss/http-server";
3
- import { getApiHeaders, registerToolFromSchema } from "@ttoss/http-server-mcp";
3
+ import { getApiHeaders } from "@ttoss/http-server-mcp";
4
4
 
5
5
  //#region src/schema.ts
6
6
  var isRecord$1 = value => {
@@ -351,7 +351,7 @@ var pinnedArgs = parameters => {
351
351
  /**
352
352
  * Wraps a `path` / `query` builder so pinned values replace whatever the args
353
353
  * carry. Applied in the builder itself, so every consumer of the tool
354
- * definition sends them, not only `registerOpenApiTools`.
354
+ * definition sends them, not only `openApiToTools`.
355
355
  */
356
356
  var withPinned = args => {
357
357
  const {
@@ -809,7 +809,7 @@ var defaultToError = response => {
809
809
  return new Error(errorMessageOf(response.body) ?? `HTTP ${response.status}`);
810
810
  };
811
811
  /**
812
- * A `callApi` for {@link registerOpenApiTools} that serves each tool call
812
+ * A `callApi` for {@link openApiToTools} that serves each tool call
813
813
  * against the REST app in this same process, with no socket: validation,
814
814
  * authorization and error handling run once, in the routes, for both
815
815
  * surfaces.
@@ -821,10 +821,9 @@ var defaultToError = response => {
821
821
  *
822
822
  * @example
823
823
  * ```typescript
824
- * registerOpenApiTools({
824
+ * registerTools({
825
825
  * server,
826
- * spec,
827
- * callApi: createInProcessCallApi({ app }),
826
+ * tools: openApiToTools({ spec, callApi: createInProcessCallApi({ app }) }),
828
827
  * });
829
828
  * ```
830
829
  */
@@ -989,6 +988,12 @@ var extractExtensions = operation => {
989
988
  for (const [key, value] of Object.entries(operation)) if (key.startsWith("x-")) extensions[key] = value;
990
989
  return extensions;
991
990
  };
991
+ /** The operation's tags, ignoring entries a malformed spec typed otherwise. */
992
+ var operationTags = operation => {
993
+ return (operation.tags ?? []).filter(tag => {
994
+ return typeof tag === "string";
995
+ });
996
+ };
992
997
  var processOperation = args => {
993
998
  const httpMethod = args.method.toUpperCase();
994
999
  if (!SUPPORTED_METHODS.includes(httpMethod) || !args.operation.operationId || args.operation[args.options.excludeExtension]) return null;
@@ -1039,6 +1044,7 @@ var processOperation = args => {
1039
1044
  method: httpMethod,
1040
1045
  pathTemplate: args.pathTemplate,
1041
1046
  operationId: args.operation.operationId,
1047
+ tags: operationTags(args.operation),
1042
1048
  path: withPinned({
1043
1049
  build: buildPathFn(args.pathTemplate, pathParams),
1044
1050
  pinned
@@ -1117,7 +1123,7 @@ var openApiToToolDefinitions = args => {
1117
1123
  };
1118
1124
 
1119
1125
  //#endregion
1120
- //#region src/registerOpenApiTools.ts
1126
+ //#region src/openApiToTools.ts
1121
1127
  /** The text the default `toText` answers when the API returned no body. */
1122
1128
  var NO_CONTENT_TEXT = "Succeeded. The operation returned no content.";
1123
1129
  var defaultToText = data => {
@@ -1143,21 +1149,21 @@ var applyServerParameters = async args => {
1143
1149
  return result;
1144
1150
  };
1145
1151
  /**
1146
- * Derives MCP tools from OpenAPI document(s) and registers each on the given
1147
- * MCP server. Every tool's handler resolves the incoming args into a concrete
1148
- * HTTP request and delegates execution to `callApi`.
1152
+ * Derives MCP tools from OpenAPI document(s). Each tool's handler resolves
1153
+ * the incoming args into a concrete HTTP request and delegates execution to
1154
+ * `callApi`. Register the result with `registerTools` from
1155
+ * `@ttoss/http-server-mcp` — one MCP tool each, or deferred.
1149
1156
  *
1150
- * @returns The list of {@link ToolDefinition} that were registered.
1157
+ * @returns One {@link OpenApiTool} per translatable operation.
1151
1158
  *
1152
1159
  * @example
1153
1160
  * ```typescript
1154
- * import { McpServer } from '@ttoss/http-server-mcp';
1155
- * import { registerOpenApiTools } from '@ttoss/http-server-mcp-openapi';
1161
+ * import { McpServer, registerTools } from '@ttoss/http-server-mcp';
1162
+ * import { openApiToTools } from '@ttoss/http-server-mcp-openapi';
1156
1163
  *
1157
1164
  * const server = new McpServer({ name: 'my-api', version: '1.0.0' });
1158
1165
  *
1159
- * registerOpenApiTools({
1160
- * server,
1166
+ * const tools = openApiToTools({
1161
1167
  * spec: myOpenApiDocument,
1162
1168
  * callApi: async ({ method, url, body, headers }) => {
1163
1169
  * const res = await fetch(`https://api.example.com${url}`, {
@@ -1168,54 +1174,63 @@ var applyServerParameters = async args => {
1168
1174
  * return res.json();
1169
1175
  * },
1170
1176
  * });
1177
+ *
1178
+ * registerTools({ server, tools });
1171
1179
  * ```
1172
1180
  */
1173
- var registerOpenApiTools = args => {
1181
+ var openApiToTools = args => {
1174
1182
  const toText = args.toText ?? defaultToText;
1175
- const tools = openApiToToolDefinitions({
1183
+ return openApiToToolDefinitions({
1176
1184
  spec: args.spec,
1177
1185
  options: args.options
1186
+ }).map(definition => {
1187
+ const route = `${definition.method} ${definition.pathTemplate}`;
1188
+ return {
1189
+ name: definition.name,
1190
+ description: definition.description,
1191
+ inputSchema: definition.inputSchema,
1192
+ validateArguments: args.validateArguments ?? false,
1193
+ ...(definition.tags.length > 0 ? {
1194
+ tags: definition.tags
1195
+ } : {}),
1196
+ summary: definition.description ? `${route} — ${definition.description}` : route,
1197
+ _meta: args.toolMeta?.({
1198
+ tool: definition
1199
+ }),
1200
+ definition,
1201
+ handler: async rawArgs => {
1202
+ const headers = getApiHeaders();
1203
+ const handlerArgs = await applyServerParameters({
1204
+ tool: definition,
1205
+ handlerArgs: rawArgs,
1206
+ headers,
1207
+ serverParameters: args.serverParameters
1208
+ });
1209
+ const url = definition.path(handlerArgs) + (definition.query ? definition.query(handlerArgs) : "");
1210
+ const data = await args.callApi({
1211
+ method: definition.method,
1212
+ url,
1213
+ body: definition.body ? definition.body(handlerArgs) : void 0,
1214
+ tool: definition,
1215
+ headers
1216
+ });
1217
+ const structuredContent = args.toStructuredContent?.({
1218
+ data,
1219
+ tool: definition
1220
+ });
1221
+ return {
1222
+ content: [{
1223
+ type: "text",
1224
+ text: toText(data)
1225
+ }],
1226
+ ...(structuredContent === void 0 ? {} : {
1227
+ structuredContent
1228
+ })
1229
+ };
1230
+ }
1231
+ };
1178
1232
  });
1179
- for (const tool of tools) registerToolFromSchema(args.server, {
1180
- name: tool.name,
1181
- description: tool.description,
1182
- inputSchema: tool.inputSchema,
1183
- _meta: args.toolMeta?.({
1184
- tool
1185
- }),
1186
- handler: async rawArgs => {
1187
- const headers = getApiHeaders();
1188
- const handlerArgs = await applyServerParameters({
1189
- tool,
1190
- handlerArgs: rawArgs,
1191
- headers,
1192
- serverParameters: args.serverParameters
1193
- });
1194
- const url = tool.path(handlerArgs) + (tool.query ? tool.query(handlerArgs) : "");
1195
- const data = await args.callApi({
1196
- method: tool.method,
1197
- url,
1198
- body: tool.body ? tool.body(handlerArgs) : void 0,
1199
- tool,
1200
- headers
1201
- });
1202
- const structuredContent = args.toStructuredContent?.({
1203
- data,
1204
- tool
1205
- });
1206
- return {
1207
- content: [{
1208
- type: "text",
1209
- text: toText(data)
1210
- }],
1211
- ...(structuredContent === void 0 ? {} : {
1212
- structuredContent
1213
- })
1214
- };
1215
- }
1216
- });
1217
- return tools;
1218
1233
  };
1219
1234
 
1220
1235
  //#endregion
1221
- export { DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, NO_CONTENT_TEXT, buildBodyFn, buildFullInputSchema, buildInputSchema, buildPathFn, buildQueryFn, createInProcessCallApi, dereferenceSchema, errorMessageOf, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractPinnedBody, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, operationIdToToolName, processOperation, processPath, registerOpenApiTools, resolveParameter, resolveSchema, snakeToCamel, toToolSchema };
1236
+ export { DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, NO_CONTENT_TEXT, buildBodyFn, buildFullInputSchema, buildInputSchema, buildPathFn, buildQueryFn, createInProcessCallApi, dereferenceSchema, errorMessageOf, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractPinnedBody, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, openApiToTools, operationIdToToolName, processOperation, processPath, resolveParameter, resolveSchema, snakeToCamel, toToolSchema };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/http-server-mcp-openapi",
3
- "version": "0.7.3",
3
+ "version": "0.8.0",
4
4
  "description": "Generate Model Context Protocol (MCP) tools from an OpenAPI specification for @ttoss/http-server-mcp",
5
5
  "keywords": [
6
6
  "ai",
@@ -32,11 +32,12 @@
32
32
  }
33
33
  },
34
34
  "files": [
35
+ "MIGRATIONS.md",
35
36
  "dist"
36
37
  ],
37
38
  "dependencies": {
38
- "@ttoss/http-server": "^0.11.1",
39
- "@ttoss/http-server-mcp": "^0.33.2"
39
+ "@ttoss/http-server-mcp": "^0.34.0",
40
+ "@ttoss/http-server": "^0.11.1"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@modelcontextprotocol/server": "^2.0.0",