<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ricardo Rodrigues</title>
    <description>The latest articles on DEV Community by Ricardo Rodrigues (@codemalasartes).</description>
    <link>https://dev.to/codemalasartes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F900488%2Ff2206bfb-c9eb-4f28-be82-666e0114d62e.jpeg</url>
      <title>DEV Community: Ricardo Rodrigues</title>
      <link>https://dev.to/codemalasartes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codemalasartes"/>
    <language>en</language>
    <item>
      <title>The Day Your AI Agent Has the Keys to Everything</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Sun, 24 May 2026 13:06:47 +0000</pubDate>
      <link>https://dev.to/codemalasartes/the-day-your-ai-agent-has-the-keys-to-everything-78k</link>
      <guid>https://dev.to/codemalasartes/the-day-your-ai-agent-has-the-keys-to-everything-78k</guid>
      <description>&lt;p&gt;There's a moment coming in your company, if it hasn't arrived already.&lt;/p&gt;

&lt;p&gt;A developer wires up an AI agent — Claude, Cursor, whatever your team uses — to a Model Context Protocol server. Suddenly the agent can query your production database, read your private repos, hit internal APIs, trigger deployments. Not &lt;em&gt;suggest&lt;/em&gt; doing those things. &lt;em&gt;Do&lt;/em&gt; them. Autonomously, in response to natural language, often without a human approving each action.&lt;/p&gt;

&lt;p&gt;On a laptop, that's a productivity miracle. In production, it's a question nobody in the room can answer: &lt;strong&gt;who is allowed to do what, and how would we ever know what happened?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That question is the one this piece is about. Because the answer, for most companies adopting MCP today, is: &lt;em&gt;we have no idea.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern we've seen before
&lt;/h2&gt;

&lt;p&gt;If you've been in infrastructure long enough, this rhymes with something.&lt;/p&gt;

&lt;p&gt;A decade ago, microservices arrived the same way. Teams split monoliths apart, called the pieces "services," and shipped. The architecture was exciting; the governance was an afterthought. We spent the &lt;em&gt;next&lt;/em&gt; five years retrofitting service meshes, API gateways, identity, and observability onto systems that were never designed to be governed. The cleanup cost more than the migration.&lt;/p&gt;

&lt;p&gt;MCP is at the exact same stage microservices were in 2014 — explosive adoption, no governance layer, and a collective decision to worry about security later.&lt;/p&gt;

&lt;p&gt;"Later" has a way of arriving as an incident.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap, stated plainly
&lt;/h2&gt;

&lt;p&gt;Here is what MCP adoption actually looks like inside most teams right now:&lt;/p&gt;

&lt;p&gt;Every developer installs their own MCP servers, with their own credentials, on their own machine. Security has no approved list and no visibility into what's connected. Many of those servers run as local processes — meaning they can't be centrally monitored, shared, revoked, or audited. And when an agent does something — queries a customer table, posts to a channel, runs a command — there is no record of who initiated it, through which identity, or whether it should have been allowed.&lt;/p&gt;

&lt;p&gt;This isn't hypothetical. Security researchers recently found roughly 1,800 MCP servers exposed to the public internet. Of the sample they analyzed, every single one accepted unauthenticated requests. Some of those servers connect directly to internal systems that would otherwise never be reachable from outside.&lt;/p&gt;

&lt;p&gt;Read that again: tools that can act on internal infrastructure, reachable by anyone, authenticating no one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is worse than a normal security gap
&lt;/h2&gt;

&lt;p&gt;A normal vulnerability is a door someone might pick. This is different, and worse, in two specific ways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, the agent is unpredictable by design.&lt;/strong&gt; A traditional application does what it was coded to do. An AI agent does what it's &lt;em&gt;persuaded&lt;/em&gt; to do. If a developer points an agent at an untrusted web page or an unvetted codebase, an attacker can embed instructions in that content — and the agent, trying to be helpful, may call a real tool with real credentials. The infrastructure did nothing wrong. The agent was simply talked into it. Your firewall has no concept of "the model was tricked."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second, there's no chain of custody.&lt;/strong&gt; When the incident review happens — and at scale, it always eventually happens — the question will be: &lt;em&gt;which agent, acting for which person, called which tool, against which system, and was that permitted?&lt;/em&gt; If your MCP setup is a pile of local configs, you cannot answer that. Not because you didn't log enough. Because the activity never passed through anywhere that &lt;em&gt;could&lt;/em&gt; log it.&lt;/p&gt;

&lt;p&gt;This is the part that turns a quiet adoption decision into a board-level risk: by the time you need the audit trail, it's too late to have started keeping one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What governing this actually requires
&lt;/h2&gt;

&lt;p&gt;Strip away the noise and the requirements are not exotic. They're the same disciplines identity providers brought to applications fifteen years ago — applied, now, to tool calls made by AI.&lt;/p&gt;

&lt;p&gt;You need a single point every tool call passes through, instead of dozens of direct, ungoverned connections. You need per-person identity, so every action is attributable and individually revocable — not a shared token that gives everyone the same keys. You need tool-level permissions, so a support engineer's agent can read a ticket but not delete a database. And you need an audit trail of every call — who, what, when, outcome — that exists &lt;em&gt;by default&lt;/em&gt;, not as something you scramble to bolt on after the first scare.&lt;/p&gt;

&lt;p&gt;Notice what governs this can't be the individual server, and can't be the client. A local server can harden itself but can't prove custody across a team. The client can't reason about what other members are doing. The governance has to live at the layer all the traffic passes through. That's not a feature you add to MCP. It's a layer you put in front of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this goes
&lt;/h2&gt;

&lt;p&gt;The companies that get this right won't be the ones with the most AI agents. They'll be the ones who can answer, on any given Tuesday, exactly what their agents did and whether it was allowed. That capability is about to separate the teams that scale AI safely from the ones that quietly accumulate risk until it surfaces.&lt;/p&gt;

&lt;p&gt;This is the layer we build at &lt;a href="https://mcpnest.io" rel="noopener noreferrer"&gt;mcpnest.io&lt;/a&gt; — a governed gateway for MCP, with per-member access, tool-level permissions, hosted infrastructure, and a protocol-level audit log that stores metadata, never payloads, so it's EU-resident and clean by construction. One endpoint your team connects through. Everything attributable. Everything revocable. Everything recorded.&lt;/p&gt;

&lt;p&gt;If you're adopting MCP and the questions in this piece made you slightly uncomfortable, that discomfort is the signal. You can scan your own MCP configuration for these exact risks, free and entirely in your browser, at &lt;a href="https://mcpnest.io/scan" rel="noopener noreferrer"&gt;mcpnest.io/scan&lt;/a&gt; — nothing leaves your machine.&lt;/p&gt;

&lt;p&gt;The microservices generation learned the cost of governing too late. The MCP generation doesn't have to.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>mcp</category>
      <category>claude</category>
    </item>
    <item>
      <title>Why Enterprises Will Struggle With MCP — And What to Do About It</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Wed, 20 May 2026 14:35:16 +0000</pubDate>
      <link>https://dev.to/codemalasartes/why-enterprises-will-struggle-with-mcp-and-what-to-do-about-it-1mbf</link>
      <guid>https://dev.to/codemalasartes/why-enterprises-will-struggle-with-mcp-and-what-to-do-about-it-1mbf</guid>
      <description>&lt;h2&gt;
  
  
  What Enterprise IT Asks First
&lt;/h2&gt;

&lt;p&gt;When any new technology enters an enterprise, four questions must be answered before broad deployment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Who has access to what?&lt;/li&gt;
&lt;li&gt;What happened, and when?&lt;/li&gt;
&lt;li&gt;How do we remove access when someone leaves?&lt;/li&gt;
&lt;li&gt;Can we prove compliance to an auditor?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For MCP today, in a default setup, the honest answers are: everyone has access to everything, we do not know what happened, we cannot remove access without breaking the whole team, and no we cannot prove compliance.&lt;/p&gt;

&lt;p&gt;This is not a reason to avoid MCP. It is a reason to build the governance layer before the rollout, not after.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three Phases Every Enterprise Goes Through
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Phase 1 — Exploration&lt;/strong&gt;&lt;br&gt;
A few developers install MCP servers individually. Cursor with GitHub integration. Claude Desktop with a database connector. Productivity improves visibly. Word spreads internally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 2 — Team Adoption&lt;/strong&gt;&lt;br&gt;
Teams start sharing configs. Someone creates a recommended MCP stack document. A workspace token gets shared in Slack. Now the entire team is using the same token with the same access to the same tools. Nobody is logging anything. Security has no visibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 3 — The Incident&lt;/strong&gt;&lt;br&gt;
Something unexpected happens. A production query runs at an unexpected time. A file gets modified that should not have been. An internal API gets called by an agent nobody authorised. Now the question is: "what happened, and who did it?" Nobody can answer it.&lt;/p&gt;

&lt;p&gt;This is the moment governance becomes urgent. The problem is that retrofitting governance into an existing MCP deployment is significantly harder than building it correctly from the start — because you have no historical data, no baseline, and no audit trail from before the governance layer existed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Seven Capabilities Enterprise MCP Requires
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Centralised endpoint&lt;/strong&gt;&lt;br&gt;
One authenticated URL per team. Not dozens of individual JSON configs across dozens of developer machines. A single point of control, logging, and revocation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Per-member identity&lt;/strong&gt;&lt;br&gt;
Every tool call attributable to a specific person. Not "the workspace called something." Individual tokens per member, so the audit trail captures who did what.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Tool-level access control&lt;/strong&gt;&lt;br&gt;
The ability to say "Alice can use these tools, Bob can use those." Enforced at the protocol level. The principle of least privilege applied to AI tooling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Isolated server deployment&lt;/strong&gt;&lt;br&gt;
MCP servers running in defined, auditable environments — not on developer laptops. Containers with clean lifecycle management: deployable, monitorable, and terminatable centrally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Quality and trust signals&lt;/strong&gt;&lt;br&gt;
A trust signal per server that goes beyond GitHub stars. Maintenance velocity, last commit date, publisher verification, config completeness — visible before installation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Instant revocation&lt;/strong&gt;&lt;br&gt;
When someone leaves the team, their access gone in seconds. Without rotating the workspace token. Without reconfiguring every AI client on the team. Individual member revocation with no blast radius.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Protocol-level audit log&lt;/strong&gt;&lt;br&gt;
A record of every tool call — who called it, which tool, which server, when, and whether it succeeded. Not application-level logging. Protocol-level logging that captures everything that flows through the gateway.&lt;/p&gt;

