@ivotoby/openapi-mcp-server 1.3.0 → 1.4.1
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 +1 -1
- package/dist/bundle.js +139 -20
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/bundle.js
CHANGED
|
@@ -14450,6 +14450,33 @@ var OpenAPISpecLoader = class {
|
|
|
14450
14450
|
}
|
|
14451
14451
|
return schemaObj;
|
|
14452
14452
|
}
|
|
14453
|
+
/**
|
|
14454
|
+
* Determine the appropriate JSON Schema type for a parameter
|
|
14455
|
+
* @param paramSchema The OpenAPI schema object after inlining
|
|
14456
|
+
* @param paramName The name of the parameter (for logging purposes)
|
|
14457
|
+
* @returns The determined type string, or undefined if the type should be omitted
|
|
14458
|
+
*/
|
|
14459
|
+
determineParameterType(paramSchema, paramName) {
|
|
14460
|
+
if (Object.keys(paramSchema).length === 0 && typeof paramSchema !== "boolean") {
|
|
14461
|
+
console.warn(
|
|
14462
|
+
`Parameter '${paramName}' schema was empty after inlining (potential cycle or unresolvable ref), defaulting to string.`
|
|
14463
|
+
);
|
|
14464
|
+
return "string";
|
|
14465
|
+
}
|
|
14466
|
+
if (typeof paramSchema === "boolean") {
|
|
14467
|
+
return "boolean";
|
|
14468
|
+
}
|
|
14469
|
+
if (paramSchema.type) {
|
|
14470
|
+
return paramSchema.type;
|
|
14471
|
+
}
|
|
14472
|
+
const hasProperties = "properties" in paramSchema && paramSchema.properties && Object.keys(paramSchema.properties).length > 0;
|
|
14473
|
+
const hasItems = paramSchema.type === "array" && !!paramSchema.items;
|
|
14474
|
+
const hasComposition = "allOf" in paramSchema && paramSchema.allOf && paramSchema.allOf.length > 0 || "anyOf" in paramSchema && paramSchema.anyOf && paramSchema.anyOf.length > 0 || "oneOf" in paramSchema && paramSchema.oneOf && paramSchema.oneOf.length > 0;
|
|
14475
|
+
if (!hasProperties && !hasItems && !hasComposition) {
|
|
14476
|
+
return "string";
|
|
14477
|
+
}
|
|
14478
|
+
return void 0;
|
|
14479
|
+
}
|
|
14453
14480
|
/**
|
|
14454
14481
|
* Parse an OpenAPI specification into a map of tools
|
|
14455
14482
|
*/
|
|
@@ -14459,7 +14486,10 @@ var OpenAPISpecLoader = class {
|
|
|
14459
14486
|
if (!pathItem) continue;
|
|
14460
14487
|
for (const [method, operation] of Object.entries(pathItem)) {
|
|
14461
14488
|
if (method === "parameters" || !operation) continue;
|
|
14462
|
-
if (!["get", "
|
|
14489
|
+
if (!["get", "post", "put", "patch", "delete", "options", "head"].includes(
|
|
14490
|
+
method.toLowerCase()
|
|
14491
|
+
)) {
|
|
14492
|
+
console.warn(`Skipping non-HTTP method "${method}" for path ${path}`);
|
|
14463
14493
|
continue;
|
|
14464
14494
|
}
|
|
14465
14495
|
const op = operation;
|
|
@@ -14479,22 +14509,35 @@ var OpenAPISpecLoader = class {
|
|
|
14479
14509
|
if (op.parameters) {
|
|
14480
14510
|
for (const param of op.parameters) {
|
|
14481
14511
|
let paramObj;
|
|
14482
|
-
if (
|
|
14483
|
-
|
|
14484
|
-
|
|
14485
|
-
|
|
14486
|
-
|
|
14487
|
-
|
|
14488
|
-
if (!resolvedParam || !("name" in resolvedParam)) continue;
|
|
14512
|
+
if ("$ref" in param && typeof param.$ref === "string") {
|
|
14513
|
+
const refMatch = param.$ref.match(/^#\/components\/parameters\/(.+)$/);
|
|
14514
|
+
if (refMatch && spec.components?.parameters) {
|
|
14515
|
+
const paramNameFromRef = refMatch[1];
|
|
14516
|
+
const resolvedParam = spec.components.parameters[paramNameFromRef];
|
|
14517
|
+
if (resolvedParam && "name" in resolvedParam && "in" in resolvedParam) {
|
|
14489
14518
|
paramObj = resolvedParam;
|
|
14490
14519
|
} else {
|
|
14520
|
+
console.warn(
|
|
14521
|
+
`Could not resolve parameter reference or invalid structure: ${param.$ref}`
|
|
14522
|
+
);
|
|
14491
14523
|
continue;
|
|
14492
14524
|
}
|
|
14493
14525
|
} else {
|
|
14526
|
+
console.warn(`Could not parse parameter reference: ${param.$ref}`);
|
|
14494
14527
|
continue;
|
|
14495
14528
|
}
|
|
14496
|
-
} else {
|
|
14529
|
+
} else if ("name" in param && "in" in param) {
|
|
14497
14530
|
paramObj = param;
|
|
14531
|
+
} else {
|
|
14532
|
+
console.warn(
|
|
14533
|
+
"Skipping parameter due to missing 'name' or 'in' properties and not being a valid $ref:",
|
|
14534
|
+
param
|
|
14535
|
+
);
|
|
14536
|
+
continue;
|
|
14537
|
+
}
|
|
14538
|
+
if (!paramObj) {
|
|
14539
|
+
console.warn("Failed to process a parameter (paramObj is undefined):", param);
|
|
14540
|
+
continue;
|
|
14498
14541
|
}
|
|
14499
14542
|
if (paramObj.schema) {
|
|
14500
14543
|
const paramSchema = this.inlineSchema(
|
|
@@ -14503,16 +14546,20 @@ var OpenAPISpecLoader = class {
|
|
|
14503
14546
|
/* @__PURE__ */ new Set()
|
|
14504
14547
|
);
|
|
14505
14548
|
const paramDef = {
|
|
14506
|
-
description: paramObj.description || `${paramObj.name} parameter
|
|
14549
|
+
description: paramObj.description || `${paramObj.name} parameter`,
|
|
14550
|
+
"x-parameter-location": paramObj.in
|
|
14551
|
+
// Store parameter location (path, query, etc.)
|
|
14507
14552
|
};
|
|
14508
|
-
|
|
14509
|
-
|
|
14510
|
-
|
|
14511
|
-
paramDef.type = "string";
|
|
14553
|
+
const paramType = this.determineParameterType(paramSchema, paramObj.name);
|
|
14554
|
+
if (paramType !== void 0) {
|
|
14555
|
+
paramDef.type = paramType;
|
|
14512
14556
|
}
|
|
14513
|
-
|
|
14514
|
-
|
|
14515
|
-
|
|
14557
|
+
if (typeof paramSchema === "object" && paramSchema !== null) {
|
|
14558
|
+
for (const [key, value] of Object.entries(paramSchema)) {
|
|
14559
|
+
if (key === "description" && paramDef.description) continue;
|
|
14560
|
+
if (key === "type" && paramDef.type) continue;
|
|
14561
|
+
paramDef[key] = value;
|
|
14562
|
+
}
|
|
14516
14563
|
}
|
|
14517
14564
|
tool.inputSchema.properties[paramObj.name] = paramDef;
|
|
14518
14565
|
if (paramObj.required === true) {
|
|
@@ -14794,6 +14841,13 @@ var ToolsManager = class {
|
|
|
14794
14841
|
getAllTools() {
|
|
14795
14842
|
return Array.from(this.tools.values());
|
|
14796
14843
|
}
|
|
14844
|
+
/**
|
|
14845
|
+
* Get all available tools with their IDs
|
|
14846
|
+
* Returns array of [toolId, tool] pairs
|
|
14847
|
+
*/
|
|
14848
|
+
getToolsWithIds() {
|
|
14849
|
+
return Array.from(this.tools.entries());
|
|
14850
|
+
}
|
|
14797
14851
|
/**
|
|
14798
14852
|
* Find a tool by ID or name
|
|
14799
14853
|
*/
|
|
@@ -18145,6 +18199,24 @@ var ApiClient = class {
|
|
|
18145
18199
|
});
|
|
18146
18200
|
}
|
|
18147
18201
|
axiosInstance;
|
|
18202
|
+
toolsMap = /* @__PURE__ */ new Map();
|
|
18203
|
+
/**
|
|
18204
|
+
* Set the available tools for the client
|
|
18205
|
+
*
|
|
18206
|
+
* @param tools - Map of tool ID to tool definition
|
|
18207
|
+
*/
|
|
18208
|
+
setTools(tools) {
|
|
18209
|
+
this.toolsMap = tools;
|
|
18210
|
+
}
|
|
18211
|
+
/**
|
|
18212
|
+
* Get a tool definition by ID
|
|
18213
|
+
*
|
|
18214
|
+
* @param toolId - The tool ID
|
|
18215
|
+
* @returns The tool definition if found
|
|
18216
|
+
*/
|
|
18217
|
+
getToolDefinition(toolId) {
|
|
18218
|
+
return this.toolsMap.get(toolId);
|
|
18219
|
+
}
|
|
18148
18220
|
/**
|
|
18149
18221
|
* Execute an API call based on the tool ID and parameters
|
|
18150
18222
|
*
|
|
@@ -18155,15 +18227,57 @@ var ApiClient = class {
|
|
|
18155
18227
|
async executeApiCall(toolId, params) {
|
|
18156
18228
|
try {
|
|
18157
18229
|
const { method, path } = this.parseToolId(toolId);
|
|
18230
|
+
const toolDef = this.getToolDefinition(toolId);
|
|
18231
|
+
const paramsCopy = { ...params };
|
|
18232
|
+
let resolvedPath = path;
|
|
18233
|
+
const escapeRegExp = (str2) => {
|
|
18234
|
+
return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
18235
|
+
};
|
|
18236
|
+
if (toolDef?.inputSchema?.properties) {
|
|
18237
|
+
for (const [key, value] of Object.entries(paramsCopy)) {
|
|
18238
|
+
const paramDef = toolDef.inputSchema.properties[key];
|
|
18239
|
+
const paramDef_any = paramDef;
|
|
18240
|
+
const paramLocation = paramDef_any?.["x-parameter-location"];
|
|
18241
|
+
if (paramLocation === "path") {
|
|
18242
|
+
const escapedKey = escapeRegExp(key);
|
|
18243
|
+
const paramRegex = new RegExp(`\\{${escapedKey}\\}|:${escapedKey}(?:\\/|$)`, "g");
|
|
18244
|
+
if (paramRegex.test(resolvedPath)) {
|
|
18245
|
+
resolvedPath = resolvedPath.replace(
|
|
18246
|
+
paramRegex,
|
|
18247
|
+
(match) => encodeURIComponent(value) + (match.endsWith("/") ? "/" : "")
|
|
18248
|
+
);
|
|
18249
|
+
} else {
|
|
18250
|
+
resolvedPath = resolvedPath.replace(`/${key}`, `/${encodeURIComponent(value)}`);
|
|
18251
|
+
}
|
|
18252
|
+
delete paramsCopy[key];
|
|
18253
|
+
}
|
|
18254
|
+
}
|
|
18255
|
+
} else {
|
|
18256
|
+
for (const key of Object.keys(paramsCopy)) {
|
|
18257
|
+
const value = paramsCopy[key];
|
|
18258
|
+
const escapedKey = escapeRegExp(key);
|
|
18259
|
+
const paramRegex = new RegExp(`\\{${escapedKey}\\}|:${escapedKey}(?:\\/|$)`, "g");
|
|
18260
|
+
if (paramRegex.test(resolvedPath)) {
|
|
18261
|
+
resolvedPath = resolvedPath.replace(
|
|
18262
|
+
paramRegex,
|
|
18263
|
+
(match) => encodeURIComponent(value) + (match.endsWith("/") ? "/" : "")
|
|
18264
|
+
);
|
|
18265
|
+
delete paramsCopy[key];
|
|
18266
|
+
} else if (resolvedPath.includes(`/${key}`)) {
|
|
18267
|
+
resolvedPath = resolvedPath.replace(`/${key}`, `/${encodeURIComponent(value)}`);
|
|
18268
|
+
delete paramsCopy[key];
|
|
18269
|
+
}
|
|
18270
|
+
}
|
|
18271
|
+
}
|
|
18158
18272
|
const config = {
|
|
18159
18273
|
method: method.toLowerCase(),
|
|
18160
|
-
url:
|
|
18274
|
+
url: resolvedPath,
|
|
18161
18275
|
headers: this.headers
|
|
18162
18276
|
};
|
|
18163
18277
|
if (["get", "delete", "head", "options"].includes(method.toLowerCase())) {
|
|
18164
|
-
config.params = this.processQueryParams(
|
|
18278
|
+
config.params = this.processQueryParams(paramsCopy);
|
|
18165
18279
|
} else {
|
|
18166
|
-
config.data =
|
|
18280
|
+
config.data = paramsCopy;
|
|
18167
18281
|
}
|
|
18168
18282
|
const response = await this.axiosInstance(config);
|
|
18169
18283
|
return response.data;
|
|
@@ -18286,6 +18400,11 @@ var OpenAPIServer = class {
|
|
|
18286
18400
|
*/
|
|
18287
18401
|
async start(transport) {
|
|
18288
18402
|
await this.toolsManager.initialize();
|
|
18403
|
+
const toolsMap = /* @__PURE__ */ new Map();
|
|
18404
|
+
for (const [toolId, tool] of this.toolsManager.getToolsWithIds()) {
|
|
18405
|
+
toolsMap.set(toolId, tool);
|
|
18406
|
+
}
|
|
18407
|
+
this.apiClient.setTools(toolsMap);
|
|
18289
18408
|
await this.server.connect(transport);
|
|
18290
18409
|
}
|
|
18291
18410
|
};
|