What if you don't need MCP at all?

2025-11-1618:58235183mariozechner.at

Got Bash and some code interpreter? Skip MCP.

2025-11-02

One chonky MCP server

After months of agentic coding frenzy, Twitter is still ablaze with discussions about MCP servers. I previously did some very light benchmarking to see if Bash tools or MCP servers are better suited for a specific task. The TL;DR: both can be efficient if you take care.

Unfortunately, many of the most popular MCP servers are inefficient for a specific task. They need to cover all bases, which means they provide large numbers of tools with lengthy descriptions, consuming significant context.

It's also hard to extend an existing MCP server. You could check out the source and modify it, but then you'd have to understand the codebase, together with your agent.

MCP servers also aren't composable. Results returned by an MCP server have to go through the agent's context to be persisted to disk or combined with other results.

I'm a simple boy, so I like simple things. Agents can run Bash and write code well. Bash and code are composable. So what's simpler than having your agent just invoke CLI tools and write code? This is nothing new. We've all been doing this since the beginning. I'd just like to convince you that in many situations, you don't need or even want an MCP server.

Let me illustrate this with a common MCP server use case: browser dev tools.

My Browser DevTools Use Cases

My use cases are working on web frontends together with my agent, or abusing my agent to become a scrapey little hacker boy so I can scrape all the data in the world. For these two use cases, I only need a minimal set of tools:

  • Start the browser, optionally with my default profile so I'm logged in
  • Navigate to a URL, either in the active tab or a new tab
  • Execute JavaScript in the active page context
  • Take a screenshot of the viewport

And if my use case requires additional special tooling, I want to quickly have my agent generate that for me and slot it in with the other tools.

Problems with Common Browser DevTools for Your Agent

