I was wrong about MCPs

MCP servers often focus on integrating a single service, giving the agent new tools and/or context. But what if we shift our perspective and break a few familiar patterns, turning MCP into a set of new capabilities the agent can use however it needs?

To be clear - MCPs and CLIs built around a single service work perfectly well for many use cases. What follows is a different approach, one that reaches far beyond direct integrations. Whether or not you find it useful, it may change how you think about the programmer’s role in the AI era.
Concept behind Model Context Protocol
If you haven't come across it yet: the Model Context Protocol (MCP) standardizes how AI agents, like ChatGPT, Claude, OpenCode, or Amp, connect to external systems. The protocol does more, but its core use case is simple: delivering JSON Schemas that describe which tools an agent can select, and what arguments to call them with.

In practice, an existing API, say Resend's, can be translated into a set of tools optimized for AI agents, letting them send emails, manage contacts, or launch campaigns, for example.
Compared to the raw API, MCP tools provide context LLMs lack by default: descriptions and hints that increase the odds an action succeeds, or that the agent recovers when it doesn't. Below is a scenario where the agent gets stuck using the raw API to send an email, due to a missing property. In the MCP scenario, it gets a clear hint on how to recover from the error.

When an agent uses a well-known service like GitHub, it already knows the interface. There's little value in additional context here. But with less popular services, the agent either fails and learns from errors, or has to find the latest docs first to learn how to use it.
For coding agents, CLI tools are often more convenient than MCPs: they have native access to bash and, through it, to the entire device they control. This works well for a single user and simple integrations, but the advantage fades the moment you go beyond a single-user context or move remote. So the whole "MCPs vs CLIs" debate doesn't really make sense, we're talking about different use cases.
Knowing all this, let's broaden the perspective and think about MCPs beyond integrations alone.
Moving beyond integrating services
To explore what MCPs can really do, let's look at Kody a personal assistant built by Kent C. Dodds (& contributors), that focuses on generalized capabilities rather than direct integrations.
Running on Cloudflare, Kody can remotely connect to any agentic harness that supports MCP, or work in the background, on a schedule or in response to events. In practice, the assistant is available wherever the user is: OpenAI Codex, Anthropic Claude Code, or any custom UI.

At its core, the assistant comes down to just two tools:
Together, they let the agent explore available capabilities, including ones created during previous interactions, and use them within scripts. Sounds powerful. But why?
Well, ask a typical agent to "prepare a weekly email report" and it has to perform a whole series of actions to get there. And since LLMs are non-deterministic, the risk of something going wrong compounds with every additional step!

Kody takes a different path. **It writes and tests a script that fetches all messages once, then saves it as a Package.** From then on, it simply reuses the Package. Since code is mostly deterministic, the results remain consistent unless the script calls an LLM, for example, to summarize the messages, or contains other logic that introduces randomness or produces unpredictable results.
Either way, this approach is far more reliable and efficient.

Code execution is just the tip of the iceberg. What makes this MCP special are its native components, and they're generalized in a way that goes well beyond a typical integration.
Note: what follows matters not just for MCP, but for working with AI agents in general.
So instead of thinking in terms of every single feature, we should elevate our thinking toward system design and product engineering. That shifts our focus away from details AI already handles with ease, toward the high-level concepts that shape the environment agents operate in. This won't come out of thin air, though: it requires a deep understanding of user context and possible use cases, far beyond a simple requirements doc describing a given feature.
Let’s consider a few examples here, by looking closer at Kody’s architecture.
#1 Packages
As mentioned, an assistant can either perform every action step by step each time, or write a script to save and reuse later.
In an example below, the user asks the agent for a podcast that highlights the most important news. The logic for it is then designed, tested and stored. It may be even shared with others! And from now on, whenever the users asks for the podcast, the agent simply picks the right package and executes it.

From a technical perspective:
Packages are a clever way to leverage how good AI has become at programming, letting agents work smart instead of hard. I don’t need to mention this saves tons of tokens, meaning your money.
#2 Integrations
The way of connecting agents with external apps and services is another of Kody's components, and another example of how we can shift our programming mindset. Instead of building dedicated integrations with communicators, email, calendars, issue trackers, maps, or various devices, Kody provides generalized primitives for OAuth, API credentials, OpenAPI specifications, external MCP servers, and private-network connectors. Then it exposes their functionality to the "execute" tool's runtime.
This makes the agent independent enough that when it faces a task requiring an integration it doesn't have, it simply creates one, asking the user to log in or securely provide an API key.
The example below shows two scenarios:

