Skip to content

Commit 42c3967

Browse files
committed
add to readme
1 parent c90d6c9 commit 42c3967

File tree

2 files changed

+128
-11
lines changed

2 files changed

+128
-11
lines changed

README.md

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,33 @@ server.registerResource(
150150
}]
151151
})
152152
);
153+
154+
// Resource with context-aware completion
155+
server.registerResource(
156+
"repository",
157+
new ResourceTemplate("github://repos/{owner}/{repo}", {
158+
list: undefined,
159+
complete: {
160+
// Provide intelligent completions based on previously resolved parameters
161+
repo: (value, context) => {
162+
if (context?.arguments?.["owner"] === "org1") {
163+
return ["project1", "project2", "project3"].filter(r => r.startsWith(value));
164+
}
165+
return ["default-repo"].filter(r => r.startsWith(value));
166+
}
167+
}
168+
}),
169+
{
170+
title: "GitHub Repository",
171+
description: "Repository information"
172+
},
173+
async (uri, { owner, repo }) => ({
174+
contents: [{
175+
uri: uri.href,
176+
text: `Repository: ${owner}/${repo}`
177+
}]
178+
})
179+
);
153180
```
154181

155182
### Tools
@@ -233,12 +260,14 @@ Tools can return `ResourceLink` objects to reference resources without embedding
233260
Prompts are reusable templates that help LLMs interact with your server effectively:
234261

235262
```typescript
263+
import { completable } from "@modelcontextprotocol/sdk/server/completable.js";
264+
236265
server.registerPrompt(
237266
"review-code",
238267
{
239268
title: "Code Review",
240269
description: "Review code for best practices and potential issues",
241-
arguments: { code: z.string() }
270+
argsSchema: { code: z.string() }
242271
},
243272
({ code }) => ({
244273
messages: [{
@@ -250,6 +279,35 @@ server.registerPrompt(
250279
}]
251280
})
252281
);
282+
283+
// Prompt with context-aware completion
284+
server.registerPrompt(
285+
"team-greeting",
286+
{
287+
title: "Team Greeting",
288+
description: "Generate a greeting for team members",
289+
argsSchema: {
290+
// Completable arguments can use context for intelligent suggestions
291+
name: completable(z.string(), (value, context) => {
292+
if (context?.arguments?.["department"] === "engineering") {
293+
return ["Alice", "Bob", "Charlie"].filter(n => n.startsWith(value));
294+
} else if (context?.arguments?.["department"] === "sales") {
295+
return ["David", "Eve", "Frank"].filter(n => n.startsWith(value));
296+
}
297+
return ["Guest"].filter(n => n.startsWith(value));
298+
})
299+
}
300+
},
301+
({ name }) => ({
302+
messages: [{
303+
role: "assistant",
304+
content: {
305+
type: "text",
306+
text: `Hello ${name}, welcome to the team!`
307+
}
308+
}]
309+
})
310+
);
253311
```
254312

255313
### Display Names and Metadata
@@ -637,6 +695,57 @@ server.registerTool(
637695

638696
## Advanced Usage
639697

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+
640749
### Dynamic Servers
641750

642751
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: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3747,7 +3747,7 @@ describe("Tool title precedence", () => {
37473747
version: "1.0",
37483748
});
37493749

3750-
mcpServer.resource(
3750+
mcpServer.registerResource(
37513751
"test",
37523752
new ResourceTemplate("github://repos/{owner}/{repo}", {
37533753
list: undefined,
@@ -3762,6 +3762,10 @@ describe("Tool title precedence", () => {
37623762
},
37633763
},
37643764
}),
3765+
{
3766+
title: "GitHub Repository",
3767+
description: "Repository information"
3768+
},
37653769
async () => ({
37663770
contents: [
37673771
{
@@ -3865,17 +3869,21 @@ describe("Tool title precedence", () => {
38653869
version: "1.0",
38663870
});
38673871

3868-
mcpServer.prompt(
3872+
mcpServer.registerPrompt(
38693873
"test-prompt",
38703874
{
3871-
name: completable(z.string(), (value, context) => {
3872-
if (context?.arguments?.["category"] === "developers") {
3873-
return ["Alice", "Bob", "Charlie"].filter(n => n.startsWith(value));
3874-
} else if (context?.arguments?.["category"] === "managers") {
3875-
return ["David", "Eve", "Frank"].filter(n => n.startsWith(value));
3876-
}
3877-
return ["Guest"].filter(n => n.startsWith(value));
3878-
}),
3875+
title: "Team Greeting",
3876+
description: "Generate a greeting for team members",
3877+
argsSchema: {
3878+
name: completable(z.string(), (value, context) => {
3879+
if (context?.arguments?.["category"] === "developers") {
3880+
return ["Alice", "Bob", "Charlie"].filter(n => n.startsWith(value));
3881+
} else if (context?.arguments?.["category"] === "managers") {
3882+
return ["David", "Eve", "Frank"].filter(n => n.startsWith(value));
3883+
}
3884+
return ["Guest"].filter(n => n.startsWith(value));
3885+
}),
3886+
}
38793887
},
38803888
async ({ name }) => ({
38813889
messages: [

0 commit comments

Comments
 (0)