summaryrefslogtreecommitdiffhomepage
path: root/packages/mcp/src/config.test.ts
blob: 38c9b5088be99084139095aab34dcf3060db9288 (plain)
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"]);
	});
});