Why tool calls feel clunky and how elicitation fixes it

An MCP server that lets an AI agent call tools is only half the story. The other half is what happens when the agent doesn't have all the information it needs to complete a call. A typical fallback is to silently apply defaults or to fail with an error, neither of which feels like a natural interaction. The Model Context Protocol's elicitation mechanism addresses this gap: an MCP server can pause a tool execution, ask the user only for the missing details, and then continue where it left off.

Elicitation is a relatively new addition to the MCP specification, having been introduced in the June 2025 revision. Support varies by host — GitHub Copilot in Visual Studio Code supports it, but you should check MCP's feature support matrix for other clients.

From many tools to one consolidated flow

A turn-based game MCP server (tic-tac-toe, rock-paper-scissors) initially implemented elicitation as separate tools rather than replacing the existing ones. This was done intentionally to compare behavior between the two approaches before standardizing. The result was tool sprawl:

  • create-tic-tac-toe-game plus create-tic-tac-toe-game-interactive
  • create-rock-paper-scissors-game plus create-rock-paper-scissors-game-interactive
  • play-tic-tac-toe and play-rock-paper-scissors

That turned out to be a problem: when an agent like Copilot is given tools with similar names and descriptions, it can pick the wrong one. This happened repeatedly during testing. The fix was to consolidate everything into a single unified set based on DRY principles.

A screenshot of GitHub Copilot Chat in Visual Studio Code where the user has asked "Let's play a game of tictactoe". Copilot has triggered the elicitation experience, requesting additional preferences to customize the experience.

The consolidated server now offers four tools instead of eight:

  • create-game — handles all game types, with elicitation
  • play-game — unified play interface
  • analyze-game — game state analysis
  • wait-for-player-move — turn management

Only ask for what's actually missing

The original implementation had a flaw that surfaced during the live stream: elicitation fired on every invocation of the tool, even when the user's request already supplied needed values. After the stream, the logic was reworked to check which parameters the initial request already provided and to elicit only the remainder. Property names are now aligned between the tool schemas and the elicitation schemas, reducing ambiguity.

The flow inside the MCP server now works like this:

  1. When create_game is invoked, the handler checks for required parameters — for example, which game the user wants to play.
  2. Optional identified arguments are passed to a separate method that evaluates what's missing: difficulty, player name, or turn order.
  3. If information is missing, elicitation is initiated, pausing the tool execution.
  4. Schema-driven prompts present formatted questions for each missing parameter.
  5. The MCP client (VS Code here) handles the user interface for collecting responses.
  6. Once all information is gathered, the original tool request completes — the game is created using the user's choices.
A screenshot of GitHub Copilot Chat in Visual Studio Code where a new UI modal appears, prompting the user for their preferences. This example shows the user selecting the Difficulty as hard.

The user-visible result is concrete. Instead of a generic lobby like "Player vs AI (Medium)," prompting the agent to start a game can yield "Chris vs AI (Hard)" with the AI making the first move when the user chooses to play second.

Lessons learned along the way

Elicitation adds complexity, but it can be worth it

Users rarely provide every required piece of information up front. Elicitation gives a path between forcing users to work around poor defaults and failing outright. But it adds complexity to tool flows, so it needs deliberate design rather than being bolted on.

Naming and descriptions are part of the API

For an AI agent, tool names and descriptions are core parts of the interface. Ambiguous naming or overlapping descriptions can cause unpredictable tool selection. Merging similar tools and using clear, distinct names is important for reliable behavior.

Iterate rather than aiming for perfect upfront design

The practical progression here was: build basic functionality first, identify pain points through real usage, add elicitation to address those friction points, and use Copilot coding agent mode to help with cleanup. That pattern is worth keeping for any MCP server project.

Try the sample yourself

  1. Fork the repository at gh.io/rdt-blog/game-mcp.
  2. Set up your dev environment by creating a GitHub Codespace.
  3. Run the sample by building the code, starting the MCP server, and running the web app/API server.

Improving AI tools is not just about the model. The surrounding experience — the ability to interpret context, ask meaningful follow-up questions, and deliver exactly what a user needs — is where many of the remaining wins live. Elicitation is one step in that direction for the MCP ecosystem.