People will recommend Playwright MCP or Chrome DevTools MCP for the use cases I illustrated above. Both are fine, but they need to cover all the bases. Playwright MCP has 21 tools using 13.7k tokens (6.8% of Claude's context). Chrome DevTools MCP has 26 tools using 18.0k tokens (9.0%). That many tools will confuse your agent, especially when combined with other MCP servers and built-in tools.

Using those tools also means you suffer from the composability issue: any output has to go through your agent's context. You can kind of fix this by using sub-agents, but then you rope in all the issues that sub-agents come with.

Embracing Bash (and Code)

Here's my minimal set of tools, illustrated via the README.md:

# Browser Tools Minimal CDP tools for collaborative site exploration. ## Start Chrome \`\`\`bash
./start.js # Fresh profile
./start.js --profile # Copy your profile (cookies, logins)
\`\`\` Start Chrome on `:9222` with remote debugging. ## Navigate \`\`\`bash
./nav.js https://example.com
./nav.js https://example.com --new
\`\`\` Navigate current tab or open new tab. ## Evaluate JavaScript \`\`\`bash
./eval.js 'document.title'
./eval.js 'document.querySelectorAll("a").length'
\`\`\` Execute JavaScript in active tab (async context). ## Screenshot \`\`\`bash
./screenshot.js
\`\`\`

Screenshot current viewport, returns temp file path.

This is all I feed to my agent. It's a handful of tools that cover all the bases for my use case. Each tool is a simple Node.js script that uses Puppeteer Core. By reading that README, the agent knows the available tools, when to use them, and how to use them via Bash.

When I start a session where the agent needs to interact with a browser, I just tell it to read that file in full and that's all it needs to be effective. Let's walk through their implementations to see how little code this actually is.

The Start Tool

The agent needs to be able to start a new browser session. For scraping tasks, I often want to use my actual Chrome profile so I'm logged in everywhere. This script either rsyncs my Chrome profile to a temporary folder (Chrome doesn't allow debugging on the default profile), or starts fresh:

 import { spawn, execSync } from "node:child_process";
import puppeteer from "puppeteer-core"; const useProfile = process.argv[2] === "--profile"; if (process.argv[2] && process.argv[2] !== "--profile") { console.log("Usage: start.ts [--profile]"); console.log("\nOptions:"); console.log(" --profile Copy your default Chrome profile (cookies, logins)"); console.log("\nExamples:"); console.log(" start.ts # Start with fresh profile"); console.log(" start.ts --profile # Start with your Chrome profile"); process.exit(1);
} try { execSync("killall 'Google Chrome'", { stdio: "ignore" });
} catch {} await new Promise((r) => setTimeout(r, 1000)); execSync("mkdir -p ~/.cache/scraping", { stdio: "ignore" }); if (useProfile) { execSync( 'rsync -a --delete "/Users/badlogic/Library/Application Support/Google/Chrome/" ~/.cache/scraping/', { stdio: "pipe" }, );
} spawn( "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", ["--remote-debugging-port=9222", `--user-data-dir=${process.env["HOME"]}/.cache/scraping`], { detached: true, stdio: "ignore" },
).unref(); let connected = false;
for (let i = 0; i < 30; i++) { try { const browser = await puppeteer.connect({ browserURL: "http://localhost:9222", defaultViewport: null, }); await browser.disconnect(); connected = true; break; } catch { await new Promise((r) => setTimeout(r, 500)); }
} if (!connected) { console.error("✗ Failed to connect to Chrome"); process.exit(1);
} console.log(`✓ Chrome started on :9222${useProfile ? " with your profile" : ""}`);

All the agent needs to know is to use Bash to run the start.js script, either with --profile or without.

The Navigate Tool

Once the browser is running, the agent needs to navigate to URLs, either in a new tab or the active tab. That's exactly what the navigate tool provides:

 import puppeteer from "puppeteer-core"; const url = process.argv[2];
const newTab = process.argv[3] === "--new"; if (!url) { console.log("Usage: nav.js <url> [--new]"); console.log("\nExamples:"); console.log(" nav.js https://example.com # Navigate current tab"); console.log(" nav.js https://example.com --new # Open in new tab"); process.exit(1);
} const b = await puppeteer.connect({ browserURL: "http://localhost:9222", defaultViewport: null,
}); if (newTab) { const p = await b.newPage(); await p.goto(url, { waitUntil: "domcontentloaded" }); console.log("✓ Opened:", url);
} else { const p = (await b.pages()).at(-1); await p.goto(url, { waitUntil: "domcontentloaded" }); console.log("✓ Navigated to:", url);
} await b.disconnect();

The Evaluate JavaScript Tool

The agent needs to execute JavaScript to read and modify the DOM of the active tab. The JavaScript it writes runs in the page context, so it doesn't have to fuck around with Puppeteer itself. All it needs to know is how to write code using the DOM API, and it sure knows how to do that:

 import puppeteer from "puppeteer-core"; const code = process.argv.slice(2).join(" ");
if (!code) { console.log("Usage: eval.js 'code'"); console.log("\nExamples:"); console.log(' eval.js "document.title"'); console.log(' eval.js "document.querySelectorAll(\'a\').length"'); process.exit(1);
} const b = await puppeteer.connect({ browserURL: "http://localhost:9222", defaultViewport: null,
}); const p = (await b.pages()).at(-1); if (!p) { console.error("✗ No active tab found"); process.exit(1);
} const result = await p.evaluate((c) => { const AsyncFunction = (async () => {}).constructor; return new AsyncFunction(`return (${c})`)();
}, code); if (Array.isArray(result)) { for (let i = 0; i < result.length; i++) { if (i > 0) console.log(""); for (const [key, value] of Object.entries(result[i])) { console.log(`${key}: ${value}`); } }
} else if (typeof result === "object" && result !== null) { for (const [key, value] of Object.entries(result)) { console.log(`${key}: ${value}`); }
} else { console.log(result);
} await b.disconnect();

The Screenshot Tool

Sometimes the agent needs to have a visual impression of a page, so naturally we want a screenshot tool:

 import { tmpdir } from "node:os";
import { join } from "node:path";
import puppeteer from "puppeteer-core"; const b = await puppeteer.connect({ browserURL: "http://localhost:9222", defaultViewport: null,
}); const p = (await b.pages()).at(-1); if (!p) { console.error("✗ No active tab found"); process.exit(1);
} const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
const filename = `screenshot-${timestamp}.png`;
const filepath = join(tmpdir(), filename); await p.screenshot({ path: filepath }); console.log(filepath); await b.disconnect();

This will take a screenshot of the current viewport of the active tab, write it to a .png file in a temporary directory, and output the file path to the agent, which can then turn around and read it in and use its vision capabilities to "see" the image.

The Benefits

So how does this compare to the MCP servers I mentioned above? Well, to start, I can pull in the README whenever I need it and don't pay for it in every session. This is very similar to Anthropic's recently introduced skills capabilities. Except it's even more ad hoc and works with any coding agent. All I need to do is instruct my agent to read the README file.

Side note: many folks including myself have used this kind of setup before Anthropic released their skills system. You can see something similar in my "Prompts are Code" blog post or my little sitegeist.ai. Armin has also touched on the power of Bash and code compared to MCPs previously. Anthropic's skills add progressive disclosure (love it) and they make them available to a non-technical audience across almost all their products (also love it).

Speaking of the README, instead of pulling in 13,000 to 18,000 tokens like the MCP servers mentioned above, this README has a whopping 225 tokens. This efficiency comes from the fact that models know how to write code and use Bash. I'm conserving context space by relying heavily on their existing knowledge.

These simple tools are also composable. Instead of reading the outputs of an invocation into the context, the agent can decide to save them to a file for later processing, either by itself or by code. The agent can also easily chain multiple invocations in a single Bash command.

If I find that the output of a tool is not token efficient, I can just change the output format. Something that's hard or impossible to do depending on what MCP server you use.

And it's ridiculously easy to add a new tool or modify an existing tool for my needs. Let me illustrate.

Adding the Pick Tool

When the agent and I try to come up with a scraping method for a specific site, it's often more efficient if I'm able to point out DOM elements to it directly by just clicking on them. To make this super easy, I can just build a picker. Here's what I add to the README:

## Pick Elements \`\`\`bash
./pick.js "Click the submit button"
\`\`\`

Interactive element picker. Click to select, Cmd/Ctrl+Click for multi-select, Enter to finish.

And here's the code:

 import puppeteer from "puppeteer-core"; const message = process.argv.slice(2).join(" ");
if (!message) { console.log("Usage: pick.js 'message'"); console.log("\nExample:"); console.log(' pick.js "Click the submit button"'); process.exit(1);
} const b = await puppeteer.connect({ browserURL: "http://localhost:9222", defaultViewport: null,
}); const p = (await b.pages()).at(-1); if (!p) { console.error("✗ No active tab found"); process.exit(1);
} await p.evaluate(() => { if (!window.pick) { window.pick = async (message) => { if (!message) { throw new Error("pick() requires a message parameter"); } return new Promise((resolve) => { const selections = []; const selectedElements = new Set(); const overlay = document.createElement("div"); overlay.style.cssText = "position:fixed;top:0;left:0;width:100%;height:100%;z-index:2147483647;pointer-events:none"; const highlight = document.createElement("div"); highlight.style.cssText = "position:absolute;border:2px solid #3b82f6;background:rgba(59,130,246,0.1);transition:all 0.1s"; overlay.appendChild(highlight); const banner = document.createElement("div"); banner.style.cssText = "position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:#1f2937;color:white;padding:12px 24px;border-radius:8px;font:14px sans-serif;box-shadow:0 4px 12px rgba(0,0,0,0.3);pointer-events:auto;z-index:2147483647"; const updateBanner = () => { banner.textContent = `${message} (${selections.length} selected, Cmd/Ctrl+click to add, Enter to finish, ESC to cancel)`; }; updateBanner(); document.body.append(banner, overlay); const cleanup = () => { document.removeEventListener("mousemove", onMove, true); document.removeEventListener("click", onClick, true); document.removeEventListener("keydown", onKey, true); overlay.remove(); banner.remove(); selectedElements.forEach((el) => { el.style.outline = ""; }); }; const onMove = (e) => { const el = document.elementFromPoint(e.clientX, e.clientY); if (!el || overlay.contains(el) || banner.contains(el)) return; const r = el.getBoundingClientRect(); highlight.style.cssText = `position:absolute;border:2px solid #3b82f6;background:rgba(59,130,246,0.1);top:${r.top}px;left:${r.left}px;width:${r.width}px;height:${r.height}px`; }; const buildElementInfo = (el) => { const parents = []; let current = el.parentElement; while (current && current !== document.body) { const parentInfo = current.tagName.toLowerCase(); const id = current.id ? `#${current.id}` : ""; const cls = current.className ? `.${current.className.trim().split(/\s+/).join(".")}` : ""; parents.push(parentInfo + id + cls); current = current.parentElement; } return { tag: el.tagName.toLowerCase(), id: el.id || null, class: el.className || null, text: el.textContent?.trim().slice(0, 200) || null, html: el.outerHTML.slice(0, 500), parents: parents.join(" > "), }; }; const onClick = (e) => { if (banner.contains(e.target)) return; e.preventDefault(); e.stopPropagation(); const el = document.elementFromPoint(e.clientX, e.clientY); if (!el || overlay.contains(el) || banner.contains(el)) return; if (e.metaKey || e.ctrlKey) { if (!selectedElements.has(el)) { selectedElements.add(el); el.style.outline = "3px solid #10b981"; selections.push(buildElementInfo(el)); updateBanner(); } } else { cleanup(); const info = buildElementInfo(el); resolve(selections.length > 0 ? selections : info); } }; const onKey = (e) => { if (e.key === "Escape") { e.preventDefault(); cleanup(); resolve(null); } else if (e.key === "Enter" && selections.length > 0) { e.preventDefault(); cleanup(); resolve(selections); } }; document.addEventListener("mousemove", onMove, true); document.addEventListener("click", onClick, true); document.addEventListener("keydown", onKey, true); }); }; }
}); const result = await p.evaluate((msg) => window.pick(msg), message); if (Array.isArray(result)) { for (let i = 0; i < result.length; i++) { if (i > 0) console.log(""); for (const [key, value] of Object.entries(result[i])) { console.log(`${key}: ${value}`); } }
} else if (typeof result === "object" && result !== null) { for (const [key, value] of Object.entries(result)) { console.log(`${key}: ${value}`); }
} else { console.log(result);
} await b.disconnect();

