I was digging through old code on my machine the other day. Back in 2023, when I first started building AI apps, I wrote a bunch of plugin-related stuff. OpenAI had just launched Plugins, it felt shiny, I followed the docs and wired up a couple. Looking at that code now feels like reading stone-age engineering.
Three years of AI-to-tool integration, three big steps: OpenAI Plugins → Function Calling → MCP. Each generation fixed the previous one's problems. Each generation had its share of wreckage. This post walks through the timeline, what each generation solved, and what it left behind.
Generation 1: OpenAI Plugins (March 2023) — Beautiful on Paper, Painful in Practice
March 2023, OpenAI shipped ChatGPT Plugins. The AI community lost its mind. ChatGPT could finally reach the web and call external APIs! I remember staying up all night writing a "weather lookup plugin," deploying it, feeling like I was on the cutting edge.
In hindsight, Plugins' design was simple: you host a /.well-known/ai-plugin.json file on your server describing what your plugin does and how to call it. ChatGPT discovers it and knows how to invoke it.
Sounds a lot like MCP, right? It is. So why did Plugins die?
Problem one: locked into OpenAI. Plugins were a proprietary protocol. Only ChatGPT could use them. You wrote a plugin, it lived inside ChatGPT, and no other AI platform recognized it. Terrible deal for developers. Why build a custom integration for one platform?
Problem two: broken UX. Using a plugin in ChatGPT felt like getting redirected to another page. The experience was inconsistent. Plugin triggering logic was fuzzy. Sometimes ChatGPT didn't call a plugin when it should. Other times it called one when it shouldn't.
Problem three: the ecosystem never arrived. People were excited for a minute, then developer numbers flatlined. Why? Low ROI. Spend time writing a plugin, use it only inside ChatGPT, limited users, no monetization path.
That weather plugin I built? Barely anyone used it after launch. OpenAI stopped pushing Plugins, and the whole thing faded.
Generation 2: Function Calling (June 2023) — Practical, But Not Standard
After Plugins faded, OpenAI shipped Function Calling. This was more grounded.
The idea: when you call the LLM, you pass your supported functions (tools) as JSON Schema. When the model decides it needs a tool, it returns a function name and arguments. You call the real API yourself, then feed the result back to the model.
Roughly:
import openai
tools = [
{
"type": "function",
"function": {
"name": "search_hotels",
"description": "Search hotels",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"},
"check_in": {"type": "string", "description": "Check-in date"},
"check_out": {"type": "string", "description": "Check-out date"}
},
"required": ["city", "check_in", "check_out"]
}
}
}
]
# First call: let the model decide if it needs a tool
response = openai.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Find me hotels in Shanghai"}],
tools=tools
)
# Model returns it wants to call search_hotels
tool_call = response.choices[0].message.tool_calls[0]
print(tool_call.function.name) # "search_hotels"
print(tool_call.function.arguments) # '{"city": "Shanghai", ...}'
# You call the real API yourself
result = call_real_hotel_api(tool_call.function.arguments)
# Second call: feed the result back
response2 = openai.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": "Find me hotels in Shanghai"},
response.choices[0].message,
{"role": "tool", "tool_call_id": tool_call.id, "content": result}
],
tools=tools
)
# Model packages the result into a natural-language reply
Function Calling was genuinely more useful than Plugins. It was an open technical paradigm, not a platform-exclusive plugin system. After OpenAI shipped it, Anthropic and Google followed quickly. Everyone supported similar tool-calling mechanisms.
But Function Calling had a fundamental issue: it was an LLM-layer capability, not a real "tool-calling protocol."
Meaning: you still wrote all the glue code yourself. You defined functions, wrote parameter schemas, handled auth, called APIs, fed results back. Every AI app reinvented these wheels. And each LLM platform's Function Calling format was different. OpenAI's format wasn't Anthropic's, which wasn't Google's. Want to support multiple LLMs? Write multiple adapter layers.
Before we built our hotel MCP, we started with Function Calling. We wrote tons of adapter code: tool schemas, parameter validation, backend API calls, response formatting. Switch LLMs and we rewrote everything. That 1,000+ lines of adapter code? MCP replaces it with a few dozen lines of config.
Generation 3: MCP Protocol (November 2024) — Finally, an Industry Standard
November 2024, Anthropic launched MCP (Model Context Protocol). I didn't pay much attention at first. Another new protocol. The more I used it, the more I realized: this is the actual solution.
What separates MCP from the first two generations? It's a real, open, cross-platform tool-calling protocol.
Specifically:
- Open standard. Not a company's private property. Open source protocol. After Anthropic shipped it, OpenAI, Google, Cursor, and Windsurf all supported it.
- Server-client architecture. Tool providers implement MCP servers. AI apps connect as MCP clients. Implement once, every MCP-compatible client uses it.
- Standardized capability discovery. The client connects, auto-discovers tools, parameters, and response formats. No hand-written schemas.
- Cross-platform. Whether you use Claude, GPT, or any other LLM, as long as it supports MCP, it connects to the same MCP server.
This is like the move from custom API formats to RESTful standards. Every system had its own interface style. Then one standard emerged, and everyone stopped reinventing.
MCP's ecosystem grew fast. Tens of thousands of MCP servers now cover databases, cloud services, dev tools, industry data, and more. Our RollingGo hotel MCP is one of them. It has close to 300 GitHub stars, with both an MCP server and travel skills. It supports 40+ major LLM clients directly: Cursor, Claude Code, Codex, Windsurf, and more. Behind it: 500+ global suppliers and 2M+ hotel properties across brands. 110K+ direct-contracted hotels with direct inventory and real-time price confirmation. What you see is what you can book. Completely free, no call-volume limits. Developer partners can set country-based markup rates and earn commission, with orders and revenue visible in real time.
From Plugins to Function Calling to MCP, the biggest takeaway: we finally stop writing all that adapter code. Want to experience MCP-era developer productivity? Grab an API key and try it.
Setup in Qoder:
{
"mcpServers": {
"RollingGo-Hotel": {
"type": "sse",
"url": "https://mcp.rollinggo.ai/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
Restart Qoder and you're calling hotel search, room detail, and price confirmation directly. From Plugins to Function Calling to MCP, the productivity jump is order-of-magnitude.
Three Generations Side by Side
| Dimension | OpenAI Plugins | Function Calling | MCP Protocol |
|---|---|---|---|
| Launched | March 2023 | June 2023 | November 2024 |
| What it is | Platform-exclusive plugin system | LLM API tool-calling capability | Open tool-calling protocol standard |
| Openness | OpenAI private, ChatGPT only | Per-platform, formats differ | Open source, cross-platform |
| Developer effort | Write plugin manifest + backend | Write schema + glue code yourself | Implement MCP once, use everywhere |
| Tool discovery | ChatGPT auto-discovers | You pass schema to the model | Client auto-discovers from server |
| Status | Mostly obsolete | Still used, being replaced | Ecosystem growing fast, new standard |
Why Did MCP Win?
From Plugins to Function Calling to MCP, why did MCP come out on top? One core reason: it solved the "reinventing wheels" problem.
Plugins failed because they were closed. Developers wouldn't invest in one platform.
Function Calling worked but didn't scale. Every AI app wrote its own tool adapter layer. Too much repeated labor. Cross-platform compatibility was a nightmare. A tool written in OpenAI's format needed rewrites for Anthropic.
MCP won because it standardized tool adaptation. Tool providers implement MCP once. Every MCP-aware AI client uses it automatically. AI developers stop caring how each tool works. Just connect to the MCP server.
That's the power of standardization. Like USB-C unified charging. Like HTTP unified web communication. MCP unified how AI calls tools. Once the standard holds, the ecosystem snowballs: tool providers build MCP servers because they reach every MCP client. AI developers use MCP because tools are ready-made.
What This Means for Developers
If you're building AI apps and still hand-writing tool adapters with Function Calling, take MCP seriously. Function Calling works, but MCP eliminates a lot of repetitive work.
If you're on the data services or SaaS side, pay even closer attention. Building an MCP server is cheap. You immediately reach every AI app in the MCP ecosystem. That's a new distribution channel. Instead of negotiating with AI companies one by one, you put your MCP server out there and they find you.
MCP isn't perfect. I wrote about its boundaries and pitfalls in another post. But on "standardized tool calling" specifically, MCP is the best solution we have right now.
Closing Thoughts
Looking back at three years, the trajectory is clear: closed to open, fragmented to standardized, every app writing its own glue code to an ecosystem sharing one protocol. This mirrors web tech history almost exactly: custom interfaces to RESTful standards, private plugins to open APIs.
Tech evolves this way. A burst of competing approaches, then convergence to a widely accepted standard. MCP is that standard for AI tool calling.
Which generation did you start with? Plugins era, Function Calling era, or MCP era? Drop a comment.
Top comments (0)