Skip to content
Conduit

mcp server

mcp-agent-harness

Generic, SRE-hardened Model Context Protocol (MCP) harness for autonomous agents.

emmanuelol/mcp-agent-harnesscommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 22, 2026

MCP Agent Harness

CI Pipeline License: MIT Python: 3.11+ Release: v0.2.0

Generic, SRE-hardened Model Context Protocol (MCP) harness for autonomous agents. Acts as an operational firewall preventing LLM context exhaustion, enforcing data boundary blockades, throttling runaway agent retry loops, and guaranteeing zero unhandled panics across SSE streams.


5-Line FastAPI Quickstart

from fastapi import FastAPI
from mcp_agent_harness import AgentHarness

app = FastAPI()
harness = AgentHarness("ops-agent")
@harness.tool(max_chars=1000, rate_limit=(10, 60.0), catch_unhandled=True)
def get_status() -> str: return "System healthy"
app.mount("/mcp", harness.sse_app())

Architecture: The MCP SRE Firewall

flowchart TD
    Client["Autonomous LLM / MCP Client (OpenClaw)"]
    SSE["FastAPI Mount (/mcp/sse)"]
    
    subgraph Harness ["AgentHarness SRE Firewall"]
        Trace["1. Telemetry Tracer (init_trace)"]
        Rate["2. Sliding Window Rate Limiter"]
        Func["3. Tool Execution (Sync/Async)"]
        DFGuard["4. DataFrame Blockade (Zero-Import MRO)"]
        LogGuard["5. Log Line Capping (cap_log_lines)"]
        CtxGuard["6. Context Truncation & XML Strip"]
        ErrWrap["7. Deterministic Error Envelope"]
    end
    
    Backend["Host Backend Services (DB, Redis, APIs)"]

    Client -->|JSON-RPC via SSE| SSE
    SSE --> Trace
    Trace --> Rate
    Rate --> Func
    Func <--> Backend
    Func --> DFGuard
    DFGuard --> LogGuard
    LogGuard --> CtxGuard
    CtxGuard -->|Clean Bounded Payload| Client
    Func -.->|Unhandled Panic / Rate Limit| ErrWrap
    DFGuard -.->|TokenStarvationError| ErrWrap
    ErrWrap -->|JSON Error Envelope| Client

Benchmark Metrics & SRE Hardening

MetricUnguarded FastMCPAgentHarness v0.2.0Operational Impact
Token Consumption (1k rows)~85,000 tokens~420 tokens99.5% prompt token reduction
Prompt Injection DefenseRaw XML <DATA> leakSanitized scalar previewImmune to XML unclosed tag context hijack
Hallucination Loop DefenseUncapped infinite retriesSliding Window Rate LimitHard stop on agent runaway retry storms
Stream StabilitySSE drops on unhandled panic100% Stream UptimeDeterministic JSON error envelope return
Guard Latency OverheadNone< 0.15 msSub-millisecond boundary verification
DependenciesRequires pandas at installZero Core C-depsMRO duck-typing for pandas, polars, pyarrow

Prerequisites

  • Docker >= 24.0
  • Docker Compose >= 2.20
  • GNU Make >= 4.3
  • (Optional for local development) Python >= 3.11

Quickstart (Containerized)

No local Python environment or dependency installation required. All lifecycle steps run inside isolated containers:

# 1. Build the hardened container image
make build

# 2. Run the integration test suite
make test

# 3. Spin up the harness and verify live endpoint health
make demo

# 4. Run the security, leak, and Trivy CVE audit gate
make audit

API & Configuration Reference

AgentHarness

Main server class wrapping FastMCP with SRE boundary guards.

from mcp_agent_harness import AgentHarness

harness = AgentHarness(
    name="analytics-mcp",
    instructions="Operational analytics tools for agents.",
    register_builtins=True,
)
ParameterTypeDefaultDescription
namestr"mcp-agent-harness"Identifier for the MCP server instance.
instructionsstr"Generic SRE-hardened MCP Harness"System instructions exposed to MCP clients.
register_builtinsboolTrueRegisters default diagnostic tools (health, ping, diagnostics).

Declarative Tool Decorator (@harness.tool)

Configurable declarative SRE policies applied at the decorator boundary:

@harness.tool(
    max_chars=2000,
    max_lines=200,
    strip_xml=True,
    catch_unhandled=True,
    rate_limit=(10, 60.0),
)
def query_system_logs(service: str) -> str:
    ...
ParameterTypeDefaultDescription
max_charsOptional[int]NoneAutomatically truncates string outputs exceeding character limit.
max_linesOptional[int]NoneCaps string output lines to prevent context terminal flooding.
strip_xmlboolTrueStrips raw <TAG>...</TAG> blocks when max_chars is enforced.
catch_unhandledboolFalseCatches unexpected exceptions and returns structured JSON error envelopes.
rate_limitOptional[tuple[int, float]]None(max_calls, period_seconds) sliding window limiter per tool.

Guardrails in Action

1. Token Starvation Guard (DataFrame Blockade)

The harness blocks raw tabular data from entering LLM context. Returning a raw DataFrame immediately triggers TokenStarvationError, captured into a structured error envelope:

import pandas as pd
from mcp_agent_harness import AgentHarness

harness = AgentHarness()

# ❌ BAD: Leaks raw DataFrame
@harness.tool()
def query_orders() -> pd.DataFrame:
    return pd.DataFrame({"order_id": [1, 2], "amount": [99.5, 14.2]})

# Invoking returns a safe error envelope instead of leaking rows:
# {
#   "status": "error",
#   "error_code": "TokenStarvationError",
#   "message": "Raw DataFrames are strictly prohibited in MCP tools. Return scalar metrics or token-compressed strings.",
#   "trace_id": "mcp-3a1b4c9e"
# }

# ✅ GOOD: Return compact scalar metrics
@harness.tool()
def query_order_metrics() -> dict:
    df = pd.DataFrame({"order_id": [1, 2], "amount": [99.5, 14.2]})
    return {
        "order_count": len(df),
        "total_revenue": float(df["amount"].sum()),
        "average_order": float(df["amount"].mean()),
    }

2. Hallucination Throttling (Rate Limiting)

Throttles runaway LLM retries when an agent enters an infinite retry loop:

@harness.tool(rate_limit=(3, 60.0), catch_unhandled=True)
def trigger_external_mutation(action: str) -> dict:
    return {"status": "dispatched", "action": action}

# On the 4th invocation within 60s, execution is stopped before hitting backend:
# {
#   "status": "error",
#   "error_code": "ToolRateLimitError",
#   "message": "Rate limit exceeded: 3 calls per 60.0s limit reached.",
#   "trace_id": "mcp-9b2f11c4"
# }

Telemetry & Error Envelopes

Every tool invocation automatically initializes an OpenTelemetry-compatible trace_id (mcp-xxxxxxxx).

When catch_unhandled=True is configured, internal tool exceptions are safely converted to structured responses without crashing the SSE connection:

{
  "status": "error",
  "error_code": "ConnectionResetError",
  "message": "Remote database closed connection",
  "trace_id": "mcp-e4f912a7"
}
↑↓ navigate openesc close