Whenever I think it's faster for me to just click on a bunch of DOM elements instead of having the agent figure out the DOM structure, I can just tell it to use the pick tool. It's super efficient and allows me to build scrapers in no time. It's also fantastic to adjust the scraper if the DOM layout of a site changed.

If you're having trouble following what this tool does, worry not, I will have a video at the end of the blog post where you can see it in action. Before we look at that, let me show you an additional tool.

Adding the Cookies Tool

During one of my recent scraping adventures, I had a need for HTTP-only cookies of that site, so the deterministic scraper could pretend it's me. The Evaluate JavaScript tool cannot handle this as it executes in the page context. But it took not even a minute for me to instruct Claude to create that tool, add it to the readme, and away we went.

This is so much easier than adjusting, testing, and debugging an existing MCP server.

A Contrived Example

Let me illustrate usage of this set of tools with a contrived example. I set out to build a simple Hacker News scraper where I basically pick the DOM elements for the agent, based on which it can then write a minimal Node.js scraper. Here's how that looks in action. I sped up a few sections where Claude was its usual slow self.

Real world scraping tasks would look a bit more involved. Also, there's no point in doing it like this for such a simple site like Hacker News. But you get the idea.

Final token tally:

Making This Reusable Across Agents

Here's how I've set things up so I can use this with Claude Code and other agents. I have a folder agent-tools in my home directory. I then clone the repositories of individual tools, like the browser tools repository above, into that folder. Then I set up an alias:

alias cl="PATH=$PATH:/Users/badlogic/agent-tools/browser-tools:<other-tool-dirs> && claude --dangerously-skip-permissions"

This way all of the scripts are available to sessions of Claude, but don't pollute my normal environment. I also prefix each script with the full tool name, e.g. browser-tools-start.js, to eliminate name collisions. I also add a single sentence to the README telling the agent that all the scripts are globally available. This way, the agent doesn't have to change its working directory just to call a tool script, saving a few tokens here and there, and reducing the chances of the agent getting confused by the constant working directory changes.

Finally, I add the agent tools directory as a working directory to Claude Code via /add-dir, so I can use @README.md to reference a specific tool's README file and get it into the agent's context. I prefer this to Anthropic's skill auto-discovery, which I found to not work reliably in practice. It also means I save a few more tokens: Claude Code injects all the frontmatter of all skills it can find into the system prompt (or first user message, I forgot, see https://cchistory.mariozechner.at)

In Conclusion

Building these tools is ridiculously easy, gives you all the freedom you need, and makes you, your agent, and your token usage efficient. You can find the browser tools on GitHub.

This general principle can apply to any kind of harness that has some kind of code execution environment. Think outside the MCP box and you'll find that this is much more powerful than the more rigid structure you have to follow with MCP.

With great power comes great responsibility though. You will have to come up with a structure for how you build and maintain those tools yourself. Anthropic's skill system can be one way to do it, though that's less transferable to other agents. Or you follow my setup above.

This page respects your privacy by not using cookies or similar technologies and by not collecting any personally identifiable information.


Read the original article

