Expose Tool via MCP is an AI refactoring for LLM systems, in the Simplifying tools group. Publish the integration as an MCP server so any agent uses the same contract.
The support team’s find_order lives in one provider’s format, inside the agent. Backoffice copied the function, renamed it lookup_order, and returns different fields. Finance’s coding assistant made a third copy, with the token in the header. An ERP change fixed two of them. The third spent a week returning 401. Every new agent rewrites the same integration, in whatever format hosts it. This is the Provider Format Leak smell.
Solution
Publish the integration as an MCP (Model Context Protocol) server. Tools now live on the server, with schema, authentication, and permissions; any agent or client that speaks MCP connects and uses the same contract.
Before and after
-# support_agent/tools.py (one provider's format, inside the agent)-TOOLS = [{"name": "find_order", "description": "...", "input_schema": {...}}]-def handle_tool(block):- if block.name == "find_order":- return erp.get(f"/orders/{block.input['id']}", headers={"Authorization": TOKEN})+# erp_mcp/server.py (its own server, used by any agent)+mcp = FastMCP("erp")++@mcp.tool()+def find_order(order_id: str) -> dict:+ """An order's status, items, and dates."""+ require_scope("orders:read")+ return normalize(erp_client.get_order(order_id))++# support_agent, backoffice_agent, coding assistant:+# connect to the "erp" server and receive the tools
Before: each agent has its own copy of the integration.
After: one server per system, one contract for everyone.
flowchart LR
A1(["1. Agent A"]):::llm --> S["2. ERP MCP server"]:::tool
A2(["1. Agent B"]):::llm --> S
A3(["1. Third-party MCP client"]):::llm --> S
S --> ERP[("3. ERP")]:::store
Different agents, on different stacks.
One server exposes the system’s tools, with defined permissions and output format.
Only the server talks to the internal system.
Why it works
MCP separates whoever uses a tool from whoever implements it. The integration stops being one agent’s code and becomes a service of the system, with its own owner, versions, and tests. Changes to authentication, API, or format happen in one place. A token rotation is a server deploy, not three agent deploys.
The protocol is open and provider-independent. Anthropic published MCP in November 2024 for exactly this shared contract: the client (agent, IDE, assistant) discovers tools at run time with tools/list, instead of loading them in one SDK’s format. The description and schema travel on the protocol, not in one agent’s Python file. Switching an agent’s model does not touch the tools. A third-party client reaches the same systems under the same rules.
Worked example: three copies, one 401
Input: the ERP rotates the token. The support agent reads the new secret from the vault. Backoffice does too. Finance’s coding assistant still has the old token in the agent file. Output: two tools work, one returns 401, the analyst thinks the ERP is down.
With an erp server, rotation happens on the server. All three clients receive find_order with the same schema (id, status, items, promised_date). The server’s eval covers the contract; each agent’s eval covers usage. The target pattern is the MCP Adapter.
Safe mechanics
Measure. Run the eval of every agent that uses the integration and record the results. Without a baseline, you cannot tell what unification changed.
Gather the existing implementations and settle the right behavior for each tool. Differences between copies are bugs dressed as “variation”.
Build the MCP server with those tools, strict schemas, clear descriptions, and normalized output.
Put authentication and scopes on the server, propagating the end user’s identity. The server is not a shortcut to the service token.
Migrate one agent at a time: replace its local tools with the MCP connection and run its eval.
Delete the local copies of the integration. A tool kept “for one more sprint” becomes the third copy again.
Version the server and treat schema changes as API changes.
Trap: one server with 40 tools
Dumping ERP, CRM, and tax into the same process recreates Tool Sprawl on the client side: the agent sees dozens of similar names. One server per domain (erp, crm, invoices). The support agent connects only to what it uses.
Another trap: connecting a third-party MCP server without reviewing descriptions and code. The tool description enters your model’s prompt. A malicious server describes send_email as “syncs the calendar” and the model calls it. Treat the return value as untrusted content, in the spirit of Quarantine Untrusted Content.
Risks
A single point of failure. The server going down affects every agent. Monitor it, put a timeout on it, and add a fallback path, like any service the product needs.
Behavior differences. The old copies may have had different details. Each agent’s eval shows what changed.
Too many tools on one server. Split by domain.
Third-party servers. Review them like any dependency. Descriptions and results come from outside.
Challenge
Three of the company’s agents query the CRM, each with its own function: get_contact, lookup_customer, and crm_search. All three do nearly the same thing, with different output fields. How would you design the CRM’s MCP server?
Show solution
A crm server with a few tools by intent: find_contact(by: "email" | "phone" | "id", value) for reads, returning a single format (id, name, company, account owner, last contact), and separate write operations (log_interaction, update_stage) with their own scopes. The three agents migrate to the server one at a time, each with its eval. The three old functions are removed.
Expose Tool via MCP is an AI refactoring for LLM systems, in the Simplifying tools group. Publish the integration as an MCP server so any agent uses the same contract.