&lt;p&gt;None of these are optional for enterprise. All of them are absent from a default MCP setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Retrofit Problem
&lt;/h2&gt;

&lt;p&gt;The most expensive version of this problem is the one teams build toward without realising it.&lt;/p&gt;

&lt;p&gt;A team that deploys MCP without governance for six months has six months of tool calls with no attribution, no audit trail, and no access history. When an auditor asks "what did your AI agents have access to between January and June?", the answer is "we do not know."&lt;/p&gt;

&lt;p&gt;That answer is not acceptable in regulated industries. It is barely acceptable in any enterprise context where AI agents have access to production systems.&lt;/p&gt;

&lt;p&gt;The teams that establish governance now will have a clean audit trail from the first tool call. The teams that wait will be unable to reconstruct the past.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Window Is Now
&lt;/h2&gt;

&lt;p&gt;MCP adoption in enterprise is in Phase 1 and early Phase 2 for most organisations. The exploration is happening. The team adoption is beginning.&lt;/p&gt;

&lt;p&gt;The governance layer needs to arrive before Phase 3.&lt;/p&gt;

&lt;p&gt;Building it after an incident is possible. It is just significantly more expensive — in time, in credibility, and in the irreversible absence of historical audit data.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;MCPNest is the enterprise governance layer for MCP servers — Gateway, per-member access control, hosted infrastructure, and audit logging for AI engineering teams.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;mcpnest.io&lt;/em&gt;&lt;/p&gt;







&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm49w91mbb7nw1tcxtgck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm49w91mbb7nw1tcxtgck.png" alt=" " width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>mcp</category>
      <category>cursor</category>
    </item>
    <item>
      <title>The MCP Security Gap No One Is Talking About</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Sun, 17 May 2026 17:11:34 +0000</pubDate>
      <link>https://dev.to/codemalasartes/the-mcp-security-gap-no-one-is-talking-about-5h30</link>
      <guid>https://dev.to/codemalasartes/the-mcp-security-gap-no-one-is-talking-about-5h30</guid>
      <description>&lt;p&gt;The MCP ecosystem is growing fast. Thousands of servers, dozens of clients, and teams across the industry moving from personal experimentation to production deployments. But there is a security architecture problem baked into how most teams are using MCP today — and most of them do not know it yet.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: One Token, Everyone
&lt;/h2&gt;

&lt;p&gt;When you set up an MCP workspace for your team, you generate one Bearer token. That token goes into every team member's AI client configuration. Claude Desktop, Cursor, Windsurf — they all use the same token to authenticate against your MCP servers.&lt;/p&gt;

&lt;p&gt;This means every team member has identical access to every MCP tool in your workspace.&lt;/p&gt;

&lt;p&gt;Your junior developer has the same permissions as your principal engineer. Your intern can call the deployment tools. Your contractor can query the production database. There is no way to say "Alice can use the database tools but not the CI/CD tools" — not without managing separate workspaces per person, which defeats the purpose of a shared workspace entirely.&lt;/p&gt;

&lt;p&gt;This is not a preference problem. It is a security architecture problem. And it gets worse.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Revocation Problem
&lt;/h2&gt;

&lt;p&gt;Imagine someone leaves the team. To revoke their access, you rotate the workspace token. Now you have to update the configuration of every AI client on the team. Every developer. Every machine. Every client app. Simultaneously.&lt;/p&gt;

&lt;p&gt;In a team of ten people, this is painful. In a team of fifty, it is a production incident.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Proper Access Control Looks Like
&lt;/h2&gt;

&lt;p&gt;Enterprise security operates on the principle of least privilege. Every actor gets access to exactly what they need to do their job — and nothing else. When someone leaves, you revoke their access specifically, without affecting anyone else.&lt;/p&gt;

&lt;p&gt;For MCP, this means per-member tokens and per-member tool allowlists.&lt;/p&gt;




&lt;h2&gt;
  
  
  How MCPNest Gateway Layer 2 Works
&lt;/h2&gt;

&lt;p&gt;We built Gateway Layer 2 to solve this at the infrastructure level, not the application level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-member Bearer tokens.&lt;/strong&gt; Every workspace member gets their own token. The workspace token still exists for system-level access, but individual members authenticate with their own credentials. The audit trail captures &lt;code&gt;member_id&lt;/code&gt; on every call — you know exactly who called what tool and when.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool allowlists per member.&lt;/strong&gt; Admins define exactly which tools each member is permitted to call. Alice gets the database tools. Bob gets the search and retrieval tools. The deployment tools are restricted to the engineers who should have them. These allowlists are configured in the Security tab of the workspace UI — no code required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enforcement toggle.&lt;/strong&gt; The workspace owner enables or disables allowlist enforcement with a single toggle. You define the allowlists first, verify they are correct, and then enable enforcement when ready.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instant revocation.&lt;/strong&gt; When someone leaves the team, you delete their token. Their access is gone in seconds. Nobody else is affected. No workspace token rotation. No client reconfiguration across the team.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Audit Trail
&lt;/h2&gt;

&lt;p&gt;Every &lt;code&gt;tools/call&lt;/code&gt; through the MCPNest Gateway is logged with:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;workspace_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Which workspace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;member_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Which team member&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tool_name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Which tool was called&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;latency_ms&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;How long the call took&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Success or failure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is not workspace-level logging. This is tool-level forensics. When something goes wrong — and in production, something always goes wrong — you know exactly what happened, who triggered it, and when.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters Now
&lt;/h2&gt;

&lt;p&gt;The MCP ecosystem is at the same inflection point that OAuth was at in 2010. Teams are moving from "I set this up on my laptop" to "we are running this in production for the whole engineering org." The security model needs to evolve at the same pace.&lt;/p&gt;

&lt;p&gt;Right now, most teams are one credential leak away from full workspace exposure. One misconfigured client. One developer who stored their token in a public dotfile. One contractor whose access should have been revoked three months ago.&lt;/p&gt;

&lt;p&gt;Per-member access control is not a nice-to-have for enterprise MCP deployments. It is the minimum viable security posture for any team taking this seriously.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;MCPNest is the governance layer for MCP servers — Gateway, Layer 2 access control, hosted MCP infrastructure, and a marketplace of 7,554+ servers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mcpnest.io" rel="noopener noreferrer"&gt;mcpnest.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ricardo Rodrigues is the founder of MCPNest and a Platform Engineer at a large financial institution in Portugal.&lt;/em&gt;&lt;/p&gt;







</description>
      <category>ai</category>
      <category>claude</category>
      <category>mcp</category>
      <category>cursor</category>
    </item>
    <item>
      <title>Why MCP Needs a Governance Layer</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Thu, 14 May 2026 12:53:58 +0000</pubDate>
      <link>https://dev.to/codemalasartes/why-mcp-needs-a-governance-layer-16p8</link>
      <guid>https://dev.to/codemalasartes/why-mcp-needs-a-governance-layer-16p8</guid>
      <description>&lt;p&gt;The MCP ecosystem is at an inflection point. What started as a protocol for connecting AI assistants to external tools has become the default integration layer for a generation of AI-powered engineering tools — Claude, Cursor, Windsurf, GitHub Copilot. Thousands of MCP servers exist. Tens of thousands of developers have installed them.&lt;/p&gt;

&lt;p&gt;Almost none of them have thought about what happens when this goes to production.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Individual Problem Is Solved
&lt;/h2&gt;

&lt;p&gt;For a solo developer, MCP is close to perfect. You find a server, copy a JSON snippet, paste it into your config file, restart your AI client, and you have a new capability. GitHub integration, database access, Slack messaging, web search — all available in natural language. The friction is low enough that exploration is easy.&lt;/p&gt;

&lt;p&gt;The MCP ecosystem solved the individual problem well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Team Problem Is Not
&lt;/h2&gt;

&lt;p&gt;The moment a second person joins, the model breaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication.&lt;/strong&gt; You have a workspace token. You share it with your team. Now everyone has the same access to every tool. You cannot differentiate between what Alice is allowed to do and what Bob is allowed to do. You cannot revoke Bob's access without rotating the token — which breaks every AI client on the team simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment.&lt;/strong&gt; Most MCP servers run as local stdio processes via npx. They exist only on the machine where they were installed. They cannot be shared across a team. They cannot be put behind a gateway. They cannot be monitored or audited. When a developer leaves, their MCP servers leave with them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visibility.&lt;/strong&gt; When something goes wrong — when a production database gets queried unexpectedly, when a CI/CD pipeline is triggered by an agent, when sensitive data appears in a context where it should not — you cannot answer the most basic post-incident question: "which agent called which tool, and when?" There is no log. There is no audit trail. There is no answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quality.&lt;/strong&gt; 7,500+ MCP servers exist. GitHub stars measure historical interest, not current health. A server with 3,000 stars may not have had a commit in 18 months. There is no quality signal. There is no trust layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters Now
&lt;/h2&gt;

&lt;p&gt;AI agents are moving toward production infrastructure. They are not just answering questions — they are writing code, querying databases, triggering deployments, sending messages. The tools they use via MCP are real tools with real access to real systems.&lt;/p&gt;

&lt;p&gt;The governance problem is not theoretical. It is the same problem that made API keys dangerous before OAuth, that made server access chaotic before centralised identity providers, that made network access ungovernable before Zero Trust. Every time a powerful capability becomes accessible to teams, governance follows — because it has to.&lt;/p&gt;

&lt;p&gt;MCP is at the API key moment. The capability exists. The governance does not.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Governance for MCP Looks Like
&lt;/h2&gt;

&lt;p&gt;A governance layer for MCP needs to answer four questions consistently:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Who is using which tools?&lt;/strong&gt;&lt;br&gt;
Every tool call must be attributable to a specific person. Not "the workspace called something" — "Alice called the database query tool." Member-level attribution requires per-member tokens and protocol-level logging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. What is each person allowed to do?&lt;/strong&gt;&lt;br&gt;
Access control must operate at the tool level, not the workspace level. The security engineer should not have the same MCP permissions as the junior developer. Tool allowlists per member enforce least privilege at the protocol layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. How do you revoke access instantly?&lt;/strong&gt;&lt;br&gt;
When someone leaves the team, their access must be gone in seconds. Without touching anyone else's configuration. Without rotating credentials that break the whole team. Per-member tokens make this possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Where do the servers run?&lt;/strong&gt;&lt;br&gt;
Local stdio processes are ungovernable by design. MCP servers need to run in isolated environments with defined lifecycles — deployable, monitorable, and terminatable without touching developer machines.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Category That Does Not Exist Yet
&lt;/h2&gt;

&lt;p&gt;Enterprise MCP governance is not a product category yet. It will be.&lt;/p&gt;

&lt;p&gt;The same pattern has played out in every previous infrastructure layer. API management was chaos before control planes emerged. Identity was chaos before centralised providers. Network access was chaos before Zero Trust made it manageable.&lt;/p&gt;

&lt;p&gt;MCP is the next layer. The governance problem is structural, not optional. And the window to define this category is open now — before the major platforms build their own solutions, before the ecosystem consolidates, before the standard emerges.&lt;/p&gt;

&lt;p&gt;The teams that govern MCP today will not be scrambling to retrofit security into production deployments tomorrow.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ricardo Rodrigues is the founder of MCPNest.io and a Platform Engineer at a large financial institution in Portugal. MCPNest.io is the enterprise governance layer for MCP servers — Gateway, per-member access control, hosted infrastructure, and audit logging.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;mcpnest.io&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>claude</category>
    </item>
    <item>
      <title>From Developer Laptops to Isolated Containers — Enterprise MCP Infrastructure with MCPNest</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Sat, 09 May 2026 22:56:00 +0000</pubDate>
      <link>https://dev.to/codemalasartes/from-developer-laptops-to-isolated-containers-enterprise-mcp-infrastructure-with-mcpnest-3phj</link>
      <guid>https://dev.to/codemalasartes/from-developer-laptops-to-isolated-containers-enterprise-mcp-infrastructure-with-mcpnest-3phj</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;The MCP ecosystem is growing fast. Anthropic, Microsoft, Google, AWS, and Cloudflare are all publishing official MCP servers. Developers are connecting AI tools — Claude, Cursor, Windsurf — to databases, internal APIs, GitHub, and business systems.&lt;/p&gt;

&lt;p&gt;The infrastructure for doing this at an individual level is mature. The infrastructure for doing this at an enterprise level does not exist.&lt;/p&gt;

&lt;p&gt;Today, at most engineering teams, MCP servers run on developer laptops via npx. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Credentials stored in JSON files on individual machines&lt;/li&gt;
&lt;li&gt;No isolation between the MCP server and the host system&lt;/li&gt;
&lt;li&gt;No central visibility into what is running&lt;/li&gt;
&lt;li&gt;No clean offboarding when a developer leaves&lt;/li&gt;
&lt;li&gt;No audit trail of what tools were called or what data was accessed
This is not a theoretical risk. It is the default state of every engineering team that has adopted MCP tooling without a governance layer.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What We Built
&lt;/h2&gt;

&lt;p&gt;The MCPNest Orchestrator is the infrastructure layer that fixes this.&lt;/p&gt;

&lt;p&gt;Instead of running MCP servers locally, the Orchestrator manages isolated Docker containers on central infrastructure. Developers deploy from the workspace dashboard. The AI client connects to the MCPNest Gateway, which authenticates the request, checks the tool allowlist, and proxies to the hosted container.&lt;/p&gt;

&lt;p&gt;Nothing changes in the developer workflow. Everything changes in visibility and control.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Claude / Cursor / Windsurf
  ↓ Bearer mng_xxx (per-member token)
MCPNest Gateway (Next.js on Vercel)
  ↓ Auth + allowlist check + audit log
MCPNest Orchestrator (FastAPI on Hetzner, Nuremberg EU)
  ↓ Docker socket
MCP Bridge Container
  ↓ stdio
MCP Server (npx package)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Gateway handles authentication and authorisation. The Orchestrator handles the container lifecycle. The Bridge handles protocol translation between HTTP and stdio.&lt;/p&gt;




&lt;h2&gt;
  
  
  The MCP Bridge
&lt;/h2&gt;

&lt;p&gt;Most MCP servers speak stdio — they expect to be launched as a subprocess and communicate via stdin/stdout. The Gateway speaks HTTP.&lt;/p&gt;

&lt;p&gt;The Bridge is a FastAPI application that wraps any stdio MCP server as an HTTP endpoint. It launches the MCP server as a subprocess on startup, performs the MCP handshake, and exposes two HTTP endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST /tools/list&lt;/code&gt; — returns the server tool definitions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /tools/call&lt;/code&gt; — proxies a tool call to the subprocess
The Bridge image pre-installs 12 MCP server packages to avoid cold-start delays:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@modelcontextprotocol/server-filesystem
@modelcontextprotocol/server-github
@modelcontextprotocol/server-postgres
@modelcontextprotocol/server-memory
@modelcontextprotocol/server-everything
@modelcontextprotocol/server-sequential-thinking
@modelcontextprotocol/server-brave-search
@modelcontextprotocol/server-slack
@modelcontextprotocol/server-puppeteer
@upstash/context7-mcp
@notionhq/notion-mcp-server
mcp-server-sqlite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server to run is passed via the &lt;code&gt;MCP_COMMAND&lt;/code&gt; environment variable. The Bridge reads it on startup using &lt;code&gt;shlex.split&lt;/code&gt;, launches the subprocess, performs the MCP initialize handshake, and begins listening on port 8080.&lt;/p&gt;

&lt;p&gt;If the subprocess closes stdout before the handshake completes — which happens when a server requires credentials that were not provided — the Bridge raises a &lt;code&gt;RuntimeError&lt;/code&gt; and the container exits. This is by design: servers that require credentials must have them configured before deploy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Container Security
&lt;/h2&gt;

&lt;p&gt;Every container the Orchestrator starts is hardened at the Docker level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cap_drop ALL&lt;/strong&gt;&lt;br&gt;
Removes all Linux capabilities from the container. The MCP server process has zero elevated permissions. It cannot bind to privileged ports, modify network interfaces, or perform any operation that requires elevated access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;no-new-privileges&lt;/strong&gt;&lt;br&gt;
Prevents the process from gaining additional privileges via setuid binaries or file capabilities. Even if the MCP server package contains a setuid binary, it cannot use it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource limits&lt;/strong&gt;&lt;br&gt;
CPU and memory limits are enforced per container based on the resource profile (small / medium / large). This prevents runaway processes and resource exhaustion that could affect other containers on the same host.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dedicated Docker network&lt;/strong&gt;&lt;br&gt;
All hosted containers run on a dedicated Docker network (&lt;code&gt;mcpnest_hosted&lt;/code&gt;), isolated from the host network. Containers cannot reach the host network directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-root user&lt;/strong&gt;&lt;br&gt;
The Bridge runs as a non-root &lt;code&gt;bridge&lt;/code&gt; user inside the container. The MCP server subprocess inherits this user context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credential isolation&lt;/strong&gt;&lt;br&gt;
Credentials are passed as environment variables to the container at deploy time. They are never logged by the Orchestrator (explicitly excluded from logs), never stored in plain text in the database, and never visible to developers after submission.&lt;/p&gt;


&lt;h2&gt;
  
  
  Credential Management
&lt;/h2&gt;

&lt;p&gt;Not all MCP servers start cleanly without configuration. Servers like the GitHub MCP server require a Personal Access Token. The PostgreSQL server requires a connection string. Slack requires a bot token and team ID.&lt;/p&gt;

&lt;p&gt;Without credential management, these servers fail silently — the subprocess closes stdout before the handshake completes and the container exits with an error that is difficult to diagnose.&lt;/p&gt;

&lt;p&gt;We solved this with a &lt;code&gt;required_env_vars&lt;/code&gt; column in the &lt;code&gt;mcp_allowed_images&lt;/code&gt; table. Each entry defines the credentials a server needs, with a key, label, type (text or password), and help text.&lt;/p&gt;

&lt;p&gt;When a developer clicks Deploy on a server that has required credentials, a modal opens before the deploy request is sent. The modal collects the values — clearly labelled, with help text, password inputs masked. Only when all required fields are filled can the developer proceed.&lt;/p&gt;

&lt;p&gt;The values are passed directly to the Orchestrator in the deploy request body and injected as environment variables into the container. They are never written to disk on the host and never appear in Orchestrator logs.&lt;/p&gt;

&lt;p&gt;When a developer's access is revoked, their Bearer token is invalidated at the Gateway level. The hosted containers continue running for other team members unaffected. The credentials inside the containers are not exposed.&lt;/p&gt;


&lt;h2&gt;
  
  
  Deploy Flow
&lt;/h2&gt;

&lt;p&gt;The full flow from click to running container:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Developer clicks Deploy in the workspace Hosted tab&lt;/li&gt;
&lt;li&gt;If the server has &lt;code&gt;required_env_vars&lt;/code&gt;, a modal collects the credentials before the request is sent&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;POST /api/hosted&lt;/code&gt; request goes to the Next.js API route with the server slug and credentials&lt;/li&gt;
&lt;li&gt;The API route creates an instance record in Supabase with status &lt;code&gt;starting&lt;/code&gt; and forwards the deploy request to the Orchestrator&lt;/li&gt;
&lt;li&gt;The Orchestrator checks if the Bridge image is already present locally using &lt;code&gt;docker.images.get()&lt;/code&gt; — skips pull if found, pulls only if not cached&lt;/li&gt;
&lt;li&gt;The Orchestrator starts the container with &lt;code&gt;cap_drop ALL&lt;/code&gt;, &lt;code&gt;no-new-privileges&lt;/code&gt;, resource limits, and the credentials as environment variables&lt;/li&gt;
&lt;li&gt;The Orchestrator updates the instance record in Supabase with status &lt;code&gt;running&lt;/code&gt; and the assigned host port&lt;/li&gt;
&lt;li&gt;The Next.js API route returns the &lt;code&gt;instance_id&lt;/code&gt; to the client&lt;/li&gt;
&lt;li&gt;The workspace UI opens a terminal modal that polls &lt;code&gt;/api/hosted/{id}/logs&lt;/code&gt; every 3 seconds&lt;/li&gt;
&lt;li&gt;When the container reaches RUNNING + HEALTHY state (Docker health check passing), the modal updates automatically and stops polling
The real-time deploy console shows the container logs as they stream. The developer sees the MCP server startup output — including any errors — in real time. There is no need to SSH into the server or use Docker CLI.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  The Pull-Skip Optimisation
&lt;/h2&gt;

&lt;p&gt;Early in development, every deploy attempt pulled the Bridge image from the registry, even though the image is local-only and was never pushed to Docker Hub. This caused every deploy to fail with a &lt;code&gt;pull access denied&lt;/code&gt; error.&lt;/p&gt;

&lt;p&gt;The fix was simple but important: check if the image exists locally before attempting a pull.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Image %s already present locally, skipping pull&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_event_loop&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;run_in_executor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to pull image &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also makes deploys faster — there is no network round-trip for images that are already cached on the host.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Gives Enterprise Teams
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Isolation&lt;/strong&gt;&lt;br&gt;
MCP servers run in sandboxed containers. A misconfigured or compromised server cannot access the host system or interfere with other containers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Central credential management&lt;/strong&gt;&lt;br&gt;
No credentials on developer machines. No JSON files with GitHub tokens or database connection strings on laptops. Clean offboarding — when a developer leaves, their Gateway token is revoked and their access is gone immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audit trail&lt;/strong&gt;&lt;br&gt;
Every tool call is logged at the Gateway level — member, server, tool name, latency, HTTP status, timestamp. No inputs or outputs are stored. GDPR safe by design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistent infrastructure&lt;/strong&gt;&lt;br&gt;
Every developer on the team deploys from the same verified catalog. No drift between machines, no manual setup, no "works on my machine" issues with MCP server configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visibility&lt;/strong&gt;&lt;br&gt;
Real-time deploy logs during startup. Per-instance log viewer for ongoing debugging. Health monitoring with automatic RUNNING + HEALTHY detection. Terminate with full cleanup — container removed, database record updated.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current State
&lt;/h2&gt;

&lt;p&gt;The Orchestrator runs on a dedicated Hetzner server in Nuremberg, EU. All state is managed in Supabase (Frankfurt, EU). The Gateway runs on Vercel's edge network.&lt;/p&gt;

&lt;p&gt;12 verified MCP servers are available in the hosted catalog today: filesystem, GitHub, PostgreSQL, Notion, Context7, Slack, SQLite, Brave Search, Puppeteer, Memory, Sequential Thinking, Everything.&lt;/p&gt;

&lt;p&gt;SOC 2 Type 1 is planned. Self-host via Docker is available for teams that require on-premise deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The MCP ecosystem is at the same inflection point that npm was in 2012 — growing fast, with tooling that works well for individuals and not yet for enterprises.&lt;/p&gt;

&lt;p&gt;The gap is not in the protocol. The protocol is solid. The gap is in infrastructure, governance, and auditability.&lt;/p&gt;

&lt;p&gt;Running MCP servers on developer laptops is the path of least resistance. It works until it doesn't — until a developer leaves with credentials, until a server is misconfigured and accesses something it shouldn't, until a security team asks what tools the AI has been calling and nobody can answer.&lt;/p&gt;

&lt;p&gt;The MCPNest Orchestrator is the infrastructure layer that closes that gap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mcpnest.io&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>claude</category>
      <category>cursor</category>
    </item>
    <item>
      <title>MCPNest — One Month. The Problem, The Solution, Every Feature Explained.</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Tue, 05 May 2026 23:27:57 +0000</pubDate>
      <link>https://dev.to/codemalasartes/mcpnest-one-month-the-problem-the-solution-every-feature-explained-2ad8</link>
      <guid>https://dev.to/codemalasartes/mcpnest-one-month-the-problem-the-solution-every-feature-explained-2ad8</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;The MCP ecosystem is expanding at an extraordinary pace. Anthropic, Microsoft, Google, AWS, and Cloudflare are all publishing official MCP servers. Hundreds of open source servers exist for every conceivable integration. Developers are connecting AI tools — Claude, Cursor, Windsurf — to internal databases, codebases, APIs, and filesystems.&lt;/p&gt;

&lt;p&gt;The infrastructure for doing this exists. The governance layer does not.&lt;/p&gt;

&lt;p&gt;Today, at most engineering teams:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every developer runs MCP servers on their own machine&lt;/li&gt;
&lt;li&gt;There is no central record of what servers are active&lt;/li&gt;
&lt;li&gt;There is no audit trail of what tools were called, by whom, or when&lt;/li&gt;
&lt;li&gt;Credentials — GitHub personal access tokens, database connection strings, API keys — are stored in JSON files on developer laptops&lt;/li&gt;
&lt;li&gt;There is no approval process for which servers developers can use&lt;/li&gt;
&lt;li&gt;There is no isolation — MCP servers run with the full permissions of the local user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the gap MCPNest fills.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Platform
&lt;/h2&gt;

&lt;p&gt;MCPNest is the governance and infrastructure platform for MCP servers. It operates across three layers: a marketplace for discovery, a gateway for control, and a hosted infrastructure layer for isolation and centralisation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 1 — Marketplace
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A searchable catalogue of 7,500+ MCP servers indexed from the official Anthropic registry and GitHub. Every server has a quality score, compatibility matrix, publisher profile, and install configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What problem it solves&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Without a central catalogue, developers find MCP servers through GitHub searches, Reddit posts, and blog articles. There is no quality signal, no verification, no compatibility information. Teams end up with inconsistent tooling and no visibility into what is actually being used.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;7,500+ servers indexed with quality scores and compatibility filters&lt;/li&gt;
&lt;li&gt;One-click install for Cursor and VS Code&lt;/li&gt;
&lt;li&gt;Publisher profiles with verified badges&lt;/li&gt;
&lt;li&gt;Server of the Week editorial picks&lt;/li&gt;
&lt;li&gt;Collections and curated starter packs&lt;/li&gt;
&lt;li&gt;Config Validator — validates syntax, endpoints, and arguments before installation&lt;/li&gt;
&lt;li&gt;MCP Composer — build multi-server configurations and share via link&lt;/li&gt;
&lt;li&gt;Trending servers with weekly install data&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Layer 2 — Gateway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A single authenticated HTTPS endpoint per workspace. Every developer on the team points their AI client at the same Gateway URL. The Gateway authenticates the request, checks the tool allowlist, proxies to the correct upstream server, and logs the call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What problem it solves&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Without a gateway, every developer maintains their own local configuration. When a server changes, everyone updates manually. There is no central authentication, no audit, and no way to enforce which tools developers can use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single endpoint per workspace&lt;/strong&gt;&lt;br&gt;
One URL replaces individual configurations across every developer machine. When the admin adds or removes a server, the change is immediate for the entire team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bearer token authentication (SHA-256)&lt;/strong&gt;&lt;br&gt;
Every request is authenticated. Tokens are stored as SHA-256 hashes with timing-safe comparison. No plain text secrets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-member tokens&lt;/strong&gt;&lt;br&gt;
Each developer has their own Bearer token. This means every tool call is attributable to a specific individual, not just to the workspace. Tokens can be revoked instantly for any member without affecting the rest of the team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool allowlists per member&lt;/strong&gt;&lt;br&gt;
Admins define which tools each developer can call at the protocol level. A developer with access to the GitHub MCP server can be restricted to specific tools — for example, read-only operations only. Workspace-wide enforcement toggle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full audit log per tool call&lt;/strong&gt;&lt;br&gt;
Every call is logged with: workspace ID, member ID, server, tool name, HTTP status, latency, timestamp, and error code where applicable. No inputs or outputs are stored — only metadata. GDPR safe by design. Logs are exportable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool namespacing&lt;/strong&gt;&lt;br&gt;
Automatic conflict resolution when multiple servers expose tools with the same name. No manual configuration required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workspace RBAC&lt;/strong&gt;&lt;br&gt;
Three roles: Owner, Admin, Member. Only Admins can approve servers for the workspace. Separation of duties between team management and tool usage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 3 — Hosted Infrastructure
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MCP servers running in isolated Docker containers on central infrastructure, managed by the MCPNest Orchestrator. Developers deploy servers from a catalogue via the workspace dashboard. The AI client connects to the Gateway, which proxies to the hosted container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What problem it solves&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Running MCP servers locally means no isolation, no central credential management, no shared infrastructure, and no visibility into what is actually running. When a developer's laptop is lost or stolen, every credential in every local config file is exposed. When a developer leaves the company, there is no clean offboarding process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;12 verified servers available for one-click deploy&lt;/strong&gt;&lt;br&gt;
Filesystem, GitHub, PostgreSQL, Notion, Context7, Slack, SQLite, Brave Search, Puppeteer, Memory, Sequential Thinking, Everything. All pre-validated and running on the MCPNest Bridge image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Container isolation&lt;/strong&gt;&lt;br&gt;
Every container runs with: cap_drop ALL (zero Linux capabilities), no-new-privileges flag, CPU and memory resource limits enforced, dedicated Docker network per workspace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credential management&lt;/strong&gt;&lt;br&gt;
Servers that require credentials — GitHub personal access tokens, database connection strings, Slack bot tokens, API keys — prompt for them via a modal before deploy. Credentials are encrypted and never logged. Developers never see or store them locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-time deploy console&lt;/strong&gt;&lt;br&gt;
A terminal modal streams container logs during startup. The system auto-detects RUNNING + HEALTHY state and closes automatically. No manual refresh required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-instance log viewer&lt;/strong&gt;&lt;br&gt;
Every running instance has a Logs button that shows the last 50 lines of container output. Debugging without SSH access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminate with cleanup&lt;/strong&gt;&lt;br&gt;
Stopping a server removes the container and cleans the database record. No orphaned containers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP Bridge&lt;/strong&gt;&lt;br&gt;
A stdio-to-HTTP adapter that wraps any npx-based MCP server into an HTTP endpoint compatible with the Gateway. Enables hosting of any MCP server without modifying its source.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security and Compliance
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt;&lt;br&gt;
All infrastructure is EU-based. Supabase (Frankfurt) for the database. Hetzner (Nuremberg) for the orchestrator and hosted containers. Vercel edge network for the application layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token security&lt;/strong&gt;&lt;br&gt;
Bearer tokens are stored as SHA-256 hashes. Timing-safe comparison on every request. Per-member tokens enable individual audit trails and instant revocation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data handling&lt;/strong&gt;&lt;br&gt;
No inputs or outputs from tool calls are stored. Only metadata is logged (who, when, which tool, what status). GDPR safe by design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Container security&lt;/strong&gt;&lt;br&gt;
cap_drop ALL removes all Linux capabilities from containers. no-new-privileges prevents privilege escalation. Resource limits prevent noisy neighbour and runaway processes. Dedicated Docker network per workspace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-host&lt;/strong&gt;&lt;br&gt;
The full MCPNest stack is available for self-hosted deployment via Docker for teams that require on-premise infrastructure.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;One month. 14 versions shipped. 7,500+ MCP servers indexed. Enterprise Gateway live. 12 hosted servers operational. Partnerships with Grafana, RailPush, and Context7 confirmed.&lt;/p&gt;

&lt;p&gt;The MCP ecosystem needed a governance layer. MCPNest is it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mcpnest.io&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx75mo5p2m6p3ninmqz3o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx75mo5p2m6p3ninmqz3o.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>claude</category>
      <category>openai</category>
    </item>
    <item>
      <title>Hosting MCP Servers at Scale: The Orchestrator</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Wed, 29 Apr 2026 20:39:35 +0000</pubDate>
      <link>https://dev.to/codemalasartes/hosting-mcp-servers-at-scale-the-orchestrator-517o</link>
      <guid>https://dev.to/codemalasartes/hosting-mcp-servers-at-scale-the-orchestrator-517o</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fadnaa4tyqdj8x2viqkcz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fadnaa4tyqdj8x2viqkcz.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;How MCPNest deploys isolated Docker containers for MCP servers and routes tool calls intelligently across your workspace.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;MCP servers have a deployment problem.&lt;/p&gt;

&lt;p&gt;Most servers are stdio-based — they run as a subprocess via &lt;code&gt;npx&lt;/code&gt; and communicate over stdin/stdout. That works fine on a developer's laptop. It does not work for a team.&lt;/p&gt;

&lt;p&gt;You cannot share a stdio process across machines. You cannot health-check it remotely. You cannot restart it when it crashes without someone noticing. You cannot give five engineers access to the same instance running on one person's laptop.&lt;/p&gt;

&lt;p&gt;The standard solution is to wrap stdio servers in an HTTP adapter and deploy them to a server. The problem: that is significant infrastructure work for every MCP server you want to use. Dockerfile, networking, health checks, restart policies, resource limits — multiply that by every server your team needs.&lt;/p&gt;

&lt;p&gt;We built MCPNest Hosted Servers to handle all of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  How hosted MCP servers work
&lt;/h2&gt;

