# How to Connect MAREF to Your Agent via MCP — Step-by-Step

> Source: <https://maref.cc/en/blog/mcp-integration-tutorial>
> Published: 2026-08-14 00:00:00+00:00

# How to Connect MAREF to Your Agent via MCP — Step-by-Step

By MAREF Engineering

**Model Context Protocol (MCP)** has become the universal interface for agent-to-tool communication. Claude Code, Cursor, and Windsurf all speak it. The question isn't whether your agent will use MCP — it's whether anyone is watching the tools it calls. MAREF speaks MCP on both sides of that conversation, so governance is a layer, not a bolt-on.

This tutorial is written against the real MAREF API (`maref.integration.mcp_client`

and `maref.integration.mcp_bridge`

). Everything below runs on a stock `pip install maref`

.

## Two roles, one protocol

MAREF works in two directions over MCP, and understanding which one you need is the whole setup:

**MAREF as MCP client**— MAREF reaches out to external MCP servers (file, shell, browser, email, or a third-party tool server), lists their tools, and runs every invocation through its security gate before the call goes through.**MAREF as MCP server**— Claude Code / Cursor / Windsurf connect to MAREF as a tool server. Every tool the agent would call becomes a governed tool in MAREF's registry.

Most teams start with the first and graduate to the second. Both are covered below.

## 1. MAREF as an MCP client — governing external tools

The entry point is `MCPClient`

. You register an external server with an `MCPServerConfig`

, and MAREF manages the connection lifecycle — initialize, capability negotiation, reconnects — for you:

``` python
from maref.integration.mcp_client import MCPClient, MCPServerConfig

client = MCPClient()

config = MCPServerConfig(
    command=["npx", "-y", "@some/tool-server"],
    transport_type="stdio",          # or "sse" with url=
    server_name="my-tool-server",
    env={"TOOL_API_KEY": "..."},
)

conn = client.register_server(config)   # returns an MCPConnection
tools = client.list_tools(conn)         # list[MCPToolDef]
```

Now the interesting part. A raw `MCPClient.call_tool`

skips governance. The safe path is `MCPBridge`

, which wraps every call in the security gate:

``` python
from maref.integration.mcp_bridge import MCPBridge

bridge = MCPBridge(client)               # optional: pass your own MCPSecurityGate

# watch governance events
bridge.on("maref.mcp.invoke", lambda e: print("governed:", e.data))

bridge.discover_tools(conn)              # security-check each tool once

result = bridge.invoke_tool(
    conn,
    tool_name="create_file",
    args={"path": "/tmp/demo.txt", "content": "hello"},
)
# if the security gate returns DENY, invoke_tool returns
# {"error": "Tool blocked by security gate", "tool": ...} — the
# external server is never even contacted.
```

That one line — `bridge.invoke_tool`

— is the difference between "an agent that can call any tool" and "an agent that can call tools its policy allows." Every invocation emits a `maref.mcp.invoke`

event you can route to your audit log, SIEM, or dashboards.

## 2. MAREF as an MCP server — governing Claude Code / Cursor

If your agent host already speaks MCP, expose MAREF's own tool registry as an MCP server. The `MCPServerAdapter`

bridges MAREF's `ToolRegistry`

to the MCP wire protocol — `list_tools`

and `handle_tool_call`

are the two methods the protocol needs:

``` python
from maref.mcp.router import MCPServerAdapter
from maref.tools import ToolRegistry

registry = ToolRegistry()                # your governed tools live here
adapter = MCPServerAdapter(registry)

# MCP JSON-RPC requests come in, governed responses go out
adapter.handle_tool_call("send_email", {"to": "[email protected]"})
```

In practice you usually mount this behind the full `MCPServer`

implementation (`maref.integration.mcp_server`

), which gives you resources, prompts, and sampling callbacks on top of tools. MAREF doesn't ship a built-in `maref mcp serve`

CLI command — the stdio entrypoint is a ~15-line launcher wired straight to the real `MCPServer`

API:

``` python
import json, sys
from maref.integration.mcp_transport import JSONRPCRequest
from maref.integration.mcp_server import MCPServer

server = MCPServer(name="maref-mcp-server", security_gate=gate)  # gate: your security gate
# ... server.register_tool(...) register your governed tools ...

for line in sys.stdin:                     # newline-delimited JSON-RPC 2.0
    msg = json.loads(line)
    req = JSONRPCRequest(method=msg["method"], params=msg.get("params"), id=msg.get("id", 0))
    resp = server.handle_request(req)
    sys.stdout.write(json.dumps({"jsonrpc": resp.jsonrpc, "result": resp.result, "error": resp.error, "id": resp.id}, ensure_ascii=False) + "
")
    sys.stdout.flush()
{
  "mcpServers": {
    "maref": {
      "command": "python3",
      "args": ["/path/to/mcp_stdio.py"]
    }
  }
}
```

From that point on, when Claude Code or Cursor calls any tool, the call passes through MAREF's governance state machine — policy decision tree, safety gates, and audit trail — before it touches the world.

## 3. What governance actually blocks

Governance isn't a suggestion. It's a decision, and it's made four ways in the policy tree — **Rule → Mode → SafetyGate → User**:

- A
**hard rule**(never touch`/etc`

) blocks instantly, no model consultation. - The
**current mode**(read-only, triage, full) narrows what's permitted. - The
**safety gate** catches risky operations — high blast radius, untrusted targets, anomalous patterns. **Human escalation** fires for the genuinely dangerous cases, with a named approver and an audit line.

And because every decision is signed per-agent (Ed25519) and written to the audit log, "which agent did this?" is never a debate.

## Try it now

The fastest way to see the loop working is the local demo — it boots a governed toy agent and a live dashboard so you can watch BLOCK/ALLOW decisions stream in:

```
pip install maref
maref demo --port 8080
# open http://localhost:8080 — the dashboard shows the 8-layer
# defense pipeline, trust scores, and the audit log, all live.
```

*🛡️ Sources: MAREF source — src/maref/integration/mcp_client.py (MCPClient, MCPServerConfig, register_server), src/maref/integration/mcp_bridge.py (MCPBridge.discover_tools / invoke_tool), src/maref/integration/mcp_server.py (MCPServer), src/maref/mcp/router.py (MCPServerAdapter). *

[See all integration options](/en/integrations/).
