@frontmcp/adapters 0.1.2
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 +3 -0
- package/package.json +21 -0
- package/src/openapi/index.d.ts +2 -0
- package/src/openapi/index.js +8 -0
- package/src/openapi/index.js.map +1 -0
- package/src/openapi/openapi.adapter.d.ts +16 -0
- package/src/openapi/openapi.adapter.js +91 -0
- package/src/openapi/openapi.adapter.js.map +1 -0
- package/src/openapi/openapi.types.d.ts +18 -0
- package/src/openapi/openapi.types.js +3 -0
- package/src/openapi/openapi.types.js.map +1 -0
package/README.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@frontmcp/adapters",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"type": "commonjs",
|
|
5
|
+
"main": "./src/index.js",
|
|
6
|
+
"types": "./src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./package.json": "./package.json",
|
|
9
|
+
"./openapi": {
|
|
10
|
+
"development": "./src/openapi/index.ts",
|
|
11
|
+
"types": "./dist/src/openapi/index.d.ts",
|
|
12
|
+
"import": "./dist/src/openapi/index.js",
|
|
13
|
+
"default": "./dist/src/openapi/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"tslib": "^2.3.0",
|
|
18
|
+
"openapi-mcp-generator": "^3.2.0",
|
|
19
|
+
"json-schema-to-zod": "^2.6.1"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
var openapi_adapter_1 = require("./openapi.adapter");
|
|
6
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return tslib_1.__importDefault(openapi_adapter_1).default; } });
|
|
7
|
+
tslib_1.__exportStar(require("./openapi.types"), exports);
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/openapi/index.ts"],"names":[],"mappings":";;;;AAAA,qDAA4C;AAAnC,mIAAA,OAAO,OAAA;AAChB,0DAAgC","sourcesContent":["export { default } from './openapi.adapter';\nexport * from './openapi.types';\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DynamicAdapter, FrontMcpAdapterResponse } from '@frontmcp/sdk';
|
|
2
|
+
import { OpenApiAdapterOptions } from './openapi.types';
|
|
3
|
+
export default class OpenapiAdapter extends DynamicAdapter<OpenApiAdapterOptions> {
|
|
4
|
+
options: OpenApiAdapterOptions;
|
|
5
|
+
constructor(options: OpenApiAdapterOptions);
|
|
6
|
+
fetch(): Promise<FrontMcpAdapterResponse>;
|
|
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
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const sdk_1 = require("@frontmcp/sdk");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const openapi_mcp_generator_1 = require("openapi-mcp-generator");
|
|
7
|
+
const zod_from_json_schema_1 = require("zod-from-json-schema");
|
|
8
|
+
let OpenapiAdapter = class OpenapiAdapter extends sdk_1.DynamicAdapter {
|
|
9
|
+
constructor(options) {
|
|
10
|
+
super();
|
|
11
|
+
this.options = options;
|
|
12
|
+
}
|
|
13
|
+
async fetch() {
|
|
14
|
+
const openapiLink = this.options.url;
|
|
15
|
+
const openApiTools = await withSilencedConsole((0, openapi_mcp_generator_1.getToolsFromOpenApi)(openapiLink, {
|
|
16
|
+
dereference: false,
|
|
17
|
+
}));
|
|
18
|
+
return {
|
|
19
|
+
tools: this.parseTools(openApiTools),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
parseTools(openApiTools) {
|
|
23
|
+
return openApiTools.map(oTool => {
|
|
24
|
+
const inputSchema = this.getZodSchemaFromJsonSchema(oTool.inputSchema, oTool.name);
|
|
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
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
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
|
+
};
|
|
67
|
+
OpenapiAdapter = tslib_1.__decorate([
|
|
68
|
+
(0, sdk_1.Adapter)({
|
|
69
|
+
name: 'openapi',
|
|
70
|
+
description: 'OpenAPI adapter that plugin for expense-mcp',
|
|
71
|
+
}),
|
|
72
|
+
tslib_1.__metadata("design:paramtypes", [Object])
|
|
73
|
+
], OpenapiAdapter);
|
|
74
|
+
exports.default = OpenapiAdapter;
|
|
75
|
+
async function withSilencedConsole(fn) {
|
|
76
|
+
const methods = ['log', 'info', 'debug', 'warn', 'error', 'table', 'group', 'groupCollapsed', 'groupEnd', 'dir'];
|
|
77
|
+
const originals = {};
|
|
78
|
+
try {
|
|
79
|
+
for (const m of methods) {
|
|
80
|
+
originals[m] = console[m];
|
|
81
|
+
console[m] = () => {
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return await fn;
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
for (const m of Object.keys(originals))
|
|
88
|
+
console[m] = originals[m];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=openapi.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.adapter.js","sourceRoot":"","sources":["../../../src/openapi/openapi.adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Adapter,\n DynamicAdapter,\n FrontMcpAdapterResponse,\n tool,\n} from '@frontmcp/sdk';\nimport {OpenApiAdapterOptions} from './openapi.types';\nimport {z} from 'zod';\nimport {getToolsFromOpenApi, McpToolDefinition} from 'openapi-mcp-generator';\nimport {convertJsonSchemaToZod} from 'zod-from-json-schema';\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 openApiTools = await withSilencedConsole(getToolsFromOpenApi(openapiLink, {\n dereference: false,\n }));\n\n return {\n tools: this.parseTools(openApiTools),\n };\n }\n\n private parseTools(openApiTools: McpToolDefinition[]) {\n return openApiTools.map(oTool => {\n const inputSchema = this.getZodSchemaFromJsonSchema(oTool.inputSchema, oTool.name);\n // const outputSchema = this.getZodSchemaFromJsonSchema(oTool.outputSchema, oTool.name);\n\n return tool({\n id: oTool.name,\n name: oTool.name,\n description: oTool.description,\n inputSchema: inputSchema.shape,\n rawInputSchema: oTool.inputSchema as any,\n // outputSchema: outputSchema.shape\n })((input, ctx) => {\n return {\n data: {\n id: '1',\n name: 'test',\n },\n };\n });\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 */\n private 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}\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,18 @@
|
|
|
1
|
+
import { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js";
|
|
2
|
+
export interface OpenApiAdapterOptions {
|
|
3
|
+
name: string;
|
|
4
|
+
url: string;
|
|
5
|
+
additionalHeaders?: Record<string, string>;
|
|
6
|
+
headersMapper?: (authInfo: AuthInfo, headers: Record<string, string>) => Record<string, string>;
|
|
7
|
+
bodyMapper?: (authInfo: AuthInfo, body: any) => any;
|
|
8
|
+
/**
|
|
9
|
+
* This can be used to map request information to specific
|
|
10
|
+
* input schema values as required by the API.
|
|
11
|
+
* For example, mapping tenantId from authenticated session payload to
|
|
12
|
+
* a specific proprty in the input schema, this key will be hidden to mcp clients
|
|
13
|
+
* and filled by the adapter before sending the request to the API.
|
|
14
|
+
* @param authInfo
|
|
15
|
+
* @param request
|
|
16
|
+
*/
|
|
17
|
+
inputSchemaMapper?: (inputSchema: any) => any;
|
|
18
|
+
}
|
|
@@ -0,0 +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: Record<string, string>) => Record<string, string>;\n bodyMapper?: (authInfo: AuthInfo, body: any) => any;\n\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"]}
|