Files
oh-my-pi/packages/coding-agent/test/issue-956-repro.test.ts
T
can1357 7272907c33 fix(coding-agent): /mcp test enumerates connected servers
Interactive /mcp test only consulted getMCPConfigPath("user"|"project")
configs and missed servers defined in standalone .mcp.json. /mcp reauth
already resolved through #findConfiguredServer, which includes that
fallback path. Route /mcp test through the same resolver so both
commands enumerate the same set of servers.

Fixes #956
2026-05-09 03:11:19 +02:00

107 lines
3.3 KiB
TypeScript

import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "bun:test";
import * as fs from "node:fs/promises";
import * as os from "node:os";
import * as path from "node:path";
import { getConfigRootDir, getProjectDir, setAgentDir, setProjectDir } from "@oh-my-pi/pi-utils";
import * as mcpClient from "../src/mcp/client";
import { MCPCommandController } from "../src/modes/controllers/mcp-command-controller";
import { initTheme } from "../src/modes/theme/theme";
const originalProjectDir = getProjectDir();
const originalAgentDir = process.env.PI_CODING_AGENT_DIR;
const fallbackAgentDir = path.join(getConfigRootDir(), "agent");
describe("issue #956: interactive /mcp test", () => {
let projectDir = "";
let agentDir = "";
beforeAll(() => {
initTheme();
});
beforeEach(async () => {
projectDir = await fs.mkdtemp(path.join(os.tmpdir(), "omp-issue-956-project-"));
agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "omp-issue-956-agent-"));
setProjectDir(projectDir);
setAgentDir(agentDir);
await fs.writeFile(
path.join(projectDir, ".mcp.json"),
JSON.stringify(
{
mcpServers: {
github: {
type: "stdio",
command: "github-mcp-server",
args: ["serve"],
},
},
},
null,
2,
),
);
});
afterEach(async () => {
vi.restoreAllMocks();
setProjectDir(originalProjectDir);
if (originalAgentDir) {
setAgentDir(originalAgentDir);
} else {
setAgentDir(fallbackAgentDir);
delete process.env.PI_CODING_AGENT_DIR;
}
await fs.rm(projectDir, { recursive: true, force: true });
await fs.rm(agentDir, { recursive: true, force: true });
});
it("tests a connected server discovered from standalone .mcp.json", async () => {
const transport = {
connected: true,
request: vi.fn(),
notify: vi.fn(),
close: vi.fn(async () => {}),
};
const connection = {
name: "github",
config: { type: "stdio" as const, command: "github-mcp-server", args: ["serve"] },
transport,
serverInfo: { name: "GitHub MCP", version: "1.0.0" },
capabilities: {},
};
const showError = vi.fn();
const showStatus = vi.fn();
const requestRender = vi.fn();
const addChild = vi.fn();
const refreshMCPTools = vi.fn();
const connectToServer = vi.spyOn(mcpClient, "connectToServer").mockResolvedValue(connection);
const listTools = vi.spyOn(mcpClient, "listTools").mockResolvedValue([{ name: "search_issues" }] as never);
const disconnectServer = vi.spyOn(mcpClient, "disconnectServer").mockResolvedValue();
const controller = new MCPCommandController({
chatContainer: { addChild },
ui: { requestRender },
editor: {},
showError,
showStatus,
session: { refreshMCPTools },
mcpManager: {
prepareConfig: vi.fn(async config => config),
getConnectionStatus: vi.fn(() => "connected"),
},
} as never);
await controller.handle("/mcp test github");
expect(showError).not.toHaveBeenCalled();
expect(connectToServer).toHaveBeenCalledWith(
"github",
expect.objectContaining({ command: "github-mcp-server", args: ["serve"] }),
expect.objectContaining({ signal: expect.any(AbortSignal) }),
);
expect(listTools).toHaveBeenCalledWith(connection, expect.objectContaining({ signal: expect.any(AbortSignal) }));
expect(disconnectServer).toHaveBeenCalledWith(connection);
expect(requestRender).toHaveBeenCalled();
});
});