@frontmcp/adapters 0.1.3 → 0.2.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/package.json +6 -5
- package/src/index.d.ts +2 -0
- package/src/index.js +8 -0
- package/src/index.js.map +1 -0
- package/src/openapi/openapi.adapter.d.ts +0 -8
- package/src/openapi/openapi.adapter.js +10 -45
- package/src/openapi/openapi.adapter.js.map +1 -1
- package/src/openapi/openapi.tool.d.ts +3 -0
- package/src/openapi/openapi.tool.js +106 -0
- package/src/openapi/openapi.tool.js.map +1 -0
- package/src/openapi/openapi.types.d.ts +3 -2
- package/src/openapi/openapi.types.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/adapters",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
"./package.json": "./package.json",
|
|
9
|
-
"
|
|
10
|
-
"types": "./src/
|
|
11
|
-
"import": "./src/
|
|
12
|
-
"default": "./src/
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"import": "./src/index.js",
|
|
12
|
+
"default": "./src/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"tslib": "^2.3.0",
|
|
17
|
+
"@frontmcp/sdk": "^0.2.1",
|
|
17
18
|
"openapi-mcp-generator": "^3.2.0",
|
|
18
19
|
"json-schema-to-zod": "^2.6.1"
|
|
19
20
|
}
|
package/src/index.d.ts
ADDED
package/src/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpenapiAdapter = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
var openapi_1 = require("./openapi");
|
|
6
|
+
Object.defineProperty(exports, "OpenapiAdapter", { enumerable: true, get: function () { return tslib_1.__importDefault(openapi_1).default; } });
|
|
7
|
+
tslib_1.__exportStar(require("./openapi"), exports);
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;AAAA,qCAAmD;AAA3C,kIAAA,OAAO,OAAkB;AACjC,oDAAyB","sourcesContent":["export {default as OpenapiAdapter} from './openapi'\nexport * from './openapi'"]}
|
|
@@ -5,12 +5,4 @@ export default class OpenapiAdapter extends DynamicAdapter<OpenApiAdapterOptions
|
|
|
5
5
|
constructor(options: OpenApiAdapterOptions);
|
|
6
6
|
fetch(): Promise<FrontMcpAdapterResponse>;
|
|
7
7
|
private parseTools;
|
|
8
|
-
/**
|
|
9
|
-
* Converts a JSON Schema to a Zod schema for runtime validation
|
|
10
|
-
*
|
|
11
|
-
* @param jsonSchema JSON Schema
|
|
12
|
-
* @param toolName Tool name for error reporting
|
|
13
|
-
* @returns Zod schema
|
|
14
|
-
*/
|
|
15
|
-
private getZodSchemaFromJsonSchema;
|
|
16
8
|
}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const sdk_1 = require("@frontmcp/sdk");
|
|
5
|
-
const zod_1 = require("zod");
|
|
6
5
|
const openapi_mcp_generator_1 = require("openapi-mcp-generator");
|
|
7
|
-
const
|
|
6
|
+
const openapi_tool_1 = require("./openapi.tool");
|
|
8
7
|
let OpenapiAdapter = class OpenapiAdapter extends sdk_1.DynamicAdapter {
|
|
9
8
|
constructor(options) {
|
|
10
9
|
super();
|
|
@@ -12,57 +11,23 @@ let OpenapiAdapter = class OpenapiAdapter extends sdk_1.DynamicAdapter {
|
|
|
12
11
|
}
|
|
13
12
|
async fetch() {
|
|
14
13
|
const openapiLink = this.options.url;
|
|
15
|
-
const
|
|
14
|
+
const { baseUrl, filterFn, defaultInclude, excludeOperationIds } = this.options;
|
|
15
|
+
const openApiTools = await (0, openapi_mcp_generator_1.getToolsFromOpenApi)(openapiLink, {
|
|
16
|
+
baseUrl,
|
|
17
|
+
filterFn,
|
|
18
|
+
defaultInclude,
|
|
19
|
+
excludeOperationIds,
|
|
16
20
|
dereference: false,
|
|
17
|
-
})
|
|
21
|
+
});
|
|
18
22
|
return {
|
|
19
23
|
tools: this.parseTools(openApiTools),
|
|
20
24
|
};
|
|
21
25
|
}
|
|
22
26
|
parseTools(openApiTools) {
|
|
23
|
-
return openApiTools.map(
|
|
24
|
-
|
|
25
|
-
// const outputSchema = this.getZodSchemaFromJsonSchema(oTool.outputSchema, oTool.name);
|
|
26
|
-
return (0, sdk_1.tool)({
|
|
27
|
-
id: oTool.name,
|
|
28
|
-
name: oTool.name,
|
|
29
|
-
description: oTool.description,
|
|
30
|
-
inputSchema: inputSchema.shape,
|
|
31
|
-
rawInputSchema: oTool.inputSchema,
|
|
32
|
-
// outputSchema: outputSchema.shape
|
|
33
|
-
})((input, ctx) => {
|
|
34
|
-
return {
|
|
35
|
-
data: {
|
|
36
|
-
id: '1',
|
|
37
|
-
name: 'test',
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
});
|
|
27
|
+
return openApiTools.map(tool => {
|
|
28
|
+
return (0, openapi_tool_1.createOpenApiTool)(tool, this.options);
|
|
41
29
|
});
|
|
42
30
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Converts a JSON Schema to a Zod schema for runtime validation
|
|
45
|
-
*
|
|
46
|
-
* @param jsonSchema JSON Schema
|
|
47
|
-
* @param toolName Tool name for error reporting
|
|
48
|
-
* @returns Zod schema
|
|
49
|
-
*/
|
|
50
|
-
getZodSchemaFromJsonSchema(jsonSchema, toolName) {
|
|
51
|
-
if (typeof jsonSchema !== 'object' || jsonSchema === null) {
|
|
52
|
-
return zod_1.z.object({}).passthrough();
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
const zodSchema = (0, zod_from_json_schema_1.convertJsonSchemaToZod)(jsonSchema);
|
|
56
|
-
if (typeof zodSchema?.parse !== 'function') {
|
|
57
|
-
throw new Error('Eval did not produce a valid Zod schema.');
|
|
58
|
-
}
|
|
59
|
-
return zodSchema;
|
|
60
|
-
}
|
|
61
|
-
catch (err) {
|
|
62
|
-
console.error(`Failed to generate/evaluate Zod schema for '${toolName}':`, err);
|
|
63
|
-
return zod_1.z.object({}).passthrough();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
31
|
};
|
|
67
32
|
OpenapiAdapter = tslib_1.__decorate([
|
|
68
33
|
(0, sdk_1.Adapter)({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.adapter.js","sourceRoot":"","sources":["../../../src/openapi/openapi.adapter.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"openapi.adapter.js","sourceRoot":"","sources":["../../../src/openapi/openapi.adapter.ts"],"names":[],"mappings":";;;AAAA,uCAIuB;AAEvB,iEAA6E;AAC7E,iDAAiD;AAOlC,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,oBAAqC;IAG/E,YAAY,OAA8B;QACxC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAGD,KAAK,CAAC,KAAK;QACT,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAA;QACpC,MAAM,EAAC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,mBAAmB,EAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9E,MAAM,YAAY,GAAG,MAAM,IAAA,2CAAmB,EAAC,WAAW,EAAE;YAC1D,OAAO;YACP,QAAQ;YACR,cAAc;YACd,mBAAmB;YACnB,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;QAEH,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;SACrC,CAAC;IACJ,CAAC;IAEO,UAAU,CAAC,YAAiC;QAClD,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC7B,OAAO,IAAA,gCAAiB,EAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;CAGF,CAAA;AAhCoB,cAAc;IAJlC,IAAA,aAAO,EAAC;QACP,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,8CAA8C;KAC5D,CAAC;;GACmB,cAAc,CAgClC;kBAhCoB,cAAc;AAkCnC,KAAK,UAAU,mBAAmB,CAAC,EAAgB;IACjD,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;IACjH,MAAM,SAAS,GAAG,EAAE,CAAC;IACrB,IAAI,CAAC;QACH,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAC1B,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE;YAClB,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,EAAE,CAAC;IAClB,CAAC;YAAS,CAAC;QACT,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;AACH,CAAC","sourcesContent":["import {\n Adapter,\n DynamicAdapter,\n FrontMcpAdapterResponse,\n} from '@frontmcp/sdk';\nimport {OpenApiAdapterOptions} from './openapi.types';\nimport {getToolsFromOpenApi, McpToolDefinition} from 'openapi-mcp-generator';\nimport {createOpenApiTool} from \"./openapi.tool\";\n\n\n@Adapter({\n name: 'openapi',\n description: 'OpenAPI adapter that plugin for expense-mcp',\n})\nexport default class OpenapiAdapter extends DynamicAdapter<OpenApiAdapterOptions> {\n options: OpenApiAdapterOptions;\n\n constructor(options: OpenApiAdapterOptions) {\n super();\n this.options = options;\n }\n\n\n async fetch(): Promise<FrontMcpAdapterResponse> {\n const openapiLink = this.options.url\n const {baseUrl, filterFn, defaultInclude, excludeOperationIds} = this.options;\n const openApiTools = await getToolsFromOpenApi(openapiLink, {\n baseUrl,\n filterFn,\n defaultInclude,\n excludeOperationIds,\n dereference: false,\n });\n\n return {\n tools: this.parseTools(openApiTools),\n };\n }\n\n private parseTools(openApiTools: McpToolDefinition[]) {\n return openApiTools.map(tool => {\n return createOpenApiTool(tool, this.options);\n });\n }\n\n\n}\n\nasync function withSilencedConsole(fn: Promise<any>) {\n const methods = ['log', 'info', 'debug', 'warn', 'error', 'table', 'group', 'groupCollapsed', 'groupEnd', 'dir'];\n const originals = {};\n try {\n for (const m of methods) {\n originals[m] = console[m];\n console[m] = () => {\n };\n }\n return await fn;\n } finally {\n for (const m of Object.keys(originals)) console[m] = originals[m];\n }\n}\n"]}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createOpenApiTool = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const sdk_1 = require("@frontmcp/sdk");
|
|
6
|
+
const zod_from_json_schema_1 = require("zod-from-json-schema");
|
|
7
|
+
const createOpenApiTool = (oTool, options) => {
|
|
8
|
+
const inputSchema = getZodSchemaFromJsonSchema(oTool.inputSchema, oTool.name);
|
|
9
|
+
const { additionalHeaders, headersMapper } = options;
|
|
10
|
+
return (0, sdk_1.tool)({
|
|
11
|
+
id: oTool.name,
|
|
12
|
+
name: oTool.name,
|
|
13
|
+
description: oTool.description,
|
|
14
|
+
inputSchema: inputSchema,
|
|
15
|
+
rawInputSchema: oTool.inputSchema,
|
|
16
|
+
// outputSchema: outputSchema.shape
|
|
17
|
+
})(async (input, ctx) => {
|
|
18
|
+
let { urlPath, headers, queryParams } = prepareUrl(oTool, input);
|
|
19
|
+
let requestBodyData = undefined;
|
|
20
|
+
if (additionalHeaders) {
|
|
21
|
+
for (const [key, value] of Object.entries(additionalHeaders)) {
|
|
22
|
+
headers.append(key, value);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (typeof headersMapper === 'function') {
|
|
26
|
+
headers = headersMapper(ctx.authInfo, headers);
|
|
27
|
+
}
|
|
28
|
+
if (!['HEAD', 'GET', 'OPTIONS'].includes(oTool.method)) {
|
|
29
|
+
// prepare body
|
|
30
|
+
if (oTool.requestBodyContentType && typeof input['requestBody'] !== 'undefined') {
|
|
31
|
+
requestBodyData = input['requestBody'];
|
|
32
|
+
headers.set('content-type', oTool.requestBodyContentType);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const query = queryParams.toString();
|
|
36
|
+
const url = `${options.baseUrl}${urlPath}${query ? `?${query}` : ''}`;
|
|
37
|
+
const res = await fetch(url, {
|
|
38
|
+
method: oTool.method,
|
|
39
|
+
headers,
|
|
40
|
+
body: requestBodyData,
|
|
41
|
+
});
|
|
42
|
+
const data = await res.text();
|
|
43
|
+
let result = { data };
|
|
44
|
+
if (res.headers.get('content-type')?.includes('application/json')) {
|
|
45
|
+
try {
|
|
46
|
+
result.data = JSON.parse(data);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
console.error("failed to parse api response"); // migrate to logger
|
|
50
|
+
result.data = data;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
exports.createOpenApiTool = createOpenApiTool;
|
|
57
|
+
/**
|
|
58
|
+
* Converts a JSON Schema to a Zod schema for runtime validation
|
|
59
|
+
*
|
|
60
|
+
* @param jsonSchema JSON Schema
|
|
61
|
+
* @param toolName Tool name for error reporting
|
|
62
|
+
* @returns Zod schema
|
|
63
|
+
*/
|
|
64
|
+
function getZodSchemaFromJsonSchema(jsonSchema, toolName) {
|
|
65
|
+
if (typeof jsonSchema !== 'object' || jsonSchema === null) {
|
|
66
|
+
return zod_1.z.object({}).passthrough();
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const zodSchema = (0, zod_from_json_schema_1.convertJsonSchemaToZod)(jsonSchema);
|
|
70
|
+
if (typeof zodSchema?.parse !== 'function') {
|
|
71
|
+
throw new Error('Eval did not produce a valid Zod schema.');
|
|
72
|
+
}
|
|
73
|
+
return zodSchema;
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
console.error(`Failed to generate/evaluate Zod schema for '${toolName}':`, err);
|
|
77
|
+
return zod_1.z.object({}).passthrough();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const prepareUrl = (definition, validatedArgs) => {
|
|
81
|
+
// Prepare URL, query parameters, headers, and request body
|
|
82
|
+
let urlPath = definition.pathTemplate;
|
|
83
|
+
const queryParams = new URLSearchParams({ "v": '1' });
|
|
84
|
+
const headers = new Headers({ 'accept': 'application/json' });
|
|
85
|
+
// Apply parameters to the URL path, query, or headers
|
|
86
|
+
definition.executionParameters.forEach((param) => {
|
|
87
|
+
const value = validatedArgs[param.name];
|
|
88
|
+
if (typeof value !== 'undefined' && value !== null) {
|
|
89
|
+
if (param.in === 'path') {
|
|
90
|
+
urlPath = urlPath.replace(`{${param.name}}`, encodeURIComponent(String(value)));
|
|
91
|
+
}
|
|
92
|
+
else if (param.in === 'query') {
|
|
93
|
+
queryParams.set(param.name, value);
|
|
94
|
+
}
|
|
95
|
+
else if (param.in === 'header') {
|
|
96
|
+
headers.append(param.name.toLowerCase(), String(value));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
// Ensure all path parameters are resolved
|
|
101
|
+
if (urlPath.includes('{')) {
|
|
102
|
+
throw new Error(`Failed to resolve path parameters: ${urlPath}`);
|
|
103
|
+
}
|
|
104
|
+
return { urlPath, headers, queryParams };
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=openapi.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.tool.js","sourceRoot":"","sources":["../../../src/openapi/openapi.tool.ts"],"names":[],"mappings":"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","sourcesContent":["import {z} from \"zod\";\nimport {McpToolDefinition} from \"openapi-mcp-generator\";\nimport {tool} from \"@frontmcp/sdk\";\nimport {convertJsonSchemaToZod} from \"zod-from-json-schema\";\nimport {OpenApiAdapterOptions} from \"./openapi.types\";\n\n\nexport const createOpenApiTool = (oTool: McpToolDefinition, options: OpenApiAdapterOptions) => {\n const inputSchema = getZodSchemaFromJsonSchema(oTool.inputSchema, oTool.name);\n\n const {additionalHeaders, headersMapper} = options;\n return tool({\n id: oTool.name,\n name: oTool.name,\n description: oTool.description,\n inputSchema: inputSchema as any,\n rawInputSchema: oTool.inputSchema as any,\n // outputSchema: outputSchema.shape\n })(async (input, ctx) => {\n\n let {urlPath, headers, queryParams} = prepareUrl(oTool, input);\n let requestBodyData: any = undefined;\n\n if (additionalHeaders) {\n for (const [key, value] of Object.entries(additionalHeaders)) {\n headers.append(key, value);\n }\n }\n if (typeof headersMapper === 'function') {\n headers = headersMapper(ctx.authInfo, headers)\n }\n\n if (!['HEAD', 'GET', 'OPTIONS'].includes(oTool.method)) {\n // prepare body\n if (oTool.requestBodyContentType && typeof input['requestBody'] !== 'undefined') {\n requestBodyData = input['requestBody'];\n headers.set('content-type', oTool.requestBodyContentType);\n }\n }\n\n const query = queryParams.toString()\n const url = `${options.baseUrl}${urlPath}${query ? `?${query}` : ''}`;\n const res = await fetch(url, {\n method: oTool.method,\n headers,\n body: requestBodyData,\n });\n const data = await res.text()\n let result = {data}\n if (res.headers.get('content-type')?.includes('application/json')) {\n try {\n result.data = JSON.parse(data)\n } catch (e) {\n console.error(\"failed to parse api response\")// migrate to logger\n result.data = data\n }\n }\n return result\n });\n};\n\n\n/**\n * Converts a JSON Schema to a Zod schema for runtime validation\n *\n * @param jsonSchema JSON Schema\n * @param toolName Tool name for error reporting\n * @returns Zod schema\n */\nfunction getZodSchemaFromJsonSchema(jsonSchema: any, toolName: string): z.ZodObject<any> {\n if (typeof jsonSchema !== 'object' || jsonSchema === null) {\n return z.object({}).passthrough();\n }\n try {\n const zodSchema = convertJsonSchemaToZod(jsonSchema);\n if (typeof zodSchema?.parse !== 'function') {\n throw new Error('Eval did not produce a valid Zod schema.');\n }\n return zodSchema as any;\n } catch (err: any) {\n console.error(`Failed to generate/evaluate Zod schema for '${toolName}':`, err);\n return z.object({}).passthrough();\n }\n}\n\nconst prepareUrl = (definition: McpToolDefinition, validatedArgs: any) => {\n // Prepare URL, query parameters, headers, and request body\n let urlPath = definition.pathTemplate;\n const queryParams = new URLSearchParams({\"v\": '1'})\n const headers = new Headers({'accept': 'application/json'})\n\n\n // Apply parameters to the URL path, query, or headers\n definition.executionParameters.forEach((param) => {\n const value = validatedArgs[param.name];\n if (typeof value !== 'undefined' && value !== null) {\n if (param.in === 'path') {\n urlPath = urlPath.replace(`{${param.name}}`, encodeURIComponent(String(value)));\n } else if (param.in === 'query') {\n queryParams.set(param.name, value)\n } else if (param.in === 'header') {\n headers.append(param.name.toLowerCase(), String(value));\n }\n }\n });\n\n // Ensure all path parameters are resolved\n if (urlPath.includes('{')) {\n throw new Error(`Failed to resolve path parameters: ${urlPath}`);\n }\n\n return {urlPath, headers, queryParams};\n}"]}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js";
|
|
2
|
-
|
|
2
|
+
import { GetToolsOptions } from "openapi-mcp-generator/dist/api";
|
|
3
|
+
export interface OpenApiAdapterOptions extends Omit<GetToolsOptions, 'dereference'> {
|
|
3
4
|
name: string;
|
|
4
5
|
url: string;
|
|
5
6
|
additionalHeaders?: Record<string, string>;
|
|
6
|
-
headersMapper?: (authInfo: AuthInfo, headers:
|
|
7
|
+
headersMapper?: (authInfo: AuthInfo, headers: Headers) => Headers;
|
|
7
8
|
bodyMapper?: (authInfo: AuthInfo, body: any) => any;
|
|
8
9
|
/**
|
|
9
10
|
* This can be used to map request information to specific
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.types.js","sourceRoot":"","sources":["../../../src/openapi/openapi.types.ts"],"names":[],"mappings":"","sourcesContent":["import {AuthInfo} from \"@modelcontextprotocol/sdk/server/auth/types.js\";\n\nexport interface OpenApiAdapterOptions {\n name: string;\n url: string;\n\n additionalHeaders?: Record<string, string>;\n headersMapper?: (authInfo: AuthInfo, headers:
|
|
1
|
+
{"version":3,"file":"openapi.types.js","sourceRoot":"","sources":["../../../src/openapi/openapi.types.ts"],"names":[],"mappings":"","sourcesContent":["import {AuthInfo} from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport {GetToolsOptions} from \"openapi-mcp-generator/dist/api\";\n\nexport interface OpenApiAdapterOptions extends Omit<GetToolsOptions, 'dereference'> {\n name: string;\n url: string;\n\n additionalHeaders?: Record<string, string>;\n headersMapper?: (authInfo: AuthInfo, headers: Headers) => Headers;\n bodyMapper?: (authInfo: AuthInfo, body: any) => any;\n /**\n * This can be used to map request information to specific\n * input schema values as required by the API.\n * For example, mapping tenantId from authenticated session payload to\n * a specific proprty in the input schema, this key will be hidden to mcp clients\n * and filled by the adapter before sending the request to the API.\n * @param authInfo\n * @param request\n */\n inputSchemaMapper?: (inputSchema: any) => any;\n}\n"]}
|