@lenso/mcp 0.3.0 → 0.4.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.
- package/README.md +10 -0
- package/dist/index.js +33 -22
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -37,6 +37,16 @@ service still enforces its tenant/object/owner rules. Manage/`createAgentTools`
|
|
|
37
37
|
are the canonical schema/metadata source; all selected schemas must convert to
|
|
38
38
|
SDK-compatible object schemas before readiness, including currently hidden tools.
|
|
39
39
|
|
|
40
|
+
The borrowed adapter prepares one immutable Manage selection for its lifetime.
|
|
41
|
+
Discovery, invocation policies and bindings receive the same frozen declaration
|
|
42
|
+
snapshots, retaining exact plugin/schema/function identities. Do not key policies
|
|
43
|
+
by the original declaration object's identity; use the exact plugin and declared
|
|
44
|
+
method. Original declaration edits do not change admission or dispatch. Replace
|
|
45
|
+
the adapter when changing its selection. Existing `operation_N` tool names remain
|
|
46
|
+
entry-local, translated internally to Manage's selection-scoped opaque keys.
|
|
47
|
+
Close revokes admission, waits for actual work to drain, then releases the
|
|
48
|
+
selection's runtime references; policy closures retain any resources they capture.
|
|
49
|
+
|
|
40
50
|
For a **dedicated local process**, replace the adapter creation above with:
|
|
41
51
|
|
|
42
52
|
```ts
|
package/dist/index.js
CHANGED
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
import { environmentSecrets, redact } from "@lenso/engine/diagnostics";
|
|
38
38
|
|
|
39
39
|
// src/adapter.ts
|
|
40
|
-
import { createAgentTools,
|
|
40
|
+
import { createAgentTools, createManageSelection } from "@lenso/manage";
|
|
41
41
|
import {
|
|
42
42
|
boundedJson
|
|
43
43
|
} from "@lenso/engine/operations";
|
|
@@ -100,19 +100,24 @@ function failure(code) {
|
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
102
|
async function createMcpAdapter(options) {
|
|
103
|
+
const { running, plugins, operations, ...policies } = options;
|
|
104
|
+
const selection = createManageSelection({ running, plugins, operations });
|
|
105
|
+
try {
|
|
106
|
+
return await adapterForSelection(selection, policies);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
selection.close();
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async function adapterForSelection(selection, options) {
|
|
103
113
|
const maxInput = positive(options.maxInputBytes, 256 * 1024);
|
|
104
114
|
const maxOutput = positive(options.maxOutputBytes, 1024 * 1024, 256);
|
|
105
115
|
const maxCatalog = positive(options.maxCatalogBytes, 256 * 1024);
|
|
106
116
|
const maxConcurrent = positive(options.maxConcurrentCalls, 4);
|
|
107
117
|
const timeout = positive(options.requestTimeoutMs, 30000);
|
|
108
|
-
const operations = Object.freeze([...options.operations]);
|
|
109
|
-
const plugins = Object.freeze([...options.plugins]);
|
|
110
118
|
if ([options.binding, options.canList, options.authorize].some((fn) => typeof fn !== "function"))
|
|
111
119
|
throw new TypeError("MCP requires trusted binding, catalog and invocation policies.");
|
|
112
|
-
const canonical =
|
|
113
|
-
running: options.running,
|
|
114
|
-
plugins,
|
|
115
|
-
operations,
|
|
120
|
+
const canonical = selection.createAdapter({
|
|
116
121
|
canList: () => true,
|
|
117
122
|
binding: () => {
|
|
118
123
|
throw new Error("Metadata adapter cannot invoke.");
|
|
@@ -126,7 +131,7 @@ async function createMcpAdapter(options) {
|
|
|
126
131
|
const tools = agentTools.map((item, index) => {
|
|
127
132
|
const operation = catalog[index];
|
|
128
133
|
const tool = {
|
|
129
|
-
name:
|
|
134
|
+
name: `operation_${index}`,
|
|
130
135
|
title: `${operation.pluginId}.${operation.method}`,
|
|
131
136
|
description: [
|
|
132
137
|
item.description,
|
|
@@ -149,6 +154,7 @@ async function createMcpAdapter(options) {
|
|
|
149
154
|
return tool;
|
|
150
155
|
});
|
|
151
156
|
boundedJson({ tools }, maxCatalog);
|
|
157
|
+
const toolByKey = new Map(catalog.map((operation, index) => [operation.key, tools[index]]));
|
|
152
158
|
let closed = false;
|
|
153
159
|
let closePromise;
|
|
154
160
|
const pending = new Set;
|
|
@@ -196,12 +202,18 @@ async function createMcpAdapter(options) {
|
|
|
196
202
|
throw new McpError(ErrorCode.InternalError, "Adapter is busy.");
|
|
197
203
|
try {
|
|
198
204
|
return await tracked(request, async (context) => {
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
+
const scoped = selection.createAdapter({
|
|
206
|
+
maxOutputBytes: maxCatalog,
|
|
207
|
+
binding: () => {
|
|
208
|
+
throw new Error("Metadata adapter cannot invoke.");
|
|
209
|
+
},
|
|
210
|
+
canList: async (operation) => {
|
|
211
|
+
const visible = await options.canList(operation, context);
|
|
212
|
+
context.signal.throwIfAborted();
|
|
213
|
+
return visible;
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
const visible = (await scoped.catalog()).map((operation) => toolByKey.get(operation.key));
|
|
205
217
|
return JSON.parse(boundedJson({ tools: visible }, maxCatalog));
|
|
206
218
|
});
|
|
207
219
|
} catch {
|
|
@@ -210,7 +222,7 @@ async function createMcpAdapter(options) {
|
|
|
210
222
|
},
|
|
211
223
|
async callTool(name, input, request) {
|
|
212
224
|
const match = /^operation_(0|[1-9][0-9]*)$/.exec(name);
|
|
213
|
-
if (!match || !
|
|
225
|
+
if (!match || !catalog[Number(match[1])])
|
|
214
226
|
throw new McpError(ErrorCode.InvalidParams, "Unknown tool.");
|
|
215
227
|
if (closed)
|
|
216
228
|
return failure("adapter-closed");
|
|
@@ -225,10 +237,7 @@ async function createMcpAdapter(options) {
|
|
|
225
237
|
}
|
|
226
238
|
try {
|
|
227
239
|
const value = await tracked(request, async (context) => {
|
|
228
|
-
const scoped =
|
|
229
|
-
running: options.running,
|
|
230
|
-
plugins,
|
|
231
|
-
operations,
|
|
240
|
+
const scoped = selection.createAdapter({
|
|
232
241
|
maxOutputBytes: maxOutput,
|
|
233
242
|
canList: async (operation) => {
|
|
234
243
|
const visible = await options.canList(operation, context);
|
|
@@ -245,13 +254,13 @@ async function createMcpAdapter(options) {
|
|
|
245
254
|
};
|
|
246
255
|
}
|
|
247
256
|
});
|
|
248
|
-
const result = await scoped.invokeEntry(
|
|
257
|
+
const result = await scoped.invokeEntry(catalog[Number(match[1])].key, input);
|
|
249
258
|
context.signal.throwIfAborted();
|
|
250
259
|
return result;
|
|
251
260
|
});
|
|
252
261
|
return { content: [{ type: "text", text: boundedJson(value, maxOutput) }] };
|
|
253
262
|
} catch (error) {
|
|
254
|
-
return failure(error instanceof EngineError ? error.diagnostic.code :
|
|
263
|
+
return failure(error instanceof EngineError ? error.diagnostic.code : "invocation-failed");
|
|
255
264
|
}
|
|
256
265
|
},
|
|
257
266
|
close() {
|
|
@@ -260,7 +269,9 @@ async function createMcpAdapter(options) {
|
|
|
260
269
|
closed = true;
|
|
261
270
|
for (const controller of controllers)
|
|
262
271
|
controller.abort();
|
|
263
|
-
closePromise = Promise.allSettled(pending).then(() => {
|
|
272
|
+
closePromise = Promise.allSettled(pending).then(() => {
|
|
273
|
+
selection.close();
|
|
274
|
+
});
|
|
264
275
|
return closePromise;
|
|
265
276
|
}
|
|
266
277
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenso/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"test": "bun test"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@lenso/cli": "^0.
|
|
28
|
-
"@lenso/core": "^0.3.
|
|
29
|
-
"@lenso/engine": "^0.
|
|
30
|
-
"@lenso/manage": "^0.
|
|
27
|
+
"@lenso/cli": "^0.20.1",
|
|
28
|
+
"@lenso/core": "^0.3.1",
|
|
29
|
+
"@lenso/engine": "^0.6.0",
|
|
30
|
+
"@lenso/manage": "^0.5.0",
|
|
31
31
|
"@modelcontextprotocol/sdk": "1.32.1",
|
|
32
32
|
"zod": "4.6.5"
|
|
33
33
|
}
|