I have a confession to make.
For the last year and a half, I haven't been building "Cutting Edge AI Systems". I've been building duct tape.
Digital duct tape.
I've spent hundreds of hours writing wrappers around APIs. I've written translators to convert OpenAI function definitions into Anthropic tool schemas. I've debugged why a Llama 3 model running locally couldn't understand the same JSON structure as GPT-4.
It was exhausted. It was wasteful. It was janitorial work masquerading as engineering.
Every time a provider updated their SDK, my glue code broke. Every time I wanted to swap models, I had to rewrite the orchestration layer.
That era ended on December 9th.
The Agentic AI Foundation (AAIF) launched. Hosted by the Linux Foundation. Backed by Google, Microsoft, OpenAI, and Anthropic.
They have agreed on a standard. The protocol wars are over.
If you are currently writing custom integrations for your AI agents, stop. You are building technical debt.
I've written a comprehensive deep-dive on the strategic implications here, but in this article, I want to show you the code. I want to show you how to build an agent tool that works with everything, right now.
The Problem: The Tower of Babel
To understand why I'm so relieved, we need to look at the mess we're leaving behind.
Let's say you wanted to give an AI agent access to check the status of your production servers. In the "Old World" (last month), you had to write a specific definition for the model you were using.
If you were using OpenAI, you wrote this:
// The "Old Way" - Vendor Lock-in
const openAITool = {
type: "function",
function: {
name: "check_server_health",
description: "Checks CPU and Memory usage of a specific server instance",
parameters: {
type: "object",
properties: {
instanceId: { type: "string" },
region: { type: "string" }
},
required: ["instanceId"]
}
}
};
Then, if you wanted to switch to Anthropic, you had to rewrite it. If you wanted to use LangChain, you wrapped it in their abstraction. If you used Microsoft Semantic Kernel, you did it their way.
You weren't building a tool. You were building a plugin for a specific walled garden.
The Solution: Model Context Protocol (MCP)
Anthropic donated the Model Context Protocol (MCP) to the foundation.
Think of MCP as a USB port for AI.
When you plug a mouse into your computer, the computer doesn't need to know if it's a Logitech or a Razer. It just knows it speaks "USB Mouse".
MCP does the same for AI tools. You build an "MCP Server" that exposes your tools. Any "MCP Client" (Claude Desktop, Cursor, your own custom agent) can connect to it.
The model asks: "What can you do?"
The server replies: "I can check server health."
The protocol handles the rest.
Let's build one.
Tutorial: Building a DevOps MCP Server
We are going to build a simple MCP server that gives an AI agent read-access to a hypothetical system log. We will use TypeScript because type safety is non-negotiable in production.
1. Setup
First, forget about installing the OpenAI SDK or the Anthropic SDK. We don't need them. We only need the MCP SDK.
mkdir mcp-devops-monitor
cd mcp-devops-monitor
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node tsx
npx tsc --init
2. The Server Code
Create a file called index.ts.
We are going to do three things:
- Create the server instance.
- Define a "Tool" (a capability).
- Handle the execution of that tool.
// index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// Create the server instance
const server = new McpServer({
name: "DevOps-Monitor",
version: "1.0.0",
});
// Mock database of server logs
const SERVER_LOGS = {
"prod-us-east": "CPU: 12% | Memory: 45% | Status: HEALTHY",
"prod-eu-west": "CPU: 98% | Memory: 92% | Status: CRITICAL",
"staging": "CPU: 0% | Memory: 1% | Status: IDLE"
};
// REGISTER THE TOOL
// Notice: No vendor-specific JSON here. Just Zod schema.
server.tool(
"check_status",
"Get the current health metrics of a server instance",
{
instanceId: z.string().describe("The ID of the server (e.g., prod-us-east)"),
},
async ({ instanceId }) => {
// This is where you would call your real API
// AWS SDK, Datadog API, etc.
console.error(`[LOG] Agent requested status for ${instanceId}`);
const status = SERVER_LOGS[instanceId as keyof typeof SERVER_LOGS];
if (!status) {
return {
content: [{
type: "text",
text: `Error: Server '${instanceId}' not found.`
}]
};
}
return {
content: [{
type: "text",
text: status
}]
};
}
);
// Connect via Stdio
// This allows the agent to run this process locally and talk over Stdin/Stdout
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("DevOps MCP Server running on stdio...");
Read that code again.
Do you see any mention of GPT-4? Any mention of Claude? Any mention of temperature settings or tokens?
No.
This is pure functionality. It describes what it does, not who it talks to.
3. Running It (The Magic)
This is where it gets interesting. You don't "run" this server and visit localhost:3000. This server is designed to be spawned by an Agent.
If you have the Claude Desktop app installed (or any MCP-compliant client), you can hook this up immediately via configuration.
Add this to your claude_desktop_config.json:
{
"mcpServers": {
"devops-monitor": {
"command": "npx",
"args": [
"-y",
"tsx",
"/absolute/path/to/mcp-devops-monitor/index.ts"
]
}
}
}
Restart Claude. Look at the attached tools icon.
You will see check_status.
You can now type: "Check the health of the eu-west production server."
The model will see the tool definition, formulate the request, send it to your local Node process via standard IO, execute the function, and render the result.
If you switch your underlying model in the client? The code doesn't change.
If you switch to a different MCP client entirely? The code doesn't change.
This is interoperability. Finally.
The Missing Piece: Context
Tools are only half the battle. The other reason agents fail in production is that they don't understand the context of the project.
Usually, we solve this by pasting massive "Context Dumps" into the system prompt.
"You are a coding assistant. We use React. We use Tailwind. Do not use generic CSS. Here is our folder structure..."
It's brittle. It's hidden in prompt configurations. It's not version controlled.
The AAIF also introduced AGENTS.md. OpenAI donated this standard.
It is basically a README.md for robots.
In your repository root, you create an AGENTS.md file. This acts as the authoritative source of truth for any agent entering your codebase.
Here is what it looks like for our DevOps tool:
# AGENTS.md
## Scope
This repository contains the MCP Server for the DevOps Monitor tool.
## Code Style
- Use TypeScript for all logic.
- Use Zod for schema validation.
- DO NOT use `console.log` for debugging, use `console.error` as `console.log` interferes with the MCP JSON-RPC transport.
## Capabilities
The `check_status` tool is read-only. It simulates a database lookup.
## Known Issues
- The `prod-eu-west` server frequently reports high CPU. This is a known false positive.
When an MCP-compliant agent (like the new ones being built with goose, another AAIF donation) enters this directory, it reads this file.
It learns the rules.
If the agent tries to write a console.log, it will read the rule in AGENTS.md and correct itself to use console.error.
We have moved "Prompt Engineering" out of the chat window and into the file system. Where it belongs.
Why This Changes Everything
I am usually the first person to roll my eyes at a new "Standard".
(Plastic influencer. AI Fanboy. Cardboard expert. All terms entering the modern lexicon to describe the wave of 'hype' surrounding AI.)
But this is different.
- Vendor Neutrality: The Linux Foundation hosting this means no single company can pull the rug out from under us.
- Modular Security: Because the MCP server runs as a separate process, you can sandbox it. You can grant it read-only access to files. You don't have to give the LLM your root API keys.
- Ecosystem: We are about to see an explosion of "MCP Servers". Stripe will release one. AWS will release one. You won't have to write the integration code anymore. You'll just
npm install @stripe/mcp-server.
The Bigger Picture
We are moving from the "Wild West" phase of AI to the "Industrial" phase.
In the Wild West, you built everything yourself. You forged your own nails. You cut your own wood. It was exciting, but it didn't scale.
In the Industrial phase, we have standards. We have screw threads that match nuts. We have voltage standards for electricity.
The Agentic AI Foundation has given us our voltage standard.
Does this mean the end of innovation? No. It means the beginning of useful innovation.
We can stop arguing about how to format a JSON request and start focusing on what these agents can actually achieve when they can talk to every tool in your stack.
The plumbing is done. The water is flowing.
Now, if you will excuse me, I'm off to delete about 4,000 lines of proprietary wrapper code. (And I won't miss a single line of it).
TL;DR
- The Protocol Wars are over: Google, Microsoft, OpenAI, and Anthropic have united under the Linux Foundation.
- MCP is the standard: The Model Context Protocol standardises how agents connect to data and tools.
- Stop writing glue: Don't build custom API wrappers. Build MCP Servers.
- AGENTS.md: Use this standard file to document your code for AI, not just humans.
- It works now: You can run MCP servers locally with Claude Desktop or any compliant client today.
Full analysis with strategic breakdown →
Built something similar? Completely disagree? I'm genuinely curious.
More technical breakdowns at tyingshoelaces.com. I write about what works in production, not what looks good in demos.
Let's Chat
Are you going to refactor your current agents to use MCP, or are you waiting to see if the standard holds?
Top comments (2)
Totally! I'm particularly excited about ChatGPT Apps and the new MCP Apps extension protocol—I think that visual, interactive experiences is what takes MCP to the stratosphere!
That said, I also hesitate to go all-in on open standards to the exclusion of vendor-specific implementations personally. I figure there's always a world where (1) the 800-pound gorillas in the space do whatever they want, and (2) generic abstractions break down as platforms specialize & diverge. Like with React Native, you always end up needing some vendor-specific behavior to deliver the best possible experience. I think that core MCP falls more in the HTTP bucket while MCP Apps are closer to the React Native bucket. Stoked to see how it all plays out!
Really enjoyed this breakdown — your experience honestly makes everything way clearer. I’d love to learn more and talk about it with you.