Agentrim MCP

Agentrim MCP

A least-privilege enforcement proxy for MCP servers. It sits between MCP clients and upstream servers, enforcing tool policies, hiding denied tools, requiring human approval for risky actions, and providing a structured audit trail.

Category
访问服务器

README

Agentrim MCP

A least-privilege enforcement proxy for MCP servers.

CI License: MIT Python 3.10+ Code style: ruff Type checked: mypy Tests: 86 passing

Agentrim MCP sits between an MCP client (an agent or LLM harness) and one or more real upstream Model Context Protocol servers. It builds and verifies a tool inventory offline, then enforces least-privilege access to that inventory online: hiding denied tools entirely, requiring human confirmation for risky ones, validating every call against parameter constraints and rate limits, and logging everything in a structured, greppable audit trail.

Table of contents

How it works, in plain English

Think of an AI agent as a traveler, and the tools it can call (delete a file, send an email, read a spreadsheet) as items the traveler wants to carry onto a plane. agentrim-mcp is the security checkpoint standing between the traveler and the gate.

  • Before anyone travels, security studies the manifest. The offline extractor connects to the real server once, reads the full list of tools it offers, and writes down what each one does and how risky it looks (read-only, like reading a book, versus destructive, like detonating something). If a tool's description quietly changes later, that is flagged immediately: a tool that used to say "reads a file" suddenly saying "reads a file and emails it to a stranger" is exactly the kind of trick a hidden attacker would try, and it gets caught before anyone acts on it.
  • At the gate, the traveler only sees the lanes they are allowed to use. Tools that are outright forbidden never even show up in the list the agent sees. An agent cannot be tricked into asking for something it never knew existed.
  • Every attempt to use something is checked, every single time. An everyday, harmless action passes straight through. A risky action gets held for a human to approve first. A dangerous action is stopped automatically, no matter how the request is worded or how convincing the surrounding conversation sounds.
  • Everything is written in a logbook. Every decision, allowed, denied, or held for approval, is recorded, so if something ever goes wrong there is a full paper trail to investigate.

That is the entire idea. The rest of this document is the engineering detail behind those four bullet points.

Architecture

flowchart TB
    subgraph Offline["Offline: run once per upstream server"]
        direction LR
        SA[static_analyzer.py] --> TC[trace_collector.py]
        TC --> RC[risk classifier]
        RC --> V[verifier.py]
    end

    V --> INV[(ToolInventory JSON<br/>drift-checked)]

    subgraph Online["Online: every agent request"]
        direction LR
        AF[adaptive_filter.py]
        VA[validator.py]
    end

    Agent["Agent / LLM<br/>MCP client"] <-->|MCP| PS[proxy_server.py]
    PS --> AF
    PS --> VA
    INV --> AF
    INV --> VA
    PS <-->|MCP| Upstream["Real upstream MCP server<br/>filesystem, memory, ..."]
    PS --> AL[audit_log.py<br/>JSON lines]

A single tool call looks like this:

sequenceDiagram
    participant Agent as Agent / LLM
    participant Proxy as agentrim-mcp
    participant Policy as Policy engine
    participant Upstream as Real MCP server

    Agent->>Proxy: tools/call delete_file
    Proxy->>Policy: evaluate(tool, arguments)
    Policy-->>Proxy: DENY, destructive tier
    Proxy-->>Agent: DENIED, with reason
    Note over Proxy,Upstream: Upstream is never contacted

Full design detail, including every judgment call made and why, is in docs/architecture.md.

Provenance, please read this

