


























@@ -1,31 +1,21 @@
1-import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2-import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
31import { afterEach, describe, expect, it, vi } from "vitest";
42import type { AnyAgentTool } from "../agents/tools/common.js";
53import {
64initializeGlobalHookRunner,
75resetGlobalHookRunner,
86} from "../plugins/hook-runner-global.js";
97import { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js";
10-import { createPluginToolsMcpServer } from "./plugin-tools-serve.js";
8+import { createPluginToolsMcpHandlers } from "./plugin-tools-handlers.js";
11912-async function connectPluginToolsServer(tools: AnyAgentTool[]) {
13-const server = createPluginToolsMcpServer({ tools });
14-const client = new Client({ name: "plugin-tools-test-client", version: "1.0.0" });
15-const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
16-await server.connect(serverTransport);
17-await client.connect(clientTransport);
18-return {
19- client,
20-close: async () => {
21-await client.close();
22-await server.close();
23-},
24-};
25-}
10+const callGatewayTool = vi.hoisted(() => vi.fn());
11+12+vi.mock("../agents/tools/gateway.js", () => ({
13+ callGatewayTool,
14+}));
26152716afterEach(() => {
2817vi.restoreAllMocks();
18+callGatewayTool.mockReset();
2919resetGlobalHookRunner();
3020});
3121@@ -47,36 +37,32 @@ describe("plugin tools MCP server", () => {
4737 execute,
4838} as unknown as AnyAgentTool;
493950-const session = await connectPluginToolsServer([tool]);
51-try {
52-const listed = await session.client.listTools();
53-expect(listed.tools).toEqual([
54-expect.objectContaining({
55-name: "memory_recall",
56-description: "Recall stored memory",
57-inputSchema: expect.objectContaining({
58-type: "object",
59-required: ["query"],
60-}),
40+const handlers = createPluginToolsMcpHandlers([tool]);
41+const listed = await handlers.listTools();
42+expect(listed.tools).toEqual([
43+expect.objectContaining({
44+name: "memory_recall",
45+description: "Recall stored memory",
46+inputSchema: expect.objectContaining({
47+type: "object",
48+required: ["query"],
6149}),
62-]);
50+}),
51+]);
635264-const result = await session.client.callTool({
65-name: "memory_recall",
66-arguments: { query: "remember this" },
67-});
68-expect(execute).toHaveBeenCalledWith(
69-expect.stringMatching(/^mcp-\d+$/),
70-{
71-query: "remember this",
72-},
73-undefined,
74-undefined,
75-);
76-expect(result.content).toEqual([{ type: "text", text: "Stored." }]);
77-} finally {
78-await session.close();
79-}
53+const result = await handlers.callTool({
54+name: "memory_recall",
55+arguments: { query: "remember this" },
56+});
57+expect(execute).toHaveBeenCalledWith(
58+expect.stringMatching(/^mcp-\d+$/),
59+{
60+query: "remember this",
61+},
62+undefined,
63+undefined,
64+);
65+expect(result.content).toEqual([{ type: "text", text: "Stored." }]);
8066});
81678268it("returns MCP errors for unknown tools and thrown tool errors", async () => {
@@ -87,24 +73,20 @@ describe("plugin tools MCP server", () => {
8773execute: vi.fn().mockRejectedValue(new Error("boom")),
8874} as unknown as AnyAgentTool;
897590-const session = await connectPluginToolsServer([failingTool]);
91-try {
92-const unknown = await session.client.callTool({
93-name: "missing_tool",
94-arguments: {},
95-});
96-expect(unknown.isError).toBe(true);
97-expect(unknown.content).toEqual([{ type: "text", text: "Unknown tool: missing_tool" }]);
76+const handlers = createPluginToolsMcpHandlers([failingTool]);
77+const unknown = await handlers.callTool({
78+name: "missing_tool",
79+arguments: {},
80+});
81+expect(unknown.isError).toBe(true);
82+expect(unknown.content).toEqual([{ type: "text", text: "Unknown tool: missing_tool" }]);
988399-const failed = await session.client.callTool({
100-name: "memory_forget",
101-arguments: {},
102-});
103-expect(failed.isError).toBe(true);
104-expect(failed.content).toEqual([{ type: "text", text: "Tool error: boom" }]);
105-} finally {
106-await session.close();
107-}
84+const failed = await handlers.callTool({
85+name: "memory_forget",
86+arguments: {},
87+});
88+expect(failed.isError).toBe(true);
89+expect(failed.content).toEqual([{ type: "text", text: "Tool error: boom" }]);
10890});
1099111092it("blocks tool execution when before_tool_call requires approval on the MCP bridge", async () => {
@@ -129,27 +111,24 @@ describe("plugin tools MCP server", () => {
129111},
130112]),
131113);
114+callGatewayTool.mockRejectedValueOnce(new Error("gateway unavailable"));
132115const tool = {
133116name: "memory_store",
134117description: "Store memory",
135118parameters: { type: "object", properties: {} },
136119 execute,
137120} as unknown as AnyAgentTool;
138121139-const session = await connectPluginToolsServer([tool]);
140-try {
141-const result = await session.client.callTool({
142-name: "memory_store",
143-arguments: { text: "remember this" },
144-});
145-expect(hookCalls).toBe(1);
146-expect(execute).not.toHaveBeenCalled();
147-expect(result.isError).toBe(true);
148-expect(result.content).toEqual([
149-{ type: "text", text: "Tool error: Plugin approval required (gateway unavailable)" },
150-]);
151-} finally {
152-await session.close();
153-}
122+const handlers = createPluginToolsMcpHandlers([tool]);
123+const result = await handlers.callTool({
124+name: "memory_store",
125+arguments: { text: "remember this" },
126+});
127+expect(hookCalls).toBe(1);
128+expect(execute).not.toHaveBeenCalled();
129+expect(result.isError).toBe(true);
130+expect(result.content).toEqual([
131+{ type: "text", text: "Tool error: Plugin approval required (gateway unavailable)" },
132+]);
154133});
155134});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。