@abhishekkumar00019/swagger-mcp 1.0.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.
@@ -0,0 +1,167 @@
1
+ import { getAuthHeaders } from "./auth.js";
2
+ /**
3
+ * Executes an HTTP request for a tool invocation.
4
+ *
5
+ * Takes the tool mapping (which knows the operation details) and the
6
+ * arguments provided by the LLM, builds the full HTTP request, executes it,
7
+ * and returns the response as a string.
8
+ */
9
+ export async function executeToolRequest(mapping, args, config, baseUrl) {
10
+ const { operation } = mapping;
11
+ try {
12
+ // 1. Validate required path parameters are present
13
+ const missingPathParams = operation.parameters
14
+ .filter((p) => p.in === "path" && p.required && args[p.name] === undefined)
15
+ .map((p) => p.name);
16
+ if (missingPathParams.length > 0) {
17
+ return {
18
+ content: `Missing required path parameter(s): ${missingPathParams.join(", ")}`,
19
+ isError: true,
20
+ };
21
+ }
22
+ // 2. Build the URL with path parameters substituted
23
+ let url = buildUrl(baseUrl, operation.path, args, operation.parameters);
24
+ // 3. Append query parameters
25
+ url = appendQueryParams(url, args, operation.parameters);
26
+ // 4. Build headers
27
+ const headers = {
28
+ Accept: "application/json",
29
+ ...config.defaultHeaders,
30
+ ...getAuthHeaders(config.auth),
31
+ };
32
+ // Add header parameters from args
33
+ for (const param of operation.parameters) {
34
+ if (param.in === "header" && args[param.name] !== undefined) {
35
+ headers[param.name] = String(args[param.name]);
36
+ }
37
+ }
38
+ // 5. Build request body (for methods that support it)
39
+ let body;
40
+ if (args.body !== undefined && ["post", "put", "patch", "delete"].includes(operation.method)) {
41
+ headers["Content-Type"] =
42
+ operation.requestBody?.contentType || "application/json";
43
+ body =
44
+ typeof args.body === "string"
45
+ ? args.body
46
+ : JSON.stringify(args.body);
47
+ }
48
+ // 6. Execute the request
49
+ console.error(`[swagger-mcp] ${operation.method.toUpperCase()} ${url}`);
50
+ const controller = new AbortController();
51
+ const timeoutId = setTimeout(() => controller.abort(), config.timeout);
52
+ try {
53
+ const response = await fetch(url, {
54
+ method: operation.method.toUpperCase(),
55
+ headers,
56
+ body,
57
+ signal: controller.signal,
58
+ });
59
+ clearTimeout(timeoutId);
60
+ // 7. Process response
61
+ const responseText = await response.text();
62
+ if (!response.ok) {
63
+ return {
64
+ content: formatErrorResponse(response.status, response.statusText, responseText),
65
+ isError: true,
66
+ };
67
+ }
68
+ return {
69
+ content: formatSuccessResponse(response.status, responseText),
70
+ isError: false,
71
+ };
72
+ }
73
+ finally {
74
+ clearTimeout(timeoutId);
75
+ }
76
+ }
77
+ catch (error) {
78
+ // Use standard AbortError detection instead of string matching
79
+ if (error instanceof Error && error.name === "AbortError") {
80
+ return {
81
+ content: `Request timed out after ${config.timeout}ms`,
82
+ isError: true,
83
+ };
84
+ }
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ return {
87
+ content: `Request failed: ${message}`,
88
+ isError: true,
89
+ };
90
+ }
91
+ }
92
+ /**
93
+ * Builds the full URL by substituting path parameters into the template.
94
+ * Uses replaceAll to handle duplicate path params (e.g. /users/{id}/friends/{id}).
95
+ */
96
+ function buildUrl(baseUrl, pathTemplate, args, parameters) {
97
+ let resolvedPath = pathTemplate;
98
+ // Substitute path parameters: /users/{id} → /users/123
99
+ for (const param of parameters) {
100
+ if (param.in === "path" && args[param.name] !== undefined) {
101
+ resolvedPath = resolvedPath.replaceAll(`{${param.name}}`, encodeURIComponent(String(args[param.name])));
102
+ }
103
+ }
104
+ // Ensure no double slashes between baseUrl and path
105
+ const cleanBase = baseUrl.replace(/\/+$/, "");
106
+ const cleanPath = resolvedPath.startsWith("/")
107
+ ? resolvedPath
108
+ : `/${resolvedPath}`;
109
+ return `${cleanBase}${cleanPath}`;
110
+ }
111
+ /**
112
+ * Appends query parameters to the URL.
113
+ * Skips null/undefined values to prevent sending "null" as a string.
114
+ */
115
+ function appendQueryParams(url, args, parameters) {
116
+ const queryParams = new URLSearchParams();
117
+ for (const param of parameters) {
118
+ if (param.in === "query" && args[param.name] != null) {
119
+ const value = args[param.name];
120
+ if (Array.isArray(value)) {
121
+ // Handle array query params
122
+ for (const item of value) {
123
+ if (item != null) {
124
+ queryParams.append(param.name, String(item));
125
+ }
126
+ }
127
+ }
128
+ else {
129
+ queryParams.set(param.name, String(value));
130
+ }
131
+ }
132
+ }
133
+ const queryString = queryParams.toString();
134
+ if (!queryString)
135
+ return url;
136
+ const separator = url.includes("?") ? "&" : "?";
137
+ return `${url}${separator}${queryString}`;
138
+ }
139
+ /**
140
+ * Formats a successful response for the MCP tool result.
141
+ */
142
+ function formatSuccessResponse(status, body) {
143
+ let formattedBody;
144
+ try {
145
+ const parsed = JSON.parse(body);
146
+ formattedBody = JSON.stringify(parsed, null, 2);
147
+ }
148
+ catch {
149
+ formattedBody = body;
150
+ }
151
+ return `HTTP ${status}\n\n${formattedBody}`;
152
+ }
153
+ /**
154
+ * Formats an error response for the MCP tool result.
155
+ */
156
+ function formatErrorResponse(status, statusText, body) {
157
+ let formattedBody;
158
+ try {
159
+ const parsed = JSON.parse(body);
160
+ formattedBody = JSON.stringify(parsed, null, 2);
161
+ }
162
+ catch {
163
+ formattedBody = body;
164
+ }
165
+ return `HTTP ${status} ${statusText}\n\n${formattedBody}`;
166
+ }
167
+ //# sourceMappingURL=request-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-handler.js","sourceRoot":"","sources":["../../src/http/request-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { loadConfig } from "./core/config.js";
4
+ import { createServer } from "./server.js";
5
+ /**
6
+ * Entry point for the swagger-mcp server.
7
+ *
8
+ * Loads configuration, creates the MCP server, and connects it
9
+ * to stdio transport for communication with MCP clients.
10
+ */
11
+ async function main() {
12
+ console.error("[swagger-mcp] Starting...");
13
+ // Load configuration from env vars and CLI args
14
+ const config = loadConfig();
15
+ console.error(`[swagger-mcp] Spec URL: ${config.specUrl}`);
16
+ try {
17
+ // Create the MCP server (fetches spec, builds tools)
18
+ const server = await createServer(config);
19
+ // Connect via stdio transport
20
+ const transport = new StdioServerTransport();
21
+ await server.connect(transport);
22
+ console.error("[swagger-mcp] Server is running. Waiting for requests...");
23
+ // Handle graceful shutdown
24
+ const shutdown = async () => {
25
+ console.error("[swagger-mcp] Shutting down...");
26
+ await server.close();
27
+ process.exit(0);
28
+ };
29
+ process.on("SIGINT", shutdown);
30
+ process.on("SIGTERM", shutdown);
31
+ }
32
+ catch (error) {
33
+ const message = error instanceof Error ? error.message : String(error);
34
+ console.error(`[swagger-mcp] Fatal error: ${message}`);
35
+ if (error instanceof Error && error.stack) {
36
+ console.error(error.stack);
37
+ }
38
+ process.exit(1);
39
+ }
40
+ }
41
+ // Safety nets for unhandled errors in the stdio server process
42
+ process.on("unhandledRejection", (reason) => {
43
+ console.error("[swagger-mcp] Unhandled rejection:", reason);
44
+ });
45
+ process.on("uncaughtException", (error) => {
46
+ console.error("[swagger-mcp] Uncaught exception:", error);
47
+ process.exit(1);
48
+ });
49
+ main();
50
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;GAKG;AACH,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAE3C,gDAAgD;IAChD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,OAAO,CAAC,KAAK,CAAC,2BAA2B,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAE3D,IAAI,CAAC;QACH,qDAAqD;QACrD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QAE1C,8BAA8B;QAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEhC,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAE1E,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;YAC1B,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YAChD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,8BAA8B,OAAO,EAAE,CAAC,CAAC;QACvD,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC1C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,EAAE;IAC1C,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,MAAM,CAAC,CAAC;AAC9D,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,EAAE;IACxC,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;IAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,IAAI,EAAE,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { ParsedOperation } from "../core/types.js";
2
+ /**
3
+ * Fetches and parses a Swagger/OpenAPI spec from a URL or file path.
4
+ * Supports both Swagger 2.0 and OpenAPI 3.x.
5
+ * Returns parsed operations and the resolved base URL from the spec.
6
+ */
7
+ export declare function parseSwaggerSpec(specUrl: string): Promise<{
8
+ operations: ParsedOperation[];
9
+ specBaseUrl: string | undefined;
10
+ title: string;
11
+ version: string;
12
+ }>;
13
+ /**
14
+ * Sanitizes a schema object for use as a JSON Schema in MCP tools.
15
+ * Removes OpenAPI-specific extensions and null/undefined values.
16
+ *
17
+ * Uses a WeakSet to track visited objects and prevent infinite loops
18
+ * on circular references (which SwaggerParser.dereference() can create).
19
+ */
20
+ export declare function sanitizeSchema(schema: Record<string, unknown>, visited?: WeakSet<object>): Record<string, unknown>;
@@ -0,0 +1,262 @@
1
+ import SwaggerParser from "@apidevtools/swagger-parser";
2
+ import { HTTP_METHODS, } from "../core/types.js";
3
+ /**
4
+ * Fetches and parses a Swagger/OpenAPI spec from a URL or file path.
5
+ * Supports both Swagger 2.0 and OpenAPI 3.x.
6
+ * Returns parsed operations and the resolved base URL from the spec.
7
+ */
8
+ export async function parseSwaggerSpec(specUrl) {
9
+ console.error(`[swagger-mcp] Fetching spec from: ${specUrl}`);
10
+ let api;
11
+ try {
12
+ // Dereference resolves all $ref pointers so we get a flat object
13
+ api = await SwaggerParser.dereference(specUrl);
14
+ }
15
+ catch (error) {
16
+ const message = error instanceof Error ? error.message : String(error);
17
+ throw new Error(`Failed to fetch or parse OpenAPI spec from "${specUrl}": ${message}`);
18
+ }
19
+ const title = api.info?.title || "Unknown API";
20
+ const version = api.info?.version || "0.0.0";
21
+ console.error(`[swagger-mcp] Parsed: ${title} v${version}`);
22
+ const specBaseUrl = extractBaseUrl(api);
23
+ const operations = extractOperations(api);
24
+ console.error(`[swagger-mcp] Found ${operations.length} operations`);
25
+ return { operations, specBaseUrl, title, version };
26
+ }
27
+ /**
28
+ * Extracts the base URL from the spec.
29
+ * - OpenAPI 3.x: uses servers[0].url
30
+ * - Swagger 2.0: uses host + basePath + schemes
31
+ */
32
+ function extractBaseUrl(api) {
33
+ // OpenAPI 3.x
34
+ if ("openapi" in api && api.openapi?.startsWith("3")) {
35
+ const doc = api;
36
+ if (doc.servers && doc.servers.length > 0) {
37
+ return doc.servers[0].url;
38
+ }
39
+ return undefined;
40
+ }
41
+ // Swagger 2.0
42
+ if ("swagger" in api) {
43
+ const doc = api;
44
+ if (doc.host) {
45
+ const scheme = doc.schemes && doc.schemes.length > 0 ? doc.schemes[0] : "https";
46
+ const basePath = doc.basePath || "";
47
+ return `${scheme}://${doc.host}${basePath}`;
48
+ }
49
+ return undefined;
50
+ }
51
+ return undefined;
52
+ }
53
+ /**
54
+ * Extracts all operations from the spec into ParsedOperation objects.
55
+ */
56
+ function extractOperations(api) {
57
+ const operations = [];
58
+ if (!api.paths)
59
+ return operations;
60
+ const isV3 = "openapi" in api;
61
+ for (const [path, pathItem] of Object.entries(api.paths)) {
62
+ if (!pathItem)
63
+ continue;
64
+ // Path-level parameters (shared by all operations on this path)
65
+ const pathLevelParams = extractPathLevelParams(pathItem);
66
+ for (const method of HTTP_METHODS) {
67
+ const operation = pathItem[method];
68
+ if (!operation || typeof operation !== "object")
69
+ continue;
70
+ const op = operation;
71
+ // Parse operation-level parameters, filtering out body params for Swagger 2.0
72
+ // (body params are handled separately in parseRequestBody)
73
+ const rawOperationParams = parseParameters(op.parameters || []);
74
+ const operationParams = rawOperationParams.filter((p) => p.in !== "body");
75
+ // Merge path-level and operation-level parameters
76
+ const mergedParams = mergeParameters(pathLevelParams, operationParams);
77
+ // Parse request body
78
+ const requestBody = parseRequestBody(op, api);
79
+ // Extract tag
80
+ const tags = op.tags;
81
+ const tag = tags && tags.length > 0 ? tags[0] : undefined;
82
+ operations.push({
83
+ operationId: op.operationId,
84
+ method,
85
+ path,
86
+ tag,
87
+ summary: op.summary,
88
+ description: op.description,
89
+ parameters: mergedParams,
90
+ requestBody,
91
+ });
92
+ }
93
+ }
94
+ return operations;
95
+ }
96
+ /**
97
+ * Extracts path-level parameters from a path item.
98
+ * Filters out body and formData params (handled separately).
99
+ */
100
+ function extractPathLevelParams(pathItem) {
101
+ const params = pathItem.parameters;
102
+ if (!Array.isArray(params))
103
+ return [];
104
+ return parseParameters(params).filter((p) => p.in !== "body");
105
+ }
106
+ /**
107
+ * Parses parameter objects into ParsedParameter[].
108
+ * Handles both Swagger 2.0 and OpenAPI 3.x parameter formats.
109
+ */
110
+ function parseParameters(params) {
111
+ return params
112
+ .filter((p) => p !== null && typeof p === "object")
113
+ .filter((param) => {
114
+ // Skip formData params — they're used for file uploads and
115
+ // don't map cleanly to JSON-based MCP tool inputs
116
+ const paramIn = param.in;
117
+ return paramIn !== "formData";
118
+ })
119
+ .map((param) => {
120
+ // Swagger 2.0: type is directly on the param
121
+ // OpenAPI 3.x: type is in param.schema
122
+ let schema = {};
123
+ if (param.schema && typeof param.schema === "object") {
124
+ // OpenAPI 3.x
125
+ schema = sanitizeSchema(param.schema);
126
+ }
127
+ else if (param.type) {
128
+ // Swagger 2.0
129
+ const schemaObj = {
130
+ type: param.type,
131
+ };
132
+ if (param.format)
133
+ schemaObj.format = param.format;
134
+ if (param.enum)
135
+ schemaObj.enum = param.enum;
136
+ if (param.default !== undefined)
137
+ schemaObj.default = param.default;
138
+ if (param.items && typeof param.items === "object") {
139
+ schemaObj.items = sanitizeSchema(param.items);
140
+ }
141
+ schema = sanitizeSchema(schemaObj);
142
+ }
143
+ return {
144
+ name: param.name,
145
+ in: param.in,
146
+ description: param.description,
147
+ required: param.required || false,
148
+ schema,
149
+ };
150
+ });
151
+ }
152
+ /**
153
+ * Parses request body from an operation.
154
+ * Handles both Swagger 2.0 (body parameter) and OpenAPI 3.x (requestBody).
155
+ */
156
+ function parseRequestBody(operation, api) {
157
+ // OpenAPI 3.x: requestBody object
158
+ if ("openapi" in api && operation.requestBody) {
159
+ const rb = operation.requestBody;
160
+ const content = rb.content;
161
+ if (content) {
162
+ // Prefer application/json, fall back to first content type
163
+ const contentType = content["application/json"]
164
+ ? "application/json"
165
+ : Object.keys(content)[0];
166
+ if (contentType) {
167
+ const mediaType = content[contentType];
168
+ const schema = mediaType?.schema;
169
+ return {
170
+ description: rb.description,
171
+ required: rb.required || false,
172
+ schema: schema ? sanitizeSchema(schema) : { type: "object" },
173
+ contentType,
174
+ };
175
+ }
176
+ }
177
+ return undefined;
178
+ }
179
+ // Swagger 2.0: look for a parameter with in: "body"
180
+ const params = operation.parameters;
181
+ if (params) {
182
+ const bodyParam = params.find((p) => p !== null &&
183
+ typeof p === "object" &&
184
+ p.in === "body");
185
+ if (bodyParam) {
186
+ const schema = bodyParam.schema;
187
+ return {
188
+ description: bodyParam.description,
189
+ required: bodyParam.required || false,
190
+ schema: schema ? sanitizeSchema(schema) : { type: "object" },
191
+ contentType: "application/json",
192
+ };
193
+ }
194
+ }
195
+ return undefined;
196
+ }
197
+ /**
198
+ * Merge path-level and operation-level parameters.
199
+ * Operation params override path-level params with the same name+in.
200
+ */
201
+ function mergeParameters(pathParams, operationParams) {
202
+ const merged = new Map();
203
+ for (const p of pathParams) {
204
+ merged.set(`${p.in}:${p.name}`, p);
205
+ }
206
+ for (const p of operationParams) {
207
+ merged.set(`${p.in}:${p.name}`, p);
208
+ }
209
+ return Array.from(merged.values());
210
+ }
211
+ /**
212
+ * Sanitizes a schema object for use as a JSON Schema in MCP tools.
213
+ * Removes OpenAPI-specific extensions and null/undefined values.
214
+ *
215
+ * Uses a WeakSet to track visited objects and prevent infinite loops
216
+ * on circular references (which SwaggerParser.dereference() can create).
217
+ */
218
+ export function sanitizeSchema(schema, visited = new WeakSet()) {
219
+ // Circular reference guard
220
+ if (visited.has(schema)) {
221
+ return { type: "object", description: "(circular reference)" };
222
+ }
223
+ visited.add(schema);
224
+ const result = {};
225
+ for (const [key, value] of Object.entries(schema)) {
226
+ // Skip OpenAPI-specific extensions and undefined/null values
227
+ if (key.startsWith("x-") || value === undefined || value === null)
228
+ continue;
229
+ // Skip XML definitions
230
+ if (key === "xml")
231
+ continue;
232
+ if (key === "properties" && typeof value === "object" && value !== null) {
233
+ // Recursively sanitize nested property schemas
234
+ const props = {};
235
+ for (const [propName, propSchema] of Object.entries(value)) {
236
+ if (propSchema && typeof propSchema === "object") {
237
+ props[propName] = sanitizeSchema(propSchema, visited);
238
+ }
239
+ else {
240
+ props[propName] = propSchema;
241
+ }
242
+ }
243
+ result[key] = props;
244
+ }
245
+ else if (key === "items" &&
246
+ typeof value === "object" &&
247
+ value !== null) {
248
+ // Recursively sanitize array items schema
249
+ result[key] = sanitizeSchema(value, visited);
250
+ }
251
+ else if (key === "additionalProperties" &&
252
+ typeof value === "object" &&
253
+ value !== null) {
254
+ result[key] = sanitizeSchema(value, visited);
255
+ }
256
+ else {
257
+ result[key] = value;
258
+ }
259
+ }
260
+ return result;
261
+ }
262
+ //# sourceMappingURL=swagger-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swagger-parser.js","sourceRoot":"","sources":["../../src/parser/swagger-parser.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAKL,YAAY,GACb,MAAM,kBAAkB,CAAC;AAQ1B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAe;IAMpD,OAAO,CAAC,KAAK,CAAC,qCAAqC,OAAO,EAAE,CAAC,CAAC;IAE9D,IAAI,GAAoB,CAAC;IACzB,IAAI,CAAC;QACH,iEAAiE;QACjE,GAAG,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,KAAK,CACb,+CAA+C,OAAO,MAAM,OAAO,EAAE,CACtE,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,aAAa,CAAC;IAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,OAAO,CAAC;IAC7C,OAAO,CAAC,KAAK,CAAC,yBAAyB,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC;IAE5D,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAE1C,OAAO,CAAC,KAAK,CAAC,uBAAuB,UAAU,CAAC,MAAM,aAAa,CAAC,CAAC;IACrE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,GAAoB;IAC1C,cAAc;IACd,IAAI,SAAS,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,GAAG,CAAC;QAChB,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAC5B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,cAAc;IACd,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,GAAG,CAAC;QAChB,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACb,MAAM,MAAM,GACV,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACnE,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;YACpC,OAAO,GAAG,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC;QAC9C,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,GAAoB;IAC7C,MAAM,UAAU,GAAsB,EAAE,CAAC;IAEzC,IAAI,CAAC,GAAG,CAAC,KAAK;QAAE,OAAO,UAAU,CAAC;IAElC,MAAM,IAAI,GAAG,SAAS,IAAI,GAAG,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,IAAI,CAAC,QAAQ;YAAE,SAAS;QAExB,gEAAgE;QAChE,MAAM,eAAe,GAAG,sBAAsB,CAC5C,QAAmC,CACpC,CAAC;QAEF,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,MAAM,SAAS,GAAI,QAAoC,CAAC,MAAM,CAAC,CAAC;YAChE,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ;gBAAE,SAAS;YAE1D,MAAM,EAAE,GAAG,SAAoC,CAAC;YAEhD,8EAA8E;YAC9E,2DAA2D;YAC3D,MAAM,kBAAkB,GAAG,eAAe,CACvC,EAAE,CAAC,UAAwB,IAAI,EAAE,CACnC,CAAC;YACF,MAAM,eAAe,GAAG,kBAAkB,CAAC,MAAM,CAC/C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAgB,CACjC,CAAC;YAEF,kDAAkD;YAClD,MAAM,YAAY,GAAG,eAAe,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;YAEvE,qBAAqB;YACrB,MAAM,WAAW,GAAG,gBAAgB,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAE9C,cAAc;YACd,MAAM,IAAI,GAAG,EAAE,CAAC,IAA4B,CAAC;YAC7C,MAAM,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAE1D,UAAU,CAAC,IAAI,CAAC;gBACd,WAAW,EAAE,EAAE,CAAC,WAAiC;gBACjD,MAAM;gBACN,IAAI;gBACJ,GAAG;gBACH,OAAO,EAAE,EAAE,CAAC,OAA6B;gBACzC,WAAW,EAAE,EAAE,CAAC,WAAiC;gBACjD,UAAU,EAAE,YAAY;gBACxB,WAAW;aACZ,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,SAAS,sBAAsB,CAC7B,QAAiC;IAEjC,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,MAAM,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAgB,CACjC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,MAAiB;IACxC,OAAO,MAAM;SACV,MAAM,CACL,CAAC,CAAC,EAAgC,EAAE,CAClC,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,CACtC;SACA,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAChB,2DAA2D;QAC3D,kDAAkD;QAClD,MAAM,OAAO,GAAG,KAAK,CAAC,EAAY,CAAC;QACnC,OAAO,OAAO,KAAK,UAAU,CAAC;IAChC,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,6CAA6C;QAC7C,uCAAuC;QACvC,IAAI,MAAM,GAA4B,EAAE,CAAC;QAEzC,IAAI,KAAK,CAAC,MAAM,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACrD,cAAc;YACd,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,MAAiC,CAAC,CAAC;QACnE,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACtB,cAAc;YACd,MAAM,SAAS,GAA4B;gBACzC,IAAI,EAAE,KAAK,CAAC,IAAc;aAC3B,CAAC;YACF,IAAI,KAAK,CAAC,MAAM;gBAAE,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAClD,IAAI,KAAK,CAAC,IAAI;gBAAE,SAAS,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;YAC5C,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;gBAAE,SAAS,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;YACnE,IAAI,KAAK,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACnD,SAAS,CAAC,KAAK,GAAG,cAAc,CAC9B,KAAK,CAAC,KAAgC,CACvC,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;QACrC,CAAC;QAED,OAAO;YACL,IAAI,EAAE,KAAK,CAAC,IAAc;YAC1B,EAAE,EAAE,KAAK,CAAC,EAA2B;YACrC,WAAW,EAAE,KAAK,CAAC,WAAiC;YACpD,QAAQ,EAAG,KAAK,CAAC,QAAoB,IAAI,KAAK;YAC9C,MAAM;SACP,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CACvB,SAAkC,EAClC,GAAoB;IAEpB,kCAAkC;IAClC,IAAI,SAAS,IAAI,GAAG,IAAI,SAAS,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,EAAE,GAAG,SAAS,CAAC,WAAsC,CAAC;QAC5D,MAAM,OAAO,GAAG,EAAE,CAAC,OAA8C,CAAC;QAElE,IAAI,OAAO,EAAE,CAAC;YACZ,2DAA2D;YAC3D,MAAM,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC;gBAC7C,CAAC,CAAC,kBAAkB;gBACpB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YAE5B,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAA4B,CAAC;gBAClE,MAAM,MAAM,GAAG,SAAS,EAAE,MAEb,CAAC;gBAEd,OAAO;oBACL,WAAW,EAAE,EAAE,CAAC,WAAiC;oBACjD,QAAQ,EAAG,EAAE,CAAC,QAAoB,IAAI,KAAK;oBAC3C,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAC5D,WAAW;iBACZ,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,oDAAoD;IACpD,MAAM,MAAM,GAAG,SAAS,CAAC,UAAmC,CAAC;IAC7D,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAC3B,CAAC,CAAU,EAAE,EAAE,CACb,CAAC,KAAK,IAAI;YACV,OAAO,CAAC,KAAK,QAAQ;YACpB,CAA6B,CAAC,EAAE,KAAK,MAAM,CACR,CAAC;QAEzC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,SAAS,CAAC,MAA6C,CAAC;YACvE,OAAO;gBACL,WAAW,EAAE,SAAS,CAAC,WAAiC;gBACxD,QAAQ,EAAG,SAAS,CAAC,QAAoB,IAAI,KAAK;gBAClD,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC5D,WAAW,EAAE,kBAAkB;aAChC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CACtB,UAA6B,EAC7B,eAAkC;IAElC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;IAElD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,MAA+B,EAC/B,UAA2B,IAAI,OAAO,EAAE;IAExC,2BAA2B;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC;IACjE,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEpB,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,6DAA6D;QAC7D,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QAC5E,uBAAuB;QACvB,IAAI,GAAG,KAAK,KAAK;YAAE,SAAS;QAE5B,IAAI,GAAG,KAAK,YAAY,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACxE,+CAA+C;YAC/C,MAAM,KAAK,GAA4B,EAAE,CAAC;YAC1C,KAAK,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CACjD,KAAgC,CACjC,EAAE,CAAC;gBACF,IAAI,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;oBACjD,KAAK,CAAC,QAAQ,CAAC,GAAG,cAAc,CAC9B,UAAqC,EACrC,OAAO,CACR,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC;gBAC/B,CAAC;YACH,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;aAAM,IACL,GAAG,KAAK,OAAO;YACf,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI,EACd,CAAC;YACD,0CAA0C;YAC1C,MAAM,CAAC,GAAG,CAAC,GAAG,cAAc,CAC1B,KAAgC,EAChC,OAAO,CACR,CAAC;QACJ,CAAC;aAAM,IACL,GAAG,KAAK,sBAAsB;YAC9B,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI,EACd,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,cAAc,CAC1B,KAAgC,EAChC,OAAO,CACR,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { ParsedOperation, ToolMapping } from "../core/types.js";
2
+ /**
3
+ * Converts parsed OpenAPI operations into MCP tool definitions and mappings.
4
+ */
5
+ export declare function buildTools(operations: ParsedOperation[]): {
6
+ tools: McpToolDefinition[];
7
+ mappings: Map<string, ToolMapping>;
8
+ };
9
+ export interface McpToolDefinition {
10
+ name: string;
11
+ description: string;
12
+ inputSchema: {
13
+ type: "object";
14
+ properties: Record<string, unknown>;
15
+ required?: string[];
16
+ };
17
+ }
18
+ /**
19
+ * Generates a unique MCP tool name for an operation.
20
+ *
21
+ * Priority:
22
+ * 1. operationId (if present in the spec) — preserves casing
23
+ * 2. tag + method + path (if tag exists) — lowercased
24
+ * 3. method + path (last resort) — lowercased
25
+ *
26
+ * Sanitization: replace special chars with _, collapse multiples,
27
+ * strip leading/trailing _, max 64 chars.
28
+ */
29
+ export declare function generateToolName(operation: ParsedOperation, usedNames: Set<string>): string;