@akira-tl/forgerelay 1.1.0 → 1.1.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/CHANGELOG.md +19 -0
- package/README.md +4 -2
- package/dist/activity/runtime/mcp-query-tools.js +16 -10
- package/dist/cli/mcp/external-mcp.js +481 -0
- package/dist/cli/mcp/status.js +295 -0
- package/dist/cli.js +14 -1
- package/dist/lsp/test-support/server-fixture.js +1 -2
- package/dist/mcp/oauth/auth-protocol.js +375 -0
- package/dist/mcp/oauth/oauth-provider.js +11 -12
- package/dist/mcp/oauth/oauth-store.js +2 -2
- package/dist/mcp/oauth/router.js +2 -6
- package/dist/mcp/operations/batch/executor.js +1 -1
- package/dist/mcp/operations/external-mcp/external-mcp-oauth.js +387 -0
- package/dist/mcp/operations/external-mcp/external-mcp-runtime.js +23 -6
- package/dist/mcp/operations/external-mcp/external-mcp.js +178 -23
- package/dist/mcp/operations/native-bulk-mutations.js +1 -1
- package/dist/mcp/process/tools.js +19 -15
- package/dist/mcp/request-context.js +18 -0
- package/dist/mcp/request-meta.js +28 -3
- package/dist/mcp/server/core/capabilities.js +1 -4
- package/dist/mcp/server/operations/runtime/filesystem-tools.js +35 -28
- package/dist/mcp/server/operations/runtime/operation-runtime.js +7 -7
- package/dist/mcp/server/transport/http-server.js +41 -20
- package/dist/mcp/server/workspace/runtime/workspace-open.js +13 -9
- package/dist/mcp/server/workspace/runtime/workspace-tools.js +29 -25
- package/dist/runtime/config/external-mcp-auth-store.js +225 -0
- package/dist/runtime/config/external-mcp-config.js +76 -22
- package/dist/runtime/config/external-mcp-registry.js +165 -0
- package/dist/runtime/testing/server-fixture.js +4 -4
- package/dist/server.js +15 -9
- package/dist/ui/.vite/manifest.json +297 -298
- package/dist/ui/activity-panel-app.html +1 -1
- package/dist/ui/assets/activity-panel-app-Bw7ZFX2g.js +114 -0
- package/dist/ui/assets/angular-html-DeUNP12X.js +1 -0
- package/dist/ui/assets/{angular-ts-BearSZDb.js → angular-ts-B3v8FKi_.js} +1 -1
- package/dist/ui/assets/{apl-CYQtr-y6.js → apl-Bs3iQm4P.js} +1 -1
- package/dist/ui/assets/{astro-DDzqKIjK.js → astro-D6GHecBY.js} +1 -1
- package/dist/ui/assets/{blade-DkwEyHvQ.js → blade-BMNbVOHv.js} +1 -1
- package/dist/ui/assets/c-BquuA6bv.js +1 -0
- package/dist/ui/assets/{cobol-xBn5JxHE.js → cobol-BuZ6kfps.js} +1 -1
- package/dist/ui/assets/{coffee-BaXXvoJw.js → coffee-DgC5uBzL.js} +1 -1
- package/dist/ui/assets/cpp-BdvWqCaB.js +1 -0
- package/dist/ui/assets/{crystal-DjOpXVU1.js → crystal-0Q5qBvNI.js} +1 -1
- package/dist/ui/assets/css-Be_T8idh.js +1 -0
- package/dist/ui/assets/{edge-DNaRizoR.js → edge-DaGLdgh_.js} +1 -1
- package/dist/ui/assets/{elixir-CwBMwZmy.js → elixir-CMgiFIzB.js} +1 -1
- package/dist/ui/assets/{elm-gOUD2CW3.js → elm-B-ufMlMC.js} +1 -1
- package/dist/ui/assets/{erb-BcR-fjUp.js → erb-CaGiOZM-.js} +1 -1
- package/dist/ui/assets/{git-rebase-BAQPKHF6.js → git-rebase-CpwUWCzK.js} +1 -1
- package/dist/ui/assets/{glimmer-js-P_wOfSz_.js → glimmer-js-BRxccvnE.js} +1 -1
- package/dist/ui/assets/{glimmer-ts-B44aY1fZ.js → glimmer-ts-CgQbPzlT.js} +1 -1
- package/dist/ui/assets/glsl-D7JmHFr0.js +1 -0
- package/dist/ui/assets/graphql-C8n0eUBK.js +1 -0
- package/dist/ui/assets/{hack-ddU2k0nt.js → hack-lVN7KVQv.js} +1 -1
- package/dist/ui/assets/haml-h18lG0pS.js +1 -0
- package/dist/ui/assets/{handlebars-BpzaUpmz.js → handlebars-lRFjRPfj.js} +1 -1
- package/dist/ui/assets/heavy-payload-Cqx9MOkH.js +290 -0
- package/dist/ui/assets/html-DtILqTE1.js +1 -0
- package/dist/ui/assets/{html-derivative-B2beVdmA.js → html-derivative-CSTSmPup.js} +1 -1
- package/dist/ui/assets/{http-iEskZy8U.js → http-DNI8fsbY.js} +1 -1
- package/dist/ui/assets/{hurl-BuUsLSKv.js → hurl-DgRi60JG.js} +1 -1
- package/dist/ui/assets/java-CW9pZ5bh.js +1 -0
- package/dist/ui/assets/javascript-Cvg2UrWL.js +1 -0
- package/dist/ui/assets/{jinja-CRpkWwrH.js → jinja-CZw_S1FB.js} +1 -1
- package/dist/ui/assets/{jison-BYfSnuHj.js → jison-C56u_FZv.js} +1 -1
- package/dist/ui/assets/json-DW2UTv1q.js +1 -0
- package/dist/ui/assets/jsx-Zj5gobdD.js +1 -0
- package/dist/ui/assets/{julia-B8Rxy7vD.js → julia-Cvcrre-L.js} +1 -1
- package/dist/ui/assets/{just-DzhIWpFP.js → just-8CZ2u6Tj.js} +1 -1
- package/dist/ui/assets/{latex-CUNjUUL-.js → latex-D289AXWG.js} +1 -1
- package/dist/ui/assets/{liquid-hUg7nC61.js → liquid-CFEX3SkZ.js} +1 -1
- package/dist/ui/assets/lua-BKpJ0ybO.js +1 -0
- package/dist/ui/assets/{marko-CQmIkwMF.js → marko-D9maZ0a6.js} +1 -1
- package/dist/ui/assets/{mdc-CB-6dHYa.js → mdc-rM9l0qWR.js} +1 -1
- package/dist/ui/assets/{nginx-CQORo_Bt.js → nginx-C9w6p2C9.js} +1 -1
- package/dist/ui/assets/{nim-BNwBNzdn.js → nim-BRePHk0J.js} +1 -1
- package/dist/ui/assets/{perl-Cnz14fAJ.js → perl-CskTmiPQ.js} +1 -1
- package/dist/ui/assets/{php-YywDo63b.js → php-DCU_FvNI.js} +1 -1
- package/dist/ui/assets/{pug-BwbJp4cM.js → pug-XLaVxTvv.js} +1 -1
- package/dist/ui/assets/{qml-D2DY6dMH.js → qml-CaONKSl-.js} +1 -1
- package/dist/ui/assets/r-BCVR0ZE3.js +1 -0
- package/dist/ui/assets/{razor-pMTG7k41.js → razor-DDnGXxnU.js} +1 -1
- package/dist/ui/assets/regexp-DWGTYYVx.js +1 -0
- package/dist/ui/assets/{rst-CO_ndDm4.js → rst-Dz3GWvQm.js} +1 -1
- package/dist/ui/assets/{ruby-xzRn9gTh.js → ruby-DC3jGtMY.js} +1 -1
- package/dist/ui/assets/{sas-CBdtFKLA.js → sas-7mNpvsjZ.js} +1 -1
- package/dist/ui/assets/scss-uBsoCJVy.js +1 -0
- package/dist/ui/assets/shellscript-BCN9N_Jf.js +1 -0
- package/dist/ui/assets/{shellsession-BaZnm5rZ.js → shellsession-Hsw46VXV.js} +1 -1
- package/dist/ui/assets/{soy-IouG3xdB.js → soy-D6KV69HU.js} +1 -1
- package/dist/ui/assets/sql-CVzVQkJh.js +1 -0
- package/dist/ui/assets/{stata-dgbkIZHP.js → stata-BwUjXNhI.js} +1 -1
- package/dist/ui/assets/{surrealql-CBROnw_p.js → surrealql-CgloWqRa.js} +1 -1
- package/dist/ui/assets/{svelte-6r6BpX4-.js → svelte-DcC3n6IC.js} +1 -1
- package/dist/ui/assets/{templ-BKD_PsbL.js → templ-DOFfnWTJ.js} +1 -1
- package/dist/ui/assets/{tex-CKY1bwHb.js → tex-ln89VPaX.js} +1 -1
- package/dist/ui/assets/{ts-tags-BiYP5N_C.js → ts-tags-CWMzCstH.js} +1 -1
- package/dist/ui/assets/tsx-DgzfiGeK.js +1 -0
- package/dist/ui/assets/{twig-BTe1oPFW.js → twig-Bi2itZL9.js} +1 -1
- package/dist/ui/assets/typescript-CQ24f4zW.js +1 -0
- package/dist/ui/assets/{vue-CT0IiySh.js → vue-BS8jE5u6.js} +1 -1
- package/dist/ui/assets/{vue-html-B-tXcbat.js → vue-html-o38xqhyB.js} +1 -1
- package/dist/ui/assets/{vue-vine-C5ZyDCrs.js → vue-vine-D2NvKv50.js} +1 -1
- package/dist/ui/assets/xml-_44rx9_2.js +1 -0
- package/dist/ui/assets/{xsl-DvDSndNI.js → xsl-B5QWQPoi.js} +1 -1
- package/dist/ui/assets/yaml-CKL2pEWe.js +1 -0
- package/dist/workspaces/relay/auth/remote-auth.js +3 -5
- package/dist/workspaces/relay/tests/test-support.js +7 -4
- package/dist/workspaces/relay/workspace-relay.js +14 -8
- package/docs/configuration.md +154 -4
- package/docs/debugging.md +8 -5
- package/docs/roadmap.md +64 -3
- package/docs/security.md +18 -0
- package/package.json +11 -4
- package/scripts/debug/accept/bootstrap.mjs +2 -0
- package/scripts/debug/accept/harness.mjs +9 -2
- package/scripts/debug/accept/modern-http.mjs +169 -0
- package/scripts/debug/accept/support.mjs +10 -6
- package/scripts/debug/accept.mjs +1 -0
- package/scripts/debug/runtime.mjs +4 -1
- package/scripts/debug/runtime.test.mjs +9 -0
- package/scripts/release/parity-sandbox.mjs +35 -0
- package/scripts/release/release-gate.test.mjs +42 -1
- package/scripts/release-parity.mjs +3 -22
- package/scripts/release-proof.mjs +24 -4
- package/scripts/release-proof.test.mjs +12 -4
- package/dist/ui/assets/activity-panel-app-XlqSanXT.js +0 -115
- package/dist/ui/assets/angular-html-tB9EchbM.js +0 -1
- package/dist/ui/assets/c-Dv-N5hjn.js +0 -1
- package/dist/ui/assets/cpp-C3unXX-3.js +0 -1
- package/dist/ui/assets/css-8Xr4kNNH.js +0 -1
- package/dist/ui/assets/glsl-BvCQg9MI.js +0 -1
- package/dist/ui/assets/graphql-C9S90gn_.js +0 -1
- package/dist/ui/assets/haml-Bb1w9rMG.js +0 -1
- package/dist/ui/assets/heavy-payload-CJKqi8Ac.js +0 -290
- package/dist/ui/assets/html-dUOs5pA9.js +0 -1
- package/dist/ui/assets/java-BFZCrORY.js +0 -1
- package/dist/ui/assets/javascript-DaIQ0Zqj.js +0 -1
- package/dist/ui/assets/json-BQC_Yp48.js +0 -1
- package/dist/ui/assets/jsx-Dd-CJRf9.js +0 -1
- package/dist/ui/assets/lua-BoZTiL2I.js +0 -1
- package/dist/ui/assets/r-B5nYsy-M.js +0 -1
- package/dist/ui/assets/regexp-oP0lbks_.js +0 -1
- package/dist/ui/assets/scss-CEqgKQNf.js +0 -1
- package/dist/ui/assets/shellscript-DzJJiWQC.js +0 -1
- package/dist/ui/assets/sql-DC2rdTzV.js +0 -1
- package/dist/ui/assets/tsx-D2OMiPNF.js +0 -1
- package/dist/ui/assets/typescript-BGIABksB.js +0 -1
- package/dist/ui/assets/xml-CfeBNlMP.js +0 -1
- package/dist/ui/assets/yaml-umbj2r1g.js +0 -1
|
@@ -3,6 +3,7 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { isAbsolute } from "node:path";
|
|
4
4
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
5
5
|
import * as z from "zod/v4";
|
|
6
|
+
import { mcpHandlerRequestContext } from "../../../request-context.js";
|
|
6
7
|
import { applyPatch } from "../../../filesystem/apply-patch.js";
|
|
7
8
|
import { readFileTool } from "../../../filesystem/filesystem-tools.js";
|
|
8
9
|
import { createMediaBudget } from "../../../operations/media-content.js";
|
|
@@ -85,6 +86,7 @@ export function registerFilesystemTools(options) {
|
|
|
85
86
|
_meta: {},
|
|
86
87
|
annotations: { readOnlyHint: true },
|
|
87
88
|
}, async ({ workspaceId, member, path, paths, offset, limit }, extra) => {
|
|
89
|
+
const requestContext = mcpHandlerRequestContext(extra);
|
|
88
90
|
if ((path === undefined) === (paths === undefined)) {
|
|
89
91
|
throw new Error("read requires exactly one of path or paths.");
|
|
90
92
|
}
|
|
@@ -101,7 +103,7 @@ export function registerFilesystemTools(options) {
|
|
|
101
103
|
const mediaBudget = createMediaBudget(config.mediaMaxBytes);
|
|
102
104
|
const execution = await executeBulkRead({
|
|
103
105
|
paths: requestedPaths,
|
|
104
|
-
signal:
|
|
106
|
+
signal: requestContext.signal,
|
|
105
107
|
run: (requestedPath) => readFileTool({ path: requestedPath, offset, limit }, {
|
|
106
108
|
cwd: process.cwd(),
|
|
107
109
|
root: config.allowedRoots[0] ?? process.cwd(),
|
|
@@ -181,20 +183,20 @@ export function registerFilesystemTools(options) {
|
|
|
181
183
|
}
|
|
182
184
|
const target = resolveExecutionTarget(workspaceId, member);
|
|
183
185
|
const executionWorkspaceId = target.executionWorkspaceId;
|
|
184
|
-
const executionContext = await prepareExecutionContext(target,
|
|
186
|
+
const executionContext = await prepareExecutionContext(target, requestContext);
|
|
185
187
|
if (remoteWorkspaces.has(executionWorkspaceId)) {
|
|
186
|
-
return presentSemanticWorkResult(await remoteWorkspaces.read(executionWorkspaceId, { path, paths, offset, limit }, hostScopeIdFor(
|
|
188
|
+
return presentSemanticWorkResult(await remoteWorkspaces.read(executionWorkspaceId, { path, paths, offset, limit }, hostScopeIdFor(requestContext)), target, hostScopeIdFor(requestContext));
|
|
187
189
|
}
|
|
188
190
|
if (path !== undefined) {
|
|
189
|
-
return presentSemanticWorkResult(await coreOperations.read({ workspaceId: executionWorkspaceId, path, offset, limit }, executionContext), target, hostScopeIdFor(
|
|
191
|
+
return presentSemanticWorkResult(await coreOperations.read({ workspaceId: executionWorkspaceId, path, offset, limit }, executionContext), target, hostScopeIdFor(requestContext));
|
|
190
192
|
}
|
|
191
193
|
const workspace = workspaces.getWorkspace(executionWorkspaceId);
|
|
192
194
|
let response;
|
|
193
|
-
await runActivityTool(activityLifecycle, workspace, hostScopeIdFor(
|
|
195
|
+
await runActivityTool(activityLifecycle, workspace, hostScopeIdFor(requestContext), toolNames.read, activityRequestFor({ workspaceId: executionWorkspaceId, paths, offset, limit }, executionContext), async (parentContext) => {
|
|
194
196
|
const mediaBudget = createMediaBudget(config.mediaMaxBytes);
|
|
195
197
|
const execution = await executeBulkRead({
|
|
196
198
|
paths: paths,
|
|
197
|
-
signal:
|
|
199
|
+
signal: requestContext.signal,
|
|
198
200
|
run: (childPath) => coreOperations.read({ workspaceId: executionWorkspaceId, path: childPath, offset, limit }, {
|
|
199
201
|
...executionContext,
|
|
200
202
|
parentActivityId: parentContext.activityId,
|
|
@@ -247,7 +249,7 @@ export function registerFilesystemTools(options) {
|
|
|
247
249
|
: { type: "succeeded" }, activityRelationFor(executionContext));
|
|
248
250
|
if (!response)
|
|
249
251
|
throw new Error("Bulk Read completed without a response.");
|
|
250
|
-
return presentSemanticWorkResult(response, target, hostScopeIdFor(
|
|
252
|
+
return presentSemanticWorkResult(response, target, hostScopeIdFor(requestContext));
|
|
251
253
|
});
|
|
252
254
|
if (config.toolMode !== "codex") {
|
|
253
255
|
registerAppTool(server, toolNames.write, {
|
|
@@ -267,13 +269,14 @@ export function registerFilesystemTools(options) {
|
|
|
267
269
|
_meta: {},
|
|
268
270
|
annotations: WRITE_TOOL_ANNOTATIONS,
|
|
269
271
|
}, async ({ workspaceId, member, ...input }, extra) => {
|
|
272
|
+
const requestContext = mcpHandlerRequestContext(extra);
|
|
270
273
|
const target = resolveExecutionTarget(workspaceId, member);
|
|
271
274
|
const executionWorkspaceId = target.executionWorkspaceId;
|
|
272
|
-
const executionContext = await prepareExecutionContext(target,
|
|
275
|
+
const executionContext = await prepareExecutionContext(target, requestContext);
|
|
273
276
|
if (remoteWorkspaces.has(executionWorkspaceId)) {
|
|
274
|
-
return presentSemanticWorkResult(await remoteWorkspaces.write(executionWorkspaceId, input, hostScopeIdFor(
|
|
277
|
+
return presentSemanticWorkResult(await remoteWorkspaces.write(executionWorkspaceId, input, hostScopeIdFor(requestContext)), target, hostScopeIdFor(requestContext));
|
|
275
278
|
}
|
|
276
|
-
return presentSemanticWorkResult(await coreOperations.write({ workspaceId: executionWorkspaceId, ...input }, executionContext), target, hostScopeIdFor(
|
|
279
|
+
return presentSemanticWorkResult(await coreOperations.write({ workspaceId: executionWorkspaceId, ...input }, executionContext), target, hostScopeIdFor(requestContext));
|
|
277
280
|
});
|
|
278
281
|
registerAppTool(server, toolNames.edit, {
|
|
279
282
|
title: "Edit file",
|
|
@@ -317,19 +320,20 @@ export function registerFilesystemTools(options) {
|
|
|
317
320
|
_meta: {},
|
|
318
321
|
annotations: EDIT_TOOL_ANNOTATIONS,
|
|
319
322
|
}, async ({ workspaceId, member, path, paths, edits }, extra) => {
|
|
323
|
+
const requestContext = mcpHandlerRequestContext(extra);
|
|
320
324
|
if ((path === undefined) === (paths === undefined)) {
|
|
321
325
|
throw new Error("edit requires exactly one of path or paths.");
|
|
322
326
|
}
|
|
323
327
|
const target = resolveExecutionTarget(workspaceId, member);
|
|
324
328
|
const executionWorkspaceId = target.executionWorkspaceId;
|
|
325
|
-
const executionContext = await prepareExecutionContext(target,
|
|
329
|
+
const executionContext = await prepareExecutionContext(target, requestContext);
|
|
326
330
|
if (remoteWorkspaces.has(executionWorkspaceId)) {
|
|
327
|
-
return presentSemanticWorkResult(await remoteWorkspaces.edit(executionWorkspaceId, { path, paths, edits }, hostScopeIdFor(
|
|
331
|
+
return presentSemanticWorkResult(await remoteWorkspaces.edit(executionWorkspaceId, { path, paths, edits }, hostScopeIdFor(requestContext)), target, hostScopeIdFor(requestContext));
|
|
328
332
|
}
|
|
329
333
|
if (path !== undefined) {
|
|
330
|
-
return presentSemanticWorkResult(await coreOperations.edit({ workspaceId: executionWorkspaceId, path, edits }, executionContext), target, hostScopeIdFor(
|
|
334
|
+
return presentSemanticWorkResult(await coreOperations.edit({ workspaceId: executionWorkspaceId, path, edits }, executionContext), target, hostScopeIdFor(requestContext));
|
|
331
335
|
}
|
|
332
|
-
return presentSemanticWorkResult(await nativeBulkMutations.edit({ workspaceId: executionWorkspaceId, paths: paths, edits }, executionContext), target, hostScopeIdFor(
|
|
336
|
+
return presentSemanticWorkResult(await nativeBulkMutations.edit({ workspaceId: executionWorkspaceId, paths: paths, edits }, executionContext), target, hostScopeIdFor(requestContext));
|
|
333
337
|
});
|
|
334
338
|
}
|
|
335
339
|
registerAppTool(server, toolNames.rename, {
|
|
@@ -349,13 +353,14 @@ export function registerFilesystemTools(options) {
|
|
|
349
353
|
_meta: {},
|
|
350
354
|
annotations: EDIT_TOOL_ANNOTATIONS,
|
|
351
355
|
}, async ({ workspaceId, member, path, newPath }, extra) => {
|
|
356
|
+
const requestContext = mcpHandlerRequestContext(extra);
|
|
352
357
|
const target = resolveExecutionTarget(workspaceId, member);
|
|
353
358
|
const executionWorkspaceId = target.executionWorkspaceId;
|
|
354
|
-
const executionContext = await prepareExecutionContext(target,
|
|
359
|
+
const executionContext = await prepareExecutionContext(target, requestContext);
|
|
355
360
|
if (remoteWorkspaces.has(executionWorkspaceId)) {
|
|
356
|
-
return presentSemanticWorkResult(await remoteWorkspaces.rename(executionWorkspaceId, { path, newPath }, hostScopeIdFor(
|
|
361
|
+
return presentSemanticWorkResult(await remoteWorkspaces.rename(executionWorkspaceId, { path, newPath }, hostScopeIdFor(requestContext)), target, hostScopeIdFor(requestContext));
|
|
357
362
|
}
|
|
358
|
-
return presentSemanticWorkResult(await coreOperations.rename({ workspaceId: executionWorkspaceId, path, newPath }, executionContext), target, hostScopeIdFor(
|
|
363
|
+
return presentSemanticWorkResult(await coreOperations.rename({ workspaceId: executionWorkspaceId, path, newPath }, executionContext), target, hostScopeIdFor(requestContext));
|
|
359
364
|
});
|
|
360
365
|
registerAppTool(server, toolNames.delete, {
|
|
361
366
|
title: "Delete path",
|
|
@@ -389,19 +394,20 @@ export function registerFilesystemTools(options) {
|
|
|
389
394
|
_meta: {},
|
|
390
395
|
annotations: EDIT_TOOL_ANNOTATIONS,
|
|
391
396
|
}, async ({ workspaceId, member, path, paths, recursive }, extra) => {
|
|
397
|
+
const requestContext = mcpHandlerRequestContext(extra);
|
|
392
398
|
if ((path === undefined) === (paths === undefined)) {
|
|
393
399
|
throw new Error("delete requires exactly one of path or paths.");
|
|
394
400
|
}
|
|
395
401
|
const target = resolveExecutionTarget(workspaceId, member);
|
|
396
402
|
const executionWorkspaceId = target.executionWorkspaceId;
|
|
397
|
-
const executionContext = await prepareExecutionContext(target,
|
|
403
|
+
const executionContext = await prepareExecutionContext(target, requestContext);
|
|
398
404
|
if (remoteWorkspaces.has(executionWorkspaceId)) {
|
|
399
|
-
return presentSemanticWorkResult(await remoteWorkspaces.delete(executionWorkspaceId, { path, paths, recursive }, hostScopeIdFor(
|
|
405
|
+
return presentSemanticWorkResult(await remoteWorkspaces.delete(executionWorkspaceId, { path, paths, recursive }, hostScopeIdFor(requestContext)), target, hostScopeIdFor(requestContext));
|
|
400
406
|
}
|
|
401
407
|
if (path !== undefined) {
|
|
402
|
-
return presentSemanticWorkResult(await coreOperations.delete({ workspaceId: executionWorkspaceId, path, recursive }, executionContext), target, hostScopeIdFor(
|
|
408
|
+
return presentSemanticWorkResult(await coreOperations.delete({ workspaceId: executionWorkspaceId, path, recursive }, executionContext), target, hostScopeIdFor(requestContext));
|
|
403
409
|
}
|
|
404
|
-
return presentSemanticWorkResult(await nativeBulkMutations.delete({ workspaceId: executionWorkspaceId, paths: paths, recursive }, executionContext), target, hostScopeIdFor(
|
|
410
|
+
return presentSemanticWorkResult(await nativeBulkMutations.delete({ workspaceId: executionWorkspaceId, paths: paths, recursive }, executionContext), target, hostScopeIdFor(requestContext));
|
|
405
411
|
});
|
|
406
412
|
if (config.toolMode === "codex") {
|
|
407
413
|
registerAppTool(server, "apply_patch", {
|
|
@@ -428,15 +434,16 @@ export function registerFilesystemTools(options) {
|
|
|
428
434
|
_meta: {},
|
|
429
435
|
annotations: EDIT_TOOL_ANNOTATIONS,
|
|
430
436
|
}, async ({ workspaceId, member, patch }, extra) => {
|
|
437
|
+
const requestContext = mcpHandlerRequestContext(extra);
|
|
431
438
|
const target = resolveExecutionTarget(workspaceId, member);
|
|
432
439
|
const executionWorkspaceId = target.executionWorkspaceId;
|
|
433
|
-
const executionContext = await prepareExecutionContext(target,
|
|
440
|
+
const executionContext = await prepareExecutionContext(target, requestContext);
|
|
434
441
|
if (remoteWorkspaces.has(executionWorkspaceId)) {
|
|
435
|
-
return presentSemanticWorkResult(await remoteWorkspaces.applyPatch(executionWorkspaceId, { patch }, hostScopeIdFor(
|
|
442
|
+
return presentSemanticWorkResult(await remoteWorkspaces.applyPatch(executionWorkspaceId, { patch }, hostScopeIdFor(requestContext)), target, hostScopeIdFor(requestContext));
|
|
436
443
|
}
|
|
437
444
|
const workspace = workspaces.getWorkspace(executionWorkspaceId);
|
|
438
|
-
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(
|
|
439
|
-
signal:
|
|
445
|
+
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(requestContext), activityRequestFor({ workspaceId: executionWorkspaceId, patch }, executionContext), {
|
|
446
|
+
signal: requestContext.signal,
|
|
440
447
|
tool: "apply_patch",
|
|
441
448
|
invocation: workspaceHookInvocation(workspace),
|
|
442
449
|
payload: { patchBytes: Buffer.byteLength(patch) },
|
|
@@ -456,7 +463,7 @@ export function registerFilesystemTools(options) {
|
|
|
456
463
|
.map((file) => file.path);
|
|
457
464
|
logToolCall(config, {
|
|
458
465
|
tool: "apply_patch",
|
|
459
|
-
...workspaceLogContext(workspace,
|
|
466
|
+
...workspaceLogContext(workspace, requestContext.transportSessionId),
|
|
460
467
|
path: displayPath,
|
|
461
468
|
success: true,
|
|
462
469
|
durationMs: Math.round(performance.now() - startedAt),
|
|
@@ -483,9 +490,9 @@ export function registerFilesystemTools(options) {
|
|
|
483
490
|
removals: applied.removals,
|
|
484
491
|
files: applied.files,
|
|
485
492
|
},
|
|
486
|
-
}, codeIntelligence, workspace.root, diagnosticPaths,
|
|
493
|
+
}, codeIntelligence, workspace.root, diagnosticPaths, requestContext.signal);
|
|
487
494
|
},
|
|
488
|
-
}, activityRelationFor(executionContext)).then((result) => presentSemanticWorkResult(result, target, hostScopeIdFor(
|
|
495
|
+
}, activityRelationFor(executionContext)).then((result) => presentSemanticWorkResult(result, target, hostScopeIdFor(requestContext)));
|
|
489
496
|
});
|
|
490
497
|
}
|
|
491
498
|
}
|
|
@@ -20,7 +20,7 @@ export function createOperationRuntime(options) {
|
|
|
20
20
|
read: async (input, context) => {
|
|
21
21
|
const { workspaceId, ...readInput } = input;
|
|
22
22
|
const workspace = workspaces.getWorkspace(workspaceId);
|
|
23
|
-
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(context
|
|
23
|
+
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(context), activityRequestFor(input, context), {
|
|
24
24
|
signal: context.signal,
|
|
25
25
|
tool: toolNames.read,
|
|
26
26
|
invocation: workspaceHookInvocation(workspace),
|
|
@@ -96,7 +96,7 @@ export function createOperationRuntime(options) {
|
|
|
96
96
|
write: async (input, context) => {
|
|
97
97
|
const { workspaceId, ...writeInput } = input;
|
|
98
98
|
const workspace = workspaces.getWorkspace(workspaceId);
|
|
99
|
-
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(context
|
|
99
|
+
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(context), activityRequestFor(input, context), {
|
|
100
100
|
signal: context.signal,
|
|
101
101
|
tool: toolNames.write,
|
|
102
102
|
invocation: workspaceHookInvocation(workspace),
|
|
@@ -157,7 +157,7 @@ export function createOperationRuntime(options) {
|
|
|
157
157
|
edit: async (input, context) => {
|
|
158
158
|
const { workspaceId, ...editInput } = input;
|
|
159
159
|
const workspace = workspaces.getWorkspace(workspaceId);
|
|
160
|
-
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(context
|
|
160
|
+
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(context), activityRequestFor(input, context), {
|
|
161
161
|
signal: context.signal,
|
|
162
162
|
tool: toolNames.edit,
|
|
163
163
|
invocation: workspaceHookInvocation(workspace),
|
|
@@ -219,7 +219,7 @@ export function createOperationRuntime(options) {
|
|
|
219
219
|
rename: async (input, context) => {
|
|
220
220
|
const { workspaceId, path, newPath } = input;
|
|
221
221
|
const workspace = workspaces.getWorkspace(workspaceId);
|
|
222
|
-
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(context
|
|
222
|
+
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(context), activityRequestFor(input, context), {
|
|
223
223
|
signal: context.signal,
|
|
224
224
|
tool: toolNames.rename,
|
|
225
225
|
invocation: workspaceHookInvocation(workspace),
|
|
@@ -278,7 +278,7 @@ export function createOperationRuntime(options) {
|
|
|
278
278
|
delete: async (input, context) => {
|
|
279
279
|
const { workspaceId, path, recursive } = input;
|
|
280
280
|
const workspace = workspaces.getWorkspace(workspaceId);
|
|
281
|
-
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(context
|
|
281
|
+
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(context), activityRequestFor(input, context), {
|
|
282
282
|
signal: context.signal,
|
|
283
283
|
tool: toolNames.delete,
|
|
284
284
|
invocation: workspaceHookInvocation(workspace),
|
|
@@ -362,7 +362,7 @@ export function createOperationRuntime(options) {
|
|
|
362
362
|
maxOutputTokens,
|
|
363
363
|
};
|
|
364
364
|
let undeliveredProcessId;
|
|
365
|
-
const activityResult = await runActivityTool(activityLifecycle, workspace, hostScopeIdFor(context
|
|
365
|
+
const activityResult = await runActivityTool(activityLifecycle, workspace, hostScopeIdFor(context), surface, activityRequestFor(activityRequest, context), async (activityContext) => {
|
|
366
366
|
try {
|
|
367
367
|
const result = await runToolWithHooks(hooks, {
|
|
368
368
|
signal: context.signal,
|
|
@@ -488,7 +488,7 @@ export function createOperationRuntime(options) {
|
|
|
488
488
|
}
|
|
489
489
|
const workspace = workspaces.getWorkspace(workspaceId);
|
|
490
490
|
let changedPaths = [];
|
|
491
|
-
return runActivityTool(activityLifecycle, workspace, hostScopeIdFor(context
|
|
491
|
+
return runActivityTool(activityLifecycle, workspace, hostScopeIdFor(context), toolNames.capability, activityRequestFor(capabilityActivityAuditRequest(input), context), (activityContext) => runToolWithHooks(hooks, {
|
|
492
492
|
signal: context.signal,
|
|
493
493
|
tool: toolNames.capability,
|
|
494
494
|
invocation: workspaceHookInvocation(workspace),
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import {
|
|
3
|
-
import { getOAuthProtectedResourceMetadataUrl } from "@modelcontextprotocol/
|
|
4
|
-
import {
|
|
5
|
-
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
6
|
-
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
7
|
-
import { checkResourceAllowed, resourceUrlFromServerUrl } from "@modelcontextprotocol/sdk/shared/auth-utils.js";
|
|
2
|
+
import { checkResourceAllowed, createMcpHandler, isInitializeRequest, isLegacyRequest, resourceUrlFromServerUrl, } from "@modelcontextprotocol/server";
|
|
3
|
+
import { createMcpExpressApp, getOAuthProtectedResourceMetadataUrl, requireBearerAuth, } from "@modelcontextprotocol/express";
|
|
4
|
+
import { NodeStreamableHTTPServerTransport, toNodeHandler, toWebRequest, } from "@modelcontextprotocol/node";
|
|
8
5
|
import express from "express";
|
|
9
6
|
import { ActivityAuditStore } from "../../../activity/history/audit-store.js";
|
|
10
7
|
import { BashOutputStore } from "../../../activity/history/bash-output-store.js";
|
|
@@ -79,6 +76,26 @@ export function createHttpServer(config, options, createMcpServer) {
|
|
|
79
76
|
const subagentProviders = config.subagents
|
|
80
77
|
? getSubagentProviderAvailabilitySnapshot()
|
|
81
78
|
: [];
|
|
79
|
+
const buildMcpServer = () => createMcpServer(config, workspaces, reviewCheckpoints, processSessions, subagentProviders, incomingArtifactAdapters, codeIntelligence, activityLifecycle, bashOutputStore, activityQueries, {
|
|
80
|
+
taskReminders: sharedTaskReminders,
|
|
81
|
+
remoteWorkspaces: sharedRemoteWorkspaces,
|
|
82
|
+
compositeWorkspaces: sharedCompositeWorkspaces,
|
|
83
|
+
});
|
|
84
|
+
const modernMcp = createMcpHandler(() => buildMcpServer(), {
|
|
85
|
+
legacy: "reject",
|
|
86
|
+
onerror: (error) => {
|
|
87
|
+
logEvent(config.logging, "error", "mcp_modern_handler_error", {
|
|
88
|
+
error: error.message,
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
const modernNodeHandler = toNodeHandler(modernMcp, {
|
|
93
|
+
onerror: (error) => {
|
|
94
|
+
logEvent(config.logging, "error", "mcp_modern_adapter_error", {
|
|
95
|
+
error: error.message,
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
});
|
|
82
99
|
const logTransportCloseResults = (reason, results) => {
|
|
83
100
|
let closedCount = 0;
|
|
84
101
|
for (const result of results) {
|
|
@@ -219,15 +236,22 @@ export function createHttpServer(config, options, createMcpServer) {
|
|
|
219
236
|
sendJsonRpcError(res, 401, -32001, "Unauthorized");
|
|
220
237
|
return;
|
|
221
238
|
}
|
|
222
|
-
logEvent(config.logging, "debug", "mcp_request", {
|
|
223
|
-
requestId,
|
|
224
|
-
httpMethod: req.method,
|
|
225
|
-
transportSessionIdPresent: Boolean(transportSessionId),
|
|
226
|
-
transportSessionIdPrefix: transportSessionIdPrefix(transportSessionId),
|
|
227
|
-
isInitialize: initializeRequest,
|
|
228
|
-
...mcpRequestDebugFields(req.body),
|
|
229
|
-
});
|
|
230
239
|
try {
|
|
240
|
+
const webRequest = await toWebRequest(req, req.body);
|
|
241
|
+
const legacyRequest = await isLegacyRequest(webRequest, req.body);
|
|
242
|
+
logEvent(config.logging, "debug", "mcp_request", {
|
|
243
|
+
requestId,
|
|
244
|
+
httpMethod: req.method,
|
|
245
|
+
protocolEra: legacyRequest ? "legacy" : "modern",
|
|
246
|
+
transportSessionIdPresent: Boolean(transportSessionId),
|
|
247
|
+
transportSessionIdPrefix: transportSessionIdPrefix(transportSessionId),
|
|
248
|
+
isInitialize: initializeRequest,
|
|
249
|
+
...mcpRequestDebugFields(req.body),
|
|
250
|
+
});
|
|
251
|
+
if (!legacyRequest) {
|
|
252
|
+
await modernNodeHandler(req, res, req.body);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
231
255
|
let transport;
|
|
232
256
|
if (transportSessionId) {
|
|
233
257
|
transport = transports.get(transportSessionId);
|
|
@@ -237,7 +261,7 @@ export function createHttpServer(config, options, createMcpServer) {
|
|
|
237
261
|
}
|
|
238
262
|
}
|
|
239
263
|
else if (initializeRequest) {
|
|
240
|
-
transport = new
|
|
264
|
+
transport = new NodeStreamableHTTPServerTransport({
|
|
241
265
|
sessionIdGenerator: () => randomUUID(),
|
|
242
266
|
onsessioninitialized: (newTransportSessionId) => {
|
|
243
267
|
if (transport) {
|
|
@@ -261,11 +285,7 @@ export function createHttpServer(config, options, createMcpServer) {
|
|
|
261
285
|
});
|
|
262
286
|
}
|
|
263
287
|
};
|
|
264
|
-
const server =
|
|
265
|
-
taskReminders: sharedTaskReminders,
|
|
266
|
-
remoteWorkspaces: sharedRemoteWorkspaces,
|
|
267
|
-
compositeWorkspaces: sharedCompositeWorkspaces,
|
|
268
|
-
});
|
|
288
|
+
const server = buildMcpServer();
|
|
269
289
|
await server.connect(transport);
|
|
270
290
|
}
|
|
271
291
|
else {
|
|
@@ -294,6 +314,7 @@ export function createHttpServer(config, options, createMcpServer) {
|
|
|
294
314
|
clearInterval(transportCleanupTimer);
|
|
295
315
|
const results = await transports.closeAll();
|
|
296
316
|
logTransportCloseResults("server_shutdown", results);
|
|
317
|
+
await modernMcp.close();
|
|
297
318
|
await sharedRemoteWorkspaces.shutdown();
|
|
298
319
|
processSessions.shutdown();
|
|
299
320
|
await codeIntelligence.shutdown();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
2
|
-
import {
|
|
2
|
+
import { mcpHandlerRequestContext } from "../../../request-context.js";
|
|
3
3
|
import { formatPathForPrompt } from "../../../../workspaces/resources/skills.js";
|
|
4
4
|
import { compositeCapabilityContext } from "../../core/capability-support.js";
|
|
5
5
|
import { compositeWorkspaceLogContext, logToolCall, textBlock } from "../../core/tool-support.js";
|
|
@@ -7,14 +7,13 @@ import { openWorkspaceToolDefinition } from "./workspace-open-schema.js";
|
|
|
7
7
|
import { presentLocalWorkspaceOpen, workspaceTaskUsageInstruction, } from "./workspace-open-presentation.js";
|
|
8
8
|
export function registerOpenWorkspaceTool(options) {
|
|
9
9
|
const { server } = options;
|
|
10
|
-
registerAppTool(server, "open_workspace", openWorkspaceToolDefinition, (args, extra) => handleOpenWorkspace(options, args, extra));
|
|
10
|
+
registerAppTool(server, "open_workspace", openWorkspaceToolDefinition, (args, extra) => handleOpenWorkspace(options, args, mcpHandlerRequestContext(extra)));
|
|
11
11
|
}
|
|
12
|
-
async function handleOpenWorkspace(options, input,
|
|
13
|
-
const { config, workspaces, remoteWorkspaces, compositeWorkspaces, workspaceTasks, processSessions, capabilityRegistry, compositeTaskGuides, loadCompositeMemberContext, rememberWorkspacePanelState, hostScopeIdFor, presentation, } = options;
|
|
12
|
+
async function handleOpenWorkspace(options, input, requestContext) {
|
|
13
|
+
const { config, workspaces, remoteWorkspaces, compositeWorkspaces, workspaceTasks, processSessions, capabilityRegistry, compositeTaskGuides, loadCompositeMemberContext, rememberWorkspacePanelState, hostScopeIdFor, contextDeliveryScopeIdFor, presentation, } = options;
|
|
14
14
|
const { action = "open", memberAction, member, kind, name, memberName, path, relay, workspaceId, mode, baseRef, newWorktree, newWorkspace, context, root, status, state, staleOnly, offset, limit, } = input;
|
|
15
|
-
const { _meta, sessionId } = extra;
|
|
16
15
|
const startedAt = performance.now();
|
|
17
|
-
const conversationScopeId =
|
|
16
|
+
const conversationScopeId = contextDeliveryScopeIdFor(requestContext);
|
|
18
17
|
const protectedWorkspaceIds = processSessions.activeWorkspaceIds();
|
|
19
18
|
const inspectTaskSummary = (targetWorkspaceId) => {
|
|
20
19
|
try {
|
|
@@ -469,7 +468,7 @@ async function handleOpenWorkspace(options, input, extra) {
|
|
|
469
468
|
newWorktree !== undefined || newWorkspace !== undefined) {
|
|
470
469
|
throw new Error("Resuming a relayed Workspace by workspaceId accepts context only.");
|
|
471
470
|
}
|
|
472
|
-
const resumed = await remoteWorkspaces.resumeWorkspace(workspaceId, context ?? "auto", hostScopeIdFor(
|
|
471
|
+
const resumed = await remoteWorkspaces.resumeWorkspace(workspaceId, context ?? "auto", hostScopeIdFor(requestContext));
|
|
473
472
|
rememberWorkspacePanelState(workspaceId, resumed);
|
|
474
473
|
return resumed;
|
|
475
474
|
}
|
|
@@ -483,7 +482,7 @@ async function handleOpenWorkspace(options, input, extra) {
|
|
|
483
482
|
newWorktree,
|
|
484
483
|
newWorkspace,
|
|
485
484
|
context,
|
|
486
|
-
}, hostScopeIdFor(
|
|
485
|
+
}, hostScopeIdFor(requestContext));
|
|
487
486
|
const relayedSkills = Array.isArray(opened.skills)
|
|
488
487
|
? opened.skills
|
|
489
488
|
: [];
|
|
@@ -568,5 +567,10 @@ async function handleOpenWorkspace(options, input, extra) {
|
|
|
568
567
|
rememberWorkspacePanelState(opened.workspaceId, response);
|
|
569
568
|
return response;
|
|
570
569
|
}
|
|
571
|
-
return presentLocalWorkspaceOpen(presentation, input, {
|
|
570
|
+
return presentLocalWorkspaceOpen(presentation, input, {
|
|
571
|
+
conversationScopeId,
|
|
572
|
+
protectedWorkspaceIds,
|
|
573
|
+
startedAt,
|
|
574
|
+
sessionId: requestContext.transportSessionId,
|
|
575
|
+
});
|
|
572
576
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
2
2
|
import * as z from "zod/v4";
|
|
3
|
+
import { mcpHandlerRequestContext } from "../../../request-context.js";
|
|
3
4
|
import { CapabilityError } from "../../core/capability-registry.js";
|
|
4
5
|
import { attachHookReports, runToolWithHooks } from "../../../hooks/hooks.js";
|
|
5
6
|
import { toolNames } from "../../../server-instructions.js";
|
|
@@ -36,8 +37,9 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
36
37
|
openWorldHint: false,
|
|
37
38
|
},
|
|
38
39
|
}, async ({ workspaceId, path }, extra) => {
|
|
40
|
+
const requestContext = mcpHandlerRequestContext(extra);
|
|
39
41
|
if (remoteWorkspaces.has(workspaceId)) {
|
|
40
|
-
return remoteWorkspaces.workspaceInstruction(workspaceId, path, hostScopeIdFor(
|
|
42
|
+
return remoteWorkspaces.workspaceInstruction(workspaceId, path, hostScopeIdFor(requestContext));
|
|
41
43
|
}
|
|
42
44
|
if (compositeWorkspaces.has(workspaceId)) {
|
|
43
45
|
throw new Error("Composite Workspace instructions belong to a selected member; open that member context before viewing its instruction files.");
|
|
@@ -91,6 +93,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
91
93
|
openWorldHint: true,
|
|
92
94
|
},
|
|
93
95
|
}, async ({ workspaceId, member, name, action, arguments: capabilityArguments, file }, extra) => {
|
|
96
|
+
const requestContext = mcpHandlerRequestContext(extra);
|
|
94
97
|
if (name === "workspace.tasks" && compositeWorkspaces.has(workspaceId)) {
|
|
95
98
|
if (member !== undefined) {
|
|
96
99
|
throw new Error(`workspace.tasks belongs to Composite Workspace ${workspaceId} itself and does not accept member.`);
|
|
@@ -105,9 +108,9 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
105
108
|
if (action === "run") {
|
|
106
109
|
const execution = await capabilityRegistry.run(name, capabilityArguments ?? {}, context, {
|
|
107
110
|
nativeFile: file,
|
|
108
|
-
signal:
|
|
109
|
-
requestMeta:
|
|
110
|
-
sessionId:
|
|
111
|
+
signal: requestContext.signal,
|
|
112
|
+
requestMeta: requestContext.requestMeta,
|
|
113
|
+
sessionId: requestContext.transportSessionId,
|
|
111
114
|
});
|
|
112
115
|
const result = {
|
|
113
116
|
content: [textBlock(`Capability ${name} completed.\n${JSON.stringify(execution.value, null, 2)}`)],
|
|
@@ -146,7 +149,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
146
149
|
return result;
|
|
147
150
|
}
|
|
148
151
|
catch (error) {
|
|
149
|
-
if (
|
|
152
|
+
if (requestContext.signal.aborted)
|
|
150
153
|
throw error;
|
|
151
154
|
const capabilityError = error instanceof CapabilityError
|
|
152
155
|
? error
|
|
@@ -171,16 +174,16 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
171
174
|
}
|
|
172
175
|
const target = resolveExecutionTarget(workspaceId, member);
|
|
173
176
|
const executionWorkspaceId = target.executionWorkspaceId;
|
|
174
|
-
const executionContext = await prepareExecutionContext(target,
|
|
177
|
+
const executionContext = await prepareExecutionContext(target, requestContext);
|
|
175
178
|
if (remoteWorkspaces.has(executionWorkspaceId)) {
|
|
176
179
|
const response = await remoteWorkspaces.capability(executionWorkspaceId, {
|
|
177
180
|
name,
|
|
178
181
|
action,
|
|
179
182
|
...(capabilityArguments !== undefined ? { arguments: capabilityArguments } : {}),
|
|
180
183
|
...(file !== undefined ? { file } : {}),
|
|
181
|
-
}, hostScopeIdFor(
|
|
184
|
+
}, hostScopeIdFor(requestContext));
|
|
182
185
|
return action === "run" && name !== "workspace.tasks"
|
|
183
|
-
? presentSemanticWorkResult(response, target, hostScopeIdFor(
|
|
186
|
+
? presentSemanticWorkResult(response, target, hostScopeIdFor(requestContext))
|
|
184
187
|
: presentExecutionResult(response, target);
|
|
185
188
|
}
|
|
186
189
|
if (action === "run" && name === "batch.execute") {
|
|
@@ -189,9 +192,9 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
189
192
|
try {
|
|
190
193
|
const execution = await capabilityRegistry.run(name, capabilityArguments ?? {}, capabilityContextFor(workspace), {
|
|
191
194
|
nativeFile: file,
|
|
192
|
-
signal:
|
|
193
|
-
requestMeta:
|
|
194
|
-
sessionId:
|
|
195
|
+
signal: requestContext.signal,
|
|
196
|
+
requestMeta: requestContext.requestMeta,
|
|
197
|
+
sessionId: requestContext.transportSessionId,
|
|
195
198
|
});
|
|
196
199
|
const result = {
|
|
197
200
|
content: [textBlock(`Capability ${name} completed.\n${JSON.stringify(execution.value, null, 2)}`)],
|
|
@@ -199,16 +202,16 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
199
202
|
};
|
|
200
203
|
logToolCall(config, {
|
|
201
204
|
tool: toolNames.capability,
|
|
202
|
-
...workspaceLogContext(workspace,
|
|
205
|
+
...workspaceLogContext(workspace, requestContext.transportSessionId),
|
|
203
206
|
capability: name,
|
|
204
207
|
action,
|
|
205
208
|
success: true,
|
|
206
209
|
durationMs: Math.round(performance.now() - startedAt),
|
|
207
210
|
});
|
|
208
|
-
return presentSemanticWorkResult(result, target, hostScopeIdFor(
|
|
211
|
+
return presentSemanticWorkResult(result, target, hostScopeIdFor(requestContext));
|
|
209
212
|
}
|
|
210
213
|
catch (error) {
|
|
211
|
-
if (
|
|
214
|
+
if (requestContext.signal.aborted)
|
|
212
215
|
throw error;
|
|
213
216
|
const capabilityError = error instanceof CapabilityError
|
|
214
217
|
? error
|
|
@@ -224,7 +227,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
224
227
|
};
|
|
225
228
|
logFailedToolResponse(config, {
|
|
226
229
|
tool: toolNames.capability,
|
|
227
|
-
...workspaceLogContext(workspace,
|
|
230
|
+
...workspaceLogContext(workspace, requestContext.transportSessionId),
|
|
228
231
|
capability: name,
|
|
229
232
|
action,
|
|
230
233
|
}, result.content, startedAt);
|
|
@@ -235,11 +238,11 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
235
238
|
const response = await coreOperations.capabilityRun({ workspaceId: executionWorkspaceId, name, arguments: capabilityArguments, file }, executionContext);
|
|
236
239
|
return name === "workspace.tasks"
|
|
237
240
|
? presentExecutionResult(response, target)
|
|
238
|
-
: presentSemanticWorkResult(response, target, hostScopeIdFor(
|
|
241
|
+
: presentSemanticWorkResult(response, target, hostScopeIdFor(requestContext));
|
|
239
242
|
}
|
|
240
243
|
const workspace = workspaces.getWorkspace(executionWorkspaceId);
|
|
241
|
-
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(
|
|
242
|
-
signal:
|
|
244
|
+
return runActivityToolWithHooks(activityLifecycle, hooks, workspace, hostScopeIdFor(requestContext), activityRequestFor({ workspaceId: executionWorkspaceId, name, action, arguments: capabilityArguments, file }, executionContext), {
|
|
245
|
+
signal: requestContext.signal,
|
|
243
246
|
tool: toolNames.capability,
|
|
244
247
|
invocation: workspaceHookInvocation(workspace),
|
|
245
248
|
payload: { name, action },
|
|
@@ -332,6 +335,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
332
335
|
_meta: {},
|
|
333
336
|
annotations: WRITE_TOOL_ANNOTATIONS,
|
|
334
337
|
}, async ({ workspaceId, action = "close", commitMessage }, extra) => {
|
|
338
|
+
const requestContext = mcpHandlerRequestContext(extra);
|
|
335
339
|
if (compositeWorkspaces.has(workspaceId)) {
|
|
336
340
|
const startedAt = performance.now();
|
|
337
341
|
if (commitMessage !== undefined) {
|
|
@@ -392,7 +396,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
392
396
|
};
|
|
393
397
|
}
|
|
394
398
|
if (remoteWorkspaces.has(workspaceId)) {
|
|
395
|
-
const response = await remoteWorkspaces.closeWorkspace(workspaceId, { action, ...(commitMessage !== undefined ? { commitMessage } : {}) }, hostScopeIdFor(
|
|
399
|
+
const response = await remoteWorkspaces.closeWorkspace(workspaceId, { action, ...(commitMessage !== undefined ? { commitMessage } : {}) }, hostScopeIdFor(requestContext));
|
|
396
400
|
if (action === "delete") {
|
|
397
401
|
activityQueries.deleteWorkspaceHistory(config.stateDir, workspaceId);
|
|
398
402
|
}
|
|
@@ -409,7 +413,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
409
413
|
throw new Error(`Workspace ${session.id} still owns a running process. Poll, interrupt, or wait for it before deleting this Workspace.`);
|
|
410
414
|
}
|
|
411
415
|
const response = await runToolWithHooks(hooks, {
|
|
412
|
-
signal:
|
|
416
|
+
signal: requestContext.signal,
|
|
413
417
|
tool: toolNames.closeWorkspace,
|
|
414
418
|
invocation: {
|
|
415
419
|
workspaceId: session.id,
|
|
@@ -428,7 +432,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
428
432
|
const result = `Deleted ForgeRelay Workspace ${session.id}. Physical project files were not removed.`;
|
|
429
433
|
logToolCall(config, {
|
|
430
434
|
tool: toolNames.closeWorkspace,
|
|
431
|
-
...workspaceLogContext(session,
|
|
435
|
+
...workspaceLogContext(session, requestContext.transportSessionId),
|
|
432
436
|
action: "delete",
|
|
433
437
|
path: session.root,
|
|
434
438
|
success: true,
|
|
@@ -463,7 +467,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
463
467
|
}
|
|
464
468
|
const hookRoot = session.sourceRoot ?? session.root;
|
|
465
469
|
const response = await runToolWithHooks(hooks, {
|
|
466
|
-
signal:
|
|
470
|
+
signal: requestContext.signal,
|
|
467
471
|
tool: toolNames.closeWorkspace,
|
|
468
472
|
invocation: {
|
|
469
473
|
workspaceId: session.id,
|
|
@@ -509,7 +513,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
509
513
|
}
|
|
510
514
|
const workspace = workspaces.getWorkspace(session.id);
|
|
511
515
|
const response = await runToolWithHooks(hooks, {
|
|
512
|
-
signal:
|
|
516
|
+
signal: requestContext.signal,
|
|
513
517
|
tool: toolNames.closeWorkspace,
|
|
514
518
|
invocation: workspaceHookInvocation(workspace),
|
|
515
519
|
payload: { workspaceId: workspace.id, action, commitMessage, mode: workspace.mode },
|
|
@@ -558,7 +562,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
558
562
|
].join("\n");
|
|
559
563
|
logToolCall(config, {
|
|
560
564
|
tool: toolNames.closeWorkspace,
|
|
561
|
-
...workspaceLogContext(workspace,
|
|
565
|
+
...workspaceLogContext(workspace, requestContext.transportSessionId),
|
|
562
566
|
action,
|
|
563
567
|
path: closed.sourceRoot,
|
|
564
568
|
success: true,
|
|
@@ -610,7 +614,7 @@ export function registerWorkspaceAuxiliaryTools(options) {
|
|
|
610
614
|
const result = `Closed checkout-backed Workspace ${checkoutWorkspaceId}; its ForgeRelay identity was preserved for later reopen. Physical project files were not removed.`;
|
|
611
615
|
logToolCall(config, {
|
|
612
616
|
tool: toolNames.closeWorkspace,
|
|
613
|
-
...workspaceLogContext(workspace,
|
|
617
|
+
...workspaceLogContext(workspace, requestContext.transportSessionId),
|
|
614
618
|
action: "close",
|
|
615
619
|
path: workspace.root,
|
|
616
620
|
success: true,
|