From a technical perspective, Kody owns the reusable authentication machinery, so the agent doesn't have to rebuild everything from scratch every time. Instead, it focuses on supplying the provider-specific configuration and deciding what to do with the resulting connection. The diagram below shows this in action.

This is the reality we live in. Many of us remember when building an OAuth integration took hours. Now agents generate them on the fly, needing only a little steering. Realizing this is what moved Kent's assistant from one that needs integrations built by hand to one that builds them on its own!
And there's a bonus here: the assistant generally improves automatically with every upgrade of the LLM it runs on. And "the acceleration is accelerating", as you've probably noticed.
#3 Jobs and Workflows
Purely reactive agents, ones that only act when prompted, still have their uses, but they're starting to feel like a relic. Today, an agent shouldn't just respond to what we say - it should also act when we're not around.
With the Packages Kody can build, background tasks naturally come to mind. After all, once the code is written, it can run automatically, without involving the LLM at all. And since the Jobs and Workflows are Kody’s native capabilities, it can manage them on its own.

From a technical perspective:
Here's how Jobs and Workflows differ:

Jobs, in a nutshell, pair a one-time or recurring schedule with code to execute, either a standalone snippet or a package-owned job entry. They're great for automations like sending follow-ups or generating reports.
Workflows, in turn, rely on Cloudflare Workflows to manage individual durable executions. They come in handy when work needs to wait, continue beyond the original request, avoid duplicate runs, or retry after a failure, which makes them a natural fit for multi-step tasks.
#4 Memory
Agents need memory so they can act without being handed every detail each time. And while agentic memory remains an open problem, some promising strategies are already out there, like the Quarq Agent and Observational Memory which can be combined and achieve impressive results.
Kody keeps it simpler: a search tool with hybrid search underneath, combining lexical matching and vector search, plus some filtering and re-ranking on top.
In practice, you can ask the agent to remember something, and it prepares a new entry candidate and compares it against existing records. Based on that, the agent decides whether to store a new memory or update an existing one.

And since memory is just another capability, it combines easily with other actions, including those performed through Packages. Say we tell the assistant about our favorite places, later, we can simply ask for directions to that restaurant we enjoyed last time.

It’s worth noting that "agentic memory" doesn’t necessarily work like human memory. Depending on the implementation, an agent may not realize it knows something and, even when asked about it directly, may fail to retrieve the relevant memories. This can lead to confabulations or degraded performance.
#5 Values
Some code snippets, Package apps, Jobs, or Workflows need stable configuration that can be read again later. Kody provides the Values capability for storing small, readable settings within the context of a session, app, or user.
Unlike Memory, Values are retrieved deterministically by name rather than contextually by meaning or pattern matching. They are intended primarily for non-sensitive configuration, such as a time zone, selected workspace, report format, or default project.
For example, if a Package includes a UI, an app-scoped Value can preserve the user’s settings between sessions.

This simple primitive can support many useful scenarios. For example, a background Job could periodically update a user-scoped **currentCity** Value. A Package or agent could then retrieve it explicitly when answering a question such as, "Where can I find good food nearby?"

Values are best suited to the latest small configuration value. Location history or a larger collection of records would belong in Storage instead.
#6 Storage
A Package, Job, service, app, or execution may need its own private database for runtime state and accumulated records.
Instead of representing this information as individual Values in Kody’s central D1 database, Kody assigns the runtime a StorageRunner Durable Object.
Technically, Kody Storage is a private, durable database tied to a single runtime identity. The Worker executing the code is temporary; the data it writes persists.

#7 Remote Connectors and External MCP Servers
As mentioned, Kody is an MCP server that exposes two tools, search and execute, along with a set of capabilities. Agents acting as MCP clients can connect to Kody and interact with these tools. But Kody can also extend its capability registry with tools provided by external systems.
It supports two connection models:

In both cases, the additional tools become part of the user’s isolated Kody environment. The agent can discover them through search and invoke them from execute, just like Kody’s built-in capabilities.
Takeaway
Shifting the perspective from a connector to a capability layer makes the concept of an MCP server far more flexible and, in many ways, truly AI-native. Rather than viewing an agent’s capabilities through the lens of old programming habits, where everything had to be built by hand, Kent draws on nearly everything AI can do today to create an assistant that overcomes many of the limitations typical agents face. Most importantly, his assistant improves as the underlying models improve - something worth keeping in mind whenever we design for AI.
Here are a few points worth taking away:
That's it. I was wrong about MCPs. I used to think of them as connectors with a few extra features coming from the protocol itself, and assumed the entire capability layer had to be tied directly to the host.
I’m curious what you think about all this, so feel free to leave a comment or repost it if you find it useful.

