Anthropicβs Model Context Protocol (MCP) faces a critical usability gap in headless environments. Developers using Claude Code in CI pipelines or via the claude -p flag are encountering hard failures when their MCP tools attempt to use the ctx.elicit() method. Unlike interactive sessions, headless clients lack a back-channel for server-initiated requests, causing the tool call to crash rather than gracefully degrade.
The Silent Failure in Headless Sessions
The core issue is architectural: elicitation requires a live user to respond to a server prompt. In headless contexts, such as automated scripts or continuous integration, there is no user interface to receive these requests. Consequently, the elicit() call raises an exception with the message "Cannot send 'elicitation/create': this transport context has no back-channel for server-initiated requests." This bypasses standard error handling logic, such as checking for result.action != "accept", rendering the tool completely unusable in non-interactive modes.
Implementing a Parameter-First Fallback
The recommended solution, tested on Claude Code 2.1.310 with Python MCP SDK 2.3.0, involves restructuring tool definitions to prioritize explicit parameters. Developers should define required inputs as optional parameters in the tool schema. The ctx.elicit() call should only trigger if these parameters are missing. Crucially, the code must wrap the elicitation in a try-except block. If the elicitation fails due to the lack of a back-channel, the tool should return a clear error string instructing the model to retry with the necessary parameters, rather than raising an exception that the model may interpret as a broken tool.
SDK Migration and Testing Gotchas
This fix also highlights recent changes in the Python MCP SDK. The class FastMCP has been renamed to MCPServer in version 2.x, requiring import updates from mcp.server.mcpserver. Additionally, when writing custom test clients, developers must note that the elicitation parameters field uses snake_case (requested_schema) in the Python SDK, differing from the requestedSchema camelCase defined in the JSON-RPC specification. These discrepancies can lead to silent bugs if not carefully managed during development.
Key Takeaways
- Headless Claude Code environments lack back-channels for MCP server-initiated requests, causing
ctx.elicit()to fail. - The fix is to make elicitation parameters optional and provide a fallback error message that guides the model to pass parameters explicitly.
- Python MCP SDK 2.x renamed
FastMCPtoMCPServerand uses snake_case for elicitation parameters in Python clients. - Clear tool docstrings are essential for models to understand when to pass parameters versus relying on elicitation.
The Bottom Line
Interactive UX patterns like elicitation are brittle in automation pipelines; treat headless compatibility as a first-class requirement for any MCP tool intended for CI/CD use.