Skip to content

Instantly share code, notes, and snippets.

@abhiaiyer91
Last active November 29, 2025 14:45
Show Gist options
  • Select an option

  • Save abhiaiyer91/5bf4569ab97fe9b0aeb5cb8c79e625c3 to your computer and use it in GitHub Desktop.

Select an option

Save abhiaiyer91/5bf4569ab97fe9b0aeb5cb8c79e625c3 to your computer and use it in GitHub Desktop.
/**
* Reproduction script for issue #10668 - FIXED VERSION
*
* This shows the correct way to handle elicitation requests
*/
import { MCPClient } from './src/client/configuration';
import { MCPServer } from './src/server/server';
import http from 'http';
import { z } from 'zod';
const PORT = 9700 + Math.floor(Math.random() * 1000);
const SERVER_URL = `http://localhost:${PORT}/http`;
// Create the MCP server with a tool that uses elicitation
const server = new MCPServer({
name: 'TestElicitationServer',
version: '1.0.0',
tools: {
confirmAction: {
description: 'A tool that requires user confirmation via elicitation',
parameters: z.object({
action: z.string().describe('The action to confirm'),
}),
execute: async (inputData, context) => {
try {
const userApproval = await context?.mcp?.elicitation?.sendRequest({
mode: 'form',
message: 'Are you sure?',
requestedSchema: {
type: 'object',
properties: {
userConfirmation: {
type: 'boolean',
title: 'User Confirmation',
description: 'Are you sure?',
},
},
required: ['userConfirmation'],
},
});
if (userApproval.action !== 'accept') {
console.log('User did not accept!');
return {
content: [
{
type: 'text' as const,
text: 'User did not accept!',
},
],
};
}
return {
content: [
{
type: 'text' as const,
text: 'User has given confirmation!',
},
],
};
} catch (error) {
console.error('Error in tool execution:', error);
return {
content: [
{
type: 'text' as const,
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
},
},
},
});
// Start HTTP server
const httpServer = http.createServer(async (req, res) => {
const url = new URL(req.url || '', `http://localhost:${PORT}`);
await server.startHTTP({
url,
httpPath: '/http',
req,
res,
});
});
await new Promise<void>(resolve => {
httpServer.listen(PORT, () => {
console.log(`βœ… Server started on port ${PORT}`);
resolve();
});
});
// Simulate user's exact initialization pattern
const config = {
mcps: [
{
type: 'http' as const,
name: 'BASIC_MCP',
url: SERVER_URL,
timeout: 15000,
headers: undefined as Record<string, string> | undefined,
},
],
};
const servers: Record<string, any> = {};
for (const mcp of config.mcps) {
if (mcp.type === 'http') {
const serverConfig: any = {
url: new URL(mcp.url),
timeout: mcp.timeout || 15000,
capabilities: {
elicitation: {
form: {},
},
},
};
if (mcp.headers) {
serverConfig.requestInit = {
headers: mcp.headers,
};
}
servers[mcp.name] = serverConfig;
}
}
const mcpClient = new MCPClient({ servers: servers, timeout: 15000 });
// βœ… FIXED: Handler returns content that matches the schema
if (config.mcps && mcpClient) {
for (const mcp of config.mcps) {
switch (mcp.name) {
case 'BASIC_MCP':
console.log('Setting up elicitation handler for BASIC_MCP');
await mcpClient.elicitation.onRequest('BASIC_MCP', async request => {
console.log('πŸ”” Elicitation request received for BASIC_MCP');
const schema: any = request.requestedSchema;
const properties = schema.properties || {};
const required = (schema.required as string[]) || [];
// βœ… FIX: Return content that matches the schema
// Build the response based on the schema
const content: Record<string, any> = {};
for (const fieldName of Object.keys(properties)) {
const field = properties[fieldName];
// For boolean fields, default to true (or prompt user)
if (field.type === 'boolean') {
content[fieldName] = true; // Or get from user input
} else if (field.type === 'string') {
content[fieldName] = ''; // Or get from user input
} else if (field.type === 'number') {
content[fieldName] = 0; // Or get from user input
}
}
console.log('βœ… Returning content that matches schema:', content);
return { action: 'accept', content };
});
break;
default:
break;
}
}
}
// Get tools and execute
const tools = await mcpClient.listTools();
const tool = tools['BASIC_MCP_confirmAction'];
console.log('\nπŸ“‹ Executing tool with FIXED handler...');
const result = await tool.execute({
action: 'test action',
});
console.log('\nπŸ“Š Result:');
console.log(JSON.stringify(result, null, 2));
if (result.isError) {
console.log('\n❌ Tool execution resulted in error');
} else {
const resultText = result.content[0]?.text;
if (resultText && resultText.includes('User has given confirmation')) {
console.log('\nβœ… SUCCESS! Handler worked correctly!');
}
}
// Cleanup
await mcpClient.disconnect();
await server.close();
httpServer.closeAllConnections?.();
await new Promise<void>(resolve => {
httpServer.close(() => resolve());
});
console.log('\nβœ… Done');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment