惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

TaoSecurity Blog
TaoSecurity Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
F
Fortinet All Blogs
Cisco Talos Blog
Cisco Talos Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Secure Thoughts
美团技术团队
雷峰网
雷峰网
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
Engineering at Meta
Engineering at Meta
人人都是产品经理
人人都是产品经理
月光博客
月光博客
T
Tor Project blog
P
Privacy & Cybersecurity Law Blog
Recorded Future
Recorded Future
I
Intezer
博客园 - 【当耐特】
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
GbyAI
GbyAI
罗磊的独立博客
V
V2EX
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
Last Week in AI
Last Week in AI
T
Tailwind CSS Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
A
About on SuperTechFans
Scott Helme
Scott Helme
Vercel News
Vercel News
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
Recent Announcements
Recent Announcements
Hacker News: Ask HN
Hacker News: Ask HN
C
CERT Recently Published Vulnerability Notes
G
Google Developers Blog
B
Blog
博客园 - 叶小钗
WordPress大学
WordPress大学
博客园 - 聂微东
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Jina AI
Jina AI
IT之家
IT之家
C
Cybersecurity and Infrastructure Security Agency CISA
P
Palo Alto Networks Blog
小众软件
小众软件
博客园 - Franky
Microsoft Azure Blog
Microsoft Azure Blog
AWS News Blog
AWS News Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Rediscovering Domain-Driven Design, one MCP server at a time
Dennis Traub · 2026-05-18 · via DEV Community

A few days ago, a devops engineer posted on r/devops:

"MCP servers just showed up in our infrastructure and I genuinely have no idea how to secure them, anyone been through this?"

Filesystem access, shell permissions, database connectors - all callable by agents without human approval. At the time I'm writing this, the thread has 76 upvotes and 39 comments from fellow engineers improvising solutions: "separate by blast radius," "don't mix list_files and execute_shell in one server," "three security surfaces, not one."

They're all describing the same thing. They just don't have the words for it yet.

The patterns they are rediscovering have been formalized in Domain-Driven Design (DDD), by Eric Evans.

In his book, Eric introduced concepts like Bounded Contexts and Anti-Corruption Layers, which gave us the vocabulary we've been using for system boundaries ever since. They helped us survive the microservices transition, and they apply directly to the architectural problems AI systems are creating right now.

We made the same mistakes a decade ago

In the 2010s, many teams adopted microservices without understanding what made them work. They took monoliths, split them apart, and called the pieces "services." More often than not, the result was distributed monoliths - all the operational complexity of distribution with none of the architectural benefits of real, well-defined boundaries.

The correction took years. We learned (painfully) that a microservice boundary isn't where you split the code. It's where you split the mental model you have of the application. A payment service and a user service don't just live in different containers - they have different vocabularies, different invariants, different reasons to change.

And the same mistake is happening again, this time with MCP servers. We wrap existing REST APIs one-to-one and call it AI integration. David Soria Parra, one of the creators of MCP, said "it's a bit cringe, it just results in horrible things" at AI Engineer World's Fair 2025. The Thoughtworks Technology Radar placed "MCP by default" as a Caution. And if you dive into the argument they make, they're both saying the same thing: we're building distributed monoliths again.

But the correction doesn't have to take years this time. The vocabulary already exists - and has been battle-tested for more than 20 years.

Bounded Contexts: one server, one model, one language

A Bounded Context defines where a particular (data or object) model is valid. Inside the boundary, terms have precise meanings: a "transaction" in the finance context means money changing hands, a "transaction" in the booking context means a reservation. Inside each boundary lives one language and one set of rules. Across boundaries, you expect translation.

And MCP is particularly interesting from this angle: the protocol already enforces bounded contexts at the topology level.

MCP's architecture uses a one-client-per-server model. The host spawns a separate client for each MCP server, and each client talks to exactly one server. An MCP server for your database cannot accidentally leak data to an MCP server for your file system. Unlike microservices, where any service can trivially call any other over the network, an MCP server has no protocol-level way to reach another server's tools. You have to deliberately build that bridge. Cross-boundary coupling becomes visible and intentional rather than accidental.

But only if you design your servers as bounded contexts.

The failure mode is an MCP server that exposes everything, including filesystem access, shell execution, and database connectors in a single server. That's three separate concerns crammed into one boundary - the equivalent of a microservice that owns users, payments, and notifications.

The commenter on Reddit who wrote "don't mix list_files and execute_shell in one server" was actually designing context boundaries, even if he didn't know the term.

Anti-Corruption Layers: separating the tools from domain logic

An Anti-Corruption Layer (ACL) prevents one system's model from contaminating another. It translates between two different worldviews.

In AI systems, two fundamentally different models collide every time an agent calls a tool:

  • For the LLM, everything is strings, parameters are simple, and context is a token window. It reasons in natural language to generate structured calls.
  • The domain consists of rich types, configuration, state, complex error handling, and business invariants that must hold regardless of how they're invoked.

The tools layer sits between these two worlds. In Chris Hughes’s words, it “protects your domain from the LLM’s interface requirements - translating between ‘strings the LLM can reason about’ and ‘rich domain objects your code works with’.”

Here's a tool that ignores this principle:

# Everything in one function - LLM interface mixed with domain logic

@mcp.tool()
async def transfer_funds(from_account: str, to_account: str, amount: str):
    amount_decimal = Decimal(amount)
    from_acc = await db.get_account(from_account)

    if from_acc.balance < amount_decimal:
        return "Insufficient funds"

    if from_acc.is_frozen:
        return "Account frozen"

    await db.execute_transfer(from_acc, to_account, amount_decimal)
    await audit_log.record(from_account, to_account, amount_decimal)

    return f"Transferred {amount} from {from_account} to {to_account}"

Enter fullscreen mode Exit fullscreen mode

And here's the same operation with a proper separation:

# Tool layer: thin adapter (the ACL)
@mcp.tool()
async def transfer_funds(from_account: str, to_account: str, amount: str):
    result = await transfer_service.execute(
        from_account=from_account,
        to_account=to_account,
        amount=Decimal(amount)
    )
    return result.to_agent_summary()

# Service layer: domain logic, testable without the LLM
class TransferService:
    async def execute(self, from_account, to_account, amount) -> TransferResult:
        account = await self.accounts.get(from_account)
        account.validate_transfer(amount)  # raises on invariant violation
        transfer = account.initiate_transfer(to_account, amount)
        await self.transfers.save(transfer)
        await self.audit.record(transfer)
        return TransferResult(transfer)

Enter fullscreen mode Exit fullscreen mode

The second version gives you:

  • Testability: the service works without an LLM. Run it from tests, CLI, scripts.
  • Replaceability: change the LLM interface (tool parameters, response format) without touching business logic. Change business rules without touching the tool layer.
  • Composability: other MCP servers, other agents, or humans can call the same service through their own interface.

The ACL protects both sides. The domain doesn't get contaminated by the LLM's string-based worldview. The LLM doesn't get overwhelmed by domain complexity it can't reason about.

The same vocabulary in a new domain

Back to that Reddit thread.

"Separate MCP servers by blast radius." That's bounded context design. Each server owns one domain. The blast radius is contained because the boundary is real.

"Three security surfaces, not one - tool capability, tool description, and tool call chains." The ACL decomposed into its responsibilities. Tool capability is what the domain allows. Tool description is what the LLM thinks it can do. Tool call chains are cross-boundary interactions that need explicit orchestration.

"The dangerous part is not one tool in isolation. It is the chain." In DDD terms: an aggregate invariant violation. A sequence of operations crossing bounded contexts without coordination. Each operation succeeds locally while the system fails globally.

Same patterns, same structural problem, discovered independently because the problem is real.

The "abstraction tax" is the ACL doing its job

One fair criticism is that MCP adds a layer. The Thoughtworks Tech Radar calls this the "abstraction tax" - every protocol layer between an agent and an API loses fidelity. Simon Willison notes that "almost everything I might achieve with an MCP can be handled by a CLI tool instead."

This is correct. And it's exactly the same argument people made against microservice boundaries, API gateways, and anti-corruption layers in traditional systems. The translation layer comes with costs: you lose directness.

But this loss is intentional. It's the ACL doing its job. The LLM doesn't need to know about your domain's internal types, retry logic, or state management. The domain doesn't need to accommodate the LLM's string-based reasoning model. The "tax" buys you isolation, replaceability, and, ultimately, peace of mind.

It's only a mistake if we're paying this tax without getting the architectural benefit - which is exactly what REST-to-MCP 1:1 wrappers do. They add the layer without adding the boundary: all cost, no benefit.

The vocabulary already exists. Let's keep using it.

We don't have to reinvent these patterns - DDD has 20+ years of battle scars. We've learned the hard way where to draw boundaries, how to enforce them, and what happens when we don't. AI or no AI, Eric Evans's Domain-Driven Design is still the canonical reference for complex software systems.

MCP is already designed to establish bounded contexts; the tools layer is already an anti-corruption layer. Name your MCP servers after the domain they own, not the API they wrap, and when someone on your team says "separate by blast radius" - let them know that there are established patterns for what they're describing.