MCP in Production: Building Enterprise AI Integrations with Model Context Protocol
A comprehensive guide to Model Context Protocol (MCP) in production: build servers in Python and TypeScript, deploy at scale, and architect enterprise AI...
The Protocol That Changed How AI Connects to Everything
In November 2024, Anthropic quietly released an open protocol called the Model Context Protocol (MCP). Eighteen months later, it has become the backbone of enterprise AI integration. The MCP Registry now hosts over 10,000 public servers. OpenAI adopted MCP in March 2025 across its products including the ChatGPT desktop app. Google DeepMind confirmed MCP support in Gemini models. Microsoft built first-class MCP support into Semantic Kernel and Copilot. Cloudflare, AWS, and Azure all provide managed MCP infrastructure.
Neural network architecture: data flows through input, hidden, and output layers.
The projected MCP ecosystem market has reached $1.8 billion, with analysts estimating it could exceed $10 billion by the end of 2027 as enterprise adoption accelerates. In December 2025, Anthropic donated MCP to the Agentic AI Foundation (AAIF), a directed fund under the Linux Foundation co-founded by Anthropic, Block, and OpenAI, with support from Google, Microsoft, AWS, Cloudflare, and Bloomberg.
This is not speculative technology. MCP is production infrastructure. This guide covers what it is, how to build with it, and how to deploy it at enterprise scale.
What MCP Is and Why It Matters
Before MCP, every AI integration was a custom job. Want your LLM to query a database? Write a custom function. Want it to access your CRM? Build another bespoke adapter. Want it to interact with your CI/CD pipeline? Yet another integration. The result was an N-times-M problem: N AI models times M tools, each requiring its own glue code.
MCP is often described as "USB-C for AI" -- a single, standardized interface that lets any AI model connect to any tool or data source. It defines a JSON-RPC 2.0 based protocol with three core primitives:
- Tools: Functions the AI can invoke (e.g., query a database, create a ticket, send an email)
- Resources: Data the AI can read (e.g., file contents, database schemas, configuration)
- Prompts: Reusable prompt templates that guide model behavior for specific tasks
The architecture follows a client-server model. An MCP Host (like Claude Desktop, VS Code, or your custom application) contains an MCP Client that connects to one or more MCP Servers. Each server exposes tools, resources, and prompts through a standardized interface.
The Three Transport Mechanisms
MCP defines two active transport mechanisms, with a third deprecated but still supported:
1. stdio -- The client launches the MCP server as a subprocess. Communication happens over standard input/output using newline-delimited JSON-RPC messages. Best for local development, CLI tools, and desktop applications.
2. Streamable HTTP -- Introduced in March 2025 as the standard for remote connections. The server exposes a single HTTP endpoint supporting POST and GET methods, with optional Server-Sent Events (SSE) for streaming responses. This is the production transport for web-deployed servers.
3. SSE (deprecated) -- The original remote transport, now replaced by Streamable HTTP. Many tools still support it, but new implementations should use Streamable HTTP.
Building an MCP Server from Scratch
Let us walk through building a production-quality MCP server in both Python and TypeScript. We will create a server that provides tools for interacting with a PostgreSQL database.
Python Implementation with FastMCP
The Python SDK provides the FastMCP class for rapid server development:
Get more insights on AI & Machine Learning
Join 2,000+ engineers who get our weekly deep-dives. No spam, unsubscribe anytime.
# database_server.py
from mcp.server.fastmcp import FastMCP
import asyncpg
import json
from typing import Any
mcp = FastMCP(
"Database Explorer",
version="1.0.0",
description="Query and explore PostgreSQL databases"
)
# Connection pool managed at module level
pool: asyncpg.Pool | None = None
async def get_pool() -> asyncpg.Pool:
global pool
if pool is None:
pool = await asyncpg.create_pool(
dsn="postgresql://user:pass@localhost:5432/mydb",
min_size=2,
max_size=10
)
return pool
@mcp.tool()
async def query_database(sql: str, params: list[Any] | None = None) -> str:
"""Execute a read-only SQL query against the database.
Returns results as a JSON array of objects.
Only SELECT statements are permitted."""
if not sql.strip().upper().startswith("SELECT"):
return json.dumps({"error": "Only SELECT queries are allowed"})
db = await get_pool()
async with db.acquire() as conn:
rows = await conn.fetch(sql, *(params or []))
return json.dumps([dict(r) for r in rows], default=str)
@mcp.tool()
async def list_tables() -> str:
"""List all tables in the public schema with their row counts."""
db = await get_pool()
async with db.acquire() as conn:
rows = await conn.fetch("""
SELECT tablename,
pg_stat_get_live_tuples(
(quote_ident(tablename))::regclass
) as row_count
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY tablename
""")
return json.dumps([dict(r) for r in rows], default=str)
@mcp.resource("schema://tables/{table_name}")
async def get_table_schema(table_name: str) -> str:
"""Get the column definitions for a specific table."""
db = await get_pool()
async with db.acquire() as conn:
rows = await conn.fetch("""
SELECT column_name, data_type, is_nullable,
column_default
FROM information_schema.columns
WHERE table_name = $1 AND table_schema = 'public'
ORDER BY ordinal_position
""", table_name)
return json.dumps([dict(r) for r in rows], default=str)
if __name__ == "__main__":
mcp.run(transport="streamable-http", host="0.0.0.0", port=8080)
TypeScript Implementation
The TypeScript SDK, published as @modelcontextprotocol/sdk, provides equivalent functionality:
// database-server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from
"@modelcontextprotocol/sdk/server/streamableHttp.js";
import { z } from "zod";
import pg from "pg";
import express from "express";
const pool = new pg.Pool({
connectionString: process.env.DATABASE_URL,
max: 10,
});
const server = new McpServer({
name: "Database Explorer",
version: "1.0.0",
});
server.tool(
"query_database",
"Execute a read-only SQL query. Only SELECT statements are permitted.",
{
sql: z.string().describe("The SQL SELECT query to execute"),
params: z.array(z.any()).optional().describe("Query parameters"),
},
async ({ sql, params }) => {
if (!sql.trim().toUpperCase().startsWith("SELECT")) {
return {
content: [{
type: "text",
text: JSON.stringify({ error: "Only SELECT queries allowed" }),
}],
};
}
const result = await pool.query(sql, params ?? []);
return {
content: [{ type: "text", text: JSON.stringify(result.rows) }],
};
}
);
server.tool(
"list_tables",
"List all tables in the public schema with row counts.",
{},
async () => {
const result = await pool.query(`
SELECT tablename,
pg_stat_get_live_tuples(
(quote_ident(tablename))::regclass
) as row_count
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY tablename
`);
return {
content: [{ type: "text", text: JSON.stringify(result.rows) }],
};
}
);
// Express app for Streamable HTTP transport
const app = express();
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
app.post("/mcp", async (req, res) => {
await transport.handleRequest(req, res, req.body);
});
app.get("/mcp", async (req, res) => {
await transport.handleRequest(req, res);
});
await server.connect(transport);
app.listen(8080, () => console.log("MCP server running on port 8080"));
Production Considerations
Moving from a working MCP server to a production deployment requires attention to several critical areas.
Authentication and Authorization
The MCP specification now supports OAuth 2.1 for authentication. In production, every MCP server endpoint should require authentication:
from mcp.server.fastmcp import FastMCP
from starlette.middleware import Middleware
from starlette.middleware.authentication import AuthenticationMiddleware
mcp = FastMCP("Secure Server")
# OAuth 2.1 middleware validates bearer tokens
# before any tool invocation reaches your code
@mcp.tool()
async def sensitive_operation(action: str) -> str:
"""This tool is only accessible with a valid token."""
# The auth middleware has already validated the request
return f"Executed: {action}"
For enterprise deployments, layer your MCP servers behind an API gateway (Kong, Envoy, or a cloud-native gateway) that handles token validation, role-based access control, and request routing.
Rate Limiting and Quotas
AI agents can invoke tools aggressively. Without rate limiting, a single runaway agent can overwhelm a downstream service. Implement rate limiting at two levels:
- Per-client rate limits at the gateway layer (e.g., 100 tool invocations per minute per client)
- Per-tool rate limits in the server itself for expensive operations (e.g., database queries limited to 10 per minute)
Error Handling
MCP tools should return structured error responses rather than throwing exceptions that crash the server:
@mcp.tool()
async def safe_query(sql: str) -> str:
"""Execute a query with comprehensive error handling."""
try:
result = await execute_query(sql)
return json.dumps({"status": "success", "data": result})
except asyncpg.PostgresError as e:
return json.dumps({
"status": "error",
"error_type": "database_error",
"message": str(e),
"suggestion": "Check your SQL syntax and table names"
})
except Exception as e:
logger.exception("Unexpected error in safe_query")
return json.dumps({
"status": "error",
"error_type": "internal_error",
"message": "An internal error occurred"
})
Monitoring and Observability
Instrument your MCP servers with metrics and tracing from day one:
- Tool invocation counts by tool name and client ID
- Latency histograms per tool
- Error rates by error type
- Token usage if your tools interact with LLMs downstream
- Distributed tracing with OpenTelemetry to follow requests from AI agent through MCP server to downstream services
RAG architecture: user prompts are embedded, matched against a vector store, then fed to an LLM with retrieved context.
Enterprise Deployment Patterns
Gateway Architecture
The most common enterprise pattern places an MCP Gateway between AI agents and backend MCP servers:
[AI Agents] --> [MCP Gateway] --> [MCP Server: CRM]
| --> [MCP Server: Database]
| --> [MCP Server: CI/CD]
| --> [MCP Server: Monitoring]
The gateway handles:
- Authentication: Validate OAuth tokens, API keys, or mTLS certificates
- Authorization: Check which tools each client is permitted to invoke
- Rate limiting: Enforce per-client and per-tool quotas
- Audit logging: Record every tool invocation with client identity, parameters, and results
- Tool discovery: Aggregate tools from multiple backend servers into a unified catalog
- Load balancing: Distribute requests across multiple instances of each server
Access Control and Audit Logging
Enterprise environments require fine-grained access control. A typical RBAC configuration might look like this:
# mcp-access-policy.yaml
roles:
analyst:
allowed_tools:
- query_database
- list_tables
denied_tools:
- execute_migration
- drop_table
admin:
allowed_tools: ["*"]
require_approval:
- drop_table
- execute_migration
Every tool invocation should produce an audit log entry containing: timestamp, client identity, tool name, input parameters (with sensitive fields redacted), result status, and execution duration. These logs feed into your SIEM for compliance and forensic analysis.
Cloudflare Workers: MCP at the Edge
Cloudflare provides first-class support for hosting MCP servers on their edge network. This is significant for two reasons: global low-latency access and zero infrastructure management.
// Cloudflare Worker MCP Server
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { McpAgent } from "agents/mcp";
export class MyMcpAgent extends McpAgent {
server = new McpServer({
name: "Edge Analytics",
version: "1.0.0",
});
async init() {
this.server.tool(
"get_regional_metrics",
"Get performance metrics for a specific region.",
{ region: z.string() },
async ({ region }) => {
// Runs at the edge closest to the caller
const metrics = await this.env.ANALYTICS_DB
.prepare("SELECT * FROM metrics WHERE region = ?")
.bind(region)
.all();
return {
content: [{ type: "text", text: JSON.stringify(metrics.results) }],
};
}
);
}
}
Deploy with wrangler deploy, and your MCP server is live on Cloudflare's global network, complete with automatic OAuth support via their managed authentication flow.
Integration with the Existing Stack
The real power of MCP emerges when you connect it to your existing infrastructure:
Databases
Free Resource
Free Cloud Architecture Checklist
A 47-point checklist covering security, scalability, cost optimization, and disaster recovery for production cloud environments.
Beyond the PostgreSQL example above, MCP servers exist for MongoDB, MySQL, Redis, Elasticsearch, and most major databases. The pattern is consistent: expose read operations as tools, expose schemas as resources, and guard write operations behind authorization checks.
APIs and SaaS Products
CRM systems like Salesforce and HubSpot, project management tools like Jira and Linear, communication platforms like Slack -- all have community or official MCP servers. The MCP Registry at registry.modelcontextprotocol.io serves as the canonical directory.
CI/CD Pipelines
MCP servers for GitHub Actions, GitLab CI, and Jenkins allow AI agents to trigger builds, check pipeline status, and review deployment logs. This transforms incident response: an AI agent can diagnose an issue, identify the relevant code change, check the CI/CD pipeline, and prepare a fix -- all through standardized MCP tool calls.
Microsoft Semantic Kernel Integration
Microsoft's Semantic Kernel has built first-class MCP support that deserves specific attention. SK can act as both an MCP host (client) and an MCP server, making it the primary enterprise framework for .NET-based MCP deployments.
The Microsoft Agent Framework, which reached Release Candidate 1.0 in February 2026 with GA targeted for end of Q1 2026, was designed from day one to support MCP and the Agent-to-Agent (A2A) protocol. This means instant integration with hundreds of MCP servers including HubSpot, Salesforce, Slack, and Azure DevOps.
For .NET enterprise shops, SK provides the most straightforward path to MCP adoption, combining it with native Azure Active Directory integration, enterprise audit logging, and the broader Microsoft security ecosystem.
Real-World Use Cases
CRM Integration: A financial services firm connected their Salesforce instance via MCP to their AI assistant. Sales teams ask natural language questions like "Show me all deals over $100K that haven't been updated in 30 days" and get instant, accurate answers without writing SOQL queries.
Code Repository Access: Engineering teams use MCP-connected Git servers to let AI agents review pull requests, search codebases, and even draft code changes. The AI reads the repository structure and file contents through MCP resources, then creates changes through MCP tools.
Monitoring Dashboards: An SRE team connected Prometheus, Grafana, and PagerDuty through MCP. Their on-call AI agent can pull current metrics, check alert history, and draft incident summaries -- reducing mean time to acknowledgment from minutes to seconds.
ML pipeline: from raw data collection through training, evaluation, deployment, and continuous monitoring.
The Road Ahead: Anthropic and Microsoft's 2026 Roadmap
The AAIF has published a roadmap that includes several key milestones for 2026:
- Formal specification standardization through the Linux Foundation
- Enhanced security model with per-tool OAuth scopes and capability-based access control
- Agent-to-agent communication enabling MCP servers to invoke tools on other MCP servers, creating composable agent architectures
- Improved tool discovery through the official Registry with semantic search and compatibility scoring
MCP has moved past the "is this real" phase. With 10,000+ public servers, backing from every major AI company, and a governance home at the Linux Foundation, it is the integration standard for production AI systems. The question is no longer whether to adopt MCP, but how quickly you can get your enterprise infrastructure connected.
Start with one high-value integration -- your most-queried database, your most-used internal API -- and expand from there. The protocol is stable, the tooling is mature, and the ecosystem is thriving.
Related Service
Cloud Solutions
Let our experts help you build the right technology strategy for your business.
Need help with ai & machine learning?
TechSaaS provides expert consulting and managed services for cloud infrastructure, DevOps, and AI/ML operations.
We Will Build You a Demo Site — For Free
Like it? Pay us. Do not like it? Walk away, zero complaints. You will spend way less than hiring developers or any agency.
No spam. No contracts. Just a free demo.