Skip to content

Commit fa7855a

Browse files
committed
fix(xcode-ide): route CLI gateway tools via daemon
1 parent e656580 commit fa7855a

File tree

8 files changed

+16
-10
lines changed

8 files changed

+16
-10
lines changed

docs/TOOLS-CLI.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,4 +206,4 @@ XcodeBuildMCP provides 76 canonical tools organized into 14 workflow groups.
206206

207207
---
208208

209-
*This documentation is automatically generated by `scripts/update-tools-docs.ts` from the tools manifest. Last updated: 2026-03-07T20:50:55.840Z UTC*
209+
*This documentation is automatically generated by `scripts/update-tools-docs.ts` from the tools manifest. Last updated: 2026-03-16T20:47:13.697Z UTC*

docs/TOOLS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,4 @@ This document lists MCP tool names as exposed to MCP clients. XcodeBuildMCP prov
222222

223223
---
224224

225-
*This documentation is automatically generated by `scripts/update-tools-docs.ts` from the tools manifest. Last updated: 2026-03-07T20:50:55.840Z UTC*
225+
*This documentation is automatically generated by `scripts/update-tools-docs.ts` from the tools manifest. Last updated: 2026-03-16T20:47:13.697Z UTC*

manifests/tools/xcode_ide_call_tool.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ names:
44
mcp: xcode_ide_call_tool
55
cli: call-tool
66
description: Call a remote Xcode IDE MCP tool.
7-
predicates:
8-
- mcpRuntimeOnly
7+
routing:
8+
stateful: true
99
annotations:
1010
title: Call Xcode IDE Tool
1111
readOnlyHint: false

manifests/tools/xcode_ide_list_tools.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ names:
44
mcp: xcode_ide_list_tools
55
cli: list-tools
66
description: "Lists Xcode-IDE-only MCP capabilities (Use for: SwiftUI previews image capture, code snippet execution, issue Navigator/build logs, and window/tab context)."
7-
predicates:
8-
- mcpRuntimeOnly
7+
routing:
8+
stateful: true
99
annotations:
1010
title: List Xcode IDE Tools
1111
readOnlyHint: true

manifests/workflows/xcode-ide.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ id: xcode-ide
22
title: Xcode IDE Integration
33
description: Bridge tools for connecting to Xcode's built-in MCP server (mcpbridge) to access IDE-specific functionality.
44
availability:
5-
cli: false
5+
cli: true
66
predicates:
77
- hideWhenXcodeAgentMode
88
tools:

src/core/manifest/__tests__/load-manifest.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ describe('load-manifest', () => {
9494
expect(xcodeIde?.predicates).not.toContain('debugEnabled');
9595
});
9696

97-
it('should keep xcode bridge debug tools gated by debugEnabled', () => {
97+
it('should keep xcode bridge gateway tools daemon-routed and debug tools gated', () => {
9898
const manifest = loadManifest();
9999

100-
expect(manifest.tools.get('xcode_ide_list_tools')?.predicates).toContain('mcpRuntimeOnly');
101-
expect(manifest.tools.get('xcode_ide_call_tool')?.predicates).toContain('mcpRuntimeOnly');
100+
expect(manifest.tools.get('xcode_ide_list_tools')?.routing?.stateful).toBe(true);
101+
expect(manifest.tools.get('xcode_ide_call_tool')?.routing?.stateful).toBe(true);
102102
expect(manifest.tools.get('xcode_tools_bridge_status')?.predicates).toContain('debugEnabled');
103103
expect(manifest.tools.get('xcode_tools_bridge_sync')?.predicates).toContain('debugEnabled');
104104
expect(manifest.tools.get('xcode_tools_bridge_disconnect')?.predicates).toContain(

src/integrations/xcode-tools-bridge/standalone.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ export class StandaloneXcodeToolsBridge {
8484
} catch (error) {
8585
const message = error instanceof Error ? error.message : String(error);
8686
return createErrorResponse(classifyBridgeError(error, 'list'), message);
87+
} finally {
88+
await this.service.disconnect();
8789
}
8890
}
8991

@@ -100,6 +102,8 @@ export class StandaloneXcodeToolsBridge {
100102
} catch (error) {
101103
const message = error instanceof Error ? error.message : String(error);
102104
return createErrorResponse(classifyBridgeError(error, 'call'), message);
105+
} finally {
106+
await this.service.disconnect();
103107
}
104108
}
105109
}

src/mcp/tools/xcode-ide/__tests__/bridge_tools.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,13 @@ describe('xcode-ide bridge tools (standalone fallback)', () => {
108108
expect(payload.toolCount).toBe(2);
109109
expect(payload.tools).toHaveLength(2);
110110
expect(clientMocks.listTools).toHaveBeenCalledOnce();
111+
expect(clientMocks.disconnect).toHaveBeenCalledOnce();
111112
});
112113

113114
it('call handler forwards remote tool calls without MCP server instance', async () => {
114115
const result = await callHandler({ remoteTool: 'toolA', arguments: { foo: 'bar' } });
115116
expect(result.isError).toBe(false);
116117
expect(clientMocks.callTool).toHaveBeenCalledWith('toolA', { foo: 'bar' }, {});
118+
expect(clientMocks.disconnect).toHaveBeenCalledOnce();
117119
});
118120
});

0 commit comments

Comments
 (0)