Merge pull request #546 from fredericbarthelet/register-completions-capabilities
fix: Ensure completions capability is registered on setCompletionRequestHandler call
This commit is contained in:
commit
2cf4f0ca86
2 changed files with 160 additions and 198 deletions
|
|
@ -913,18 +913,10 @@ describe("tool()", () => {
|
|||
name: "test server",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.tool(
|
||||
"test",
|
||||
|
|
@ -1056,17 +1048,10 @@ describe("tool()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
// Register a tool with outputSchema
|
||||
mcpServer.registerTool(
|
||||
|
|
@ -1169,17 +1154,10 @@ describe("tool()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
// Register a tool with outputSchema that returns only content without structuredContent
|
||||
mcpServer.registerTool(
|
||||
|
|
@ -1233,17 +1211,10 @@ describe("tool()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
// Register a tool with outputSchema that returns invalid data
|
||||
mcpServer.registerTool(
|
||||
|
|
@ -1308,17 +1279,10 @@ describe("tool()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
let receivedSessionId: string | undefined;
|
||||
mcpServer.tool("test-tool", async (extra) => {
|
||||
|
|
@ -1364,17 +1328,10 @@ describe("tool()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
let receivedRequestId: string | number | undefined;
|
||||
mcpServer.tool("request-id-test", async (extra) => {
|
||||
|
|
@ -1423,17 +1380,10 @@ describe("tool()", () => {
|
|||
{ capabilities: { logging: {} } },
|
||||
);
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
let receivedLogMessage: string | undefined;
|
||||
const loggingMessage = "hello here is log message 1";
|
||||
|
|
@ -1480,17 +1430,10 @@ describe("tool()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.tool(
|
||||
"test",
|
||||
|
|
@ -1546,17 +1489,10 @@ describe("tool()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.tool("error-test", async () => {
|
||||
throw new Error("Tool execution failed");
|
||||
|
|
@ -1598,17 +1534,10 @@ describe("tool()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.tool("test-tool", async () => ({
|
||||
content: [
|
||||
|
|
@ -2392,6 +2321,48 @@ describe("resource()", () => {
|
|||
).rejects.toThrow(/Resource test:\/\/nonexistent not found/);
|
||||
});
|
||||
|
||||
/***
|
||||
* Test: Registering a resource template with a complete callback should update server capabilities to advertise support for completion
|
||||
*/
|
||||
test("should advertise support for completion when a resource template with a complete callback is defined", async () => {
|
||||
const mcpServer = new McpServer({
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
});
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.resource(
|
||||
"test",
|
||||
new ResourceTemplate("test://resource/{category}", {
|
||||
list: undefined,
|
||||
complete: {
|
||||
category: () => ["books", "movies", "music"],
|
||||
},
|
||||
}),
|
||||
async () => ({
|
||||
contents: [
|
||||
{
|
||||
uri: "test://resource/test",
|
||||
text: "Test content",
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
const [clientTransport, serverTransport] =
|
||||
InMemoryTransport.createLinkedPair();
|
||||
|
||||
await Promise.all([
|
||||
client.connect(clientTransport),
|
||||
mcpServer.server.connect(serverTransport),
|
||||
]);
|
||||
|
||||
expect(client.getServerCapabilities()).toMatchObject({ completions: {} })
|
||||
})
|
||||
|
||||
/***
|
||||
* Test: Resource Template Parameter Completion
|
||||
*/
|
||||
|
|
@ -2401,17 +2372,10 @@ describe("resource()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
resources: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.resource(
|
||||
"test",
|
||||
|
|
@ -2469,17 +2433,10 @@ describe("resource()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
resources: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.resource(
|
||||
"test",
|
||||
|
|
@ -2540,17 +2497,10 @@ describe("resource()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
resources: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
let receivedRequestId: string | number | undefined;
|
||||
mcpServer.resource("request-id-test", "test://resource", async (_uri, extra) => {
|
||||
|
|
@ -3052,17 +3002,10 @@ describe("prompt()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
prompts: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.prompt(
|
||||
"test",
|
||||
|
|
@ -3258,17 +3201,10 @@ describe("prompt()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
prompts: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.prompt("test-prompt", async () => ({
|
||||
messages: [
|
||||
|
|
@ -3303,6 +3239,49 @@ describe("prompt()", () => {
|
|||
).rejects.toThrow(/Prompt nonexistent-prompt not found/);
|
||||
});
|
||||
|
||||
|
||||
/***
|
||||
* Test: Registering a prompt with a completable argument should update server capabilities to advertise support for completion
|
||||
*/
|
||||
test("should advertise support for completion when a prompt with a completable argument is defined", async () => {
|
||||
const mcpServer = new McpServer({
|
||||
name: "test server",
|
||||
version: "1.0",
|
||||
});
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.prompt(
|
||||
"test-prompt",
|
||||
{
|
||||
name: completable(z.string(), () => ["Alice", "Bob", "Charlie"]),
|
||||
},
|
||||
async ({ name }) => ({
|
||||
messages: [
|
||||
{
|
||||
role: "assistant",
|
||||
content: {
|
||||
type: "text",
|
||||
text: `Hello ${name}`,
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
const [clientTransport, serverTransport] =
|
||||
InMemoryTransport.createLinkedPair();
|
||||
|
||||
await Promise.all([
|
||||
client.connect(clientTransport),
|
||||
mcpServer.server.connect(serverTransport),
|
||||
]);
|
||||
|
||||
expect(client.getServerCapabilities()).toMatchObject({ completions: {} })
|
||||
})
|
||||
|
||||
/***
|
||||
* Test: Prompt Argument Completion
|
||||
*/
|
||||
|
|
@ -3312,17 +3291,10 @@ describe("prompt()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
prompts: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.prompt(
|
||||
"test-prompt",
|
||||
|
|
@ -3380,17 +3352,10 @@ describe("prompt()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
prompts: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
mcpServer.prompt(
|
||||
"test-prompt",
|
||||
|
|
@ -3450,17 +3415,10 @@ describe("prompt()", () => {
|
|||
version: "1.0",
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
{
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
prompts: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
const client = new Client({
|
||||
name: "test client",
|
||||
version: "1.0",
|
||||
});
|
||||
|
||||
let receivedRequestId: string | number | undefined;
|
||||
mcpServer.prompt("request-id-test", async (extra) => {
|
||||
|
|
|
|||
|
|
@ -236,6 +236,10 @@ export class McpServer {
|
|||
CompleteRequestSchema.shape.method.value,
|
||||
);
|
||||
|
||||
this.server.registerCapabilities({
|
||||
completions: {},
|
||||
});
|
||||
|
||||
this.server.setRequestHandler(
|
||||
CompleteRequestSchema,
|
||||
async (request): Promise<CompleteResult> => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue