Capstone: Building an Enterprise MCP Tool Ecosystem End-to-End

14 min read Module 10 of 10 Topic 30 of 30

What you'll learn

  • Design a complete enterprise MCP architecture spanning multiple servers, a federation gateway, and shared security infrastructure
  • Trace a single agent request through every layer: auth, routing, tool execution, tracing, and audit logging
  • Identify the operational ownership boundaries between platform, security, and individual product teams in this architecture
  • Trace a compound failure scenario end to end and identify exactly which of the course's safeguards catches it, and at which stage
Building this at your company? For enterprise and company teams taking this to production: book a 30-minute session with our AI engineers for architecture guidance, code review, and a rollout plan for your use case.
Book a Team Session

This capstone does not introduce new mechanisms, it assembles the fifteen preceding lessons’ worth of them into one coherent, production-shaped architecture, traces a single real request through every layer, and then, since a happy-path trace alone under-tests a security-conscious architecture, walks through a second, deliberately compound failure scenario to show how the course’s layered defenses interact when more than one thing goes wrong at once.

The Complete Architecture

flowchart TB
    subgraph clients["Agent Clients"]
        Sales["Sales Agent\n(Claude Agent SDK)"]
        Support["Support Agent\n(LangGraph)"]
        Internal["Internal Ops Agent\n(self-hosted gpt-oss-120b\n+ tool-calling harness)"]
    end

    subgraph platform["Shared Platform Infrastructure"]
        AuthZ["OAuth 2.1 Authorization Server\n(enterprise IdP)"]
        Registry["Internal MCP Registry\n(self-registration, health)"]
        Gateway["Federation Gateway\n(namespacing, routing,\nauth pass-through)"]
        Otel["OpenTelemetry Collector\n(traces, metrics)"]
    end

    subgraph servers["Team-Owned MCP Servers"]
        CRM["crm MCP Server\n(Sales/RevOps team)"]
        KB["kb MCP Server\n(Support team)"]
        SupportSys["support MCP Server\n(Support team)"]
        DW["warehouse MCP Server\n(Data Platform team)"]
    end

    Sales -->|"1. OAuth token"| AuthZ
    Sales -->|"2. tools/call\n(bearer token)"| Gateway
    Support --> Gateway
    Internal --> Gateway

    Gateway -->|"3. validate token"| AuthZ
    Gateway -->|"4. resolve healthy servers"| Registry
    Gateway -->|"5. route namespaced call"| CRM
    Gateway --> KB
    Gateway --> SupportSys
    Gateway --> DW

    CRM -.->|traces + audit logs| Otel
    KB -.->|traces + audit logs| Otel
    SupportSys -.->|traces + audit logs| Otel
    DW -.->|traces + audit logs| Otel
    Gateway -.->|traces| Otel

    style Sales fill:#EEF0F7,stroke:#6366F1,color:#0F172A
    style Support fill:#EEF0F7,stroke:#6366F1,color:#0F172A
    style Internal fill:#EEF0F7,stroke:#6366F1,color:#0F172A
    style AuthZ fill:#fff7ed,stroke:#f59e0b,color:#0F172A
    style Registry fill:#fff7ed,stroke:#f59e0b,color:#0F172A
    style Gateway fill:#f0fdf9,stroke:#0D9488,color:#0F172A
    style Otel fill:#fff7ed,stroke:#f59e0b,color:#0F172A
    style CRM fill:#EEF0F7,stroke:#6366F1,color:#0F172A
    style KB fill:#EEF0F7,stroke:#6366F1,color:#0F172A
    style SupportSys fill:#EEF0F7,stroke:#6366F1,color:#0F172A
    style DW fill:#EEF0F7,stroke:#6366F1,color:#0F172A

Tracing One Request Through Every Layer: The Happy Path

A sales agent asks: “What’s the status of Acme Corp’s most recent support ticket?”

sequenceDiagram
    participant Agent as Sales Agent
    participant Gateway as Federation Gateway
    participant AuthZ as OAuth Server
    participant Registry
    participant SupportSrv as support MCP Server
    participant Otel as OTel Collector

    Agent->>AuthZ: Already holds valid bearer token (Module 4)
    Agent->>Gateway: tools/call support.get_latest_ticket(account="Acme")
    Gateway->>AuthZ: Validate token, extract scopes (Lesson 10)
    AuthZ-->>Gateway: subject=sales-agent-42, scopes=[support:read, crm:read]
    Gateway->>Gateway: Check scope covers support.get_latest_ticket (Lesson 12)
    Gateway->>Registry: Resolve healthy endpoint for "support" (Lesson 18)
    Registry-->>Gateway: https://mcp.internal/support/v2, status=healthy
    Gateway->>SupportSrv: tools/call get_latest_ticket(account="Acme")\ntraceparent propagated (Lesson 25)
    SupportSrv->>SupportSrv: Validate input (Module 2),\nquery via parameterized query (Lesson 14)
    SupportSrv-->>Gateway: Structured result
    Gateway-->>Agent: Result
    SupportSrv-->>Otel: Span + audit log entry (Lessons 21, 25)
    Gateway-->>Otel: Span (linked, same trace)

Every lesson in this course maps to a concrete piece of this one request: authentication and scoping (Module 4) gate it before it reaches any server; registry-based routing (Module 6) finds the right healthy backend; the server itself validates input and queries safely (Modules 2 and 5); and tracing plus audit logging (Module 9) make the whole path inspectable after the fact.

A Compound Failure Scenario: When More Than One Thing Goes Wrong

