{"id":"2076440928726708612","url":"https://x.com/_overment/status/2076440928726708612","text":"","author":{"name":"Adam","username":"_overment","avatarUrl":"https://pbs.twimg.com/profile_images/1919648969363251201/F2dwDJPF_200x200.jpg"},"createdAt":"Sun Jul 12 22:57:50 +0000 2026","engagement":{"replies":18,"retweets":27,"likes":180,"views":82622},"article":{"title":"I was wrong about MCPs","previewText":"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","coverImageUrl":"https://pbs.twimg.com/media/HND9zGvXcAAuCKW.jpg","content":"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?\n\n![](https://pbs.twimg.com/media/HND4S1dXYAA7s2E.png)\n\nTo 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.\n\n## Concept behind Model Context Protocol\n\nIf 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.\n\n![](https://pbs.twimg.com/media/HND4b73XMAAtChS.png)\n\nIn 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.\n\nCompared 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.\n\n![](https://pbs.twimg.com/media/HND4kKUWwAAhzRW.png)\n\nWhen 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.\n\nFor 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.\n\nKnowing all this, let's broaden the perspective and think about MCPs beyond integrations alone.\n\n## Moving beyond integrating services\n\nTo explore what MCPs can really do, let's look at [Kody](https://github.com/kentcdodds/kody) a personal assistant built by [Kent C. Dodds](https://x.com/kentcdodds) (& contributors), that focuses on generalized capabilities rather than direct integrations.\n\nRunning 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.\n\n![](https://pbs.twimg.com/media/HND46WoXUAAXw1z.png)\n\nAt its core, the assistant comes down to just two tools:\n\n- search: finds and/or loads Kody's capabilities\n\n- execute: runs TypeScript code inside Kody's runtime, with direct access to all its features.\n\nTogether, they let the agent explore available capabilities, including ones created during previous interactions, and use them within scripts. Sounds powerful. But why?\n\nWell, 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! \n\n![](https://pbs.twimg.com/media/HND5FzrWIAAIrG_.png)\n\nKody 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.\n\nEither way, this approach is far more reliable and efficient.\n\n![](https://pbs.twimg.com/media/HND5LWkWMAEWWLE.png)\n\nCode 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.\n\n> Note: what follows matters not just for MCP, but for working with AI agents in general.\n\nSo 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.\n\nLet’s consider a few examples here, by looking closer at Kody’s architecture.\n\n## #1 Packages\n\nAs mentioned, an assistant can either perform every action step by step each time, or write a script to save and reuse later.\n\nIn 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.\n\n![](https://pbs.twimg.com/media/HND99idW8AAO-Zu.jpg)\n\nFrom a technical perspective:                                                                                                     \n\n- D1 Database keeps track of the package and its details.                                                                                                                    \n\n- Cloudflare Artifacts holds the original, versioned source code\n\n- Cloudflare KV stores the package’s ready-to-run bundles.                                                                                                          \n\n- Cloudflare Workers provide an isolated environment in which the code runs.\n\n- Cloudflare Durable Objects preserve data and support realtime sessions or long-running services when needed. \n\nPackages 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.\n\n## #2 Integrations\n\nThe 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.\n\nThis 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.\n\nThe example below shows two scenarios: \n\n- one where a missing integration stops the agent cold, \n\n- and one where the agent configures a connection and builds reusable behavior around it, simply asking the user for help with authorization.\n\n![](https://pbs.twimg.com/media/HND5qaOXMAAnyqT.png)\n\nFrom 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.\n\n![](https://pbs.twimg.com/media/HND5vYJWUAAsaEw.jpg)\n\nThis 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! \n\nAnd 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.\n\n## #3 Jobs and Workflows\n\nPurely 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.\n\nWith 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. \n\n![](https://pbs.twimg.com/media/HND55RaXsAABnN6.png)\n\nFrom a technical perspective:\n\n- D1 tracks Job schedules, Workflow statuses, and executions\n\n- Cloudflare Artifacts keep the source code for Jobs and Packages\n\n- JobManager Durable Objects wake Kody up for scheduled Jobs\n\n- Workflows manage durable runs, including waits and retries\n\n- Workers execute Job packages and inline Workflow code\n\n- StorageRunner Durable Objects preserve Job data between runs\n\n- After execution, D1 records the outcome and, for recurring Jobs, the next run time\n\nHere's how Jobs and Workflows differ:\n\n![](https://pbs.twimg.com/media/HND6MU0XoAAMzJb.png)\n\nJobs, 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.\n\nWorkflows, 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.\n\n## #4 Memory\n\nAgents 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](https://x.com/quarqlabs/status/2061571757488972153) and [Observational Memory](https://mastra.ai/blog/observational-memory) which can be combined and achieve impressive results. \n\nKody keeps it simpler: a search tool with hybrid search underneath, combining lexical matching and vector search, plus some filtering and re-ranking on top. \n\nIn 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.\n\n![](https://pbs.twimg.com/media/HND6f2dXwAAsvQ3.png)\n\nAnd 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.\n\n![](https://pbs.twimg.com/media/HND6muSWUAAYYNq.png)\n\nIt’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. \n\n## #5 Values\n\nSome 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.\n\nUnlike 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.\n\nFor example, if a Package includes a UI, an app-scoped Value can preserve the user’s settings between sessions.            \n\n![](https://pbs.twimg.com/media/HND6t31XsAAjDFV.png)\n\nThis 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?\"                                                         \n\n![](https://pbs.twimg.com/media/HND6yEQXMAAfJga.png)\n\nValues are best suited to the latest small configuration value. Location history or a larger collection of records would belong in Storage instead. \n\n## #6 Storage\n\nA Package, Job, service, app, or execution may need its own private database for runtime state and accumulated records.\n\nInstead of representing this information as individual Values in Kody’s central D1 database, Kody assigns the runtime a StorageRunner Durable Object.\n\nTechnically, 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.\n\n![](https://pbs.twimg.com/media/HND68vHWAAARsnj.png)\n\n## #7 Remote Connectors and External MCP Servers \n\nAs 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.\n\nIt supports two connection models:\n\n- Kody can act as MCP Client itself and access external MCP Server tools through kody.mcp interface\n\n- Local processes can reach Kody and expose their tools through kody.remote interface\n\n![](https://pbs.twimg.com/media/HND7HrpXgAAoOFy.png)\n\nIn 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.\n\n## Takeaway\n\nShifting 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.\n\nHere are a few points worth taking away:\n\n- Code mode: Reasoning models can generate useful code. Rather than forcing every task through predefined tools, give agents a sandboxed runtime where appropriate. Dedicated tools still matter when stable interfaces, permissions, and auditability are required.\n\n- Determinism: LLM behavior can vary, especially when sampling is used. Instead of trying to remove that variability entirely, use it during generation and evaluation. An agent can generate an implementation, test it, and revise it. Once validated, running that implementation is usually faster, cheaper, and more reliable than repeating the full reasoning process each time.\n\n- Generalization: Instead of implementing every action ourselves, we can shape environments where agents create and execute task specific actions, while code enforces constraints and verifies outcomes deterministically.\n\n- Primitives: Components designed around one narrow use case limit agents. Prefer small capabilities with clear contracts that can support several use cases without becoming vague or unsafe.\n\n- Composition: Agents can compose primitives when their interfaces, permissions, and failure modes are explicit. Instead of building each workflow ourselves, we need to give agents reusable components they can safely assemble into new workflows.\n\n- Control: Agents generating their own capabilities creates legitimate engineering risks. The answer is not to ignore them or stop exploring, but to constrain execution through sandboxing, least privilege, validation, observability, approval gates, and rollback.\n\n- Verification: Deterministic execution does not guarantee a correct outcome. Verification must test explicit invariants, permissions, and expected effects. Where success cannot be formalized, use evaluation, human review, or bounded uncertainty.\n\nThat'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.\n\nI’m curious what you think about all this, so feel free to leave a comment or repost it if you find it useful."}}