Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 54 additions & 5 deletions apps/desktop/src/main/__tests__/mcp-runtime-e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,13 @@ test('MCP tools stay bound to the connection generation that advertised them', a
);
// The published descriptor carries the real MCP identity: the Host
// re-proxies it to the same mcp__fixture__echo model-facing name.
assert.deepEqual(provider.offers()[0]?.tools[0] && {
serverId: provider.offers()[0]?.tools[0]?.serverId,
name: provider.offers()[0]?.tools[0]?.name,
inputSchema: provider.offers()[0]?.tools[0]?.inputSchema,
const publishedEcho = provider.offers()
.flatMap(({ tools }) => tools)
.find(({ serverId, name }) => serverId === 'fixture' && name === 'echo');
assert.deepEqual(publishedEcho && {
serverId: publishedEcho.serverId,
name: publishedEcho.name,
inputSchema: publishedEcho.inputSchema,
}, {
serverId: 'fixture',
name: 'echo',
Expand All @@ -87,6 +90,23 @@ test('MCP tools stay bound to the connection generation that advertised them', a
properties: { value: { type: 'string' } },
},
});
const publishedAnnotated = provider.offers()
.flatMap(({ tools }) => tools)
.find(({ serverId, name }) => serverId === 'fixture' && name === 'annotated');
assert.deepEqual(publishedAnnotated && {
serverId: publishedAnnotated.serverId,
name: publishedAnnotated.name,
inputSchema: publishedAnnotated.inputSchema,
}, {
serverId: 'fixture',
name: 'annotated',
inputSchema: {
type: 'object',
properties: { value: { type: 'string' } },
patternProperties: { '^tag:': { type: 'string' } },
additionalItems: { type: 'integer' },
},
});
if (!provider.call) throw new Error('Expected a callable Desktop capability provider');
assert.throws(
() => provider.call!(
Expand All @@ -96,7 +116,7 @@ test('MCP tools stay bound to the connection generation that advertised them', a
registrationId: 'registration-1',
offerId: 'desktop_mcp_fixture',
serverId: 'fixture',
toolName: 'annotated',
toolName: 'missing',
arguments: {},
sessionId: 'session',
turnId: 'turn',
Expand All @@ -111,6 +131,35 @@ test('MCP tools stay bound to the connection generation that advertised them', a
),
/not offered/u,
);
let annotatedAdmissionEvidence: unknown;
assert.deepEqual(
await provider.call(
{
kind: 'client.capability.call',
invocationId: 'annotated-invocation',
registrationId: 'registration-1',
offerId: 'desktop_mcp_fixture',
serverId: 'fixture',
toolName: 'annotated',
arguments: { fallback: 'desktop-capability' },
sessionId: 'session',
turnId: 'turn',
toolCallId: 'annotated-capability-call',
cwd: process.cwd(),
},
{
signal: new AbortController().signal,
accept: async (evidence) => {
annotatedAdmissionEvidence = evidence;
},
requestInteraction: async () => assert.fail('Unexpected provider interaction'),
},
),
{
content: [{ type: 'text', text: 'annotated:desktop-capability' }],
},
);
assert.deepEqual(annotatedAdmissionEvidence, { kind: 'none' });
let admissionEvidence: unknown;
assert.deepEqual(
await provider.call(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -567,15 +567,63 @@ test('closes the claimed Host connection when native capability construction fai
releaseComputerUseSession() {},
}),
),
// The desktop-local schema check moved into the shared protocol decoder,
// which rejects a non-object tool schema root with its own wording.
/tool schema root must be an object/,
);

assert.equal(ipc.size, 0);
assert.equal(host.closeCalls, 1);
});

test('isolates an invalid dynamic MCP tool without dropping the Host connection', async () => {
// Per-tool isolation: one bad tool is skipped and the provider still
// constructs, so the Host connection stays alive.
const ipc = ipcHarness();
const host = connectionHarness('invalid-capability');
const invalidTool = {
...nativeTool(),
parameters: z.string(),
} as unknown as MakaTool;
const healthyTool = {
...nativeTool(),
name: 'healthy_mcp',
impl: async () => 'healthy',
};

const candidate = await createDesktopRuntimeHostCandidate(
host.connection,
deps(ipc, {
browserTools: [],
resolveBrowserUrl: () => 'https://example.com/',
releaseBrowserSession() {},
computerUseTools: emptyComputerUseTools(),
releaseComputerUseSession() {},
additionalGroups: () => [
{
offerId: 'desktop_mcp',
label: 'MCP',
description: 'MCP tools',
tools: [invalidTool, healthyTool],
},
],
}),
);

assert.equal(host.capabilityRegistrations, 1);
assert.equal(host.closeCalls, 0);
assert.deepEqual(
await host.invokeCapability({
...capabilityFrame('session-invalid-capability'),
offerId: 'desktop_mcp',
serverId: 'desktop_mcp',
toolName: 'healthy_mcp',
}),
{ content: [{ type: 'text', text: 'healthy' }] },
);

await candidate.close();
assert.equal(host.closeCalls, 1);
});

test('does not release or report a Revision the Host retained during cleanup', async () => {
const ipc = ipcHarness();
const host = connectionHarness('retained-revision', { revisionAbandon: 'retained' });
Expand Down
Loading