A single happy-path trace under-tests a security-conscious architecture, since it never exercises the layered defenses that matter precisely when something goes wrong. Consider a harder scenario, deliberately stacking two independent problems in the same window: (1) an attacker has embedded an injection payload in a support ticket, per Lesson 19, instructing any agent that reads it to export all CRM records to an external address, and (2) at the same moment, the CRM MCP server happens to be mid-canary-rollout (Lesson 29) of a new version, and that new version has an authorization bug causing it to under-check the crm:export scope for certain callers.

flowchart TD
    Injection["Injected instruction in a\nsupport ticket (Lesson 19)"] --> Agent["Agent reads ticket,\nreasoning is influenced"]
    Agent -->|"attempts crm_export_all_records"| Gateway["Federation Gateway"]
    Gateway --> Canary["CRM server, canary version\n(authorization bug present)"]
    Canary -->|"BUG: scope check\nunder-enforced"| WouldSucceed["Would otherwise\nproceed to export"]
    WouldSucceed --> ConfirmGate{"confirmation_token\nrequired (Lesson 19/20)?"}
    ConfirmGate -->|"no valid token,\ninjection cannot produce one"| Blocked["Export BLOCKED,\nregardless of the\nauthorization bug"]

    style Injection fill:#fef2f2,stroke:#dc2626,color:#0F172A
    style Agent fill:#EEF0F7,stroke:#6366F1,color:#0F172A
    style Gateway fill:#f0fdf9,stroke:#0D9488,color:#0F172A
    style Canary fill:#fef2f2,stroke:#dc2626,color:#0F172A
    style WouldSucceed fill:#fef2f2,stroke:#dc2626,color:#0F172A
    style ConfirmGate fill:#fff7ed,stroke:#f59e0b,color:#0F172A
    style Blocked fill:#f0fdf9,stroke:#0D9488,color:#0F172A

Even with both failures compounding, the injection succeeding at the reasoning layer and the canary’s authorization check being broken, the export still does not happen, because the confirmation-token requirement on crm_export_all_records (Lessons 19-20) depends on neither of those two things. It requires an out-of-band human approval that no injected text and no buggy in-tool scope check can produce. This is the concrete payoff of defense in depth as a design principle rather than a slogan: no single layer in this course’s architecture is assumed to be perfect, and the layers are chosen so that a failure in one (reasoning-layer injection defense, or a specific tool’s authorization logic) does not automatically cascade into the worst-case outcome, because a different, independent layer still holds. Separately, the canary’s error-rate analysis (Lesson 29) would likely catch the authorization bug itself on its own metrics within the 10% traffic window and roll it back, and the audit log (Lesson 21) would let an investigator confirm afterward exactly which calls were attempted against the canary during the incident window, but neither of those is what actually prevented the export in the moment, the confirmation gate is.

Ownership Boundaries

Shared, cross-cutting infrastructure, the authorization server, the registry, the federation gateway, sits under a platform or security team’s ownership, since every product team depends on it and inconsistency there creates risk broadly. Individual MCP servers (CRM, support, knowledge base, data warehouse) are owned by the teams closest to that system’s data and domain logic, following the same pattern as any other well-run platform engineering organization. This split is what lets the CRM team ship a new tool version on their own schedule (Lesson 16’s versioning discipline) without needing platform team involvement, while still inheriting consistent authentication, discovery, and observability for free, and it is also what lets the CRM team’s own canary rollout mistake, in the scenario above, be contained by shared, non-negotiable controls (the confirmation gate) that no individual team’s rollout schedule can bypass.

Where to Go From Here

You have now built, secured, and operated a complete MCP-based enterprise tool ecosystem: protocol fundamentals, a real server with validated tools and resources, authentication and fine-grained authorization, integrations across REST APIs, databases, and SaaS systems, versioning and federation across many servers, defenses against the injection and confused-deputy risks specific to agent-facing infrastructure, connections to Claude, other model providers, and self-hosted open-weight models, and the observability, testing, and CI/CD discipline that keeps all of it reliable in production, plus, in this closing scenario, a concrete demonstration of why no single one of those layers is meant to carry the whole burden alone. The natural next step is applying this architecture to your own organization’s systems, starting with the single highest-value integration and expanding outward using the same patterns, and, as new tools are added over time, deliberately asking of each one: which of this course’s layers actually stops the worst-case misuse of this specific tool, and is that layer something a bug elsewhere in the system could quietly disable.

Knowledge Check

3 questions to test your understanding

1 In the capstone architecture, which team should own the OAuth 2.1 authorization server and the internal MCP registry, versus which team should own an individual server like the CRM MCP server?

2 A request from a sales agent to look up a customer's support history touches the federation gateway, the OAuth validation middleware, the support MCP server, and the audit/tracing infrastructure. If the support MCP server's tool schema changed in a breaking way without a version bump, at which stage would this course's safeguards have caught it before it reached the agent?

3 A compromised support ticket (Lesson 19's prompt-injection scenario) attempts to get an agent to export all CRM records, and separately, the CRM MCP server happens to be mid-canary-rollout of a version with a subtly broken authorization check. Which single safeguard from this course, if functioning correctly, would still block the export even if both the injection attempt succeeds at the reasoning layer AND the canary's authorization bug is present?

Go further with expert guidance

Ready to build production AI?
Talk to our R&D team.

These courses give you the foundation. Our embedded AI teams take you from prototype to production in 30–90 days, with your team, your codebase, your goals. Book a free strategy call to see how we can accelerate your AI initiative.

30 minutes · No obligation · Expert AI engineers, not sales reps

AI Architecture Review

Audit your current stack and identify high-impact improvements

Project Review

Get expert feedback on your AI implementation and codebase

Team Mentoring

Upskill your engineers with hands-on AI coaching sessions

AI Strategy

Define your AI roadmap, prioritization, and implementation plan