This is an independent engineering interpretation of the two-phase architecture (offline tool extractor plus online tool orchestrator enforcing least-privilege tool access via adaptive filtering and status-aware validation, evaluated on AgentDojo) described in AgenTRIM (arXiv:2601.12449, Betser, Bose, Giloni, Picardi, Padakandla and Vainshtein, Fujitsu Research, submitted January 2026, under review). The paper discloses that architecture at a conceptual level but not its exact algorithms, thresholds, or scoring functions, and this project does not claim to reproduce any of that. Every design decision that goes beyond what the paper discloses (the risk classifier's keyword heuristics, the policy YAML schema, the relevance-ranking algorithm, the sequence-anomaly enforcement strength, and more) is original engineering work, tracked claim by claim in docs/paper-mapping.md.

This repository was also built and tested inside a sandboxed environment with no live LLM API access. Every result described as "real" below (extraction against live servers, test pass counts, evaluation numbers) was actually run during development; see PROGRESS.md for the phase-by-phase log and KNOWN_ISSUES.md for the real bugs live testing surfaced. The shipped evaluation numbers are an explicitly-labeled illustrative synthetic run, not a live AgentDojo benchmark against an LLM; see Evaluation below.

Quickstart

git clone <this-repo> agentrim-mcp && cd agentrim-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

# 1. Cache the official filesystem MCP reference server once (needs npm registry access).
npx -y @modelcontextprotocol/server-filesystem --help

# 2. Find its resolved entrypoint. Invoking node directly avoids a real npx
#    stdio-interaction bug documented in KNOWN_ISSUES.md #1.
ENTRYPOINT=$(find "$(npm config get cache)/_npx" -path "*server-filesystem/dist/index.js" | head -1)

# 3. Extract and verify a tool inventory for a sandbox directory.
mkdir -p /tmp/agentrim-sandbox
agentrim extract --server-name filesystem --command node \
    --args "$ENTRYPOINT /tmp/agentrim-sandbox" \
    --output /tmp/fs_inventory.json
agentrim verify /tmp/fs_inventory.json

# 4. Serve the proxy in front of the real server.
agentrim serve --inventory-path /tmp/fs_inventory.json \
    --policy-path src/agentrim/policy/default_policy.yaml \
    --upstream-command node \
    --upstream-args "$ENTRYPOINT /tmp/agentrim-sandbox" \
    --audit-log-path /tmp/agentrim_audit.jsonl

Point your MCP client's stdio transport at agentrim serve (instead of directly at the upstream server) and it now enforces the policy in default_policy.yaml: read-only tools allowed, writes require confirmation through the agentrim_confirm meta-tool, destructive or unclassified tools denied. See examples/wrap_filesystem_server.py and examples/wrap_memory_server.py for runnable, end-to-end programmatic versions of the same flow; both were run live against the real reference servers during development.

Every step above completes in well under five minutes on a machine with npm registry access. The only slow step is the one-time package cache warm (roughly 10 to 20 seconds); everything after is near instant.

Installing

pip install -e ".[dev]"     # core package plus test and lint tooling
pip install -e ".[eval]"    # adds agentdojo, for the evaluation harness

Requirements:

  • Python 3.10 or newer.
  • agentrim serve/extract launch upstream MCP servers as subprocesses (for example via node, npx, or any other command), so whatever runtime the upstream server needs (Node.js, Go, and so on) must also be installed separately. Most official MCP reference servers need Node.js 18 or newer.

Docker

A Dockerfile is included for containerized deployment:

docker build -t agentrim-mcp .
docker run --rm -it \
    -v "$(pwd)/data:/data" \
    -v "$(pwd)/logs:/var/log/agentrim" \
    agentrim-mcp \
    agentrim serve \
      --inventory-path /data/inventory.json \
      --policy-path /app/config/example.policy.yaml \
      --upstream-command node \
      --upstream-args "/data/upstream-server/index.js /data" \
      --audit-log-path /var/log/agentrim/audit.jsonl

Note: the Dockerfile has been reviewed for correctness but has not been build-tested in this project's own development environment, since Docker was not available there. Please verify it builds in yours before relying on it; see KNOWN_ISSUES.md for the full note.

Command-line reference

All commands are available via the agentrim entrypoint once installed.

agentrim extract

Connects to a live upstream MCP server, runs the offline extractor, and writes a verified tool inventory.

Flag Required Description
--server-name yes Logical name for the upstream server, stored in the inventory.
--command yes Command used to launch the upstream server, for example node.
--args no Space-separated arguments for that command.
--trace-file no Path to a JSONL execution-trace log to augment the inventory with observed call sequences.
--output no Path to write the inventory JSON (default inventory.json). If a file already exists there, it is used as the previous inventory for drift detection.

agentrim verify

agentrim verify path/to/inventory.json

Prints a table of every tool in a previously extracted inventory, its risk tier, and whether it is currently flagged for description or schema drift.

agentrim serve

Starts the orchestrator proxy: connects to the real upstream server over stdio and serves a filtered, validated MCP server over stdio to the downstream client.

Flag Required Description
--inventory-path yes Path to a verified inventory JSON (from extract).
--policy-path yes Path to a policy YAML file.
--upstream-command yes Command used to launch the upstream server.
--upstream-args no Space-separated arguments for that command.
--max-visible-tools no Cap on how many tools are shown per tools/list after relevance ranking.
--audit-log-path no Path to write JSON audit log lines; if omitted, logs go to stdout.

agentrim report

agentrim report path/to/audit.jsonl

Summarizes an audit log: total validated calls, counts by verdict, drift-related denials, and how many soft sequence anomalies were logged.

Writing a policy

Policies are explicit, human-editable YAML with a structurally-enforced default-deny posture: Policy.default_action cannot be set to allow, the schema itself raises on load if you try. See src/agentrim/policy/default_policy.yaml for the minimal default this repo ships with, and config/example.policy.yaml for a fuller, annotated example covering parameter constraints, rate limits, and glob rules, including a documented pitfall around rule ordering.

Minimal shape:

version: 1
default_action: deny   # only "deny" or "confirm" are ever valid here

risk_tier_defaults:
  read_only: allow
  write: confirm
  destructive: deny
  unknown: deny

rules:
  - tool: "read_file"
    action: allow
    param_constraints:
      - param: "path"
        deny_patterns: ["\\.\\."]   # blocks path traversal, checked against
                                     # both the raw and URL-decoded value

global_rate_limit_per_minute: 120

Running in production

A few practical notes beyond the Quickstart:

  • Run agentrim extract on a schedule (a cron job or CI job) against your production upstream servers, and diff the resulting inventory against the previous one before deploying it; agentrim verify and the drifted column it prints are the signal to look at.
  • Point --audit-log-path at a durable, rotated log destination. The audit logger writes one JSON object per line, so it is directly consumable by jq, a log shipper, or agentrim report.
  • Treat the policy YAML as configuration that goes through the same review process as code; it is the actual security boundary.
  • The proxy currently tracks one logical session per process (see docs/architecture.md's Roadmap for a future multi-session store), so run one agentrim serve process per agent connection in a multi-agent deployment.

Testing

pytest -v --cov=agentrim --cov-report=term-missing
ruff check src/ tests/ evaluation/ examples/
ruff format --check src/ tests/ evaluation/ examples/
mypy src/

86 tests, all passing, at roughly 93 percent statement coverage on src/agentrim as of the last run; ruff and mypy --strict are both clean. Coverage is weakest in cli.py (around 76 percent), mostly the serve command's live-process wiring, which is exercised by the example scripts run manually rather than by unit tests. tests/test_stress.py covers scale (2000-tool inventories, 10,000-line trace files), unicode tool names and arguments, exact rate-limit boundaries, and a range of malformed policy documents.

One CLI test and both examples/ scripts run live against the real, official @modelcontextprotocol/server-filesystem and @modelcontextprotocol/server-memory reference servers when node and those packages are available locally; they skip gracefully otherwise, so no network access is required to run the rest of the suite.

Evaluation

evaluation/agentdojo_runner.py is a real, tested integration with the actual AgentDojo package (agentdojo==0.1.35): it converts a real AgentDojo task suite's tools into an agentrim-mcp ToolInventory and wraps FunctionsRuntime so every call is validated by the same policy engine the MCP proxy uses.

evaluation/baseline_vs_agentrim.py, run for real during development, loads the actual official AgentDojo v1.1.1 workspace suite and its real environment, and runs a small, deterministic, non-LLM mock agent through three synthetic indirect-prompt-injection scenarios, with and without agentrim-mcp in front. This development environment has no live LLM API access, so this is explicitly an illustrative synthetic run, not a live AgentDojo benchmark; see the label in its own JSON output and docs/paper-mapping.md for why. The real result of that real run:

Task Completion Rate Attack Success Rate
Baseline, no agentrim-mcp 1.00 1.00
With agentrim-mcp 1.00 0.00

That is, the legitimate task still completes, and every injected-destructive-call attempt this scenario set models is blocked. Full output is in evaluation/results/illustrative_baseline_vs_agentrim.json. .github/workflows/eval.yml is ready for a maintainer with real LLM API credentials to run an actual AgentDojo benchmark.

Security

See SECURITY_REVIEW.md for an adversarial review that found and fixed a real path-traversal-encoding bypass, a real confirmation-token replay gap, and hardened the validator to fail closed on unexpected internal errors, all verified with tests rather than reasoned about in the abstract. This is a portfolio and reference project rather than a monitored production service; see CONTRIBUTING.md for how to report a further finding.

Troubleshooting

  • npx-launched upstream servers crash or hang. Invoke node directly on the resolved entrypoint instead of going through npx; see KNOWN_ISSUES.md #1 for the root cause.
  • A read-only-looking tool got classified as write or destructive. The risk classifier is a transparent keyword heuristic, not a semantic model; check src/agentrim/risk/risk_tags.py for the exact keyword lists and override the classification with an explicit rule in your policy YAML if needed.
  • A tool I expected to be visible is missing from tools/list. Check whether it resolved to deny under your policy (denied tools are removed from the list entirely by design, not merely blocked at call time); agentrim verify and the audit log will show the policy decision.
  • A confirmation token stopped working. Tokens expire after ProxyConfig.confirmation_ttl_seconds (300 seconds by default); request the call again to get a fresh token.

Known issues and roadmap

See KNOWN_ISSUES.md for real bugs found and fixed during development, including risk-classifier false positives found by running against live reference servers and AgentDojo's real tool set, and docs/architecture.md's Roadmap section for what was deliberately deferred rather than gold-plated for v1: semantic relevance ranking, a distributed session store, and a review dashboard.

Contributing

See CONTRIBUTING.md for setup instructions, the pre-commit hooks, and the standard this project holds itself to for new changes.

License

MIT, see LICENSE. Chosen for maximum compatibility with the MCP Python SDK and the broader MCP server ecosystem this project wraps, and because a permissive license suits a reference and portfolio security tool meant to be freely adapted.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选
mcp-server-qdrant

mcp-server-qdrant

这个仓库展示了如何为向量搜索引擎 Qdrant 创建一个 MCP (Managed Control Plane) 服务器的示例。

官方
精选