AI Engineer World's Fair 2025
Full Spec MCP: Hidden Capabilities of the MCP Spec — Harald Kirschner, Microsoft/VS Code
Read the talk
Full Spec MCP: Hidden Capabilities of the MCP Spec
MCP can do more than expose functions: dynamic discovery, resources, sampling and user input let servers adapt as a task and its context change.
From a talk by Harald Kirschner
Before you start: You should be familiar with MCP clients and servers, model tool calling, and basic Python.
Why does an MCP server fail to work?
Who has built an MCP server and found that it did not work? That opening question reaches beyond connection errors. A server can expose valid tools and still leave the model choosing the wrong action, missing relevant context or struggling through an interaction that the protocol could support more directly. Harald Kirschner approaches that problem from his work on VS Code and local development, with lessons that apply beyond the IDE.
The ecosystem in this recording is still forming its working practices. Kirschner describes its first in-person MCP steering committee gathering as having happened ten days earlier, after collaboration largely through Discord. The missing pieces are opportunities for implementation and feedback, rather than evidence that the specification has failed.
MCP already includes roots, sampling, prompts, tools and resources. Together, these support dynamic discovery, persistent resources and richer interactions. Yet the fastest path to a useful product is often to wrap an API in tools. Successful products establish examples that other developers copy, reinforcing a tools-only ecosystem. Missing support in clients, SDKs, documentation and reference implementations makes that choice harder to escape.
Tools can approximate some prompt and resource workflows, so starting there is understandable. VS Code did the same: its initial MCP implementation concentrated on tools, with discovery and roots already included. Kirschner then announces broader specification support in Insiders and an upcoming release, documented in the VS Code 1.101 release notes. This is the historical implementation context of the demonstrations; experimental sampling and later draft additions should not be read as a claim that every future capability was already shipped. The goal is richer, stateful interactions, not merely a larger inventory of callable functions.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Give the model the tools it needs now
Tools represent actions and map naturally to function calling. In the Playwright example, a server opens a browser and takes a screenshot. But adding more tools does not automatically improve the model’s ability to complete a task: the IDE may reject the inventory, or the model may select an inappropriate action.
Kirschner points to LangChain research on three sources of difficulty: tool count, the diversity of domains and instructions, and repeated tool-use steps. Benchmarking Single Agent Performance examines these pressures in a particular ReAct assistant, rather than establishing a universal tool-count limit. A focused UI-testing tool set gives the model a more coherent task environment than a mixture of unrelated actions, properties and instructions. Longer sequences also give it more opportunities to lose track of the task.
VS Code exposes several ways to narrow or direct tool use:
| Control | What it changes |
|---|---|
| Per-chat tool picker | Limits the tools available in the current session |
| Explicit tool mentions | Names the intended action while the model supplies parameters |
| User-defined tool sets | Saves a reusable selection, such as front-end testing tools |
The picker supports keyboard interaction and preserves the selection for the session. Tool sets make the same decision reusable: once the relevant testing tools are identified, the user can invoke that collection without rebuilding it for every conversation. These controls put quality of selection ahead of quantity of exposure.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Make available actions follow the game state
Manual selection is only one way to control the tool inventory. Dynamic discovery lets the server change the tools it exposes while an interaction is underway. In the dungeon crawler demonstration, a custom chat mode gives the agent a game-master prompt. The user switches to the MUD mode and begins playing; the server adapts the available actions to the current room.
The player can move between rooms, travel east or north, and pick up items. Fighting makes sense only when a monster is present, so the battle tool should be absent in an empty room. When the player eventually encounters a goblin, the battle tool appears. Availability expresses the game’s current state instead of requiring the model to infer that an always-visible action is temporarily invalid.
The selection rule can be expressed directly in Python. This small example isolates the inventory decision: entering the goblin encounter exposes battle; it does not execute a battle.
python
from dataclasses import dataclass
@dataclass(frozen=True)
class Room:
exits: tuple[str, ...]
items: tuple[str, ...] = ()
monster: str | None = None
def available_tools(room: Room) -> list[str]:
tools = []
if room.exits:
tools.append("move")
if room.items:
tools.append("pick_up")
if room.monster is not None:
tools.append("battle")
return tools
empty_room = Room(exits=("east", "north"))
goblin_room = Room(exits=("east", "north"), monster="goblin")
assert available_tools(empty_room) == ["move"]
assert available_tools(goblin_room) == ["move", "battle"]
The MCP integration must expose the changed inventory through discovery so the client can make the new action available to the model. The useful boundary is between an action becoming possible and the agent choosing to perform it.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Expose artifacts and understand the workspace
An action may produce context without needing to place all of it in the immediate tool response. Instead of returning a giant file, a server can return a reference that the model follows when needed or that the user acts on directly. Resource links in tool results were still prospective here and subsequently appeared in the June 2025 specification revision.
Resources give artifacts meaning beyond a text response. A screenshot captured through Playwright should be accessible to both the model and the user. Treating it as a resource preserves that shared role: the artifact is something to inspect or use, rather than merely content buried inside an action’s output.
A development server can also adapt to information already present in the workspace. It can inspect the Python environment and settings, then use installed packages and libraries to distinguish a React project from a Svelte project. This avoids repeatedly asking the user to identify a framework that the project itself reveals. Reading CI/CD configuration extends the same approach through the delivery pipeline, connecting local development with the rest of the workflow.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Request model work through the client
Sampling lets an MCP server request an LLM completion from the client. The sampling specification calls this operation sampling/createMessage. “From the client” identifies who mediates access; it does not require the model to run locally. In the demonstration, VS Code displays a permission dialog before allowing the server to access the model. Kirschner identifies GPT-4.1 as that implementation’s default, not a protocol requirement. The client retains control over model selection and permissions.
Structured formatting for sampling is described as further specification work. That distinction matters because a server requesting a completion still needs to handle the response format its client supports; later structured tool output is a separate capability.
Sampling provides a natural path to progressive enhancement:
- Summarize resources: turn a large resource into a more focused representation instead of always returning everything.
- Prepare fetched content: convert a website into Markdown suitable for the model’s next step.
- Run agentic server tools: let a server’s workflow request model work through the client.
The server can supply useful content without sampling, then perform additional processing when the client supports it. This makes model access an enhancement to the interaction rather than an assumption hidden inside every tool.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Keep both sides of the connection current
The dungeon’s changing tool set is one instance of a broader pattern. Roots, resources, tools and prompts participate in an interaction whose context can change after the connection begins.
| Origin | What changes |
|---|---|
| Client | Workspace roots as the VS Code workspace changes |
| Server | Available resources, tools and prompts as server state changes |
Discovery therefore needs to be treated as an ongoing exchange, not just an initial inventory. The client keeps the server informed about the workspace, while the server keeps the client informed about what it can currently provide.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Debug the process the host launches
Richer server behavior also needs a workable development loop. VS Code provides an MCP server console for diagnostic output, then adds a development-mode toggle that enables debugger attachment. In the demonstration, invoking a prompt generated by the server reaches a breakpoint in its implementation.
The difficulty is process ownership: an MCP server is often launched by its client or host, rather than by a command the developer starts manually under a debugger. VS Code occupies both roles, so it can launch the server and attach its debugger. The historical automatic debugging support covers Node.js and Python servers launched with node and python, respectively.
That turns debugging into a direct loop:
- Enable development mode for the server.
- Set a breakpoint in the server implementation.
- Invoke the server-generated prompt from chat.
- Step through the handler and inspect its state.
The important improvement is that the interaction being debugged comes from the actual MCP host, rather than requiring a separate manual reproduction of the server call.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Exercise authorization and transport before they harden
Draft specifications need implementation feedback before they become stable. Otherwise, a feature can advance without enough real use to expose its problems, leaving a later revision to repair them. Kirschner uses authorization as the example and characterizes its update as enabling enterprise-grade authorization. He points to Ben’s protected-server session for a deeper discussion.
Transport support has a similar dependency on adoption. Kirschner says VS Code had supported Streamable HTTP for two releases, but the small number of hosted servers using it made interoperability difficult to test. His recommendation to hosting providers is to move from the older HTTP+SSE transport to Streamable HTTP.
This is not a recommendation to abandon SSE itself. The Streamable HTTP transport specification retains optional SSE streaming and permits stateful sessions. The distinction is between the older transport arrangement and the newer HTTP-based one, not between streaming and non-streaming, or stateful and inherently stateless servers. Kirschner’s stated operational benefit is avoiding the older arrangement’s stateful server churn.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Help users find servers and supply missing information
Discovery also has a meaning outside an active connection: how does a user find a server in the first place? Passing configuration JSON blobs from developer to user is a cumbersome distribution mechanism. The community MCP Registry is presented as public work toward making servers easier to discover. This complements dynamic capability discovery: one helps users find a server; the other helps a connected client understand what that server currently offers.
Once a tool is running, another gap can appear: the model has supplied arguments, but the workflow still needs concrete information from the user. Elicitation, presented here as an upcoming draft capability and later included in the June revision, lets the server reach back for that information. Instead of sending the user into another chat experience, the client can offer a direct input interaction. The tool workflow can then continue with information supplied by the person who actually knows it.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Make richer implementations useful enough to spread
Progressive enhancement gives server authors a way to build beyond tools without waiting for every client to catch up. Implement richer behavior in clients that support the relevant capabilities, test it with real users, and publish examples that show why stateful interactions are useful. Reference servers and shared practices can turn isolated implementations into patterns other developers can adopt. As users demonstrate those benefits, they create demand for missing client support.
The design target is an action-oriented server that understands context and exposes meaningful artifacts. Contributing to that target includes reading open proposals such as namespaces and search, following the corresponding SDK issues, and reporting implementation experience. Kirschner emphasizes that this feedback has practical influence: the VS Code team reads incoming MCP issues and uses them to shape its roadmap.
Sampling is his final example of a capability worth asking clients to support. The remaining work is not only to extend the specification, but to make its existing capabilities usable across implementations. A server that demonstrates a better interaction—and supplies concrete feedback when a client cannot support it—helps close that gap.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
From the talk
The March 2025 protocol contract for servers requesting model generations through clients, including permissions and model preferences.
Streamable HTTP's request flow, optional SSE streaming and session management in the March 2025 specification.
The community registry project for publishing and discovering MCP servers.
Further reading
Historical release documentation for MCP prompts, resources, experimental sampling, tool sets and server debugging.
A dungeon game server illustrating tools that appear as game state changes, alongside resources, prompts and sampling.
LangChain's experiments on how additional tools and instructions affect a ReAct assistant's calendar and customer-support tasks.
Updates since the talk
- MCP June 2025 specification changesDocumentation
The subsequent specification revision adding elicitation, resource links, structured tool output and revised authorization requirements.
Read the transcript and explore slides
Loading transcript and slides…