diff --git a/package.json b/package.json index 9ca92d4..6cc3eda 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "toolception", - "version": "0.5.0", + "version": "0.5.1", "private": false, "type": "module", "main": "dist/index.js", diff --git a/src/server/createMcpServer.ts b/src/server/createMcpServer.ts index 2e586fe..b7ef665 100644 --- a/src/server/createMcpServer.ts +++ b/src/server/createMcpServer.ts @@ -87,6 +87,11 @@ export async function createMcpServer(options: CreateMcpServerOptions) { : mode === "DYNAMIC", }); + // In STATIC mode, wait for initialization to complete before starting + if (mode === "STATIC") { + await orchestrator.ensureReady(); + } + const transport = new FastifyTransport( orchestrator.getManager(), () => { diff --git a/tests/createMcpServer.test.ts b/tests/createMcpServer.test.ts index 4a15105..4d8184b 100644 --- a/tests/createMcpServer.test.ts +++ b/tests/createMcpServer.test.ts @@ -160,4 +160,50 @@ describe("createMcpServer", () => { // No additional registrations should have occurred on the shared server expect(base.calls.filter((n) => n === "core.ping").length).toBe(1); }); + + it("ensures tools are ready immediately in STATIC mode (waits for async module loaders)", async () => { + const f = makeFakeServerFactory(); + let moduleLoaderStarted = false; + let moduleLoaderCompleted = false; + + const staticCatalog = { + testset: { + name: "Test Toolset", + description: "Test tools with async loading", + modules: ["testset"], + }, + } as any; + + await createMcpServer({ + catalog: staticCatalog, + moduleLoaders: { + testset: async () => { + moduleLoaderStarted = true; + // Simulate async loading delay + await new Promise((r) => setTimeout(r, 100)); + moduleLoaderCompleted = true; + return [ + { + name: "test_tool", + description: "A test tool", + inputSchema: { type: "object", properties: {} }, + handler: async () => ({ + content: [{ type: "text", text: "test" }], + }), + }, + ]; + }, + }, + startup: { mode: "STATIC", toolsets: ["testset"] }, + createServer: f.createServer, + }); + + // After createMcpServer returns, the module loader should have completed + expect(moduleLoaderStarted).toBe(true); + expect(moduleLoaderCompleted).toBe(true); + + // Tools should be registered on the server + const base = f.created[0]; + expect(base.calls.filter((n) => n === "testset.test_tool").length).toBe(1); + }); });