Skip to content

Commit 0086d96

Browse files
chore: add additional tests for tools interface on server
1 parent 33b14e0 commit 0086d96

File tree

1 file changed

+120
-2
lines changed

1 file changed

+120
-2
lines changed

tests/integration/server.test.ts

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,64 @@
1+
import { MCPConnectionManager } from "../../src/common/connectionManager.js";
2+
import { ExportsManager } from "../../src/common/exportsManager.js";
3+
import { CompositeLogger } from "../../src/common/logger.js";
4+
import { DeviceId } from "../../src/helpers/deviceId.js";
5+
import { Session } from "../../src/common/session.js";
16
import { defaultTestConfig, expectDefined } from "./helpers.js";
27
import { describeWithMongoDB } from "./tools/mongodb/mongodbHelpers.js";
3-
import { describe, expect, it } from "vitest";
8+
import { afterEach, describe, expect, it } from "vitest";
9+
import { Elicitation, Keychain, Telemetry } from "../../src/lib.js";
10+
import { VectorSearchEmbeddingsManager } from "../../src/common/search/vectorSearchEmbeddingsManager.js";
11+
import { defaultCreateAtlasLocalClient } from "../../src/common/atlasLocal.js";
12+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
13+
import { Server } from "../../src/server.js";
14+
import { connectionErrorHandler } from "../../src/common/connectionErrorHandler.js";
15+
import { type OperationType, ToolBase, type ToolCategory, type ToolClass } from "../../src/tools/tool.js";
16+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
17+
import type { TelemetryToolMetadata } from "../../src/telemetry/types.js";
18+
import { InMemoryTransport } from "../../src/transports/inMemoryTransport.js";
19+
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
20+
21+
class TestToolOne extends ToolBase {
22+
public name = "test-tool-one";
23+
protected description = "A test tool one for verification tests";
24+
static category: ToolCategory = "mongodb";
25+
static operationType: OperationType = "delete";
26+
protected argsShape = {};
27+
protected async execute(): Promise<CallToolResult> {
28+
return Promise.resolve({
29+
content: [
30+
{
31+
type: "text",
32+
text: "Test tool one executed successfully",
33+
},
34+
],
35+
});
36+
}
37+
protected resolveTelemetryMetadata(): TelemetryToolMetadata {
38+
return {};
39+
}
40+
}
41+
42+
class TestToolTwo extends ToolBase {
43+
public name = "test-tool-two";
44+
protected description = "A test tool two for verification tests";
45+
static category: ToolCategory = "mongodb";
46+
static operationType: OperationType = "delete";
47+
protected argsShape = {};
48+
protected async execute(): Promise<CallToolResult> {
49+
return Promise.resolve({
50+
content: [
51+
{
52+
type: "text",
53+
text: "Test tool two executed successfully",
54+
},
55+
],
56+
});
57+
}
58+
protected resolveTelemetryMetadata(): TelemetryToolMetadata {
59+
return {};
60+
}
61+
}
462

563
describe("Server integration test", () => {
664
describeWithMongoDB(
@@ -84,7 +142,7 @@ describe("Server integration test", () => {
84142
// Check that non-read tools are NOT available
85143
expect(tools.tools.some((tool) => tool.name === "insert-many")).toBe(false);
86144
expect(tools.tools.some((tool) => tool.name === "update-many")).toBe(false);
87-
expect(tools.tools.some((tool) => tool.name === "delete-one")).toBe(false);
145+
expect(tools.tools.some((tool) => tool.name === "delete-many")).toBe(false);
88146
expect(tools.tools.some((tool) => tool.name === "drop-collection")).toBe(false);
89147
});
90148
},
@@ -97,4 +155,64 @@ describe("Server integration test", () => {
97155
}),
98156
}
99157
);
158+
159+
describe("with additional tools", () => {
160+
const initServerWithTools = async (tools: ToolClass[]): Promise<{ server: Server; transport: Transport }> => {
161+
const logger = new CompositeLogger();
162+
const deviceId = DeviceId.create(logger);
163+
const connectionManager = new MCPConnectionManager(defaultTestConfig, logger, deviceId);
164+
const exportsManager = ExportsManager.init(defaultTestConfig, logger);
165+
166+
const session = new Session({
167+
userConfig: defaultTestConfig,
168+
logger,
169+
exportsManager,
170+
connectionManager,
171+
keychain: Keychain.root,
172+
vectorSearchEmbeddingsManager: new VectorSearchEmbeddingsManager(defaultTestConfig, connectionManager),
173+
atlasLocalClient: await defaultCreateAtlasLocalClient(),
174+
});
175+
176+
const telemetry = Telemetry.create(session, defaultTestConfig, deviceId);
177+
const mcpServerInstance = new McpServer({ name: "test", version: "1.0" });
178+
const elicitation = new Elicitation({ server: mcpServerInstance.server });
179+
180+
const server = new Server({
181+
session,
182+
userConfig: defaultTestConfig,
183+
telemetry,
184+
mcpServer: mcpServerInstance,
185+
elicitation,
186+
connectionErrorHandler,
187+
tools: [...tools],
188+
});
189+
190+
const transport = new InMemoryTransport();
191+
192+
return { transport, server };
193+
};
194+
195+
let server: Server | undefined;
196+
let transport: Transport | undefined;
197+
198+
afterEach(async () => {
199+
await transport?.close();
200+
});
201+
202+
it("should start server with only the tools provided", async () => {
203+
({ server, transport } = await initServerWithTools([TestToolOne]));
204+
await server.connect(transport);
205+
expect(server.tools).toHaveLength(1);
206+
});
207+
208+
it("should throw error before starting when provided tools have name conflict", async () => {
209+
({ server, transport } = await initServerWithTools([
210+
TestToolOne,
211+
class TestToolTwoButOne extends TestToolTwo {
212+
public name = "test-tool-one";
213+
},
214+
]));
215+
await expect(server.connect(transport)).rejects.toThrow(/Tool test-tool-one is already registered/);
216+
});
217+
});
100218
});

0 commit comments

Comments
 (0)