M
Mastraβ€’2w ago
Om

How to handle MCP elicitations using MCPClient?

Hey team, I am not able to handle elicitation requests using MCPClient even after sending it from the tool on server. I am initialising the MCPClient as follows:
const servers: Record<string, MastraMCPServerDefinition> = {};
for (const mcp of config.mcps) {
if (mcp.type === 'http') {
const serverConfig: MastraMCPServerDefinition = {
url: new URL(mcp.url),
timeout: mcp.timeout || 15000,
capabilities: {
elicitation: {
form: {}
}
}
};
if (mcp.headers) {
serverConfig.requestInit = {
headers: mcp.headers,
};
}
servers[mcp.name] = serverConfig
} else if (mcp.type === 'command') {
const serverConfig: MastraMCPServerDefinition = {
command: mcp.command,
args: mcp.args,
}
servers[mcp.name] = serverConfig
}
}
this.mcpClient = new MCPClient({ servers: servers, timeout: 15000 });
const servers: Record<string, MastraMCPServerDefinition> = {};
for (const mcp of config.mcps) {
if (mcp.type === 'http') {
const serverConfig: MastraMCPServerDefinition = {
url: new URL(mcp.url),
timeout: mcp.timeout || 15000,
capabilities: {
elicitation: {
form: {}
}
}
};
if (mcp.headers) {
serverConfig.requestInit = {
headers: mcp.headers,
};
}
servers[mcp.name] = serverConfig
} else if (mcp.type === 'command') {
const serverConfig: MastraMCPServerDefinition = {
command: mcp.command,
args: mcp.args,
}
servers[mcp.name] = serverConfig
}
}
this.mcpClient = new MCPClient({ servers: servers, timeout: 15000 });
I adding onRequest handler after getting tools from the server as follow:
if (config.mcps && this.mcpClient) {
for (const mcp of config.mcps) {
switch (mcp.name) {
case 'BASIC_MCP':
this.logger.info('Setting up elicitation handler for BASIC_MCP');
await this.mcpClient.elicitation.onRequest('BASIC_MCP', async (request) => {
this.logger.info('Elicitation request received for BASIC_MCP: ' + JSON.stringify(request, null, 2));
const schema: any = request.requestedSchema;
const properties = schema.properties || {};
const required = (schema.required as string[]) || [];
// send default accept as of now
return { action: 'accept', content: {} };
});
break;
default:
break;
}
}
}
if (config.mcps && this.mcpClient) {
for (const mcp of config.mcps) {
switch (mcp.name) {
case 'BASIC_MCP':
this.logger.info('Setting up elicitation handler for BASIC_MCP');
await this.mcpClient.elicitation.onRequest('BASIC_MCP', async (request) => {
this.logger.info('Elicitation request received for BASIC_MCP: ' + JSON.stringify(request, null, 2));
const schema: any = request.requestedSchema;
const properties = schema.properties || {};
const required = (schema.required as string[]) || [];
// send default accept as of now
return { action: 'accept', content: {} };
});
break;
default:
break;
}
}
}
(1/2)
6 Replies
Om
OmOPβ€’2w ago
Tool that I have defined on the server side:
case 'REDACTED_TOOL_NAME': {
server.registerTool(
'REDACTED_TOOL_NAME',
{
title: 'REDACTED_TITLE',
description: 'REDACTED_DESCRIPTION',
inputSchema: InputSchema,
},
async (params: Input) => {
const userApproval = await server.server.elicitInput({
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') {
logger.info('User did not accept!');
return {
content: [
{
type: 'text' as const,
text: 'User did not accept!',
},
],
};
}

return {"type":"text", "content":"User has gven confirmation!"}
},
);
break;
}
case 'REDACTED_TOOL_NAME': {
server.registerTool(
'REDACTED_TOOL_NAME',
{
title: 'REDACTED_TITLE',
description: 'REDACTED_DESCRIPTION',
inputSchema: InputSchema,
},
async (params: Input) => {
const userApproval = await server.server.elicitInput({
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') {
logger.info('User did not accept!');
return {
content: [
{
type: 'text' as const,
text: 'User did not accept!',
},
],
};
}

return {"type":"text", "content":"User has gven confirmation!"}
},
);
break;
}
What am I missing here? (2/2) And yes the error I get when I try to do this is:
McpError: MCP error -32001: Request timed out
McpError: MCP error -32001: Request timed out
from the MCP Server
Failed tool execution
Failed tool execution
from agents backend Dependencies I am using: "@mastra/core": "^0.24.1", "@mastra/mcp": "^0.14.4", "@modelcontextprotocol/sdk": "^1.22.0" I can see my MCP sever is trying to elicit the user input but same is not being accepted by the MCPClient
Mastra Triager
Mastra Triagerβ€’2w ago
πŸ“ Created GitHub issue: https://github.com/mastra-ai/mastra/issues/10668 πŸ” If you're experiencing an error, please provide a minimal reproducible example whenever possible to help us resolve it quickly. πŸ™ Thank you for helping us improve Mastra!
Abhi Aiyer
Abhi Aiyerβ€’2w ago
Hey @Om ill take a look! Hmm i tried reproducing, and while i dont get Request timed out i do get an elicitation failed error Let me post my repro and the fixed version
Abhi Aiyer
Abhi Aiyerβ€’2w ago
Gist
elicitation-broken.ts
GitHub Gist: instantly share code, notes, and snippets.
Gist
elicitation-fixed.ts
GitHub Gist: instantly share code, notes, and snippets.
Om
OmOPβ€’2w ago
@Abhi Aiyer thankyou so much for your efforts. Appreciated, but the issue was from my side. The way I was orchestrating MCP server was wrong so I fixed that and it worked perfectly. Sorry for the trouble tho 😬 Thankyou!
Abhi Aiyer
Abhi Aiyerβ€’2w ago
That’s great to hear! No problem!

Did you find this page helpful?