dev-mcps/coding-agent-mcp/README.md

4.3 KiB
Raw Permalink Blame History

coding-agent-mcp

An MCP server for coding agents. It provides workspace-subpath-scoped file editing and typed build/test tasks, including Python tests.

Security model

This is intentionally a single combined server: coding-agent-mcp. The old split servers and the generic run_command API were removed.

  • HTTP requires an API key. Set CODING_AGENT_MCP_API_KEYS to SUBJECT=TOKEN entries separated by commas.
  • An SSE connection creates a server-generated session bound to that authenticated subject. MCP requests must use that live session; callers cannot choose a session ID.
  • The sessions optional workspaceSubpath is bound when SSE opens and cannot change afterward. It is the only filesystem scope beneath the configured workspace root; the server-generated session ID is not part of the directory path.
  • File and task paths are relative only. The client cannot select a root or use absolute paths.
  • File paths are checked for traversal and symlink escapes.
  • HTTP sends no permissive CORS header. Set CODING_AGENT_MCP_CORS_ORIGINS to an explicit comma-separated origin allowlist only when browser access is required.
  • Remote HTTP command execution defaults to disabled. Set CODING_AGENT_MCP_EXECUTION_BACKEND=local only in the hardened runner deployment below.

run_task deliberately accepts no shell command, flags, environment variables, npm script name, or local executable. It maps a typed request to a fixed invocation. Project tests and build scripts still execute project code, so this validation is not a sandbox.

Tools

Workspace tools: list_files, read_file, read_files, read_binary_file, search_text, write_file, write_binary_file, apply_patch, make_directory, delete_path, move_path, rename_path, and file_info.

Execution tool: run_task.

Example Python request:

{
  "runner": "pytest",
  "task": "test",
  "paths": ["tests/unit"],
  "timeoutSeconds": 300
}

Supported runners are pytest, npm, pnpm, yarn, maven, gradle, go, and cargo. Supported tasks depend on the runner; the server rejects unsupported combinations.

Local trusted use

Stdio is intended for a local, trusted client and enables typed task execution by default:

npm run start:coding-agent -- --root /absolute/path/to/workspace

The runtime needs the selected tool installed. The supplied Docker image contains Python 3 and pytest.

Remote hardened deployment

  1. Copy .env.example to .env and set a long random API token.
  2. Create a dedicated workspace directory; do not mount a home directory, source checkout, Docker socket, or secrets.
  3. Make that directory writable by CODING_AGENT_UID:CODING_AGENT_GID.
  4. Deploy with docker compose up --build -d.

The Compose deployment runs as a non-root UID, makes the container filesystem read-only, provides an ephemeral /tmp, removes Linux capabilities, applies process/memory/CPU limits, and places the MCP service on an internal-only Docker network. The workspace mount is the only intended writable persistent path.

This is a hardened local runner, not a VM-grade security boundary. For untrusted agents or untrusted repositories, connect run_task to an external ephemeral VM/container runner with a copy-on-write workspace, no host bind mounts, no Docker socket, no inherited secrets, resource quotas, and explicit network policy. Keep execution disabled until such a runner is configured.

HTTP protocol

All HTTP endpoints require Authorization: Bearer TOKEN (or x-api-key).

  • Send an MCP initialize JSON-RPC request to POST /mcp. The response includes Mcp-Session-Id.
  • Send subsequent MCP requests to POST /mcp with that Mcp-Session-Id header.
  • Use DELETE /mcp with Mcp-Session-Id to terminate the session.
  • GET /mcp with Mcp-Session-Id opens an optional server-to-client SSE stream.

Legacy SSE

  • GET /sse opens the former MCP SSE transport. It emits an endpoint event for posting messages.
  • For automatic legacy-client fallback, GET /mcp without Mcp-Session-Id provides the same SSE handshake.
  • The pre-existing custom transport is retained: GET /events returns x-session-id; send it on POST /mcp as x-session-id.
  • Bind x-workspace-subpath only when opening or initializing a session; it cannot change afterward.
  • GET /health reports server health.

Development

npm test