Post

Building Production-Ready Agentic Pipelines with Model Context Protocol (MCP)

Building Production-Ready Agentic Pipelines with Model Context Protocol (MCP)

The landscape of Artificial Intelligence has undergone a massive paradigm shift. We have moved rapidly from standard Large Language Model (LLM) prompting to Retrieval-Augmented Generation (RAG), and now into the era of autonomous agentic workflows.

However, as engineers began integrating LLMs into enterprise ecosystems, a major architectural bottleneck emerged: integration fragmentation. Every platform—whether GitHub, Jira, PostgreSQL, or Kubernetes—required custom integration code, bespoke function-calling schemas, and unique authentication wrappers.

Enter the Model Context Protocol (MCP), an open standard introduced to standardize how AI applications interact with external tools, data sources, and runtime environments. Often described as the “USB-C port for AI apps,” MCP abstracts context retrieval and action execution away from model-specific APIs.

In this technical post, we will explore the architecture of MCP, build a production-grade custom MCP server in Python, and discuss deployment patterns for modern enterprise DevOps infrastructure.


Understanding the MCP Architecture

At its core, MCP follows an asynchronous client-server architecture designed to isolate responsibilities cleanly:

1
2
3
4
5
6
7
8
9
10
+-------------------+        MCP Protocol        +-------------------+
|                   |  (JSON-RPC over stdio/SSE) |                   |
|    MCP Client     | <------------------------> |    MCP Server     |
| (Claude Desktop,  |                            | (Database, GitHub,|
| Cursor, Host App) |                            | Custom Microservice)
|                   |                            |                   |
+-------------------+        +-----------+       +-------------------+
          |                  | Target API|                 |
          +----------------> |  or DB    | <---------------+
                             +-----------+

Key Components

  1. MCP Host: The user-facing application orchestrating the workflow (e.g., Cursor IDE, Claude Desktop, or a custom orchestration service).
  2. MCP Client: The client implementation within the host that maintains a 1:1 connection with an MCP server.
  3. MCP Server: A lightweight service exposing capabilities through standardized protocol primitives.

Core Protocol Primitives

MCP standardizes three main types of interactions between the client and server:

  • Resources: Read-only data sources exposed by the server (e.g., log files, system metrics, database schemas).
  • Tools: Executable functions that allow the LLM to perform side-effecting actions (e.g., triggering a CI/CD pipeline, running a SQL query, restarting a Pod).
  • Prompts: Pre-configured prompt templates provided by the server to guide the user/LLM in specific tasks.

Building a Custom Enterprise MCP Server with FastMCP

Let’s build a custom Python-based MCP server designed for DevOps engineering pipelines. This server will expose system diagnostics (Resources) and allow incident mitigation actions (Tools).

Prerequisites

Ensure you have Python 3.10+ installed along with the official FastMCP SDK:

1
pip install mcp mps-server pydantic httpx

Step 1: Defining the MCP Server

Create a file named devops_mcp_server.py. We will use FastMCP to abstract low-level JSON-RPC messaging logic.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import asyncio
import psutil
import httpx
from mcp.server.fastmcp import FastMCP

# Initialize the MCP Server
mcp = FastMCP(
    name="DevOps-Observability-Server",
    dependencies=["psutil", "httpx"]
)

# ------------------------------------------------------------------
# 1. RESOURCE PRIMITIVE: System Health Metrics
# ------------------------------------------------------------------
@mcp.resource("system://health")
def get_system_health() -> str:
    """Returns current system CPU, Memory, and Disk utilization stats."""
    cpu_usage = psutil.cpu_percent(interval=1)
    memory = psutil.virtual_memory()
    disk = psutil.disk_usage('/')

    return (
        f"System Metrics:\n"
        f"- CPU Usage: {cpu_usage}%\n"
        f"- Memory Used: {memory.percent}% ({memory.used // (1024**2)} MB / {memory.total // (1024**2)} MB)\n"
        f"- Disk Used: {disk.percent}% ({disk.used // (1024**3)} GB / {disk.total // (1024**3)} GB)"
    )

# ------------------------------------------------------------------
# 2. TOOL PRIMITIVE: Incident Mitigation
# ------------------------------------------------------------------
@mcp.tool()
async def trigger_service_restart(service_name: str, environment: str) -> str:
    """
    Triggers a graceful restart for a target microservice in a specified environment.
    
    Args:
        service_name: The name of the microservice (e.g., 'auth-api', 'payment-v2')
        environment: Target deployment env ('staging', 'production')
    """
    if environment not in ["staging", "production"]:
        raise ValueError("Invalid environment specified. Must be 'staging' or 'production'.")

    # In a real enterprise system, this sends an authenticated request to your CI/CD or K8s API
    await asyncio.sleep(1.5) # Simulate network latency
    
    return f"SUCCESS: Service '{service_name}' restart command dispatched to {environment} cluster."

@mcp.tool()
async def fetch_deployment_logs(service_name: str, lines: int = 50) -> str:
    """Retrieves recent stderr/stdout logs for a specific microservice."""
    # Mock response illustrating log context retrieval
    return f"[LOGS for {service_name}]\n2026-07-21 16:20:00 [INFO] Starting instance...\n2026-07-21 16:20:05 [WARN] High connection latency on pool-2"

if __name__ == "__main__":
    mcp.run(transport="stdio")

Integrating MCP into Production Infrastructure

Deploying MCP servers in production requires moving beyond standard local execution (stdio) toward scalable network transports.

Transport Protocols: Standard I/O vs. SSE

MCP supports two main communication channels:

  1. Standard I/O (stdio): Ideal for local execution, CLI tools, and desktop hosts (e.g., Cursor connecting directly to a subprocess).
  2. Server-Sent Events (SSE): Essential for remote microservices, Kubernetes deployments, and enterprise API gateways where the host and server live on different machines.

Running MCP via HTTP/SSE

To expose your server using SSE for cloud deployment, update your entry point:

1
2
3
if __name__ == "__main__":
    # Host server on port 8000 using HTTP/SSE transport
    mcp.run(transport="sse", host="0.0.0.0", port=8000)

Containerization with Docker

To deploy our MCP server reliably across environments, wrap it in a multi-stage Docker image:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM python:3.11-slim as builder

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM python:3.11-slim

WORKDIR /app
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY devops_mcp_server.py .

EXPOSE 8000
ENTRYPOINT ["python", "devops_mcp_server.py"]

Security Best Practices for Agentic Tool Execution

Allowing an LLM agent to execute tools in production infrastructure introduces security risks. Apply these core principles to harden your setup:

  • Principle of Least Privilege: Ensure the credentials used by the MCP server have strictly bound RBAC permissions (e.g., read-only access where write actions are not strictly required).
  • Human-in-the-Loop (HITL): Implement explicit approval mechanisms at the MCP Client level before executing destructive tools (e.g., trigger_service_restart on production).
  • Input Validation: Use strict schema enforcement via libraries like Pydantic to prevent prompt injection attacks from passing malicious shell commands or parameters into tool arguments.
  • Audit Logging: Structured JSON logs should track every tool call, including inputs, user contexts, and execution latency.

The Road Ahead

Model Context Protocol is rapidly establishing itself as an essential standard in modern software architecture. By decoupling agent orchestration from tool integration, MCP enables platform engineering teams to build reusable, secure, and vendor-agnostic infrastructure capabilities for AI systems.

Whether you are building internal developer platforms, automated observability pipelines, or intelligent code-assist tools, adopting MCP will future-proof your AI integration architecture.


Found this deep dive helpful? Read more engineering insights and system design tutorials at purushotham.me.

This post is licensed under CC BY 4.0 by the author.