MCP Is the Wrong Abstraction ![rw-book-cover](https://i.ytimg.com/vi/bAYZjVAodoo/maxresdefault.jpg) ## Metadata - Author: [[Theo - t3․gg]] - Full Title: MCP Is the Wrong Abstraction - Category: #articles - Document Note: --- tags: [React, Frontend, Web Performance, Frameworks, Ecosystem] author: [MISSING] source: Theo - t3.gg (YouTube) reference: [https://www.youtube.com/watch?v=LrUpYblQIV4] date created: {{date:YYYY-MM-DD}} {{time:HH:mm}} --- # 🏷️ Title: React is killing the web ## 🧰 Action Inbox - [H1] Draft a framework-evaluation checklist — share with Core and Hosting teams/https://www.youtube.com/watch?v=LrUpYblQIV4 #articleseed - [H5] Build a “JS on the critical path” explainer — Training team/https://www.youtube.com/watch?v=LrUpYblQIV4 #articleseed - [H3] Produce a “useEffect pitfalls” clinic — DevRel + Docs/https://react.dev/learn/you-might-not-need-an-effect #share - [H12] Pilot scheduling patterns in React apps — Core Performance WG/https://react.dev/learn/transition #xref - [H8] Run a Qwik resumability demo — Playground module/https://qwik.builder.io/ #articleseed - [H10] Write a monoculture risk note — The WPCC board packet/https://www.youtube.com/watch?v=LrUpYblQIV4 #addendum - [H9] Document React stability guarantees — OSPO guidance/https://react.dev/blog #xref - [H2] Contrast VDOM vs compiler approaches — FAIR.pm brief/https://svelte.dev/blog/virtual-dom-is-pure-overhead #share - [H7] Reproduce JS Framework Benchmark subset — DX lab/https://krausest.github.io/js-framework-benchmark/current.html #xref - [H6] Create “tools you understand” pledge — Contributor onboarding/https://www.youtube.com/watch?v=LrUpYblQIV4 #articleseed - [H4] RSC adoption guardrails — Core AI + Hosting/https://nextjs.org/docs/app/building-your-application/rendering/server-components #xref - [H1] Update hiring rubric to stress fundamentals — OSPO + HR/https://developer.mozilla.org/ #share ## 🧭 Table of Contents - [📝 Summary](#-summary) - [📖 Main Content](#-main-content) - [🗒️ Notes](#️-notes) - [📚 References](#-references) - [🗣️ Paraphrase](#️-paraphrase) - [📰 Newsletter](#-newsletter) - [✅ Action Items](#-action-items) - [🧪 Hypotheses](#-hypotheses) - [📊 Methodology](#-methodology) - [❓ Questions](#-questions) - [🔮 Future Research](#-future-research) - [💡 Implications](#-implications) - [🧠 Learning Styles Assessment](#-learning-styles-assessment) - [📊 Accessibility Assessment](#-accessibility-assessment) - [🌍 DEIB Assessment](#-deib-assessment) - [✅ Logical Validity](#-logical-validity) - [🛡️ DARVO Analysis](#-darvo-analysis) - [🎯 Conclusion](#-conclusion) ### 🔗 References - Include links cited in or relevant to the article. ## 📝 Summary - The video reviews claims that React’s default status slows innovation. - It compares models: virtual DOM, compilers, signals, and resumability. - Stakeholders include framework authors, enterprises, OSS maintainers, and educators. - Risks involve monoculture, hiring filters, and misused hooks causing outages. - Bottom line: choose tools deliberately; elevate fundamentals and scheduling. ## 📖 Main Content - React became the default through ecosystem strength and stability. - Alternatives show real gains: compilers, signals, and resumability patterns. - Performance bottlenecks often stem from JavaScript on the critical path. - Scheduling and selective hydration matter at large scale. - Education should center web fundamentals before framework features. - Monoculture risks exist, but stability and ecosystem value remain high. - Teams should pilot alternatives where constraints demand it. - Governance should guard against lock-in and promote portability. ### 🗒️ Notes #### ⏱️ [00:03:01](https://www.youtube.com/watch?v=LrUpYblQIV4&t=181) Opening premise and defaults ### [H1] React-by-default reduces evaluation rigor > [!quote] [React is killing the web](https://www.youtube.com/watch?v=LrUpYblQIV4) by [an unnamed author] via [[Theo - t3.gg (YouTube)]]. Published [MISSING]. Accessed {{date:YYYY-MM-DD}}. > “When teams need a new front end, the conversation rarely starts with what are the constraints… It often starts with let’s use React.” Teams skip fit assessment. Encourage a checklist. [view highlight](https://www.youtube.com/watch?v=LrUpYblQIV4&t=181) #articleseed #xref ID:rw_[MISSING] #### ⏱️ [05:10](https://www.youtube.com/watch?v=LrUpYblQIV4&t=310) Virtual DOM context ### [H2] Virtual DOM solves 2013 problems; adds overhead today > [!quote] [React is killing the web](https://www.youtube.com/watch?v=LrUpYblQIV4) > “The virtual DOM was a clever solution for 2013’s problems.” Prefer compilers or signals where constraints fit. [view highlight](https://www.youtube.com/watch?v=LrUpYblQIV4&t=310) #xref #articleseed ID:rw_[MISSING] #### ⏱️ [06:53](https://www.youtube.com/watch?v=LrUpYblQIV4&t=413) Hooks and compilers ### [H3] Hooks reduce classes but create new complexity > [!quote] [React is killing the web](https://www.youtube.com/watch?v=LrUpYblQIV4) > “Hooks address class component pain, but they introduce new kinds of complexity.” Teach effect restraint and alternatives. [view highlight](https://www.youtube.com/watch?v=LrUpYblQIV4&t=413) #share #xref ID:rw_[MISSING] #### ⏱️ [06:53](https://www.youtube.com/watch?v=LrUpYblQIV4&t=413) RSC mention ### [H4] Server Components improve TTFB yet add complexity > [!quote] [React is killing the web](https://www.youtube.com/watch?v=LrUpYblQIV4) > “Server components improve time to first bite, but they add architectural complexity…” Adopt with guardrails and migration plans. [view highlight](https://www.youtube.com/watch?v=LrUpYblQIV4&t=413) #xref ID:rw_[MISSING] #### ⏱️ [15:40](https://www.youtube.com/watch?v=LrUpYblQIV4&t=940) Perf principle ### [H5] JavaScript on the critical path is expensive > [!quote] [React is killing the web](https://www.youtube.com/watch?v=LrUpYblQIV4) > “JavaScript is expensive on the critical path.” Favor less JS and smarter scheduling. [view highlight](https://www.youtube.com/watch?v=LrUpYblQIV4&t=940) #articleseed ID:rw_[MISSING] #### ⏱️ [20:43](https://www.youtube.com/watch?v=LrUpYblQIV4&t=1243) Tool literacy ### [H6] Use tools you understand to avoid failures > [!quote] [React is killing the web](https://www.youtube.com/watch?v=LrUpYblQIV4) > “Stop using tools that you don’t understand.” Make fundamentals mandatory in onboarding. [view highlight](https://www.youtube.com/watch?v=LrUpYblQIV4&t=1243) #articleseed ID:rw_[MISSING] #### ⏱️ [22:22](https://www.youtube.com/watch?v=LrUpYblQIV4&t=1342) Benchmarks ### [H7] Solid shows faster updates in targeted cases > [!quote] [React is killing the web](https://www.youtube.com/watch?v=LrUpYblQIV4) > “Benchmarks… show that alternatives like Solid can achieve up to two to three times faster updates…” Reproduce only relevant scenarios. [view highlight](https://www.youtube.com/watch?v=LrUpYblQIV4&t=1342) #xref ID:rw_[MISSING] #### ⏱️ [27:17](https://www.youtube.com/watch?v=LrUpYblQIV4&t=1637) Resumability ### [H8] Qwik resumability enables instant startup > [!quote] [React is killing the web](https://www.youtube.com/watch?v=LrUpYblQIV4) > “Quick uses resumability instead of hydration…” Evaluate for e-commerce “add to cart” speed. [view highlight](https://www.youtube.com/watch?v=LrUpYblQIV4&t=1637) #articleseed #xref ID:rw_[MISSING] #### ⏱️ [54:31](https://www.youtube.com/watch?v=LrUpYblQIV4&t=3271) Stability ### [H9] React maintains cross-version stability unusually well > [!quote] [React is killing the web](https://www.youtube.com/watch?v=LrUpYblQIV4) > “Generally speaking, you can take code from the OG first release of React and run it in modern React totally fine.” Note exceptions for RSC bootstrapping. [view highlight](https://www.youtube.com/watch?v=LrUpYblQIV4&t=3271) #xref ID:rw_[MISSING] #### ⏱️ [56:02](https://www.youtube.com/watch?v=LrUpYblQIV4&t=3362) Monoculture ### [H10] Monoculture risks slow platform evolution > [!quote] [React is killing the web](https://www.youtube.com/watch?v=LrUpYblQIV4) > “Monoculture slows web evolution when one framework’s constraints become de facto limits.” Encourage pluralism and upstream funding. [view highlight](https://www.youtube.com/watch?v=LrUpYblQIV4&t=3362) #addendum #articleseed ID:rw_[MISSING] #### ⏱️ [59:20](https://www.youtube.com/watch?v=LrUpYblQIV4&t=3560) Adoption curve ### [H11] Innovators must feel big wins to a - Summary: MCP is one of those things that I don't really talk about. There's a reason for that... Thank you Depot for sponsoring! Check them out at: https://soydev.link/depot SOURCE https://blog.cloudflare.com/code-mode Want to sponsor a video? Learn more here: https://soydev.link/sponsor-me Check out my Twitch, Twitter, Discord more at https://t3.gg S/O Ph4se0n3 for the awesome edit 🙏 - URL: https://www.youtube.com/watch?v=bAYZjVAodoo I talk a lot about AI stuff on thischannel, but there’s a couple of AI thingsyou might notice I haven’t mentioned alot. One of those is MCP, the ModelContext Protocol. You might assume thisis because I have some crazy hatred forAnthropic and I’m just avoiding talkingabout their stuff, but it’s not that. Itcomes down to something much simpler. Itry to talk about the things I’mactually using, playing with, andworking with every day. And I found thatfor my stuff and my work, MCP has notbeen particularly useful. Seems like I’mnot the only one who feels this waybecause Cloudflare just put up a post that is very exciting to me. Not justwhat they are releasing here, but theconcept of MCP not really being the bestprotocol and a future where we can dosomething much better. I don’t want tospoil everything just yet, but to giveyou a little teaser, the concept thatthey are working on here is instead ofdoing MCP calls by listing all thesetools for the model to call directly,what if you gave it a TypeScript API andlet the LLM write code to call the API?This is a really interesting concept andI’m super excited to see how this works. In the real world, to break down the work these guys did, in particular, Sunil, who's been a good friend for a long time.Really cool stuff that Cloudflare's cooking here. Can't wait to break it all down.But first, a quick word from today's sponsor. We've seen a ton of innovation in how fast development teams can move thanks to all these cool new AI tools.But there are certain things that we haven't seen move very much. It's kind of crazy when you think about it. We can make a PR five times faster than we could before, but actually building and running that code takes as long, if not longer, than ever.Unless you check out today's sponsor, Depot. These guys really get builds, and it shows. They knocked Post Hog's build times down by 17x from over an hour and a half to under 6 minutes.Mastadon got 38 times faster from almost 2 hours to under 3 minutes. Genuinely unbelievable how much faster things can be when you have a proper infrastructure for doing builds. If you're wondering how they do it, it's not super secret. It's just a ton of annoying work that they've put the effort into. They set up their own action runners with way faster CPUs. Times faster networking, unrestrictedconcurrency, and the caching is just somuch better. As a result, they alsorethought Docker builds to really takeadvantage of the different layers asyou're building, making it way easier tocache and restore things. It's so muchfaster with Docker images. They actuallyintroduced a product on top of it, theirremote agent sandboxes for cloud code. You can set up your developmentenvironment with everything you need torun an agentic session. And now it'sjust cached and ready to go. All of asudden, you can run a command and runcloud code in the cloud on their infowith all of the performance benefitsthat we've been talking about this wholetime. Must be super expensive, right?Yeah, 20 bucks a month. Pretty insanedeal if you ask me. If you wish your CIwas faster, your Docker builds werecached better, or you just wantsomewhere to run your cloud codeinstances, look no further than Checkthem out now at soy.link/depo. You know it's going to be good when thefirst sentence is, "Turns out we've allbeen using MCP wrong." Most agents todayuse MCP by directly exposing the toolsTo the LLM. We tried somethingdifferent: convert the MCP tools into aTypeScript API and then ask an LLM towrite code that calls that API. I'mgoing to show you guys something funquick. Let me open up my terminal. So, Iwas hanging out with the creators ofTrey a few days ago, and I had a lot ofquestions on how it worked internally. If you'renot familiar, Trey is by theByteDance guys. It's their attempt atbuilding their own from scratch VS Codefork, an all-in-one code AI IDE thing. Andwhen I was playing with it, I noticed that the quality of the outputs justwasn't as good as what I was gettingfrom other similar tools. And it wasgetting stuck calling all sorts ofthings and not really doing what Iexpected it to do. And I was workingwith them trying to figure out what wasup. So I just asked Trey, "List toolsyou have access to. If somehow you'renot already familiar with tool calls,the really quick TL;DR is that a toolcall is a format that you can let amodel output to then go run code or dosome specific task. So if you want themodel to have access to like weatherinformation, you can tell it to use thisSyntax tool name equals weather value. Zip code equals 1 2 3 4 5. And if youtell it about this format and thatyou'll respond in a certain way, now themodel can put in this text, stop, waitfor you to run code and get a response,and then keep generating accordingly.It's a core pattern to how all these AIthings got so good. It's why all theseeditors and whatnot are as powerful asthey are. It's the whole concept ofagents, which is largely based around the powerto do these tool calls and functioncalls. And MCP is meant to be a protocolfor standardizing these and letting youbuild more dynamic tools. In particular, the idea of exposing these tools as aweb service or thing on the internetthat you can just plug in by copyingand pasting the definition of it into yourAI tool of choice. So with a thing likeTrey, I wanted to see all the toolsthey're giving their agent in order forit to be able to do AI code stuff. Sohere, I told it just to list all your tools,and it does. It has a run agent solodocument, which is how it documents whatit's going to do. It has two codedevelopment tools, which are both alsoagents. Coding and running agent solo dev builder.There are two different agents that can be triggeredvia a function call. Okay, interesting. Keep going. Code analysis and search.It has four different tools. One is forjust searching generically. One issearching with regex. Then there's viewfiles and view folder. Then we havecheck command status, web search, andmore. But the most important thing hereis that there are three separate sub-agentsthat can be triggered. So, I asked it to run one of these, the solo coding agent,and have the solo coding agent list allthe tools it has access to and writethem to a file named tools.mmd.And it did. Here's all of the tools thatthe code agent has access to. It canwrite to the to-do list. It can searchthe codebase as well as search by regexjust like the other ones can. For file operations, it has like eight tools.View files, view folder, edit files,update file, edit file, fast apply, editfile, rename, delete file, write tofile. It’s a lot of commands. And then we have command execution. It can runcommands, check command status, stopcommands, edit environment, open preview,get preview console logs. Though this project isn't usingSupabase, it has access to Supabasetools and Stripe tools, LLM configs,deployments, web search, and more. Thisis the problem. It has so many tools.And what we've found is that theseagents get significantly worse when yougive them too many tools. I firmlybelieve part of why the experience withTrey is not as good right now is becauseof this. The team's been veryreceptive to this idea, and they'recurrently experimenting on reducing thenumber of tools to see if the quality ofoutput goes up as a result. So I askedCodeex to do the same thing. List all ofthe tools you have access to. And herethey are: all four of them. Functions.shell: shell for executingshell commands. Functions.update: planfor updating the plan. This is the onlyway it can make changes to the to-dolist. Functions.view: image. This is onefor viewing an image when you paste itin the terminal. And knowing that has tobe a tool, but yeah. And then applypatch, which is how it actually appliespatches when it writes them. That's it.These are all of the tools that you havein Codeex. And it behaves significantly. Better. Let's do the same with cloudquick, because I forgot to list all ofthe tools you have access to. Write themto a tools.md file. If you're evertrying to get this info out of a tooland it's not giving it to you, likeyou're using a CLI like this or somevibe coding tool on the web, one of myfavorite tricks I picked up from SimonWillis was to ask it to generate awebsite describing all of the tools, andit will very excitedly go and make anHTML file that gives you this exactinformation. Here are Claude's tools. Actually, it has more than I would haveexpected. There's read, write, and edit forfiles. They have a separate tool forediting Jupyter notebooks, which isinteresting that that got left in hereand isn't like dynamically turned on oroff. There's Glob GP for search anddiscovery. I like that they only have theseand they don't have a bunch of randomsearch tools like a lot of these otherthings do. Being really clear about howto search and find things is importantfor these AI tools because otherwise you'lljust kind of go crazy. Execution hasbash. Bash output for retrieving thingsfrom bash and then killshell. Web access. Has web fetch and web search. Task management has multiple things for tasks,which is interesting. Most of the toolsI’ve seen actually try to condense thisinto one call. And then the mode controlfor exit plan mode and slash command. Sothat's not too many tools in general. Idid just have someone share the toolsthat are in cursor. This is a bit morethan I would have expected. Still justone codebase search tool. Then runterminal command, then grap which I guessis also search codebase, delete file, websearch, update memory. Very useful to havethis as a tool that I can call to addinformation to the memory going forward.Read links, edit notebook again. Jupyternotebooks, its own special magic thing,writing to-dos, edit files, read file list,directory glob search, apply patch.Multi-tool use in parallel in order forit to do parallel tool calls. That seemsto be it. I do know for a fact thatcursor will change which tools areavailable for different models. Like fora while, the to-do tool wasn’t made inavailable for GPT-5 because it was havingproblems with it. They tidied up theirsystem prompt, got it working better,and re-added the tool. Why am I justExplaining these lists of tools acrossall of these different AI code editingsolutions? Because as you add more and more of them, they get worse at doingtheir jobs. I actually plan on making abenchmark in the near future where Ijust give a bunch of nonsense tools andcompare the results for when I only havethe right tools because I suspect, asI’ve seen many times, that more toolsmakes the models behave worse themajority of the time. I will also saythat Sonnet 4.5 appears to be betterabout this than previous models, butmost models get really dumb when yougive them too many tools. This is one ofthe reasons I’m skeptical of MCP becausewhen you start adding a ton of MCPservers, you’re adding a bunch ofadditional tools. You’re bloating thecontext and you’re giving the model morethings than it needs that distract itfrom what it’s actually supposed to bedoing. As Chad is saying, this is a verysimilar problem to giving models toomuch context. So, this is why I’mexcited about what Cloudflare is doingtoday. I’ve myself experienced this frommy own work with AI stuff. AI gets a lotsmarter when you’re not just telling itTo do the work and give you a result,but you're telling it to generate thecode to go run and get you the result. It's really cool when I hand it a giantHTML document and say, "Hey, I want toparse these values. Write me theJavaScript I can paste in the console toget these values out of the page, and itdoes it. Then I paste the JavaScriptand get the answer I'm looking for. It'sso much better than if you're justtrying to get it to do this giant needlein a haystack problem. Code is greatbecause it's deterministic, and AI is notdeterministic. So if you give it toolsto do more deterministic things, theresults will be much better. And thatseems to be the direction Cloudflare isleaning into here. As they said, they're trying something different: convertingthe MCP tools into TypeScript APIs, thenasking the LLM to write code to callthose APIs instead. The results arestriking. We found agents are able tohandle many more tools and more complextools when the tools are presented as aTypeScript API rather than directly.They don't know why this is, but theirtheories are that this is perhapsbecause LLMs have an enormous amount ofReal world TypeScript in their trainingdata, but only a small set of contrivedexamples of tool calls. Very likely. Then, point two here, the approach reallyshines when an agent needs to stringtogether multiple calls. With thetraditional approach, the output of eachtool call must feed into the LLM'sneural network just to be copied over tothe inputs of the next call, wastingtime, energy, and tokens. When the LLMcan write code, it can skip all that andonly read back the final results that itneeds. In short, LLMs are better atwriting code to call MCP than they areat calling MCP directly. I totallyagree. I want to run a poll with youguys, though. Do you use MCP? Verycurious how you guys feel. Feel freeto explain more in chat too if you havestrong opinions on this type of stuff. Yeah, so far these numbers are roughlywhere I would expect. Most people sayingno. A decent number saying yes. Meh. Butalso about 15% or so saying yes, and theyactually love the results. Only context7. Only context 7. I have context 7 insoul. I haven't had a great experience.Context 7 only. Context 7 plus playwrightMCP. KP is great for migrating tables. Interesting. I actually like Convexbecause I don't feel like I need the MCPworking. MCP serverswork using module federation, which seemsto be solving one of the many issues,such as many people saying, "I have one."Have you talked with everyone'sfavorite, the creator of modulefederation about this? I'm sure Zach hasa lot of thoughts. It's been so funtalking with Zach about AI stuff lately. If any people who love MCP could sharewhy, I'd love to hear more. Like, nothere to talk; I'm just curious what it'sbeen doing for you guys. A concern Ihave with new businesses is this "tearing of tools" problem.So my concern with this is the idea that thingsare built on top of things. So if wehave, like, AWS as a foundational block,and on top of this we're building with, Idon't know, something like Vercel, to makethe font smaller to make this easier tomanage. And on top of that, we'rebuilding random products like T3 Chat. This makes a ton of sense. WithoutVercel, I could build T3 Chat on top ofAWS, but there are a lot of layers thathave to be built between AWS and T3 Chat inorder to make that work. At this, I saw, "Oh, there's anopportunity for us to build a layer hereto make it easier for businesses tobuild things like T3 chat on top." It makesa ton of sense. The order of events hereis pretty simple. First, there's anestablished platform that makes iteasier to build. I don’t even know ifit’s easier; I’ll say it’s possible to build.Step two is lots of people try buildingand run into issues. And then pointthree, middleware tooling companiesappear to solve those problems. So AWShappened, lots of businesses startedbuilding on top. Vercel noticed a lotof them running into similar problemsand decided to build a layer between.There are a lot of companies, like Planet Scale,rethinking how databases work or companieslike Convex rethinking how the data layerworks for your applications. They see sharedproblems across user space and crossdeveloper space and decide to solvethose with an abstraction. But in orderto do this, there has to be enough goingon this layer to justify the creation of entities in this layer. Ifhypothetically, there were more companiestrying to compete with Vercel than thereWe were trying to compete with us a layerabove that would make this layer notvery valuable. So why do we do thisbackwards for MCP? With MCP, the orderwas that a new standard is created, thiscase is MCP, and then step two was tons oftooling companies that started to form,building things for MCP. But we forgotthe actual step two, which is supposed tobe people using that first piece andrunning into issues. So if we were to dothis honestly, we kind of skipped to stepthree here, and then step two neverhappened. And this is a big part of whyI’m so skeptical about MCP stuff. I knowmore companies building observabilityfor model context protocol, so you cansee how the MCPS are behaving than Iknow companies that actually needobservability for MCP. They’re trying tolike, you know, the whole sellpickaxes during the gold rush thing. They’re selling pickaxes when we needfishing rods. It just doesn’t makesense. Like no one is using these thingsyet. The idea of building observabilityfor it’s kind of stupid because we’renot at that stage yet. It feels likewe’re talking about MCP more than we’reusing it by quite a bit, and it’s beenVery frustrating for me to see. Thatsaid, I want to see people who actuallylike it. I asked chat: MCP does the samestuff with less overhead. Wake up, sheep! That's one way of putting it. MCP'sletting the code agent manage webdeployment autonomously. Contact 7 forlatest docs and SDK version. Yep.Stopped using Context 7 'cause I'd ratherjust save the context from the websitelocally and point an agent to that. Lesscontext bloat with the MCP tools.Freaking love what Cloudflare is doing.The protocol is an absolute shambles.Nick from TRPC has a PR open where thereare literally not only type defs but docsthat are 100% wrong everywhere aboutbehavior under the hood.That's painful using the Figma MCP togenerate scaffolds for designs. A loteasier to give the correct context fromthat's cool. I like to write quickone-off MCP servers for my codebase todo tasks that help keep the contextsmall, like writing and reading key-valuetranslations to a file without loadingthe massive JSON. I did this because Inoticed every time I wanted to read thefile, my cost per session went up. Interesting. I like this idea of likeGenerating code to reduce context sizeon giant files. That's actually a reallyinteresting one, Funky. Thanks forsharing that. I also like the idea ofdynamically generating code tosolve these types of problems on thefly. Rather than having the model take aton of input and context and cost more,have the model take a little bit ofcontext, generate code for how to getthe rest of the context, run it, andthen put that little bit of extra stuffinto the context window. Got it. I havea video I've wanted to do about thisidea for a while. Like how many timesdoes the average function run? The thingI've been thinking about a lot recently. It's probably going to be a wholededicated video. PreI, my guess would bethat the average code, if we're lookingat the median code, like a givenfunction, it's probably not run a wholelot, but the mean would be a lot becausethere are functions that are runhundreds of billions of times a day. Soa given function in a codebase has agood chance of being run quite a bit onaverage. But with AI, I expect therewill be more and more over time. We're going tosee like a given endpoint a user goes toThe code being executed isn’t just thecode for that endpoint in your codebase. So instead of having a function get doingsome standard thing for everybody’srequests where it’s like const request equalsget user, you pass the request and thendo something with it, like returnuser.credits. My suspicion is there’s a future whereinstead of all endpoints looking likethat, endpoints will look more likeI don’t know, you have some context inthis and you call something likeconst response equals await generatecode for context and user. I’ll sayconst code to execute, and then youreturn effectively like evaluating code toexecute. Obviously, you should use somesafe layer to do this. The point I’m trying to make here is I suspect there’sa future where if two different peoplehit the same endpoint, both will berunning unique code for that hit on thatendpoint. Right now, that just kind offeels insane, because you write code foran endpoint and then the same code runsfor everybody. You might go downdifferent paths, but the actual codethat was written is static and doesn’tchange. But if different users haveDifferent enough requirements, I could absolutely see a future where theendpoint is executing unique code peruser, which is a really cool and weirdconcept that’s been on my minda lot. And I think that’s kind of what’s being touched on here that I think is socool. The idea of writing code orwriting a tool not to have as part ofyour toolbox that’s used all the time,but writing it to use it one time andthen throw it away and pretend itdoesn’t exist. That I actually reallylike. The idea of code being so cheap toproduce that producing it for one-offthings like that is worth it. Genuinelyan exciting idea to me. Apparently thenotion MCP is quite good. MCPs feel arebottlenecked by the models you use andthe drop-off for great tool calling. Good tool calling is way toolarge. I agree. If the model isn’t greatat tool calls, it sucks. Pretty easy towrite MCP with quad code. So it’s bestto just scratch all your own itchesinstead of using other people’s. Iactually had an MCP I wanted to create.So let’s do that here. You know what?I’ll voice-to-text it. Thank you, WhisperFlow, for making my life easier with oneHand, I want to create my first MCPtool. The role of the tool is to providea journal for AI agents to use todescribe how they feel about tasks. Itshould be specified that the journal isprivate and the model does not have toworry about humans reading what itwrites. The MCP should log both theprompt and the details that the modelshared with it in a markdown file in adirectory in the project that we're in. I would like for this MCP to beavailable for all instances of cloudcode that I run on this machine. We'llsee how cloud code does with that. Theobvious question when you see how muchhype there is around MCP is why? Why isthere so much hype? Why do people careso much about this? And this goes backto one of my older hot takes that I'vebeen pushing since way before AI stuffhappened. I've personally beenfrustrated for a long time that so manyof the things I want to do can't be donevia code. They have to be done via somesketchy dashboard or some annoying adminpanel somewhere. It genuinelyfrustrates me to no end that I have togo to a random panel somewhere to changea setting. The right information set up on theirprofiles and accounts means that no one elsecan change it. It also breaks the ideaof my code history being thehistory of the service. The more of yourconfiguration that exists in a dashboardor a panel or some service, the lessexists in your codebase. The less youactually know about how the projectworks from the code. That's always beena problem, and it's frustrated meforever. The idea of configuringrole-based access control in theSupabase dashboard or setting upfunction calls in some other dashboardor configuring Lambda by hand and clicking a button to deploy — allthese things stress me out. Terraformhelps, but not enough. In an ideal world,all configuration would just exist asfiles in your codebase, and when you hitmerge and it goes to main, everythingwill update automatically accordingly.This is part of why I liked Vercel somuch back in the day and even part ofwhy I liked Netlify before then. The ideaof having your configuration purely ascode that lives inside your toolsthat are in your codebase to describe howthings work outside of it was awesome. And I was all in on that as soon as Ihad the opportunity to lean in thatdirection. It's also a big part of why Ilove Convex. The only configuration I have todo when I spin up Convex is paste insome environment variables. Everythingelse is managed just by using Convexlocally inside of your dev environment.Just write the code in the folders andit can now configure Convex exactly howyou detailed. I love that. But a lot oftools are not built for this. AWS isn'tbuilt for this. Supabase isn't built forthis. Figma certainly isn't built forthis. A lot of the tools that are reallypopular right now do not work well withinfrastructure as code. We're making progresshere, but we're still not quite thereyet. And doing this is really hard. There's a reason that companies likeHashiCorp could exist and be worthbillions of dollars. It's because thisproblem is so hard that things likeTerraform, Pulumi, and more all neededto exist to try and solve it. And thisis where the spicy take comes in: MCP isthe next generation of Terraform. It isanother attempt to take these legacySolutions force them to behave in amodern era. People wanted to control AWSvia code. Terraform tried its hardest tolet them do that. People want to controltheir AWS configs via AI. MCP lets themdo that. The whole point of all of thisis that MCP enables these legacy toolsthat don't have the context in yourcodebase to make calls to control andget access to and figure out how thingswork because you don't have that accessin the codebase. A codebase usingSuperbase doesn't know how things areconfigured in Superbase. A codebaseusing AWS doesn't know how things areconfigured in AWS. That is additionalstate that exists outside of the code. And sadly, state makes AI behave muchworse if it has to go find theinformation before it can do the thinginstead of it just being there. Apparently, the Superbase MCP is reallygood. People are saying this in chatthat it's been awesome for them to use,but that's a patch as far as I'mconcerned. Like it is an attempt to fixthese things not existing within yourcontext of the codebase. But in an idealworld, those would just be files in thecode that could be edited and read. Used the same way everything else inyour codebase is. MCP is a patch forlegacy infrastructure that does not letyou control it via code. It is a hell ofa lot cheaper to get people hyped on MCPthan it is to rebuild AWS to be configfirst. And yes, Chad has caught on. Thisis why Convex is amazing. This isactually the big thing that when itclicked for me, I went from being aConvex hater to maybe I could like thisin the future. I very much likedthe idea that my entire configurationfor Convex was just a folder in mycodebase. That’s also why I pushed themto go make Chef, which is their AI vibecoding app builder thing, because I knewthe power of having all of the contextin your codebase as a file or a folder. And I think that’s going to be thelong-term future. That’s my super spicybet: I don’t think tools that requirean MCP to configure them are going tosurvive in a world where the configcould just be part of the codebasedirectly. If my options are to use an MCPto set up role-based access control inSuperbase or just write a folder inConvex and write a file that describeswhat I want, I’m going to pick Convex. Every time. Remember, I was a hugeskeptic of Convex, and this was one ofthe big pieces that won me over as aresult. Back to the article that I'vebeen dancing around and not reallycovering. They said point one is thatit's better at handling multiple tools.When you give it a ton ofdifferent tools to use, it's way betterwith code than it is otherwise. And thenpoint two, the approach really shineswhen an agent needs to string togethermultiple calls. With the traditionalapproach, the output of each tool callmust be fed into the LM's neural networkjust to be copied over to the inputs ofthe next call, wasting time, energy, andtokens. Yes, this is a really big deal. To diagram what this looks like, if Ihave a request, I give a model like, "Whatclothes should I wear today?" I send thisto the model. So, we have the usermessages and we have model messages. Ifthe model somehow magically knew what wewanted here, it just knew what theweather was, how we dress, and all ofthose things, it could just respond,"Wear your red collared shirt and alight jacket." But it doesn't knowenough to know that, so it will reasonTo itself, it will say, "What do we needto know to make a good recommendation?"We have access to tools that could helphere. Maybe we should use the memorytool and the weather tool to figure outmore. First, we should check our memoryto see if we know the user's location. Now, we finish reasoning, and thenoutput. Let's pretend there's some toolnamed "memory" and the value we search forequals "user location."So, you then have it call the memorytool to figure out what the user'slocation is to see if we have that inmemory. You would think that this willjust respond and the agent keeps going. But this is where things getinteresting. The output's now over. Thisis the end of that output. What happensnow is code gets executed to look intoor run the thing that you just did. Sowe have a hard break here. I'll draw oneof these lines whenever there is a newgeneration being done effectively. So the user submits a message. Thisreasoning step happens. Then this outputhappens. Now there's a break. The toolruns. I'll just put in here like "toolruns and gives result," and the result isuser zip code 01234. Their zip. Now, this is in the messagehistory, and a new generation is run. Soonce again reasoning occurs. This timeit has the message history from before.So, it has all of this data that wegenerated, and then it looks at it andmakes up its mind about what it’s going to do.Okay, we know the user's location now.We should use their zip code to figureout what the weather is like today. Toolname is weather value 012 34. And now,another break. Tool runs gives result. You get the idea. This happens multipletimes. And you’re not running the modelonce. You’re running the model howevermany times it takes for each tool. Eachtool call is creating yet another chainresponse effectively. And if you were tomeasure this by tokens, I’m just goingto make up numbers as we go. We’ll justdo the number of words: 1, 2, 3, 4, 5, 6. Sothis one, six input tokens. So these sixinput tokens get passed to this. So weonly have six tokens here, but there'sgoing to be quite a bit of outputinstead. I’ll just paste this into theOpenAI tokenizer. It’s the one that’sonline that’s the easiest. 89 tokens forthis output. So, six input tokens, 89output tokens. But then another run. This one has all of these added plus theuser zip code. We'll just say that 1 2 34. That's another four tokens. So inputtokens is now math. We have the six frombefore plus the 89 plus the five fromthe user zip code part here. So now wehave quite a bit more input tokens.We're now at 100. So the first run onlyhad six input tokens. Now we have 100.We're still generating more response. You get the idea. This chains up, and allof the outputs from previous runs getadded for each additional call. So youend up building quite a bit of inputtokens. Even if your input is only sixtokens, this could quickly get tothousands, if not tens of thousands ofinput tokens because each tool call isadding more info to the context, causingthe context bloat to go up. I know thisis unintuitive initially. It feels likethe model is just pausing, doing thetool, and then continuing to run. Butmodels don't pause. They generate untilthey're done, and then they stop. Thenyou can run code based on what they didand then come back with the result. Butnow imagine instead of doing it thisway, it wrote code. Do these different tool calls. It's toldwe have these different tools to writecode. Let's rethink this whole thingaccordingly. What clothes should I wear?What do we need to know to make a goodrecommendation? We have access to APIsthat can help here. Maybe we should usethe memory API and the weather API tofigure out more. First, we should checkour memory to see if we know the user'slocation. Then, we should use the zipcode with the weather tool. Then, weshould check memory for the user'spreferences for clothing. Then, weshould pull it all together for a finalanswer. And now, the output instead ofit being the tool calls, it could beJavaScript code that does this. Make memock TypeScript code that would resolvethe order of events described below. Five minutes. No reason to go harder. Okay,it's writing out the whole mock API.Compose clothing recommendation. Here weare.So, it could write this part and nothingelse, assuming that it already hadeverything else. Is this more outputthan if it was just calling a tool?Sure. But what's cool here is it onlyhas to write the output once because theThe layer of abstraction, like thequestion, is where do we handle 1, 2, 3, 4? If we handle that as part of the agenticenvironment, suddenly the model has torerun for every step along the way. Butif instead we create a safe sandbox torun code and expose these things astools, it can write the code once thatdoes all of the different steps or, atthe very least, combines multiple ofthem. So we don't have to do a fullseparate message call, full separategeneration call per tool call. Thisabstraction allows you to combine abunch of stuff and also programmaticallygenerate answers, which is super cool andpowerful. So if instead of splittingevery time a tool call is made, youcondense as many as possible into onerun by effectively creating your owndynamic tool writing code instead. Itmakes a ton of sense. It's really coolto see this. I want to go back to thearticle, but first I want to see howClaude is doing here. Oh, it wanted todo a web search. Apparently, the quickstart server for the MCPIO site was notresponding. That is quite funny if you think about it, that it’s getting 404strying to fetch the MCP site through theCLI. Oh gosh, that’s going to triggerme. MCP should have been built inGraphQL. Okay, you guys are catching onto one of the scary parts here. How dowe execute eval? One thing that’s scaryisn’t it terrifying to justgive AI access to eval? Yes, itabsolutely is, which is why you have torun it in a safe environment with aminimal set of tools that you give itaccess to. There’s a lot of solutions tomaking this safe. I’m sure thatCloudflare is relatively safe. One ofthe channel sponsors, Daytona, does thisreally well. They let you create secureenvironments to run AI-generated code insafely. It’s a super, super coolplatform. Highly recommend them ifyou’re looking for a place to executecode remotely. Their infrastructure is greatfor this. They even have like Gitintegration and it’s super cool. While this is continuing to run andcontinuing to hit 404s for some reason,I’ll keep reading. As they said withpoint 2 here, the output of each toolcall must be fed into the LM’s neuralnetwork just to be copied over to theinput of the next call, which wastestime, energy, and tokens. It can write code, skip all thosesteps, and read back just the finalresults that it needs. In short, LMs arebetter at writing code to call MCP thanthey are at calling MCP directly, as wesee here, as it fails to fetch basic MCPinformation from the MCP site. Oh,apparently they had their owndescription of MCP in the article. We'llgo over it quickly. For those who aren'tfamiliar, MCP is a standard protocol forgiving AI agents access to externaltools so they can directly perform work,rather than just chat with you. Also,fun fact, MCP has no concept of O, whichmakes half the things you want to dowith it kind of useless. MCP is auniform way to expose an API for doing athing along with documenting how itwould work for an LM to understand it,with authorization handled out of band. Yeah, SVS are making waves throughout2025 as it has suddenly greatly expandedthe capabilities of AI agents. The APIexposed by an MCP server is expressed asa set of tools. Each tool is essentiallya remote procedure call function. It iscalled with some parameters and itreturns a response. Called function calling, which meansthat they are trained to output text incertain formats when they want to invokea tool. The program invoking the LM seesthis format and invokes the tool asspecified, then feeds the result backinto the LM as input, just as Idescribed. Under the hood, an LMgenerates a stream of tokens thatrepresent the output. A token mightrepresent a word, syllable, some sort ofpunctuation, or some other component oftext. A tool call, though, involves atoken that does not have any textualequivalent. The LM is trained, or moreoften fine-tuned, to understand aspecial token that it can output. Thatmeans the following should beinterpreted as a tool call and thenanother special token that means this isthe end of the tool call. This is likehere I had my tool input and outputspecified as XML. There’s a lot ofdifferent formats for it. Doesn’t matterwhat you use. Just that’s the key that they’re talking about here. Between thetwo tokens, the LM will typically writetokens corresponding to some sort ofJSON message that describes the call. Asan example, imagine you connected anAn agent connects to an MCP server that providesweather information. Notice that everyone usesweather information as the example. It'sbecause there aren't many betterexamples. Note that here we've usedwords in these brackets with the bars torepresent our special tokens. But infact, these do not represent text atall. It's just for illustration. Here wehave the tool call, the actual JSON forthe tool we want to call, and then we endthe tool call. Upon seeing these specialtokens in the output, the LM's harnesswill interpret the sequence as a toolcall. That's the key. Whatever layer ismanaging this, the code that is callingthe LLM, that layer sees this syntax andknows that it needs to execute code now. And then it goes and does it. It parsesthe JSON message and returns a separatecomponent of the structured API result.The agent calling the LLM API sees thetool call, invokes the relevant MCPserver, and then sends the result backto the LLM API. The LM's harness willthen use another set of special tokensto feed the result back. Here we havetool result, and the results, and toolresult. Get the idea? So, what's wrongwith this? Special tokens used in toolCalls are things LMS have never seen inthe wild. They must be specially trainedto use tools based on synthetic trainingdata. This one's really fun. There arecertain models that tried really hard tobe trained on tool calling, like Grock4. And the result is that it will justrandomly hallucinate tool calling syntaxand dump it deep in the actual outputs. So, a lot of people would try to use Gro4 on T3 chat to search, and it would justoutput XML about searching but not do itin the right format. So it wouldn'ttrigger the search tool, and now they'rejust getting this funny looking outputwhere it's writing code to tell you whatthe search is going to be, but thendoesn't actually do it. They aren'talways good at doing this. As I justsaid, Grock's been hilarious with this. If you present an LLM with too manytools or overly complex tools, it maystruggle to choose the right one or touse it correctly. As a result, MCPserver designers are encouraged topresent greatly simplified APIs comparedto the more traditional APIthat they might expose to developersotherwise. Meanwhile, LM are gettingreally good at writing code. Asked to write code against the fullcomplex APIs that are normally exposedto developers, they don’t seem to have too muchtrouble with it. Why then do MCPinterfaces have to dumb it down? Writingcode and calling tools are almost thesame thing, but it seems like LM can doone much better than the other. Theanswer is simple. LMs have seen a lot ofcode. They’ve not seen a lot of toolcalls. In fact, the tool calls they haveseen are probably limited to contrivedtraining sets constructed by the LMs’own developers in order to try to trainthem. Whereas they have seen real-worldcode from millions of open-source projects. Making an LLM perform taskswith tool calling is like puttingShakespeare through a month-long classin Mandarin and then asking him to writea play in it. It’s just not going to behis best work. Bold statement. See whatyou’re trying to say. Don’t actuallydisagree. Apparently, OpenAI doesn’tdisagree either because Harmony’sformatting for a lot of this stuff isjust to define functions as TypeScriptsyntax. That’s really cool. I didn’tknow that.I hadn’t really thought of it that way. I will say. Yeah, I love this, the ideathat they define a namespace asTypeScript syntax showing all the thingsit can do and what they'll look like.It's actually really cool. Instead ofdoing just chaotic XML, TypeScript is inhere even though this whole project forthe most part is in Rust and Python.That's actually really cool. Good callout. Thank you, Vbits. Great first chat.But MCP is still useful mostly becauseit's uniform. MCP is designed for toolcalling, but it doesn't actually have tobe used that way. The tools that MCPserver exposes are really just an RPCinterface with attached documentation. We don't have to present them as tools.We can take the tools, turn them into aprogramming language API instead. Butwhy would we do that when theprogramming language APIs already existindependently? Almost every MCP serveris just a wrap around an existing API.Why not expose those instead? Well, itturns out MCP does something else that'sreally useful. It provides a uniform wayto connect to and learn about an API.Again, this is the stuff that I thinkmakes MCP both good and also why I thinkit's a bunch of band-aids and ductTape. Ideally, the way you learn about aservice or system is through the typedefinitions for it in the package that'sin your codebase. But if you can't do itthat way, having an API that isself-describing and shows you how to useit is a meaningful step up from thealternatives. An AI agent can use an MCPserver even if the agent's developershave never heard of a particular MCP server. And the MCP server's developers havenever heard of the particular agent.This has rarely been true of traditionalAPIs of the past. Usually, the clientdeveloper has to know exactly what APIthey are coding for. And as a result,every API is able to do things likebasic connectivity, authorization,documentation, but all a little bitdifferently. The uniformity is usefuleven when the AI agent is writing code. We'd like the AI agent to run it in asandbox so that it can only access thetools that we give it. MCP makes itpossible for the agentic framework toimplement this by handling connectivityand authorization in a standard way,independent of AI code. We also don'twant the AI to have to search theinternet for documentation. MCP providesIt directly connects in the protocol. But thereis a catch. As we mentioned earlier, Ois handled out of band. The O solutionis not standard at all, which makes thisa bit more complex. So let’s see howthis works on Cloudflare. We’ve extendedthe Cloudflare agent SDK to support thenew model. Say you have an app builtwith ASDK that looks like this: Dreamtext model OpenAI system message, yourhelpful assistant message. Write afunction that adds two numbers. You giveit tool definitions. You can wrap the tools and prompt with the code modehelper and use them in your app. So youwrite the system and tools definitionhere, and you wrap it with code mode. Sonow you have a custom system and toolsthat you can pass in for the AI SDK, whichwill let you call those tools throughcode instead of calling them throughMCP. With this change, your app will nowstart generating and running code thatwill itself make calls to the tools youdefined. MCP servers included. We willintroduce variants to other libraries inthe very near future. Read the docs formore details and examples. So how do weconvert MCP to TypeScript? When youconnect to an MCP server in code mode,The agents SDK will fetch the MCP serverschema and then convert it to aTypeScript API complete with docs,comments, etc. All based on the schema. So if you tell it to use the MCP serverfor Cloudflare agents, it will generatetype definitions like this: fetch agentimplementation, documentation output,search agents, yada yada.Fetch entire documentation files forGitHub repo, cloud for agents. Usefulfor general questions. Always call thistool first if asked about Cloudflareagents. We have that search agentdocumentation. This one is interestingbecause, like, I don’t know how usefulthese will be chained. Like, what willthe code do if it fetches thisinformation and then does a thing? Idon’t know how well it will do that inone shot, but at the very least it onlyhas to write code to get the info nowand have it fed in instead. So, let’srun the code in a sandbox now. Insteadof being presented with all the toolsthat the connected MCP server has, theagent is only presented with one tool,which simply executes TypeScript code. The code is then executed in a securesandbox totally isolated from theThe internet only has access to theoutside world through the TypeScriptAPIs representing the connected MCPservers. I trust Cloudflare to do thisright because of the amount of stuffthey’ve had to do with isolated layersfor their hacks on top of V8 withworkers to behave properly and safely isinsane. So, they know how to isolateTypeScript and JavaScript code verywell. They’re one of the few that Itrust to do this right. I’m sure thatthey did. The APIs are backed by RPCinvocations which call back to theagentic loop. There, the agent SDKdispatches the call to the appropriateservers. Cool. The sandbox code returnsresults to the agent the obvious way byinvoking console log. When the scriptfinishes, all of the outputs are passedback to the agent. Provide tool schemas,provide function matching MCP tools,output special text, and call the MCP tool. Nice. And now the code mode. Provide thetool schema, provide the TypeScript API,write code against it, execute in asandbox, call the bindings, and thencall the tools. And you’re done.The sandbox is the key piece. Also, a funthing about the console log. Uh, if weGo to Model Context Protocol and look atthe getting started section; one of my favoritethings in here is logging into MCPservers. When implementing MCP servers,be careful about how you handle logging. For standard out-based servers, neverwrite to standard output. That includesprint in Python, console log inJavaScript, and print line in Go.Writing to standard out will corrupt theJSON RPC messages and break your server. Wonderful standards! Don’t you lovestandards, guys? Dynamic workloading. Nocontainers here. The new approachrequires access to a secure sandbox.Again, they’re doing this with isolatesin V8. I’ve talked about this a bunch inother videos about how Cloudflare works.You get the idea; they’re much morelightweight than containers. Yep, theyhave the right infrastructure for this. It feels like you’re just evaling codedirectly, but actually securely. Upuntil now, there was no way for a workerto directly load an isolate containingarbitrary code. All worker code had tobe uploaded via Cloudflare's APIs, whichwould then deploy it globally so itcould run anywhere. That’s not what wewant for agents; we want the code toJust run right where the agent is. Again, that thing I was talking aboutearlier, the idea that a given requestcould be executing code that is specificto that request breaks a lot ofinfrastructure. Most info assumesall of the code is a binary that'sstored on a box attached to that serveralready. If the code is generated on thefly, there's a lot of things that changeabout that runtime environment.Cloudflare couldn't do it because theyrequired all code that's executed to behanded up through the workers API. Nowthey changed that to enable this. Theworker loader API in particular is thesolution here where you can callenv.loader and return a bunch ofdifferent keys, but also modules likeactual JavaScript definitions, and nowthey can be called and run externally. Start playing with this now. Workers arebetter sandboxes. Yep.And since those MCP servers are definedexternally, you don't have to worryabout including all the API keys.That'll be nice for me as someone who'sleaked far too many API keys throughouttheir life of streaming. Good stuff. Ilike this idea. I genuinely thinkThere's a lot more to explore in thisgeneral world. As I've gone over here,the MCP patterns are not necessarily thebest ways to build things. And I'mexcited to see the benefits of MCP beingexplored in other formats like this. Genuinely really cool work by theCloudflare team. Shout out to bothKenton and Sunnil for the work they putinto this and being as transparent asthey have been with what they have foundand what they're working on. This ishopefully going to push the wholeindustry forward as we learn more andmore and we build more and more usingthese things. A future where we're notdestroying our context windows, not justadding literally dozens of tools foreverything we want to do, and instead wejust have code being written to do whatwe want instead. Sounds like a muchbetter thing. Code is good. We shouldn'tbe so scared of it. Just because AI willabstract it for us doesn't mean the codeitself isn't valuable. And I'm surprisedthat this hasn't been explored more indepth already. Let me know what you guysthink. Am I being too harsh on MCP, or isthis actually a potential path forward?Let me know. And until next time, peace. Nerds., MCP Is the Wrong Abstraction, Theo - t3․gg, 01k6x516t0p4gfxwc45gtc5k6q.