xcode-copilot-server 3.4.1 → 3.4.2
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/config.json5 +2 -4
- package/package.json +2 -3
- package/scripts/mcpbridge-proxy.mjs +0 -73
package/config.json5
CHANGED
|
@@ -13,12 +13,10 @@
|
|
|
13
13
|
toolBridge: false,
|
|
14
14
|
|
|
15
15
|
mcpServers: {
|
|
16
|
-
// Proxies Apple's xcrun mcpbridge (Xcode 26.3+). The script exits
|
|
17
|
-
// gracefully if mcpbridge isn't installed, so safe to leave enabled.
|
|
18
16
|
xcode: {
|
|
19
17
|
type: "local",
|
|
20
|
-
command: "
|
|
21
|
-
args: ["
|
|
18
|
+
command: "xcrun",
|
|
19
|
+
args: ["mcpbridge"],
|
|
22
20
|
allowedTools: ["*"],
|
|
23
21
|
},
|
|
24
22
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xcode-copilot-server",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.2",
|
|
4
4
|
"description": "OpenAI-compatible proxy API server for Xcode, powered by GitHub Copilot",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"dist/",
|
|
19
|
-
"config.json5"
|
|
20
|
-
"scripts/"
|
|
19
|
+
"config.json5"
|
|
21
20
|
],
|
|
22
21
|
"scripts": {
|
|
23
22
|
"build": "tsc",
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* MCP stdio proxy for Apple's `xcrun mcpbridge`.
|
|
5
|
-
*
|
|
6
|
-
* mcpbridge declares output schemas on its tools but returns
|
|
7
|
-
* results via the `content` field (text array) without the corresponding
|
|
8
|
-
* `structuredContent` field that the MCP spec requires. The Copilot CLI
|
|
9
|
-
* enforces this strictly and rejects the response with error -32600.
|
|
10
|
-
*
|
|
11
|
-
* So, intercept every JSON-RPC response from mcpbridge. When a response
|
|
12
|
-
* carries `content` but no `structuredContent`, synthesise it from the
|
|
13
|
-
* first text content item — parsing as JSON when possible, falling back
|
|
14
|
-
* to a `{ text }` wrapper otherwise.
|
|
15
|
-
*
|
|
16
|
-
* Source: https://rudrank.com/exploring-xcode-using-mcp-tools-cursor-external-clients
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import { spawn, execFile } from "node:child_process";
|
|
20
|
-
import { createInterface } from "node:readline";
|
|
21
|
-
import { promisify } from "node:util";
|
|
22
|
-
|
|
23
|
-
const execFileAsync = promisify(execFile);
|
|
24
|
-
|
|
25
|
-
function patchIfNeeded(msg) {
|
|
26
|
-
const result = msg.result;
|
|
27
|
-
if (!result || typeof result !== "object") return;
|
|
28
|
-
if (!Array.isArray(result.content) || result.content.length === 0) return;
|
|
29
|
-
if (result.structuredContent !== undefined) return;
|
|
30
|
-
|
|
31
|
-
const textItem = result.content.find((c) => c.type === "text");
|
|
32
|
-
if (!textItem?.text) return;
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
result.structuredContent = JSON.parse(textItem.text);
|
|
36
|
-
} catch {
|
|
37
|
-
result.structuredContent = { text: textItem.text };
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
try {
|
|
42
|
-
await execFileAsync("xcrun", ["--find", "mcpbridge"]);
|
|
43
|
-
} catch (err) {
|
|
44
|
-
console.error(
|
|
45
|
-
"Error: xcrun mcpbridge not found. This requires Xcode 26.3 or later."
|
|
46
|
-
);
|
|
47
|
-
console.error(
|
|
48
|
-
"Please install Xcode 26.3+ or remove the 'xcode' MCP server from config.json5"
|
|
49
|
-
);
|
|
50
|
-
process.exit(1);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const bridge = spawn("xcrun", ["mcpbridge", ...process.argv.slice(2)], {
|
|
54
|
-
stdio: ["pipe", "pipe", "inherit"],
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
process.stdin.pipe(bridge.stdin);
|
|
58
|
-
|
|
59
|
-
const reader = createInterface({ input: bridge.stdout, crlfDelay: Infinity });
|
|
60
|
-
|
|
61
|
-
reader.on("line", (line) => {
|
|
62
|
-
try {
|
|
63
|
-
const msg = JSON.parse(line);
|
|
64
|
-
patchIfNeeded(msg);
|
|
65
|
-
process.stdout.write(JSON.stringify(msg) + "\n");
|
|
66
|
-
} catch {
|
|
67
|
-
process.stdout.write(line + "\n");
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
bridge.on("exit", (code) => process.exit(code ?? 0));
|
|
72
|
-
process.on("SIGTERM", () => bridge.kill("SIGTERM"));
|
|
73
|
-
process.on("SIGINT", () => bridge.kill("SIGINT"));
|