MCP Plugin
An MCP plugin lets an AI application use tools implemented by another program. The application's host records each tool's description and execution address. Its dispatcher can then run a built-in tool locally or send an external call through an MCP client, while the external server keeps the tool implementation.
Suppose you need to read a project file and its retry-policy note. The host
already has read_file, but the note belongs to the Notes server. Adding that
server's tools gives the same dispatcher another destination. Think of the
tool pool as a directory with forwarding addresses: a description says what
you can request; its address tells the host where to send it. A correct address
still cannot make a missing note exist.
How an MCP Plugin Extends the Tool Pool
The host is the application coordinating the model and tools. It owns the tool pool and an MCP client for the Notes server. The server implements the external tools; it can run in a local process or as a remote service. Crossing the boundary in this drawing means leaving the host's executor, not necessarily crossing the internet. These roles follow the MCP architecture.
"Plugin" here is the host's packaging for integration configuration. MCP does not require every application to use that package format. Enabling the fixture integration tells this host to create its Notes client and discover tools.
MCP Plugin Step by Step
The default enables the Notes integration and requests note n1. Both calls
are authored test inputs so you can inspect routing without guessing what a
model might choose.
1. Start with the built-in tool. The host pool contains read_file, with a
route to its local executor. Both execution counters are zero. The integration
creates a Notes client inside the host; creation alone sends no tool call.
2. Discover the capability, then list the tools. The host sends
server/discover with request ID notes-1. The response advertises a tools
capability. Next, tools/list, ID notes-2, returns read_note, which accepts
a string id, and search_notes, which accepts a string query. At this
point the pool still contains one registered entry. The two returned
descriptions are data awaiting registration.
3. Register destinations. This host prefixes the external names with
notes. and retains the original server names in its routes:
| Exposed name | Runs through | Name sent to server |
|---|---|---|
read_file | Local executor | — |
notes.read_note | Notes client | read_note |
notes.search_notes | Notes client | search_notes |
The pool now has three entries. This prefix is a host naming choice. The server receives its own tool name when a call is dispatched. For model tool selection, the host offers names, descriptions, and input schemas; its executor objects stay inside the host.
4. Run the local call. Authored call c1 requests
read_file({"path":"README.md"}). The pool selects the local executor, which
reads the fixture file and returns Project: Sketchpad. The host attaches this
observation to c1. One local tool has executed; no external tool has run.
5. Route the external call. Call c2 requests
notes.read_note({"id":"n1"}). Its registered route selects the Notes client.
The client sends tools/call with request ID notes-3, server name
read_note, and the unchanged argument {"id":"n1"}.
6. Execute and return. The Notes server looks up n1 in its own fixture
collection. It returns Retry policy: Retry temporary failures up to three times. The complete result has isError: false, and its response ID is
notes-3. The host correlates that response with its pending call c2 and
attaches the observation. The final counters are one local execution and one
external execution.
The wire request ID and the originating call ID belong to different layers.
The host maps between them. The MCP
base protocol
defines request/response correlation; the fixture's c1 and c2 identifiers
are host bookkeeping. No final model answer is generated in this walkthrough.
Why a Listed Tool Can Still Fail
Keep the integration enabled and change the note ID to missing. Discovery
and registration produce exactly the same three-entry pool. The host finds
the route, the client sends the request, and the server runs read_note once.
The lookup now returns Note not found: missing with isError: true.
Availability answered whether the host could dispatch this tool. The lookup answered whether the requested data existed. The successful discovery cannot answer the second question in advance. In MCP, tool execution failures travel inside a tool result; protocol errors, such as an unknown server tool name, use a JSON-RPC error response. The tools specification defines the distinction.
Now disable the integration while retaining either note ID. The pool contains
only read_file. Call c1 still succeeds. The authored c2 probe cannot find
notes.read_note, so the host produces a local availability error without
sending any MCP traffic. It would be misleading to label that error a response
from a server the host never contacted.
Try the Integration disabled and Listed tool, missing note scenarios.
Each pauses before c2 is routed. Predict whether the server's execution
counter will increase, then advance the player to check.
Check the Failure Location Before Changing the Input
A tool integration failure and a failed lookup need different repairs. Use the registry entry, outbound call and returned failure flag to locate the problem:
| What this run shows | Where it failed | What to check next |
|---|---|---|
No notes.read_note entry; no tools/call | Host availability lookup | Enable the integration and check tool registration. Changing n1 cannot create a route. |
The route exists; read_note returns isError: true | Notes tool execution | Check the note ID and the server's data. Repeating discovery returns the same tool description. |
For another tool on the same Notes server, the host needs another description and server route in its directory. The existing client can carry that tool's calls. The dispatcher still looks up the requested name and follows the registered destination. This is the part that transfers beyond the two calls: adding a tool extends the registry without requiring a new dispatch procedure for every tool name.
Edge Cases
- No integration: the pool retains the built-in tool. An argument change cannot supply the missing external route.
- A missing note: the route exists and the tool executes, but its result reports failure. A delivered error is not a dropped packet.
- No search matches: the advertised
search_notesimplementation returns an empty-search message without an execution error. This tool is included in discovery, although the two-call demo invokes onlyread_note. - Tool discovery and permission: a discovered tool still needs to satisfy the host's policy before use. The read-only fixture policy permits these calls; Permission opens that separate decision.
Common Mistakes
- Treating a descriptor as executable code. The host needs an implementation or a route behind the name. A schema validates a call shape; it cannot read a note.
- Sending the host alias unchanged. Here
notes.read_noteidentifies a host entry, while the Notes server expectsread_note. - Counting discovery as tool execution. Capability discovery and listing leave both tool execution counters unchanged.
- Dropping the error flag. The next consumer needs the explicit failure signal even when the result contains readable text.
- Assuming the model chose an unavailable tool. The disabled scenario deliberately injects an authored availability probe. It makes no claim about how a real model would behave with that exposed tool list.
Protocol Revision Used by This MCP Plugin
This run uses MCP 2026-07-28. Requests carry their protocol version and
client metadata. The host chooses to start with server/discover, which asks
for supported versions and capabilities. Calling it is optional for clients;
it is not a mandatory session handshake. Earlier protocol revisions used
initialize followed by notifications/initialized. See the
discovery contract
and versioning explanation
when comparing examples from different revisions.
A Note on Simplification
This is an explainer with an in-memory host, one simulated server, two fixed calls, and a small fixture dataset. It is not a substitute for the protocol specification or formal training. Transport, authentication, permission negotiation, model decisions, streaming, retries, pagination, caching, subscriptions, resources, and prompts are omitted. The host-specific plugin package and alias convention are teaching choices. The inspector shows payload excerpts; the generated records retain required request metadata and response fields. Playback seconds are teaching time, not measurements of MCP latency.
Keep exploring
A few lessons that share the same technique or lead into the next idea.
Premium players need paid access. Every Explain doc is free.
Found a mistake or something unclear? Leave feedback.