Merge pull request #2215 from dend/elicitation-support
Example showing how to use elicitation
This commit is contained in:
commit
5a48c0bf06
2 changed files with 87 additions and 0 deletions
|
|
@ -72,6 +72,14 @@ This MCP server attempts to exercise all the features of the MCP protocol. It is
|
||||||
- Embedded resource with `type: "resource"`
|
- Embedded resource with `type: "resource"`
|
||||||
- Text instruction for using the resource URI
|
- Text instruction for using the resource URI
|
||||||
|
|
||||||
|
9. `startElicitation`
|
||||||
|
- Initiates an elicitation (interaction) within the MCP client.
|
||||||
|
- Inputs:
|
||||||
|
- `color` (string): Favorite color
|
||||||
|
- `number` (number, 1-100): Favorite number
|
||||||
|
- `pets` (enum): Favorite pet
|
||||||
|
- Returns: Confirmation of the elicitation demo with selection summary.
|
||||||
|
|
||||||
### Resources
|
### Resources
|
||||||
|
|
||||||
The server provides 100 test resources in two formats:
|
The server provides 100 test resources in two formats:
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,8 @@ const GetResourceReferenceSchema = z.object({
|
||||||
.describe("ID of the resource to reference (1-100)"),
|
.describe("ID of the resource to reference (1-100)"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const ElicitationSchema = z.object({});
|
||||||
|
|
||||||
const GetResourceLinksSchema = z.object({
|
const GetResourceLinksSchema = z.object({
|
||||||
count: z
|
count: z
|
||||||
.number()
|
.number()
|
||||||
|
|
@ -104,6 +106,7 @@ enum ToolName {
|
||||||
GET_TINY_IMAGE = "getTinyImage",
|
GET_TINY_IMAGE = "getTinyImage",
|
||||||
ANNOTATED_MESSAGE = "annotatedMessage",
|
ANNOTATED_MESSAGE = "annotatedMessage",
|
||||||
GET_RESOURCE_REFERENCE = "getResourceReference",
|
GET_RESOURCE_REFERENCE = "getResourceReference",
|
||||||
|
ELICITATION = "startElicitation",
|
||||||
GET_RESOURCE_LINKS = "getResourceLinks",
|
GET_RESOURCE_LINKS = "getResourceLinks",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,6 +129,7 @@ export const createServer = () => {
|
||||||
tools: {},
|
tools: {},
|
||||||
logging: {},
|
logging: {},
|
||||||
completions: {},
|
completions: {},
|
||||||
|
elicitation: {},
|
||||||
},
|
},
|
||||||
instructions
|
instructions
|
||||||
}
|
}
|
||||||
|
|
@ -216,6 +220,21 @@ export const createServer = () => {
|
||||||
return await server.request(request, CreateMessageResultSchema);
|
return await server.request(request, CreateMessageResultSchema);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const requestElicitation = async (
|
||||||
|
message: string,
|
||||||
|
requestedSchema: any
|
||||||
|
) => {
|
||||||
|
const request = {
|
||||||
|
method: 'elicitation/create',
|
||||||
|
params: {
|
||||||
|
message,
|
||||||
|
requestedSchema
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return await server.request(request, z.any());
|
||||||
|
};
|
||||||
|
|
||||||
const ALL_RESOURCES: Resource[] = Array.from({ length: 100 }, (_, i) => {
|
const ALL_RESOURCES: Resource[] = Array.from({ length: 100 }, (_, i) => {
|
||||||
const uri = `test://static/resource/${i + 1}`;
|
const uri = `test://static/resource/${i + 1}`;
|
||||||
if (i % 2 === 0) {
|
if (i % 2 === 0) {
|
||||||
|
|
@ -469,6 +488,11 @@ export const createServer = () => {
|
||||||
"Returns a resource reference that can be used by MCP clients",
|
"Returns a resource reference that can be used by MCP clients",
|
||||||
inputSchema: zodToJsonSchema(GetResourceReferenceSchema) as ToolInput,
|
inputSchema: zodToJsonSchema(GetResourceReferenceSchema) as ToolInput,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: ToolName.ELICITATION,
|
||||||
|
description: "Demonstrates the Elicitation feature by asking the user to provide information about their favorite color, number, and pets.",
|
||||||
|
inputSchema: zodToJsonSchema(ElicitationSchema) as ToolInput,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: ToolName.GET_RESOURCE_LINKS,
|
name: ToolName.GET_RESOURCE_LINKS,
|
||||||
description:
|
description:
|
||||||
|
|
@ -664,6 +688,61 @@ export const createServer = () => {
|
||||||
return { content };
|
return { content };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name === ToolName.ELICITATION) {
|
||||||
|
ElicitationSchema.parse(args);
|
||||||
|
|
||||||
|
const elicitationResult = await requestElicitation(
|
||||||
|
'What are your favorite things?',
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
color: { type: 'string', description: 'Favorite color' },
|
||||||
|
number: { type: 'integer', description: 'Favorite number', minimum: 1, maximum: 100 },
|
||||||
|
pets: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['cats', 'dogs', 'birds', 'fish', 'reptiles'],
|
||||||
|
description: 'Favorite pets'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Handle different response actions
|
||||||
|
const content = [];
|
||||||
|
|
||||||
|
if (elicitationResult.action === 'accept' && elicitationResult.content) {
|
||||||
|
content.push({
|
||||||
|
type: "text",
|
||||||
|
text: `✅ User provided their favorite things!`,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only access elicitationResult.content when action is accept
|
||||||
|
const { color, number, pets } = elicitationResult.content;
|
||||||
|
content.push({
|
||||||
|
type: "text",
|
||||||
|
text: `Their favorites are:\n- Color: ${color || 'not specified'}\n- Number: ${number || 'not specified'}\n- Pets: ${pets || 'not specified'}`,
|
||||||
|
});
|
||||||
|
} else if (elicitationResult.action === 'decline') {
|
||||||
|
content.push({
|
||||||
|
type: "text",
|
||||||
|
text: `❌ User declined to provide their favorite things.`,
|
||||||
|
});
|
||||||
|
} else if (elicitationResult.action === 'cancel') {
|
||||||
|
content.push({
|
||||||
|
type: "text",
|
||||||
|
text: `⚠️ User cancelled the elicitation dialog.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include raw result for debugging
|
||||||
|
content.push({
|
||||||
|
type: "text",
|
||||||
|
text: `\nRaw result: ${JSON.stringify(elicitationResult, null, 2)}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
return { content };
|
||||||
|
}
|
||||||
|
|
||||||
if (name === ToolName.GET_RESOURCE_LINKS) {
|
if (name === ToolName.GET_RESOURCE_LINKS) {
|
||||||
const { count } = GetResourceLinksSchema.parse(args);
|
const { count } = GetResourceLinksSchema.parse(args);
|
||||||
const content = [];
|
const content = [];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue