<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged mcp</title>
<link>https://coderlegion.com/tag/mcp</link>
<description>Powered by Question2Answer</description>
<item>
<title>SAP's CTO Says Building the Agent Is Now the Easy Part</title>
<link>https://coderlegion.com/32733/saps-cto-says-building-the-agent-is-now-the-easy-part</link>
<description>&lt;p&gt;Ask a developer how long it takes to build a working AI agent today, and the answer is often hours, not weeks. Ask how long it takes to get that agent approved, connected to production data, and trusted by the business, and the answer gets a lot less certain.&lt;/p&gt;
&lt;p&gt;SAP CTO Philipp Herzig made that point bluntly during a virtual media Q&amp;amp;A at SAP TechEd 2026 in Berlin on Tuesday. &quot;Building is, quite frankly, the most unimportant part these days, because you can do it so quickly,&quot; he said. The harder questions come before and after: what to build, whether to deploy it, which agents get access to core systems, and whether the agent delivers the value it promised.&lt;/p&gt;
&lt;p&gt;That framing explains most of what SAP announced this week. The new developer tools are less about writing agents and more about everything around them.&lt;/p&gt;
&lt;p&gt;Start with Joule Studio, SAP's AI-first environment for building and extending agents. The Joule Studio CLI can now configure Model Context Protocol (MCP) connections, development skills, and authorizations in one step. When a developer opens the project in their own IDE, business and product requirements are already there as structured project files. SAP says the goal is to let developers spend their time on agent logic instead of setup. General availability is rolling out in phases.&lt;/p&gt;
&lt;p&gt;Testing got attention, too. Joule Studio adds a built-in sandbox where teams can run test queries, inspect traces, and use auto-generated unit tests before an agent reaches production. Offline evaluations, planned for late Q4 2026, will check accuracy, agent-to-agent (A2A) call correctness, and resistance to prompt injection against auto-generated scenarios. Changes to prompts, models, or data sources can be tracked, approved, and rolled back. That gives teams an audit trail when something breaks.&lt;/p&gt;
&lt;p&gt;Then there's governance at the traffic level. SAP Enterprise AI Gateway, planned for Q1 2027, will put MCP, API, A2A, and LLM traffic under one control plane. It handles authentication, policy enforcement, routing, monitoring, usage tracking, and auditing. For developers, it includes an MCP developer hub for discovering and subscribing to MCP servers from any provider and reusing existing APIs and integration flows as agent-ready tools.&lt;/p&gt;
&lt;p&gt;Herzig explained why that control point matters. &quot;You don't want every agent out there to just arbitrarily talk to the SAP system and get the data out, or write something back into the system,&quot; he said. In SAP's model, an agent is registered in the SAP AI Agent Hub, reviewed against rules such as the EU AI Act, and verified. Only verified agents can run against the gateway. After deployment, SAP Signavio's agent mining compares what the agent actually delivers with what it was expected to deliver.&lt;/p&gt;
&lt;p&gt;The other theme was cost. Herzig said customers worry about &quot;the huge token bill,&quot; and he blamed much of it on naive use of LLMs. SAP's pitch is that business context from SAP Knowledge Graph cuts the number of tokens an agent needs. &quot;The question is always how can we avoid tokens in the first place,&quot; he said.&lt;/p&gt;
&lt;p&gt;He pointed to a comparison from the keynote. According to Herzig, the first iteration of the same agent took roughly 30 hours to build with Claude Code and two hours in Joule Studio, at about half the cost. He also acknowledged that developers can reach the same outcome with Claude Code. This is SAP's own benchmark on one example, so treat it as a claim to test, not a settled result.&lt;/p&gt;
&lt;p&gt;Data access is part of the same story. SAP Business Data Cloud is adding a lakehouse built on Dremio, with native Apache Iceberg support, an Apache Polaris-based catalog, and a distributed SQL engine that queries data without copying it. General availability is planned for Q1 2027. A new Ontology Manager, planned for beta in November, will let developers curate domain-specific business context and reuse it across agents.&lt;/p&gt;
&lt;p&gt;SAP also expanded its tabular AI models for structured data. SAP-RPT-TS handles time-series forecasting and is available now through SAP HANA Cloud or SAP AI Core. SAP-RPT-Decisions, aimed at approvals and routing decisions, is planned for Q4 2026. SAP-RPT-2, planned for Q1 2027, adds anomaly detection, embeddings, and multi-table processing. SAP and HPE also plan to run SAP-RPT aboard the International Space Station to triage anomalies and reconstruct missing sensor data without sending it back to Earth.&lt;/p&gt;
&lt;p&gt;Some of this is usable today. SAP Integration Suite now supports native Git operations on integration flows, including comparing flows and resolving conflicts. The Joule Studio developer certification is free through Dec. 31. And for select customers, deploying and running custom agents on the SAP-managed Joule Studio runtime is free through December, with design-time tooling free under fair-use limits.&lt;/p&gt;
&lt;p&gt;Herzig was clear that SAP doesn't expect to own every agent experience. &quot;We are not saying that we are the center of the universe,&quot; he said. Through A2A and SAP's agent gateway, third-party agents running in tools like Copilot or Claude can call Joule Agents.&lt;/p&gt;
&lt;p&gt;On autonomy, he compared agents to coding assistants. At first, developers approve every command. &quot;And after a while, it's like, why is it bothering me all the time?&quot; he said. Trust builds on simple, repeatable tasks. Regulated, high-risk decisions, such as those in HR, will keep a human in the loop for a while.&lt;/p&gt;
&lt;p&gt;The open questions are practical ones. Much of the lineup won't be generally available until Q4 2026 or Q1 2027. SAP hasn't said what runtime pricing looks like after the free period ends. And the 30-hours-versus-two-hours claim needs testing outside SAP's demo.&lt;/p&gt;
&lt;p&gt;But Herzig's core argument holds up. If an agent can be built in an afternoon, the bottleneck moves to deciding which agents deserve access, proving they work, and keeping the token bill in check. That's where SAP is putting its developer investment.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/32733/saps-cto-says-building-the-agent-is-now-the-easy-part</guid>
<pubDate>Tue, 27 Oct 2026 18:07:47 +0000</pubDate>
</item>
<item>
<title>Agent Browser</title>
<link>https://coderlegion.com/32600/agent-browser</link>
<description>&lt;p&gt;A real Chromium browser exposed as an MCP server, priced per action in USDC on Base via x402: navigate $0.005, extract $0.005, accessibility snapshot $0.005, act $0.01, screenshot $0.02, close free. No account, no API key, no subscription. Runs free self-hosted over stdio, or pay per action on the hosted endpoint. Every settled action lands in a public receipts log. Live in the Official MCP Registry as com.scriptmasterlabs/agent-browser; first payment settled on Base (block 53135025). By Script Master Labs LLC, a Service-Disabled Veteran-Owned Small Business.&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/32600/agent-browser</guid>
<pubDate>Tue, 27 Oct 2026 00:28:03 +0000</pubDate>
</item>
<item>
<title>URL-to-Markdown API</title>
<link>https://coderlegion.com/32349/url-to-markdown-api</link>
<description>&lt;p&gt;URL-to-Markdown API turns any web page into clean Markdown an AI agent can actually use — one call, $0.001 per read, paid per call over x402 in USDC, with a real settlement receipt for every read. It is the proven job in the ScriptMasterLabs catalog: live on Product Hunt since October 17, 2026, settling real reads today. Built by ScriptMasterLabs, a Service-Disabled Veteran-Owned Small Business.&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/32349/url-to-markdown-api</guid>
<pubDate>Sun, 25 Oct 2026 09:03:19 +0000</pubDate>
</item>
<item>
<title>Triple-Trigger — Live Schwab Scanner</title>
<link>https://coderlegion.com/32346/triple-trigger-live-schwab-scanner</link>
<description>&lt;p&gt;Triple-Trigger is a live Schwab-data scanner that stages three triggers — liquidity sweeps, VWAP reclaims, and unusual options activity — into WATCH and VERDICT signals, each with a public track record. It runs on dynamic 5-minute scan cycles, posts WATCH/VERDICT alerts to Discord, and every wallet gets its first 3 VERDICTs free. First live scheduler cycles run Monday, October 26. Built by ScriptMasterLabs, a Service-Disabled Veteran-Owned Small Business. No signals are backfilled and no outcome is promised — the track record is the pitch.&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/32346/triple-trigger-live-schwab-scanner</guid>
<pubDate>Sun, 25 Oct 2026 06:05:28 +0000</pubDate>
</item>
<item>
<title>SqueezeOS — Federal, RWA &amp; Finance MCP</title>
<link>https://coderlegion.com/32345/squeezeos-federal-rwa-finance-mcp</link>
<description>&lt;p&gt;SqueezeOS is ScriptMasterLabs' MCP server for federal, real-world-asset and finance data — built so AI agents can pull structured market and federal data through one MCP surface instead of stitching together raw APIs. It is live and public on AWS Marketplace (enterprise offer, 10-day free trial) and is in review for the Claude connector directory on its read-only surface. Built and run by ScriptMasterLabs, a Service-Disabled Veteran-Owned Small Business. Proof over pitch: the listings are live and checkable today, not a roadmap.&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/32345/squeezeos-federal-rwa-finance-mcp</guid>
<pubDate>Sun, 25 Oct 2026 05:37:25 +0000</pubDate>
</item>
<item>
<title>MNEMOS by ScriptMasterLabs</title>
<link>https://coderlegion.com/32343/mnemos-by-scriptmasterlabs</link>
<description>&lt;p&gt;MNEMOS is the memory and judgment layer for AI agents: an MCP server and x402 API that gives agents decisions, options analysis, arbitrage scans, gas recommendations, and compliance screens — each call priced in micro-USDC and settled on Base with a receipt.&lt;/p&gt;
&lt;p&gt;Live routes include /decisions ($0.001), /options ($0.003), /v1/gas/recommend ($0.001), /v1/arb/scan ($0.002), /v1/compliance/screen ($0.005), and /v1/options/scan ($0.01). It settled through both the CDP and PayAI facilitators on its first day and is listed in the official MCP Registry with 8 tools.&lt;/p&gt;
&lt;p&gt;Built by Script Master Labs LLC, a service-disabled veteran-owned small business.&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/32343/mnemos-by-scriptmasterlabs</guid>
<pubDate>Sat, 24 Oct 2026 20:29:51 +0000</pubDate>
</item>
<item>
<title>Verdict Protocol by ScriptMasterLabs</title>
<link>https://coderlegion.com/32342/verdict-protocol-by-scriptmasterlabs</link>
<description>&lt;p&gt;Verdict Protocol is a decision gate for agent payments. Before money settles, a capsule of the proposed payment is scored by five specialized Jev jurors under a non-overridable constitution; the sealed decision comes back as a signed, verifiable receipt.&lt;/p&gt;
&lt;p&gt;Live on Base via x402: POST /decide costs $0.25 and POST /seal costs $0.01, with a public OpenAPI spec and an agent card at verdict.scriptmasterlabs.com. Settlements verified on-chain; an API-key door is available for operators.&lt;/p&gt;
&lt;p&gt;Built by Script Master Labs LLC, a service-disabled veteran-owned small business. Jev chooses. Code decides.&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/32342/verdict-protocol-by-scriptmasterlabs</guid>
<pubDate>Sat, 24 Oct 2026 20:08:43 +0000</pubDate>
</item>
<item>
<title>OMNIGATE — One Gate for Agent Payments</title>
<link>https://coderlegion.com/32341/omnigate-one-gate-for-agent-payments</link>
<description>&lt;p&gt;OMNIGATE is the settlement gate for the ScriptMasterLabs fleet: one x402 front door in front of 44 paid agent services — market data, risk models, research, citation checks, and a 5-juror decision engine.&lt;/p&gt;
&lt;p&gt;Every payment through the gate is decision-scored against owner-set thresholds before it settles (0.80 and up pays, 0.50–0.79 asks the owner, below 0.50 escalates), settles on Base in USDC directly from buyer to seller — the gate never holds funds — and returns a signed receipt. Replaying a payment hash returns the stored result instead of charging twice.&lt;/p&gt;
&lt;p&gt;Live today, not a demo: 42 of its 44 routes are listed in the CDP Bazaar, and live status is public at the website URL above. Built by Script Master Labs LLC, a service-disabled veteran-owned small business.&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/32341/omnigate-one-gate-for-agent-payments</guid>
<pubDate>Sat, 24 Oct 2026 20:05:54 +0000</pubDate>
</item>
<item>
<title>Bridging Model Context Protocol (MCP) to Browser Agents via W3C WebMCP (document.modelContext)</title>
<link>https://coderlegion.com/32204/bridging-model-context-protocol-mcp-browser-agents-via-w3c-webmcp-document-modelcontext</link>
<description>&lt;p&gt;As AI agents move from local developer runtimes (like Claude Desktop and Cursor) into browser environments, developers face a major integration challenge: how to expose structured backend tools to client-side agents securely and without fragile DOM scraping.&lt;/p&gt;
&lt;p&gt;At SEOSiri, we solved this by implementing the W3C WebMCP specification (document.modelContext). Our central developer portal dynamically registers our entire autonomous tool catalog on boot, proxying execution requests seamlessly through secure, stateless Cloudflare Edge Gateways.&lt;/p&gt;
&lt;p&gt;Key Technical Implementation Highlights:&lt;/p&gt;
&lt;p&gt;Dynamic Universal Registry: Automatically loops through master component registers to bind server schemas into browser runtimes.&lt;br&gt;
Edge Proxying &amp;amp; Security: Ensures zero secret exposure by keeping backend encryption keys locked inside Cloudflare Worker environment variables while marshaling public JSON-RPC requests across HTTPS.&lt;br&gt;
Namespace Segregation: Explicitly namespaced tool identifiers prevent collision with browser default diagnostic suites.&lt;br&gt;
Native DevTools Debugging: Streamlines inspection and verification via the Chrome DevTools WebMCP application panel.&lt;/p&gt;
&lt;p&gt;Read the Full Engineering Walkthrough:&lt;br&gt;
🔗 &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.seosiri.com/2026/10/webmcp-chrome-mcp-tools-guide.html&quot;&gt;https://www.seosiri.com/2026/10/webmcp-chrome-mcp-tools-guide.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;coderlegion-webdev-aiagents-mcp-typescript-architecture-edgecomputing&quot;&gt;coderlegion #webdev #aiagents #mcp #typescript #architecture #edgecomputing&lt;/h2&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/32204/bridging-model-context-protocol-mcp-browser-agents-via-w3c-webmcp-document-modelcontext</guid>
<pubDate>Fri, 23 Oct 2026 16:11:38 +0000</pubDate>
</item>
<item>
<title>AAIF Hits 10 Projects. Its CTO on What to Adopt Now and the Security Gaps Left Open</title>
<link>https://coderlegion.com/32119/aaif-hits-10-projects-its-cto-on-what-to-adopt-now-and-the-security-gaps-left-open</link>
<description>&lt;p&gt;The Agentic AI Foundation (AAIF) launched in December 2025 with three projects: the Model Context Protocol (MCP), goose, and AGENTS.md. Less than a year later, it hosts 10.&lt;/p&gt;
&lt;p&gt;On October 22, at AGNTCon + MCPCon North America in San Jose, AAIF added four more. Anthropic contributed Agent Skills. OpenAI contributed Open Responses. Hugging Face contributed OpenEnv. Alibaba contributed OpenSandbox. The foundation also announced it has passed 300 member organizations.&lt;/p&gt;
&lt;p&gt;That's a lot of new pieces in a short time. So I asked Manik Surtani, AAIF's CTO and co-founder, what vendor-neutral governance means for developers who build on these projects. He worked with all four companies to bring the projects in.&lt;/p&gt;
&lt;p&gt;His answers are practical. Nothing changes in how you use MCP today. Don't wait for a reference stack. Pick a sandbox and a gateway now. And the two biggest security gaps in the agentic stack, agent identity and attestation, aren't covered by any AAIF project yet.&lt;/p&gt;
&lt;h3 id=&quot;the-four-new-projects-at-a-glance&quot;&gt;The four new projects at a glance&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Agent Skills (Anthropic):&lt;/strong&gt; An open format for packaging instructions, scripts, and resources so agents can load specialized know-how on demand, across products.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open Responses (OpenAI):&lt;/strong&gt; An open spec, based on the OpenAI Responses API, for describing LLM requests and outputs once and running them across model providers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenEnv (Hugging Face):&lt;/strong&gt; A framework and community hub for building and sharing reinforcement learning environments. Each environment runs as a containerized service that exposes MCP and the Gym training interface.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenSandbox (Alibaba):&lt;/strong&gt; A general-purpose sandbox platform for coding agents, GUI agents, evaluation, code execution, and RL training, with Docker and Kubernetes runtimes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They join A2A, Agent Router, agentgateway, AGENTS.md, goose, and MCP.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Answers have been edited for length and clarity.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;You worked with four companies to bring these projects in. What did neutral governance need to guarantee before they handed them over? What did each company give up, and what did it keep?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OpenAI and Anthropic helped bootstrap AAIF, so they already knew what good neutral governance looks like and what it means for them.&lt;/p&gt;
&lt;p&gt;Alibaba wanted to be the first non-US project in the foundation, and specifically the first Chinese one. I think that will open the door to more projects coming out of Asia, and I'm excited about that. They didn't need many guarantees either. They have a lot of projects in the CNCF and already see the value. AAIF is part of the Linux Foundation, a sister organization to the CNCF, so they already trusted us.&lt;/p&gt;
&lt;p&gt;Hugging Face is a similar story. The Linux Foundation brand is well known, and that trust made it relatively easy to get everyone on board. The common thread is that these companies already understood and valued vendor-neutral stewardship. The conversation was much shorter than people might expect.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For a developer who has already built on MCP or Agent Skills, what actually changes now that the project sits at AAIF?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Day to day, nothing changes. Using these standards stays the same.&lt;/p&gt;
&lt;p&gt;What changes is how the projects evolve. Spec changes and improvements will happen with a lot more transparency, with much more of that work in the open. Each project will also have a more structured maintainer group. That gives others a real path to maintainership. The more you participate, contribute, and show commitment, the better your chance of becoming a maintainer and helping steer the project.&lt;/p&gt;
&lt;p&gt;So for existing users, the practical effect is stability today and a more open, more broadly governed process for how the specs develop tomorrow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open Responses is based on OpenAI's Responses API. How do you keep a spec neutral when it started as one vendor's API?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It comes down to the same mechanism. Competing model providers can now join the project as contributors and help shape the API.&lt;/p&gt;
&lt;p&gt;It's also already not just OpenAI's API. Open Responses has been an open source project for a while. More than one company has adopted it, and others are contributing to it. So neutrality isn't hypothetical. A competing provider's path to influence is the same as anyone else's: show up, contribute, build trust, and earn a seat in steering the direction.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;These projects touch each other. How is AAIF making sure the 10 projects fit together? Is there a reference stack developers can follow?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;People always ask me about a reference stack, and I tend to push back. We started out thinking there should be one. But the more I think about it, the more I believe any reference stack we build today will be out of date tomorrow. The space is changing too fast. I don't want to use one as a roadmap to hunt for missing pieces.&lt;/p&gt;
&lt;p&gt;Right now, I think of it as a giant experiment. Everyone is assembling these pieces in different ways, and it's great to see what works and what doesn't. When people deploy something in production, that becomes the reference for that pattern. Other people assemble the same building blocks differently, which is just as interesting.&lt;/p&gt;
&lt;p&gt;This isn't cloud, a mature technology with a fairly static, well-understood reference stack. This space is still new and experimental.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If a developer starts a new agent project today, which AAIF projects should they adopt first? Which should they watch?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;MCP and A2A are our two most mature projects. Open Responses is now very mature as well.&lt;/p&gt;
&lt;p&gt;OpenSandbox is still pretty nascent, and many sandboxing technologies with different approaches are coming out. It's worth watching. But you do need a sandbox. Pick one and start moving. Running without any sandbox is dangerous, and you shouldn't do it.&lt;/p&gt;
&lt;p&gt;Routers and gateways sit in the middle. They're an important part of the ecosystem, and the space will keep evolving, so grab one to get started.&lt;/p&gt;
&lt;p&gt;The good news is that switching is relatively easy in the agentic world. With agent-driven development, you can migrate from one tool to another without much hassle. In the old days of handcrafting everything, migration was far more expensive. So pick one, and make sure there's a gateway somewhere in between. That gives you the option to migrate models and other important pieces later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where are the biggest security gaps in the agentic stack right now? Which ones does no AAIF project cover yet?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The biggest gaps are around identity and authentication. There are nascent standards, but nothing we've adopted yet. There are plenty of commercial products for agent identity worth looking at. Still, I don't think anyone has cracked that nut. We have a working group going deep into the space, and we want to see what comes out of it.&lt;/p&gt;
&lt;p&gt;The other big gap is attestation: proof that an agent actually did what you asked and didn't go off the rails and do something else. There are a lot of interesting proposals on the table, and we might soon spin up a working group there as well.&lt;/p&gt;
&lt;p&gt;Neither area is covered by an AAIF project today. Both are worth watching closely.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OpenEnv brings AAIF into reinforcement learning. Why do training and evaluation belong in the same foundation as runtime protocols? What does it mean for teams that never train a model?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Having a number of projects doesn't mean everyone needs to adopt everything in one stack. Some pieces matter more to certain engineers, companies, or products, and less to others.&lt;/p&gt;
&lt;p&gt;OpenEnv is a good example. It appeals strongly to a certain class of companies and products, but not to everyone. If your team never trains a model, nothing obliges you to touch it. Adopt the protocols and runtime pieces that fit your needs and ignore the rest. AAIF is a home for the building blocks of the agentic ecosystem. Each team takes what's relevant to what it's building.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AAIF passed 300 members in under a year. How does an individual developer or a small team get a real say in a project's roadmap?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Like many open source projects, it's very meritocratic. Get involved, roll up your sleeves, and start working on the project. Contribute ideas, conversations, or code. That's how you earn credibility with the project, and the more you have, the more you can shape it.&lt;/p&gt;
&lt;p&gt;There's no fixed timeline. It depends on how much you put in. The path is the same for an individual developer as for a large company: participate, show what you're good at, and demonstrate commitment. Over time, you earn the trust to influence the project's direction and potentially become a maintainer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vendors ship new agent features every few weeks. Consensus takes time. How do you balance speed with neutral governance?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One of our main tools is the Sandbox lifecycle stage. &lt;em&gt;(Editor's note: this is a project maturity level, not the OpenSandbox project.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When we started the foundation, projects could come in at two levels. Impact meant broad, industry-wide adoption, a project that was already a pillar of the industry. Growth was one step before that: production usage and adoption, but not yet ubiquitous.&lt;/p&gt;
&lt;p&gt;Even that wasn't enough in a space moving this fast. We needed something earlier for projects with little production usage but lots of developer adoption, momentum, and excitement. Sandbox lets us bring those projects in early without investing too much, so we can watch, learn, and help shape the space.&lt;/p&gt;
&lt;p&gt;I think of it as early-stage investing. You make early bets. Some become big and important. Most won't, and that's okay.&lt;/p&gt;
&lt;p&gt;As for a concrete example of governance speeding up or slowing down a project, I think it's still too early to point to one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What should developers expect from AAIF over the next 12 months?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A lot more projects, many more member companies, and a number of AGNTCon + MCPCon events. We have a big lineup planned for next year, from local grassroots events to large conferences like this one. For updates, follow along at &lt;a rel=&quot;nofollow&quot; href=&quot;https://aaif.io&quot;&gt;aaif.io&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-developers-should-take-from-this&quot;&gt;What developers should take from this&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nothing breaks.&lt;/strong&gt; If you build on MCP, Agent Skills, or Open Responses today, your code doesn't change. What changes is who gets a say in what comes next.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Don't wait for a blueprint.&lt;/strong&gt; AAIF won't publish a reference stack any time soon. Production deployments are the reference.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sandbox and gateway now.&lt;/strong&gt; Surtani was clear: running agents without a sandbox is dangerous. A gateway in the middle keeps your options open on models and tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watch identity and attestation.&lt;/strong&gt; These are the two biggest open security gaps, and no AAIF project covers them yet. If you're building agents that act on real systems, that's where your own controls need to be strongest.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Influence is earned.&lt;/strong&gt; Contributing is the path to a say in the roadmap, for individuals and large vendors alike.&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/32119/aaif-hits-10-projects-its-cto-on-what-to-adopt-now-and-the-security-gaps-left-open</guid>
<pubDate>Fri, 23 Oct 2026 12:00:00 +0000</pubDate>
</item>
<item>
<title>WebMCP: Letting Browser Agents Use Your Site's Own Tools</title>
<link>https://coderlegion.com/32138/webmcp-letting-browser-agents-use-your-sites-own-tools</link>
<description>&lt;p&gt;WebMCP is a proposed web standard that lets a page register its own tools, either JavaScript functions or marked-up HTML forms, which an agent in the visitor's browser can then call instead of feeling its way through buttons and inputs. In October 2026 it's a W3C Community Group draft with a Chrome origin trial, and the API changed during 2026, so many tutorials are already out of date.&lt;/p&gt;
&lt;p&gt;I explain what it is and who's behind it, and summarise its status: an origin trial starting in Chrome 149, a flag for local testing, the move from navigator.modelContext to document.modelContext in May 2026, and early support elsewhere. Anything built now should feature-detect and fail silently.&lt;/p&gt;
&lt;p&gt;The imperative API is registerTool(), with a name, description, input schema, callback and annotations including one that marks consequential actions like booking or paying. The declarative API turns an existing form into a tool with a few attributes. I compare WebMCP with a server-side MCP server: one lives in an open tab with the user's session, the other is a network endpoint any client can call, and Chrome's own guidance suggests using both for different jobs.&lt;/p&gt;
&lt;p&gt;The security section covers HTTPS only, same-origin by default, a person in the loop and prompt injection as the main risk. I include a small business example and an honest list of when not to bother yet.&lt;/p&gt;
&lt;h4 id=&quot;key-takeaways&quot;&gt;Key takeaways&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;WebMCP lets a page expose tools to in-browser agents&lt;/li&gt;
&lt;li&gt;It's an experimental draft with an active Chrome origin trial&lt;/li&gt;
&lt;li&gt;Forms can become tools with a few attributes&lt;/li&gt;
&lt;li&gt;It complements, not replaces, a server-side MCP server&lt;/li&gt;
&lt;li&gt;Mark consequential tools and validate everything server-side&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Related on BuiltToWinWeb: &lt;a rel=&quot;nofollow&quot; href=&quot;https://built2winweb.com/blog/add-mcp-server-to-website/&quot;&gt;adding a server-side MCP server&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Read the full guide on BuiltToWinWeb:&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://built2winweb.com/blog/webmcp-explained/&quot;&gt;&lt;strong&gt;WebMCP explained, with a working example&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A summary by Jacob Campbell of an article first published on built2winweb.com on October 7, 2026.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/32138/webmcp-letting-browser-agents-use-your-sites-own-tools</guid>
<pubDate>Fri, 23 Oct 2026 03:36:01 +0000</pubDate>
</item>
<item>
<title>CyberCartel Pointed Claude and Grok Agents at 400+ Banks. The Stack Looks Like Yours.</title>
<link>https://coderlegion.com/32054/cybercartel-pointed-claude-and-grok-agents-at-400-banks-the-stack-looks-like-yours</link>
<description>&lt;p&gt;A financial crime group active since 2012 just showed developers what their everyday agent stack looks like in the wrong hands.&lt;/p&gt;
&lt;p&gt;New research from Straiker shows how CyberCartel built a multi-agent attack system called CARLIY0S and aimed it at more than 400 banks, payment providers, and other financial organizations across Latin America. The system ran on commercial models, including Anthropic's Claude and xAI's Grok, with Moonshot AI's Kimi in the mix.&lt;/p&gt;
&lt;p&gt;The tools will look familiar. Cursor. MCP servers. API keys in .env files. Playwright. That's the part developers should sit with.&lt;/p&gt;
&lt;h3 id=&quot;how-straiker-got-inside&quot;&gt;How Straiker Got Inside&lt;/h3&gt;
&lt;p&gt;CyberCartel made an operational security mistake. That gave Straiker a snapshot of the group's working environment. The September 24, 2026 snapshot captured the group's stolen-credential database, called &quot;FinancialSoft.&quot; It held 4,493 records, including passwords and API keys.&lt;/p&gt;
&lt;p&gt;Could it have been a decoy? Vinay Pidathala, vice president of AI security research at Straiker, doesn't think so. The team tied the environment to more than 270 pentest reports against real organizations. &quot;The volume and specificity across hundreds of entities is inconsistent with a honeypot,&quot; he said.&lt;/p&gt;
&lt;p&gt;Straiker attributes the work with high confidence to Tr4nsHack Team, which operated under the front name Hexagon Security Labs Mexico. Operator handles in the source code and reports matched known CyberCartel operators.&lt;/p&gt;
&lt;p&gt;The irony: the group's rule files told the models never to output the Tr4nsHack alias. The name showed up in its own reports and code anyway.&lt;/p&gt;
&lt;h3 id=&quot;four-agents-and-an-arbiter&quot;&gt;Four Agents and an Arbiter&lt;/h3&gt;
&lt;p&gt;Here's how the system worked, based on the group's own scripts and configuration. Straiker notes it did not validate the outcome for any individual target.&lt;/p&gt;
&lt;p&gt;A commander, Claude running in Cursor, sets a high-level objective. It delegates through the Anthropic API to four role-based agents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A recon agent maps the target's infrastructure and looks for ways to avoid detection.&lt;/li&gt;
&lt;li&gt;An exploit agent writes the attack code and automation.&lt;/li&gt;
&lt;li&gt;A third agent suggests lateral and unconventional attack paths.&lt;/li&gt;
&lt;li&gt;An arbiter weighs the debate among the other three and returns a single decision.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Five Grok &quot;miners&quot; analyzed the collected data and posted it to the attackers' dashboard.&lt;/p&gt;
&lt;p&gt;Execution ran through a headless browser routed over residential proxies, so traffic looked like it came from domestic Mexican IP addresses. Once the system gained code execution through a target's web admin panel, it dropped the browser for a faster, quieter scripted session. Automated payloads then scanned databases, hunted for credentials and SSH keys, and mapped internal networks.&lt;/p&gt;
&lt;p&gt;Why the debate format? Straiker doesn't know, and it didn't test whether four agents beat one.&lt;/p&gt;
&lt;h3 id=&quot;getting-past-the-guardrails&quot;&gt;Getting Past the Guardrails&lt;/h3&gt;
&lt;p&gt;The operators framed their requests as authorized red-team engagements or academic penetration tests. Straiker calls this dual-use contextual framing.&lt;/p&gt;
&lt;p&gt;It didn't work on every model. Refusals varied inside the same system, and Straiker says it has no visibility into why. When a model refused, the orchestrator fell back to a local file of pre-written attack code, so the operation kept moving.&lt;/p&gt;
&lt;p&gt;So how much did AI actually add? According to Pidathala, all 270+ attack reports were AI-generated. &quot;We did not see evidence of manual efforts,&quot; he said. The local script was a fallback, not the main engine.&lt;/p&gt;
&lt;p&gt;The configuration also listed claude-fable-5. Straiker can't confirm it ever ran. &quot;A configuration entry is not evidence of successful execution,&quot; Pidathala said.&lt;/p&gt;
&lt;h3 id=&quot;what-we-don-t-know&quot;&gt;What We Don't Know&lt;/h3&gt;
&lt;p&gt;Quite a bit. Straiker isn't sharing how many of the 400+ targets were compromised or how much money was lost. It cites responsible disclosure while affected organizations and providers work through the fallout. The 400 figure counts targets, not confirmed breaches.&lt;/p&gt;
&lt;p&gt;According to The Information, Anthropic investigated after Straiker shared its findings and blocked the group's access to Claude. Straiker reported that xAI was notified and is investigating the use of Grok.&lt;/p&gt;
&lt;h3 id=&quot;what-developers-should-take-from-this-1&quot;&gt;What Developers Should Take From This&lt;/h3&gt;
&lt;p&gt;The core lesson is that this tooling is dual-use. &quot;The same agent stack that builds software can run an offensive operation,&quot; Pidathala said.&lt;/p&gt;
&lt;p&gt;That isn't a reason to stop building agents. They do a lot of good work. It's a reason to own what your agents can reach. Whoever builds an agent is responsible for what it does. So is the company that deploys it.&lt;/p&gt;
&lt;p&gt;Straiker's guidance for teams building agents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Test agents against real attack techniques before production.&lt;/strong&gt; Pidathala calls this the single highest-value action a team can take this week.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rotate agent credentials often and scope them tightly.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add observability and guardrails&lt;/strong&gt; to detect and stop abuse at runtime.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Treat .env API keys and MCP server access as high-value assets&lt;/strong&gt; to secure and monitor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last point is easy to skip. An API key in a .env file feels routine. In CARLIY0S, API access is what let one commander direct a team of agents across hundreds of targets.&lt;/p&gt;
&lt;h3 id=&quot;where-this-goes-next&quot;&gt;Where This Goes Next&lt;/h3&gt;
&lt;p&gt;Pidathala expects these operations to grow in sophistication and scale as models get more capable, compute gets cheaper, and attackers build AI skills. Defenders, he said, will need to continuously test their infrastructure and be ready to &quot;detect and respond to AI-powered attacks at machine speed.&quot;&lt;/p&gt;
&lt;p&gt;That's not hype. It's a small team, a familiar toolchain, and more than 400 financial targets. The gap between the agents developers build and the agents attackers build is mostly intent. Security has to cover the rest.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/32054/cybercartel-pointed-claude-and-grok-agents-at-400-banks-the-stack-looks-like-yours</guid>
<pubDate>Thu, 22 Oct 2026 13:30:00 +0000</pubDate>
</item>
<item>
<title>Mapping 32k+ MCP Servers: How we are handling tool discovery without schema drift</title>
<link>https://coderlegion.com/31988/mapping-32k-mcp-servers-how-we-are-handling-tool-discovery-without-schema-drift</link>
<description>&lt;p&gt;Hey devs! 👋&lt;/p&gt;
&lt;p&gt;If you are currently running automated code generation or orchestrating local agent loops inside Claude Code, Cursor, or Windsurf, you've probably noticed how fast legacy REST integrations break down under heavy production prompts.&lt;/p&gt;
&lt;p&gt;The ecosystem is rapidly moving toward the Model Context Protocol (MCP) using JSON-RPC 2.0 transport layers. To map out where this tech is heading, we've indexed and tracked the data footprints of active servers across three main directories:&lt;/p&gt;
&lt;p&gt;• Glama Layer: 22.7k–32.7k live environments tracked via active usage signal telemetry.&lt;br&gt;
• mcp.so Index: 20k+ community schema setups.&lt;br&gt;
• Smithery Layer: 6k–7.3k configurations supporting single-command automated setups.&lt;/p&gt;
&lt;p&gt;We wrote a comprehensive engineering guide breaking down how to securely connect trendy components like GitHub repository hooks, PostgreSQL data layers, and Playwright automation routines without blowing up context limits or leaking environmental tokens.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=16557954759598184536&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Check out our structural layout mapping and read the full technical walkthrough on our main blog:&lt;br&gt;
🔗 &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.seosiri.com/2026/10/mcp-server-registries-guide.html&quot;&gt;https://www.seosiri.com/2026/10/mcp-server-registries-guide.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let's discuss in the comments below: What custom MCP servers are you currently spinning up in your workspace? 🛠️👇&lt;/p&gt;
&lt;h2 id=&quot;softwareengineering-aiagents-modelcontextprotocol-webdev-buildinpublic&quot;&gt;SoftwareEngineering #AIAgents #ModelContextProtocol #WebDev #BuildInPublic&lt;/h2&gt;
</description>
<category>Discussions</category>
<guid isPermaLink="true">https://coderlegion.com/31988/mapping-32k-mcp-servers-how-we-are-handling-tool-discovery-without-schema-drift</guid>
<pubDate>Wed, 21 Oct 2026 14:28:26 +0000</pubDate>
</item>
<item>
<title>MCP Protocol Engineer vs. MCP Tooling Developer: Why &quot;Vibe Coding&quot; Works for One but Fails the Other</title>
<link>https://coderlegion.com/31807/protocol-engineer-mcp-tooling-developer-why-vibe-coding-works-for-one-but-fails-the-other</link>
<description>&lt;p&gt;Hey everyone,&lt;/p&gt;
&lt;p&gt;With the widespread adoption of the Model Context Protocol (MCP) across Claude Code, Cursor, and autonomous agent frameworks, there is a lot of discussion around using AI-assisted workflows (&quot;vibe coding&quot;) to build out agent infrastructure.&lt;/p&gt;
&lt;p&gt;We wrote an in-depth systems analysis dissecting the boundary between foundational protocol engineering and application-layer tooling:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Tooling Developer Layer:&lt;br&gt;
MCP tool authoring is largely declarative (JSON Schema Draft-07, REST/GraphQL fetch wrappers, and response payload formatting). LLMs are exceptionally good at this. An experienced engineer who knows how to tune semantic descriptions (to avoid tool selection hallucinations) and sanitize inputs can build reliable tools with AI assistance in a fraction of the time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Protocol Engineer Layer:&lt;br&gt;
Implementing the underlying protocol (JSON-RPC 2.0 framing, stdio process pipe backpressure, Server-Sent Events, and zero-allocation memory buffers in Rust/Go/C++) requires strict, deterministic systems programming. Probabilistic models frequently introduce subtle multi-threading bugs, unhandled partial reads, and stream deadlocks that only manifest under high concurrent load.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The core conclusion: Vibe coding provides massive velocity when bridging APIs and tools to models, but relying on probabilistic synthesis for low-level protocol primitives introduces dangerous cognitive debt and production instability.&lt;/p&gt;
&lt;p&gt;Full technical write-up with comparison matrix and architecture breakdown:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.seosiri.com/2026/10/mcp-protocol-engineer-vs-tooling-developer-vibe-coding.html&quot;&gt;https://www.seosiri.com/2026/10/mcp-protocol-engineer-vs-tooling-developer-vibe-coding.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Curious to hear how other teams are structuring the boundary between core protocol maintenance and rapid tool authoring in their agent stacks.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31807/protocol-engineer-mcp-tooling-developer-why-vibe-coding-works-for-one-but-fails-the-other</guid>
<pubDate>Tue, 20 Oct 2026 07:23:48 +0000</pubDate>
</item>
<item>
<title>How to Inspect an Agent Skill Before You Adopt It — with n8n and Agentel MCP</title>
<link>https://coderlegion.com/31721/how-to-inspect-an-agent-skill-before-you-adopt-it-with-n8n-and-agentel-mcp</link>
<description>&lt;p&gt;Before giving an Agent a new Skill, what can you actually check?&lt;/p&gt;
&lt;p&gt;A description may sound promising, but it won't tell you everything you need to know. Which version is registered? What permissions are declared? Is there a license? What evidence backs up the listing?&lt;/p&gt;
&lt;p&gt;We built a small, manual n8n workflow to make those details easier to inspect. It's now &lt;a rel=&quot;nofollow&quot; href=&quot;https://n8n.io/workflows/21182-inspect-agentel-mcp-skill-evidence-and-metering-with-the-mcp-client/&quot;&gt;published in the n8n template library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It also checks which Agentel Reader you're using, whether there's enough reading allowance for one detail request, and what the allowance looks like afterward.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No LLM, model API key or AI Agent node is needed.&lt;/strong&gt; This is a regular, deterministic n8n workflow.&lt;/p&gt;
&lt;h3 id=&quot;what-the-workflow-does&quot;&gt;What the workflow does&lt;/h3&gt;
&lt;p&gt;Here's the path:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Run manually → Choose Skill → Connection before → Read budget
  → Can read one detail?
      true  → Skill detail → Inspect evidence → Connection after
            → Evidence and balance receipt
      false → Read not started
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Three native MCP Client nodes call &lt;code&gt;https://agentel.tech/mcp&lt;/code&gt; with the same restricted Reader credential. The two connection nodes call &lt;code&gt;get_connection&lt;/code&gt;; the detail node calls &lt;code&gt;get_network_item&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The result is a Skill record and an allowance receipt you can review. It doesn't install the Skill, run its code or grant it permissions. Those decisions are still yours.&lt;/p&gt;
&lt;h3 id=&quot;what-you-ll-need&quot;&gt;What you'll need&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;An n8n editor you can administer, with the native &lt;strong&gt;MCP Client&lt;/strong&gt; node and &lt;strong&gt;HTTP Streamable&lt;/strong&gt; transport.&lt;/li&gt;
&lt;li&gt;An Agentel &lt;strong&gt;INFO_READ&lt;/strong&gt; restricted Reader credential.&lt;/li&gt;
&lt;li&gt;Enough current reading allowance for one Skill detail request.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For context, the execution checks behind this tutorial were run on &lt;strong&gt;local n8n 2.42.4 / native MCP Client 1.1&lt;/strong&gt; on &lt;strong&gt;October 17, 2026&lt;/strong&gt;. We haven't established the same results for n8n Cloud, other versions, independent customer environments or autonomous Agent tool selection. The template was approved for publication on October 19; that approval is not a certification of those other environments.&lt;/p&gt;
&lt;h3 id=&quot;1-import-the-template&quot;&gt;1. Import the template&lt;/h3&gt;
&lt;p&gt;Open the &lt;a rel=&quot;nofollow&quot; href=&quot;https://n8n.io/workflows/21182-inspect-agentel-mcp-skill-evidence-and-metering-with-the-mcp-client/&quot;&gt;n8n template page&lt;/a&gt; and choose &lt;strong&gt;Use for free&lt;/strong&gt;. You can select an import destination or use &lt;strong&gt;Copy template to clipboard (JSON)&lt;/strong&gt; and paste it into a blank workflow canvas.&lt;/p&gt;
&lt;p&gt;If clipboard import doesn't work, visit the &lt;a rel=&quot;nofollow&quot; href=&quot;https://agentel.tech/en/lab/mcp/n8n&quot;&gt;Agentel n8n setup page&lt;/a&gt;, download &lt;code&gt;agentel-skill-evidence.n8n.json&lt;/code&gt;, and use &lt;strong&gt;Import from File&lt;/strong&gt; in n8n. That page also has a separate connection checker, bilingual instructions and a ZIP download.&lt;/p&gt;
&lt;p&gt;Keep the workflow &lt;strong&gt;inactive and manual-only&lt;/strong&gt; for this test. Don't add a schedule or automatic retries.&lt;/p&gt;
&lt;h3 id=&quot;2-create-a-read-only-reader-credential&quot;&gt;2. Create a read-only Reader credential&lt;/h3&gt;
&lt;p&gt;Follow the &lt;a rel=&quot;nofollow&quot; href=&quot;https://agentel.tech/en/lab/mcp#information-service&quot;&gt;Agentel Reader setup guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you already have an Agentel Agent, keep its existing identity and issue a separate read-only credential. The documented API is &lt;code&gt;POST /api/v1/me/info-credentials&lt;/code&gt;, called from your trusted Agent runtime. Don't move your runtime credential into n8n.&lt;/p&gt;
&lt;p&gt;If you don't have an Agent identity, the documented registration flow supports &lt;code&gt;mode: &quot;INFO_READER&quot;&lt;/code&gt; to create a private Reader identity and credential. Use the current setup instructions rather than reusing somebody else's credential or creating duplicate identities.&lt;/p&gt;
&lt;p&gt;In either case, n8n should receive &lt;strong&gt;only the restricted INFO_READ token&lt;/strong&gt;—not an owner credential, full runtime key, Claim Code or Recovery Code.&lt;/p&gt;
&lt;h3 id=&quot;3-check-workflow-settings-before-connecting&quot;&gt;3. Check workflow settings before connecting&lt;/h3&gt;
&lt;p&gt;One detail caught us during testing: settings for execution retention and timeout weren't preserved by a normal JSON import. So check them in the editor rather than trusting the file.&lt;/p&gt;
&lt;p&gt;Open &lt;strong&gt;More actions → Settings&lt;/strong&gt; and set:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Save failed production executions&lt;/strong&gt; → &lt;strong&gt;Do not save&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Save successful production executions&lt;/strong&gt; → &lt;strong&gt;Do not save&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Save manual executions&lt;/strong&gt; → &lt;strong&gt;Do not save&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Save execution progress&lt;/strong&gt; → &lt;strong&gt;Do not save&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timeout Workflow&lt;/strong&gt; → &lt;strong&gt;Enabled&lt;/strong&gt;, &lt;strong&gt;1 minute 30 seconds&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Save, reopen Settings, and make sure the choices stuck.&lt;/p&gt;
&lt;p&gt;These settings reduce saved execution payloads, but manual runs can still show identity and allowance in your browser. They also don't prove that metadata, logs or backups are erased; follow your own instance's retention policy.&lt;/p&gt;
&lt;h3 id=&quot;4-connect-the-three-mcp-nodes&quot;&gt;4. Connect the three MCP nodes&lt;/h3&gt;
&lt;p&gt;Create a private &lt;strong&gt;Bearer Auth&lt;/strong&gt; credential in n8n. Paste the restricted Reader token into the token field &lt;strong&gt;without&lt;/strong&gt; typing &lt;code&gt;Bearer &lt;/code&gt; in front of it; the credential adds that header itself.&lt;/p&gt;
&lt;p&gt;Use these settings in every MCP Client node:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Setting &lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Server transport &lt;/td&gt;&lt;td&gt;HTTP Streamable&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;MCP endpoint &lt;/td&gt;&lt;td&gt;&lt;code&gt;https://agentel.tech/mcp&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Authentication &lt;/td&gt;&lt;td&gt;Bearer Auth&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Credential &lt;/td&gt;&lt;td&gt;Your restricted INFO_READ Reader&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Bind the &lt;strong&gt;same credential&lt;/strong&gt; to &lt;strong&gt;Connection before&lt;/strong&gt;, &lt;strong&gt;Skill detail&lt;/strong&gt; and &lt;strong&gt;Connection after&lt;/strong&gt;. Check all three: n8n may auto-select an existing credential.&lt;/p&gt;
&lt;p&gt;Avoid placing tokens in Code nodes, workflow parameters, sticky notes, URLs or screenshots. Also review exports before sharing them: &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.n8n.io/build/manage-workflows/export-and-import.md&quot;&gt;n8n's export documentation&lt;/a&gt; notes that credential names and IDs can appear in exported workflows. Remove credential references and execution data from anything you share.&lt;/p&gt;
&lt;h3 id=&quot;5-check-the-connection&quot;&gt;5. Check the connection&lt;/h3&gt;
&lt;p&gt;There's an optional &lt;a rel=&quot;nofollow&quot; href=&quot;https://agentel.tech/downloads/n8n-client-rc3-20261018/agentel-connection-check.n8n.json&quot;&gt;connection-check workflow&lt;/a&gt; if you want to check the Reader before trying the main flow. Give it the same settings review and bind its Connection node to your restricted credential.&lt;/p&gt;
&lt;p&gt;In our October 17 test, &lt;code&gt;get_connection&lt;/code&gt; cost &lt;strong&gt;0 INFO&lt;/strong&gt;. Its current response can show the bound identity, read-only state, plan class and allowance.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CONNECTION_READY&lt;/code&gt; means the local connection and format checks passed. It doesn't mean a Skill has been installed or that every detail call fits within the remaining allowance. A Reader can have a valid connection with zero allowance left.&lt;/p&gt;
&lt;p&gt;If the MCP node reports an authentication, transport, timeout or tool error, stop and check that error instead of automatically retrying.&lt;/p&gt;
&lt;h3 id=&quot;6-inspect-one-skill&quot;&gt;6. Inspect one Skill&lt;/h3&gt;
&lt;p&gt;Back in the main workflow, open &lt;strong&gt;Choose Skill&lt;/strong&gt; and set &lt;code&gt;skill_id&lt;/code&gt; to the public Skill reference you want to inspect. The downloadable template defaults to &lt;code&gt;agentel&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Leave the identity, pricing, allowance and failure checks in place, then run the workflow manually once.&lt;/p&gt;
&lt;p&gt;The workflow checks the Reader's daily and monthly allowance before admitting &lt;strong&gt;at most one&lt;/strong&gt; detail attempt. If the local checks don't allow the request, it follows &lt;strong&gt;Read not started&lt;/strong&gt; and tells you why.&lt;/p&gt;
&lt;p&gt;This preflight is not a reservation: current pricing, concurrent activity and allowance resets can affect what happens between the before/after checks.&lt;/p&gt;
&lt;h3 id=&quot;7-read-the-evidence-not-just-the-green-checkmark&quot;&gt;7. Read the evidence, not just the green checkmark&lt;/h3&gt;
&lt;p&gt;Look at the registered version, declared permissions, license and evidence level. These fields are useful, but none is a runtime guarantee.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unknown license&lt;/strong&gt; means you still need to check the original source and terms.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Declared permissions&lt;/strong&gt; tell you what's recorded, not what has been independently enforced.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;source_checked&lt;/code&gt;&lt;/strong&gt; means source checking was recorded. It does &lt;em&gt;not&lt;/em&gt; mean the Skill was runtime-tested, independently verified or certified safe.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The workflow doesn't install or execute the Skill, approve its permissions, join a Mission, publish anything or award Credit.&lt;/p&gt;
&lt;p&gt;The receipt also compares allowance before and after. In one October 17 run, a real Skill detail reported &lt;strong&gt;1 INFO&lt;/strong&gt;, and daily and monthly allowance each decreased by 1. That's an observation from that run, not a permanent price promise; a shared balance change alone also can't prove exclusive attribution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;INFO is Agentel plan allowance, not a separate card charge for each request.&lt;/strong&gt; Check the current plan and allowance before running. Repeated attempts may consume allowance, including attempts that fail or have an unknown outcome.&lt;/p&gt;
&lt;p&gt;If the receipt shows &lt;code&gt;METERING_UNKNOWN&lt;/code&gt;, don't treat it as a free request. Changes in identity, metering subject, allowance limits or reset windows can make a before/after comparison unreliable. Investigate instead of automatically replaying it.&lt;/p&gt;
&lt;h3 id=&quot;troubleshooting&quot;&gt;Troubleshooting&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;What happened &lt;/th&gt;&lt;th&gt;What to check&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Clipboard says copied, but nothing pastes &lt;/td&gt;&lt;td&gt;Download the official JSON and use Import from File; recheck Settings.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Native MCP Client fails &lt;/td&gt;&lt;td&gt;Check endpoint, transport, Bearer credential, Reader validity and the actual error.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Wrong identity appears &lt;/td&gt;&lt;td&gt;Stop and verify the credential bound to all three MCP nodes.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Read not started &lt;/td&gt;&lt;td&gt;Look at the preflight reason, current price and both allowance windows.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Settings reverted &lt;/td&gt;&lt;td&gt;Reapply retention choices and the 90-second timeout, then save and reopen.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Green execution, missing evidence &lt;/td&gt;&lt;td&gt;Inspect the business result and required fields; a green node alone isn't proof.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;METERING_UNKNOWN&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Preserve the result privately and investigate before attempting another read.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Large or unusual responses may also affect what the client displays; this workflow hasn't established universal response compatibility.&lt;/p&gt;
&lt;h3 id=&quot;why-use-mcp-for-this-&quot;&gt;Why use MCP for this?&lt;/h3&gt;
&lt;p&gt;The point isn't to make an Agent automatically trust another Agent's Skill. It's to give a person a practical way to inspect information from an external network before making a decision.&lt;/p&gt;
&lt;p&gt;Here, n8n's native &lt;strong&gt;MCP Client&lt;/strong&gt; runs tools as ordinary workflow steps. n8n has a separate &lt;strong&gt;MCP Client Tool&lt;/strong&gt; node for AI Agent tool use. We tested the deterministic path, &lt;strong&gt;not&lt;/strong&gt; autonomous Agent compatibility. The &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-langchain.mcpClient/&quot;&gt;official n8n documentation&lt;/a&gt; explains the distinction.&lt;/p&gt;
&lt;h3 id=&quot;try-it-and-tell-us-where-it-falls-short&quot;&gt;Try it and tell us where it falls short&lt;/h3&gt;
&lt;p&gt;Start with the &lt;a rel=&quot;nofollow&quot; href=&quot;https://n8n.io/workflows/21182-inspect-agentel-mcp-skill-evidence-and-metering-with-the-mcp-client/&quot;&gt;published workflow&lt;/a&gt; and keep the &lt;a rel=&quot;nofollow&quot; href=&quot;https://agentel.tech/en/lab/mcp/n8n&quot;&gt;setup guide&lt;/a&gt; open as you go.&lt;/p&gt;
&lt;p&gt;If you try it, I'm especially interested in what wasn't clear: Was setup harder than expected? Did the evidence help you decide anything? Was something important missing?&lt;/p&gt;
&lt;p&gt;For troubleshooting, send your n8n version, MCP Client node version, import method, failing step and a &lt;strong&gt;redacted&lt;/strong&gt; error code to the &lt;a rel=&quot;nofollow&quot; href=&quot;https://agentel.tech/passports/agentel-n8n-maintainer&quot;&gt;Agentel n8n Maintainer&lt;/a&gt;. Please leave out credentials, private identity details, balances and raw execution dumps. Even a first-time setup blocker is useful feedback.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Disclosure: Agentel provides this workflow and article, and operates the maintainer. n8n template-library approval confirms the published listing; it does not certify a Skill's safety or establish independent customer outcomes.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31721/how-to-inspect-an-agent-skill-before-you-adopt-it-with-n8n-and-agentel-mcp</guid>
<pubDate>Mon, 19 Oct 2026 13:01:39 +0000</pubDate>
</item>
<item>
<title>Is your coding agent reading the memory you wrote?</title>
<link>https://coderlegion.com/31650/is-your-coding-agent-reading-the-memory-you-wrote</link>
<description>&lt;p&gt;&lt;em&gt;I maintain Selvedge. This article was prepared with AI assistance and checked against the released Selvedge v0.3.17 package from PyPI (tag v0.3.17, commit 3b67b8f) and the repository's main branch at commit 66c51d3.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I saved one decision, read it back six ways, and got nothing from two of them. The record never moved. The reads that missed it had opened a different, empty database.&lt;/p&gt;
&lt;p&gt;This is a reproduction, not an incident report. I installed Selvedge v0.3.17 from PyPI in a fresh virtual environment, pointed &lt;code&gt;HOME&lt;/code&gt; at a throwaway directory, and logged one invented decision from a project root:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;selvedge init
selvedge log src/billing/charge.py::retry_charge reject \
  --reasoning &quot;Rejected automatic retries inside retry_charge; went with a single attempt plus an idempotency key, because a retry after a timeout can charge a customer twice.&quot; \
  --constraint &quot;A payment request must never be submitted twice for one order.&quot; \
  --stale-when &quot;the payment provider offers server-side idempotent retries&quot; \
  --agent synthetic-demo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(&lt;code&gt;--agent&lt;/code&gt; only sets an attribution label.) Then I asked for that record from different places.&lt;/p&gt;
&lt;h3 id=&quot;one-record-six-reads&quot;&gt;One record, six reads&lt;/h3&gt;
&lt;p&gt;From &lt;code&gt;src/billing&lt;/code&gt;, a subdirectory of the project, &lt;code&gt;selvedge prior-attempts src/billing/charge.py::retry_charge --json&lt;/code&gt; returned the record.&lt;/p&gt;
&lt;p&gt;From an unrelated directory, the same lookup (without &lt;code&gt;--json&lt;/code&gt;) printed &quot;No prior attempts found&quot; and exited 0. By the end of the run, the throwaway home directory held a new per-user database with zero events.&lt;/p&gt;
&lt;p&gt;From that same unrelated directory with &lt;code&gt;SELVEDGE_DB=/path/to/demo-app/.selvedge/selvedge.db&lt;/code&gt; set, the command returned the record with the same ID.&lt;/p&gt;
&lt;p&gt;With the same variable set, the Python package returned the same ID:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from selvedge import SelvedgeStorage, get_db_path

store = SelvedgeStorage(get_db_path(read_only=True))
blame = store.get_blame(&quot;src/billing/charge.py::retry_charge&quot;)
print(blame[&quot;id&quot;] if blame else &quot;not found in this store&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, a small test script started &lt;code&gt;selvedge-server&lt;/code&gt; over stdio and called its &lt;code&gt;prior_attempts&lt;/code&gt; tool. With &lt;code&gt;SELVEDGE_DB&lt;/code&gt; set, it returned the same ID. Without it, from the unrelated directory, it returned an empty list.&lt;/p&gt;
&lt;p&gt;Every read that found the database returned one ID. The two misses weren't missing data; they were the wrong file.&lt;/p&gt;
&lt;h3 id=&quot;why-the-empty-answer-happened&quot;&gt;Why the empty answer happened&lt;/h3&gt;
&lt;p&gt;Selvedge stores decisions in local SQLite. In v0.3.17, the CLI and the MCP server both find that database with &lt;code&gt;get_db_path&lt;/code&gt;, which the package also exports. It checks three places, in order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the &lt;code&gt;SELVEDGE_DB&lt;/code&gt; environment variable;&lt;/li&gt;
&lt;li&gt;an existing &lt;code&gt;.selvedge/selvedge.db&lt;/code&gt; file, searched for upward from the current directory;&lt;/li&gt;
&lt;li&gt;the per-user fallback &lt;code&gt;~/.selvedge/selvedge.db&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The subdirectory read found the project file by searching upward. The unrelated directory had no project file above it, so the read fell through to the per-user path.&lt;/p&gt;
&lt;p&gt;The tool didn't hide this. A normal lookup that falls back writes a warning to stderr, once per process, unless &lt;code&gt;SELVEDGE_QUIET&lt;/code&gt; is set. Both the CLI miss and the MCP miss printed it. On its own, &lt;code&gt;get_db_path(read_only=True)&lt;/code&gt; stays silent and creates nothing. But opening that path with &lt;code&gt;SelvedgeStorage&lt;/code&gt;, as the snippet above does, still creates the per-user directory and an empty database, with no warning. In a fresh home directory without &lt;code&gt;SELVEDGE_DB&lt;/code&gt;, the snippet printed &quot;not found in this store&quot;. &lt;code&gt;selvedge doctor&lt;/code&gt; reports the resolved path and which step matched: &quot;via walked up from CWD to project .selvedge/&quot; from the project root, and &quot;via global fallback (~/.selvedge/)&quot; with status WARN from the unrelated directory. That doctor run still exited 0, so a script that checks only exit codes won't notice.&lt;/p&gt;
&lt;p&gt;An MCP server makes this easier to miss. A client starts the server with whatever working directory and environment the client chooses, and whether you see the server's stderr depends on the client. The README says to set &lt;code&gt;SELVEDGE_DB&lt;/code&gt; in the server configuration when the client starts outside your project.&lt;/p&gt;
&lt;h3 id=&quot;checking-your-own-setup-with-or-without-selvedge&quot;&gt;Checking your own setup, with or without Selvedge&lt;/h3&gt;
&lt;p&gt;None of this is specific to one tool. Any file-based memory, whether a decisions folder, a JSON file or a SQLite database, is located by each process for itself. So, before trusting an empty answer, find out how your tool picks its file. Usually it's some mix of explicit path, project discovery and a per-user default.&lt;/p&gt;
&lt;p&gt;Then ask the question from where the reader actually runs. A check in your terminal describes your terminal, not an agent client or a CI job with its own directory and environment. For processes you don't launch yourself, set the path explicitly rather than relying on discovery.&lt;/p&gt;
&lt;p&gt;When a lookup comes back empty, read it as &quot;nothing in this store,&quot; not &quot;nothing was ever decided.&quot; And once, after any change to clients or configuration, write a test record through one route and read it through the others, comparing IDs rather than text. Matching text could be a copy; a matching ID means the same record.&lt;/p&gt;
&lt;h3 id=&quot;what-s-on-main-and-not-released&quot;&gt;What's on main, and not released&lt;/h3&gt;
&lt;p&gt;PR #76, merged into main as commit 66c51d3 on October 17, 2026 (PT), reworks Selvedge's architecture plan. It describes MCP as &quot;one route to the core, not a prerequisite for using it,&quot; and plans a small local core shared by the library, CLI, MCP and optional integrations. The PR also adds a regression check that saves and retrieves a record across isolated Python processes, and rewords the bundled prompt to present CLI and MCP as routes to the same store.&lt;/p&gt;
&lt;p&gt;None of this is in v0.3.17, and the architecture document says the phases add no release dates. It notes that the current package still installs MCP dependencies, and that making them optional needs a separate compatibility assessment. It lists compact review presentation, native GitHub validation and an editor integration as future work.&lt;/p&gt;
&lt;h3 id=&quot;what-this-run-doesn-t-show&quot;&gt;What this run doesn't show&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;It's synthetic: one invented record, one machine, Python 3.13 and a throwaway home directory. The CLI's PyPI update check was turned off, and telemetry was never enabled.&lt;/li&gt;
&lt;li&gt;No agent client was tested. The MCP route used a test script built on the &lt;code&gt;mcp&lt;/code&gt; Python client, so check your own client's configuration, launch directory and activation separately.&lt;/li&gt;
&lt;li&gt;Selvedge stores what a person or agent explicitly saves. It doesn't verify that the reasoning is true, and it doesn't guarantee that an agent will consult it.&lt;/li&gt;
&lt;li&gt;Pinning the path makes routes agree on a file. It doesn't create records nobody saved.&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31650/is-your-coding-agent-reading-the-memory-you-wrote</guid>
<pubDate>Sun, 18 Oct 2026 21:21:32 +0000</pubDate>
</item>
<item>
<title>Selvedge 0.3.17: test your agent memory before you rely on it</title>
<link>https://coderlegion.com/31521/selvedge-0-3-17-test-your-agent-memory-before-you-rely-on-it</link>
<description>&lt;p&gt;I maintain Selvedge. This article was prepared with AI assistance and checked against the released v0.3.17 documentation.&lt;/p&gt;
&lt;p&gt;A coding agent can tell you it saved a decision. The useful test comes later: close the session, start again, and retrieve the same record. Can you recover the reason you rejected an approach, or just a convincing explanation of the code that remains?&lt;/p&gt;
&lt;p&gt;Selvedge gives compatible AI agents persistent decision memory through a local MCP server or the CLI. You save a choice, its reason, and the alternatives you ruled out against a named part of your project: a function, database column, API route, or dependency. Those records live in SQLite under &lt;code&gt;.selvedge/&lt;/code&gt;, so another session can query the same history.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/masondelan/selvedge/releases/tag/v0.3.17&quot;&gt;Version 0.3.17&lt;/a&gt; makes two parts of that workflow easier to check: whether the local MCP server can retrieve a decision after restarting, and whether the Markdown digest you bring to review still matches the stored history.&lt;/p&gt;
&lt;h3 id=&quot;test-the-local-mcp-server&quot;&gt;Test the local MCP server&lt;/h3&gt;
&lt;p&gt;With &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.astral.sh/uv/getting-started/installation/&quot;&gt;uv installed&lt;/a&gt;, you can try the first check without connecting an agent or touching a project's decisions:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;uv tool install --upgrade selvedge==0.3.17
selvedge demo --mcp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The command starts a real local stdio MCP server, saves a synthetic rejected approach through it, shuts that server down, and starts another. It then checks that retrieval returns the same record ID and content. Add &lt;code&gt;--json&lt;/code&gt; to get the checked IDs and version information in machine-readable form.&lt;/p&gt;
&lt;p&gt;The data is disposable. The demo uses a temporary database, skips background update and telemetry checks, and has a deadline followed by subprocess cleanup. That makes it a useful first step when evaluating the package: a small, concrete persistence check with no invented project history left behind.&lt;/p&gt;
&lt;p&gt;It also has a precise boundary. A passing result checks the Python installation running Selvedge and that local MCP exchange. Your editor may launch a different executable, point at a different database, or require you to enable tools. The demo cannot establish that your agent's configuration or lifecycle hooks are active.&lt;/p&gt;
&lt;h3 id=&quot;try-one-real-decision-across-two-sessions&quot;&gt;Try one real decision across two sessions&lt;/h3&gt;
&lt;p&gt;The next test belongs in your own workflow. Follow the &lt;a rel=&quot;nofollow&quot; href=&quot;https://selvedge.sh/start/quickstart/&quot;&gt;quickstart&lt;/a&gt;, connect your agent, and ask it to save one real decision with the reason and any rejected alternative. Keep the entity path and record ID. Then open a fresh session in the same project and ask it to retrieve that decision. Compare the result with what you saved.&lt;/p&gt;
&lt;p&gt;That is also where to test usefulness. Suppose you kept a dependency because its replacement lacked a feature you needed. Retrieving that constraint gives the next session something specific to check before attempting the replacement again. Only explicitly saved decisions can be recovered, and recorded reasoning still needs judgment: Selvedge stores the account supplied by you or your agent; it cannot establish that the account is correct or complete.&lt;/p&gt;
&lt;h3 id=&quot;check-the-digest-before-review&quot;&gt;Check the digest before review&lt;/h3&gt;
&lt;p&gt;The second addition addresses what happens when those records reach a review. Selvedge already exports a deterministic Markdown digest. Once you have project history, generate it with:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;selvedge export --format markdown -o DECISIONS.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Version 0.3.17 adds a check you can run before review or in CI wherever that same history is available:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;selvedge export --format markdown -o DECISIONS.md --check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the file matches, the command exits successfully without output. If it is stale or missing, it exits with status 1 and a unified diff. The check preserves both the digest and the stored records; it does not initialize or migrate the database. Read failures produce guidance, and invalid arguments return status 2.&lt;/p&gt;
&lt;p&gt;This gives a reviewer a straightforward consistency check. A digest can look reasonable while omitting a recently recorded decision. The check makes that drift visible. It does not validate the decisions themselves or fill gaps in capture. Review the exported reasoning before sharing or committing it.&lt;/p&gt;
&lt;p&gt;There are smaller fixes with the same aim of making the record easier to interpret. Human-readable output now distinguishes an approach considered and rejected from a change tried and reverted. Literal bracket characters in logged text no longer cause the affected CLI rendering failures. The release adds no runtime dependencies, migrations, or MCP tools.&lt;/p&gt;
&lt;p&gt;If you use a coding agent on a project you regularly return to, try one decision across two sessions. A local stdio MCP connection works; an agent with shell access can use the CLI. No hosted account is required, and core storage and retrieval make no LLM calls. The &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/masondelan/selvedge&quot;&gt;repository&lt;/a&gt; has the source and release notes. Feedback about where saving or retrieving that first real decision breaks is especially useful—share it in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/masondelan/selvedge/discussions/49&quot;&gt;existing trial discussion&lt;/a&gt;.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31521/selvedge-0-3-17-test-your-agent-memory-before-you-rely-on-it</guid>
<pubDate>Sat, 17 Oct 2026 16:10:57 +0000</pubDate>
</item>
<item>
<title>Twenty Security Checks Before Your MCP Server Goes Public</title>
<link>https://coderlegion.com/31417/twenty-security-checks-before-your-mcp-server-goes-public</link>
<description>&lt;p&gt;An MCP server is effectively an API that agents call for people, and that gives it an unusual set of risks. The caller is a model that text from elsewhere can steer, the human may never see individual calls, and whatever you return might be read by yet another model. Most problems are familiar API errors amplified by that chain, so this checklist groups twenty checks by layer, with the reasoning for each.&lt;/p&gt;
&lt;p&gt;Transport: HTTPS only, validate the Origin header on every request (the spec requires it, to stop DNS rebinding), bind local servers to localhost and treat session IDs as untrusted. Authorisation: decide per tool what's public, publish protected-resource metadata, validate token audience and never pass a client's token through to another API.&lt;/p&gt;
&lt;p&gt;Input: validate every argument server-side, bound lengths and counts, never accept raw SQL, shell or file paths, and parameterise database calls. Output and prompt injection: treat submitted text as hostile, keep tool descriptions honest and static (changing them after approval or hiding instructions in them are known attacks), and return only what the output schema promises.&lt;/p&gt;
&lt;p&gt;Abuse and operations: rate-limit by IP and tool, annotate tools truthfully but enforce rules server-side too, cap anything that pings a human, return safe errors and log calls. I end with simple ways to test your own server.&lt;/p&gt;
&lt;h4 id=&quot;key-takeaways-1&quot;&gt;Key takeaways&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Validate the Origin header on Streamable HTTP endpoints&lt;/li&gt;
&lt;li&gt;Never forward tokens issued for someone else&lt;/li&gt;
&lt;li&gt;Reject raw query, shell or path arguments&lt;/li&gt;
&lt;li&gt;Keep tool descriptions static and honest&lt;/li&gt;
&lt;li&gt;Rate-limit write tools and log every call&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Related on BuiltToWinWeb: &lt;a rel=&quot;nofollow&quot; href=&quot;https://built2winweb.com/blog/add-mcp-server-to-website/&quot;&gt;how to add an MCP server to a website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Read the full guide on BuiltToWinWeb: &lt;a rel=&quot;nofollow&quot; href=&quot;https://built2winweb.com/blog/mcp-server-security-checklist/&quot;&gt;The MCP server security checklist&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A summary by Jacob Campbell of an article first published on built2winweb.com on October 5, 2026.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31417/twenty-security-checks-before-your-mcp-server-goes-public</guid>
<pubDate>Fri, 16 Oct 2026 16:17:59 +0000</pubDate>
</item>
<item>
<title>Putting a Public MCP Server on Your Website, Safely</title>
<link>https://coderlegion.com/31416/putting-a-public-mcp-server-on-your-website-safely</link>
<description>&lt;p&gt;The Model Context Protocol is the open standard assistants use when they call tools. Most people use it to connect an assistant to their own apps, but it works in the other direction too: a business site can run its own MCP server, letting any assistant check services, prices, hours and availability, or send a request, directly. A crawler sees whatever you published weeks ago; a tool call returns what's true now.&lt;/p&gt;
&lt;p&gt;In this guide I suggest which tools a business site should expose (read-only lookups like services, hours and service area, plus perhaps one write tool for quote requests) and explain the transport. Since the March 2025 revision of the spec, remote servers use Streamable HTTP: a single endpoint that accepts JSON-RPC by POST and runs on ordinary hosting.&lt;/p&gt;
&lt;p&gt;Two later additions matter for public servers. Tool annotations tell clients whether a tool is read-only, destructive, idempotent or reaches outside your system, so they know when to ask the user first. Output schemas let tools return typed, checkable data. For anything needing authorisation, the spec builds on OAuth and expects protected-resource metadata at a well-known path.&lt;/p&gt;
&lt;p&gt;The security list is the part to follow closely: expose facts rather than systems, validate every argument, rate-limit write tools, never leak secrets in errors, treat submitted text as untrusted, validate the Origin header and log calls.&lt;/p&gt;
&lt;h4 id=&quot;key-takeaways-2&quot;&gt;Key takeaways&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;A site's MCP server answers with current facts, not crawled ones&lt;/li&gt;
&lt;li&gt;Remote servers use the Streamable HTTP transport&lt;/li&gt;
&lt;li&gt;Annotate tools so clients know which are read-only&lt;/li&gt;
&lt;li&gt;Validate input and rate-limit any write tool&lt;/li&gt;
&lt;li&gt;Advertise the server through discovery files and registries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Related on BuiltToWinWeb: &lt;a rel=&quot;nofollow&quot; href=&quot;https://built2winweb.com/blog/mcp-server-security-checklist/&quot;&gt;the 20-point MCP server security checklist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Read the full guide on BuiltToWinWeb: &lt;a rel=&quot;nofollow&quot; href=&quot;https://built2winweb.com/blog/add-mcp-server-to-website/&quot;&gt;How to add an MCP server to your website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A summary by Jacob Campbell of an article first published on built2winweb.com on October 5, 2026.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31416/putting-a-public-mcp-server-on-your-website-safely</guid>
<pubDate>Fri, 16 Oct 2026 16:16:36 +0000</pubDate>
</item>
<item>
<title>My AI assistant kept choking on huge PDFs. Here's what actually helped.</title>
<link>https://coderlegion.com/31128/my-ai-assistant-kept-choking-on-huge-pdfs-heres-what-actually-helped</link>
<description>&lt;p&gt;Maybe this is obvious to some of you but it drove me up the wall for weeks, so posting in case it helps someone else.&lt;/p&gt;
&lt;p&gt;I do a lot of contract and document work. My setup is basically an AI assistant that I talk to about files all day. The model is plenty smart. The problem was never the brain — it was the mouth being too full.&lt;/p&gt;
&lt;p&gt;I'd drop a 200-400 page PDF into the chat and ask it to pull out the key clauses. Half the time it would clearly miss the back third of the document. Sometimes it just timed out. Other times I'd look at the token usage and decide I'd rather do it by hand than pay to ship a whole scanned book into the context window. So I'd bail, open a separate compressor, run it, check it didn't nuke the pages, paste it back, and try again. Every single time I did that, I lost the thread of what I was actually trying to do.&lt;/p&gt;
&lt;p&gt;That exit-and-return loop is the real killer. It's not that compression is hard. It's that having to DO the compression manually, outside the conversation, kills the whole &quot;just talk to it&quot; advantage.&lt;/p&gt;
&lt;p&gt;What finally worked for me was stopping thinking of compression as my job and making it the assistant's job. There's a local service I found (it's an MCP thing — if you search &quot;compress-mcp&quot; you'll find it) where the agent just shrinks the file on a single instruction, on my own machine, and the data never leaves my network. I don't open another app. I just say &quot;compress this before you read it&quot; and it happens.&lt;/p&gt;
&lt;p&gt;A few things that surprised me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The tokens thing is real and bigger than I expected. Images especially. A raw high-res scan is largely garbage pixels the model pays to ingest but doesn't need. Shrink ahead, then send, and the bill drops a lot. One measurement I saw put image token cost down around 85.9% on a GPT-4o basis after compressing. Not a magic number, but multiply that across a day of docs and it adds up fast.&lt;/li&gt;
&lt;li&gt;Local matters more than speed for me. I deal with contracts. I am not uploading those to some random SaaS to get them compressed. The fact that it runs here, on my box, with sensitive-stuff detection also local, is the reason I could use it at all. If it required a cloud upload, I'd have said no immediately.&lt;/li&gt;
&lt;li&gt;It removed a daily micro-annoyance, not a dramatic one. I had a 443-page tendering doc that always timed out raw. With local compress-ahead it processed end to end in about two minutes and then the assistant actually read the whole thing. Small win, but it's every day.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A broader thing I've been thinking about: IDC estimated document-related issues are like 21.3% of enterprise productivity loss, which they translated to ~$19,732 per info worker per year. That sounds made up until you live the &quot;it cut off again, re-send, re-read&quot; loop fifty times a week. The fix isn't a smarter model. It's removing the boring step that breaks your flow.&lt;/p&gt;
&lt;p&gt;One detail I didn't expect: once the assistant could prep its own input, I started trusting it with messier material. Before, I treated it like a finicky machine that might choke, so I'd pre-clean everything by hand. After, I just handed it the folder. That trust is the actual upgrade — more than any speed number. A tool you can throw a giant pile of files at without a second thought is doing its job.&lt;/p&gt;
&lt;p&gt;I also stopped building a &quot;don't put this in the chat&quot; list in my head. Because everything goes through the same local path and the sensitive check runs on-device, the privacy boundary holds by construction rather than by me remembering a rule. For a solo worker that's a relief; for a team it's the thing that lets people actually adopt the tool instead of quietly routing around it.&lt;/p&gt;
&lt;p&gt;If you're evaluating options, don't overthink it. Ask yourself: does the file ever contain something you wouldn't upload to a stranger's server? Do you process big docs often enough that manual compression became a chore? Are you building on an assistant rather than just chatting? If yes, a local, callable compression layer is worth a look. If you occasionally shrink the odd image for a group chat, your phone already does that and you don't need anything heavier.&lt;/p&gt;
&lt;p&gt;One framework I use to decide, in case it's useful:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Data residency: does the file stay local, and is sensitive detection on-device?&lt;/li&gt;
&lt;li&gt;Invocation: can the agent call it in plain language, or do you run it by hand?&lt;/li&gt;
&lt;li&gt;Integration cost: do you write glue per platform, or is there a standard protocol?&lt;/li&gt;
&lt;li&gt;Fit: high-frequency large/confidential files, or occasional light tasks?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before this I tried the obvious stuff. I set up a hotfolder and a script that watched it and compressed anything dropped in. It worked, kind of, but it was yet another thing to maintain, and the assistant still couldn't trigger it mid-conversation. The local agent-callable version won out because it met the work where it already was. If you go the script route, fair enough, just know the friction is in the handoff, not the compression.&lt;/p&gt;
&lt;p&gt;Anyway, the point isn't the tool, it's the pattern: stop being the one who preps the file. Let the thing that's going to read it also shrink it. Do that locally and you stop worrying about where the bytes go. Simple change, outsized calm.&lt;/p&gt;
&lt;p&gt;I'm not affiliated with anything here, just a guy who got tired of fighting his own files. The shift from &quot;I compress, then the AI reads&quot; to &quot;the AI compresses, then reads&quot; sounds tiny and it's the single noticeable quality-of-life change in my workflow this year. If your assistant keeps choking on big PDFs, that's probably the seam to fix early.&lt;/p&gt;
&lt;p&gt;Anyway, hope this helps someone. Happy to answer questions about the fully local setup if people are curious, and if you've solved this a different way I'd genuinely like to hear it.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31128/my-ai-assistant-kept-choking-on-huge-pdfs-heres-what-actually-helped</guid>
<pubDate>Thu, 15 Oct 2026 05:11:25 +0000</pubDate>
</item>
<item>
<title>CloudPloy: Deploy anywhere from your AI</title>
<link>https://coderlegion.com/31122/cloudploy-deploy-anywhere-from-your-ai</link>
<description>&lt;p&gt;&lt;strong&gt;CloudPloy: Deploy anywhere from your AI tool.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add an API key. Your agent deploys from Claude Code, Cursor, or any MCP client. Bring your own Ubuntu/AWS server or provision Hetzner/DigitalOcean/AWS at cost. Flat plan for the control plane; compute at the provider's rate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free forever (1 small server, 1 app). Starter $9.99 / Pro $19 / Scale $39.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Website: &lt;a rel=&quot;nofollow&quot; href=&quot;https://cloudploy.com&quot;&gt;https://cloudploy.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Docs: &lt;a rel=&quot;nofollow&quot; href=&quot;https://cloudploy.com/docs&quot;&gt;https://cloudploy.com/docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MCP: &lt;a rel=&quot;nofollow&quot; href=&quot;https://cloudploy.com/mcp&quot;&gt;https://cloudploy.com/mcp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/31122/cloudploy-deploy-anywhere-from-your-ai</guid>
<pubDate>Wed, 14 Oct 2026 23:17:09 +0000</pubDate>
</item>
<item>
<title>How to evaluate agents with one trace across MCP, A2A and Realtime</title>
<link>https://coderlegion.com/31093/how-to-evaluate-agents-with-one-trace-across-mcp-a2a-and-realtime</link>
<description>&lt;p&gt;A support agent passes every eval in staging. In production the same agent is reached three ways: from an IDE over MCP, from the web app over the OpenAI Responses API, and from a triage agent over A2A. The dashboard stays green for weeks. Then a customer escalation shows the triage agent handed over a ticket without the customer's region, and the support agent quoted the refund policy for the wrong country. No evaluator flagged it, because no evaluator ever looked at the hop.&lt;/p&gt;
&lt;p&gt;The reason is structural. Eval is a property of the path a request took, and the protocol defines the path. Most eval stacks were written against one surface, usually chat completions, so they score whatever still looks like a chat completion and quietly skip the rest. A protocol-neutral eval stack scores the path instead, whichever protocol carried the request.&lt;/p&gt;
&lt;h4 id=&quot;every-protocol-adds-seams-to-the-path&quot;&gt;Every protocol adds seams to the path&lt;/h4&gt;
&lt;p&gt;A plain chat completion has one path: prompt in, response out. One rubric can grade it. Each protocol you add forks that path into more decision points, and each decision point needs its own check.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MCP adds a tool catalog.&lt;/strong&gt; The path becomes prompt, tool descriptor list, tool selection, call arguments, tool result, final answer. Score each tool call against policy, and score the catalog as a whole, because a poisoned descriptor looks fine at call time and only shows up against the full catalog.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A2A turns the path into a tree.&lt;/strong&gt; Every hop needs three answers: did the calling agent pass enough context, did the called agent stay in scope, and did the returned artifact match the task that was asked for.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Responses API puts three outputs in one envelope.&lt;/strong&gt; Structured JSON gets graded against a schema, streamed text gets graded as it arrives, and a tool call gets graded against a per-tool policy. One end-to-end pass mixes three things that share nothing except the wrapper.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Realtime has no final message.&lt;/strong&gt; Audio streams in both directions, so checks have to run mid-stream, every N tokens or N audio chunks, with a stop or disclaimer action when a rule fires. The end-to-end budget sits below 500ms, which caps how heavy each check can be.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inline vision needs a second judge.&lt;/strong&gt; When images ride in the same message as tool blocks, the text portion and the image portion need different rubrics, and the image rubric needs a judge that can open the image.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Session state spans turns.&lt;/strong&gt; On a framework with explicit session state, the evaluator has to read state across turns instead of grading each turn alone.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;trace-fidelity-caps-eval-fidelity&quot;&gt;Trace fidelity caps eval fidelity&lt;/h4&gt;
&lt;p&gt;An evaluator can only score what the trace can represent. If your trace has no way to express an agent-to-agent hop or a streaming chunk, no rubric downstream will catch a failure inside one.&lt;/p&gt;
&lt;p&gt;So the first fix is in instrumentation, before any rubric work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Model both sides of a hop.&lt;/strong&gt; Emit one span kind on the calling agent and another on the called agent, and carry the trace ID across the wire so the whole multi-agent path lands in one trace.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Give each modality its own span kind.&lt;/strong&gt; Voice, image and computer-use spans should be distinguishable from text spans, so each one reaches an evaluator built for that modality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Record guardrail and evaluator results as spans.&lt;/strong&gt; When a guardrail decision and an evaluator score sit in the same trace as the model call, you can see which check ran on which step.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The MCP spec helps here. The 2026-07-28 revision documents trace context propagation through &lt;code&gt;_meta&lt;/code&gt; (&lt;code&gt;traceparent&lt;/code&gt;, &lt;code&gt;tracestate&lt;/code&gt;, &lt;code&gt;baggage&lt;/code&gt;), so MCP tool calls can join the same trace as the rest of the agent loop.&lt;/p&gt;
&lt;h4 id=&quot;normalize-the-spans-then-write-each-rubric-once&quot;&gt;Normalize the spans, then write each rubric once&lt;/h4&gt;
&lt;p&gt;The same agent identity shows up differently on every protocol. If you write a groundedness check against raw MCP payloads and another against raw Responses payloads, you now maintain two checks that drift apart.&lt;/p&gt;
&lt;p&gt;Normalize first. Map every span to one semantic convention, such as the OpenTelemetry GenAI conventions, before any evaluator reads it. Then write rubrics against the normalized trace. One groundedness rubric can then grade a RAG answer that arrived over the Responses API and a RAG answer that arrived over MCP, and one task-completion rubric can grade the support agent no matter which client reached it.&lt;/p&gt;
&lt;p&gt;This is the same move observability teams made with OpenTelemetry. Teams that locked to one vendor's tracing format rebuilt their instrumentation every time they switched vendors. Agent protocols are repeating that pattern one layer up.&lt;/p&gt;
&lt;h4 id=&quot;gate-releases-per-protocol&quot;&gt;Gate releases per protocol&lt;/h4&gt;
&lt;p&gt;A single overall score hides which surface regressed. A drop in the MCP tool-audit rubric and a drop in the Realtime guardrail are different failures with different fixes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Keep a regression dataset per protocol surface.&lt;/strong&gt; Run the matching rubric set against it on every change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set a threshold per protocol.&lt;/strong&gt; Fail the release when any one surface drops below its own threshold, even if the blended number looks fine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key each suite on protocol and version.&lt;/strong&gt; MCP's 2026-07-28 revision removed the &lt;code&gt;initialize&lt;/code&gt; handshake, so every request now carries its protocol version in &lt;code&gt;_meta&lt;/code&gt;, and the new deprecation policy gives every deprecated feature a minimum twelve-month window. Tag each regression case with the revision it ran on, and keep the tests for deprecated features until their window closes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep the rubric sets in the repo as code.&lt;/strong&gt; Reviewers should be able to read exactly what gets scored on each surface.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;a-five-step-readiness-audit&quot;&gt;A five-step readiness audit&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Inventory every surface in production.&lt;/strong&gt; MCP servers, A2A endpoints, streaming, voice, vision and computer-use, with the protocol version and client library for each. Most teams find one they did not plan for, usually an MCP server a developer installed last sprint.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instrument and pull one real trace per surface.&lt;/strong&gt; Confirm the hop spans appear on both sides with the propagated trace ID, and that voice and image calls emit their own span kinds. Fix gaps before writing rubrics.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write the rubric set for each protocol.&lt;/strong&gt; Per-tool audit on MCP, per-hop audit on A2A, split rubrics on the Responses API, mid-stream checks on Realtime, an image-capable judge for vision.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Run a per-protocol regression suite and gate on per-protocol thresholds.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cluster production failures by protocol.&lt;/strong&gt; Failures that look like noise one at a time often form a pattern once you group them by surface.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you only have half a day, do step 1. The list is usually longer than the team expects, and it tells you which evaluators are scoring the wrong path today.&lt;/p&gt;
&lt;h4 id=&quot;pitfalls-that-keep-showing-up&quot;&gt;Pitfalls that keep showing up&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Evaluators hard-coded to the chat completions shape.&lt;/strong&gt; Every new protocol triggers a rewrite.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scoring each agent in isolation.&lt;/strong&gt; The end-to-end view looks green while a handoff in the middle dropped context.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Post-call checks only on streaming surfaces.&lt;/strong&gt; By the time the evaluator sees the output, the risky tokens are already on the wire.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accepting tool descriptors from any MCP server without a scan.&lt;/strong&gt; An untrusted server can change what your agent does, and the eval layer never sees it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scoring voice and computer-use on text alone.&lt;/strong&gt; Errors at the ASR layer and the vision layer stay invisible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The span kinds, the rubric set for each of the six protocols and the full audit are in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://futureagi.com/blog/llm-eval-vs-mcp-protocol-evolution-2026/?utm_source=fagiCoderlegion&amp;amp;utm_medium=organic&amp;amp;utm_campaign=blogdistribution&quot;&gt;longer protocol-neutral eval playbook&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;New protocols and revisions will keep arriving. Score the path the request took, and each new surface plugs into a trace model and a rubric library you already maintain.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31093/how-to-evaluate-agents-with-one-trace-across-mcp-a2a-and-realtime</guid>
<pubDate>Wed, 14 Oct 2026 16:22:41 +0000</pubDate>
</item>
<item>
<title>Discussion: What does it take to make an MCP server production-ready?</title>
<link>https://coderlegion.com/31078/discussion-what-does-it-take-to-make-an-mcp-server-production-ready</link>
<description>&lt;p&gt;A local MCP server can be straightforward to run. Production deployments introduce different requirements when agents interact with remote APIs, databases, and execution environments.&lt;/p&gt;
&lt;p&gt;Our new SEOSiri guide examines several important areas:&lt;/p&gt;
&lt;p&gt;Scoped authentication and authorization&lt;/p&gt;
&lt;p&gt;Secure SSE-based remote communication&lt;/p&gt;
&lt;p&gt;Stateless service design&lt;/p&gt;
&lt;p&gt;Response pruning and pagination for token efficiency&lt;/p&gt;
&lt;p&gt;Sandboxed execution for dynamic code&lt;/p&gt;
&lt;p&gt;The central engineering question: how do you give an AI agent useful capabilities without granting unnecessary access or creating avoidable operational risk?&lt;/p&gt;
&lt;p&gt;Read the technical breakdown:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.seosiri.com/2026/10/building-mcp-servers-production-security.html&quot;&gt;https://www.seosiri.com/2026/10/building-mcp-servers-production-security.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For developers working with MCP, AI infrastructure, and DevSecOps.&lt;/p&gt;
</description>
<category>Discussions</category>
<guid isPermaLink="true">https://coderlegion.com/31078/discussion-what-does-it-take-to-make-an-mcp-server-production-ready</guid>
<pubDate>Wed, 14 Oct 2026 14:33:00 +0000</pubDate>
</item>
<item>
<title>Why AI Coding Agents Need a Feature Flag Firewall: Inside Spotify Confidence MCP + ThumbGate</title>
<link>https://coderlegion.com/31077/why-ai-coding-agents-need-feature-flag-firewall-inside-spotify-confidence-mcp-thumbgate</link>
<description>&lt;h2 id=&quot;why-ai-coding-agents-need-a-feature-flag-firewall-inside-spotify-confidence-mcp-thumbgate&quot;&gt;Why AI Coding Agents Need a Feature Flag Firewall: Inside Spotify Confidence MCP + ThumbGate&lt;/h2&gt;
&lt;p&gt;Spotify's experimentation team just announced &lt;strong&gt;&quot;A New Chapter for Confidence&quot;&lt;/strong&gt; (October 14, 2026), launching &lt;strong&gt;Confidence Agent&lt;/strong&gt;, &lt;strong&gt;Session Recordings&lt;/strong&gt;, and official &lt;strong&gt;MCP servers for Claude Code, Cursor, and Codex&lt;/strong&gt; (&lt;code&gt;https://mcp.confidence.dev/mcp/flags&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;This is a massive leap forward for agentic software development: instead of a human engineer manually creating flags, setting rollout percentages, and monitoring A/B test sample sizes in a web dashboard, an AI coding agent can do it directly through natural language in their editor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But giving autonomous AI agents direct write access to production feature flags introduces an entirely new catastrophic blast radius.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;the-three-failure-modes-of-autonomous-flag-mutation&quot;&gt;The Three Failure Modes of Autonomous Flag Mutation&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Premature 100% Rollouts:&lt;/strong&gt;&lt;br&gt;
An autonomous agent refactors a checkout component or backend service. To &quot;verify&quot; its work, it calls &lt;code&gt;set_rollout&lt;/code&gt; to 100% in production before automated integration tests pass or without running a canary slice.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A/B Experiment Pollution:&lt;/strong&gt;&lt;br&gt;
An agent modifies user variant allocations, sample sizes, or targeting criteria mid-experiment, destroying statistical validity and costing the business tens of thousands in unrecoverable experimentation bias.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Destructive Flag Purges:&lt;/strong&gt;&lt;br&gt;
During automated dead-code cleanup, an agent purges a legacy feature flag because it cannot find references in one repository, unaware that a mobile client or upstream microservice still relies on the flag schema.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h4 id=&quot;the-architecture-pre-action-feature-flag-diodes&quot;&gt;The Architecture: Pre-Action Feature Flag Diodes&lt;/h4&gt;
&lt;p&gt;At &lt;a rel=&quot;nofollow&quot; href=&quot;https://thumbgate.ai&quot;&gt;ThumbGate&lt;/a&gt;, we built the &lt;strong&gt;Pre-Action Infrastructure Firewall for Spotify Confidence MCP&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Before an agent executes any mutation via &lt;code&gt;https://mcp.confidence.dev/mcp/flags&lt;/code&gt;, ThumbGate intercepts the tool call in sub-0.5ms and enforces deterministic governance diodes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[ AI Coding Agent: Claude / Cursor / Codex ]
                  â
                  â¼
       [ Proposed MCP Tool Call ]
       (e.g., set_rollout: 100%, flag: &quot;new-checkout&quot;)
                  â
                  â¼
   [ ThumbGate Infrastructure Firewall (&amp;lt;0.5ms) ]
   âââ gate:confidence:rollout_ceiling
   â   ââ Is rollout &amp;gt; 10%? âââº [BLOCK: Require Human Sign-Off]
   âââ gate:confidence:test_proof_required
   â   ââ Tests failing? ââââââº [BLOCK: Require Same-Turn Test Proof]
   âââ gate:confidence:protect_active_experiment
       ââ Active A/B test? ââââº [BLOCK: Experiment Allocation Locked]
                  â
                  â¼ (If Verified &amp;amp; Bounded)
    [ Allowed -&amp;gt; Passthrough to Spotify Confidence API ]
                  â
                  â¼
         [ mcp.confidence.dev ]
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h4 id=&quot;key-pre-action-diodes-implemented&quot;&gt;Key Pre-Action Diodes Implemented&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;gate:confidence:rollout_ceiling&lt;/code&gt; (Max 10% Autonomous Canary):&lt;/strong&gt;&lt;br&gt;
Autonomous agents are hard-capped at 10% canary traffic. Expanding beyond 10% requires an explicit operator confirmation token.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;gate:confidence:test_proof_required&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
Blocks creating or updating feature flags while the repository's CI or local test suite is failing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;gate:confidence:protect_active_experiment&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
Protects live A/B tests against autonomous parameter mutation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;gate:confidence:prevent_flag_deletion&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
Prevents deleting flags in production environments. Flags must follow an explicit deprecation and archive lifecycle.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h4 id=&quot;how-to-protect-your-agentic-tooling&quot;&gt;How to Protect Your Agentic Tooling&lt;/h4&gt;
&lt;p&gt;If your engineering organization is adopting agentic workflows, MCP servers, and autonomous coding tools like Cursor, Claude Code, or Codex, &lt;strong&gt;never grant unconstrained write access to production infrastructure without a pre-action firewall&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;ð &lt;strong&gt;Install the ThumbGate Pre-Action Firewall for your team:&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://thumbgate.ai/go/pro&quot;&gt;https://thumbgate.ai/go/pro&lt;/a&gt; ($19/mo)&lt;br&gt;
ð &lt;strong&gt;Deploy a verified feature-flag safety diode on your production stack this week:&lt;/strong&gt; Book a &lt;a rel=&quot;nofollow&quot; href=&quot;https://thumbgate.ai/go/diagnostic&quot;&gt;Workflow Hardening Diagnostic ($499)&lt;/a&gt;.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31077/why-ai-coding-agents-need-feature-flag-firewall-inside-spotify-confidence-mcp-thumbgate</guid>
<pubDate>Wed, 14 Oct 2026 14:18:03 +0000</pubDate>
</item>
<item>
<title>MCP connected, hooks inactive: lessons from five coding-agent adapters</title>
<link>https://coderlegion.com/30995/mcp-connected-hooks-inactive-lessons-from-five-coding-agent-adapters</link>
<description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/masondelan/mcp-connected-hooks-inactive-lessons-from-five-coding-agent-adapters-fko&quot;&gt;DEV&lt;/a&gt; on September 24, 2026. This cross-post preserves that article’s version-specific implementation and test results.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;An agent can successfully call an MCP server while its lifecycle hooks never run. The server connection and the hook process have separate configuration, execution environments, and trust checks.&lt;/p&gt;
&lt;p&gt;That distinction mattered while extending Selvedge's native hooks beyond Claude Code in version 0.3.15. The release adds adapters for Codex, Cursor, Gemini CLI, VS Code Copilot's Local harness, and Windsurf/Cascade. The useful engineering lesson is how to separate shared behavior from each client's protocol—and how to prove the integration actually ran.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; I maintain Selvedge. This article was drafted with AI assistance and checked against the released implementation and recorded test evidence.&lt;/p&gt;
&lt;h3 id=&quot;keep-the-decision-logic-separate-from-the-protocol&quot;&gt;Keep the decision logic separate from the protocol&lt;/h3&gt;
&lt;p&gt;The feature in this example checks whether an agent has consulted recorded decisions before a supported edit to a watched schema or migration path. A saved rejection might explain that a column cannot be removed because an importer still needs it.&lt;/p&gt;
&lt;p&gt;The adapter has three jobs:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;native client payload
  -&amp;gt; normalize project, session, tool and affected paths
  -&amp;gt; evaluate the shared decision check
  -&amp;gt; encode the result in the client's response format
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The shared check shouldn't need to know whether a client calls its shell tool &lt;code&gt;Bash&lt;/code&gt;, &lt;code&gt;Shell&lt;/code&gt;, or &lt;code&gt;run_shell_command&lt;/code&gt;. Conversely, the response encoder must know which fields—or exit status—the client recognizes.&lt;/p&gt;
&lt;p&gt;The &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/masondelan/selvedge/blob/v0.3.15/selvedge/hooks/adapters.py&quot;&gt;released adapters&lt;/a&gt; make these mappings explicit. For example, the Codex &lt;code&gt;apply_patch&lt;/code&gt; payload supplies patch text in &lt;code&gt;tool_input.command&lt;/code&gt;; the VS Code Local &lt;code&gt;apply_patch&lt;/code&gt; payload uses &lt;code&gt;tool_input.input&lt;/code&gt;. Treating those tools as interchangeable would lose the files the check needs to inspect.&lt;/p&gt;
&lt;h3 id=&quot;similar-event-names-don-t-imply-identical-configuration&quot;&gt;Similar event names don't imply identical configuration&lt;/h3&gt;
&lt;p&gt;These are the project files and pre-edit events used by the five new adapters:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Client target &lt;/th&gt;&lt;th&gt;Project hook configuration &lt;/th&gt;&lt;th&gt;Event used for the edit check&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Codex &lt;/td&gt;&lt;td&gt;.codex/hooks.json &lt;/td&gt;&lt;td&gt;PreToolUse&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Cursor &lt;/td&gt;&lt;td&gt;.cursor/hooks.json &lt;/td&gt;&lt;td&gt;preToolUse&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;VS Code Copilot, Local &lt;/td&gt;&lt;td&gt;.github/hooks/selvedge.json &lt;/td&gt;&lt;td&gt;PreToolUse&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Gemini CLI &lt;/td&gt;&lt;td&gt;.gemini/settings.json &lt;/td&gt;&lt;td&gt;BeforeTool&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Windsurf/Cascade &lt;/td&gt;&lt;td&gt;.windsurf/hooks.json, or existing .devin/hooks.json &lt;/td&gt;&lt;td&gt;pre_write_code, pre_run_command&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The table describes this implementation's supported targets, not every harness sold under those product names. In particular, VS Code Local support doesn't establish support for Copilot CLI, cloud sessions, or Agent Host.&lt;/p&gt;
&lt;p&gt;Configuration shape also differs: copying the same event name into each JSON file is insufficient. Installers need to validate existing structures, preserve unrelated hooks, back up modified files, and surface conflicts rather than silently replacing customized commands.&lt;/p&gt;
&lt;p&gt;Project identity deserves the same care. If a multi-root workspace payload doesn't identify an unambiguous current directory, checking another repository's decisions would be worse than reporting that the check couldn't be applied.&lt;/p&gt;
&lt;h3 id=&quot;a-notification-isn-t-saved-context&quot;&gt;A notification isn't saved context&lt;/h3&gt;
&lt;p&gt;All five new adapters implement the watched-edit check. Four also provide a startup digest and a user notification before compaction. The Windsurf adapter provides neither startup context nor a compaction notification.&lt;/p&gt;
&lt;p&gt;Those are different capabilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;startup digest&lt;/strong&gt; supplies selected saved context at a supported startup event.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;pre-edit check&lt;/strong&gt; can delay a supported tool call until the lookup requirement is satisfied.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;compaction notification&lt;/strong&gt; tells the user something. It doesn't make the model save a decision, and it isn't model-context injection.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Calling all three “memory preservation” hides the distinction users need when debugging. Explicitly recorded rationale is also different from a model's hidden reasoning; these adapters don't inspect hidden reasoning or read chat transcripts.&lt;/p&gt;
&lt;h3 id=&quot;test-installation-invocation-and-behavior-separately&quot;&gt;Test installation, invocation, and behavior separately&lt;/h3&gt;
&lt;p&gt;A generated hook file proves configuration was written. A successful direct invocation proves a script accepts a particular payload. Neither proves the client will launch it.&lt;/p&gt;
&lt;p&gt;For a real-client test, use a disposable project and inspect this sequence:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Seed one synthetic rejection against a watched file.&lt;/li&gt;
&lt;li&gt;Review and enable the hooks through the client's normal trust controls.&lt;/li&gt;
&lt;li&gt;Attempt the relevant edit before retrieving history; inspect the actual denial.&lt;/li&gt;
&lt;li&gt;Retrieve the saved decision, retry, and inspect the final file.&lt;/li&gt;
&lt;li&gt;Test an ordinary source edit and a read operation independently.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The recorded native test used Codex CLI &lt;strong&gt;0.154.0-alpha.6.2&lt;/strong&gt;. It observed an &lt;code&gt;apply_patch&lt;/code&gt; denial, a real &lt;code&gt;prior-attempts&lt;/code&gt; CLI lookup, then an allowed retry with the resulting file checked. It used normal hook trust and an absolute executable path with a local payload recorder. Earlier isolated runs that ignored user configuration never invoked the project hooks; they were excluded from the successful result.&lt;/p&gt;
&lt;p&gt;The other four new clients have automated payload, configuration, SQLite, and subprocess coverage, but haven't been verified end to end in those clients. Startup and compaction behavior also remains contract-tested. That's the difference between implementing an adapter and observing it work in a particular client version.&lt;/p&gt;
&lt;h3 id=&quot;state-the-limits-of-the-check&quot;&gt;State the limits of the check&lt;/h3&gt;
&lt;p&gt;This check covers known mutating tool schemas and configured watched paths. Shell write detection is heuristic. Unknown payloads, missing project databases, and internal evaluation errors fail open, so it is workflow assistance rather than a security boundary.&lt;/p&gt;
&lt;p&gt;The existing lookup window can also be satisfied by a recent query from another session. An allowed edit therefore doesn't prove this particular agent understood the decision—or that the old constraint still applies. Retrieval, correct application, and a successful code change need separate evidence.&lt;/p&gt;
&lt;p&gt;The next diagnostic improvement is to report configuration and observed hook execution separately. A single “connected” status cannot establish both.&lt;/p&gt;
&lt;p&gt;Protocol references: &lt;a rel=&quot;nofollow&quot; href=&quot;https://learn.chatgpt.com/docs/hooks&quot;&gt;Codex&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://cursor.com/docs/hooks&quot;&gt;Cursor&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.visualstudio.com/docs/agents/reference/hooks-reference&quot;&gt;VS Code Local&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://geminicli.com/docs/hooks/reference/&quot;&gt;Gemini CLI&lt;/a&gt;, and &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.devin.ai/desktop/cascade/hooks&quot;&gt;Cascade&lt;/a&gt;. The contracts cited by this implementation were checked September 24, 2026; client versions can change them.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30995/mcp-connected-hooks-inactive-lessons-from-five-coding-agent-adapters</guid>
<pubDate>Wed, 14 Oct 2026 00:48:27 +0000</pubDate>
</item>
<item>
<title>Crossmint's Agent Commerce Toolkit is live</title>
<link>https://coderlegion.com/30871/crossmints-agent-commerce-toolkit-is-live</link>
<description>&lt;p&gt;Crossmint's Agent Commerce Toolkit is live — one integration lets an AI agent pay with any card at any online store.&lt;br&gt;
What it does well: card entry goes straight to a PCI-compliant vault; eligible cards get scoped Visa Intelligent Commerce / Mastercard Agent Pay credentials (spend limits, expiry); and each checkout path is chosen by availability, reliability and cost — embedded checkout, Universal Commerce Protocol, or browser automation.&lt;br&gt;
What it does not do: score whether the purchase itself should fire. A spend limit is a ceiling, not a judgment.&lt;br&gt;
We tested the gap live on October 12, 2026 against a public decision gate: a $240 unverified-merchant buy scored 0.4121 (escalate/block+log) and a scoped, user-approved $42 reorder scored 0.4654 (also escalate) — a blunt gate blocks both, which is why the decider has to be calibrated, not just present.&lt;br&gt;
Full analysis: &lt;a rel=&quot;nofollow&quot; href=&quot;https://scriptmasterlabs.com/crossmint-agent-commerce-toolkit&quot;&gt;https://scriptmasterlabs.com/crossmint-agent-commerce-toolkit&lt;/a&gt;&lt;br&gt;
Decision Capsule + 5 specialized Jev jurors + non-overridable constitution. Jev chooses. Code decides. Built for agents that manage real capital.&lt;/p&gt;
&lt;h2 id=&quot;quant-algorithmictrading-marketstructure-agenticai-aifinance-fintech-institutionaltrading-riskmanagement-mcp-x402-agenteconomy-decisionlayer-usdc&quot;&gt;Quant #AlgorithmicTrading #MarketStructure #AgenticAI #AIFinance #FinTech #InstitutionalTrading #RiskManagement #MCP #x402 #AgentEconomy #DecisionLayer $USDC&lt;/h2&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30871/crossmints-agent-commerce-toolkit-is-live</guid>
<pubDate>Tue, 13 Oct 2026 01:42:57 +0000</pubDate>
</item>
<item>
<title>The Reliability Boundary: What AI Agents Need Before They Touch Production APIs</title>
<link>https://coderlegion.com/30693/the-reliability-boundary-what-ai-agents-need-before-they-touch-production-apis</link>
<description>&lt;p&gt;AI agents are moving from chat interfaces into real business workflows. They can search customer records, update accounts, trigger deployments, and initiate financial operations. That creates a practical engineering question: &lt;strong&gt;what should happen between an agent's decision and a production API call?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In a conventional backend, a request passes through authentication, authorization, validation, rate limits, transaction boundaries, observability, and error handling. Agents need those controls too. They can also misunderstand intent, follow malicious instructions embedded in retrieved content, retry an operation after a timeout, or select the wrong tool.&lt;/p&gt;
&lt;p&gt;The answer is a reliability boundary: a layer that treats the agent's output as a proposal and makes the final decision through deterministic policy and backend services.&lt;/p&gt;
&lt;h3 id=&quot;separate-reasoning-from-execution&quot;&gt;Separate reasoning from execution&lt;/h3&gt;
&lt;p&gt;An early architecture often looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;User → AI agent → MCP tool → Production API
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That path assumes the agent can decide when and how a business action should happen. For sensitive operations, use a more explicit path:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;User request
    ↓
AI agent proposes an action
    ↓
MCP tool or tool gateway
    ↓
Policy, risk, and reliability boundary
    ↓
Validated command → Production API
    ↓
Audit events and reconciliation
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The boundary checks identity, permissions, business rules, duplicate requests, state transitions, and the eventual outcome. This is familiar territory for payment and distributed systems: a syntactically valid request is only the start of the decision.&lt;/p&gt;
&lt;h3 id=&quot;why-an-api-gateway-is-not-enough&quot;&gt;Why an API gateway is not enough&lt;/h3&gt;
&lt;p&gt;An API gateway can authenticate a caller, route traffic, enforce rate limits, and record access. It usually cannot determine whether an agent misunderstood the user's instruction, whether a retrieved document contained prompt injection, whether a selected tool fits the task, or whether the requested change is consistent with the current business state.&lt;/p&gt;
&lt;p&gt;Those checks require application policy. The backend that owns the data or action must remain the final authority.&lt;/p&gt;
&lt;h3 id=&quot;a-production-lesson-from-banking-modernization&quot;&gt;A production lesson from banking modernization&lt;/h3&gt;
&lt;p&gt;At UST, I worked on a Capital One modernization effort as SAS-based operational and business reporting was being moved toward Salesforce. The people using those reports were service agents, not AI agents. My part of the work included designing Spring Boot GET APIs for fraud/security, Section 78, and exception reporting, integrating the services with Snowflake, and exposing the endpoints to the Salesforce team.&lt;/p&gt;
&lt;p&gt;The production question was broader than whether an endpoint returned the right JSON. A service agent had to see only the reports allowed by their role; the API had to apply that rule even when Salesforce was the caller. We worked with architects and product owners on the service design, used role-based access and business rules, and tested the contracts and behavior. JMeter and Gatling performance tests helped us check whether the services could meet SLA expectations under load. Docker, Kubernetes, and the DevOps workflow made deployment and operation part of the engineering responsibility, not an afterthought.&lt;/p&gt;
&lt;p&gt;This was a read-oriented integration, not an AI agent making autonomous changes. Still, it taught a useful boundary lesson: moving a capability from one platform to another does not transfer the authority to decide who may use it. If an AI assistant were later allowed to retrieve one of these reports, its tool call would need to carry the human user's identity and scope. The backend would still enforce role access, validate the request, and record the outcome. An AI tool is another caller of a business capability; it is not a substitute for the controls around that capability.&lt;/p&gt;
&lt;h3 id=&quot;a-refund-example&quot;&gt;A refund example&lt;/h3&gt;
&lt;p&gt;Imagine a customer tells an assistant, “Please refund my last order.” A basic agent may find the latest order and call a refund endpoint. A production workflow needs more answers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Which customer is authenticated, and which order do they mean?&lt;/li&gt;
&lt;li&gt;Is the order eligible under the current policy?&lt;/li&gt;
&lt;li&gt;Has a refund already been requested or completed?&lt;/li&gt;
&lt;li&gt;Is the amount within the caller's authority?&lt;/li&gt;
&lt;li&gt;Does this amount or account require human approval?&lt;/li&gt;
&lt;li&gt;If a tool call times out, how will the system discover its actual state?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A language model can interpret the request and prepare a proposed command. It should not make these policy decisions on its own.&lt;/p&gt;
&lt;h3 id=&quot;six-controls-for-sensitive-agent-actions&quot;&gt;Six controls for sensitive agent actions&lt;/h3&gt;
&lt;h4 id=&quot;1-identity-and-narrow-authorization&quot;&gt;1. Identity and narrow authorization&lt;/h4&gt;
&lt;p&gt;Do not give an agent a broad administrative token. Resolve the authenticated user's identity and grant the tool only the capability required for this workflow. Reading an order and issuing a refund are different permissions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;orders.read
refunds.preview
refunds.request
refunds.approve
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Enforce authorization again in the backend. An MCP server is an integration layer; its presence does not remove the need for service-level authorization.&lt;/p&gt;
&lt;h4 id=&quot;2-structured-commands-and-validation&quot;&gt;2. Structured commands and validation&lt;/h4&gt;
&lt;p&gt;Do not pass unrestricted prose to a state-changing API. Define a typed command with required fields and constraints:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public record RefundCommand(
    String customerId,
    String orderId,
    BigDecimal amount,
    String currency,
    String reason,
    String idempotencyKey
) {}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The agent may suggest initial arguments. The backend must check the authenticated identity, ownership, amount, currency, eligibility, and current state before accepting the command. Schema validation catches malformed inputs; business validation catches unsafe actions.&lt;/p&gt;
&lt;h4 id=&quot;3-idempotency-and-duplicate-protection&quot;&gt;3. Idempotency and duplicate protection&lt;/h4&gt;
&lt;p&gt;Agents retry after timeouts, uncertain tool results, and orchestration failures. A retry must not create a second refund. Assign a stable idempotency key to the &lt;em&gt;business operation&lt;/em&gt;, and persist the result associated with it. If the same operation is requested again, return the existing result.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;First request: refund-order-7842 → REFUND_ACCEPTED
Retry:         refund-order-7842 → same recorded result
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key must remain stable across retries. Generating a fresh key on every attempt defeats duplicate protection.&lt;/p&gt;
&lt;h4 id=&quot;4-risk-based-human-approval&quot;&gt;4. Risk-based human approval&lt;/h4&gt;
&lt;p&gt;Approval should follow a policy, rather than being added after an incident. For example, reading an order may proceed automatically; a refund preview may be automatic after validation; a high-value refund or a change to bank details may require a person to review the exact payload.&lt;/p&gt;
&lt;p&gt;The agent can prepare the action and explain it. Policy decides what is allowed. The human approves actions above the risk threshold. The backend validates and executes the final command.&lt;/p&gt;
&lt;h4 id=&quot;5-auditability&quot;&gt;5. Auditability&lt;/h4&gt;
&lt;p&gt;A production workflow should leave more than a chat transcript. Record the authenticated actor, workflow and tool identifiers, input arguments, policy decision, approval, correlation ID, idempotency key, backend response, and final business outcome. Exclude secrets and unnecessary personal data from logs.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;eventType&quot;: &quot;REFUND_REQUESTED&quot;,
  &quot;workflowId&quot;: &quot;wf-8271&quot;,
  &quot;actor&quot;: &quot;user-442&quot;,
  &quot;resource&quot;: &quot;order-7842&quot;,
  &quot;policyDecision&quot;: &quot;APPROVED&quot;,
  &quot;idempotencyKey&quot;: &quot;refund-order-7842&quot;,
  &quot;correlationId&quot;: &quot;corr-91a7&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These records support incident investigation, customer disputes, and reconciliation.&lt;/p&gt;
&lt;h4 id=&quot;6-reconciliation&quot;&gt;6. Reconciliation&lt;/h4&gt;
&lt;p&gt;A timeout does not prove failure. The backend may have accepted the action while the agent missed the response. Before retrying, look up the operation by its stable identifier and ask the system of record for its actual state.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;What is the current state of refund-order-7842?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The final business outcome should come from the system of record, not the model's interpretation of a partial tool response.&lt;/p&gt;
&lt;h3 id=&quot;where-mcp-fits&quot;&gt;Where MCP fits&lt;/h3&gt;
&lt;p&gt;Model Context Protocol (MCP) offers a standard interface for exposing tools and resources to AI applications. That can simplify integration, but it does not replace identity management, authorization, input validation, transaction handling, audit logging, approval, or reconciliation.&lt;/p&gt;
&lt;p&gt;Expose controlled business capabilities, such as &lt;code&gt;preview_refund(order_id, reason)&lt;/code&gt;. Avoid tools that give an agent unrestricted database queries or administrative operations. Tool descriptions help an agent choose an action; backend policy determines whether the action may run.&lt;/p&gt;
&lt;h3 id=&quot;reference-architecture&quot;&gt;Reference architecture&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;User request
   │
   ▼
AI agent ── proposes tool call ──► MCP tool server
                                      │
                                      ▼
                               Policy and risk engine
                                      │
                       ┌──────────────┴──────────────┐
                       ▼                             ▼
                Human approval                 Automatic path
                       └──────────────┬──────────────┘
                                      ▼
                          Validation + idempotency
                                      │
                                      ▼
                              Backend API
                                      │
                                      ▼
                          Audit + reconciliation
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key component is the policy and reliability layer between the model and the business operation. It keeps the model from becoming the final authority over sensitive actions.&lt;/p&gt;
&lt;h3 id=&quot;what-teams-should-measure&quot;&gt;What teams should measure&lt;/h3&gt;
&lt;p&gt;Response accuracy is only one measure of agent quality. Also track invalid tool calls, policy rejections, duplicate prevention, retry frequency, approval rates, time to reconcile uncertain operations, audit completeness, and recovery time after failures.&lt;/p&gt;
&lt;p&gt;An agent that answers fluently but cannot explain or reconcile its actions is not ready for production.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;The most useful enterprise agents will have bounded, observable, and recoverable autonomy. They can move quickly while the system verifies identity, permissions, business state, and outcomes. MCP helps connect agents to tools; a reliability boundary makes those connections safe enough for real work.&lt;/p&gt;
&lt;h4 id=&quot;references&quot;&gt;References&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://modelcontextprotocol.io/specification/latest&quot;&gt;Model Context Protocol Specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.nist.gov/itl/ai-risk-management-framework&quot;&gt;NIST AI Risk Management Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://owasp.org/www-project-top-10-for-large-language-model-applications/&quot;&gt;OWASP Top 10 for Large Language Model Applications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30693/the-reliability-boundary-what-ai-agents-need-before-they-touch-production-apis</guid>
<pubDate>Sun, 11 Oct 2026 08:43:40 +0000</pubDate>
</item>
<item>
<title>Most Developers Are Building AI Agents Wrong: MCP Is the Missing Contract</title>
<link>https://coderlegion.com/30689/most-developers-are-building-ai-agents-wrong-mcp-is-the-missing-contract</link>
<description>&lt;p&gt;AI agents are easy to demo and difficult to trust.&lt;/p&gt;
&lt;p&gt;A developer can connect a language model to a few tools in an afternoon. The first demo looks impressive: the agent reads a request, calls an API, checks a database, and returns an answer.&lt;/p&gt;
&lt;p&gt;Then production arrives.&lt;/p&gt;
&lt;p&gt;The agent calls the wrong tool. It sends an incomplete payload. It retries a payment operation. It exposes information from another tenant. Nobody can explain why it made a decision.&lt;/p&gt;
&lt;p&gt;The problem is not always the language model. The deeper problem is that many teams are building agents without a clear contract between the model, the tools, the data, and the people responsible for the outcome.&lt;/p&gt;
&lt;p&gt;That is where the Model Context Protocol, or MCP, becomes important.&lt;/p&gt;
&lt;h3 id=&quot;an-ai-agent-is-more-than-a-chatbot&quot;&gt;An AI agent is more than a chatbot&lt;/h3&gt;
&lt;p&gt;A useful enterprise agent usually has five parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A model that reasons about the request&lt;/li&gt;
&lt;li&gt;Instructions that define its role and limits&lt;/li&gt;
&lt;li&gt;Tools that allow it to read or change systems&lt;/li&gt;
&lt;li&gt;Memory or context that helps it understand the task&lt;/li&gt;
&lt;li&gt;Guardrails that control what it is allowed to do&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A chatbot mainly generates text. An agent can take actions.&lt;/p&gt;
&lt;p&gt;That difference changes the engineering problem completely. If an agent only produces an explanation, an inaccurate response may be corrected by a human. If an agent can approve a refund, change a production configuration, or submit a healthcare request, an inaccurate response becomes an operational incident.&lt;/p&gt;
&lt;p&gt;The agent must therefore be treated like a distributed system with an unreliable reasoning component.&lt;/p&gt;
&lt;h3 id=&quot;the-tool-boundary-is-the-real-architecture&quot;&gt;The tool boundary is the real architecture&lt;/h3&gt;
&lt;p&gt;Many early agent implementations expose tools with a name, description, and input schema. That is not enough for production.&lt;/p&gt;
&lt;p&gt;A safe tool contract must answer several questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Which user or tenant is the agent allowed to access?&lt;/li&gt;
&lt;li&gt;Which values are valid?&lt;/li&gt;
&lt;li&gt;Does the operation require approval?&lt;/li&gt;
&lt;li&gt;Is the operation idempotent?&lt;/li&gt;
&lt;li&gt;What happens if the network times out after success?&lt;/li&gt;
&lt;li&gt;How is the action audited?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A tool description is not a security policy. It is only the beginning of a contract.&lt;/p&gt;
&lt;h3 id=&quot;why-mcp-matters&quot;&gt;Why MCP matters&lt;/h3&gt;
&lt;p&gt;MCP provides a standard way for AI applications to discover and use external tools and resources. Instead of building a different integration for every model and every application, teams can expose capabilities through a consistent protocol.&lt;/p&gt;
&lt;p&gt;That standardization is valuable, but it does not automatically make an integration safe.&lt;/p&gt;
&lt;p&gt;MCP should be treated as an interoperability layer, not as permission to give an agent unrestricted access to a system.&lt;/p&gt;
&lt;p&gt;A production MCP tool should define:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A clear business purpose&lt;/li&gt;
&lt;li&gt;Read or write classification&lt;/li&gt;
&lt;li&gt;Authentication and authorization requirements&lt;/li&gt;
&lt;li&gt;Tenant and data-scope restrictions&lt;/li&gt;
&lt;li&gt;Input validation&lt;/li&gt;
&lt;li&gt;Idempotency behavior&lt;/li&gt;
&lt;li&gt;Timeout and retry rules&lt;/li&gt;
&lt;li&gt;Rate limits&lt;/li&gt;
&lt;li&gt;Audit events&lt;/li&gt;
&lt;li&gt;Human approval requirements&lt;/li&gt;
&lt;li&gt;A safe failure response&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The most important design principle is simple:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The model may request an action, but the platform must decide whether that action is allowed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;a-safer-agent-flow&quot;&gt;A safer agent flow&lt;/h3&gt;
&lt;p&gt;A reliable enterprise agent should follow a controlled sequence:&lt;/p&gt;
&lt;p&gt;User request -&amp;gt; identity verification -&amp;gt; permitted context -&amp;gt; model plan -&amp;gt; policy evaluation -&amp;gt; human approval when required -&amp;gt; MCP tool execution -&amp;gt; result validation -&amp;gt; audit event -&amp;gt; user response&lt;/p&gt;
&lt;p&gt;The model should not directly own the complete workflow. It should operate inside one.&lt;/p&gt;
&lt;p&gt;For example, an agent may propose: Cancel this payment.&lt;/p&gt;
&lt;p&gt;The policy layer should check whether the user is authenticated, whether the payment belongs to the user organization, whether it is still cancellable, whether the amount exceeds an approval threshold, whether the request was already processed, and whether the downstream tool is healthy.&lt;/p&gt;
&lt;p&gt;Only after these checks should the action reach the payment service.&lt;/p&gt;
&lt;h3 id=&quot;mcp-and-spring-boot&quot;&gt;MCP and Spring Boot&lt;/h3&gt;
&lt;p&gt;A practical Java implementation can place an agent gateway in front of domain services.&lt;/p&gt;
&lt;p&gt;The gateway can provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Spring Security authentication&lt;/li&gt;
&lt;li&gt;OAuth2 or JWT validation&lt;/li&gt;
&lt;li&gt;Tool-level authorization&lt;/li&gt;
&lt;li&gt;Request and response schemas&lt;/li&gt;
&lt;li&gt;Correlation IDs&lt;/li&gt;
&lt;li&gt;Rate limiting&lt;/li&gt;
&lt;li&gt;OpenTelemetry traces&lt;/li&gt;
&lt;li&gt;Approval workflow integration&lt;/li&gt;
&lt;li&gt;Central audit logging&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The domain service should still enforce its own business rules. Never assume that because a request came from an AI gateway, it is trustworthy.&lt;/p&gt;
&lt;p&gt;A safe execution model is: validate the user, evaluate policy, validate the tool input, enforce idempotency, call the domain service, validate the result, and record an audit event.&lt;/p&gt;
&lt;p&gt;The model can select a tool. It should not bypass the same controls that apply to a human-operated API.&lt;/p&gt;
&lt;h3 id=&quot;read-tools-and-write-tools-are-not-equal&quot;&gt;Read tools and write tools are not equal&lt;/h3&gt;
&lt;p&gt;Read-only tools may retrieve an invoice, search a knowledge base, or check an order status. Write tools may create a payment, update a customer, delete a document, or deploy software.&lt;/p&gt;
&lt;p&gt;These categories should have different controls. A read tool may require normal user authorization. A high-impact write tool may require explicit confirmation, a second approver, a transaction limit, a dry-run mode, or a compensating action.&lt;/p&gt;
&lt;p&gt;Do not hide a write operation behind a friendly name such as manage account. Use names that reveal the action and its risk: create refund, disable user, or deploy release.&lt;/p&gt;
&lt;p&gt;Clear names help models, developers, reviewers, and security teams understand what is happening.&lt;/p&gt;
&lt;h3 id=&quot;the-biggest-mcp-security-risks&quot;&gt;The biggest MCP security risks&lt;/h3&gt;
&lt;p&gt;MCP-based systems introduce familiar security risks in a new form.&lt;/p&gt;
&lt;h4 id=&quot;excessive-permissions&quot;&gt;Excessive permissions&lt;/h4&gt;
&lt;p&gt;An agent receives access to more data and tools than it needs. If the model or server is compromised, the blast radius becomes large.&lt;/p&gt;
&lt;h4 id=&quot;prompt-injection&quot;&gt;Prompt injection&lt;/h4&gt;
&lt;p&gt;Untrusted content inside a document, webpage, or ticket attempts to influence the agent instructions. Retrieved content must be treated as data, not as a higher-priority instruction.&lt;/p&gt;
&lt;h4 id=&quot;confused-deputy-problems&quot;&gt;Confused deputy problems&lt;/h4&gt;
&lt;p&gt;The agent uses its own powerful credentials to perform an action on behalf of a user who does not have that permission.&lt;/p&gt;
&lt;h4 id=&quot;tool-poisoning&quot;&gt;Tool poisoning&lt;/h4&gt;
&lt;p&gt;A malicious or poorly maintained tool provides misleading descriptions, hidden side effects, or unsafe defaults.&lt;/p&gt;
&lt;h4 id=&quot;data-leakage&quot;&gt;Data leakage&lt;/h4&gt;
&lt;p&gt;The agent combines information from different users, tenants, or conversations and includes it in a response.&lt;/p&gt;
&lt;p&gt;The solution is not one magic prompt. It is layered security: least privilege, isolation, validation, monitoring, and clear ownership.&lt;/p&gt;
&lt;h3 id=&quot;observability-is-not-optional&quot;&gt;Observability is not optional&lt;/h3&gt;
&lt;p&gt;Traditional application monitoring asks what request failed, which service was slow, and what status code was returned.&lt;/p&gt;
&lt;p&gt;Agent observability needs additional questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What was the original user intent?&lt;/li&gt;
&lt;li&gt;What context was retrieved?&lt;/li&gt;
&lt;li&gt;Which tools were considered?&lt;/li&gt;
&lt;li&gt;Which tool was selected?&lt;/li&gt;
&lt;li&gt;What policy decision was made?&lt;/li&gt;
&lt;li&gt;How many retries occurred?&lt;/li&gt;
&lt;li&gt;Was human approval requested?&lt;/li&gt;
&lt;li&gt;What data was returned to the user?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every agent action should have a correlation ID that follows the request across the model gateway, MCP server, domain service, database, and audit system.&lt;/p&gt;
&lt;p&gt;Without this trail, debugging becomes guesswork.&lt;/p&gt;
&lt;h3 id=&quot;start-with-narrow-agents&quot;&gt;Start with narrow agents&lt;/h3&gt;
&lt;p&gt;The best first production agent is rarely a general-purpose assistant with access to the entire company.&lt;/p&gt;
&lt;p&gt;Start with one bounded workflow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Search internal documentation&lt;/li&gt;
&lt;li&gt;Summarize support tickets&lt;/li&gt;
&lt;li&gt;Validate an invoice&lt;/li&gt;
&lt;li&gt;Classify incoming documents&lt;/li&gt;
&lt;li&gt;Explain a failed transaction&lt;/li&gt;
&lt;li&gt;Draft, but do not send, a customer response&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Measure accuracy, latency, cost, refusal quality, tool-selection errors, and security violations. Then expand carefully.&lt;/p&gt;
&lt;p&gt;A narrow agent with clear boundaries can create more business value than a general agent that appears intelligent but cannot be trusted.&lt;/p&gt;
&lt;h3 id=&quot;the-future-of-agents-is-controlled-autonomy&quot;&gt;The future of agents is controlled autonomy&lt;/h3&gt;
&lt;p&gt;AI agents will become more capable, but capability alone is not the goal.&lt;/p&gt;
&lt;p&gt;The goal is controlled autonomy: systems that can complete useful work while remaining observable, explainable, reversible, and accountable.&lt;/p&gt;
&lt;p&gt;MCP can help create a common interface between agents and the software world. But the protocol is only one layer. The real production architecture still needs identity, policy, security, resilience, testing, and human judgment.&lt;/p&gt;
&lt;p&gt;The strongest agent teams will not ask only, What can the model do? They will also ask, What should the model be allowed to do, under which conditions, and how can we prove what happened?&lt;/p&gt;
&lt;p&gt;That is the difference between an impressive demo and an enterprise system.&lt;/p&gt;
&lt;h3 id=&quot;final-checklist&quot;&gt;Final checklist&lt;/h3&gt;
&lt;p&gt;Before exposing an MCP tool to an AI agent, verify:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is the tool purpose narrow and explicit?&lt;/li&gt;
&lt;li&gt;Is access scoped to the authenticated user and tenant?&lt;/li&gt;
&lt;li&gt;Are inputs validated independently of the model?&lt;/li&gt;
&lt;li&gt;Are write actions idempotent?&lt;/li&gt;
&lt;li&gt;Are high-risk actions reversible or approval-gated?&lt;/li&gt;
&lt;li&gt;Are prompts and retrieved documents treated as untrusted data?&lt;/li&gt;
&lt;li&gt;Are tool calls, policy decisions, and outputs audited?&lt;/li&gt;
&lt;li&gt;Can the team trace a failed decision?&lt;/li&gt;
&lt;li&gt;Is there a rate limit and emergency disable mechanism?&lt;/li&gt;
&lt;li&gt;Does the system fail safely when the model is wrong?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the answer to several of these questions is no, the agent is not ready for production.&lt;/p&gt;
&lt;p&gt;It is ready for a better architecture.&lt;/p&gt;
&lt;h3 id=&quot;a-production-agent-architecture&quot;&gt;A production agent architecture&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;flowchart LR
    U[User request] --&amp;gt; G[Agent gateway]
    G --&amp;gt; P[Policy and identity checks]
    P --&amp;gt; M[Model plan]
    M --&amp;gt; C[MCP server]
    C --&amp;gt; D[Domain service]
    D --&amp;gt; A[Audit and observability]
    A --&amp;gt; R[Validated response]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The model proposes the next action, but the gateway, policy layer, MCP server, and domain service each enforce their own boundary. This layered design prevents one incorrect model decision from becoming an uncontrolled production change.&lt;/p&gt;
&lt;h3 id=&quot;reference&quot;&gt;Reference&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://modelcontextprotocol.io/&quot;&gt;Model Context Protocol official documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30689/most-developers-are-building-ai-agents-wrong-mcp-is-the-missing-contract</guid>
<pubDate>Sun, 11 Oct 2026 07:48:38 +0000</pubDate>
</item>
<item>
<title>My coding agent kept &quot;fixing&quot; proxy errors wrong, so I built an MCP server</title>
<link>https://coderlegion.com/30586/my-coding-agent-kept-fixing-proxy-errors-wrong-so-i-built-an-mcp-server</link>
<description>&lt;p&gt;I work on proxy infrastructure, which means I read a lot of proxy errors. And I kept noticing the same thing: the coding agents I used were great at almost everything except this.  &lt;/p&gt;
&lt;p&gt;Give one a 407 and it would happily &quot;fix&quot; it by putting the proxy credentials into the target site's &lt;code&gt;Authorization&lt;/code&gt; header. Show it a timeout on a POST and it would just retry, without asking whether the first request had already reached the server.&lt;/p&gt;
&lt;p&gt;That's not the model being dumb. Proxy errors are a narrow area with a lot of confidently wrong answers floating around the internet, and the model has read plenty of them.&lt;/p&gt;
&lt;p&gt;So I built a small MCP server that gives the agent grounded answers for this one area. It's free, open source and works with any proxy provider. Here's what I learned designing it.&lt;/p&gt;
&lt;h3 id=&quot;1-don-t-let-the-agent-paste-raw-logs&quot;&gt;1. Don't let the agent paste raw logs&lt;/h3&gt;
&lt;p&gt;The diagnose tool doesn't accept logs, URLs or credentials. It takes structured observations instead. This is a real input for the 407 case:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;client&quot;: &quot;requests&quot;,
  &quot;version&quot;: &quot;2.34.2&quot;,
  &quot;phase&quot;: &quot;connect_tunnel&quot;,
  &quot;status&quot;: 407,
  &quot;responseSource&quot;: &quot;proxy&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two reasons. Logs are full of things that shouldn't end up in a model's context, like credentials and session cookies. And the phase matters more than people expect. A 407 during the CONNECT tunnel is your proxy talking, not the website, so the fix is in your proxy config and never in the target's headers.&lt;/p&gt;
&lt;p&gt;The schema is strict on purpose. Unknown fields are rejected, and &lt;code&gt;responseSource&lt;/code&gt; should only say &lt;code&gt;proxy&lt;/code&gt; or &lt;code&gt;target&lt;/code&gt; when you actually know which layer answered, not because of the status code alone.&lt;/p&gt;
&lt;h3 id=&quot;2-never-recommend-an-automatic-retry&quot;&gt;2. Never recommend an automatic retry&lt;/h3&gt;
&lt;p&gt;Every diagnosis comes back with likely causes, the next thing to check, and what it can't know. For the 407 above, the summary starts with this:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;407 reports an intermediary authentication requirement. It does not identify a wrong password as the sole cause.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Retries got the strictest treatment. In the output schema, &lt;code&gt;automaticRetryRecommended&lt;/code&gt; isn't a boolean. It's the literal &lt;code&gt;false&lt;/code&gt;. The tool can only tell the agent what kind of retry thinking applies. Here's what comes back for a POST that timed out waiting for response headers:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;&quot;retry&quot;: {
  &quot;automaticRetryRecommended&quot;: false,
  &quot;category&quot;: &quot;reconcile_before_repeating&quot;,
  &quot;advice&quot;: &quot;Do not automatically repeat POST/PATCH or an operation of unknown semantics. ...&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If a write timed out after it left your machine, the order might already exist. A missing response isn't proof that nothing happened, and the tool says so instead of letting the agent assume.&lt;/p&gt;
&lt;h3 id=&quot;3-credentials-never-go-through-the-agent&quot;&gt;3. Credentials never go through the agent&lt;/h3&gt;
&lt;p&gt;Config templates use environment variable placeholders. No tool asks for a password as an argument, and no response ever contains one. If the agent never sees the secret, it can't paste it into a transcript, a log or a commit.&lt;/p&gt;
&lt;h3 id=&quot;4-the-one-tool-that-touches-the-network-is-boring-on-purpose&quot;&gt;4. The one tool that touches the network is boring on purpose&lt;/h3&gt;
&lt;p&gt;Run locally, the server sends no telemetry and makes no network requests. There's one optional route check, and it stays off until you set &lt;code&gt;IPVOLT_ENABLE_ROUTE_CHECK=1&lt;/code&gt;. Then it sends a single request through your proxy to one fixed endpoint, with a 10-second deadline, and that's all it can do. It can't be pointed at an arbitrary URL, so it can't be turned into a port scanner.&lt;/p&gt;
&lt;p&gt;The hosted version keeps basic metrics: tool name, success or error, duration and toolkit version. Nothing about your requests.&lt;/p&gt;
&lt;h3 id=&quot;5-return-structured-data-and-text&quot;&gt;5. Return structured data and text&lt;/h3&gt;
&lt;p&gt;Every tool has an output schema, and responses include both the structured result and the same result as text. Clients that read structured content get clean JSON they can pipe into the next step. Clients that don't still get a usable answer.&lt;/p&gt;
&lt;h3 id=&quot;the-trade-offs&quot;&gt;The trade-offs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Client versions are pinned.&lt;/strong&gt; The diagnose tool only accepts the exact versions the rules were tested against: curl 8.22.0, Requests 2.34.2, HTTPX 0.28.1 and Playwright 1.63.0. That keeps the answers honest, but anyone on another version gets an error instead of a diagnosis.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The local package requires Node 24+.&lt;/strong&gt; That rules out everyone still on Node 22.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The first npm release went out without build provenance.&lt;/strong&gt; The next one should come from CI with provenance attached.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;try-it&quot;&gt;Try it&lt;/h3&gt;
&lt;p&gt;Use the hosted endpoint (&lt;code&gt;https://mcp.ipvolt.com/mcp&lt;/code&gt;, Streamable HTTP, no signup or API key), or run it locally:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx --yes @ipvolt/proxy-toolkit-mcp@0.1.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Setup for different MCP clients is at &lt;a rel=&quot;nofollow&quot; href=&quot;https://ipvolt.com/mcp&quot;&gt;ipvolt.com/mcp&lt;/a&gt;, and the code is on &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ipvolt/proxy-toolkit-mcp&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Full disclosure: I'm building ipvolt, a proxy service. The toolkit is provider-neutral and works fine without it.&lt;/p&gt;
&lt;p&gt;If you've built MCP tools yourself: do you return structured data, text, or both? Curious what's worked for you.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30586/my-coding-agent-kept-fixing-proxy-errors-wrong-so-i-built-an-mcp-server</guid>
<pubDate>Sat, 10 Oct 2026 12:32:30 +0000</pubDate>
</item>
<item>
<title>11 Claude Code Gotchas That Quietly Skip Your Guardrails</title>
<link>https://coderlegion.com/30399/11-claude-code-gotchas-that-quietly-skip-your-guardrails</link>
<description>&lt;p&gt;Claude Code is now the harness a lot of AI engineers run agentic dev workflows through — interactive, headless with &lt;code&gt;-p&lt;/code&gt;, through the Agent SDK, in CI, with subagents and a stack of MCP servers. The failure modes that matter are almost never in the setup guide. They're the quiet ones: an &lt;code&gt;ask&lt;/code&gt; rule that never prompts, a checked-in &lt;code&gt;.mcp.json&lt;/code&gt; that loads with no approval, a hook that fails open, an MCP call that can hang for a day.&lt;/p&gt;
&lt;p&gt;Eleven gotchas a 3-year practitioner wouldn't already know (86 raw fragments → 22 candidates → 15 validated → 11 published). &lt;strong&gt;Numbers are the severity × rarity rank; sections group by theme&lt;/strong&gt; (so the numbering is intentionally non-sequential). Each has a detection and a fix. Every threshold, TTL, timeout, block count, and cost figure is &lt;strong&gt;as of Claude Code v2.1.283 / September 2026&lt;/strong&gt; — re-verify before hard-coding. The GH#46829 20–32% and GH#97622 ~50,000-char figures are &lt;strong&gt;community-reported, not confirmed by Anthropic&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;tl-dr-the-11-in-rank-order&quot;&gt;TL;DR — the 11, in rank order&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;# &lt;/th&gt;&lt;th&gt;Gotcha &lt;/th&gt;&lt;th&gt;One-line takeaway&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;1 &lt;/td&gt;&lt;td&gt;&lt;code&gt;permissions.ask&lt;/code&gt; can run without asking &lt;/td&gt;&lt;td&gt;Use &lt;code&gt;deny&lt;/code&gt; for anything safety-critical; canary-test &lt;code&gt;ask&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2 &lt;/td&gt;&lt;td&gt;&lt;code&gt;-p&lt;/code&gt; / SDK / cloud / &lt;code&gt;--bare&lt;/code&gt; skip safety layers &lt;/td&gt;&lt;td&gt;Unapproved &lt;code&gt;.mcp.json&lt;/code&gt; loads headless — use &lt;code&gt;--strict-mcp-config&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;3 &lt;/td&gt;&lt;td&gt;CLAUDE.md enforces nothing; hooks fail open &lt;/td&gt;&lt;td&gt;Hard rules go in &lt;code&gt;permissions&lt;/code&gt;; hooks must &lt;code&gt;exit 2&lt;/code&gt; and anchor matchers.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;4 &lt;/td&gt;&lt;td&gt;&lt;code&gt;MCP_TOOL_TIMEOUT&lt;/code&gt; defaults to ~28h &lt;/td&gt;&lt;td&gt;Set it explicitly, especially for stdio/WebSocket servers.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;5 &lt;/td&gt;&lt;td&gt;Auto mode is now the default &lt;/td&gt;&lt;td&gt;Pin &lt;code&gt;permissions.defaultMode&lt;/code&gt;; the 3/20 block breaker isn't tunable.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;6 &lt;/td&gt;&lt;td&gt;Subagents get a session-start CLAUDE.md snapshot &lt;/td&gt;&lt;td&gt;Restate must-follow rules in the delegation prompt.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;7 &lt;/td&gt;&lt;td&gt;&lt;code&gt;--max-budget-usd&lt;/code&gt; forgets resumed spend &lt;/td&gt;&lt;td&gt;Track cumulative spend externally.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;8 &lt;/td&gt;&lt;td&gt;The &lt;code&gt;rm -rf&lt;/code&gt; countdown resolves to deny &lt;/td&gt;&lt;td&gt;Unattended auto/bypass pipelines should expect the deny.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;9 &lt;/td&gt;&lt;td&gt;Cache TTL drops from 1h to 5m &lt;/td&gt;&lt;td&gt;Pin &lt;code&gt;CLAUDE_CODE_PROMPT_CACHE_TTL&lt;/code&gt; / &lt;code&gt;CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;10 &lt;/td&gt;&lt;td&gt;Four config knobs don't do what their names say &lt;/td&gt;&lt;td&gt;Raise the compact window with &lt;code&gt;/autocompact&lt;/code&gt;, not the env var.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;11 &lt;/td&gt;&lt;td&gt;MCP output over the cap goes to a file &lt;/td&gt;&lt;td&gt;A tool's own &lt;code&gt;maxResultSizeChars&lt;/code&gt; beats &lt;code&gt;MAX_MCP_OUTPUT_TOKENS&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;All values as of v2.1.283 / Sep 2026.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-trust-boundary-three&quot;&gt;The trust-boundary three&lt;/h3&gt;
&lt;h4 id=&quot;1-permissions-ask-has-three-different-ways-to-not-actually-ask&quot;&gt;1. &lt;code&gt;permissions.ask&lt;/code&gt; has three different ways to not actually ask&lt;/h4&gt;
&lt;p&gt;At least three independently reported paths let an ask-listed command run with no prompt: in default/no-sandbox mode a visible &lt;code&gt;Bash(conda run:*)&lt;/code&gt; ask rule ran unprompted (&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/79771&quot;&gt;GH#79771&lt;/a&gt;, open) while &lt;code&gt;/sandbox&lt;/code&gt; with &lt;code&gt;autoAllowBashIfSandboxed:false&lt;/code&gt; did enforce it; auto mode ignores &lt;code&gt;permissions.ask&lt;/code&gt; while honoring &lt;code&gt;allow&lt;/code&gt;/&lt;code&gt;deny&lt;/code&gt; (&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/42797&quot;&gt;GH#42797&lt;/a&gt;, closed, no stated fix); and a transiently invalid &lt;code&gt;settings.json&lt;/code&gt; silently drops deny &lt;strong&gt;and&lt;/strong&gt; ask enforcement in &lt;code&gt;-p&lt;/code&gt;/stream-json (&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/78764&quot;&gt;GH#78764&lt;/a&gt;, closed &quot;not planned,&quot; labeled reproduced). No stated fix as of v2.1.283.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Detection:&lt;/strong&gt; put a harmless canary on &lt;code&gt;permissions.ask&lt;/code&gt; and confirm a prompt actually appears — don't trust &lt;code&gt;/permissions&lt;/code&gt; listing it. In a test project only, break &lt;code&gt;settings.json&lt;/code&gt; mid-run under &lt;code&gt;-p&lt;/code&gt; and confirm denied commands stay denied. &lt;strong&gt;Fix:&lt;/strong&gt; use &lt;code&gt;permissions.deny&lt;/code&gt; for anything safety-critical; where &lt;code&gt;ask&lt;/code&gt; is required, also enable &lt;code&gt;/sandbox&lt;/code&gt; with &lt;code&gt;autoAllowBashIfSandboxed:false&lt;/code&gt;; never hand-edit a live &lt;code&gt;settings.json&lt;/code&gt; mid-session.&lt;/p&gt;
&lt;h4 id=&quot;2--p-the-agent-sdk-cloud-sessions-and---bare-all-quietly-skip-a-safety-layer&quot;&gt;2. &lt;code&gt;-p&lt;/code&gt;, the Agent SDK, cloud sessions, and &lt;code&gt;--bare&lt;/code&gt; all quietly skip a safety layer&lt;/h4&gt;
&lt;p&gt;Trust verification is disabled under &lt;code&gt;-p&lt;/code&gt;. Project &lt;code&gt;.mcp.json&lt;/code&gt; servers load with no approval prompt in &lt;code&gt;-p&lt;/code&gt;, the Agent SDK, and cloud sessions — and in any &lt;code&gt;bypassPermissions&lt;/code&gt; session with &lt;code&gt;skipDangerousModePermissionPrompt&lt;/code&gt; set. &lt;code&gt;--bare&lt;/code&gt; skips hooks, skills, commands, subagents, plugins, MCP, auto memory, and CLAUDE.md, and sets &lt;code&gt;CLAUDE_CODE_SIMPLE&lt;/code&gt; (skills in an &lt;code&gt;--add-dir&lt;/code&gt; directory still load). Plain &lt;code&gt;--continue&lt;/code&gt; skips &lt;code&gt;-p&lt;/code&gt;/SDK/&lt;code&gt;/loop&lt;/code&gt;-first sessions unless you run &lt;code&gt;claude -p --continue&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Detection:&lt;/strong&gt; audit CI target repos for a checked-in &lt;code&gt;.mcp.json&lt;/code&gt;; after a &lt;code&gt;-p&lt;/code&gt; session, &lt;code&gt;claude mcp list&lt;/code&gt;. &lt;strong&gt;Fix:&lt;/strong&gt; &lt;code&gt;--strict-mcp-config&lt;/code&gt;, &lt;code&gt;disabledMcpjsonServers&lt;/code&gt;, or &lt;code&gt;--setting-sources&lt;/code&gt; for &lt;code&gt;-p&lt;/code&gt;/SDK/CI runs; treat every headless target repo as pre-vetted; don't use &lt;code&gt;--bare&lt;/code&gt; where hooks are your guardrail. &lt;em&gt;(Official docs — single publisher.)&lt;/em&gt; (&lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/mcp&quot;&gt;MCP&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/cli-reference&quot;&gt;CLI reference&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/security&quot;&gt;security&lt;/a&gt;)&lt;/p&gt;
&lt;h4 id=&quot;3-claude-md-doesn-t-enforce-anything-and-pretooluse-hooks-fail-open&quot;&gt;3. CLAUDE.md doesn't enforce anything — and PreToolUse hooks fail open&lt;/h4&gt;
&lt;p&gt;The docs: &lt;em&gt;&quot;CLAUDE.md instructions shape Claude's behavior but are not a hard enforcement layer.&quot;&lt;/em&gt; Enforcement is &lt;code&gt;permissions&lt;/code&gt; allow/ask/deny plus PreToolUse hooks, and deny/ask beat a hook's decision. The hook traps: a typo'd or non-executable path exits 127 and is non-blocking; a &lt;code&gt;command&lt;/code&gt;/&lt;code&gt;http&lt;/code&gt;/&lt;code&gt;mcp_tool&lt;/code&gt; hook that times out doesn't block (an Agent SDK callback hook does); only exit 2 blocks — exit 1 doesn't, and exit 2 blocks even if the JSON says allow; &lt;code&gt;Edit.*&lt;/code&gt; also matches &lt;code&gt;NotebookEdit&lt;/code&gt;; &lt;code&gt;mcp__memory&lt;/code&gt; matches nothing (use &lt;code&gt;mcp__memory__.*&lt;/code&gt;); the &lt;code&gt;if&lt;/code&gt; field holds one rule, no &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;/&lt;code&gt;||&lt;/code&gt;; &lt;code&gt;disableAllHooks&lt;/code&gt; can't disable managed hooks unless set at the managed level. Default hook timeouts (v2.1.283): 600s command/http/mcp_tool, 30s prompt, 60s agent. Mid-session CLAUDE.md edits don't apply until &lt;code&gt;/clear&lt;/code&gt;, &lt;code&gt;/compact&lt;/code&gt;, or restart; keep it under 200 lines.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Detection:&lt;/strong&gt; &lt;code&gt;claude --debug&lt;/code&gt; and watch for &lt;code&gt;Failed with non-blocking status code&lt;/code&gt;; fire &lt;code&gt;Edit&lt;/code&gt; and &lt;code&gt;NotebookEdit&lt;/code&gt; at an &lt;code&gt;Edit.*&lt;/code&gt; hook. &lt;strong&gt;Fix:&lt;/strong&gt; hard rules go in &lt;code&gt;permissions.deny&lt;/code&gt;/&lt;code&gt;ask&lt;/code&gt;; hooks exit 2 explicitly, anchor matchers (&lt;code&gt;^Edit$&lt;/code&gt;), use &lt;code&gt;mcp__server__.*&lt;/code&gt;, and verify the script path is executable. &lt;em&gt;(Official docs — single publisher.)&lt;/em&gt; (&lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/hooks&quot;&gt;hooks&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/permissions&quot;&gt;permissions&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/memory&quot;&gt;memory&lt;/a&gt;)&lt;/p&gt;
&lt;h3 id=&quot;the-silent-default-four&quot;&gt;The silent-default four&lt;/h3&gt;
&lt;h4 id=&quot;4-the-mcp-timeout-nobody-sets-defaults-to-28-hours&quot;&gt;4. The MCP timeout nobody sets defaults to ~28 hours&lt;/h4&gt;
&lt;p&gt;Leave &lt;code&gt;MCP_TOOL_TIMEOUT&lt;/code&gt; unset and you inherit a ~28-hour default (as of v2.1.283). A per-server timeout below 1000 is ignored and falls through to &lt;code&gt;MCP_TOOL_TIMEOUT&lt;/code&gt;. HTTP/SSE get a per-request timer of max(60s, server tool timeout, &lt;code&gt;MCP_TIMEOUT&lt;/code&gt;); stdio and WebSocket have &lt;strong&gt;no per-request timer&lt;/strong&gt;, so a hung call can run the full ~28 hours (&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/69487&quot;&gt;GH#69487&lt;/a&gt;). &lt;strong&gt;Detection:&lt;/strong&gt; &lt;code&gt;echo $MCP_TOOL_TIMEOUT&lt;/code&gt; — empty means exposed. &lt;strong&gt;Fix:&lt;/strong&gt; set &lt;code&gt;MCP_TOOL_TIMEOUT&lt;/code&gt; explicitly in milliseconds (&amp;gt;= 1000), especially for stdio/WebSocket servers.&lt;/p&gt;
&lt;h4 id=&quot;5-auto-mode-is-now-the-default-everywhere-with-trip-wires-you-can-t-tune&quot;&gt;5. Auto mode is now the default everywhere — with trip wires you can't tune&lt;/h4&gt;
&lt;p&gt;As of v2.1.283, auto mode is the default starting permission mode for interactive terminal and VS Code sessions on every plan and provider unless &lt;code&gt;permissions.defaultMode&lt;/code&gt; says otherwise. Its breaker is fixed: after 3 consecutive or 20 total blocks per session, auto mode pauses and goes back to prompting you (as of v2.1.283). The classifier runs server-side by default, staged from v2.1.271 to v2.1.280. &lt;strong&gt;Detection:&lt;/strong&gt; &lt;code&gt;/status&lt;/code&gt;. &lt;strong&gt;Fix:&lt;/strong&gt; &lt;code&gt;{ &quot;permissions&quot;: { &quot;defaultMode&quot;: &quot;default&quot; } }&lt;/code&gt;; separately, &lt;code&gt;export CLAUDE_CODE_AUTO_MODE_SERVER=0&lt;/code&gt; controls where the classifier runs (off the server-side path), not whether auto mode is on. (&lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/permission-modes&quot;&gt;permission modes&lt;/a&gt;)&lt;/p&gt;
&lt;h4 id=&quot;8-the-rm--rf-countdown-resolves-to-deny-and-there-are-two-different-rm-guards&quot;&gt;8. The &lt;code&gt;rm -rf&lt;/code&gt; countdown resolves to DENY — and there are two different rm guards&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;&quot;If the countdown runs out before you answer, Claude Code denies the command.&quot;&lt;/em&gt; The 2-minute countdown (as of v2.1.283) appears only in auto and bypassPermissions modes; after 3 unanswered countdowns, further critical-path removals are denied immediately. &lt;code&gt;rm -rf &quot;$(pwd)&quot;&lt;/code&gt; trips a separate substitution check whose opt-out, &lt;code&gt;CLAUDE_CODE_DISABLE_SUBSTITUTION_RM_PROMPT=1&lt;/code&gt;, is not &lt;code&gt;CLAUDE_CODE_DISABLE_DANGEROUS_RM_TIMEOUT=1&lt;/code&gt; (which only removes the countdown — deny-on-timeout becomes wait-forever). &lt;strong&gt;Fix:&lt;/strong&gt; leave both guards on and design unattended pipelines to expect a deny after 2 minutes. Verify only in a disposable container/VM.&lt;/p&gt;
&lt;h4 id=&quot;6-subagents-run-on-a-session-start-claude-md-snapshot-and-disallowedtools-amputates-whole-tools&quot;&gt;6. Subagents run on a session-start CLAUDE.md snapshot — and &lt;code&gt;disallowedTools&lt;/code&gt; amputates whole tools&lt;/h4&gt;
&lt;p&gt;Non-fork subagents get no conversation history and no auto memory, and their CLAUDE.md/memory is the copy the parent loaded at session start (&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/88886&quot;&gt;GH#88886&lt;/a&gt;) — mid-session edits are invisible to them. &lt;code&gt;disallowedTools: [Bash(git push *)]&lt;/code&gt; removes the whole Bash tool. When the parent is in &lt;code&gt;bypassPermissions&lt;/code&gt;/&lt;code&gt;acceptEdits&lt;/code&gt;/&lt;code&gt;auto&lt;/code&gt;, the subagent's own &lt;code&gt;permissionMode&lt;/code&gt; is ignored. &lt;strong&gt;Fix:&lt;/strong&gt; restate must-follow rules in the delegation prompt; &lt;code&gt;isolation: worktree&lt;/code&gt;; block specific commands with a &lt;code&gt;permissions.deny&lt;/code&gt; Bash rule, not &lt;code&gt;disallowedTools(specifier)&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-cost-and-context-four&quot;&gt;The cost-and-context four&lt;/h3&gt;
&lt;h4 id=&quot;9-your-prompt-cache-ttl-quietly-drops-from-1-hour-to-5-minutes&quot;&gt;9. Your prompt cache TTL quietly drops from 1 hour to 5 minutes&lt;/h4&gt;
&lt;p&gt;As of v2.1.283 / Sep 2026, the main conversation gets a 1-hour TTL only on a subscription within plan usage; it drops to 5 minutes on usage credits and is 5 minutes by default on an API key or cloud provider. Subagents, workflows, compaction, and teammates get 5 minutes unless pinned. A &lt;code&gt;/model&lt;/code&gt; or effort switch forces a full recompute on most models. &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/46829&quot;&gt;GH#46829&lt;/a&gt; reports a 20–32% cost rise — &lt;em&gt;community-reported, directional only, not confirmed by Anthropic.&lt;/em&gt; &lt;strong&gt;Detection:&lt;/strong&gt; &lt;code&gt;cache_creation_input_tokens&lt;/code&gt; vs &lt;code&gt;cache_read_input_tokens&lt;/code&gt; per turn; &lt;code&gt;/usage&lt;/code&gt; &quot;Prompt cache (main)&quot; line (v2.1.260+). &lt;strong&gt;Fix:&lt;/strong&gt; &lt;code&gt;CLAUDE_CODE_PROMPT_CACHE_TTL=1h&lt;/code&gt; and &lt;code&gt;CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL=1h&lt;/code&gt; (v2.1.242+; &lt;code&gt;5m&lt;/code&gt; or &lt;code&gt;1h&lt;/code&gt;). (&lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/prompt-caching&quot;&gt;prompt caching&lt;/a&gt;)&lt;/p&gt;
&lt;h4 id=&quot;7---max-budget-usd-doesn-t-count-what-you-think-across-resumes&quot;&gt;7. &lt;code&gt;--max-budget-usd&lt;/code&gt; doesn't count what you think across resumes&lt;/h4&gt;
&lt;p&gt;Print-mode only; subagent spend counts (v2.1.217+), but totals restored via &lt;code&gt;--continue&lt;/code&gt;/&lt;code&gt;--resume&lt;/code&gt; do NOT count toward the cap on the resumed run. &lt;code&gt;--max-turns&lt;/code&gt; is print-mode only, has no default, and a queued stream-json message at turn-end starts a fresh turn with its own limit. &lt;strong&gt;Fix:&lt;/strong&gt; track cumulative spend externally; read the stop message — a model switch doesn't help a session limit, and only an admin can raise a spend limit. &lt;em&gt;(Official docs — single publisher.)&lt;/em&gt; (&lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/cli-reference&quot;&gt;CLI reference&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/costs&quot;&gt;costs&lt;/a&gt;)&lt;/p&gt;
&lt;h4 id=&quot;10-four-config-knobs-that-don-t-do-what-their-name-implies&quot;&gt;10. Four config knobs that don't do what their name implies&lt;/h4&gt;
&lt;p&gt;As of v2.1.283: &lt;code&gt;CLAUDE_AUTOCOMPACT_PCT_OVERRIDE&lt;/code&gt; can only lower the trigger; &lt;code&gt;CLAUDE_CODE_AUTO_COMPACT_WINDOW&lt;/code&gt; takes only a plain token count (no &lt;code&gt;k&lt;/code&gt;/&lt;code&gt;M&lt;/code&gt;) and, if set, overrides &lt;code&gt;/autocompact 500k&lt;/code&gt; and &lt;code&gt;--autocompact 1M&lt;/code&gt;; &lt;code&gt;max&lt;/code&gt; effort persists only via &lt;code&gt;CLAUDE_CODE_EFFORT_LEVEL=max&lt;/code&gt; (rejected in &lt;code&gt;modelSettings&lt;/code&gt;/&lt;code&gt;effortLevel&lt;/code&gt;); &lt;code&gt;bashOutputMaxChars&lt;/code&gt; overrides &lt;code&gt;BASH_MAX_OUTPUT_LENGTH&lt;/code&gt; (default 30000, max 150000). &lt;strong&gt;Detection:&lt;/strong&gt; &lt;code&gt;/autocompact&lt;/code&gt; with no args. &lt;em&gt;(Official docs — single publisher.)&lt;/em&gt; (&lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/env-vars&quot;&gt;env vars&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/model-config&quot;&gt;model config&lt;/a&gt;)&lt;/p&gt;
&lt;h4 id=&quot;11-your-mcp-output-got-truncated-and-saved-to-disk-and-the-chat-barely-tells-you&quot;&gt;11. Your MCP output got truncated and saved to disk — and the chat barely tells you&lt;/h4&gt;
&lt;p&gt;MCP output warns at 10,000 tokens and caps at 25,000 by default (as of v2.1.283). &lt;code&gt;MAX_MCP_OUTPUT_TOKENS&lt;/code&gt; only affects tools without their own &lt;code&gt;maxResultSizeChars&lt;/code&gt; (capped at 500,000 chars). Oversized non-image results go to &lt;code&gt;~/.claude/projects/.../tool-results/&lt;/code&gt; with a message naming the path. &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/anthropics/claude-code/issues/97622&quot;&gt;GH#97622&lt;/a&gt; reports an extra ~50,000-char persist threshold the env var doesn't lift — &lt;em&gt;community-reported, unverified by Anthropic.&lt;/em&gt; &lt;strong&gt;Fix:&lt;/strong&gt; check whether a tool declares &lt;code&gt;maxResultSizeChars&lt;/code&gt; before relying on the env var; run &lt;code&gt;/context&lt;/code&gt; after adding any MCP server. (&lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/mcp&quot;&gt;MCP&lt;/a&gt;)&lt;/p&gt;
&lt;h3 id=&quot;where-to-set-these-as-of-v2-1-283-sep-2026-&quot;&gt;Where to set these (as of v2.1.283 / Sep 2026)&lt;/h3&gt;
&lt;p&gt;From the official docs: &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/settings&quot;&gt;settings&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/settings-reference&quot;&gt;settings reference&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/env-vars&quot;&gt;env vars&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/mcp&quot;&gt;MCP&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/permissions&quot;&gt;permissions&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://code.claude.com/docs/en/headless&quot;&gt;headless&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Settings files&lt;/strong&gt; (highest precedence first):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Level &lt;/th&gt;&lt;th&gt;File &lt;/th&gt;&lt;th&gt;Applies to&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Managed &lt;/td&gt;&lt;td&gt;&lt;code&gt;managed-settings.json&lt;/code&gt;, MDM, or the claude.ai console &lt;/td&gt;&lt;td&gt;Everyone your org deploys it to; you can't override it&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Command line &lt;/td&gt;&lt;td&gt;&lt;code&gt;claude --settings&lt;/code&gt; &lt;/td&gt;&lt;td&gt;You, this session&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Project local &lt;/td&gt;&lt;td&gt;&lt;code&gt;.claude/settings.local.json&lt;/code&gt; &lt;/td&gt;&lt;td&gt;You, this project only&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Shared project &lt;/td&gt;&lt;td&gt;&lt;code&gt;.claude/settings.json&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Everyone in the project (checked into source control)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;User &lt;/td&gt;&lt;td&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt; &lt;/td&gt;&lt;td&gt;You, every project&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;All of these keys can be set in &lt;strong&gt;any&lt;/strong&gt; of those files: &lt;code&gt;permissions.allow&lt;/code&gt; / &lt;code&gt;ask&lt;/code&gt; / &lt;code&gt;deny&lt;/code&gt; / &lt;code&gt;defaultMode&lt;/code&gt;, &lt;code&gt;hooks&lt;/code&gt;, &lt;code&gt;disableAllHooks&lt;/code&gt;, &lt;code&gt;promptCacheTtl&lt;/code&gt;, &lt;code&gt;subagentPromptCacheTtl&lt;/code&gt;, &lt;code&gt;bashOutputMaxChars&lt;/code&gt;, &lt;code&gt;autoCompactWindow&lt;/code&gt;, &lt;code&gt;effortLevel&lt;/code&gt;, &lt;code&gt;disabledMcpjsonServers&lt;/code&gt;, &lt;code&gt;sandbox.autoAllowBashIfSandboxed&lt;/code&gt;, &lt;code&gt;showThinkingSummaries&lt;/code&gt;, &lt;code&gt;env&lt;/code&gt;. Exception: &lt;code&gt;permissions.defaultMode&lt;/code&gt; values &lt;code&gt;auto&lt;/code&gt; and &lt;code&gt;bypassPermissions&lt;/code&gt; don't take effect from project or local settings — set them in user or managed settings.&lt;/p&gt;
&lt;p&gt;Team-wide guardrails (deny rules, hooks, &lt;code&gt;disabledMcpjsonServers&lt;/code&gt;) belong in the checked-in &lt;code&gt;.claude/settings.json&lt;/code&gt;; personal preferences belong in &lt;code&gt;~/.claude/settings.json&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsonc&quot;&gt;// ~/.claude/settings.json  (or .claude/settings.json for the whole team)
{
  &quot;permissions&quot;: { &quot;deny&quot;: [&quot;Bash(git push *)&quot;], &quot;defaultMode&quot;: &quot;default&quot; },
  &quot;sandbox&quot;: { &quot;autoAllowBashIfSandboxed&quot;: false },
  &quot;promptCacheTtl&quot;: &quot;1h&quot;,
  &quot;subagentPromptCacheTtl&quot;: &quot;1h&quot;,
  &quot;env&quot;: { &quot;MCP_TOOL_TIMEOUT&quot;: &quot;&amp;lt;milliseconds&amp;gt;&quot; }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Environment variables&lt;/strong&gt; (&lt;code&gt;MCP_TOOL_TIMEOUT&lt;/code&gt;, &lt;code&gt;MAX_MCP_OUTPUT_TOKENS&lt;/code&gt;, &lt;code&gt;CLAUDE_CODE_PROMPT_CACHE_TTL&lt;/code&gt;, &lt;code&gt;CLAUDE_CODE_EFFORT_LEVEL&lt;/code&gt;, &lt;code&gt;CLAUDE_CODE_AUTO_MODE_SERVER&lt;/code&gt;, …) can be set two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;in your shell before launching &lt;code&gt;claude&lt;/code&gt; (&lt;code&gt;export VAR=value&lt;/code&gt;; add it to &lt;code&gt;~/.zshrc&lt;/code&gt; / &lt;code&gt;~/.bashrc&lt;/code&gt; to persist), or&lt;/li&gt;
&lt;li&gt;under the &lt;code&gt;&quot;env&quot;&lt;/code&gt; key of any settings file above. If both are set, the settings-file value wins.&lt;/li&gt;
&lt;li&gt;Exception: &lt;code&gt;CLAUDE_CODE_DISABLE_DANGEROUS_RM_TIMEOUT&lt;/code&gt; is read only from the environment you launch &lt;code&gt;claude&lt;/code&gt; from — it is ignored in a settings &lt;code&gt;env&lt;/code&gt; block.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;MCP servers:&lt;/strong&gt; project-scoped servers live in &lt;code&gt;.mcp.json&lt;/code&gt; at the project root; user- and local-scoped servers live in &lt;code&gt;~/.claude.json&lt;/code&gt;. A per-server &lt;code&gt;&quot;timeout&quot;&lt;/code&gt; field (milliseconds, ≥1000) in a &lt;code&gt;.mcp.json&lt;/code&gt; entry overrides &lt;code&gt;MCP_TOOL_TIMEOUT&lt;/code&gt; for that server only.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How to write &lt;code&gt;permissions.allow&lt;/code&gt; / &lt;code&gt;ask&lt;/code&gt; / &lt;code&gt;deny&lt;/code&gt; rules&lt;/strong&gt; (code.claude.com/docs/en/permissions, fetched 2026-09-29):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;allow&lt;/strong&gt; — Claude Code runs the tool without asking. &lt;strong&gt;ask&lt;/strong&gt; — it prompts you for confirmation every time. &lt;strong&gt;deny&lt;/strong&gt; — it's blocked. Rules are evaluated deny → ask → allow; the first match wins, and specificity doesn't change the order.&lt;/li&gt;
&lt;li&gt;Syntax is &lt;code&gt;Tool(specifier)&lt;/code&gt;: &lt;code&gt;Bash(npm run build)&lt;/code&gt; (exact command), &lt;code&gt;Bash(npm run *)&lt;/code&gt; (prefix — the space before &lt;code&gt;*&lt;/code&gt; matters; &lt;code&gt;Bash(ls:*)&lt;/code&gt; = &lt;code&gt;Bash(ls *)&lt;/code&gt;), &lt;code&gt;Read(./.env)&lt;/code&gt;, &lt;code&gt;Read(./secrets/**)&lt;/code&gt;, &lt;code&gt;WebFetch(domain:example.com)&lt;/code&gt;, and in deny/ask only, tool-name globs like &lt;code&gt;mcp__*&lt;/code&gt; (every MCP tool).&lt;/li&gt;
&lt;li&gt;Compound commands are split on &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;, &lt;code&gt;;&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt; and newlines; a deny or ask rule applies if &lt;strong&gt;any&lt;/strong&gt; subcommand matches.&lt;/li&gt;
&lt;li&gt;Limit: a Bash rule matches the command text Claude writes, &lt;strong&gt;not the program&lt;/strong&gt; — &lt;code&gt;Bash(rm *)&lt;/code&gt; stops &lt;code&gt;rm -rf build/&lt;/code&gt; but not &lt;code&gt;/bin/rm -rf build/&lt;/code&gt; or &lt;code&gt;bash -c 'rm -rf build/'&lt;/code&gt;. The docs say it &quot;isn't a security boundary around the program&quot;; pair it with the sandbox.&lt;/li&gt;
&lt;li&gt;View and edit the active rules with &lt;code&gt;/permissions&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;// .claude/settings.json (team) or ~/.claude/settings.json (you)
{
  &quot;permissions&quot;: {
    &quot;allow&quot;: [&quot;Bash(npm run *)&quot;, &quot;Bash(git commit *)&quot;],
    &quot;ask&quot;:   [&quot;Bash(git clean *)&quot;],
    &quot;deny&quot;:  [&quot;Bash(git push *)&quot;, &quot;Read(./.env)&quot;, &quot;Read(./secrets/**)&quot;]
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;What &quot;headless&quot; means:&lt;/strong&gt; running Claude Code with no person at the terminal — &lt;code&gt;claude -p &quot;&amp;lt;prompt&amp;gt;&quot;&lt;/code&gt; (the &lt;code&gt;-p&lt;/code&gt; / &lt;code&gt;--print&lt;/code&gt; flag runs it non-interactively) from a script, cron job or CI pipeline such as GitHub Actions, or the Agent SDK from Python/TypeScript. The docs: a &lt;code&gt;-p&lt;/code&gt; session &quot;shows no workspace trust dialog and no per-server approval prompt&quot;, and it still runs the hooks in the project's &lt;code&gt;.claude/settings.json&lt;/code&gt; and connects the servers in its &lt;code&gt;.mcp.json&lt;/code&gt;, even in a folder you've never trusted. &lt;code&gt;-p&lt;/code&gt; starts in Manual permission mode on every plan.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subagent definitions&lt;/strong&gt; live in &lt;code&gt;.claude/agents/&lt;/code&gt; (fields such as &lt;code&gt;isolation: worktree&lt;/code&gt;, &lt;code&gt;memory&lt;/code&gt;, &lt;code&gt;permissionMode&lt;/code&gt;, &lt;code&gt;disallowedTools&lt;/code&gt; go in the agent file's frontmatter).&lt;/p&gt;
&lt;h3 id=&quot;the-pattern-underneath-all-eleven&quot;&gt;The pattern underneath all eleven&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Nothing errors.&lt;/strong&gt; The ask rule resolves to allow. The headless run loads &lt;code&gt;.mcp.json&lt;/code&gt; unprompted. The typo'd hook exits 127 and the action proceeds. The stdio MCP call keeps waiting. The resumed budget covers only new spend. The cache TTL drops to 5 minutes and the bill doesn't say why. The thing you configured isn't the thing the client enforces — so the discipline that pays off is &lt;strong&gt;verifying the layer that actually enforces&lt;/strong&gt;: canary your &lt;code&gt;ask&lt;/code&gt;/&lt;code&gt;deny&lt;/code&gt; rules, pin &lt;code&gt;permissions.defaultMode&lt;/code&gt;, set &lt;code&gt;MCP_TOOL_TIMEOUT&lt;/code&gt; and cache TTLs explicitly, and watch &lt;code&gt;/usage&lt;/code&gt;, &lt;code&gt;/context&lt;/code&gt;, and &lt;code&gt;claude mcp list&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Pick the three that map to your setup and add a check this week. The one that catches a real incident pays for the afternoon.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;What's bitten you that isn't here? I'm collecting Claude Code gotchas for agentic workflows — reply and I'll add the good ones with credit.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30399/11-claude-code-gotchas-that-quietly-skip-your-guardrails</guid>
<pubDate>Fri, 09 Oct 2026 05:28:57 +0000</pubDate>
</item>
<item>
<title>How to Prevent Algorithmic Bias When Using AI Tools as MCP Connectors</title>
<link>https://coderlegion.com/30068/how-to-prevent-algorithmic-bias-when-using-ai-tools-as-mcp-connectors</link>
<description>&lt;p&gt;As developers shift toward agentic AI architectures, the Model Context Protocol (MCP) has emerged as a groundbreaking standard for connecting LLMs to local data sources, APIs, and development environments. However, hooking a powerful LLM directly into your workflows via an MCP connector introduces a major risk: amplifying algorithmic bias.&lt;/p&gt;
&lt;p&gt;If your underlying model suffers from data skew, or if your context-retrieval pipeline lacks guardrails, your AI assistant will generate biased code, flawed evaluations, or skewed data summaries.&lt;/p&gt;
&lt;p&gt;Here is a practical guide on how to design and configure your MCP connectors to actively mitigate algorithmic bias.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Enforce Structured Input &amp;amp; Output Schemas&lt;br&gt;
Bias thrives in ambiguity. When building an MCP connector tool, do not rely on open-ended text blobs. Instead, establish strict JSON schemas for both incoming requests and outgoing tool results.&lt;br&gt;
• The Fix: Filter out demographic markers or unneeded metadata at the connector layer before transmitting payload data to the model.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement Counter-Stereotypical Context Prompting&lt;br&gt;
When your MCP server injects localized data into the LLM's context window, it can trigger hidden biases within the foundation model.&lt;br&gt;
• The Fix: Hardcode robust system instructions directly into the prompt templates wrapped by your MCP server. Instruct the model to evaluate the context purely on functional logic, ignoring patterns that mimic historical biases.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Establish Multi-Source Data Diversity (Diversified RAG)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If your MCP server queries an internal database or local codebase to feed context to the LLM, a homogenous data source will lead to narrow, biased code recommendations.&lt;br&gt;
• The Fix: Program your MCP connector to pull context from multiple, distinct nodes or repositories. Introduce diverse code repositories or documentation libraries into your retrieval pipeline to ensure varied training references.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Implement Human-in-the-Loop Validation Layers&lt;br&gt;
Never allow an MCP tool to execute high-impact mutations (like direct git commits to production or automated user permission alterations) without manual validation.&lt;br&gt;
• The Fix: Design your MCP connector tools with a strict approval phase. Use intermediate state flags (status: pending_review) so a human operator can review the generated code or decision for bias before deployment.&lt;/li&gt;
&lt;li&gt;Audit MCP Interaction Logs Regularly&lt;br&gt;
Bias mitigation is an ongoing process. You must log inputs, prompt context windows, and output generation samples traversing your MCP server.&lt;br&gt;
• The Fix: Regularly analyze logs using semantic search scripts to flag repeating anomalies, unfair decision patterns, or toxic code constructs generated during model interactions.&lt;br&gt;
Get Started with MCP&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Building unbiased, highly deterministic AI workflows starts with choosing the right protocol framework. Explore open-source implementations, tools, and integration guides on the official &lt;a rel=&quot;nofollow&quot; href=&quot;https://developers.seosiri.com/&quot;&gt;SEOSiri Model Context Protocol Suite&lt;/a&gt; to secure your developer ecosystem today.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30068/how-to-prevent-algorithmic-bias-when-using-ai-tools-as-mcp-connectors</guid>
<pubDate>Wed, 07 Oct 2026 03:44:35 +0000</pubDate>
</item>
<item>
<title>Mi setup de agente barato: OpenCode + DeepSeek por céntimos (feat. IgnicionDev)</title>
<link>https://coderlegion.com/29882/mi-setup-de-agente-barato-opencode-deepseek-por-centimos-feat-igniciondev</link>
<description>&amp;lt;!--
  CoderLegion · Article · Post 00
  Serie: My cheap Setup feat IgnicionDev
  Autor: Ignacio Badenes (@yosoyignicion / IgnicionDev)
  Idioma: bilingüe ES + EN · Read time: ~8 min
  Tags: ai, aiagents, devtools, mcp · Extra: linux, opensource
--&amp;gt;
&lt;h2 id=&quot;mi-setup-de-agente-barato-opencode-deepseek-por-c-ntimos-feat-igniciondev-&quot;&gt;Mi setup de agente barato: OpenCode + DeepSeek por céntimos (feat. IgnicionDev)&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Serie:&lt;/strong&gt; &lt;em&gt;My cheap Setup feat IgnicionDev&lt;/em&gt; — Post 00&lt;br&gt;
&lt;strong&gt;Read time:&lt;/strong&gt; ~8 min · &lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;code&gt;ai&lt;/code&gt; &lt;code&gt;aiagents&lt;/code&gt; &lt;code&gt;devtools&lt;/code&gt; &lt;code&gt;mcp&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;abr-un-agente-que-cuesta-c-ntimos-y-me-devolvi-control-no-ruido&quot;&gt;Abrí un agente que cuesta céntimos y me devolvió control, no ruido&lt;/h3&gt;
&lt;p&gt;La mayoría de la conversación sobre agentes de código empieza por la potencia: el modelo más grande, el benchmark más alto, la demo más vistosa. Mi problema era el contrario. Yo no necesitaba &lt;em&gt;más&lt;/em&gt; inteligencia: necesitaba &lt;strong&gt;algo que costara céntimos, que no inundara la terminal y cuyo resultado pudiera auditar línea a línea&lt;/strong&gt;. Si no puedo leer y ejecutar lo que el agente produce, no me sirve: trabajo con dinero, facturas y datos que deben cuadrar.&lt;/p&gt;
&lt;p&gt;Así que me monté un agente barato —&lt;strong&gt;OpenCode + DeepSeek Flash&lt;/strong&gt;— y lo rodeé de disciplina: memoria persistente, reglas de gasto de tokens, permisos estrictos y verificaciones reales. Este post es el &quot;cómo&quot;, con números, y termina con &lt;strong&gt;diez cosas concretas&lt;/strong&gt; que puedes hacer hoy con un setup así. No es magia; es ingeniería honesta.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;qui-n-escribe-esto&quot;&gt;Quién escribe esto&lt;/h3&gt;
&lt;p&gt;Soy Ignacio Badenes (&lt;strong&gt;IgnicionDev&lt;/strong&gt;), técnico de sistemas e informática aplicada desde Castellón, España. Vengo del soporte y del control de accesos: protocolos, registros, sangre fría cuando algo falla. Ese hábito lo aplico ahora al software que construyo y publico —&lt;strong&gt;Aethernet&lt;/strong&gt; (auditoría WiFi local, 146 tests), &lt;strong&gt;LocalGrant-Finder&lt;/strong&gt; (subvenciones del BOE con búsqueda híbrida), &lt;strong&gt;SystemBridge-AI&lt;/strong&gt; (facturas a libro contable, dinero en &lt;code&gt;Decimal&lt;/code&gt;) y &lt;strong&gt;AssetShrink&lt;/strong&gt; (C++17, imágenes en local)—. Todos con tests, CI y licencia. Si una herramienta no es auditable, no la publico. Con mi agente, igual.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;la-tesis-la-disciplina-sustituye-a-la-potencia&quot;&gt;La tesis: la disciplina sustituye a la potencia&lt;/h3&gt;
&lt;p&gt;Un modelo barato &lt;strong&gt;no&lt;/strong&gt; te obliga a obtener resultados baratos. Te obliga a dejar de improvisar. El truco no está en el modelo: está en &lt;strong&gt;gastar pocos tokens sin perder precisión&lt;/strong&gt;. En DeepSeek Flash el precio se reparte así:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;coste = input_fresco × $0,14/M  +  input_cacheado × $0,0028/M  +  output × $0,28/M
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;El input cacheado cuesta &lt;strong&gt;50 veces menos&lt;/strong&gt; que el fresco, y el output es la partida más cara. Por eso ataqué los tres frentes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;System prompt y herramientas mínimas&lt;/strong&gt; (menos tokens fijos por petición).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Máximo reúso de caché&lt;/strong&gt; (mismo prefijo, sin UUIDs aleatorios que la rompen).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Output controlado&lt;/strong&gt; (respuestas cortas o JSON, nada de párrafos de relleno).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;En mi escenario de trabajo, esto reduce el gasto ~&lt;strong&gt;82 %&lt;/strong&gt;; una vez la caché está caliente, el coste marginal por petición cae a una &lt;strong&gt;fracción de céntimo&lt;/strong&gt;. No es &quot;gratis&quot;, pero se acerca. Y lo importante: sigue siendo correcto porque &lt;strong&gt;yo pongo la disciplina&lt;/strong&gt; donde el modelo no llega.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;el-setup-opencode-deepseek&quot;&gt;El setup: OpenCode + DeepSeek&lt;/h3&gt;
&lt;p&gt;Mi modelo es &lt;code&gt;deepseek/deepseek-v4-flash&lt;/code&gt;, servido por un proveedor compatible con OpenAI y con la caché activada:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsonc&quot;&gt;{
  &quot;model&quot;: &quot;deepseek/deepseek-v4-flash&quot;,
  &quot;provider&quot;: {
    &quot;deepseek&quot;: {
      &quot;npm&quot;: &quot;@ai-sdk/openai-compatible&quot;,
      &quot;options&quot;: { &quot;setCacheKey&quot;: true },
      &quot;models&quot;: {
        &quot;deepseek-v4-flash&quot;: {
          &quot;reasoning&quot;: true,
          &quot;interleaved&quot;: { &quot;field&quot;: &quot;reasoning_content&quot; }
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tres decisiones que marcan la diferencia a lo largo del día:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Compactación automática&lt;/strong&gt; (&lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;prune&lt;/code&gt;, &lt;code&gt;reserved: 5000&lt;/code&gt;): la conversación se poda sola y no arrastro historial gigante.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Límite de salida de herramientas&lt;/strong&gt; (&lt;code&gt;max_lines: 200&lt;/code&gt;, &lt;code&gt;max_bytes: 8192&lt;/code&gt;): un &lt;code&gt;npm install&lt;/code&gt; no me escupe 200 líneas a la cara; si trunca, reejecuto acotado.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Permisos estrictos&lt;/strong&gt; (&lt;code&gt;webfetch: deny&lt;/code&gt;, plan en solo lectura): el agente no navega ni escribe donde no debe sin que yo lo apruebe.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sobre todo esto manda un archivo: mi &lt;strong&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/strong&gt;. No es una lista de deseos, es un &lt;strong&gt;router de trabajo&lt;/strong&gt; con protocolo (entender → planear → cambio pequeño → verificar → revisar), una &lt;em&gt;Definition of Done&lt;/em&gt; honesta (typecheck, tests, lint, diff revisado) y reglas de gasto. El modelo es barato; el criterio no.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;memoria-y-contexto-que-no-repita-lo-que-ya-sabe&quot;&gt;Memoria y contexto: que no repita lo que ya sabe&lt;/h3&gt;
&lt;p&gt;Un agente sin memoria es un becario con amnesia: cada sesión empieza de cero y vuelve a pagar por lo mismo. Yo uso el plugin &lt;strong&gt;&lt;code&gt;engram + zerotoken&lt;/code&gt;&lt;/strong&gt;: memoria tipada en SQLite con &lt;strong&gt;FTS5&lt;/strong&gt;, &lt;strong&gt;auto-guardado&lt;/strong&gt; de errores→solución, decisiones de arquitectura y compactaciones, e &lt;strong&gt;inyección de solo 2 memorias / 600 tokens&lt;/strong&gt; en cada arranque. Traducido: en vez de arrastrar 50 000 tokens de historial, inyecto lo justo.&lt;/p&gt;
&lt;p&gt;A eso le sumo &lt;strong&gt;Context7&lt;/strong&gt;: cuando pregunto por una API o versión concreta, trae la documentación real y &lt;strong&gt;la cacheo como memoria&lt;/strong&gt;. La próxima vez no vuelvo a consultarla ni el modelo la alucina. Documentación viva, cero repetición.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;my-opencode-conf-el-proyecto-privado-que-da-forma-a-todo&quot;&gt;My.OpenCode.Conf: el proyecto privado que da forma a todo&lt;/h3&gt;
&lt;p&gt;Aquí está la pieza que mucha gente no ve. Mi configuración no es un &lt;code&gt;opencode.json&lt;/code&gt; suelto: es un proyecto de GitHub &lt;strong&gt;privado&lt;/strong&gt; llamado &lt;strong&gt;My.OpenCode.Conf&lt;/strong&gt;, parte de mi aprendizaje y mi forma de trabajar. Es un &lt;em&gt;bundle&lt;/em&gt; de &lt;strong&gt;tres subproyectos independientes&lt;/strong&gt; que se hablan por un protocolo abierto (&lt;strong&gt;MCP&lt;/strong&gt;):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Subproyecto &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Qué aporta &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Hecho con&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;code&gt;skill-matrix&lt;/code&gt;&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;+240 skills en formato &lt;code&gt;SKILL.md&lt;/code&gt; (técnicas y de diseño) que el agente carga &lt;strong&gt;bajo demanda&lt;/strong&gt; por triggers &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Markdown&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;code&gt;second-termux-v2&lt;/code&gt;&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Servidor MCP que lanza &lt;strong&gt;jobs en background&lt;/strong&gt; y devuelve &lt;strong&gt;una sola línea&lt;/strong&gt; de estado en vez de inundar la TUI &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;TypeScript (ESM)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;code&gt;engram+zerotoken&lt;/code&gt;&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;El plugin de &lt;strong&gt;memoria persistente&lt;/strong&gt; (FTS5) y la política de ahorro de tokens &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;TypeScript (Bun)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Los une un &lt;strong&gt;prompt maestro&lt;/strong&gt;: en vez de mantener un &lt;code&gt;install.sh&lt;/code&gt; frágil, &lt;em&gt;el propio agente se autoconfigura&lt;/em&gt; (detecta el sistema operativo y adapta los comandos). Y, para mí, lo mejor de su diseño: es &lt;strong&gt;reversible&lt;/strong&gt;. Se desinstala limpio, sin lock-in, sin telemetría y sin tocar lo que ya tenías. El repo es privado por ahora —lo enseño, lo explico y respondo dudas—, pero la lección es pública: &lt;strong&gt;una buena config es código que se puede leer, verificar y deshacer.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;las-herramientas-que-lo-conectan-mcp-y-plugins-&quot;&gt;Las herramientas que lo conectan (MCP y plugins)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;chrome-devtools&lt;/code&gt; (headless)&lt;/strong&gt; — un navegador real que el agente maneja: navegar, extraer, y hacer auditorías &lt;strong&gt;Lighthouse&lt;/strong&gt; sin abrir una ventana.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;github&lt;/code&gt;&lt;/strong&gt; — issues, PRs y acciones desde la propia conversación.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;sqlite&lt;/code&gt;&lt;/strong&gt; — consultas sobre mi base de datos local de trabajo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;context7&lt;/code&gt;&lt;/strong&gt; — documentación de librerías en vivo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;human-followup.ts&lt;/code&gt;&lt;/strong&gt; — plugin propio que usa &lt;code&gt;notify-send&lt;/code&gt;: cuando el agente &lt;strong&gt;pide datos&lt;/strong&gt;, necesita un &lt;strong&gt;permiso&lt;/strong&gt; o &lt;strong&gt;termina&lt;/strong&gt; una navegación, me salta una notificación de escritorio. Puedo dejar de mirar la terminal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subagentes&lt;/strong&gt; (&lt;code&gt;explore&lt;/code&gt;, &lt;code&gt;general&lt;/code&gt;) — para repartir exploración y trabajo pesado sin contaminar mi contexto.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;crear-tu-propio-mcp-para-publicar-sin-salir-del-agente&quot;&gt;Crear tu propio MCP para publicar sin salir del agente&lt;/h3&gt;
&lt;p&gt;El ejemplo más honesto de &quot;herramienta propia&quot; es este mismo post. En vez de copiar y pegar texto en el navegador, escribí un &lt;strong&gt;MCP local&lt;/strong&gt; para Coder Legion en &lt;strong&gt;Node ESM sin dependencias&lt;/strong&gt; (~300 líneas): una conversación &lt;strong&gt;JSON-RPC por stdio&lt;/strong&gt; contra la API REST de la plataforma. El agente lista, busca, comenta y &lt;strong&gt;redacta en borrador&lt;/strong&gt; desde la misma sesión en la que programa.&lt;/p&gt;
&lt;p&gt;Lo interesante no es el camino feliz, son los bordes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;La API no tiene campo &lt;code&gt;draft&lt;/code&gt;.&lt;/strong&gt; El borrador se implementa con &lt;code&gt;POST /posts&lt;/code&gt; seguido de &lt;code&gt;POST /posts/{id}/hide&lt;/code&gt;: el post nace invisible salvo para el autor y los mods. &lt;strong&gt;Publicar es &lt;code&gt;POST /posts/{id}/reshow&lt;/code&gt;.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;El MCP nunca publica solo.&lt;/strong&gt; &lt;code&gt;cl_create_post&lt;/code&gt; valida y crea &lt;strong&gt;siempre oculto&lt;/strong&gt;; si el &lt;code&gt;hide&lt;/code&gt; falla, devuelve el &lt;code&gt;id&lt;/code&gt; y avisa de que el post quedó &lt;strong&gt;público&lt;/strong&gt; para corregirlo de inmediato. La publicación real solo ocurre con &lt;code&gt;cl_publish_post&lt;/code&gt;, y esa llamada la decido yo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Edición incremental.&lt;/strong&gt; &lt;code&gt;cl_edit_post&lt;/code&gt; hace read-modify-write en servidor: &lt;code&gt;append&lt;/code&gt;, &lt;code&gt;prepend&lt;/code&gt;, &lt;code&gt;insert_before&lt;/code&gt;, &lt;code&gt;insert_after&lt;/code&gt; o &lt;code&gt;replace&lt;/code&gt; sobre un &lt;strong&gt;ancla literal&lt;/strong&gt;. Añado una sección sin reenviar 19 KB de markdown, con &lt;code&gt;dry_run&lt;/code&gt; para previsualizar antes de guardar.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Es el patrón que repito en todo: la API hace lo mínimo, el MCP añade la &lt;strong&gt;disciplina&lt;/strong&gt; (draft-first, revisión humana) y el agente se queda con lo mecánico. Si algo no lo puedo auditar o deshacer, no lo automatizo.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;de-la-tui-al-desktop-en-linux-ya-migrado-&quot;&gt;De la TUI al Desktop en Linux (ya migrado)&lt;/h3&gt;
&lt;p&gt;Hasta hace poco corría todo en la &lt;strong&gt;TUI&lt;/strong&gt; (v1.18.34). Acabo de dar el salto a la &lt;strong&gt;versión Desktop&lt;/strong&gt; en &lt;strong&gt;Linux Mint 22.3&lt;/strong&gt;, instalando el &lt;code&gt;.deb&lt;/code&gt; de la release oficial. En Linux no hay cask de Homebrew —eso es solo macOS—; lo correcto aquí son los paquetes de la release (&lt;code&gt;.deb&lt;/code&gt;, &lt;code&gt;.rpm&lt;/code&gt; o &lt;code&gt;.AppImage&lt;/code&gt;). El binario de escritorio registra su lanzador en el menú de aplicaciones, así que paso de &quot;abrir una terminal y teclear&quot; a &quot;abrir una app&quot;. &lt;strong&gt;Misma configuración, misma memoria, mismo agente&lt;/strong&gt;; solo cambia el envoltorio. Si tienes dudas con la instalación en Linux, te lo cuento con detalle en los comentarios.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;diez-cosas-que-mi-agente-barato-hace-hoy&quot;&gt;Diez cosas que mi agente barato hace hoy&lt;/h3&gt;
&lt;p&gt;Ejemplos reales, no humo:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Diagnosticar un repo&lt;/strong&gt;: señalarlo, que reproduzca, minimice y proponga un plan de fallos con la skill &lt;code&gt;diagnose&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escribir tests primero&lt;/strong&gt;: ciclo &lt;em&gt;red-green-refactor&lt;/em&gt; con &lt;code&gt;tdd&lt;/code&gt;, no tests de relleno.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Revisar un diff&lt;/strong&gt;: auditoría en paralelo de estándares y de especificación con &lt;code&gt;review&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auditoría web real&lt;/strong&gt;: levantar el navegador headless y ejecutar un &lt;strong&gt;Lighthouse&lt;/strong&gt; sobre mi página.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consultar docs actualizadas&lt;/strong&gt; con Context7 y &lt;strong&gt;guardarlas en Engram&lt;/strong&gt; para no repetir la consulta.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Recordar un fix entre sesiones&lt;/strong&gt;: &quot;esto ya me falló&quot;, y el error→solución está ahí.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lanzar un build largo en background&lt;/strong&gt; y recibir una sola línea de estado (&lt;code&gt;done&lt;/code&gt;) en vez de 200 líneas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Refactorizar con plan&lt;/strong&gt;: &lt;code&gt;request-refactor-plan&lt;/code&gt; descompone en commits pequeños y seguros.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crear una skill propia&lt;/strong&gt; con &lt;code&gt;write-a-skill&lt;/code&gt; cuando repito un patrón.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delegar exploración&lt;/strong&gt; de un codebase desconocido a un subagente mientras sigo trabajando.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;lo-honesto-qu-gano-y-qu-pierdo&quot;&gt;Lo honesto: qué gano y qué pierdo&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Gano&lt;/strong&gt;: coste de céntimos, memoria que persiste, permisos que respeto, cero telemetría y la tranquilidad de un sistema que puedo auditar y deshacer. &lt;strong&gt;Pierdo&lt;/strong&gt;: techo de razonamiento —un modelo Flash no es un modelo de frontera— y comodidad. Un agente barato &lt;strong&gt;no piensa por ti&lt;/strong&gt;; te obliga a decirle exactamente qué quieres y a verificar el resultado. Para mí, ese intercambio es una ventaja: es la diferencia entre &quot;confío porque lo leí&quot; y &quot;confío porque me lo dijo un modelo caro&quot;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;takeaway&quot;&gt;Takeaway&lt;/h3&gt;
&lt;p&gt;No necesitas el modelo más potente para producir software serio: necesitas &lt;strong&gt;economía de tokens, memoria y disciplina&lt;/strong&gt;. Con un modelo barato bien dirigido, el límite deja de ser el precio y pasa a ser tu criterio.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;¿Y tú? ¿Qué modelo barato usas —o usarías— y cómo compensas sus límites?&lt;/strong&gt; Cuéntamelo en los comentarios; leo y respondo a todo.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;sub&gt;&lt;strong&gt;English version below&lt;/strong&gt; · The original is in Spanish. If you're an English speaker, jump to the translation and let me know your setup in the discussion. I reply to everyone.&lt;/sub&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;h2 id=&quot;my-cheap-setup-running-opencode-deepseek-for-cents-feat-igniciondev-&quot;&gt;My cheap Setup: running OpenCode + DeepSeek for cents (feat. IgnicionDev)&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Series:&lt;/strong&gt; &lt;em&gt;My cheap Setup feat IgnicionDev&lt;/em&gt; — Post 00&lt;br&gt;
&lt;strong&gt;Read time:&lt;/strong&gt; ~8 min · &lt;strong&gt;Tags:&lt;/strong&gt; &lt;code&gt;ai&lt;/code&gt; &lt;code&gt;aiagents&lt;/code&gt; &lt;code&gt;devtools&lt;/code&gt; &lt;code&gt;mcp&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;i-built-an-agent-that-costs-cents-and-gave-me-control-back-not-noise&quot;&gt;I built an agent that costs cents and gave me control back, not noise&lt;/h3&gt;
&lt;p&gt;Most talk about coding agents starts with raw power: the biggest model, the highest benchmark, the flashiest demo. My problem was the opposite. I didn't need &lt;em&gt;more&lt;/em&gt; intelligence — I needed &lt;strong&gt;something that costs cents, doesn't flood my terminal, and produces output I can audit line by line&lt;/strong&gt;. If I can't read and run what the agent produces, it's useless to me: I work with money, invoices and data that has to add up.&lt;/p&gt;
&lt;p&gt;So I built a cheap agent —&lt;strong&gt;OpenCode + DeepSeek Flash&lt;/strong&gt;— and wrapped it in discipline: persistent memory, token-spend rules, strict permissions and real verification. This post is the &quot;how&quot;, with numbers, and it ends with &lt;strong&gt;ten concrete things&lt;/strong&gt; you can do today with a setup like this. No magic; just honest engineering.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;who-s-writing-this&quot;&gt;Who's writing this&lt;/h3&gt;
&lt;p&gt;I'm Ignacio Badenes (&lt;strong&gt;IgnicionDev&lt;/strong&gt;), an IT technician from Castellón, Spain. I come from support and access control: protocols, logs, staying calm when things break. I now apply that habit to the software I build and publish —&lt;strong&gt;Aethernet&lt;/strong&gt; (local WiFi auditing, 146 tests), &lt;strong&gt;LocalGrant-Finder&lt;/strong&gt; (Spanish official-gazette grants with hybrid search), &lt;strong&gt;SystemBridge-AI&lt;/strong&gt; (invoices into a balanced ledger, money as &lt;code&gt;Decimal&lt;/code&gt;) and &lt;strong&gt;AssetShrink&lt;/strong&gt; (C++17, local image processing)—. All with tests, CI and a licence. If a tool isn't auditable, I don't ship it. Same goes for my agent.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-thesis-discipline-replaces-raw-power&quot;&gt;The thesis: discipline replaces raw power&lt;/h3&gt;
&lt;p&gt;A cheap model &lt;strong&gt;doesn't&lt;/strong&gt; force cheap results. It forces you to stop improvising. The trick isn't the model: it's &lt;strong&gt;spending few tokens without losing accuracy&lt;/strong&gt;. With DeepSeek Flash the cost splits like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cost = fresh_input × $0.14/M  +  cached_input × $0.0028/M  +  output × $0.28/M
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cached input is &lt;strong&gt;50× cheaper&lt;/strong&gt; than fresh input, and output is the priciest line. So I attacked all three:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Minimal system prompt and tools&lt;/strong&gt; (fewer fixed tokens per request).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maximum cache reuse&lt;/strong&gt; (same prefix, no random UUIDs to break it).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Controlled output&lt;/strong&gt; (short answers or JSON, no filler paragraphs).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In my working scenario that cuts spend by ~&lt;strong&gt;82%&lt;/strong&gt;; once the cache is warm, marginal cost per request drops to a &lt;strong&gt;fraction of a cent&lt;/strong&gt;. It's not &quot;free&quot;, but it gets close. And it stays correct because &lt;strong&gt;I supply the discipline&lt;/strong&gt; where the model can't.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-setup-opencode-deepseek&quot;&gt;The setup: OpenCode + DeepSeek&lt;/h3&gt;
&lt;p&gt;My model is &lt;code&gt;deepseek/deepseek-v4-flash&lt;/code&gt;, served through an OpenAI-compatible provider with caching enabled:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsonc&quot;&gt;{
  &quot;model&quot;: &quot;deepseek/deepseek-v4-flash&quot;,
  &quot;provider&quot;: {
    &quot;deepseek&quot;: {
      &quot;npm&quot;: &quot;@ai-sdk/openai-compatible&quot;,
      &quot;options&quot;: { &quot;setCacheKey&quot;: true },
      &quot;models&quot;: {
        &quot;deepseek-v4-flash&quot;: {
          &quot;reasoning&quot;: true,
          &quot;interleaved&quot;: { &quot;field&quot;: &quot;reasoning_content&quot; }
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Three decisions that matter all day:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automatic compaction&lt;/strong&gt; (&lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;prune&lt;/code&gt;, &lt;code&gt;reserved: 5000&lt;/code&gt;): the conversation prunes itself; I don't drag a huge history.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool output limits&lt;/strong&gt; (&lt;code&gt;max_lines: 200&lt;/code&gt;, &lt;code&gt;max_bytes: 8192&lt;/code&gt;): an &lt;code&gt;npm install&lt;/code&gt; doesn't dump 200 lines in my face; if it truncates, I re-run it scoped.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strict permissions&lt;/strong&gt; (&lt;code&gt;webfetch: deny&lt;/code&gt;, read-only plan mode): the agent can't browse or write outside its lane without my approval.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Above all of this sits one file: my &lt;strong&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/strong&gt;. It isn't a wish list; it's a &lt;strong&gt;work router&lt;/strong&gt; with a protocol (understand → plan → small change → verify → review), an honest &lt;em&gt;Definition of Done&lt;/em&gt; (typecheck, tests, lint, reviewed diff) and spending rules. The model is cheap; the judgement isn't.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;memory-and-context-stop-repeating-what-it-already-knows&quot;&gt;Memory and context: stop repeating what it already knows&lt;/h3&gt;
&lt;p&gt;An agent without memory is an intern with amnesia: every session starts from zero and pays twice. I use the &lt;strong&gt;&lt;code&gt;engram + zerotoken&lt;/code&gt;&lt;/strong&gt; plugin: typed memory in SQLite with &lt;strong&gt;FTS5&lt;/strong&gt;, &lt;strong&gt;auto-saving&lt;/strong&gt; error→fix, architecture decisions and compactions, and injecting only &lt;strong&gt;2 memories / 600 tokens&lt;/strong&gt; at startup. In short: instead of dragging 50,000 tokens of history, I inject just enough.&lt;/p&gt;
&lt;p&gt;On top of that I add &lt;strong&gt;Context7&lt;/strong&gt;: when I ask about a specific API or version, it pulls the real documentation and &lt;strong&gt;caches it as a memory&lt;/strong&gt;. Next time I don't re-query it and the model doesn't hallucinate it. Live docs, zero repetition.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;my-opencode-conf-the-private-project-that-shapes-it-all&quot;&gt;My.OpenCode.Conf: the private project that shapes it all&lt;/h3&gt;
&lt;p&gt;Here's the part most people miss. My config isn't a loose &lt;code&gt;opencode.json&lt;/code&gt;: it's a &lt;strong&gt;private&lt;/strong&gt; GitHub project called &lt;strong&gt;My.OpenCode.Conf&lt;/strong&gt;, part of my learning and the way I work. It's a bundle of &lt;strong&gt;three independent subprojects&lt;/strong&gt; that talk to each other through an open protocol (&lt;strong&gt;MCP&lt;/strong&gt;):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Subproject &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;What it brings &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Built with&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;code&gt;skill-matrix&lt;/code&gt;&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;240+ skills in &lt;code&gt;SKILL.md&lt;/code&gt; format (technical and design) the agent loads &lt;strong&gt;on demand&lt;/strong&gt; via triggers &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Markdown&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;code&gt;second-termux-v2&lt;/code&gt;&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;An MCP server that runs &lt;strong&gt;background jobs&lt;/strong&gt; and returns &lt;strong&gt;a single status line&lt;/strong&gt; instead of flooding the TUI &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;TypeScript (ESM)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;code&gt;engram+zerotoken&lt;/code&gt;&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;The &lt;strong&gt;persistent-memory&lt;/strong&gt; plugin (FTS5) and the token-saving policy &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;TypeScript (Bun)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A &lt;strong&gt;master prompt&lt;/strong&gt; ties them together: instead of maintaining a fragile &lt;code&gt;install.sh&lt;/code&gt;, &lt;em&gt;the agent configures itself&lt;/em&gt; (detects the OS, adapts commands). And, to me, the best part of its design: it's &lt;strong&gt;reversible&lt;/strong&gt;. It uninstalls cleanly, with no lock-in, no telemetry and without touching what you already had. The repo is private for now —I show it, explain it and answer questions— but the lesson is public: &lt;strong&gt;a good config is code you can read, verify and undo.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-tools-that-wire-it-together-mcp-and-plugins-&quot;&gt;The tools that wire it together (MCP and plugins)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;chrome-devtools&lt;/code&gt; (headless)&lt;/strong&gt; — a real browser the agent drives: navigate, extract, and run &lt;strong&gt;Lighthouse&lt;/strong&gt; audits without opening a window.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;github&lt;/code&gt;&lt;/strong&gt; — issues, PRs and actions from the conversation itself.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;sqlite&lt;/code&gt;&lt;/strong&gt; — queries against my local work database.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;context7&lt;/code&gt;&lt;/strong&gt; — live library documentation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;human-followup.ts&lt;/code&gt;&lt;/strong&gt; — my own plugin using &lt;code&gt;notify-send&lt;/code&gt;: when the agent &lt;strong&gt;asks for input&lt;/strong&gt;, needs a &lt;strong&gt;permission&lt;/strong&gt;, or &lt;strong&gt;finishes&lt;/strong&gt; a navigation, I get a desktop notification. I can stop staring at the terminal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subagents&lt;/strong&gt; (&lt;code&gt;explore&lt;/code&gt;, &lt;code&gt;general&lt;/code&gt;) — to split exploration and heavy work without polluting my context.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;building-your-own-mcp-to-publish-without-leaving-the-agent&quot;&gt;Building your own MCP to publish without leaving the agent&lt;/h3&gt;
&lt;p&gt;The most honest example of a &quot;tool of my own&quot; is this very post. Instead of copy-pasting into a browser, I wrote a &lt;strong&gt;local MCP&lt;/strong&gt; for Coder Legion in &lt;strong&gt;dependency-free Node ESM&lt;/strong&gt; (~300 lines): a &lt;strong&gt;JSON-RPC conversation over stdio&lt;/strong&gt; against the platform's REST API. The agent lists, searches, comments and &lt;strong&gt;drafts&lt;/strong&gt; from the same session where it codes.&lt;/p&gt;
&lt;p&gt;What's interesting isn't the happy path, it's the edges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The API has no &lt;code&gt;draft&lt;/code&gt; field.&lt;/strong&gt; The draft is implemented with &lt;code&gt;POST /posts&lt;/code&gt; followed by &lt;code&gt;POST /posts/{id}/hide&lt;/code&gt;: the post is born invisible to everyone but the author and mods. &lt;strong&gt;Publishing is &lt;code&gt;POST /posts/{id}/reshow&lt;/code&gt;.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The MCP never publishes on its own.&lt;/strong&gt; &lt;code&gt;cl_create_post&lt;/code&gt; validates and creates &lt;strong&gt;always hidden&lt;/strong&gt;; if the &lt;code&gt;hide&lt;/code&gt; fails it returns the &lt;code&gt;id&lt;/code&gt; and warns that the post went &lt;strong&gt;public&lt;/strong&gt; so I fix it immediately. The real publish only happens through &lt;code&gt;cl_publish_post&lt;/code&gt;, and that call is mine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incremental editing.&lt;/strong&gt; &lt;code&gt;cl_edit_post&lt;/code&gt; does a server-side read-modify-write: &lt;code&gt;append&lt;/code&gt;, &lt;code&gt;prepend&lt;/code&gt;, &lt;code&gt;insert_before&lt;/code&gt;, &lt;code&gt;insert_after&lt;/code&gt; or &lt;code&gt;replace&lt;/code&gt; against a &lt;strong&gt;literal anchor&lt;/strong&gt;. I add a section without resending 19 KB of markdown, with &lt;code&gt;dry_run&lt;/code&gt; to preview before saving.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It's the pattern I keep repeating: the API does the bare minimum, the MCP adds the &lt;strong&gt;discipline&lt;/strong&gt; (draft-first, human review) and the agent keeps the mechanical part. If I can't audit or undo it, I don't automate it.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;from-tui-to-desktop-on-linux-already-migrated-&quot;&gt;From TUI to Desktop on Linux (already migrated)&lt;/h3&gt;
&lt;p&gt;Until recently I ran everything in the &lt;strong&gt;TUI&lt;/strong&gt; (v1.18.34). I've just moved to the &lt;strong&gt;Desktop&lt;/strong&gt; version on &lt;strong&gt;Linux Mint 22.3&lt;/strong&gt;, installing the official release &lt;code&gt;.deb&lt;/code&gt;. There's no Homebrew cask on Linux —that's macOS only—; here the right choice is the release packages (&lt;code&gt;.deb&lt;/code&gt;, &lt;code&gt;.rpm&lt;/code&gt; or &lt;code&gt;.AppImage&lt;/code&gt;). The desktop binary registers its launcher in the application menu, so I go from &quot;open a terminal and type&quot; to &quot;open an app&quot;. &lt;strong&gt;Same config, same memory, same agent&lt;/strong&gt;; only the wrapper changes. If you're stuck installing it on Linux, I'll walk you through it in the comments.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;ten-things-my-cheap-agent-does-today&quot;&gt;Ten things my cheap agent does today&lt;/h3&gt;
&lt;p&gt;Real examples, no hype:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Diagnose a repo&lt;/strong&gt;: point at it, and it reproduces, minimises and proposes a fix plan using the &lt;code&gt;diagnose&lt;/code&gt; skill.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write tests first&lt;/strong&gt;: &lt;em&gt;red-green-refactor&lt;/em&gt; with &lt;code&gt;tdd&lt;/code&gt;, not filler tests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Review a diff&lt;/strong&gt;: a parallel audit of standards and spec with &lt;code&gt;review&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real web audit&lt;/strong&gt;: spin up the headless browser and run &lt;strong&gt;Lighthouse&lt;/strong&gt; on my site.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pull up-to-date docs&lt;/strong&gt; with Context7 and &lt;strong&gt;store them in Engram&lt;/strong&gt; so the query isn't repeated.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remember a fix across sessions&lt;/strong&gt;: &quot;this broke before&quot;, and the error→fix is there.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Run a long build in the background&lt;/strong&gt; and get a single &lt;code&gt;done&lt;/code&gt; status line instead of 200.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Refactor with a plan&lt;/strong&gt;: &lt;code&gt;request-refactor-plan&lt;/code&gt; breaks it into small, safe commits.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create its own skill&lt;/strong&gt; with &lt;code&gt;write-a-skill&lt;/code&gt; when I repeat a pattern.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delegate exploration&lt;/strong&gt; of an unknown codebase to a subagent while I keep working.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-honest-part-what-i-gain-and-what-i-lose&quot;&gt;The honest part: what I gain and what I lose&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;I gain&lt;/strong&gt;: cents-level cost, memory that persists, permissions I respect, zero telemetry, and the peace of mind of a system I can audit and undo. &lt;strong&gt;I lose&lt;/strong&gt;: a reasoning ceiling —a Flash model isn't a frontier model— and convenience. A cheap agent &lt;strong&gt;doesn't think for you&lt;/strong&gt;; it forces you to say exactly what you want and to verify the result. To me, that trade is an advantage: it's the difference between &quot;I trust it because I read it&quot; and &quot;I trust it because an expensive model said so&quot;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;takeaway-1&quot;&gt;Takeaway&lt;/h3&gt;
&lt;p&gt;You don't need the most powerful model to produce serious software: you need &lt;strong&gt;token economy, memory and discipline&lt;/strong&gt;. With a cheap model well directed, the limit stops being the price and becomes your judgement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So what about you? Which cheap model do you use —or would you use— and how do you compensate for its limits?&lt;/strong&gt; Tell me in the comments; I read and reply to everyone.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;sub&gt;Licencia de los proyectos mencionados: MIT · Sin secretos ni claves en este post. · Proyectos: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/yosoyignicion&quot;&gt;github.com/yosoyignicion&lt;/a&gt;&lt;/sub&gt;&lt;/p&gt;
</description>
<category>Discussions</category>
<guid isPermaLink="true">https://coderlegion.com/29882/mi-setup-de-agente-barato-opencode-deepseek-por-centimos-feat-igniciondev</guid>
<pubDate>Mon, 05 Oct 2026 15:40:22 +0000</pubDate>
</item>
<item>
<title>CodeSage: Code Intelligence for AI Agents, and Why I Rebuilt Its Models</title>
<link>https://coderlegion.com/29515/codesage-code-intelligence-for-ai-agents-and-why-i-rebuilt-its-models</link>
<description>&lt;p&gt;Until this week, &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/iliaal/codesage&quot;&gt;CodeSage&lt;/a&gt; ran its two models exactly as they ship on Hugging Face: Jina's code embedder and the ms-marco MiniLM reranker. A full index of php-src took 1,782 seconds, just under half an hour, and I got tired of waiting.&lt;/p&gt;
&lt;p&gt;CodeSage 0.38 does the same full index in 373 seconds. Nothing was retrained. The weights are the same weights; what changed is the inference graph around them, a few things in the chunker, and one SQLite query that had been quietly eating most of the run. The two rebuilt models are now public on Hugging Face, along with the scripts that produce them byte-for-byte.&lt;/p&gt;
&lt;h3 id=&quot;what-codesage-gives-an-agent&quot;&gt;What CodeSage gives an agent&lt;/h3&gt;
&lt;p&gt;CodeSage is a code intelligence engine for AI coding agents: a structural graph (symbols, references, dependencies) plus semantic search (embedding retrieval with cross-encoder reranking), in one Rust binary that works as a CLI or an MCP server. An agent asks it questions grep can't answer, like &quot;what depends on this class&quot; or &quot;where does session handling happen&quot;, and gets file-and-line answers from an index instead of guesses from a context window.&lt;/p&gt;
&lt;p&gt;Parsing is tree-sitter, covering PHP, Python, C, C++, Java, Rust, JavaScript, TypeScript and Go. Each project gets one SQLite database at &lt;code&gt;.codesage/index.db&lt;/code&gt;, with sqlite-vec for KNN and FTS5 for literal matches. The MCP side is a stdio shim that starts or reuses a per-user daemon over a Unix socket, so concurrent agent sessions share one project cache, one model pool and one CUDA context. There is no HTTP listener.&lt;/p&gt;
&lt;p&gt;The MCP server exposes 22 tools. The ones agents lean on most:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;find_symbol&lt;/code&gt;, &lt;code&gt;find_references&lt;/code&gt;, &lt;code&gt;trace_call_path&lt;/code&gt;: where something is defined, who calls it, and the shortest call chain between two symbols.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;impact_analysis&lt;/code&gt;, &lt;code&gt;assess_risk&lt;/code&gt;: what a change to this file can break, scored from the graph plus git history.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;search&lt;/code&gt;: natural-language retrieval over ~50-line chunks, reranked.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;from_trace&lt;/code&gt;: maps a pasted stack trace or ASan report (Python, PHP with Xdebug, Rust, Java, Go, Node, gdb) onto indexed symbols.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;edit_check&lt;/code&gt;: diffs a proposed declaration against HEAD before the agent writes the file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The graph is only as useful as its recall. In August, &lt;code&gt;impact_analysis&lt;/code&gt; reported that &lt;code&gt;AxiosError&lt;/code&gt; in axios had 0 dependents. It has 23. File-path imports like &lt;code&gt;./core/AxiosError.js&lt;/code&gt; never resolved; only Rust-style &lt;code&gt;::&lt;/code&gt; paths did. Fixing that, and counting &lt;code&gt;Foo.staticMethod()&lt;/code&gt; and &lt;code&gt;x instanceof Foo&lt;/code&gt; as usage, took mean dependent recall on axios from 0.37 to 0.66 at precision 0.85. An agent told &quot;0 dependents&quot; by a tool it trusts goes ahead and changes the class.&lt;/p&gt;
&lt;h3 id=&quot;the-index-has-to-keep-up-with-the-code&quot;&gt;The index has to keep up with the code&lt;/h3&gt;
&lt;p&gt;An index that lags the code feeds the agent stale answers with full confidence, so CodeSage re-indexes from git hooks on every commit, checkout and merge. That puts the indexer's fixed cost on the hot path dozens of times a day, which is why a lot of the work across 46 releases since April has gone into cost rather than features.&lt;/p&gt;
&lt;p&gt;The per-commit path got there first. In 0.23.0, a no-change incremental run stopped loading the ONNX model and mapping a CUDA context before checking whether any file had changed:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;No-change incremental &lt;code&gt;codesage index&lt;/code&gt; &lt;/th&gt;&lt;th&gt;Time &lt;/th&gt;&lt;th&gt;Peak memory&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0.22.0 &lt;/td&gt;&lt;td&gt;2.7-4.5 s &lt;/td&gt;&lt;td&gt;1.16 GB&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.23.0 &lt;/td&gt;&lt;td&gt;0.08 s &lt;/td&gt;&lt;td&gt;150 MB&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The file watcher re-embeds only chunks whose text changed: an 8-save burst marks 90 chunks dirty and embeds 1.&lt;/p&gt;
&lt;p&gt;That leaves the full index, which nobody runs on every commit but everybody runs eventually: first onboarding, a model change, a chunker change. 0.38 itself forces one, because the embedder now reads up to 1,024 tokens per chunk instead of 512. When the full run takes half an hour on a large repo, people postpone it, and a postponed re-index is a stale index.&lt;/p&gt;
&lt;h3 id=&quot;same-weights-rebuilt-graphs&quot;&gt;Same weights, rebuilt graphs&lt;/h3&gt;
&lt;p&gt;The embedder was slow because of how it was exported, not because of what it computes. The upstream Jina v2 ONNX file is a decomposed opset-11 export. Its attention uses ALiBi plus a QK LayerNorm, a combination ONNX Runtime's transformer optimizer doesn't recognize, so nothing fuses. Every layer materializes the full &lt;code&gt;[batch, 12, seq, seq]&lt;/code&gt; score tensor several times over, and because the graph outputs per-token hidden states, every batch copies a &lt;code&gt;[batch, seq, 768]&lt;/code&gt; tensor from the GPU back to the host just so the caller can average it.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://huggingface.co/IA0x00/jina-embeddings-v2-base-code-codesage&quot;&gt;IA0x00/jina-embeddings-v2-base-code-codesage&lt;/a&gt; carries two graphs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;onnx/model.onnx&lt;/code&gt; (fp32, every execution provider): masked mean pooling and L2 normalization folded into the graph, so the output is the 768-dimension sentence embedding and nothing else crosses back to the host.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;onnx/model_cuda_fp16.onnx&lt;/code&gt; (CUDA only): the same pooling, plus attention fused by hand into &lt;code&gt;com.microsoft&lt;/code&gt; &lt;code&gt;MultiHeadAttention&lt;/code&gt;, with ALiBi and the key-padding mask passed as &lt;code&gt;attention_bias&lt;/code&gt;. Weights are fp16; the output stays fp32.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One fp16 detail: the attention mask filled padded positions with &lt;code&gt;-FLT_MAX&lt;/code&gt;, which overflows fp16. It's &lt;code&gt;-10000.0&lt;/code&gt; now, which is still negative enough to zero those positions after softmax.&lt;/p&gt;
&lt;p&gt;Measured on an RTX 4080 Laptop GPU with ONNX Runtime 1.24.4, 2,048 real chunks per corpus of up to 512 tokens each, compared against upstream fp32 with pooling done on the host:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Corpus &lt;/th&gt;&lt;th&gt;Upstream fp32 &lt;/th&gt;&lt;th&gt;Pooled fp32 &lt;/th&gt;&lt;th&gt;Fused fp16 &lt;/th&gt;&lt;th&gt;Min cosine (fp16) &lt;/th&gt;&lt;th&gt;Top-10 neighbour overlap&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;php-src (C) &lt;/td&gt;&lt;td&gt;59.7 chunks/s &lt;/td&gt;&lt;td&gt;89 &lt;/td&gt;&lt;td&gt;249-257 &lt;/td&gt;&lt;td&gt;0.99999 &lt;/td&gt;&lt;td&gt;0.994&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Laravel app (PHP) &lt;/td&gt;&lt;td&gt;67.2 &lt;/td&gt;&lt;td&gt;113 &lt;/td&gt;&lt;td&gt;301-317 &lt;/td&gt;&lt;td&gt;0.999996 &lt;/td&gt;&lt;td&gt;0.996&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;React app (TS/JS) &lt;/td&gt;&lt;td&gt;69.8 &lt;/td&gt;&lt;td&gt;109 &lt;/td&gt;&lt;td&gt;296-317 &lt;/td&gt;&lt;td&gt;0.999995 &lt;/td&gt;&lt;td&gt;0.997&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A minimum cosine of 0.99999 across 2,048 chunks means the vectors are, for retrieval purposes, the same vectors. Those throughput figures are at the 512-token cap; CodeSage now runs Jina at 1,024, because real C in php-src runs a median of 611 tokens per 1,500-byte chunk and the old cap truncated more than half of them. So the production per-chunk rate is lower than this table, and the chunks carry more of the code.&lt;/p&gt;
&lt;p&gt;The reranker needed far less. &lt;a rel=&quot;nofollow&quot; href=&quot;https://huggingface.co/IA0x00/ms-marco-MiniLM-L6-v2-codesage&quot;&gt;IA0x00/ms-marco-MiniLM-L6-v2-codesage&lt;/a&gt; is a standard BERT, so ONNX Runtime's stock optimizer fuses it (embedding LayerNorm, six Attention nodes, skip LayerNorm, bias GELU) and the work was mostly converting to fp16. Scoring 50 (query, chunk) candidates went from a median 108.0 ms per query to 20.6 ms, with the same top result on 40 of 40 test queries, top-10 overlap of 0.9975, and a maximum logit change of 0.024.&lt;/p&gt;
&lt;p&gt;Both repositories are Apache-2.0, the upstream license, and the weights are unchanged apart from precision. CodeSage pins each one by Hugging Face commit and by the sha256 of every graph and tokenizer it loads, and &lt;code&gt;scripts/derive-jina-onnx.py&lt;/code&gt; and &lt;code&gt;scripts/derive-reranker-onnx.py&lt;/code&gt; in the CodeSage repo download the pinned upstream files, verify them, and write the published files byte-for-byte. You don't have to trust my upload; you can rebuild it. Your &lt;code&gt;config.toml&lt;/code&gt; keeps the upstream model names, and the pin table maps them to the derived repos, so there is nothing to change on upgrade.&lt;/p&gt;
&lt;h3 id=&quot;the-biggest-single-win-wasn-t-a-model&quot;&gt;The biggest single win wasn't a model&lt;/h3&gt;
&lt;p&gt;Most of the half hour was SQLite. When a file changes, its old chunks are deleted first, and &lt;code&gt;file_path&lt;/code&gt; lived in an auxiliary column of the sqlite-vec table and an &lt;code&gt;UNINDEXED&lt;/code&gt; column of the FTS5 table. Neither can be searched by index, so &lt;code&gt;DELETE ... WHERE file_path = ?&lt;/code&gt; scanned both tables for every file: about one second per file at php-src's 54,000 rows, roughly 20 of the 28 minutes a full index took when I measured it.&lt;/p&gt;
&lt;p&gt;The fix is a small sidecar table, &lt;code&gt;&amp;lt;chunk_table&amp;gt;_paths(id, file_path)&lt;/code&gt;, kept in step on every insert and delete and rebuilt if it goes missing or diverges. Deletes now resolve the path to rowids and remove by rowid: 3.2 ms per file.&lt;/p&gt;
&lt;p&gt;Two chunker changes ship in the same release. Chunks that are mostly digits and commas (lookup tables, timezone and Unicode data) are no longer embedded, since no natural-language query is looking for them, and batches are length-sorted and byte-bounded so a batch of short chunks isn't padded out to the length of its longest member.&lt;/p&gt;
&lt;p&gt;Before and after, all of it together:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;&lt;code&gt;codesage index --full&lt;/code&gt; &lt;/th&gt;&lt;th&gt;Before &lt;/th&gt;&lt;th&gt;0.38&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;php-src &lt;/td&gt;&lt;td&gt;1,782 s &lt;/td&gt;&lt;td&gt;373 s&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;private mobile backend &lt;/td&gt;&lt;td&gt;469 s &lt;/td&gt;&lt;td&gt;80 s&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;private frontend app &lt;/td&gt;&lt;td&gt;295 s &lt;/td&gt;&lt;td&gt;60 s&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;That is the combined effect of the fused fp16 graph, the 1,024-token cap, the dropped data chunks, the batching, and the delete fix. I don't have a clean per-change split beyond the delete scan's own estimate, so I'm not going to invent one. Retrieval held: recall@10 is unchanged on three private eval corpora and rose from 0.765 to 0.790 on a php-src session corpus.&lt;/p&gt;
&lt;h3 id=&quot;scores-that-say-what-they-measured&quot;&gt;Scores that say what they measured&lt;/h3&gt;
&lt;p&gt;Fast answers are worthless if the agent can't tell a measurement from a default, so several releases since August went into making CodeSage say what it didn't check. &lt;code&gt;impact_analysis&lt;/code&gt; reports a lower bound, because dynamic calls and unresolved imports can hide real dependents. &lt;code&gt;assess_risk&lt;/code&gt; returns &lt;code&gt;unscored&lt;/code&gt; for a file with no indexed git history instead of a low number. &lt;code&gt;find_references&lt;/code&gt; marks a count as a floor when the symbol name is ambiguous. An empty search result carries indexed-file counts per language, so &quot;not found&quot; and &quot;never indexed&quot; stop looking identical.&lt;/p&gt;
&lt;p&gt;The same rule applies to my own benchmarks. In August I withdrew a published retrieval number (recall@10 0.932, NDCG@10 0.788 over 602 queries) after finding the harness had indexed whole repos instead of each benchmark's root and scored crashed queries as 0.000. The replacement table in the README runs 663 queries across 33 repos in 9 languages, reports per-language NDCG@10 from 0.7455 (C) to 0.9434 (JavaScript), and says it was measured on a modified 0.27.0 build. It hasn't been re-run on 0.38 yet.&lt;/p&gt;
&lt;h3 id=&quot;where-it-falls-short&quot;&gt;Where it falls short&lt;/h3&gt;
&lt;p&gt;These are the limits I know about, all of them in the README:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nine languages. On the public benchmark, 47% of queries are in languages CodeSage doesn't parse (Ruby, Kotlin, Swift, Scala) and get no recall at all.&lt;/li&gt;
&lt;li&gt;Agents don't reach for it on their own. With CodeSage and &lt;code&gt;Grep&lt;/code&gt; both available in Claude Code, agents picked CodeSage on code-identifier queries 1.1% of the time over 30 days of sessions, and 0 of 10 on a controlled harness (measured in April, not re-measured since). That is why the &lt;code&gt;codesage-tools&lt;/code&gt; Claude Code plugin serves a &lt;code&gt;codesage brief&lt;/code&gt; inline before an Edit or Write in an onboarded project instead of waiting to be asked. It stays silent when there is nothing worth saying.&lt;/li&gt;
&lt;li&gt;Every speed number in this post is CUDA. CPU and Apple's CoreML get the pooled fp32 graph but not the fused fp16 one, and I haven't measured the CPU side.&lt;/li&gt;
&lt;li&gt;No prebuilt binaries and no documented Windows support. You build it with cargo.&lt;/li&gt;
&lt;li&gt;Read-only. It doesn't edit code and doesn't query across repositories.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;try-it-1&quot;&gt;Try it&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;cargo build --release -p codesage --features cuda   # drop --features cuda for CPU / CoreML
cd /path/to/your/project
codesage init
codesage index
codesage install-hooks
claude mcp add --scope user codesage -- codesage mcp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Codex users run &lt;code&gt;codesage install codex --global&lt;/code&gt; instead of the last line. If you're on Claude Code, &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/iliaal/whetstone&quot;&gt;whetstone&lt;/a&gt; is the other half: CodeSage tells the agent what the code is, whetstone covers how to investigate, review and ship. The first index downloads the models: about 370 MB on CUDA, about 736 MB for the fp32 graphs on CPU or CoreML.&lt;/p&gt;
&lt;p&gt;Nothing about CodeSage 0.38 required a better model. It required looking at what the existing one did between input and output, and at what the database did on every file delete. Most of that half hour was overhead around the model, not the model itself.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/iliaal/codesage&quot;&gt;github.com/iliaal/codesage&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29515/codesage-code-intelligence-for-ai-agents-and-why-i-rebuilt-its-models</guid>
<pubDate>Fri, 02 Oct 2026 11:25:42 +0000</pubDate>
</item>
<item>
<title>Your coding assistant can now run a real SEO engine instead of guessing at one</title>
<link>https://coderlegion.com/29514/your-coding-assistant-can-now-run-a-real-seo-engine-instead-of-guessing-at-one</link>
<description>&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/fvkcfynvgihpjwq1lolj.png&quot; alt=&quot;Image description&quot;&gt;&lt;/p&gt;
&lt;p&gt;Ask an AI assistant whether a page has SEO problems and you get an answer that reads well and cannot be checked. It might catch the missing canonical tag. It might invent a rule that does not exist. It might tell you the title is fine when there is no title. You have no way to tell which happened without knowing the answer already.&lt;/p&gt;
&lt;p&gt;SEOCode now ships an MCP server, so the assistant stops answering from memory and starts calling the engine. Same rule engine that runs in our CLI and in our GitHub App PR review. It runs locally, on the file you point it at, and the model only formats what comes back.&lt;/p&gt;
&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;/h3&gt;
&lt;p&gt;One config block:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;mcpServers&quot;: {
    &quot;seocode&quot;: {
      &quot;command&quot;: &quot;npx&quot;,
      &quot;args&quot;: [&quot;-y&quot;, &quot;-p&quot;, &quot;@qobi/seocode&quot;, &quot;seocode-mcp&quot;]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That goes in Claude Desktop's &lt;code&gt;claude_desktop_config.json&lt;/code&gt;, Cursor's MCP settings, or &lt;code&gt;.mcp.json&lt;/code&gt; for Claude Code. Node 20 or newer. No account, no API key, no project setup.&lt;/p&gt;
&lt;p&gt;The client launches &lt;code&gt;seocode-mcp&lt;/code&gt; as a local child process and talks to it over stdio. Nothing is uploaded, and there is no network call in the audit path at all.&lt;/p&gt;
&lt;h3 id=&quot;what-it-looks-like&quot;&gt;What it looks like&lt;/h3&gt;
&lt;p&gt;You ask your assistant to check a file. It calls &lt;code&gt;audit_file&lt;/code&gt; and gets back something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;**app/products/[slug]/page.tsx** - 1 critical · 6 warning · 7 info

###  Critical
- **geo-ssr-hydration** - Critical metadata is set inside a useEffect hook, so it
  only exists after JavaScript runs on the client. AI crawlers process the
  server-rendered HTML first, so they never see it.
  - Fix: Move it into the Next.js Metadata API, export const metadata or
    export async function generateMetadata().

###  Warning
- **title-too-short**:6 - Title tags under 30 characters miss keyword opportunities.
  - Fix: Expand the title to at least 30 characters. Current: 24 chars.
- **missing-og-image** - Social shares with no og:image show no preview image.
  - Fix: Add &amp;lt;meta property=&quot;og:image&quot; content=&quot;...&quot; /&amp;gt; inside &amp;lt;head&amp;gt;.
    Recommended size 1200x630.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every finding carries the rule id, the line where it can be pinned, and the fix. Then you say &quot;fix the lazy loading one&quot; and the assistant calls &lt;code&gt;suggest_fix&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;**1-click fix for `image-missing-lazy-loading`** in `public/gallery.html` (line 11):

  &amp;lt;img loading=&quot;lazy&quot; src=&quot;/big-photo.jpg&quot; alt=&quot;A large decorative photo of the skyline&quot; /&amp;gt;

This is a deterministic replacement - apply it directly.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That replacement is not written by the model. The engine produced it, then applied it against the current file to confirm it lands cleanly before handing it over.&lt;/p&gt;
&lt;h3 id=&quot;the-two-tools&quot;&gt;The two tools&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Tool &lt;/th&gt;&lt;th&gt;Arguments &lt;/th&gt;&lt;th&gt;Returns&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;audit_file&lt;/code&gt; &lt;/td&gt;&lt;td&gt;&lt;code&gt;filePath&lt;/code&gt; required, &lt;code&gt;content&lt;/code&gt; optional for an unsaved buffer &lt;/td&gt;&lt;td&gt;Findings grouped by severity, each with rule id, line, and fix&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;suggest_fix&lt;/code&gt; &lt;/td&gt;&lt;td&gt;&lt;code&gt;filePath&lt;/code&gt;, &lt;code&gt;ruleId&lt;/code&gt; required, &lt;code&gt;line&lt;/code&gt; optional &lt;/td&gt;&lt;td&gt;A deterministic code replacement, or written guidance when the rule has no safe rewrite&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;suggest_fix&lt;/code&gt; will tell you when a rule has no auto-fix rather than producing one. Only transforms that can be made with certainty, like adding &lt;code&gt;loading=&quot;lazy&quot;&lt;/code&gt; or &lt;code&gt;rel=&quot;noopener noreferrer&quot;&lt;/code&gt;, come back as replacements. Everything else comes back as guidance, labelled as guidance.&lt;/p&gt;
&lt;h3 id=&quot;why-a-tool-call-beats-a-prompt&quot;&gt;Why a tool call beats a prompt&lt;/h3&gt;
&lt;p&gt;The split matters more than it sounds. The engine does the SEO logic deterministically. The model is the interface: it decides which file you meant and reads the result back to you. The checks themselves cannot drift, cannot hallucinate a rule, and cannot be argued into a different answer on the second ask.&lt;/p&gt;
&lt;p&gt;It is also the same engine, not a simplified copy. The MCP server loads the same &lt;code&gt;rules/seo-rules.json&lt;/code&gt; the CLI and the GitHub App load, so a file that passes in your editor passes in the PR.&lt;/p&gt;
&lt;p&gt;Two things it inherits from that engine:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Framework awareness.&lt;/strong&gt; It reads titles and descriptions through Next.js &lt;code&gt;generateMetadata()&lt;/code&gt;, Remix &lt;code&gt;meta()&lt;/code&gt;, and Astro frontmatter the way the framework actually renders them. A page whose title comes from &lt;code&gt;generateMetadata&lt;/code&gt; is not reported as missing a title. This is the part that makes the difference between a checker you keep and one you turn off after a day.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Your config.&lt;/strong&gt; It walks up from the audited file looking for &lt;code&gt;.seocode.json&lt;/code&gt; and honors the rule disables and severity overrides it finds there. The same file your team already committed for the CLI and the PR review.&lt;/p&gt;
&lt;h3 id=&quot;what-it-does-not-do&quot;&gt;What it does not do&lt;/h3&gt;
&lt;p&gt;It audits the file you point it at, when you ask. It does not scan your repo, track history, hold team config, or gate anything.&lt;/p&gt;
&lt;p&gt;That is deliberate. One file on demand is the right scope for an editor. Enforcing the same rules on every pull request, for everyone on the team, without anyone remembering to ask, is a different job and that is what the GitHub App does.&lt;/p&gt;
&lt;h3 id=&quot;how-it-is-built&quot;&gt;How it is built&lt;/h3&gt;
&lt;p&gt;MCP is a smaller protocol than the tooling around it suggests. The whole server is about 260 lines with no SDK and no dependencies beyond what the engine already uses.&lt;/p&gt;
&lt;p&gt;MCP over stdio is newline-delimited JSON-RPC 2.0. The client writes one JSON object per line to your process's stdin, you write one JSON object per line back to stdout. That is the entire transport. Four methods carry a tools-only server:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;switch (method) {
  case 'initialize':
    return result(id, {
      protocolVersion: params?.protocolVersion || '2025-06-18',
      capabilities: { tools: {} },
      serverInfo: { name: 'seocode-mcp', version: version() },
    });
  case 'ping':
    return result(id, {});
  case 'tools/list':
    return result(id, { tools: TOOLS });
  case 'tools/call': {
    const text = await callTool(params.name, params.arguments ?? {});
    return result(id, { content: [{ type: 'text', text }] });
  }
  default:
    return error(id, -32601, `Method not found: ${method}`);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Three details worth knowing if you write one of these:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;stdout belongs to the protocol.&lt;/strong&gt; One stray &lt;code&gt;console.log&lt;/code&gt; and the client sees a malformed message. All logging goes to stderr, including the startup banner.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Notifications get no reply.&lt;/strong&gt; A message with no &lt;code&gt;id&lt;/code&gt; is a notification. Answering it is a protocol error.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Buffer by newline, not by chunk.&lt;/strong&gt; A single stdin chunk can hold two messages or half of one, so you accumulate and split on &lt;code&gt;\n&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Because it is plain JSON-RPC on stdio, you can drive it without any client at all:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;printf '%s\n' \
  '{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;id&quot;:1,&quot;method&quot;:&quot;initialize&quot;,&quot;params&quot;:{&quot;protocolVersion&quot;:&quot;2025-06-18&quot;}}' \
  '{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;id&quot;:2,&quot;method&quot;:&quot;tools/list&quot;}' \
  | npx -y -p @qobi/seocode seocode-mcp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is also the fastest way to debug a server the client says is failing to start.&lt;/p&gt;
&lt;h3 id=&quot;try-it-2&quot;&gt;Try it&lt;/h3&gt;
&lt;p&gt;The MCP server is free and needs no account. Setup and troubleshooting live at &lt;a rel=&quot;nofollow&quot; href=&quot;https://seocode.io/mcp&quot;&gt;seocode.io/mcp&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want the same rules enforced on every pull request instead of only when someone asks, the GitHub App is free for public repositories: &lt;a rel=&quot;nofollow&quot; href=&quot;https://seocode.io&quot;&gt;seocode.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And if you only want to know whether you are blocking AI crawlers right now, the robots.txt checker at &lt;a rel=&quot;nofollow&quot; href=&quot;https://seocode.io/crawlers&quot;&gt;seocode.io/crawlers&lt;/a&gt; answers in a second with no signup.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29514/your-coding-assistant-can-now-run-a-real-seo-engine-instead-of-guessing-at-one</guid>
<pubDate>Fri, 02 Oct 2026 11:23:53 +0000</pubDate>
</item>
<item>
<title>Why the Enterprise Demands VPC for MCP: Deep Dive into SEOSiri’s Isolated AI Security Blueprint</title>
<link>https://coderlegion.com/29368/why-the-enterprise-demands-vpc-for-mcp-deep-dive-into-seosiris-isolated-security-blueprint</link>
<description>&lt;h3 id=&quot;section&quot;&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=15612186850484753467&quot; alt=&quot;&quot;&gt;&lt;/h3&gt;
&lt;h3 id=&quot;section-1&quot;&gt;&lt;/h3&gt;
&lt;p&gt;The adoption of the Model Context Protocol (MCP) has changed how developers orchestrate contextual data between Large Language Models (LLMs) and systems. However, as autonomous AI agents move from local terminal playgrounds into the corporate workspace, a significant structural friction point emerges: Network Security.&lt;br&gt;
Engineering and InfoSec teams have reached a turning point where exposing internal resources over standard public proxies is no longer viable.&lt;/p&gt;
&lt;h3 id=&quot;this-post-analyzes-the-architectural-necessity-of-supporting-virtual-private-clouds-vpc-for-mcp-architectures-details-how-the-updated-enterprise-suite-handles-this-natively-and-explores-why-the-corporate-landscape-is-rapidly-adopting-seosiri-solutions-&quot;&gt;This post analyzes the architectural necessity of supporting Virtual Private Clouds (VPC) for MCP architectures, details how the updated enterprise suite handles this natively, and explores why the corporate landscape is rapidly adopting &lt;a rel=&quot;nofollow&quot; href=&quot;https://developers.seosiri.com/#manual&quot;&gt;SEOSiri Solutions&lt;/a&gt;.&lt;/h3&gt;
&lt;h3 id=&quot;1-the-architectural-problem-why-mcp-needed-vpc-protection&quot;&gt;1. The Architectural Problem: Why MCP Needed VPC Protection&lt;/h3&gt;
&lt;p&gt;The Model Context Protocol establishes a direct interface enabling AI clients to read schemas, execute local development scripts, and query underlying file structures. While highly effective, exposing this capability across public endpoints presents fundamental enterprise challenges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;li&gt;Data Leakage Exposures: Without isolated boundaries, every database pointer, microservice context layer, and internal schema route traverses standard public internet paths.&lt;/li&gt;
&lt;li&gt;Compliance Deadlocks: Regulated sectors (such as FinTech, Healthcare, and Defense) operate under strict internal mandates that strictly prohibit public ingress or egress configurations for core computational stacks.&lt;/li&gt;
&lt;li&gt;Attack Surface Multipliers: Traditional public gateways require persistent firewall openings, increasing the vulnerability of internal development infrastructure to lateral scan vulnerabilities.&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;by-introducing-native-vpc-support-mcp-operations-are-brought-directly-into-standard-zero-trust-network-boundaries-enabling-secure-ai-agent-interaction-behind-isolated-perimeters-&quot;&gt;By introducing native VPC Support, MCP operations are brought directly into standard zero-trust network boundaries, enabling secure AI agent interaction behind isolated perimeters.&lt;/h3&gt;
&lt;h3 id=&quot;2-deep-dive-how-seosiri-bridges-the-isolated-network-layer&quot;&gt;2. Deep Dive: How SEOSiri Bridges the Isolated Network Layer&lt;/h3&gt;
&lt;p&gt;The latest deployment module from the &lt;a rel=&quot;nofollow&quot; href=&quot;https://developers.seosiri.com&quot;&gt;SEOSiri Developer Portal&lt;/a&gt; adapts the core Model Context Protocol to operate within fully locked-down cloud network structures:&lt;/p&gt;
&lt;p&gt;[ Isolated Core VPC Subnet ]&lt;br&gt;
  ├── Internal Data Source / DB&lt;br&gt;
  ├── Proprietary Private Repository&lt;br&gt;
  └── SEOSiri Hardened MCP Server ──► [ Intercept / Scrubbing Layer ] ──► [ Local AI Client ]&lt;/p&gt;
&lt;h3 id=&quot;key-technical-capabilities-built-into-the-security-layer&quot;&gt;Key Technical Capabilities Built into the Security Layer&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;li&gt;Private Ingress Restrictions: Restricts incoming traffic utilizing granular CIDR-block parsing logic, ensuring only explicitly allowed cluster configurations can trigger context exchanges.&lt;/li&gt;
&lt;li&gt;The PII Shield Intercept: Integrated directly within the internal server node, this pipeline monitors outgoing strings, automatically redacting and tokenizing sensitive values before structural arrays reach model reasoning endpoints.&lt;/li&gt;
&lt;li&gt;Hybrid Cloud Topologies: Native multi-cloud support allows identical initialization frameworks whether your architecture resides on AWS VPC, Google Cloud VPC, or Microsoft Azure VNets.&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-operational-advantages-the-core-benefits&quot;&gt;3. Operational Advantages: The Core Benefits&lt;/h3&gt;
&lt;p&gt;Implementing an enterprise-grade VPC strategy for your contextual AI layer yields immediate architectural dividends:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;li&gt;Sub-Millisecond Processing Rates: Running the gateway close to local database partitions reduces transit latency overhead during highly interactive multi-turn agent execution sequences.&lt;/li&gt;
&lt;li&gt;Native Log Stream Aggregation: System telemetry routes directly into your internal logging tools (like AWS CloudWatch, Google Cloud Operations Suite, or Datadog), keeping compliance audits fully within your administrative perimeter.&lt;/li&gt;
&lt;li&gt;Consistent IAM Authentication Policies: Connects directly into existing enterprise access managers using OpenID Connect (OIDC) or strict OAuth2 verification schemas without requiring secondary secret tokens.&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;4-why-the-corporate-world-is-standardizing-on-seosiri-mcp&quot;&gt;4. Why the Corporate World is Standardizing on SEOSiri MCP&lt;/h3&gt;
&lt;p&gt;Enterprise procurement and security management groups are shifting away from fragmented open-source wrappers toward verified setups for several critical reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Production-Grade Stability: Rather than fragile point-to-point scripts, it provides an audited platform tailored for high-concurrency enterprise microservices.&lt;/li&gt;
&lt;li&gt;Simplified Compliance Mapping: Pre-configured network isolation maps provide simple documentation validation for internal security review teams during software vetting cycles.&lt;/li&gt;
&lt;li&gt;Future-Proof Extensibility: The platform offers structured integration options that work seamlessly with modern development tools like Claude Desktop, Cursor AI, and Atlassian Rovo without modifying original backend logic.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h4 id=&quot;-deploy-within-your-private-network-vpc-tunnels&quot;&gt;🛠️ Deploy Within Your Private Network / VPC Tunnels&lt;/h4&gt;
&lt;p&gt;Setting up an isolated instance within your internal network or Cloudflare Zero Trust framework requires minimal configuration changes. Configure the required secure environment flags upon runtime initialization:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Initialize the SEOSiri hardened edge gateway via Cloudflare Zero Trust Tunnel (cloudflared)
# or via private container backend within your isolated VPC subnet:
docker run -d \
  --name seosiri-mcp-vpc-instance \
  --network=&quot;vpc-private-backend&quot; \
  --publish 127.0.0.1:8080:8080 \
  -e ALLOWED_CIDR_BLOCKS=&quot;10.0.0.0/16&quot; \
  -e ENCRYPTION_KEY_SECRET=&quot;$VPC_ENCRYPTION_KEY&quot; \
  -e OAUTH_DISCOVERY_URL=&quot;https://developers.seosiri.com/.well-known/openid-configuration&quot; \
  ghcr.io/seosiri-official/stal-mcp:latest

To access comprehensive configuration templates, cluster orchestration manifests, and step-by-step guides, visit the documentation space on the [SEOSiri Developer Portal][1].
For additional insights into this architecture and long-term release updates, check out the official announcement breakdown on the [SEOSiri Live Announcement Page][2].
------------------------------


  [1]: https://developers.seosiri.com/
  [2]: https://www.seosiri.com/2026/10/seosiri-mcp-vpc-support.html
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29368/why-the-enterprise-demands-vpc-for-mcp-deep-dive-into-seosiris-isolated-security-blueprint</guid>
<pubDate>Thu, 01 Oct 2026 08:36:31 +0000</pubDate>
</item>
<item>
<title>How to Build an MCP Server in Golang Using the Official MCP SDK</title>
<link>https://coderlegion.com/29194/how-to-build-an-mcp-server-in-golang-using-the-official-mcp-sdk</link>
<description>&lt;p&gt;&lt;strong&gt;What is MCP?&lt;/strong&gt;&lt;br&gt;
The Model Context Protocol is an open standard (by Anthropic) that lets LLM clients (Claude, Cursor, etc.) call external tools, read resources, and get prompted context in a uniform way — without any bespoke plugin per-model. You can read more about this on Model Context Protocol Docs&lt;/p&gt;
&lt;p&gt;In this tutorial, we'll build a basic currency conversion MCP server using Golang and the official MCP SDK. We'll explore Streamable HTTP transport for remote access, add authentication to secure our server, and finally deploy the application to Render. By the end of this guide, you'll have a solid understanding of the complete lifecycle of building and deploying an MCP server in Go.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go 1.22+&lt;/li&gt;
&lt;li&gt;Claude Desktop installed (for local testing)&lt;/li&gt;
&lt;li&gt;Basic familiarity with Go modules and &lt;code&gt;net/http&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;MCP Transports&lt;/strong&gt;&lt;br&gt;
MCP supports &lt;a rel=&quot;nofollow&quot; href=&quot;https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#stdio&quot;&gt;stdio&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; href=&quot;https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http&quot;&gt;Streamable HTTP&lt;/a&gt; transport mechanisms that define how an MCP client and server communicate with each other. In this tutorial, we'll work with Streamable HTTP.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Streamable HTTP&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Streamable HTTP allows MCP clients and servers to communicate over standard HTTP connections. The server runs independently and can be hosted remotely, making it accessible from different environments. Unlike stdio, Streamable HTTP allows the MCP server to live anywhere (local machine, Docker container, cloud VM, Kubernetes, etc.), making it much easier to share across multiple users.&lt;/p&gt;
&lt;p&gt;Streamable HTTP is a better choice when you want to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deploy your MCP server to the cloud&lt;/li&gt;
&lt;li&gt;Allow multiple clients to access the same server&lt;/li&gt;
&lt;li&gt;Add features such as authentication and centralized monitoring&lt;/li&gt;
&lt;li&gt;Manage your MCP server independently from the client application&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since we'll eventually deploy our currency conversion server to Render, Streamable HTTP will play an important role in moving from a local setup to a production-ready deployment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setting up Golang project&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can refer following &lt;a rel=&quot;nofollow&quot; href=&quot;https://go.dev/doc/tutorial/getting-started&quot;&gt;blog&lt;/a&gt; for setting up a basic golang project. We will use the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/modelcontextprotocol/go-sdk&quot;&gt;go-sdk&lt;/a&gt; for creating mcp server which is maintend by the mcp team.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go mod init example/mcp-server
go get -u github.com/gorilla/mux
go get https://github.com/modelcontextprotocol/go-sdk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Basic MCP Server&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To start, we'll set up a very basic mcp server with just 1 tool. Before building the currency conversion tool, let's start with a minimal Greeting tool so we can understand the basic structure of an MCP server.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// main.go
package main

import (
...
)

func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, &amp;amp;slog.HandlerOptions{Level: slog.LevelInfo}))

err := godotenv.Load()
if err != nil {
logger.Error(&quot;error loading .env file&quot;, &quot;err&quot;, err)
}

mcpServer := server.NewMcpServer(logger)
mcpServer.AddReceivingMiddleware(security.LoggingMiddleware())

mcpHandler := mcp.NewStreamableHTTPHandler(func(request *http.Request) *mcp.Server {
return mcpServer
}, &amp;amp;mcp.StreamableHTTPOptions{
Logger:                     logger,
JSONResponse:               true,
Stateless:                  true,
DisableLocalhostProtection: true,
})

router := server.NewHttpServer(mcpServer, mcpHandler)

mcp.AddTool(mcpServer, &amp;amp;mcp.Tool{
Title:       &quot;Greeting&quot;,
Name:        &quot;greeting&quot;,
Description: &quot;Greet a person by name&quot;,
}, SayHi)

port := os.Getenv(&quot;PORT&quot;)
if port == &quot;&quot; {
port = &quot;3000&quot;
}

server := &amp;amp;http.Server{
Addr:              &quot;:&quot; + port,
Handler:           router,
ReadTimeout:       5 * time.Minute,
ReadHeaderTimeout: 10 * time.Second,
WriteTimeout:      5 * time.Minute,
IdleTimeout:       5 * time.Minute,
MaxHeaderBytes:    1 &amp;lt;&amp;lt; 20,
}

go func() {
logger.Info(&quot;starting server&quot;, &quot;addr&quot;, port)

if err := server.ListenAndServe(); err != nil &amp;amp;&amp;amp;
err != http.ErrServerClosed {

logger.Error(&quot;server failed&quot;, &quot;err&quot;, err)
os.Exit(1)
}
}()

ctx, stop := signal.NotifyContext(
context.Background(),
syscall.SIGINT,
syscall.SIGTERM,
)
defer stop()

&amp;lt;-ctx.Done()

logger.Info(&quot;shutdown initiated&quot;)

shutdownCtx, cancel := context.WithTimeout(
context.Background(),
30*time.Second,
)
defer cancel()

if err := server.Shutdown(shutdownCtx); err != nil {
logger.Error(&quot;shutdown failed&quot;, &quot;err&quot;, err)
}

logger.Info(&quot;shutdown complete&quot;)
}

type GreetingInput struct {
Name string `json:&quot;name&quot; jsonschema:&quot;the name of the person to greet&quot;`
}

type GreetingOutput struct {
Greeting string `json:&quot;greeting&quot; jsonschema:&quot;the greeting to tell to the user&quot;`
}

func SayHi(ctx context.Context, req *mcp.CallToolRequest, input GreetingInput) (
*mcp.CallToolResult, any, error) {
return &amp;amp;mcp.CallToolResult{
Content: []mcp.Content{
&amp;amp;mcp.TextContent{Text: &quot;Hi &quot; + input.Name},
},
}, GreetingOutput{Greeting: &quot;Hi &quot; + input.Name}, nil
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// server.go
package server

import (
...
)

func NewMcpServer(logger *slog.Logger) *mcp.Server {
 implementation := &amp;amp;mcp.Implementation{
  Title:   &quot;MCP Tutorial For Greeting&quot;,
  Name:    &quot;greeting-mcp&quot;,
  Version: &quot;1.0.0&quot;,
 }

 serverOptions := &amp;amp;mcp.ServerOptions{
  Logger:    logger,
  KeepAlive: 5 * time.Minute,
 }

 return mcp.NewServer(implementation, serverOptions)
}

func NewHttpServer(server *mcp.Server, mcpHandler *mcp.StreamableHTTPHandler) *mux.Router {
router := mux.NewRouter()

router.HandleFunc(&quot;/health&quot;, func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(&quot;ok&quot;))
}).Methods(http.MethodGet)

// Optional root route to avoid confusion when testing in browser.
router.HandleFunc(&quot;/&quot;, func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(&quot;MCP server is running. Use /mcp endpoint.&quot;))
}).Methods(http.MethodGet, http.MethodPost, http.MethodOptions)

router.HandleFunc(&quot;/mcp&quot;, func(w http.ResponseWriter, req *http.Request) {
fmt.Printf(
&quot;method=%s path=%s auth=%q\n&quot;,
req.Method,
req.URL.Path,
req.Header.Get(&quot;Authorization&quot;),
)
mcpHandler.ServeHTTP(w, req)
}).Methods(http.MethodPost, http.MethodGet, http.MethodOptions)

return router
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here you can see for the http server we expose /mcp endpoint. This endpoint is not a REST endpoint that your application calls directly. It speaks the MCP protocol over HTTP and is intended to be consumed by MCP clients.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Understanding MCP Tools&lt;/strong&gt;&lt;br&gt;
I like to think of MCP tools as API endpoint which an AI agent or client understands and sends request to based on its analysis of the prompt user has typed. So it becomes very important how we name our MCP tool. You can read more on it &lt;a rel=&quot;nofollow&quot; href=&quot;https://modelcontextprotocol.io/specification/2025-11-25/server/tools&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now lets build a real life example tool which could do currency conversion. For currency conversion I am using this free API which is provided by &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/fawazahmed0&quot;&gt;fawazahmed0&lt;/a&gt; in the following github &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/fawazahmed0/exchange-api&quot;&gt;repo&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package tool

import (
...
)

// ConvertCurrencyInput is the input for the ConvertCurrencyTool
type ConvertCurrencyInput struct {
FromCurrency string  `json:&quot;from_currency&quot; jsonschema:&quot;currency codes are ISO 4217 format, e.g. USD, EUR, GBP, etc. the currency to convert from&quot;`
ToCurrency   string  `json:&quot;to_currency&quot; jsonschema:&quot;currency codes are ISO 4217 format, e.g. USD, EUR, GBP, etc. the currency to convert to&quot;`
Amount       float64 `json:&quot;amount&quot; jsonschema:&quot;the amount to convert&quot;`
}

// ConvertCurrencyOutput is the output for the ConvertCurrencyTool
type ConvertCurrencyOutput struct {
ConvertedAmount float64 `json:&quot;converted_amount&quot; jsonschema:&quot;the converted amount&quot;`
}

type CurrencyResponse struct {
Date string                        `json:&quot;date&quot; jsonschema:&quot;the date of the currency rates&quot;`
Data map[string]map[string]float64 `json:&quot;-&quot; jsonschema:&quot;the currency rates&quot;`
}

const BASE_CURRENCY_API_URL = `https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies`

// ConvertCurrencyTool converts a currency to another currency
func ConvertCurrencyTool(ctx context.Context, req *mcp.CallToolRequest, input ConvertCurrencyInput) (*mcp.CallToolResult, any, error) {
input.FromCurrency = strings.ToLower(input.FromCurrency)
input.ToCurrency = strings.ToLower(input.ToCurrency)
fmt.Println(&quot;inside convert currency tool input&quot;, input)

apiURL := fmt.Sprintf(&quot;%s/%s.json&quot;, BASE_CURRENCY_API_URL, input.FromCurrency)
resp, err := http.Get(apiURL)
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, nil, err
}

response, err := UnmarshalJSON(body)
if err != nil {
return nil, nil, err
}

if _, ok := response.Data[input.FromCurrency]; !ok {
return nil, nil, fmt.Errorf(&quot;currency %s not found&quot;, input.FromCurrency)
}

if _, ok := response.Data[input.FromCurrency][input.ToCurrency]; !ok {
return nil, nil, fmt.Errorf(&quot;currency %s not found&quot;, input.ToCurrency)
}

convertedAmount := response.Data[input.FromCurrency][input.ToCurrency] * input.Amount
return &amp;amp;mcp.CallToolResult{
Content: []mcp.Content{
&amp;amp;mcp.TextContent{
Text: fmt.Sprintf(&quot;Converted amount: %f&quot;, convertedAmount),
},
},
}, nil, nil
}

func UnmarshalJSON(data []byte) (*CurrencyResponse, error) {
var r CurrencyResponse
var raw map[string]json.RawMessage

if err := json.Unmarshal(data, &amp;amp;raw); err != nil {
return nil, err
}

// Extract date
if v, ok := raw[&quot;date&quot;]; ok {
if err := json.Unmarshal(v, &amp;amp;r.Date); err != nil {
return nil, err
}
delete(raw, &quot;date&quot;)
}

// Remaining keys are currency codes
r.Data = make(map[string]map[string]float64)

for currency, v := range raw {
var rates map[string]float64
if err := json.Unmarshal(v, &amp;amp;rates); err != nil {
return nil, err
}
r.Data[currency] = rates
}

return &amp;amp;r, nil
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now to add the mcp server we do the following&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// main.go

....

func main() {
...

mcp.AddTool(mcpServer, &amp;amp;mcp.Tool{
Title:       &quot;Currency Conversion&quot;,
Name:        &quot;currency-conversion&quot;,
Description: &quot;Convert an amount from one currency to another. Requires from_currency, to_currency (ISO 4217 codes), and amount. Uses latest exchange rates from an external API.&quot;,
}, ConvertCurrencyTool)
...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now lets understand what is happening here and how it works. First we register this tool using mcp.AddTool. Here Title is just human readable text and does not provide any help or context to the AI agent. Name and Description are 2 important things when registering a tool as this 2 piece of information helps the AI agent to make the decision on which MCP server should be used.&lt;/p&gt;
&lt;p&gt;Now lets go to the ConvertCurrencyTool. This function takes 3 arguments which is the method signature and the 3rd parameter which is input is what we will focus on. It is like the request body that we expect to receive from the AI agent. In my case I am expecting fromCurrency, toCurrency and amount. For all the fields I have jsonschema specified which, like the tool description, helps the AI understand what each field represents. The SDK converts these tags into the MCP Tool schema that the model receives during tool discovery&lt;/p&gt;
&lt;p&gt;The ConvertCurrencyTool makes an API call to fetch the latest exchange rates, performs the currency conversion, and returns the result to the MCP client.&lt;/p&gt;
&lt;p&gt;There are a few more things which can be done during mcp server creation. Another useful server configuration is Instructions. These provide additional context to the AI model and can improve tool selection and overall responses.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func NewMcpServer(logger *slog.Logger) *mcp.Server {
implementation := &amp;amp;mcp.Implementation{
Title:   &quot;MCP Tutorial For Currency Conversion&quot;,
Name:    &quot;currency-conversion-mcp&quot;,
Version: &quot;1.0.0&quot;,
}

serverOptions := &amp;amp;mcp.ServerOptions{
Logger:       logger,
KeepAlive:    5 * time.Minute,
Instructions: `You are a helpful assistant that can convert currencies. You can convert currencies using the currency-conversion tool.`,
        Capabilities: &amp;amp;mcp.ServerCapabilities{
Tools: &amp;amp;mcp.ToolCapabilities{},
},
}

return mcp.NewServer(implementation, serverOptions)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is also one more important setting that we should we about when configuring the streamable http transport&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mcpHandler := mcp.NewStreamableHTTPHandler(func(request *http.Request) *mcp.Server {
return mcpServer
}, &amp;amp;mcp.StreamableHTTPOptions{
Logger:                     logger,
JSONResponse:               true,
Stateless:                  true,
DisableLocalhostProtection: true,
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here the options part is important to understand. &lt;code&gt;JSONResponse&lt;/code&gt; is basic tells if the response type is json or not. &lt;code&gt;Stateless&lt;/code&gt; - this is one of the key option to understand. &lt;code&gt;Stateless&lt;/code&gt; mode tells the server not to rely on MCP sessions. Every request should contain all information required to process it, making deployment behind load balancers and horizontal scaling much easier.. This is very well explained in Anthropic courses named &lt;a rel=&quot;nofollow&quot; href=&quot;https://anthropic.skilljar.com/model-context-protocol-advanced-topics&quot;&gt;Model Context Protocol: Advanced Topics&lt;/a&gt;. I ideally like to keep it to &lt;code&gt;true&lt;/code&gt; as a REST API is always stateless and we use Authorization headers to validate the user so we can follow the same setup here too. The last option which is &lt;code&gt;DisableLocalhostProtection&lt;/code&gt; again an important flag to be set to &lt;code&gt;true&lt;/code&gt; when deploying to production. You can read more on this &lt;a rel=&quot;nofollow&quot; href=&quot;https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices#local-mcp-server-compromise&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To find more examples on how to create &lt;a rel=&quot;nofollow&quot; href=&quot;https://modelcontextprotocol.io/specification/2025-11-25/server/prompts&quot;&gt;Prompt&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://modelcontextprotocol.io/specification/2025-11-25/server/resources&quot;&gt;Resource&lt;/a&gt; you can always refer following &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/modelcontextprotocol/go-sdk/tree/main/examples&quot;&gt;docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How registration works&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When we call:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mcp.AddTool(mcpServer, &amp;amp;mcp.Tool{
    Title:       &quot;Currency Conversion&quot;,
    Name:        &quot;currency-conversion&quot;,
    Description: &quot;Convert an amount from one currency to another...&quot;,
}, ConvertCurrencyTool)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we are not creating a new HTTP endpoint like we would in a typical REST application. Instead, we're registering the tool with the MCP server.&lt;/p&gt;
&lt;p&gt;From this point on, the lifecycle looks like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The tool is registered: The MCP server stores the tool's metadata, including its name, description, and input schema.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The MCP client connects: When a client such as Claude Desktop connects to the server, it asks the server which tools are available.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The server advertises its tools: The server responds with the list of registered tools, including their descriptions and JSON schemas.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The LLM decides whether to use a tool: When the user asks a question like:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;&lt;p&gt;How much is 28 USD in INR?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;the model analyzes the request and determines that the &lt;code&gt;currency-conversion&lt;/code&gt; tool is appropriate.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The client invokes the tool: The client sends a tool invocation request to the MCP server containing the required input&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;from_currency&quot;: &quot;USD&quot;,
  &quot;to_currency&quot;: &quot;INR&quot;,
  &quot;amount&quot;: 28
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your Go function executes: The Go SDK automatically deserializes the request into a &lt;code&gt;ConvertCurrencyInput&lt;/code&gt; struct and calls: &lt;code&gt;ConvertCurrencyTool(ctx, req, input)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The result is returned: Your function performs the currency conversion, returns the result, and the SDK sends it back to the client. Claude then uses that result to generate its final response to the user.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
In this tutorial, we built a complete MCP server in Go using the official Go SDK. We started with a simple greeting tool, expanded it into a practical currency conversion service, exposed it using Streamable HTTP, discussed important server configuration options.&lt;/p&gt;
&lt;p&gt;In the next step, you can deploy the same server to Render and make it accessible remotely without changing the MCP client configuration.&lt;/p&gt;
&lt;p&gt;The complete source code for this tutorial is available on GitHub:&lt;/p&gt;
&lt;p&gt;GitHub Repository: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/shaileshhb/mcp-tutorial&quot;&gt;https://github.com/shaileshhb/mcp-tutorial&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29194/how-to-build-an-mcp-server-in-golang-using-the-official-mcp-sdk</guid>
<pubDate>Wed, 30 Sep 2026 06:51:40 +0000</pubDate>
</item>
<item>
<title>One common misconception about MCP:</title>
<link>https://coderlegion.com/29000/one-common-misconception-about-mcp</link>
<description>&lt;p&gt;MCP is used to connect AI agents to tools.&lt;/p&gt;
&lt;p&gt;Not only that.&lt;/p&gt;
&lt;p&gt;Tools are just one of the three core primitives an MCP server can expose.&lt;/p&gt;
&lt;p&gt;These three components are:&lt;/p&gt;
&lt;p&gt;Resources - data/context that the AI application can access&lt;/p&gt;
&lt;p&gt;For example, an email, a file, a database record, or documentation.&lt;/p&gt;
&lt;p&gt;Prompts - reusable prompt templates for specific interactions. &lt;/p&gt;
&lt;p&gt;For example, a predefined &quot;review this pull request&quot;; prompt.&lt;/p&gt;
&lt;p&gt;Tools - functions that the AI application can execute. &lt;/p&gt;
&lt;p&gt;For example, send an email, create a Jira ticket, or book a flight ticket.&lt;/p&gt;
&lt;p&gt;So a better mental model is:&lt;/p&gt;
&lt;p&gt;Resources -&amp;gt;Read&lt;/p&gt;
&lt;p&gt;Prompts -&amp;gt; Guide&lt;/p&gt;
&lt;p&gt;Tools -&amp;gt; Do&lt;/p&gt;
&lt;p&gt;This distinction matters because when you think of MCP only as a way to connect tools, you miss a significant part of what the protocol actually provides.&lt;/p&gt;
&lt;p&gt;Now, the question for you is&lt;/p&gt;
&lt;p&gt;Why not just put the prompt in the agent's system prompt? Why access it through MCP?&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29000/one-common-misconception-about-mcp</guid>
<pubDate>Tue, 29 Sep 2026 05:10:52 +0000</pubDate>
</item>
<item>
<title>CData's New AI Gateway Puts Context at the Center — Fixes the Three Reasons Enterprise AI Stalls</title>
<link>https://coderlegion.com/28982/cdatas-new-ai-gateway-puts-context-at-the-center-fixes-the-three-reasons-enterprise-stalls</link>
<description>&lt;p&gt;Most enterprise AI programs are stuck. Not because the models are bad, but because the underlying infrastructure can't keep up. Costs are climbing, productivity gains are flat, and organizations are locking down access rather than expanding it because they don't have the governance controls they need to feel comfortable.&lt;/p&gt;
&lt;p&gt;CData Software has been watching this pattern play out across hundreds of enterprise deployments over the past year. On September 29, the company is announcing what it sees as the fix: CData Connect AI Gateway, a single control point between AI agents and the enterprise systems they need to act on.&lt;/p&gt;
&lt;h3 id=&quot;three-problems-one-control-point-&quot;&gt;Three Problems. One Control Point.&lt;/h3&gt;
&lt;p&gt;Marie Forshaw, CData's SVP of Product Marketing, laid out the three challenges clearly during a pre-launch briefing. They're likely familiar to anyone who's been building or deploying AI in an enterprise context.&lt;/p&gt;
&lt;p&gt;The first is rising costs. AI budgets are burning through faster than organizations can justify. Without fine-grained visibility into who's using what model for what task, finance teams are doing the only thing they can: shutting things down.&lt;/p&gt;
&lt;p&gt;The second is stagnant productivity. Some of that is the lockdown. But Forshaw pointed to two other contributing factors: ongoing accuracy and reliability issues with AI responses, and a near-total freeze on write operations. Most organizations have enabled read use cases — querying data, summarizing it, surfacing it. Very few have enabled AI agents to actually take action. The risk is too high, and the controls aren't there.&lt;/p&gt;
&lt;p&gt;The third is governance. This is where the developer-versus-leadership tension gets real. Forshaw made the point directly: developers may not care much about centralized control, but CTOs and CIOs absolutely do. And without their sign-off, AI projects don't scale.&lt;/p&gt;
&lt;p&gt;Connect AI Gateway is designed to address all three from one place.&lt;/p&gt;
&lt;h3 id=&quot;what-the-gateway-actually-does&quot;&gt;What the Gateway Actually Does&lt;/h3&gt;
&lt;p&gt;The platform has four layers. Two of them — data connectivity and security controls — are existing CData capabilities. The two new layers are the gateway itself and a context engine, and they're where most of the interesting development is happening.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Gateway Layer&lt;/strong&gt; handles model routing, MCP traffic, and agent orchestration. It registers models, MCP servers, and agents once, then routes requests based on availability, cost, and latency. Intent-based routing is part of this — the system reads the complexity of a prompt and sends simpler requests to cheaper models automatically. Token budgets can be set at the team, agent, or tool level, giving organizations real cost visibility and control rather than a blunt shutdown switch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Context Engine&lt;/strong&gt; is the more distinctive part of the announcement. CData's argument is that most gateway providers are just routing traffic between models and MCP servers. Because CData owns the connection all the way down to the source system, it can build up and apply business context at every step of a request — and that's what separates useful AI from AI that keeps getting things wrong.&lt;/p&gt;
&lt;p&gt;The context engine pulls from four sources: company knowledge (documented processes, SOPs, Slack and Teams conversations), semantic definitions (imported from Power BI, BigQuery, dbt, or built natively in the platform), system context (schema, relationships, and field meanings from connected source systems), and data modeling (cross-source joins and derived views that calculate answers before they reach the model).&lt;/p&gt;
&lt;p&gt;Everything gets normalized into Open Knowledge Format and visualized as a context graph that administrators can edit and extend.&lt;/p&gt;
&lt;h3 id=&quot;the-self-learning-loop&quot;&gt;The Self-Learning Loop&lt;/h3&gt;
&lt;p&gt;One of the more forward-looking pieces of this announcement is a self-learning capability CData is calling the self-learning loop. The idea is that every interaction makes the system smarter — prompt patterns become vocabulary, query patterns become join hints, user-level corrections get written back to the knowledge bundle, and facts that multiple users share get promoted to company-wide knowledge.&lt;/p&gt;
&lt;p&gt;This capability is pre-beta at announcement. No customers are in production with it yet, so there's no empirical data on how long the improvement curve takes in practice. CData acknowledges that directly. The honest answer is: we'll know more in six months.&lt;/p&gt;
&lt;p&gt;Organizations will have control over what gets promoted from personal to shared knowledge. Everything can require human approval before it becomes part of the company context, or you can set specific categories to promote automatically. That configurability matters for teams with compliance requirements.&lt;/p&gt;
&lt;h3 id=&quot;the-numbers-accuracy-and-cost&quot;&gt;The Numbers: Accuracy and Cost&lt;/h3&gt;
&lt;p&gt;CData's accuracy benchmarking from earlier this year showed Connect AI at 98.5% accuracy across 378 enterprise queries, compared to 65–75% for competing MCP providers. That gap matters more as AI moves from read to write operations — a 70% accuracy rate on an agent that's taking action in your ERP is not a productivity tool. It's a liability.&lt;/p&gt;
&lt;p&gt;The newer study, published just before this briefing, tested 22 models against live enterprise data — with and without Connect AI's data layer configured. With it, every model answered correctly. Without it, every model made mistakes. The cost spread between the cheapest model tested (Mistral Small) and the most expensive (Claude Fable 5.1) was 175x.&lt;/p&gt;
&lt;p&gt;Jared Johnson, CData's Director of Technology Evangelism, explained the mechanism clearly. When you ask an AI to list your five healthiest customers, it has no idea what &quot;healthy&quot; means in your context. You can put that definition in the system prompt, but that doesn't guarantee it gets honored. When you build that definition into a derived view inside Connect AI, the model can't get it wrong — because it doesn't have access to the raw fields. It only gets the calculated answer. The model isn't doing the reasoning. CData is.&lt;/p&gt;
&lt;p&gt;That's the architecture. And it's why the same cheap model can deliver the same correct answer as one that costs 175 times more.&lt;/p&gt;
&lt;h3 id=&quot;developer-setup-minutes-to-hours&quot;&gt;Developer Setup: Minutes to Hours&lt;/h3&gt;
&lt;p&gt;Adobe cut regression test delivery from ten weeks of manual effort to roughly one week by connecting to SAP through Connect AI and running a test automation agent. For developers wondering what setup actually looks like: basic authentication to a source system can be done in minutes. A working agent with governed access typically takes hours to a day. From there, it's an iterative process — start with minimal configuration, dial in derived views and custom tools over time as the workflow becomes clearer.&lt;/p&gt;
&lt;p&gt;The path from 70% to 98.5% accuracy isn't a configuration switch. It's a development process. But the starting point is lower-friction than building your own MCP server stack.&lt;/p&gt;
&lt;h3 id=&quot;the-honest-case-for-switching&quot;&gt;The Honest Case for Switching&lt;/h3&gt;
&lt;p&gt;For development teams already running their own MCP servers, the question is fair: why hand that off to a managed platform? Johnson's answer was practical — it can seem cheaper and faster to manage your own servers when you're working on one system. The complexity compounds when you're trying to manage MCP access across multiple systems with different security models, different permission structures, and different teams using different tools.&lt;/p&gt;
&lt;p&gt;What CData is offering is the centralized governance layer that makes it possible to turn on write operations without giving a CIO a reason to shut the whole program down. That may matter less to individual developers in the short run. It matters a lot to the people deciding whether to renew the AI budget.&lt;/p&gt;
&lt;h3 id=&quot;bottom-line&quot;&gt;Bottom Line&lt;/h3&gt;
&lt;p&gt;CData Connect AI Gateway enters an increasingly crowded market. Several AI gateway announcements have come out in the past few months, and CData is not the only company making the data-layer argument. But the company has a legitimate differentiator in owning the source system connection — not just the routing layer above it — and the cost study is a concrete illustration of what that unlocks.&lt;/p&gt;
&lt;p&gt;The self-learning context engine is the most interesting long-term bet in this announcement, and also the one with the least evidence behind it yet. Worth watching as customer data comes in.&lt;/p&gt;
&lt;p&gt;Connect AI Gateway is available through an early access program beginning September 29, 2026. More information at &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.cdata.com&quot;&gt;cdata.com&lt;/a&gt;.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/28982/cdatas-new-ai-gateway-puts-context-at-the-center-fixes-the-three-reasons-enterprise-stalls</guid>
<pubDate>Tue, 29 Sep 2026 00:06:14 +0000</pubDate>
</item>
</channel>
</rss>