Compiling the next screen…
Compiling the next screen…
Tue Jul 14 2026
David Bleeker, Principal Consultant

The MCP discussion is not really about whether the protocol is useful. The practical question is whether an MCP integration can survive production constraints: changing SDKs, uneven server quality, local-first desktop clients, cloud-hosted brokers, brittle OAuth flows, and sessions that expire at the wrong time.
That changes the engineering problem. A platform team is not evaluating a protocol in isolation. It is evaluating a runtime surface that can execute tools, move data across trust boundaries, and fail in ways that are hard to replay. The gap between a demo and a dependable deployment is usually not one more SDK feature. It is the control plane around it: compatibility standards, a repeatable test harness, and trust controls that hold up before and during runtime.
Recent community work points the same way. Local-first clients such as Rowboat show that some teams want MCP execution close to the user and workstation boundary, not only through a hosted desktop app. Separately, work on an automated CI/CD test harness for MCP servers shows that protocol support alone is a weak quality bar. Both are signs of the same need: production MCP requires disciplined interfaces and verification, not just connectivity.
What standards, test harnesses, and trust controls are needed to make MCP integrations production-ready?
For a platform engineer, the useful version of that question is more concrete:
If those questions are unanswered, MCP adoption turns into exception handling. Every new server adds operational variance. Every SDK release risks regressions. Every auth edge case becomes a user-facing failure.
Production-ready MCP needs three layers working together.
First, behavioral standards on top of the wire protocol. The base protocol tells you how messages are shaped. It does not fully guarantee how tools declare side effects, how pagination works, which error classes are retryable, how timeouts are communicated, or how auth refresh is coordinated during long sessions. Teams need a profile or contract that narrows those choices.
Second, a deterministic test harness that runs in CI/CD and exercises realistic client-server exchanges. Unit tests for a server implementation are not enough. You need protocol conformance tests, schema validation, auth lifecycle tests, cancellation tests, timeout tests, replay tests, and upgrade compatibility tests across SDK versions.
Third, trust controls that treat each MCP server as a third-party execution dependency. That means identity, provenance, capability scoping, runtime isolation, policy enforcement, observability, and a way to score or index trust so approval is not an ad hoc Slack conversation.
In practice, I would reduce the production checklist to seven requirements:
Compatibility profile
Define a supported MCP feature profile per environment. Example: required message fields, supported transport assumptions, timeout envelope, error taxonomy, pagination contract, idempotency expectations, and auth refresh semantics.
Capability manifest
Every server should publish a machine-readable manifest that declares tools, resource scopes, data egress behavior, side effects, and required credentials. This is what policy engines evaluate.
CI contract harness
Every server build and every client integration build should run the same scenario suite: handshake, discovery, tool invocation, malformed input, partial failure, cancellation, reconnect, token refresh, and version skew.
Trust registry
Maintain an internal registry of approved MCP servers with owner, version, signed artifact metadata, capability risk level, last test result, and deployment status. A public trust index can help discovery, but production approval should be your own decision artifact.
Runtime policy enforcement
Gate server execution through allowlists, per-tool scopes, egress restrictions, audit logging, and sandboxing. Do not let the client become the only policy engine if you also care about central governance.
Auth/session hardening
Treat OAuth and session state as failure-prone distributed systems components. Test refresh races, session expiry during long-running operations, stale consent grants, and reconnect behavior after token rotation.
Version discipline
Pin protocol and SDK versions, run compatibility matrices, and require deprecation windows. Spec churn is manageable when you make it visible and test it as an explicit input.
The main point is that MCP reliability problems often look like application bugs but start with missing control-plane guarantees. A flaky tool call may look like a prompt issue or model issue when the real cause is token expiry during a multi-step exchange or a server silently changing a response schema. If you do not separate protocol correctness from business-logic correctness, incident response gets noisy fast.
A concrete architecture recommendation is to place an MCP gateway between clients and most production servers.
This gateway should not rewrite the protocol unless necessary, but it should enforce policy and provide shared operational services:
This is the basic shape:
Why this split matters:
I would classify MCP servers into three trust tiers:
Failure modes to design for:
Tradeoffs are real.
A gateway adds latency, operational overhead, and one more place for bugs. Capability manifests require discipline and may lag implementation. Strict conformance tests can slow server teams while the spec is still moving. But the alternative is hidden coupling. Most teams underestimate how quickly "just connect the client to the server" becomes a support burden once multiple servers, auth systems, and client runtimes are involved.
The standards I would define internally are not glamorous, but they remove ambiguity:
These are the pieces that make a trust index meaningful. A trust score should not be vibes. It should come from verifiable attributes: owner, artifact signature, test pass rate, capability risk, dependency freshness, incident history, and scope breadth.
A useful starting point is a machine-readable server manifest that the gateway can validate before allowing registration.
{
"server_id": "com.acme.github-mcp",
"display_name": "GitHub MCP Server",
"version": "1.4.2",
"mcp_profile": "acme-prod-v1",
"artifact": {
"image": "registry.acme.internal/mcp/github-server@sha256:9f1c...",
"signature": "cosign:MEUCIQ..."
},
"owner": {
"team": "developer-platform",
"oncall": "platform-github"
},
"capabilities": [
{
"tool": "create_pull_request",
"risk": "write",
"idempotent": false,
"scopes": ["repo:write"],
"network_egress": ["api.github.com:443"]
},
{
"tool": "list_pull_requests",
"risk": "read",
"idempotent": true,
"scopes": ["repo:read"],
"network_egress": ["api.github.com:443"]
}
],
"auth": {
"type": "oauth2",
"audience": "github",
"refresh_owner": "gateway",
"min_token_ttl_seconds": 300
},
"tests": {
"contract_suite": "passed",
"sdk_matrix": ["js-0.9.3", "py-0.8.1"]
}
}
That manifest becomes more useful when paired with a contract test in CI. Here is a compact example in TypeScript that checks discovery, tool invocation, timeout handling, and token refresh behavior at the client boundary.
import assert from "node:assert/strict";
import { MCPClient } from "@acme/mcp-client";
async function runContractSuite() {
const client = new MCPClient({
endpoint: process.env.MCP_GATEWAY_URL!,
serverId: "com.acme.github-mcp",
auth: {
accessToken: process.env.ACCESS_TOKEN!,
refreshToken: process.env.REFRESH_TOKEN!
},
timeoutMs: 5000
});
await client.connect();
const tools = await client.listTools();
assert(tools.some(t => t.name === "list_pull_requests"));
const readResult = await client.callTool("list_pull_requests", {
repo: "acme/platform",
state: "open"
});
assert.equal(Array.isArray(readResult.items), true);
// Verify normalized timeout behavior.
await assert.rejects(
() => client.callTool("simulate_slow_operation", {}, { timeoutMs: 50 }),
(err: any) => err.code === "TIMEOUT" && err.retryable === true
);
// Simulate token nearing expiry before a tool call.
await client.auth.injectExpiringTokenForTest({ expiresInSeconds: 5 });
const writeResult = await client.callTool("create_pull_request", {
repo: "acme/platform",
title: "Test PR",
branch: "mcp-contract-test"
});
assert.equal(writeResult.status, "created");
await client.close();
}
runContractSuite().catch(err => {
console.error(err);
process.exit(1);
});
A policy check at registration time can reject high-risk servers before they ever reach users:
apiVersion: policy.acme.io/v1
kind: MCPServerPolicy
metadata:
name: default-prod-policy
spec:
requireSignedArtifact: true
requireContractSuitePass: true
allowedRiskLevels:
- read
- write
denyIf:
- condition: "capabilities[*].network_egress contains '*'"
reason: "wildcard egress is not allowed"
- condition: "auth.refresh_owner != 'gateway'"
reason: "gateway must own token refresh in production"
- condition: "capabilities[*].tool == 'execute_shell'"
reason: "shell execution requires explicit exception"
The point of these examples is not the exact schema. It is the separation of concerns. The server states what it is and what it needs. CI verifies behavior. Policy decides whether it is admissible. Runtime enforces that decision.
Production-ready MCP is mostly a systems engineering problem, not a protocol enthusiasm problem.
If a team wants to adopt MCP seriously, the shortest path is to treat servers like production dependencies with executable contracts. That leads to better architecture decisions than asking whether a given server "supports MCP."