Skip to main content
Glama

MCP Agent Harness

CI Pipeline License: MIT Python: 3.11+

Generic, SRE-hardened Model Context Protocol (MCP) harness for autonomous agents. Designed to prevent LLM context exhaustion, enforce data boundaries, and maintain fail-closed observability across agentic workloads.


Prerequisites

  • Docker >= 24.0

  • Docker Compose >= 2.20

  • GNU Make >= 4.3

  • (Optional for local development) Python >= 3.11


Related MCP server: Graft

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

Architecture & Codebase Map

mcp-agent-harness/
├── src/
│   └── mcp_agent_harness/
│       ├── __init__.py      # Public exports: AgentHarness, guards, telemetry
│       ├── server.py        # AgentHarness, ToolList, tool decorator, SSE app mounting
│       ├── guards.py        # DataFrame blockade, TokenStarvationError, context & log capping
│       ├── telemetry.py     # Correlated trace_id generation and context logging
│       └── __main__.py      # CLI entrypoint for health checks and standalone daemon
├── tests/
│   ├── test_guards.py       # Unit tests for DataFrame blockade, context truncation, log capping
│   ├── test_server.py       # Sync/async tool execution, leak detection, registry checks
│   └── test_integration_sse.py # FastAPI SSE endpoint mounting and streaming tests
├── scripts/
│   ├── audit_image.sh       # Fail-closed Trivy CVE scanner & prohibited file leak audit
│   └── check_blacklist.sh   # Clean-room sensitive pattern scanner
├── Dockerfile               # Multi-stage hardened Debian container definition
├── docker-compose.yml       # Service definitions for daemon and test runner
└── Makefile                 # Standardized automation targets

SRE Hardening Principles

  1. Token Starvation Guards: Prevents raw DataFrames (pandas, polars) from leaking into LLM context windows. Enforces scalar metric summaries.

  2. Context Bounds: Automatically truncates bulk <DATA> payloads and caps log output lines to prevent context window blowouts.

  3. Telemetry Tracing: Generates correlated trace_id for every tool invocation.

  4. Fail-Closed Isolation: Unhandled exceptions return structured error envelopes without terminating SSE streams.


API & Configuration Reference

AgentHarness

Main server class wrapping FastMCP with SRE guards.

from mcp_agent_harness import AgentHarness

harness = AgentHarness(
    name="analytics-mcp",
    instructions="Operational analytics tools for agents.",
    register_builtins=True,
)

Parameter

Type

Default

Description

name

str

"mcp-agent-harness"

Identifier for the MCP server instance.

instructions

str

"Generic SRE-hardened MCP Harness"

System instructions exposed to MCP clients.

register_builtins

bool

True

Registers default diagnostic tools (health, ping, diagnostics).

Methods

  • @harness.tool(*args, **kwargs): Decorator registering sync or async tools with automatic trace injection and DataFrame blockades.

  • harness.list_tools() -> ToolList: Returns registered tool names (supports both sync iteration and async await).

  • harness.call_tool(name: str, *args, **kwargs) -> Any: Directly invokes a registered tool by name.

  • harness.sse_app() -> Any: Generates the Starlette/ASGI app for mounting into FastAPI.


Guard Utilities (mcp_agent_harness.guards)

Configurable standalone filters to protect agent prompt budgets:

Function

Parameters

Default

Description

truncate_context()

context: Any, max_chars: int = 2000, strip_xml: bool = True

max_chars=2000

Strips raw <DATA>...</DATA> XML blocks and truncates strings exceeding character limits.

cap_log_lines()

text: Any, max_lines: int = 200

max_lines=200

Caps multiline log dumps to prevent terminal context flooding.

block_raw_dataframes()

obj: Any

N/A

Recursively traverses dicts, lists, sets, and tuples, raising TokenStarvationError if a DataFrame is detected.


Guardrails in Action

1. Synchronous & Asynchronous Tools

from mcp_agent_harness import AgentHarness

harness = AgentHarness(name="system-tools")

# Synchronous tool
@harness.tool()
def get_system_load() -> dict:
    return {"load_1m": 0.42, "load_5m": 0.35}

# Asynchronous tool
@harness.tool()
async def fetch_cluster_metrics(region: str) -> dict:
    # Non-blocking async execution
    return {"region": region, "active_nodes": 12, "healthy": True}

2. 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: Attempting to return raw DataFrame
@harness.tool()
def query_orders() -> pd.DataFrame:
    return pd.DataFrame({"order_id": [1, 2], "amount": [99.5, 14.2]})

# Invoking this tool returns a safe error envelope instead of leaking rows:
# {
#   "status": "error",
#   "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()),
    }

3. Context & Log Bounds

from mcp_agent_harness import truncate_context, cap_log_lines

raw_logs = "INFO: Step completed\n" * 500
# Safe for LLM prompts: capped at 200 lines
clean_logs = cap_log_lines(raw_logs, max_lines=200)

raw_prompt = "User query: analyze output <DATA>large blob...</DATA>"
# Strips bulk data XML tags and caps character length
bounded_prompt = truncate_context(raw_prompt, max_chars=1000)

Telemetry & Error Envelopes

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

When an unhandled exception occurs inside a tool, the harness isolates the failure:

  • The underlying SSE stream remains open.

  • The failure is logged with the correlated trace ID.

  • The agent receives a predictable JSON envelope:

{
  "status": "error",
  "message": "Division by zero",
  "trace_id": "mcp-e4f912a7"
}

Integration with FastAPI

Install the package in your consumer application:

pip install "git+https://github.com/emmanuelol/mcp-agent-harness.git@v0.1.0"

Mount into FastAPI:

from fastapi import FastAPI
from mcp_agent_harness import AgentHarness

harness = AgentHarness(
    name="production-harness",
    instructions="Production operational agent harness.",
)

@harness.tool()
async def health_summary() -> dict:
    return {"status": "operational", "uptime_pct": 99.98}

app = FastAPI(title="Agent Platform")

@app.get("/health")
def health() -> dict:
    return {"status": "ok"}

# Mount MCP Server-Sent Events endpoint
app.mount("/mcp", harness.sse_app())

Run with Uvicorn:

uvicorn main:app --host 0.0.0.0 --port 8000

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    A lightweight server implementation that exposes Python functions as discoverable tools via HTTP using the Machine-to-Machine Communication Protocol (MCP). Enables remote execution of Python functions through a JSON-RPC interface with async support and type safety.
    4
    14 PyPI
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables building agent-ready APIs that expose tools as both HTTP and MCP endpoints from a single server definition, with automatic OpenAPI, discovery docs, and interactive API reference.
    5
    Apache 2.0
  • A
    license
    A
    quality
    C
    maintenance
    A production-ready starting point for MCP servers, adding per-tool timeouts, concurrency ceilings, error boundaries, secret redaction, correlation IDs, and structured logging so tools are safe and observable for LLM callers.
    3
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables turning any Python function into an auto-registered MCP tool and serving them over a FastMCP server with auto-discovery, optional auth, and request context.
    MIT