BoundBench

mcp-agent

Python framework for building agents and workflows on the Model Context Protocol, with a CLI scaffolder and Temporal-backed durable execution.

github.com/lastmile-ai/mcp-agent · 2026-10-04 · f62d849

Defense-in-depth score

1.7 / 10

Minimal

mcp-agent is a thin orchestration layer: as shipped it adds no approval gate, no sandbox, and no argument validation between the model and its MCP tools. The scaffolded default gives one unattended session web fetch, a filesystem server over the project directory, and the plaintext secrets file in that same directory, so a prompt injection can read API keys and overwrite files. Sub-agent specs and config are also auto-loaded from the working directory, where they can trigger Python module imports. Opt-in OAuth scoping and OpenTelemetry tracing are the strongest controls on offer.

Key gaps (4)

  1. Configured stdio MCP servers and local tools run unsandboxed as the user, with the default filesystem server rooted at the project that holds the plaintext secrets file. C4 · Code-execution isolation
  2. Rule of Two is broken by the default template: fetch, a filesystem server over the project (including the secrets file), and file write combine in one unattended session. C5 · Untrusted input blast radius
  3. Sub-agent auto-discovery is on by default and imports Python modules named in .claude/agents files from the working directory; config and .env are also discovered from the working directory with no trust prompt. C6 · Memory, context & configuration integrity
  4. The plaintext secrets file lives inside the directory the default filesystem MCP server exposes, so the model can read long-lived API keys. C8 · Secrets & sensitive-data protection

Criteria

C1 Identity & least privilege

Minimal 0.40 / 1.00

By default an mcp-agent app runs with the developer's own authority: LLM API keys come from env vars or a plaintext secrets file, and stdio MCP servers are launched as the same OS user. The one narrowing step is that stdio servers get a minimal default environment plus their configured variables rather than the full parent environment. For HTTP MCP servers the framework offers an opt-in OAuth client whose tokens are cached per user identity and per requested scope set, which is a real per-capability scoping primitive but is off unless configured per server.

C2 Approval gates

Minimal 0.00 / 1.00

The framework has no approval gate for tool calls. The hook that runs before each tool call simply returns the request unchanged unless a developer subclasses it, and the human-input tool is something the model chooses to call, not a checkpoint on actions. The only built-in human approval covers MCP sampling requests, not tool execution. In the scaffolded default config the agent can overwrite project files and fetch arbitrary URLs with no human in the loop.

C3 Tool & action scoping

Minimal 0.25 / 1.00

Tool arguments are passed through to MCP servers without framework-side validation; only local Python function tools get typed pydantic parsing. Enforcement of the per-server allowed_tools setting does not cover every path. The default template enables filesystem write and unrestricted web fetch.

C4 Code-execution isolation

Minimal 0.00 / 1.00

mcp-agent has no isolation mechanism. Configured stdio MCP servers, including the default filesystem server launched with npx, run as ordinary subprocesses of the same OS user, and local function tools run in the agent's own process. Any code those paths execute can reach the user's home directory, network, and the project's secrets file.

C5 Untrusted input blast radius

Minimal 0.00 / 1.00

Tool and MCP results are appended to the conversation as ordinary tool messages with no untrusted marking, and nothing in the framework changes what the agent may do after reading external content. In the scaffolded default, one session combines web fetch (untrusted input and an exfiltration channel), the project directory including the secrets file, and file write. A successful prompt injection can therefore both leak keys and overwrite files without any human involvement.

C6 Memory, context & configuration integrity

Minimal 0.10 / 1.00

Conversation memory is in-process and session-scoped, but configuration is not. At startup the app searches the current directory and every parent for its config and secrets files, reads a .env file from the working directory (which can set values such as the OpenAI base URL), and auto-loads sub-agent definitions from .claude/agents and .mcp-agent/agents in the working directory. Those definition files can name Python callables, which the loader imports by module name, so files in the workspace can trigger code import without any trust prompt. Because the default filesystem server is rooted at the same directory, the agent itself can write these files for the next run.

C7 Third-party extensions

Minimal 0.05 / 1.00

MCP servers are whatever the config names, and the scaffolded template launches them with npx -y and uvx with no version pins, so the latest package is fetched and executed at each launch. There is no integrity check or re-approval when a server changes. stdio servers do get a reduced default environment, but they run as the same user, and function references in sub-agent spec files are imported into the agent's own process.

C8 Secrets & sensitive-data protection

Minimal 0.25 / 1.00

API keys come from env vars or a plaintext, gitignored secrets file that sits in the project directory. The log serializer masks values under sensitive-looking keys, but leaves the first ten characters visible, and an environment variable turns masking off entirely. Usage telemetry is flagged on but currently sends nothing. The biggest problem is placement: the default filesystem server is rooted at the same directory as the secrets file, so the model can read the long-lived keys.

C9 Audit & traceability

Minimal 0.35 / 1.00

By default the aggregator logs each MCP tool call at info level with tool, server, and agent names but not the arguments, and the scaffolded config writes these logs to a file inside the project directory that the agent's own filesystem tool can edit. Logs are batched and flushed every two seconds. Opt-in OpenTelemetry tracing records tool arguments and results under agent-named spans and can export over OTLP, which is a much better record but is off by default.

C10 Limits & kill switch

Minimal 0.30 / 1.00

Each LLM generate call is limited to 10 tool-use iterations and 2048 output tokens per completion. There is no wall-clock limit, no cost cap, and tool calls have no timeout by default, so a hanging MCP server blocks indefinitely. Orchestrator, router, and swarm patterns create sub-agents that each get their own fresh iteration budget. A budgeted deep-orchestrator workflow exists but applies only to that workflow.