@nocobase/plugin-mcp-server 2.1.0-alpha.10 → 2.1.0-alpha.11
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/dist/client/index.js +1 -1
- package/dist/externalVersion.js +6 -6
- package/dist/node_modules/light-my-request/package.json +1 -1
- package/dist/node_modules/openapi-types/package.json +1 -1
- package/dist/server/mcp-server.d.ts +2 -0
- package/dist/server/mcp-server.js +5 -4
- package/dist/server/mcp-tools.d.ts +4 -0
- package/dist/server/mcp-tools.js +63 -6
- package/dist/server/plugin.d.ts +4 -1
- package/dist/server/plugin.js +33 -6
- package/package.json +2 -2
package/dist/client/index.js
CHANGED
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("@nocobase/client")):"function"==typeof define&&define.amd?define("@nocobase/plugin-mcp-server",["@nocobase/client"],t):"object"==typeof exports?exports["@nocobase/plugin-mcp-server"]=t(require("@nocobase/client")):e["@nocobase/plugin-mcp-server"]=t(e["@nocobase/client"])}(self,function(e){return function(){"use strict";var t
|
|
10
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("@nocobase/client")):"function"==typeof define&&define.amd?define("@nocobase/plugin-mcp-server",["@nocobase/client"],t):"object"==typeof exports?exports["@nocobase/plugin-mcp-server"]=t(require("@nocobase/client")):e["@nocobase/plugin-mcp-server"]=t(e["@nocobase/client"])}(self,function(e){return function(){"use strict";var t={342:function(t){t.exports=e}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,n),i.exports}n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.r=function(e){"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.g.importScripts&&(o=n.g.location+"");var o,i=n.g.document;if(!o&&i&&(i.currentScript&&"SCRIPT"===i.currentScript.tagName.toUpperCase()&&(o=i.currentScript.src),!o)){var c=i.getElementsByTagName("script");if(c.length)for(var u=c.length-1;u>-1&&(!o||!/^http(s?):/.test(o));)o=c[u--].src}if(!o)throw Error("Automatic publicPath is not supported in this browser");n.p=o.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/");var a={},l=window.__nocobase_public_path__||"";if(!l&&window.location&&window.location.pathname){var p=window.location.pathname||"/",f=p.indexOf("/v2/");l=f>=0?p.slice(0,f+1):"/"}return l&&(l=l.replace(/\/v2\/?$/,"/")),l||(l="/"),"/"!==l.charAt(l.length-1)&&(l+="/"),n.p=l+"static/plugins/@nocobase/plugin-mcp-server/dist/client/",!function(){n.r(a),n.d(a,{default:function(){return p}});var e=n(342),t={};function r(e,t,r,n,o,i,c){try{var u=e[i](c),a=u.value}catch(e){r(e);return}u.done?t(a):Promise.resolve(a).then(n,o)}function o(e,t,r){return(o=l()?Reflect.construct:function(e,t,r){var n=[null];n.push.apply(n,t);var o=new(Function.bind.apply(e,n));return r&&c(o,r.prototype),o}).apply(null,arguments)}function i(e){return(i=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function c(e,t){return(c=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function u(e){var t="function"==typeof Map?new Map:void 0;return(u=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return o(e,arguments,i(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),c(r,e)})(e)}function l(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(l=function(){return!!e})()}var p=function(e){var n;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function o(){var e,t;if(!(this instanceof o))throw TypeError("Cannot call a class as a function");return e=o,t=arguments,e=i(e),function(e,t){var r;if(t&&("object"==((r=t)&&"u">typeof Symbol&&r.constructor===Symbol?"symbol":typeof r)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,l()?Reflect.construct(e,t||[],i(this).constructor):e.apply(this,t))}return o.prototype=Object.create(e&&e.prototype,{constructor:{value:o,writable:!0,configurable:!0}}),e&&c(o,e),n=[{key:"load",value:function(){var e;return(e=function(){return function(e,t){var r,n,o,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},c=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(c,"next",{value:a(0)}),u(c,"throw",{value:a(1)}),u(c,"return",{value:a(2)}),"function"==typeof Symbol&&u(c,Symbol.iterator,{value:function(){return this}}),c;function a(u){return function(a){var l=[u,a];if(r)throw TypeError("Generator is already executing.");for(;c&&(c=0,l[0]&&(i=0)),i;)try{if(r=1,n&&(o=2&l[0]?n.return:l[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,l[1])).done)return o;switch(n=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,n=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){i.label=l[1];break}if(6===l[0]&&i.label<o[1]){i.label=o[1],o=l;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(l);break}o[2]&&i.ops.pop(),i.trys.pop();continue}l=t.call(e,i)}catch(e){l=[6,e],n=0}finally{r=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}(this,function(e){return this.flowEngine.registerModels(t),[2]})},function(){var t=this,n=arguments;return new Promise(function(o,i){var c=e.apply(t,n);function u(e){r(c,o,i,u,a,"next",e)}function a(e){r(c,o,i,u,a,"throw",e)}u(void 0)})}).call(this)}}],function(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}(o.prototype,n),o}(u(e.Plugin))}(),a}()});
|
package/dist/externalVersion.js
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
|
-
"@nocobase/flow-engine": "2.1.0-alpha.
|
|
12
|
-
"@nocobase/client": "2.1.0-alpha.
|
|
13
|
-
"@nocobase/ai": "2.1.0-alpha.
|
|
14
|
-
"@nocobase/utils": "2.1.0-alpha.
|
|
15
|
-
"@nocobase/server": "2.1.0-alpha.
|
|
16
|
-
"@nocobase/plugin-idp-oauth": "2.1.0-alpha.
|
|
11
|
+
"@nocobase/flow-engine": "2.1.0-alpha.11",
|
|
12
|
+
"@nocobase/client": "2.1.0-alpha.11",
|
|
13
|
+
"@nocobase/ai": "2.1.0-alpha.11",
|
|
14
|
+
"@nocobase/utils": "2.1.0-alpha.11",
|
|
15
|
+
"@nocobase/server": "2.1.0-alpha.11",
|
|
16
|
+
"@nocobase/plugin-idp-oauth": "2.1.0-alpha.11"
|
|
17
17
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"light-my-request","version":"6.6.0","description":"Fake HTTP injection library","main":"index.js","type":"commonjs","types":"types/index.d.ts","dependencies":{"cookie":"^1.0.1","process-warning":"^4.0.0","set-cookie-parser":"^2.6.0"},"devDependencies":{"@fastify/ajv-compiler":"^4.0.0","@fastify/pre-commit":"^2.1.0","@types/node":"^22.7.7","c8":"^10.1.2","end-of-stream":"^1.4.4","eslint":"^9.17.0","express":"^4.19.2","form-auto-content":"^3.2.1","form-data":"^4.0.0","formdata-node":"^6.0.3","multer":"^1.4.5-lts.1","neostandard":"^0.12.0","tinybench":"^3.0.0","tsd":"^0.31.0","undici":"^7.0.0"},"scripts":{"benchmark":"node benchmark/benchmark.js","coverage":"npm run unit -- --cov --coverage-report=html","lint":"eslint","lint:fix":"eslint --fix","test":"npm run lint && npm run test:unit && npm run test:typescript","test:typescript":"tsd","test:unit":"c8 --100 node --test"},"repository":{"type":"git","url":"git+https://github.com/fastify/light-my-request.git"},"keywords":["http","inject","fake","request","server"],"author":"Tomas Della Vedova - @delvedor (http://delved.org)","contributors":[{"name":"Matteo Collina","email":"hello@matteocollina.com"},{"name":"Manuel Spigolon","email":"behemoth89@gmail.com"},{"name":"Aras Abbasi","email":"aras.abbasi@gmail.com"},{"name":"Frazer Smith","email":"frazer.dev@icloud.com","url":"https://github.com/fdawgs"}],"license":"BSD-3-Clause","bugs":{"url":"https://github.com/fastify/light-my-request/issues"},"homepage":"https://github.com/fastify/light-my-request#readme","funding":[{"type":"github","url":"https://github.com/sponsors/fastify"},{"type":"opencollective","url":"https://opencollective.com/fastify"}],"_lastModified":"2026-03-
|
|
1
|
+
{"name":"light-my-request","version":"6.6.0","description":"Fake HTTP injection library","main":"index.js","type":"commonjs","types":"types/index.d.ts","dependencies":{"cookie":"^1.0.1","process-warning":"^4.0.0","set-cookie-parser":"^2.6.0"},"devDependencies":{"@fastify/ajv-compiler":"^4.0.0","@fastify/pre-commit":"^2.1.0","@types/node":"^22.7.7","c8":"^10.1.2","end-of-stream":"^1.4.4","eslint":"^9.17.0","express":"^4.19.2","form-auto-content":"^3.2.1","form-data":"^4.0.0","formdata-node":"^6.0.3","multer":"^1.4.5-lts.1","neostandard":"^0.12.0","tinybench":"^3.0.0","tsd":"^0.31.0","undici":"^7.0.0"},"scripts":{"benchmark":"node benchmark/benchmark.js","coverage":"npm run unit -- --cov --coverage-report=html","lint":"eslint","lint:fix":"eslint --fix","test":"npm run lint && npm run test:unit && npm run test:typescript","test:typescript":"tsd","test:unit":"c8 --100 node --test"},"repository":{"type":"git","url":"git+https://github.com/fastify/light-my-request.git"},"keywords":["http","inject","fake","request","server"],"author":"Tomas Della Vedova - @delvedor (http://delved.org)","contributors":[{"name":"Matteo Collina","email":"hello@matteocollina.com"},{"name":"Manuel Spigolon","email":"behemoth89@gmail.com"},{"name":"Aras Abbasi","email":"aras.abbasi@gmail.com"},{"name":"Frazer Smith","email":"frazer.dev@icloud.com","url":"https://github.com/fdawgs"}],"license":"BSD-3-Clause","bugs":{"url":"https://github.com/fastify/light-my-request/issues"},"homepage":"https://github.com/fastify/light-my-request#readme","funding":[{"type":"github","url":"https://github.com/sponsors/fastify"},{"type":"opencollective","url":"https://opencollective.com/fastify"}],"_lastModified":"2026-03-25T08:52:04.372Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"openapi-types","version":"12.1.3","description":"Types for OpenAPI documents.","main":"./dist/index.js","types":"./dist/index.d.ts","scripts":{"prepare":"../../bin/tsc","test-watch":"../../bin/tsc"},"keywords":["openapi","swagger","types","typescript"],"author":"Joseph Spencer","bugs":{"url":"https://github.com/kogosoftwarellc/open-api/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Aopenapi-types"},"repository":"https://github.com/kogosoftwarellc/open-api/tree/master/packages/openapi-types","homepage":"https://github.com/kogosoftwarellc/open-api/tree/master/packages/openapi-types#readme","license":"MIT","gitHead":"09fed6d77536b3d7d1d38a2630a096041da773ee","_lastModified":"2026-03-
|
|
1
|
+
{"name":"openapi-types","version":"12.1.3","description":"Types for OpenAPI documents.","main":"./dist/index.js","types":"./dist/index.d.ts","scripts":{"prepare":"../../bin/tsc","test-watch":"../../bin/tsc"},"keywords":["openapi","swagger","types","typescript"],"author":"Joseph Spencer","bugs":{"url":"https://github.com/kogosoftwarellc/open-api/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Aopenapi-types"},"repository":"https://github.com/kogosoftwarellc/open-api/tree/master/packages/openapi-types","homepage":"https://github.com/kogosoftwarellc/open-api/tree/master/packages/openapi-types#readme","license":"MIT","gitHead":"09fed6d77536b3d7d1d38a2630a096041da773ee","_lastModified":"2026-03-25T08:52:04.464Z"}
|
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import type { McpToolsManager } from '@nocobase/ai';
|
|
10
|
+
import type { McpTool } from '@nocobase/ai';
|
|
10
11
|
export declare class McpServer {
|
|
11
12
|
private readonly options;
|
|
12
13
|
constructor(options: {
|
|
13
14
|
name: string;
|
|
14
15
|
version: string;
|
|
15
16
|
toolsManager: McpToolsManager;
|
|
17
|
+
getTools?: (ctx: any) => Promise<McpTool[]>;
|
|
16
18
|
logger: {
|
|
17
19
|
error: (...args: any[]) => void;
|
|
18
20
|
};
|
|
@@ -97,7 +97,7 @@ class McpServer {
|
|
|
97
97
|
var _a;
|
|
98
98
|
const body = ctx.request.body || {};
|
|
99
99
|
const sdkModules = await getMcpSdkModules();
|
|
100
|
-
const server = this.createServer(sdkModules, (_a = ctx.getBearerToken) == null ? void 0 : _a.call(ctx));
|
|
100
|
+
const server = this.createServer(sdkModules, ctx, (_a = ctx.getBearerToken) == null ? void 0 : _a.call(ctx));
|
|
101
101
|
const transport = new sdkModules.StreamableHTTPServerTransport({
|
|
102
102
|
sessionIdGenerator: void 0
|
|
103
103
|
});
|
|
@@ -112,7 +112,7 @@ class McpServer {
|
|
|
112
112
|
}
|
|
113
113
|
ctx.respond = false;
|
|
114
114
|
}
|
|
115
|
-
createServer(sdkModules, requestToken) {
|
|
115
|
+
createServer(sdkModules, ctx, requestToken) {
|
|
116
116
|
const server = new sdkModules.McpServer(
|
|
117
117
|
{
|
|
118
118
|
name: this.options.name,
|
|
@@ -125,8 +125,9 @@ class McpServer {
|
|
|
125
125
|
}
|
|
126
126
|
);
|
|
127
127
|
server.server.setRequestHandler(sdkModules.ListToolsRequestSchema, async () => {
|
|
128
|
+
const tools = this.options.getTools ? await this.options.getTools(ctx) : this.options.toolsManager.listTools();
|
|
128
129
|
return {
|
|
129
|
-
tools:
|
|
130
|
+
tools: tools.map((tool) => {
|
|
130
131
|
return {
|
|
131
132
|
name: tool.name,
|
|
132
133
|
description: tool.description,
|
|
@@ -142,7 +143,7 @@ class McpServer {
|
|
|
142
143
|
var _a;
|
|
143
144
|
const toolName = request.params.name;
|
|
144
145
|
const args = request.params.arguments || {};
|
|
145
|
-
const tool = this.options.toolsManager.getTool(toolName);
|
|
146
|
+
const tool = this.options.getTools ? (await this.options.getTools(ctx)).find((item) => item.name === toolName) : this.options.toolsManager.getTool(toolName);
|
|
146
147
|
if (!tool) {
|
|
147
148
|
throw new Error(`Tool not found: ${toolName}`);
|
|
148
149
|
}
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import type { McpTool } from '@nocobase/ai';
|
|
10
|
+
export declare const DEFAULT_MCP_PACKAGE_PATTERNS: string[];
|
|
11
|
+
export declare function normalizePackageName(packageName: string): string;
|
|
12
|
+
export declare function normalizePackagePatterns(packageNames?: string[]): string[];
|
|
10
13
|
export declare function collectMcpToolsFromSwagger(options: {
|
|
11
14
|
app: {
|
|
12
15
|
db: any;
|
|
@@ -20,4 +23,5 @@ export declare function collectMcpToolsFromSwagger(options: {
|
|
|
20
23
|
};
|
|
21
24
|
callback: () => any;
|
|
22
25
|
};
|
|
26
|
+
packagePatterns?: string[];
|
|
23
27
|
}): Promise<McpTool[]>;
|
package/dist/server/mcp-tools.js
CHANGED
|
@@ -36,13 +36,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
36
36
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
37
|
var mcp_tools_exports = {};
|
|
38
38
|
__export(mcp_tools_exports, {
|
|
39
|
-
|
|
39
|
+
DEFAULT_MCP_PACKAGE_PATTERNS: () => DEFAULT_MCP_PACKAGE_PATTERNS,
|
|
40
|
+
collectMcpToolsFromSwagger: () => collectMcpToolsFromSwagger,
|
|
41
|
+
normalizePackageName: () => normalizePackageName,
|
|
42
|
+
normalizePackagePatterns: () => normalizePackagePatterns
|
|
40
43
|
});
|
|
41
44
|
module.exports = __toCommonJS(mcp_tools_exports);
|
|
42
45
|
var import_utils = require("@nocobase/utils");
|
|
43
46
|
var import_utils2 = require("@nocobase/utils");
|
|
44
47
|
var import_light_my_request = __toESM(require("light-my-request"));
|
|
45
48
|
const SWAGGER_TARGETS = ["swagger.json", "swagger/index.json", "swagger"];
|
|
49
|
+
const DEFAULT_MCP_PACKAGE_PATTERNS = [
|
|
50
|
+
"@nocobase/plugin-data-source-main",
|
|
51
|
+
"@nocobase/plugin-data-source-manager",
|
|
52
|
+
"@nocobase/plugin-workflow*",
|
|
53
|
+
"@nocobase/plugin-acl",
|
|
54
|
+
"@nocobase/plugin-users",
|
|
55
|
+
"@nocobase/plugin-auth",
|
|
56
|
+
"@nocobase/plugin-client",
|
|
57
|
+
"@nocobase/plugin-flow-engine",
|
|
58
|
+
"@nocobase/plugin-ai"
|
|
59
|
+
];
|
|
46
60
|
function getSwaggerPrefixes() {
|
|
47
61
|
if (process.env.NODE_ENV === "production") {
|
|
48
62
|
return ["lib", "dist", "src"];
|
|
@@ -64,6 +78,29 @@ function loadSwagger(packageName) {
|
|
|
64
78
|
}
|
|
65
79
|
return {};
|
|
66
80
|
}
|
|
81
|
+
function normalizePackageName(packageName) {
|
|
82
|
+
const normalized = packageName.trim();
|
|
83
|
+
if (!normalized) {
|
|
84
|
+
return "";
|
|
85
|
+
}
|
|
86
|
+
if (normalized.startsWith("@")) {
|
|
87
|
+
return normalized;
|
|
88
|
+
}
|
|
89
|
+
return `@nocobase/${normalized}`;
|
|
90
|
+
}
|
|
91
|
+
function normalizePackagePatterns(packageNames = []) {
|
|
92
|
+
return [...new Set(packageNames.map(normalizePackageName).filter(Boolean))];
|
|
93
|
+
}
|
|
94
|
+
function matchesPackagePattern(packageName, pattern) {
|
|
95
|
+
if (pattern.endsWith("*")) {
|
|
96
|
+
return packageName.startsWith(pattern.slice(0, -1));
|
|
97
|
+
}
|
|
98
|
+
return packageName === pattern;
|
|
99
|
+
}
|
|
100
|
+
function shouldIncludePackage(packageName, patterns) {
|
|
101
|
+
const normalizedPatterns = (patterns == null ? void 0 : patterns.length) ? normalizePackagePatterns(patterns) : DEFAULT_MCP_PACKAGE_PATTERNS;
|
|
102
|
+
return normalizedPatterns.some((pattern) => matchesPackagePattern(packageName, pattern));
|
|
103
|
+
}
|
|
67
104
|
function mergeSwagger(target, source) {
|
|
68
105
|
return (0, import_utils2.merge)(target, source, {
|
|
69
106
|
arrayMerge: (destinationArray, sourceArray) => sourceArray.concat(destinationArray)
|
|
@@ -132,6 +169,21 @@ function joinUrl(baseUrl, path) {
|
|
|
132
169
|
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
133
170
|
return `${normalizedBase}${normalizedPath}`;
|
|
134
171
|
}
|
|
172
|
+
function buildQueryValue(value) {
|
|
173
|
+
if (typeof value === "undefined") {
|
|
174
|
+
return void 0;
|
|
175
|
+
}
|
|
176
|
+
if (value === null) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
if (Array.isArray(value)) {
|
|
180
|
+
return value;
|
|
181
|
+
}
|
|
182
|
+
if (typeof value === "object") {
|
|
183
|
+
return JSON.stringify(value);
|
|
184
|
+
}
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
135
187
|
function buildRequest(tool, args = {}, context) {
|
|
136
188
|
var _a;
|
|
137
189
|
const missingPathParams = [];
|
|
@@ -152,7 +204,7 @@ function buildRequest(tool, args = {}, context) {
|
|
|
152
204
|
continue;
|
|
153
205
|
}
|
|
154
206
|
if (parameter.in === "query") {
|
|
155
|
-
query[parameter.name] = value;
|
|
207
|
+
query[parameter.name] = buildQueryValue(value);
|
|
156
208
|
continue;
|
|
157
209
|
}
|
|
158
210
|
if (parameter.in === "header") {
|
|
@@ -188,7 +240,7 @@ function buildRequest(tool, args = {}, context) {
|
|
|
188
240
|
}
|
|
189
241
|
async function collectMcpToolsFromSwagger(options) {
|
|
190
242
|
var _a;
|
|
191
|
-
const { app } = options;
|
|
243
|
+
const { app, packagePatterns } = options;
|
|
192
244
|
const plugins = await app.db.getRepository("applicationPlugins").find({
|
|
193
245
|
filter: {
|
|
194
246
|
enabled: true
|
|
@@ -207,10 +259,12 @@ async function collectMcpToolsFromSwagger(options) {
|
|
|
207
259
|
}
|
|
208
260
|
]
|
|
209
261
|
};
|
|
210
|
-
|
|
262
|
+
if (shouldIncludePackage("@nocobase/server", packagePatterns)) {
|
|
263
|
+
swagger = mergeSwagger(swagger, loadSwagger("@nocobase/server"));
|
|
264
|
+
}
|
|
211
265
|
for (const plugin of plugins) {
|
|
212
266
|
const packageName = plugin.get("packageName");
|
|
213
|
-
if (!packageName) {
|
|
267
|
+
if (!packageName || !shouldIncludePackage(packageName, packagePatterns)) {
|
|
214
268
|
continue;
|
|
215
269
|
}
|
|
216
270
|
const pluginSwagger = loadSwagger(packageName);
|
|
@@ -263,5 +317,8 @@ async function collectMcpToolsFromSwagger(options) {
|
|
|
263
317
|
}
|
|
264
318
|
// Annotate the CommonJS export names for ESM import in node:
|
|
265
319
|
0 && (module.exports = {
|
|
266
|
-
|
|
320
|
+
DEFAULT_MCP_PACKAGE_PATTERNS,
|
|
321
|
+
collectMcpToolsFromSwagger,
|
|
322
|
+
normalizePackageName,
|
|
323
|
+
normalizePackagePatterns
|
|
267
324
|
});
|
package/dist/server/plugin.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { Plugin } from '@nocobase/server';
|
|
|
10
10
|
export declare class PluginMcpServerServer extends Plugin {
|
|
11
11
|
private mcpServer;
|
|
12
12
|
private readonly mcpScopes;
|
|
13
|
+
private readonly mcpToolsCache;
|
|
13
14
|
private getApiBasePath;
|
|
14
15
|
private getMcpPath;
|
|
15
16
|
private getIdpOauthPlugin;
|
|
@@ -18,7 +19,9 @@ export declare class PluginMcpServerServer extends Plugin {
|
|
|
18
19
|
private registerProtectedResourceMetadataRoute;
|
|
19
20
|
private registerIdpResource;
|
|
20
21
|
private unregisterIdpResource;
|
|
21
|
-
private
|
|
22
|
+
private parsePackagePatterns;
|
|
23
|
+
private getMcpToolsCacheKey;
|
|
24
|
+
private getMcpTools;
|
|
22
25
|
afterAdd(): Promise<void>;
|
|
23
26
|
beforeLoad(): Promise<void>;
|
|
24
27
|
load(): Promise<void>;
|
package/dist/server/plugin.js
CHANGED
|
@@ -38,9 +38,11 @@ function normalizeBasePath(path = "") {
|
|
|
38
38
|
const normalized = path.replace(/\/+/g, "/").replace(/\/$/, "");
|
|
39
39
|
return normalized || "/";
|
|
40
40
|
}
|
|
41
|
+
const MCP_PACKAGES_HEADER = "x-mcp-packages";
|
|
41
42
|
class PluginMcpServerServer extends import_server.Plugin {
|
|
42
43
|
mcpServer;
|
|
43
44
|
mcpScopes = ["mcp", "offline_access"];
|
|
45
|
+
mcpToolsCache = /* @__PURE__ */ new Map();
|
|
44
46
|
getApiBasePath() {
|
|
45
47
|
return normalizeBasePath(process.env.API_BASE_PATH || "/api");
|
|
46
48
|
}
|
|
@@ -119,11 +121,36 @@ class PluginMcpServerServer extends import_server.Plugin {
|
|
|
119
121
|
var _a, _b, _c;
|
|
120
122
|
(_c = (_b = (_a = this.getIdpOauthPlugin()) == null ? void 0 : _a.service) == null ? void 0 : _b.unregisterResourceServer) == null ? void 0 : _c.call(_b, "mcp");
|
|
121
123
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
parsePackagePatterns(ctx) {
|
|
125
|
+
var _a, _b, _c;
|
|
126
|
+
const value = ((_a = ctx == null ? void 0 : ctx.headers) == null ? void 0 : _a[MCP_PACKAGES_HEADER]) ?? ((_c = (_b = ctx == null ? void 0 : ctx.request) == null ? void 0 : _b.headers) == null ? void 0 : _c[MCP_PACKAGES_HEADER]);
|
|
127
|
+
if (typeof value === "undefined") {
|
|
128
|
+
return void 0;
|
|
129
|
+
}
|
|
130
|
+
const rawValues = (Array.isArray(value) ? value : [value]).flatMap((item) => String(item).split(","));
|
|
131
|
+
return (0, import_mcp_tools.normalizePackagePatterns)(rawValues);
|
|
132
|
+
}
|
|
133
|
+
getMcpToolsCacheKey(packagePatterns) {
|
|
134
|
+
if (typeof packagePatterns === "undefined") {
|
|
135
|
+
return "__default__";
|
|
136
|
+
}
|
|
137
|
+
return packagePatterns.slice().sort().join(",");
|
|
138
|
+
}
|
|
139
|
+
async getMcpTools(ctx) {
|
|
140
|
+
const packagePatterns = this.parsePackagePatterns(ctx);
|
|
141
|
+
const cacheKey = this.getMcpToolsCacheKey(packagePatterns);
|
|
142
|
+
let toolsPromise = this.mcpToolsCache.get(cacheKey);
|
|
143
|
+
if (!toolsPromise) {
|
|
144
|
+
toolsPromise = (0, import_mcp_tools.collectMcpToolsFromSwagger)({
|
|
145
|
+
app: this.app,
|
|
146
|
+
packagePatterns
|
|
147
|
+
}).then((apiTools) => [...apiTools, (0, import_crud_tool.createCrudTool)({ app: this.app })]).catch((error) => {
|
|
148
|
+
this.mcpToolsCache.delete(cacheKey);
|
|
149
|
+
throw error;
|
|
150
|
+
});
|
|
151
|
+
this.mcpToolsCache.set(cacheKey, toolsPromise);
|
|
152
|
+
}
|
|
153
|
+
return toolsPromise;
|
|
127
154
|
}
|
|
128
155
|
async afterAdd() {
|
|
129
156
|
}
|
|
@@ -131,7 +158,6 @@ class PluginMcpServerServer extends import_server.Plugin {
|
|
|
131
158
|
}
|
|
132
159
|
async load() {
|
|
133
160
|
var _a;
|
|
134
|
-
await this.registerMcpTools();
|
|
135
161
|
if ((_a = this.getIdpOauthPlugin()) == null ? void 0 : _a.service) {
|
|
136
162
|
this.registerIdpResource();
|
|
137
163
|
this.registerProtectedResourceMetadataRoute();
|
|
@@ -140,6 +166,7 @@ class PluginMcpServerServer extends import_server.Plugin {
|
|
|
140
166
|
name: "nocobase-mcp-server",
|
|
141
167
|
version: this.options.version || "0.0.0",
|
|
142
168
|
toolsManager: this.ai.mcpToolsManager,
|
|
169
|
+
getTools: async (ctx) => this.getMcpTools(ctx),
|
|
143
170
|
logger: this.log
|
|
144
171
|
});
|
|
145
172
|
this.app.use(
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/plugin-mcp-server",
|
|
3
3
|
"main": "dist/server/index.js",
|
|
4
|
-
"version": "2.1.0-alpha.
|
|
4
|
+
"version": "2.1.0-alpha.11",
|
|
5
5
|
"displayName": "AI: MCP server",
|
|
6
6
|
"displayName.zh-CN": "AI: MCP 服务器",
|
|
7
7
|
"description": "An MCP server for building NocoBase systems and supporting business workflows.",
|
|
@@ -23,5 +23,5 @@
|
|
|
23
23
|
"keywords": [
|
|
24
24
|
"AI"
|
|
25
25
|
],
|
|
26
|
-
"gitHead": "
|
|
26
|
+
"gitHead": "bb96d633a6371afb586072ff516bd0613c757db0"
|
|
27
27
|
}
|