&lt;p&gt;When you click Deploy in your workspace Hosted tab, MCPNest:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates an instance record in the database (&lt;code&gt;status: pending&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Sends a deploy request to the MCPNest Orchestrator service&lt;/li&gt;
&lt;li&gt;Orchestrator pulls the verified image from our allowlist&lt;/li&gt;
&lt;li&gt;Orchestrator starts the container with security hardening applied&lt;/li&gt;
&lt;li&gt;Orchestrator polls health until the container responds&lt;/li&gt;
&lt;li&gt;Updates the instance to &lt;code&gt;status: running, health_status: healthy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The server automatically appears in your Gateway &lt;code&gt;tools/list&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Total time measured in production today: &lt;strong&gt;6 seconds from click to RUNNING + HEALTHY&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bridge layer
&lt;/h2&gt;

&lt;p&gt;Inside each hosted container runs MCPNest Bridge — a FastAPI server on port 8080 that translates between HTTP (external) and stdio JSON-RPC (internal).&lt;/p&gt;

&lt;p&gt;Bridge handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP protocol handshake (&lt;code&gt;initialize&lt;/code&gt; → &lt;code&gt;notifications/initialized&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Managing the stdio subprocess lifecycle&lt;/li&gt;
&lt;li&gt;Translating &lt;code&gt;POST /tools/list&lt;/code&gt; → &lt;code&gt;tools/list&lt;/code&gt; JSON-RPC request → response&lt;/li&gt;
&lt;li&gt;Translating &lt;code&gt;POST /tools/call&lt;/code&gt; → &lt;code&gt;tools/call&lt;/code&gt; JSON-RPC request → response&lt;/li&gt;
&lt;li&gt;Draining stderr in the background so it never blocks the main process&lt;/li&gt;
&lt;li&gt;asyncio.Lock per request to prevent concurrent stdio corruption&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The subprocess command is configurable per image via the &lt;code&gt;mcp_allowed_images&lt;/code&gt; table. For &lt;code&gt;node:20-alpine&lt;/code&gt; with &lt;code&gt;@modelcontextprotocol/server-filesystem&lt;/code&gt;, the command is &lt;code&gt;npx -y @modelcontextprotocol/server-filesystem /workspace&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security model
&lt;/h2&gt;

&lt;p&gt;Every container runs with these constraints — no exceptions, not configurable by the user:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Process isolation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;no-new-privileges: true&lt;/code&gt; — no privilege escalation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cap_drop: ALL&lt;/code&gt; — all Linux capabilities dropped&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cap_add: [CHOWN, SETUID, SETGID]&lt;/code&gt; — only minimum needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Network isolation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Containers bind to &lt;code&gt;127.0.0.1&lt;/code&gt; only — never exposed on a public interface&lt;/li&gt;
&lt;li&gt;Traffic flows: Gateway → Orchestrator → container (all internal)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Filesystem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/tmp&lt;/code&gt; mounted as tmpfs with &lt;code&gt;noexec, nosuid, nodev&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;No host filesystem mounts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU and memory caps enforced at container creation by plan profile&lt;/li&gt;
&lt;li&gt;Small: 0.25 vCPU, 256 MB RAM&lt;/li&gt;
&lt;li&gt;Medium: 0.5 vCPU, 512 MB RAM&lt;/li&gt;
&lt;li&gt;Large: 1.0 vCPU, 1 GB RAM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Image allowlist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only MCPNest-verified images can be deployed&lt;/li&gt;
&lt;li&gt;Images are validated against a regex pattern before pull&lt;/li&gt;
&lt;li&gt;The DB allowlist is the primary gate; the regex is defence-in-depth&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Orchestrator
&lt;/h2&gt;

&lt;p&gt;Above the containers sits the MCPNest Orchestrator — a FastAPI service that aggregates tools from all running instances in a workspace and routes tool calls to the correct container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tools/list aggregation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When your Gateway receives a &lt;code&gt;tools/list&lt;/code&gt; request and &lt;code&gt;orchestrator_enabled&lt;/code&gt; is true, it calls the Orchestrator. The Orchestrator:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Queries the database for all running instances in the workspace&lt;/li&gt;
&lt;li&gt;Fans out &lt;code&gt;POST /tools/list&lt;/code&gt; to each container in parallel&lt;/li&gt;
&lt;li&gt;Collects results, detects naming conflicts&lt;/li&gt;
&lt;li&gt;Applies namespacing: if two servers expose a tool called &lt;code&gt;query&lt;/code&gt;, they become &lt;code&gt;postgres_mcp__query&lt;/code&gt; and &lt;code&gt;mysql_mcp__query&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Caches the result for 30 seconds&lt;/li&gt;
&lt;li&gt;Returns a unified tool list&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;tools/call routing:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a &lt;code&gt;tools/call&lt;/code&gt; arrives, the Orchestrator:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Finds the ToolInfo record for the requested tool name (from cache)&lt;/li&gt;
&lt;li&gt;Looks up the live endpoint URL from the database&lt;/li&gt;
&lt;li&gt;Strips the namespace prefix if present (&lt;code&gt;postgres_mcp__query&lt;/code&gt; → &lt;code&gt;query&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Forwards the call to the correct container&lt;/li&gt;
&lt;li&gt;Logs the call to &lt;code&gt;mcp_tool_calls&lt;/code&gt; (best-effort, non-blocking)&lt;/li&gt;
&lt;li&gt;Returns the result&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Fallback behaviour:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the Orchestrator is unreachable, or if a workspace has no running hosted instances, the Gateway automatically falls back to direct fan-out to remote HTTP servers. No downtime. No manual intervention.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current state
&lt;/h2&gt;

&lt;p&gt;Three verified images are available today:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Server&lt;/th&gt;
&lt;th&gt;Image&lt;/th&gt;
&lt;th&gt;Tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;filesystem-mcp&lt;/td&gt;
&lt;td&gt;node:20-alpine + @modelcontextprotocol/server-filesystem&lt;/td&gt;
&lt;td&gt;read_file, write_file, list_directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;github-mcp&lt;/td&gt;
&lt;td&gt;ghcr.io/modelcontextprotocol/servers:github&lt;/td&gt;
&lt;td&gt;create_issue, list_prs, search_code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;postgres-mcp&lt;/td&gt;
&lt;td&gt;ghcr.io/modelcontextprotocol/servers:postgres&lt;/td&gt;
&lt;td&gt;query, list_tables, describe_table&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Plan limits: Team plan supports 3 running instances per workspace. Enterprise supports 20.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Auth headers per server (bring your own API keys — fixes degraded status on auth-required servers)&lt;/li&gt;
&lt;li&gt;More verified images: Slack, Notion, Linear&lt;/li&gt;
&lt;li&gt;Usage metering per instance for billing&lt;/li&gt;
&lt;li&gt;Auto-deploy via workspace registry URL (&lt;code&gt;mcpnest-registry-client&lt;/code&gt; npm package)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Ricardo Rodrigues — Platform Engineer @ BCP, Founder @ MCPNest&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Porto, Portugal&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCPNest — The App Store for MCP Servers&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://mcpnest.io/workspace" rel="noopener noreferrer"&gt;mcpnest.io/workspace&lt;/a&gt; → Hosted tab&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>claude</category>
      <category>cursor</category>
    </item>
    <item>
      <title>Enterprise MCP Governance: Gateway + Layer 2</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Wed, 29 Apr 2026 20:38:30 +0000</pubDate>
      <link>https://dev.to/codemalasartes/enterprise-mcp-governance-gateway-layer-2-18ea</link>
      <guid>https://dev.to/codemalasartes/enterprise-mcp-governance-gateway-layer-2-18ea</guid>
      <description>&lt;p&gt;&lt;em&gt;One endpoint. Per-member tokens. Full audit trail. How MCPNest solves the team coordination problem for MCP.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;When a team of engineers all use Claude with MCP servers, you have a coordination problem.&lt;/p&gt;

&lt;p&gt;Each person runs their own &lt;code&gt;npx&lt;/code&gt; command. Each person has their own &lt;code&gt;claude_desktop_config.json&lt;/code&gt;. When a server URL changes, someone has to update every config. There is no audit trail. No access control. No way to know who called what tool, when, and with what arguments.&lt;/p&gt;

&lt;p&gt;This is the current state of enterprise MCP usage in 2026. We built two layers to fix it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 1: The Gateway
&lt;/h2&gt;

&lt;p&gt;MCPNest Gateway gives every workspace a single endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://mcpnest.io/api/gw/{workspace-slug}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Behind that endpoint: all the MCP servers your team has approved. One Bearer token. All tools. Every call proxied and logged.&lt;/p&gt;

&lt;p&gt;The Gateway speaks JSON-RPC 2.0 — the MCP standard. Claude, Cursor, and Windsurf connect to it exactly as they would to any MCP server. Your team updates one config file once. When you add or remove a server from your workspace, every connected client sees the change automatically on the next &lt;code&gt;tools/list&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technical implementation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token format: &lt;code&gt;mng_&lt;/code&gt; prefix + 48 hex characters (192 bits of entropy)&lt;/li&gt;
&lt;li&gt;Storage: SHA-256 hash only — the raw token is never stored in plaintext&lt;/li&gt;
&lt;li&gt;Verification: &lt;code&gt;timingSafeEqual()&lt;/code&gt; to prevent timing side-channel attacks&lt;/li&gt;
&lt;li&gt;Rate limiting: 200 requests per minute per IP per workspace slug&lt;/li&gt;
&lt;li&gt;SSE support: streaming responses for MCP servers that use Server-Sent Events&lt;/li&gt;
&lt;li&gt;Tool prefix: configurable per server to avoid naming conflicts (&lt;code&gt;github_create_issue&lt;/code&gt; vs &lt;code&gt;gitlab_create_issue&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Layer 2: Per-Member Access Control
&lt;/h2&gt;

&lt;p&gt;The workspace token is admin-level — full access to all tools. For team members, you create individual Bearer tokens with the same format but different scope.&lt;/p&gt;

&lt;p&gt;Each member token can have an allowlist: &lt;code&gt;server_slug : tool_name&lt;/code&gt; pairs that define exactly which tools the member can call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Owner creates a member token in the workspace Security tab&lt;/li&gt;
&lt;li&gt;Owner defines allowlist rules: &lt;code&gt;github-mcp:list_issues&lt;/code&gt;, &lt;code&gt;grafana:get_dashboard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Owner enables enforcement&lt;/li&gt;
&lt;li&gt;Member uses their token — Gateway checks allowlist on every &lt;code&gt;tools/call&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Blocked calls return error code &lt;code&gt;-32003: Tool not allowed for this user&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Every call is logged with user identity to the audit trail&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The rule logic:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No rules defined: member has full access (open by default)&lt;/li&gt;
&lt;li&gt;Rules defined + enforcement on: member can only call listed tools&lt;/li&gt;
&lt;li&gt;Workspace admin token: always full access regardless of allowlist&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What this looks like in practice
&lt;/h2&gt;

&lt;p&gt;A DevOps team has three MCP servers in their workspace: GitHub, Grafana, and a custom internal deployment server.&lt;/p&gt;

&lt;p&gt;Junior engineers get member tokens with allowlists restricted to read-only operations: &lt;code&gt;github-mcp:list_issues&lt;/code&gt;, &lt;code&gt;grafana:get_dashboard&lt;/code&gt;. They can query and report but not write.&lt;/p&gt;

&lt;p&gt;Senior engineers get tokens with no allowlist restrictions. The deployment server is restricted to the team lead and the CI system.&lt;/p&gt;

&lt;p&gt;All of this configured in the workspace UI. No code changes. No config files to distribute to each team member.&lt;/p&gt;




&lt;h2&gt;
  
  
  The audit log
&lt;/h2&gt;

&lt;p&gt;Every action in a workspace is logged: server added, member invited, tool called, health check run. For tool calls, the log records which user (by member token identity), which server, which tool, and the response latency.&lt;/p&gt;

&lt;p&gt;This is the audit trail your security team asks for. It exists out of the box.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ricardo Rodrigues — Platform Engineer @ BCP, Founder @ MCPNest&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Porto, Portugal&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCPNest — The App Store for MCP Servers&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://mcpnest.io/workspace" rel="noopener noreferrer"&gt;mcpnest.io/workspace&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>claude</category>
      <category>cursor</category>
    </item>
    <item>
      <title>The MCP Discovery Problem</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Wed, 29 Apr 2026 20:29:01 +0000</pubDate>
      <link>https://dev.to/codemalasartes/the-mcp-discovery-problem-3map</link>
      <guid>https://dev.to/codemalasartes/the-mcp-discovery-problem-3map</guid>
      <description>&lt;p&gt;In November 2024, Anthropic released the Model Context Protocol — &lt;br&gt;
a standard that lets AI agents call external tools. Within months, &lt;br&gt;
hundreds of MCP servers appeared on GitHub. Stripe, Grafana, &lt;br&gt;
Cloudflare, AWS — all publishing official servers.&lt;/p&gt;

&lt;p&gt;The problem: there was nowhere to find them.&lt;/p&gt;

&lt;p&gt;Developers were digging through GitHub search, Reddit threads, &lt;br&gt;
and scattered READMEs to find servers that might already exist. &lt;br&gt;
The official Anthropic registry had an API but no UI. &lt;br&gt;
The most starred community lists had tens of thousands of &lt;br&gt;
GitHub stars but weren't searchable or filterable.&lt;/p&gt;

&lt;p&gt;This is the npm problem from 2012. A growing ecosystem &lt;br&gt;
with no discovery layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we built
&lt;/h2&gt;

&lt;p&gt;MCPNest indexes MCP servers from the official Anthropic registry &lt;br&gt;
and GitHub. 7,554 servers as of today, with quality scores, &lt;br&gt;
install counts, compatibility flags per client, and one-click &lt;br&gt;
install configs for Claude Desktop, Cursor, VS Code, and Windsurf.&lt;/p&gt;

&lt;p&gt;Every server page renders the GitHub README, shows the install &lt;br&gt;
config for each client, and tracks installs via a copy button &lt;br&gt;
that increments a counter in Supabase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quality scoring
&lt;/h2&gt;

&lt;p&gt;Not all MCP servers are equal. We score each server 0-100 based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has a valid install config&lt;/li&gt;
&lt;li&gt;Has a description&lt;/li&gt;
&lt;li&gt;Is verified from the official registry&lt;/li&gt;
&lt;li&gt;GitHub stars&lt;/li&gt;
&lt;li&gt;Install count&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The score maps to an A-F grade shown on each server card.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this doesn't solve
&lt;/h2&gt;

&lt;p&gt;Discovery is the easy part. Finding a server is step one. &lt;br&gt;
The harder problems are: running it reliably, giving your team &lt;br&gt;
access to it securely, and managing it at scale.&lt;/p&gt;

&lt;p&gt;That's what we built next.&lt;/p&gt;

&lt;p&gt;→ mcpnest.io&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe46pib9wymkd5z7g2ub8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe46pib9wymkd5z7g2ub8.png" alt=" " width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>mcp</category>
      <category>tooling</category>
    </item>
    <item>
      <title>The MCP Discovery Problem: Why 7,500+ Servers Is Both a Victory and a Warning</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Thu, 23 Apr 2026 16:38:33 +0000</pubDate>
      <link>https://dev.to/codemalasartes/the-mcp-discovery-problem-why-7500-servers-is-both-a-victory-and-a-warning-3joe</link>
      <guid>https://dev.to/codemalasartes/the-mcp-discovery-problem-why-7500-servers-is-both-a-victory-and-a-warning-3joe</guid>
      <description>&lt;p&gt;&lt;em&gt;The ecosystem is growing. But finding the right server is getting harder, not easier.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;There is a number that gets thrown around a lot in the MCP ecosystem right now: 20000+.&lt;/p&gt;

&lt;p&gt;That is roughly how many MCP servers exist as of April 2026. It is an impressive number. A year ago, there were a few dozen. The growth curve looks exactly like npm circa 2012–2015 — exponential, messy, and full of potential.&lt;/p&gt;

&lt;p&gt;But there is a problem nobody is talking about loudly enough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The discovery problem did not get smaller when the ecosystem grew. It got bigger.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  From "does it exist?" to "which one doesn't break in production?"
&lt;/h2&gt;

&lt;p&gt;In early 2025, the question developers asked was simple: &lt;em&gt;is there an MCP server for Postgres? For Slack? For GitHub?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The answer was usually no, or "sort of, check this GitHub repo."&lt;/p&gt;

&lt;p&gt;By April 2026, the answer to almost every "is there an MCP for X?" question is yes — often with four to eight options. The new question is harder: &lt;em&gt;which one is maintained? Which one has an install config that actually works? Which one is still actively developed?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A developer covering the MCP ecosystem at miaoquai.com framed this shift better than I have seen anywhere else — paraphrasing from the original Chinese: users are no longer asking whether an MCP server exists for something. They are asking which one is actually good. That move, from "does it exist?" to "which one is trustworthy?", is how you know an ecosystem is maturing.&lt;/p&gt;

&lt;p&gt;This is the shift from scarcity to noise. And it is the hardest phase of any ecosystem to navigate.&lt;/p&gt;




&lt;h2&gt;
  
  
  The signal problem
&lt;/h2&gt;

&lt;p&gt;When developers browse the 7,561 servers indexed at MCPNest, the most common question is not "is there a server for X?" — it is "which of these four options for X should I actually use?"&lt;/p&gt;

&lt;p&gt;The default answer most people fall back on is GitHub stars. Stars are visible, comparable, and familiar. The problem is that stars measure historical interest. They tell you how many people were excited about a server at some point in the past. They tell you very little about whether it will work today.&lt;/p&gt;

&lt;p&gt;A server can accumulate thousands of stars and then go unmaintained. The stars stay. The maintenance does not.&lt;/p&gt;




&lt;h2&gt;
  
  
  What quality actually means for an MCP server
&lt;/h2&gt;

&lt;p&gt;We built a Quality Score (A–F) for every server in the MCPNest registry. Not because scores are fun — but because without a better signal, developers keep defaulting to star counts.&lt;/p&gt;

&lt;p&gt;The factors we look at:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maintenance velocity.&lt;/strong&gt; When was the last commit? A server updated two weeks ago is categorically different from one updated six months ago, even if the code looks identical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Config completeness.&lt;/strong&gt; Does the server have a working install config for Claude Desktop, Cursor, or VS Code? A server without a valid install config is not really usable by most developers, regardless of what the README says.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verification status.&lt;/strong&gt; Is it listed in the official Anthropic registry? Not a quality guarantee, but a meaningful baseline signal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation depth.&lt;/strong&gt; Does the README explain what the server actually does, what tools it exposes, and what credentials it needs?&lt;/p&gt;

&lt;p&gt;The principle is simple: a well-maintained server with 300 stars should score higher than an abandoned one with 3,000. That is what we are trying to make visible.&lt;/p&gt;




&lt;h2&gt;
  
  
  The npm parallel
&lt;/h2&gt;

&lt;p&gt;npm crossed 100,000 packages in 2015. The JavaScript community went through a long reckoning about package quality, maintenance, and trust — left-pad, node_modules bloat, abandoned dependencies pulling production apps down with them.&lt;/p&gt;

&lt;p&gt;The MCP ecosystem is smaller and moving faster. A similar reckoning will happen. The question is whether the tooling to handle it gets built proactively or reactively.&lt;/p&gt;




&lt;h2&gt;
  
  
  What comes next
&lt;/h2&gt;

&lt;p&gt;Quality scoring is a start, but it is a static snapshot. What matters more is dynamic health — knowing when a server you depend on stops being maintained, or when a previously low-scoring server improves significantly.&lt;/p&gt;

&lt;p&gt;The goal is not to gatekeep the ecosystem. Every server deserves to be discoverable. The goal is to give developers the context to make informed decisions quickly, so they spend less time debugging abandoned configs and more time building.&lt;/p&gt;

&lt;p&gt;7,561 servers indexed is a milestone. But the milestone that actually matters is: how many of those are good, maintained, and ready to use today?&lt;/p&gt;

&lt;p&gt;That is the number we are working on making transparent.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;MCPNest (mcpnest.io) is a marketplace for MCP servers with Quality Scores, one-click install for Claude, Cursor, Windsurf and VS Code, and an enterprise Gateway for teams.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>mcp</category>
      <category>tooling</category>
    </item>
    <item>
      <title>MCPNest Gateway — One URL to Rule All Your MCP Servers</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Wed, 22 Apr 2026 13:35:55 +0000</pubDate>
      <link>https://dev.to/codemalasartes/mcpnest-gateway-one-url-to-rule-all-your-mcp-servers-3ekn</link>
      <guid>https://dev.to/codemalasartes/mcpnest-gateway-one-url-to-rule-all-your-mcp-servers-3ekn</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsx8yp1dmldyay0u7s9du.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsx8yp1dmldyay0u7s9du.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;MCPNest v1.11 | April 2026&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;The MCP ecosystem has a governance problem.&lt;/p&gt;

&lt;p&gt;Developers are installing MCP servers directly into Claude Desktop and Cursor — GitHub integrations, database connectors, web scrapers, API wrappers. The tools are good. The problem is that nobody in IT knows which ones are running, who installed them, or what they're doing.&lt;/p&gt;

&lt;p&gt;This is the problem the MCPNest Gateway solves.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem With How Teams Use MCP Today
&lt;/h2&gt;

&lt;p&gt;When a developer wants to add an MCP server to their Claude Desktop setup, they edit a JSON file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@modelcontextprotocol/server-github"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"GITHUB_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ghp_..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works fine for one developer. It falls apart for a team.&lt;/p&gt;

&lt;p&gt;There is no central list of which servers are approved. No versioning — if a server updates and breaks something, there is no rollback. No audit trail — if Claude connects to an external system and something goes wrong, there is no record of what happened. And no access control — any developer can add any server without approval.&lt;/p&gt;

&lt;p&gt;For individual developers, none of this matters. For a team of 20 at a company that cares about security, it is a governance gap.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Gateway Does
&lt;/h2&gt;

&lt;p&gt;The MCPNest Gateway gives each Enterprise workspace a single authenticated endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;https://mcpnest.io/api/gw/{workspace-slug}
Authorization: Bearer mng_...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of each developer maintaining their own JSON config with multiple servers, they point Claude Desktop or Cursor at this one URL. The Gateway handles everything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tools/list&lt;/strong&gt; — When Claude asks what tools are available, the Gateway calls &lt;code&gt;tools/list&lt;/code&gt; on every server approved in the workspace, aggregates the results, and returns a unified list. From Claude's perspective, it is talking to one server. Behind the scenes, it might be five.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tools/call&lt;/strong&gt; — When Claude calls a tool, the Gateway identifies which server owns that tool and proxies the request. The developer does not need to configure anything. The routing is automatic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logging&lt;/strong&gt; — Every tool call is logged at the protocol level: which tool was called, on which server, with what status code, and how long it took. No input or output content is stored — only metadata. GDPR-safe by design.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The Gateway is built on three files.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;auth.ts&lt;/code&gt; handles token verification. Bearer tokens are stored as SHA-256 hashes — never in plaintext. Comparison uses &lt;code&gt;timingSafeEqual&lt;/code&gt; to prevent timing attacks. Tokens use a &lt;code&gt;mng_&lt;/code&gt; prefix so they are immediately recognisable in logs and distinguishable from other API tokens.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;logging.ts&lt;/code&gt; handles fire-and-forget writes to &lt;code&gt;mcp_tool_calls&lt;/code&gt;. If the table does not exist or the write fails, the proxy continues — logging never blocks a tool call.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;route.ts&lt;/code&gt; handles the actual proxying. It resolves the workspace, verifies the token, parses the JSON-RPC body, fetches tools from each upstream server, and routes calls to the correct endpoint. It supports both JSON and SSE transport — auto-detecting from the response &lt;code&gt;content-type&lt;/code&gt; header — because different MCP servers use different transports.&lt;/p&gt;

&lt;p&gt;The database schema is straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gateway_workspaces&lt;/code&gt; — one row per workspace, with the token hash and plan&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gateway_workspace_servers&lt;/code&gt; — which servers each workspace exposes, with position ordering and optional tool prefix to avoid name collisions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mcp_tool_calls&lt;/code&gt; — append-only log of every tool call, retained for 90 days&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What Gets Logged
&lt;/h2&gt;

&lt;p&gt;Each row in &lt;code&gt;mcp_tool_calls&lt;/code&gt; contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;workspace_id&lt;/code&gt; — which workspace made the call&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;server_slug&lt;/code&gt; — which upstream server handled it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tool_name&lt;/code&gt; — which tool was called&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;status&lt;/code&gt; — HTTP-style status code (200 for success, 4xx for client errors, 5xx for upstream errors)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;latency_ms&lt;/code&gt; — how long the round trip took&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;created_at&lt;/code&gt; — timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing from the input parameters or output content is stored. The log answers "what happened" without storing "what was said."&lt;/p&gt;




&lt;h2&gt;
  
  
  A Real Test
&lt;/h2&gt;

&lt;p&gt;After deploying, I tested with a workspace containing the Context7 MCP server (documentation lookup) at &lt;code&gt;https://mcp.context7.com/mcp&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://mcpnest.io/api/gw/bcp-test &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer mng_..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jsonrpc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"resolve-library-id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"query-docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two tools returned, proxied through the Gateway, logged in &lt;code&gt;mcp_tool_calls&lt;/code&gt;. Latency around 1000ms — the Gateway adds minimal overhead on top of the upstream server response time.&lt;/p&gt;

&lt;p&gt;The Supabase log confirmed 5 calls, all status 200, latencies between 821ms and 1440ms.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Means for Enterprise Teams
&lt;/h2&gt;

&lt;p&gt;The question most IT teams ask when developers start using AI tools is: "What is Claude actually connecting to?"&lt;/p&gt;

&lt;p&gt;Without the Gateway, the answer is "we don't know." Each developer has their own config. Servers come and go. There is no central record.&lt;/p&gt;

&lt;p&gt;With the Gateway, the answer is: every tool call is in &lt;code&gt;mcp_tool_calls&lt;/code&gt;. IT controls which servers are in the workspace. Developers cannot add servers without admin approval. Every action has a timestamp and an owner.&lt;/p&gt;

&lt;p&gt;It is the same principle as an API gateway like Kong or AWS API Gateway, applied to the MCP protocol.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current Limitations
&lt;/h2&gt;

&lt;p&gt;The Gateway v0 works with MCP servers that have a remote HTTP endpoint. Local servers — those that run via &lt;code&gt;npx&lt;/code&gt; or &lt;code&gt;node&lt;/code&gt; on the developer's machine — cannot be proxied because they have no public endpoint to route to. This covers a significant portion of the MCP ecosystem today.&lt;/p&gt;

&lt;p&gt;Servers that require authentication (like RailPush, which needs a Bearer token) need their credentials configured in the workspace &lt;code&gt;config_override&lt;/code&gt;. There is no UI for this yet — it requires a direct database insert.&lt;/p&gt;

&lt;p&gt;There is also no workspace creation UI yet. Workspaces are created via SQL. This is the next thing to build.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Comes Next
&lt;/h2&gt;

&lt;p&gt;The immediate next step is a workspace creation UI — a page where Enterprise users can create a workspace, add servers, generate a Bearer token, and copy the Gateway URL. Right now all of this requires direct database access.&lt;/p&gt;

&lt;p&gt;After that: token rotation UI, per-server health status in the Gateway response, and rate limiting per workspace.&lt;/p&gt;

&lt;p&gt;The longer-term goal is making the Gateway the standard way teams distribute MCP server access — the same way Artifactory or a private npm registry distributes packages, but for MCP servers.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;MCPNest is a marketplace and governance layer for MCP servers. 7,561+ servers indexed. Gateway live since April 20, 2026. Free to use at mcpnest.io — Enterprise for teams.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; MCP, Model Context Protocol, TypeScript, Claude, Enterprise AI, API Gateway, Developer Tools&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>claude</category>
      <category>cursor</category>
    </item>
    <item>
      <title>The MCP Generator — Scaffold a Working MCP Server in 60 Seconds With Plain English</title>
      <dc:creator>Ricardo Rodrigues</dc:creator>
      <pubDate>Mon, 20 Apr 2026 11:00:11 +0000</pubDate>
      <link>https://dev.to/codemalasartes/the-mcp-generator-scaffold-a-working-mcp-server-in-60-seconds-with-plain-english-58a6</link>
      <guid>https://dev.to/codemalasartes/the-mcp-generator-scaffold-a-working-mcp-server-in-60-seconds-with-plain-english-58a6</guid>
      <description>&lt;p&gt;&lt;em&gt;Published on MCPNest Blog | April 2026&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Most developers who want a custom MCP server don't build one.&lt;/p&gt;

&lt;p&gt;Not because they can't. Because starting is hard.&lt;/p&gt;

&lt;p&gt;Where do you begin? Which SDK version? What's the right file structure? How do you register tools correctly? How do you handle errors? What does &lt;code&gt;claude_desktop_config.json&lt;/code&gt; need to say to load the server?&lt;/p&gt;

&lt;p&gt;These questions cost time. A developer unfamiliar with the MCP SDK typically spends 2-4 hours on setup before writing a single line of actual tool logic. For a solo developer or a platform engineer who already has a full day job, that's the entire Sunday afternoon gone before anything useful runs.&lt;/p&gt;

&lt;p&gt;The barrier to publishing an MCP server is high. The MCP Generator lowers it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;The MCP Generator takes a plain English description — up to 500 characters — and returns a complete MCP server scaffold in TypeScript. What would take 2-4 hours reading SDK documentation takes 30 seconds.&lt;/p&gt;

&lt;p&gt;You describe what you want. The Generator builds the structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input examples:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"A server that fetches real-time weather for any city"&lt;/li&gt;
&lt;li&gt;"An MCP server that queries a Postgres database and lists tables"&lt;/li&gt;
&lt;li&gt;"A server that reads and writes files in a local directory"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt; A JSON object with four fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"weather-mcp-server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fetches real-time weather data for any city using the OpenWeather API"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"// Complete TypeScript MCP server code..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"install"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{ &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;mcpServers&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: { &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;weather-mcp-server&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: { &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;command&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;npx&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;args&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: [&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;-y&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;weather-mcp-server&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;] } } }"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;code&lt;/code&gt; field is a complete TypeScript file — tool registration, request handlers, error handling, and the correct SDK boilerplate. The &lt;code&gt;install&lt;/code&gt; field is the config snippet ready to paste into &lt;code&gt;claude_desktop_config.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;TypeScript always. Not JavaScript. The MCP SDK is TypeScript-first and the Generator follows that convention.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works Under the Hood
&lt;/h2&gt;

&lt;p&gt;The Generator calls the Anthropic API directly — &lt;code&gt;/v1/messages&lt;/code&gt; with Claude Haiku. A specialised system prompt instructs the model to generate MCP servers that follow the correct SDK conventions, register tools with the right schema structure, and output the result as valid JSON.&lt;/p&gt;

&lt;p&gt;This is worth explaining because it matters for what the Generator is and isn't.&lt;/p&gt;

&lt;p&gt;It is not a code database. It is not a template engine. It is Claude, with a very specific prompt, generating TypeScript code for your exact use case on demand.&lt;/p&gt;

&lt;p&gt;That means the output is tailored to your description. It also means the quality of what you get depends on how clearly you describe what you want. A precise description produces a precise scaffold. A vague one produces a generic one.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem It Solves
&lt;/h2&gt;

&lt;p&gt;Building an MCP server from scratch has a steep entry cost even for experienced developers. The official MCP TypeScript SDK is well-documented, but documentation takes time to read. And most of what you need to set up — the server initialisation, the tool list handler, the tool call handler, the transport setup — is identical across every server.&lt;/p&gt;

&lt;p&gt;The parts that are unique to your use case are the tool implementations themselves: the actual logic that calls your API, queries your database, or reads your filesystem. Everything else is boilerplate.&lt;/p&gt;

&lt;p&gt;The Generator handles the boilerplate. You write the logic.&lt;/p&gt;

&lt;p&gt;It's the same principle as &lt;code&gt;create-react-app&lt;/code&gt; or &lt;code&gt;npm init&lt;/code&gt; — not a replacement for knowing how to code, but a fast path to the starting line.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Get
&lt;/h2&gt;

&lt;p&gt;When you run the Generator with a description like "a server that connects to a Postgres database with tools to query tables, list schemas, and run SELECT statements", the output includes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Correct tool registration&lt;/strong&gt; — each tool defined with its name, description, and JSON Schema for input parameters. Missing or incorrect schemas are the most common cause of MCP servers not loading.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Both required request handlers&lt;/strong&gt; — &lt;code&gt;ListToolsRequestSchema&lt;/code&gt; and &lt;code&gt;CallToolRequestSchema&lt;/code&gt;, correctly wired up. Forgetting either breaks the server entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error handling for unknown tools&lt;/strong&gt; — a catch that throws a meaningful error instead of hanging silently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Environment variable placeholders&lt;/strong&gt; — if your server needs an API key or connection string, the Generator uses &lt;code&gt;process.env.YOUR_VAR&lt;/code&gt; with a clear comment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ready-to-use install config&lt;/strong&gt; — the exact JSON snippet for &lt;code&gt;claude_desktop_config.json&lt;/code&gt;, with the correct server name and command.&lt;/p&gt;




&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;The Generator is honest about what it is.&lt;/p&gt;

&lt;p&gt;It produces a scaffold, not a finished server. The tool implementations — the actual calls to your API, the database queries, the file reads — are placeholders that you replace with your own logic. The Generator gives you the correct structure so you don't have to figure that out from documentation. The business logic is yours.&lt;/p&gt;

&lt;p&gt;It requires sign-in to use. This is to prevent abuse of the underlying API call.&lt;/p&gt;

&lt;p&gt;The output is always TypeScript. If you need JavaScript, you can transpile it, but the Generator won't produce JS directly.&lt;/p&gt;

&lt;p&gt;And because it uses a language model to generate code, edge cases or unusual patterns may not always produce exactly what you expect. Treat the output as a strong starting point, not as production-ready code that needs no review.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;The MCP Generator is at &lt;strong&gt;mcpnest.io/tools&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sign in, describe your server, and get your scaffold. Add your logic, push to GitHub, and if you want it in the MCPNest registry, submit it at mcpnest.io/publish.&lt;/p&gt;

&lt;p&gt;If you build something with it and the listing doesn't exist yet, submitting it helps the registry. Every new server makes it more useful for everyone looking for tools.&lt;/p&gt;

&lt;p&gt;And if the Generator produces something wrong, or if there's a pattern it doesn't handle well, tell me: &lt;a href="mailto:malasartes@mcpnest.io"&gt;malasartes@mcpnest.io&lt;/a&gt;. The prompt gets better every time I learn about a gap.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ricardo Rodrigues is the founder of MCPNest and a Platform Engineer at BCP in Porto, Portugal. MCPNest is the marketplace and governance layer for MCP servers — 7,561+ servers indexed, with Enterprise workspaces and a Gateway launching June 2026.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; MCP, Model Context Protocol, TypeScript, Claude, AI Tools, Developer Tools, MCP Generator&lt;/p&gt;

</description>
      <category>automation</category>
      <category>mcp</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