Comments

  • By whoknowsidont 2025-11-1621:378 reply

    MCP was a really shitty attempt at building a plugin framework that was vague enough to lure people into and then allow other companies to build plugin platforms to take care of the MCP non-sense.

    "What is MCP, what does it bring to the table? Who knows. What does it do? The LLM stuff! Pay us $10 a month thanks!"

    LLM's have function / tool calling built into them. No major models have any direct knowledge of MCP.

    Not only do you not need MCP, but you should actively avoid using it.

    Stick with tried and proven API standards that are actually observable and secure and let your models/agents directly interact with those API endpoints.

    • By jcelerier 2025-11-174:181 reply

      > LLM's have function / tool calling built into them. No major models have any direct knowledge of MCP.

      but the major user interfaces for operating LLMs do and that's what matters

      > Not only do you not need MCP, but you should actively avoid using it.

      > Stick with tried and proven API standards that are actually observable and secure and let your models/agents directly interact with those API endpoints.

      so what's the proven and standard API I can use to interact with ableton live? blender? unity3d? photoshop?

      • By whoknowsidont 2025-11-174:221 reply

        [flagged]

        • By nilslice 2025-11-175:232 reply

          What do all of the links below have in common? Do you know of another way you can control all of those applications via LLMs? Computer use?

          https://github.com/ahujasid/ableton-mcp

          https://github.com/ahujasid/blender-mcp

          https://github.com/CoplayDev/unity-mcp

          https://github.com/mikechambers/adb-mcp

          • By growt 2025-11-176:273 reply

            The mcp part is not essential for the actual controlling of the applications. You could “rip out” the mcp functionality and replace it with something else. The only reason why the authors chose mcp is most likely that it was the first and therefore most common plugin interface for llm tools.

            • By TranquilMarmot 2025-11-177:071 reply

              Unfortunately, most standards that we end up with are only standard because they're are widely used and not because they are the best or they make the most sense.

            • By theshrike79 2025-11-177:011 reply

              MCP literally is the "something else", if you have a better idea in mind, now is the time to bring it out before the MCP train is going too fast to catch up.

            • By Zetaphor 2025-11-176:40

              Isn't that the point they are making? MCP is useful because everyone is using it, not because it has a technical advantage over rolling your own solution. It won mindshare because of marketing and a large company pushing it.

              I've actually taken to both approaches recently, using the mcp-client package to give me an interface to a wide array of prebuilt tools in my non-LLM application. I could have written or sourced 10 different connectors, or I can write one client interface and any tool I plug in shares the same standard interface as all the others.

          • By whoknowsidont 2025-11-1716:212 reply

            Can you do yourself a favor and look at the source code and tell me why you think MCP is necessary here?

            I mean you just took some examples and went "See MCP!" without any actual understanding of what that code is doing.

            All of these have underlying API's that have exactly ZERO need for MCP. All of this functionality already exists and can be used with LLM's.

            * https://help.ableton.com/hc/en-us/articles/209072009-Install...

            * https://docs.blender.org/api/current/info_quickstart.html

            * https://docs.unity3d.com/6000.2/Documentation/ScriptReferenc...

            The most hilarious quote from one of those projects:

            >The proxy server is required because the public facing API for UXP Based JavaScript plugin does not allow it to listen on a socket connection (as a server) for the MCP Server to connect to (it can only connect to a socket as a client).

            Maybe that should have been the sign that this was completely unnecessary and stupid?

            >Do you know of another way you can control all of those applications via LLMs?

            Seriously. This becoming a bad joke. I mean conceptually, what did you think was happening here? MCP was just magically doing something that didn't already exist before?

            It's a waste of effort and time. Do not use MCP.

            • By jcelerier 2025-11-1813:56

              So again, how do I automate Ableton live over a network socket with a standard API? I don't know if you've read the remote control API but it doesn't open a magic socket to remote control Live, you have to code the entire integration and protocol yourself to map whatever API messages you want to Live actions manually.

              Let's forget about LLMs completely as they are only tangentially relevant to the benefits of MCP. I want to write 15 lines of python that - no matter the software - is going to trigger the "play" button/action in that software. E.g. I want to hit "play" in both Ableton, Unity and Blender without having to write three times the code, without having to manually write them each an extension plug-ins. How do you do that, today, 2025-11-17 ?

            • By nilslice 2025-11-1722:04

              Idk what you think you have to gain with your stance lol

              No one looks at MCP and sees "magic", they just see "finished integration". Something you can pretty much use straight away. That's the point.

    • By didibus 2025-11-173:511 reply

      > MCP was a really shitty attempt at building a plugin framework

      Can you go more in depth? The protocol is relatively simple, what about it you feel is "shitty" as a plugin framework?

      • By paulddraper 2025-11-174:173 reply

        The hate for MCP here is absurd.

        It's JSON-RPC, with some descriptors.

        And some comments about OAuth 2.

        The value is in the consensus. You can make a tool that agents can connect to with no apriori knowledge.

        • By rcarmo 2025-11-1715:421 reply

          Actually, MCP wastes a lot of tokens when compared to regular tool calling. You might not notice it on more trendy models with large contexts, but for those of us trying to use locked down/local/cheap models it makes very little sense.

          Also, MCP creates a new problem: providing the model with too much context when trying to combine tools across multiple servers. It works OK with small, very focused servers (like helpers for a specific data set), but if you try to mix and match servers things get out of hand really quickly and the entire workflow becomes very unreliable—too many options to digest and pursue, just like humans.

          • By didibus 2025-11-1717:061 reply

            Is that just bad implementation? Where are the wasted tokens?

            I noticed your second issue, but to me it's just from bad implementation. For some reason people keep exposing generic overlapping tools from multiple MCP servers.

            I don't know that MCP causes this issue, any vendor offering a "tools API" if they shove to many APIs it would bloat things up.

            • By cstrahan 2025-11-1719:323 reply

              > Is that just bad implementation? Where are the wasted tokens?

              How wouldn't it be wasteful?

              I'll try to summarize a couple sources:

              https://www.anthropic.com/engineering/code-execution-with-mc...

              https://blog.cloudflare.com/code-mode/

              Here's what Anthropic has to say about it: As MCP usage scales, there are two common patterns that can increase agent cost and latency:

                  Tool definitions overload the context window;
                  Intermediate tool results consume additional tokens.
                  
                  [...]
                  
                  Tool descriptions occupy more context window space, increasing response time and costs. In cases where agents are connected to thousands of tools, they’ll need to process hundreds of thousands of tokens before reading a request.
                  
                  [...]
                  
                  Most MCP clients allow models to directly call MCP tools. For example, you might ask your agent: "Download my meeting transcript from Google Drive and attach it to the Salesforce lead."
                  
                  The model will make calls like:
                  
                    TOOL CALL: gdrive.getDocument(documentId: "abc123")
                            → returns "Discussed Q4 goals...\n[full transcript text]"
                               (loaded into model context)
                    
                    TOOL CALL: salesforce.updateRecord(
                       objectType: "SalesMeeting",
                       recordId: "00Q5f000001abcXYZ",
                         data: { "Notes": "Discussed Q4 goals...\n[full transcript text written out]" }
                      )
                      (model needs to write entire transcript into context again)
                  
                  Every intermediate result must pass through the model. In this example, the full call transcript flows through twice. For a 2-hour sales meeting, that could mean processing an additional 50,000 tokens. Even larger documents may exceed context window limits, breaking the workflow.
                  
                  With large documents or complex data structures, models may be more likely to make mistakes when copying data between tool calls.
              
              
              Now, if you were to instead have the LLM write code, that code can perform whatever filtering/aggregation/transformation etc that it needs, without having to round-trip from LLM to tool(s), back and forth, and the only tokens that are consumed are those of the final result. What happens with MCP? All of the text of each MCP call is flooded into the context, only for the LLM to have to make sense of what it just read to then either regurgitate that out into a file to post process (very likely with differences/"hallucinations" slipped in), or in the usual case (I'm personifying the LLM here for rhetorical purposes) it simply tries to reason about what it read to give you the filtered/aggregated/transformed/etc result you're looking for -- again, very likely with mistakes made.

        • By whoknowsidont 2025-11-174:282 reply

          >It's JSON-RPC, with some descriptors.

          That's not even true. It defines the lifecycle of tool calling.

          JSON-RPC with some descriptors would have been fine and amazing.

          • By frumplestlatz 2025-11-1711:56

            I’m struggling to understand where you’re coming from. Your hate for MCP seems grossly outsized relative to what it actually is.

            • By whoknowsidont 2025-11-1716:241 reply

              You linked to one part of the spec and just wanted to ignore everything else? That's fine, but then you wouldn't be obeying the standard and wouldn't be an "MCP."

              So, are you agreeing with me?

              Respectfully I think I've engaged with you before and you just seem generally confused about nuanced concepts.

        • By manbitesdog 2025-11-1712:28

          Things like OpenAPI have existed for 15 years now and they also offer standarization.

          The value on MCP is not on its features or innovation, but on the rate of adoption it has had. Companies have now an incentive to open, document and standarize their APIs to enable this new distribution channel.

    • By block_dagger 2025-11-177:222 reply

      Perhaps you haven't used many MCP server, but those that I have used (GitHub, Atlassian, Glean, BuildKite, Figma, Google Workspace, etc) work very well. They teach an LLM how to do exactly what you're saying - "use the API standards...your models/agents directly interact with those API endpoints." Most MCP severs don't sit in between the LLM and the API endpoints, they just teach them how to use the tools and then the LLM calls the APIs directly as any HTTP client would. I find it works quite well and seems far better than manually maintaining rules or pointing at docs and installing CLI tools (like "gh" for GitHub) or using curl to interact with APIs from a terminal within a chat session.

      • By cstrahan 2025-11-1721:09

        > but those that I have used (GitHub, [...])

        > Most MCP severs don't sit in between the LLM and the API endpoints [...]

        Your first example certainly isn't an example of that: https://github.com/github/github-mcp-server

        I suppose someone could try to abuse MCP by stuffing information about REST API endpoints into a the prompt/descriptions in a small MCP "skeleton" service, but I don't know of any. Can you provide examples?

        > they just teach them how to use the tools and then the LLM calls the APIs directly as any HTTP client would.

        I suspect you might have some deep misunderstandings about MCP.

      • By whoknowsidont 2025-11-1716:22

        >, they just teach them how to use the tools and then the LLM calls the APIs directly as any HTTP client would.

        No. MCP does not do this. Function & tool calling is built into the LLM. MCP is not augmenting this ability in ANY way.

    • By paulddraper 2025-11-172:151 reply

      > No major models have any direct knowledge of MCP.

      Claude and ChatGPT both support MCP, as does the OpenAI Agents SDK.

      (If you mean the LLM itself, it is "known" at least as much as any other protocol. For whatever that means.)

      • By whoknowsidont 2025-11-172:576 reply

        >it is "known" at least as much as any other protocol.

        No. It is not. Please understand what the LLM's are doing. Claude nor ChatGPT nor any major model knows what MCP is.

        They know how to function & tool call. They have zero trained data on MCP.

        That is a factual statement, not an opinion.

        • By Bockit 2025-11-173:082 reply

          This is probably a semantics problem. You’re right. The models don’t know how to mcp. The harness they run in does though (Claude code, Claude desktop, etc), and dynamically exposes mcp tools as tool calls.

          • By whoknowsidont 2025-11-173:17

            >dynamically exposes mcp tools as tool calls.

            It doesn't even do that. It's not magic.

          • By llbbdd 2025-11-173:11

            HN loves inventing semantics problems around AI. It's gotten really, really annoying and I'm not sure the people doing it are even close to understanding it.

        • By choilive 2025-11-173:072 reply

          That is an easily falsifiable statement. If I ask ChatGPT or Claude what MCP is Model Context Protocol comes up, and furthermore it can clearly explain what MCP does. That seems unlikely to be a coincidental hallucination.

          • By whoknowsidont 2025-11-173:162 reply

            Training data =/= web search

            Both ChatGPT and Claude will perform web searches when you ask them a question, which the fact that you got this confused is ironically topical.

            But you're still misunderstanding the principle point because at some point these models will undoubtedly have access to that data and be trained on it.

            But they didn't need to be, because LLM function & tool calling is already trained on these models and MCP does not augment this functionality in any way.

            • By davidcbc 2025-11-173:431 reply

              Claude gives me a lengthy explanation of MCP with web search disabled

            • By judahmeek 2025-11-2111:33

              > But they didn't need to be, because LLM function & tool calling is already trained on these models and MCP does not augment this functionality in any way.

              I think you're making a weird semantic argument. How is MCP use not a tool call?

          • By cstrahan 2025-11-1719:54

            You're misinterpreting OP.

            OP is saying that the models have not been trained on particular MCP use, which is why MCP servers serve up tool descriptions, which are fed to the LLM just like any other text -- that is, these descriptions consume tokens and take up precious context.

            Here's a representative example, taken from a real world need I had a week ago. I want to port a code base from one language to another (ReasonML to TypeScript, for various reasons). I figure the best way to go about this would be to topologically sort the files by their dependencies, so I can start with porting files with absolutely zero imports, then port files where the only dependencies are on files I've already ported, and so on. Let's suppose I want to use Claude Code to help with this, just to make the choice of agent concrete.

            How should I go about this?

            The overhead of the MCP approach would be analogous to trying to cram all of the relevant files into the context, and asking Claude to sort them. Even if the context window is sufficient, that doesn't matter because I don't want Claude to "try its best" to give me the topological sort straight from its nondeterministic LLM "head".

            So what did I do?

            I gave it enough information about how to consult build metadata files to derive the dependency graph, and then had it write a Python script. The LLM is already trained on a massive corpus of Python code, so there's no need to spoon feed it "here's such and such standard library function", or "here's the basic Python syntax", etc -- it already "knows" that. No MCP tool descriptions required.

            And then Claude code spits out a script that, yes, I could have written myself, but it does it in maybe 1 minute total of my time. I can skim the script and make sure that it does exactly what it should be doing. Given that this is code, and not nondeterministic wishy washy LLM "reasoning", I know that the result is both deterministic and correct. The total token usage is tiny.

            If you look at what Anthropic and CloudFlare have to say on the matter (see https://www.anthropic.com/engineering/code-execution-with-mc... and https://blog.cloudflare.com/code-mode/), it's basically what I've described, but without explicitly telling the LLM to write a script / reviewing that script.

            If you have the LLM write code to interface with the world, it can leverage its training in that code, and the code itself will do what code does (precisely what it was configured to do), and the only tokens consumed will be the final result.

            MCP is incredibly wasteful and provides more opportunities for LLMs to make mistakes and/or get confused.

        • By cookiengineer 2025-11-174:04

          > That is a factual statement,

          I think most people, even most devs, don't actually know how crappy an MCP client is built, and that it's essentially an MITM approach and that the client sends the LLM on the other end a crappy pretext of what tools are mounted and how to call their methods in a JSON, and then tries to intelligently guess what response was a tool call.

          And that intelligent guess is where it gets interesting for pentesting, because you cannot guess anything failsafe.

        • By paulddraper 2025-11-174:121 reply

          > They have zero trained data on MCP.

          They have significant data trained on MCP.

          > They know how to function & tool call.

          Right. You can either use MCP to transmit those tool calls, or you can create some other interface.

          • By whoknowsidont 2025-11-174:301 reply

            >They have significant data trained on MCP.

            No they don't lol.

            • By paulddraper 2025-11-1715:282 reply

              Wild claim.

              MCP has been popular for well over a year.

              To filter it out of the training data would be laughable.

        • By numpad0 2025-11-173:141 reply

          (pedantry)it's something humans are talking about a lot, so up-to-date models do know about it...

          • By whoknowsidont 2025-11-173:22

            Most likely! It's hard to qualify which specific models and version I'm talking about because they're constantly being updated.

            But the point is that function & tool calling was already built in. If you take a model from before "MCP" was even referenced on the web it will still _PERFECTLY_ interact with not only other MCP servers and clients but any other API as well.

    • By cyanydeez 2025-11-1621:516 reply

      probably easier to just tell people: You want MCP? Add a "description" field to your rest API that describes how to call it.

      That's all it's doing. Just plain ole context pollution. World could be better served by continuing to build out the APIs that exist.

      • By pests 2025-11-172:561 reply

        Sometimes the actions you want to perform does not map cleanly into one or two API calls, or would be too messy to assume correct parsing. Maybe your UI is fine POSTing to /users and PUTing to /groups or whatever but giving the LLM a direct CreateUserAndAddToGroup action simplifies the task and keeps context cleaner.

        • By cstrahan 2025-11-1720:08

          This is very true. But why stop there?

          Imagine a future where we have an evolved version of MCP -- call it MCP++.

          In MCP++, instead of having to implement a finite list of specialized variants like CreateUserAndAddToGroup, imagine MCP++ has a way to to feed the desired logic (create user, then add that user to $GROUP) directly to the endpoint. So there would be something like a POST /exec endpoint. And then the /exec endpoint can run the code (maybe it's WASM for something)...

          Wait a minute! We already have this. It's called programming.

          You could have the LLM write code, so that any pipelining (like your example), aggregation, filtering, or other transformation happens in that code, and the LLM only needs to spend the output tokens to write the code, and the only input tokens consumed is the final result.

          I definitely am not the first person to suggest this:

          https://www.anthropic.com/engineering/code-execution-with-mc...

          https://blog.cloudflare.com/code-mode/

          ... but I can say that, as soon as I read about MCP, my first thought was "why?"

          MCP is wasteful.

          If you want LLMs to interact with your software/service, write a library, let the scrapers scrape that code so that future LLM revisions have the library "baked into it" (so you no longer need to spam the context with MCP tool descriptions), and let the LLM write code, which it already "knows" how to do.

          What if your library is too new, or has a revision, though?

          That's already a solved problem -- you do what you'd do in any other case where you want the LLM to write code for you: point it at the docs / codebase.

      • By jes5199 2025-11-1622:311 reply

        yesss, and OpenAI tried this first when they were going to do a “GPT store”. But REST APIs tend to be complicated because they’re supporting apps. MCP, when it works, is very simple functions

        in practice it seems like command line tools work better than either of those approaches

        • By CuriouslyC 2025-11-1623:39

          Command line tools are my preference just because they're also very useful to humans. I think providing agents function libraries and letting them compose in a repl works about as well but is higher friction due env management.

      • By tacticus 2025-11-1622:29

        > Add a "description" field to your rest API that describes how to call it.

        Isn't that swagger\grpc etc?

      • By EagnaIonat 2025-11-175:43

        > Just plain ole context pollution.

        It would normally be a second context window to figure out what tool / agent to run.

        My only quibble with MCP is in the usual AI bandwagon people are implementing for FOMO than business value. My experience is likely anecdotal though.

      • By mycall 2025-11-171:32

        Also, keep your api small as all the tool call, DTOs and user messages (e.g. workflow recipes) add up to big context windows and accuracy confusion, at least in the latest models. I hope that gets resolved.

      • By blitzar 2025-11-178:39

        > World could be better served by continuing to build out the APIs that exist.

        before LLM's and MCP the world was depreciating or locking down APIs

    • By timClicks 2025-11-176:28

      MCP is an example of "worse is better". Everyone knows that it's not very good, but it gets the job done.

    • By voidhorse 2025-11-170:282 reply

      Yeah there's no there there when it comes to MCP. It's crazy to me that the world bought into the idea when the "spec" literally boils down to "have your server give the LLM some json". Just illustrates how powerful it is to attach names to things, especially in a hypestorm in which everyone is already frothing at the mouth and reason is hard to come by. Give people some word they can utter to help them sound like they're on the "bleeding edge" and they'll buy into it even if it's totally pointless.

      • By tptacek 2025-11-170:522 reply

        "Have your XYZ give the LLM some JSON" is pretty close to how all tool calling works with or without MCP.

        • By what-the-grump 2025-11-172:33

          What next you are going to tell me rest and async are implemented in code?! And not just willed into existence by the compiler!

        • By mycall 2025-11-171:33

          Markdown is for output too.

      • By anon84873628 2025-11-181:591 reply

        It gave everyone a reason to think about the usability of the interfaces they were exposing.

        Many endpoints have tons of fields irrelevant to 95% of external users. Now those are gone.

        Or they implemented higher level abstractions for the actual tasks instead of making developers compose a bunch of little pieces.

        And it has a standardized manifest.

        Execs, PMs, and customers having that word to utter as part of the AI hype train created the opportunity for that industry-wide cleanup to happen. Calling it pointless is very naive. It's actually kind of extraordinary.

        • By voidhorse 2025-11-185:21

          Thanks for offering another perspective on it. I can buy into this partially.

          At the same time, I'm skeptical that this won't just become yet another dead protocol once the hype abates, at which point all of the perceived benefits were for naught.

    • By pjmlp 2025-11-178:57

      Fully agree, however we need to reach our KPIs and OKRs regarding AI adoption.

  • By upghost 2025-11-1623:316 reply

    So I don't disagree with any of the criticisms of MCPs but no one here has mentioned why they are useful, and I'm not sure that everyone is aware that MCP is actually just a wrapper over existing cli/API:

    1. Claude Code is aware of what MCPs it has access to at all times.

    2. Adding an MCP is like adding to the agent's actuators/vocabulary/tools because unlike cli tools or APIs you don't have to constantly remind it what MCPs it has available and "hey you have access to X" and "hey make an MCP for X" take the same level of effort on the part of the user.

    3. This effect is _significantly_ stronger than putting info about available API/cli into CLAUDE.md.

    4. You can almost trivially create an MCP that does X by asking the agent to create an MCP that does X. This saves you from having to constantly remind an agent it can do X.

    NOTE: I cannot stress enough that this property of MCPs is COMPLETELY ORTHOGONAL to the nutty way they are implemented, and I am IN NO WAY defending the implementation. But currently we are talking past the primary value prop.

    I would personally prefer some other method but having a way to make agents extensible is extremely useful.

    EXAMPLE:

    "Make a bash script that does X."

    <test manually to make sure it works>

    "Now make an MCP called Xtool that uses X."

    <restart claude>

    <claude is now aware it can do Xtool>

    • By whoknowsidont 2025-11-172:022 reply

      >This effect is _significantly_ stronger than putting info about available API/cli into CLAUDE.md.

      No it's not.

      Honestly this conversation is extremely weird to me because somehow people are gravely misunderstanding what MCP even purports to do, let alone what it actually CAN do in the most ideal situation.

      It is a protocol and while the merits of that protocol is certainly under active discussion it's irrelevant because you keep adding qualities about the protocol that it cannot deliver on.

      Just same facts to help steer this conversation correctly, and maybe help your understanding on what is actually going:

      * All LLM's/major models have function & tool calling built in.

      * Your LLMs/models do not have any knowledge on MCP, nor have they been trained on it.

      * MCP exists, at least the claim, is to help standardize the LIFECYCLE of the tool call.

      * MCP does not augment or enhance the ability of LLM's in any form.

      * MCP does not allow you to extend agents. That's an implicit feature.

      * If you have access to "X" (using your example), you don't need anything that obeys the MCP standard.

      MCP at best is for developers and tool developers. Your model does not need an MCP server or client or anything else MCP related to do what is already been trained to do.

      >I would personally prefer some other method but having a way to make agents extensible is extremely useful.

      They already are. MCP does not help with this.

      • By cjonas 2025-11-172:581 reply

        This response is spot on. People seem very confused about what MCP actually is. It's just a standard way to provide an LLM with tools. And even how that happens is up to the agent implementation. There are some other less common features, but the core is just about providing tool definitions and handling the tool_call. Useful but basically just OpenAPI for LLM

        • By anon84873628 2025-11-182:04

          I think people are really underappreciating the "OpenAPI for LLM" part. The hype forced a lot of different SaaS products and vendors of all stripes to actually follow a standard and think somewhat critically about the usability of what they expose.

      • By smallnamespace 2025-11-173:021 reply

        Three facts to consider:

        1. CLAUDE.md is not part of the system prompt

        2. The Claude Code system prompt almost certainly gives directions about how to deal with MCP tools, and may also include the list of tools

        3. Instruction adherence is higher when the instructions are placed in the system prompt

        If you put these three facts together then it’s quite likely that Claude Code usage of a particular tool (in the generic sense) is higher as an MCP server than as a CLI command.

        But why let this be a limitation? Make an MCP server that calls your bash commands. Claude Code will happily vibe code this for you, if you don’t switch to a coding tool that gives better direct control of your system prompt.

        • By whoknowsidont 2025-11-173:35

          >is higher as an MCP server than as a CLI command.

          What do you mean by "higher"?

    • By throwaway314155 2025-11-1623:431 reply

      1.) Awareness doesn’t mean they will use it. And in practice they often don’t use them.

      2.) “ unlike cli tools or APIs you don't have to constantly remind it what MCPs it has available” - this doesn’t match my experience. In fact, bash commands are substantially more discoverable.

      3.) Again, this doesn’t match my experience and the major providers recommend including available MCP tools in system prompts/CLAUDE.md/whatever.

      4.) Can’t speak to this as it’s not part of my workflow for the previous reasons.

      The only useful MCP for me is Playwright for front end work.

      • By upghost 2025-11-1623:491 reply

        Chrome Devtools is similarly an extremely high value MCP for me.

        I would agree that if you don't find they add discoverability then MCPs would have no value for you and be worse than cli tools. It sounds like we have had very opposite experiences here.

        • By throwaway314155 2025-11-171:001 reply

          Interesting. Perhaps it comes down to which platforms we're working on. I don't want to be outright dismissive of it. My primary platform is Claude Code. Are you working with another driver e.g. OpenAI Codex?

          • By upghost 2025-11-2111:04

            No, and its ok to be dismissive of it. I'm just giving an experience report.

            Actually my primary value is emacs integration with claude.

            I have an mcp with one function ( as_user_eval ) which allows it to execute arbitrary s-expressions against the portal package for emacs.

            I use this often with custom slash commands, i.e., `/read-emacs`, which instructs claude to use that mcp to pull the context from multiple pseudoregions in to the context window (along with filenames and line numbers). This saves me from having to copy paste all of that.

            I understand what the others are saying but the using the portal to talk to a running emacs client I don't find to be particularly "discoverable" on the cli.

            I can say things like, "show me in emacs the test that failed", or, "highlight the lines you are talking about", or, "interactively remap my keybindings to do X", or, "take me to the info page that covers this topic".

            This, paired with chrome devtools and playwright, had been a real productivity booster for me, and is quite fun.

            I use voice dictation for this so it feels like I'm in Star Trek :)

            I'm sure in 10 minutes we will be onto the next version of MCP... skills, ACP, Tools, whatever.

            But this extensibility/discoverability for me has been nice. I make no stronger claims than that about "what it is for" or "what is should be", as I am a simple hacker with simple needs.

    • By paulddraper 2025-11-172:121 reply

      MCP is simply a standardized RPC protocol for LLMs.

      That's it.

      The value is in all the usual features of standardization -- plug-and-play, observability, pass-through modifications, etc.

      • By whoknowsidont 2025-11-174:341 reply

        >observability

        Which MCP does the opposite of. It hides information.

        • By lsaferite 2025-11-1716:071 reply

          How so? The protocol doesn't obfuscate things. Your agent can easily expose the entire MCP conversation, but generally just exposes the call and response. This is no different than any other method of providing a tool for the LLM to call.

          You have some weird bone to pick with MCP which is making you irrationally unreceptive to any good-faith attempt to help you understand.

          If you want to expose tools to the LLM you have to provide a tool definition to the LLM for each tool and you have to map the LLM's tool calls into the agent executing the tools and returning the results. That's universal for all agent-side tools.

          The whole purpose behind MCP was to provide a low-impedance standard where some set of tools could be plugged into an existing agent with no pre-knowledge and all the needed metadata was provided to facilitate linking the tools to the agent. The initial version was clearly focused on local agents running local tools over stdio. The idea of remote tools was clearly an afterthought if you read the specification.

          If you want your agent to speak OpenAPI, you are *more* than welcome to make it do so. It'll probably be fine if it's a well-specified API. The context issues won't go away, I guarantee you. OpenAPI specs for APIs with lots of endpoint will result in large tool definitions for the LLM, just like they do with MCP.

          A core issue I see with MCP, as someone using it every day, is that most MCP Server developers clearly are missing the point and simply using MCP as a thin translation layer over some existing APIs. The biggest value with MCP is when you realize that an MCP Server should be a *curated* experience for the LLM to interact with and the output should be purposefully designed for the LLM, not just a raw data dump from an API endpoint. Sure, some calls are more like raw data dumps and should have minimal curation, but many other MCP tools should be more like what the OP of this post is doing. The OP is defining a local multi-step workflow where steps feed into other steps and *don't* need LLM mediation. That should be a *single* MCP Server Tool. They could wrap the local bash scripts up into a simple single tool stdio MCP Server and now that tool is easily portable across any agent that speaks MCP, even if the agent doesn't have the ability to directly run local CLI commands.

          Anyway, maybe take a breath and be objective about what MCP is and is not meant to do and disconnect what MCP is from how people are *currently* using (and frequently misusing) MCP.

          • By whoknowsidont 2025-11-1716:301 reply

            Probably a good read for you to start with: https://raz.sh/blog/2025-05-02_a_critical_look_at_mcp

            There are tons of articles detailing the problems if you are genuinely interested.

            Notice you couldn't technically point to anything to support your statements, but instead had to revert to religious zealotry and apologetics -- which has no place on this forum.

            >be objective about what MCP is and is not meant to do and disconnect what MCP is from how people are currently using (and frequently misusing) MCP.

            Please re-read what you wrote.

            You wrote all of that just to counter your own stated position, because I think at some fundamental level you realize how non-sense it is.

            • By lsaferite 2025-11-1717:121 reply

              To get this out of the way, you are an unpleasant person, but that doesn't mean you should be ignored though, so I'll reply.

              > you couldn't technically point to anything to support your statements, but instead had to revert to religious zealotry and apologetics

              > You wrote all of that just to counter your own stated position, because I think at some fundamental level you realize how non-sense it is.

              You need to be specific and not make a blanket assertions like that if you want and honest dialog.

              I take particular offense at you claiming "religious zealotry". Nothing in my post is even remotely definable as such. Yes, I use MCP, I also recognize when it's the right tool and when it's not. I don't think MCP is the solution to all problems. I also willingly acknowledge that other tools can fill the same gap. If anyone is being a religious zealot here, it's you and your crusade against MCP.

              With your lack of specificity, it's hard to formulate a proper response to whatever you see as lacking in references. I would point out that I haven't see one link in all of your railing against MCP until this very response.

              So, let's look at your link.

              - I agree that websockets would have been a better choice than SSE+HTTP and StreamableHTTP. Auth for WS is a little bit of a pain from the browser, but it's feasible with some common conventions. - I agree with their characterization of "web seems to be a thing we probably should support" (pretty sure I called that out in my post already... - Their "kind of breaks the Unix/Linux piping paradigm" is laughable though. MCP is hardly the first or only thing to wire a 'server' to and application via stdin/stdout chaining and it's *very* much in the spirit of UNIX (IMHO, as someone working with UNIX systems for the last 30+ years) - Again, I fully agree that the current HTTP transports are... lacking and could use a better solution. - Rant about python aside (I agree BTW), well, they are just ranting actually. Yes, the documentation could use some help. Yes, the wasn't an official Go SDK until recently. - Given this was written a while ago, it's not worth addressing the callous on SSE+HTTP beyond saying, 100% it was a bad design that appears to have been tacked on at the last minute. - The observations about StreamableHTTP are mostly valid. They get a few points wrong, but the essence is right. - Their security concerns are the same ones you'd have with any API, so I'm not sure how this is unique to MCP. - Auth is a bit of a sore subject for me as well. MCP doesn't have an ergonomic workflow for multi-tenant sets and in-band oauth credential management. Again thoug, I don't disagree with the essence of their point.

              After meandering they land on "just use stdio and websockets". So the whole rant is around the protocol transport.I agree the transport protocols need some TLC, but you *can* work with them now and new transports are something that's being worked on, even a WS transport.

              None of that post talks about the actual protocol behind MCP, how it's succeeding/failing at filling the needs it's meant to address, or any real viable alternative for a standard for linking tools to agents.

              If you feel like calling out specific point you feel I should back up with references, I can likely provide them. As with any post, much of the information is synthesized from a lot of places so things like the assertion that remote servers were clearly an afterthought is purely from my reading of the spec and the remote transports code.

    • By badlogic 2025-11-170:09

      Also not disagreeing with your argument. Just want to point out that you can achieve the same by putting minimal info about your CLI tools in your global or project specific CLAUDE.md.

      The only downside here is that it's more work than `claude mcp add x -- npx x@latest`. But you get composability in return, as well as the intermediate tool outputs not having to pass through the model's context.

    • By redhale 2025-11-171:501 reply

      > 3. This effect is _significantly_ stronger than putting info about available API/cli into CLAUDE.md.

      What? Why?

      > unlike cli tools or APIs you don't have to constantly remind it what MCPs it has available

      I think I'm missing something, because I thought this is what MCP does, literally. It just injects the instructions about what tools it has and how to use them into the context window. With MCP it just does it for you rather than you having to add a bit to your CLAUDE.md. What am I misunderstanding?

      • By cstrahan 2025-11-1720:13

        You are correct.

        I think many here have no idea what exactly MCP is, and think it's some sort of magic sauce that transcends how LLMs usually work.

            “But Brawndo has what plants crave! It's got electrolytes! '...Okay - what are electrolytes? Do you know? Yeah. It's what they use to make Brawndo.' But why do they use them in Brawndo? What do they do?''They're part of what plants crave.'But why do plants crave them?'Because plants crave Brawndo, and Brawndo has electrolytes.”
            ― Idiocracy Movie

  • By nestorD 2025-11-1623:166 reply

    So far I have seen two genuinely good arguments for the use of MCPs:

    * They can encapsulate (API) credentials, keeping those out of reach of the model,

    * Contrary to APIs, they can change their interface whenever they want and with little consequences.

    • By the_mitsuhiko 2025-11-1623:441 reply

      > * Contrary to APIs, they can change their interface whenever they want and with little consequences.

      I already made this argument before, but that's not entirely right. I understand that this is how everybody is doing it right now, but that in itself cause issues for more advanced harnesses. I have one that exposes MCP tools as function calls in code, and it encourages the agent to materialize composed MCP calls into scripts on the file system.

      If the MCP server decides to change the tools, those scripts break. That is is also similar issue for stuff like Vercel is advocating for [1].

      [1]: https://vercel.com/blog/generate-static-ai-sdk-tools-from-mc...

      • By lsaferite 2025-11-1716:09

        Wouldn't the answer to this be to have the agent generate a new materialized workflow though? You already presumably have automated the agent's ability to create these workflows based off some prompting and a set of MCP Servers.

    • By rsanheim 2025-11-172:561 reply

      But …you have to give the MCP the creds somehow. Maybe it’s via a file on disk (bad), maybe via an env var (less bad). Maybe you do it via your password CLI that you biometricly auth to, which involves a timeout of some sort for security, but that often means you can’t leave an agent unattended.

      In any case, how is any of this better than a CLI? CLIs have the same access models and tradeoffs, and a persistent agent will plumb the depths of your file system and environment to find a token to do a thing if your prompt was “do a thing, use tool/mcp/cli”.

      So where is this encapsulation benefit?

      • By tuananh 2025-11-173:37

        mcp is easy to self-host. model? a little less so.

    • By cstrahan 2025-11-1720:21

      You're not wrong, but I figured I'd point out the cons / alternatives:

      > They can encapsulate (API) credentials, keeping those out of reach of the model

      An alternative to MCP, which would still provide this: code (as suggested in https://www.anthropic.com/engineering/code-execution-with-mc... and https://blog.cloudflare.com/code-mode/).

      Put the creds in a file, or secret manager of some sort, and let the LLM write code to read and use the creds. The downside is that you'd need to review the code to make sure that it isn't printing (or otherwise moving) the credentials, but then again you should probably be reviewing what the LLM is doing anyway.

      * Contrary to APIs, they can change their interface whenever they want and with little consequences.

      The upside is as stated, but the downside is that you're always polluting the context window with MCP tool descriptions.

    • By tptacek 2025-11-170:501 reply

      What's the alternative design where the model has access to API credentials?

      • By baby_souffle 2025-11-171:11

        > What's the alternative design where the model has access to API credentials?

        All sorts of ways this can happen but it usually boils down to leaving them on disk or in an environment variable in the repo/dir(s) where the agent is operating in.

    • By moneywoes 2025-11-171:02

      what about things like rate limiting, how are those implemented, any Goodreads

    • By zombiwoof 2025-11-1623:33

      [dead]

HackerNews