1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
import { describe, expect, it } from "vitest";
import { resolveServers } from "./config.js";
describe("resolveServers", () => {
it("resolves from .dispatch/mcp.json", () => {
const dispatchConfig = JSON.stringify({
servers: {
freecad: { command: "uvx", args: ["freecad-mcp"], env: { KEY: "val" } },
},
});
const result = resolveServers({ dispatchMcpJson: dispatchConfig, opencodeJson: null });
expect(result.servers.length).toBe(1);
expect(result.servers[0].id).toBe("freecad");
expect(result.servers[0].command).toEqual(["uvx", "freecad-mcp"]);
expect(result.servers[0].env).toEqual({ KEY: "val" });
expect(result.servers[0].configSource).toBe(".dispatch/mcp.json");
expect(result.shadowed).toBe(false);
});
it("falls back to opencode.json mcp key", () => {
const opencodeConfig = JSON.stringify({
mcp: {
chrome: { command: "npx", args: ["chrome-devtools-mcp@latest"] },
},
});
const result = resolveServers({ dispatchMcpJson: null, opencodeJson: opencodeConfig });
expect(result.servers.length).toBe(1);
expect(result.servers[0].id).toBe("chrome");
expect(result.servers[0].command).toEqual(["npx", "chrome-devtools-mcp@latest"]);
expect(result.servers[0].configSource).toBe("opencode.json");
expect(result.shadowed).toBe(false);
});
it("shadow warning when both present", () => {
const dispatchConfig = JSON.stringify({
servers: {
freecad: { command: "uvx", args: ["freecad-mcp"] },
},
});
const opencodeConfig = JSON.stringify({
mcp: {
chrome: { command: "npx", args: ["chrome-devtools-mcp@latest"] },
},
});
const result = resolveServers({
dispatchMcpJson: dispatchConfig,
opencodeJson: opencodeConfig,
});
expect(result.servers.length).toBe(1);
expect(result.servers[0].id).toBe("freecad");
expect(result.shadowed).toBe(true);
});
it("empty when neither present", () => {
const result = resolveServers({ dispatchMcpJson: null, opencodeJson: null });
expect(result.servers.length).toBe(0);
expect(result.shadowed).toBe(false);
});
it("empty when dispatch has no servers key", () => {
const result = resolveServers({
dispatchMcpJson: JSON.stringify({}),
opencodeJson: null,
});
expect(result.servers.length).toBe(0);
expect(result.shadowed).toBe(false);
});
it("handles malformed JSON gracefully", () => {
const result = resolveServers({
dispatchMcpJson: "not valid json",
opencodeJson: "{ also bad",
});
expect(result.servers.length).toBe(0);
expect(result.shadowed).toBe(false);
});
it("server without args", () => {
const dispatchConfig = JSON.stringify({
servers: {
simple: { command: "my-server" },
},
});
const result = resolveServers({ dispatchMcpJson: dispatchConfig, opencodeJson: null });
expect(result.servers.length).toBe(1);
expect(result.servers[0].command).toEqual(["my-server"]);
});
it("multiple servers from dispatch", () => {
const dispatchConfig = JSON.stringify({
servers: {
a: { command: "server-a" },
b: { command: "server-b", args: ["--port", "3000"] },
},
});
const result = resolveServers({ dispatchMcpJson: dispatchConfig, opencodeJson: null });
expect(result.servers.length).toBe(2);
const ids = result.servers.map((s) => s.id).sort();
expect(ids).toEqual(["a", "b"]);
});
});
|