Merge pull request #126 from modelcontextprotocol/justin/fix-multiple-registrations

Fix registering multiple tools/resources/prompts
This commit is contained in:
Justin Spahr-Summers 2025-01-21 12:56:38 +00:00 • committed by GitHub
commit 1fb33e8117
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 100 additions and 3 deletions

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "@modelcontextprotocol/sdk",
"version": "1.3.0",
"version": "1.3.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@modelcontextprotocol/sdk",
"version": "1.3.0",
"version": "1.3.1",
"license": "MIT",
"dependencies": {
"content-type": "^1.0.5",

View file

@ -1,6 +1,6 @@
{
"name": "@modelcontextprotocol/sdk",
"version": "1.3.0",
"version": "1.3.1",
"description": "Model Context Protocol implementation for TypeScript",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",

View file

@ -310,6 +310,19 @@ describe("tool()", () => {
}).toThrow(/already registered/);
});
test("should allow registering multiple tools", () => {
const mcpServer = new McpServer({
name: "test server",
version: "1.0",
});
// This should succeed
mcpServer.tool("tool1", () => ({ content: [] }));
// This should also succeed and not throw about request handlers
mcpServer.tool("tool2", () => ({ content: [] }));
});
test("should allow client to call server tools", async () => {
const mcpServer = new McpServer({
name: "test server",
@ -734,6 +747,33 @@ describe("resource()", () => {
}).toThrow(/already registered/);
});
test("should allow registering multiple resources", () => {
const mcpServer = new McpServer({
name: "test server",
version: "1.0",
});
// This should succeed
mcpServer.resource("resource1", "test://resource1", async () => ({
contents: [
{
uri: "test://resource1",
text: "Test content 1",
},
],
}));
// This should also succeed and not throw about request handlers
mcpServer.resource("resource2", "test://resource2", async () => ({
contents: [
{
uri: "test://resource2",
text: "Test content 2",
},
],
}));
});
test("should prevent duplicate resource template registration", () => {
const mcpServer = new McpServer({
name: "test server",
@ -1210,6 +1250,39 @@ describe("prompt()", () => {
}).toThrow(/already registered/);
});
test("should allow registering multiple prompts", () => {
const mcpServer = new McpServer({
name: "test server",
version: "1.0",
});
// This should succeed
mcpServer.prompt("prompt1", async () => ({
messages: [
{
role: "assistant",
content: {
type: "text",
text: "Test response 1",
},
},
],
}));
// This should also succeed and not throw about request handlers
mcpServer.prompt("prompt2", async () => ({
messages: [
{
role: "assistant",
content: {
type: "text",
text: "Test response 2",
},
},
],
}));
});
test("should throw McpError for invalid prompt name", async () => {
const mcpServer = new McpServer({
name: "test server",

View file

@ -81,7 +81,13 @@ export class McpServer {
await this.server.close();
}
private _toolHandlersInitialized = false;
private setToolRequestHandlers() {
if (this._toolHandlersInitialized) {
return;
}
this.server.assertCanSetRequestHandler(
ListToolsRequestSchema.shape.method.value,
);
@ -165,6 +171,8 @@ export class McpServer {
}
},
);
this._toolHandlersInitialized = true;
}
private setCompletionRequestHandler() {
@ -249,7 +257,13 @@ export class McpServer {
return createCompletionResult(suggestions);
}
private _resourceHandlersInitialized = false;
private setResourceRequestHandlers() {
if (this._resourceHandlersInitialized) {
return;
}
this.server.assertCanSetRequestHandler(
ListResourcesRequestSchema.shape.method.value,
);
@ -342,9 +356,17 @@ export class McpServer {
);
this.setCompletionRequestHandler();
this._resourceHandlersInitialized = true;
}
private _promptHandlersInitialized = false;
private setPromptRequestHandlers() {
if (this._promptHandlersInitialized) {
return;
}
this.server.assertCanSetRequestHandler(
ListPromptsRequestSchema.shape.method.value,
);
@ -406,6 +428,8 @@ export class McpServer {
);
this.setCompletionRequestHandler();
this._promptHandlersInitialized = true;
}
/**