Skip to content

Commit 0e86a6d

Browse files
committed
improve readme
1 parent 42c3967 commit 0e86a6d

File tree

2 files changed

+53
-66
lines changed

2 files changed

+53
-66
lines changed

README.md

Lines changed: 12 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -287,23 +287,30 @@ server.registerPrompt(
287287
title: "Team Greeting",
288288
description: "Generate a greeting for team members",
289289
argsSchema: {
290-
// Completable arguments can use context for intelligent suggestions
290+
department: completable(z.string(), (value) => {
291+
// Department suggestions
292+
return ["engineering", "sales", "marketing", "support"].filter(d => d.startsWith(value));
293+
}),
291294
name: completable(z.string(), (value, context) => {
292-
if (context?.arguments?.["department"] === "engineering") {
295+
// Name suggestions based on selected department
296+
const department = context?.arguments?.["department"];
297+
if (department === "engineering") {
293298
return ["Alice", "Bob", "Charlie"].filter(n => n.startsWith(value));
294-
} else if (context?.arguments?.["department"] === "sales") {
299+
} else if (department === "sales") {
295300
return ["David", "Eve", "Frank"].filter(n => n.startsWith(value));
301+
} else if (department === "marketing") {
302+
return ["Grace", "Henry", "Iris"].filter(n => n.startsWith(value));
296303
}
297304
return ["Guest"].filter(n => n.startsWith(value));
298305
})
299306
}
300307
},
301-
({ name }) => ({
308+
({ department, name }) => ({
302309
messages: [{
303310
role: "assistant",
304311
content: {
305312
type: "text",
306-
text: `Hello ${name}, welcome to the team!`
313+
text: `Hello ${name}, welcome to the ${department} team!`
307314
}
308315
}]
309316
})
@@ -695,57 +702,6 @@ server.registerTool(
695702

696703
## Advanced Usage
697704

698-
### Context-Aware Completions
699-
700-
MCP supports intelligent completions that can use previously resolved values as context. This is useful for creating dependent parameter completions where later parameters depend on earlier ones:
701-
702-
```typescript
703-
import { completable } from "@modelcontextprotocol/sdk/server/completable.js";
704-
705-
// For resource templates
706-
server.registerResource(
707-
"database-query",
708-
new ResourceTemplate("db://{database}/{table}/{query}", {
709-
list: undefined,
710-
complete: {
711-
// Table completions depend on the selected database
712-
table: (value, context) => {
713-
const database = context?.arguments?.["database"];
714-
if (database === "users_db") {
715-
return ["profiles", "sessions", "preferences"].filter(t => t.startsWith(value));
716-
} else if (database === "products_db") {
717-
return ["items", "categories", "inventory"].filter(t => t.startsWith(value));
718-
}
719-
return [];
720-
}
721-
}
722-
}),
723-
metadata,
724-
handler
725-
);
726-
727-
// For prompts with completable arguments
728-
server.registerPrompt(
729-
"api-request",
730-
{
731-
argsSchema: {
732-
endpoint: z.string(),
733-
// Method completions can be context-aware
734-
method: completable(z.string(), (value, context) => {
735-
const endpoint = context?.arguments?.["endpoint"];
736-
if (endpoint?.includes("/readonly/")) {
737-
return ["GET"].filter(m => m.startsWith(value.toUpperCase()));
738-
}
739-
return ["GET", "POST", "PUT", "DELETE"].filter(m => m.startsWith(value.toUpperCase()));
740-
})
741-
}
742-
},
743-
handler
744-
);
745-
```
746-
747-
The context object contains an `arguments` field with previously resolved parameter values, allowing you to provide more intelligent and contextual completions.
748-
749705
### Dynamic Servers
750706

751707
If you want to offer an initial set of tools/prompts/resources, but later add additional ones based on user action or external state change, you can add/update/remove them _after_ the Server is connected. This will automatically emit the corresponding `listChanged` notifications:

src/server/mcp.test.ts

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3875,23 +3875,29 @@ describe("Tool title precedence", () => {
38753875
title: "Team Greeting",
38763876
description: "Generate a greeting for team members",
38773877
argsSchema: {
3878+
department: completable(z.string(), (value) => {
3879+
return ["engineering", "sales", "marketing", "support"].filter(d => d.startsWith(value));
3880+
}),
38783881
name: completable(z.string(), (value, context) => {
3879-
if (context?.arguments?.["category"] === "developers") {
3882+
const department = context?.arguments?.["department"];
3883+
if (department === "engineering") {
38803884
return ["Alice", "Bob", "Charlie"].filter(n => n.startsWith(value));
3881-
} else if (context?.arguments?.["category"] === "managers") {
3885+
} else if (department === "sales") {
38823886
return ["David", "Eve", "Frank"].filter(n => n.startsWith(value));
3887+
} else if (department === "marketing") {
3888+
return ["Grace", "Henry", "Iris"].filter(n => n.startsWith(value));
38833889
}
38843890
return ["Guest"].filter(n => n.startsWith(value));
38853891
}),
38863892
}
38873893
},
3888-
async ({ name }) => ({
3894+
async ({ department, name }) => ({
38893895
messages: [
38903896
{
38913897
role: "assistant",
38923898
content: {
38933899
type: "text",
3894-
text: `Hello ${name}`,
3900+
text: `Hello ${name}, welcome to the ${department} team!`,
38953901
},
38963902
},
38973903
],
@@ -3906,7 +3912,7 @@ describe("Tool title precedence", () => {
39063912
mcpServer.server.connect(serverTransport),
39073913
]);
39083914

3909-
// Test with developers category
3915+
// Test with engineering department
39103916
const result1 = await client.request(
39113917
{
39123918
method: "completion/complete",
@@ -3921,7 +3927,7 @@ describe("Tool title precedence", () => {
39213927
},
39223928
context: {
39233929
arguments: {
3924-
category: "developers",
3930+
department: "engineering",
39253931
},
39263932
},
39273933
},
@@ -3931,7 +3937,7 @@ describe("Tool title precedence", () => {
39313937

39323938
expect(result1.completion.values).toEqual(["Alice"]);
39333939

3934-
// Test with managers category
3940+
// Test with sales department
39353941
const result2 = await client.request(
39363942
{
39373943
method: "completion/complete",
@@ -3946,7 +3952,7 @@ describe("Tool title precedence", () => {
39463952
},
39473953
context: {
39483954
arguments: {
3949-
category: "managers",
3955+
department: "sales",
39503956
},
39513957
},
39523958
},
@@ -3956,8 +3962,33 @@ describe("Tool title precedence", () => {
39563962

39573963
expect(result2.completion.values).toEqual(["David"]);
39583964

3959-
// Test with no resolved context
3965+
// Test with marketing department
39603966
const result3 = await client.request(
3967+
{
3968+
method: "completion/complete",
3969+
params: {
3970+
ref: {
3971+
type: "ref/prompt",
3972+
name: "test-prompt",
3973+
},
3974+
argument: {
3975+
name: "name",
3976+
value: "G",
3977+
},
3978+
context: {
3979+
arguments: {
3980+
department: "marketing",
3981+
},
3982+
},
3983+
},
3984+
},
3985+
CompleteResultSchema,
3986+
);
3987+
3988+
expect(result3.completion.values).toEqual(["Grace"]);
3989+
3990+
// Test with no resolved context
3991+
const result4 = await client.request(
39613992
{
39623993
method: "completion/complete",
39633994
params: {
@@ -3974,6 +4005,6 @@ describe("Tool title precedence", () => {
39744005
CompleteResultSchema,
39754006
);
39764007

3977-
expect(result3.completion.values).toEqual(["Guest"]);
4008+
expect(result4.completion.values).toEqual(["Guest"]);
39784009
});
39794010
});

0 commit comments

Comments
 (0)