{"id":50248311,"url":"https://github.com/p4st4s/mcp-audit","last_synced_at":"2026-05-27T00:02:01.268Z","repository":{"id":359841731,"uuid":"1247690443","full_name":"P4ST4S/mcp-audit","owner":"P4ST4S","description":"A transparent Go proxy that intercepts, signs, and audits all MCP tool calls between any client and server — without modifying either.","archived":false,"fork":false,"pushed_at":"2026-05-23T17:22:54.000Z","size":33,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-23T19:17:31.935Z","etag":null,"topics":["ai-agents","anthropic","audit-log","golang","mcp","model","proxy","security"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/P4ST4S.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-23T16:43:32.000Z","updated_at":"2026-05-23T17:22:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/P4ST4S/mcp-audit","commit_stats":null,"previous_names":["p4st4s/mcp-audit"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/P4ST4S/mcp-audit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/P4ST4S%2Fmcp-audit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/P4ST4S%2Fmcp-audit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/P4ST4S%2Fmcp-audit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/P4ST4S%2Fmcp-audit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/P4ST4S","download_url":"https://codeload.github.com/P4ST4S/mcp-audit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/P4ST4S%2Fmcp-audit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33543973,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"ssl_error","status_checked_at":"2026-05-26T15:22:15.568Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","anthropic","audit-log","golang","mcp","model","proxy","security"],"created_at":"2026-05-27T00:01:59.852Z","updated_at":"2026-05-27T00:02:01.262Z","avatar_url":"https://github.com/P4ST4S.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mcp-audit\n\n![Go](https://img.shields.io/badge/Go-1.22%2B-00ADD8)\n[![CI](https://github.com/P4ST4S/mcp-audit/actions/workflows/ci.yml/badge.svg)](https://github.com/P4ST4S/mcp-audit/actions/workflows/ci.yml)\n[![mcp-audit MCP server](https://glama.ai/mcp/servers/P4ST4S/mcp-audit/badges/score.svg)](https://glama.ai/mcp/servers/P4ST4S/mcp-audit)\n![License](https://img.shields.io/badge/License-Apache--2.0-blue)\n![Status](https://img.shields.io/badge/Status-experimental-orange)\n\nA drop-in security and observability proxy for MCP servers. `mcp-audit` sits between an MCP client and any upstream MCP server to produce signed audit trails, redact sensitive payloads, enforce allow/deny policies and per-tool rate limits, and expose a local read-only dashboard.\n\n## Why mcp-audit?\n\n[The MCP 2026 roadmap](https://modelcontextprotocol.io/development/roadmap) calls out enterprise needs around audit trails, gateway patterns, and operational visibility. `mcp-audit` fills that gap as a deployable sidecar or local wrapper: it sits between any MCP client and server, preserves protocol traffic, and records signed audit entries for tool calls, resource reads, prompt requests, and all other JSON-RPC methods.\n\n```text\n+-------------+    JSON-RPC / MCP     +-----------+      JSON-RPC / MCP     +-------------+\n| MCP client  | \u003c-------------------\u003e | mcp-audit | \u003c---------------------\u003e | MCP server  |\n+-------------+                       +-----------+                         +-------------+\n                                            |\n                                            v\n                                JSONL or SQLite audit log\n                                            |\n                                            v\n                                   Read-only dashboard\n```\n\n## What This Is / Is Not\n\n`mcp-audit` is not a domain-specific MCP server. It is a transparent security and observability proxy that wraps any MCP server and audits the JSON-RPC traffic passing through it.\n\nDirectories may show the tools exposed by the upstream server, not tools implemented by `mcp-audit` itself.\n\n## Supported Transports\n\n- `stdio` for local MCP clients such as Claude Desktop\n- `http` for MCP servers exposed over HTTP\n\n## Use Cases\n\n- Audit tool calls made by AI agents in regulated environments\n- Detect unexpected or dangerous MCP tool usage\n- Keep signed JSONL or SQLite logs for incident review\n- Redact sensitive fields before storing requests and responses\n- Block disallowed tools and apply per-tool rate limits without modifying the upstream MCP server\n\n## Demo\n\n![mcp-audit demo](demo/mcp-audit-demo.gif)\n\n## Quick Start\n\nInstall Go, then build from source:\n\n```bash\nbrew install go\ngo install github.com/P4ST4S/mcp-audit/cmd/mcp-audit@v0.2.0\n```\n\nRun in stdio mode:\n\n```bash\nAUDIT_SECRET=\"$(openssl rand -hex 32)\" \\\nmcp-audit --transport stdio --upstream \"npx @modelcontextprotocol/server-filesystem /tmp\"\n```\n\nRun in HTTP mode:\n\n```bash\nmcp-audit --transport http --upstream http://localhost:8080 --port 4422\n```\n\nRun with Docker Compose:\n\n```bash\ndocker compose up --build\n```\n\nThe dashboard is available at `http://localhost:9090` by default.\nPrometheus metrics are available at `http://localhost:9091/metrics` by default.\n\n## Configuration\n\n`mcp-audit` loads `config.yaml` from the current directory by default. CLI flags override config values, and `AUDIT_SECRET` overrides `audit.secret`.\n\n| Key | Default | Description |\n| --- | --- | --- |\n| `proxy.transport` | `stdio` | Proxy transport: `stdio` or `http`. |\n| `proxy.upstream` | required | Stdio command or HTTP upstream URL. |\n| `proxy.port` | `4422` | HTTP listen port. |\n| `proxy.client_id` | `claude-desktop` | Client identifier written to audit entries. |\n| `proxy.server_id` | `filesystem` | Server identifier written to audit entries. |\n| `audit.storage` | `jsonl` | Storage backend: `jsonl` or `sqlite`. |\n| `audit.path` | `./audit.jsonl` | JSONL audit log path. |\n| `audit.sqlite_path` | `./audit.db` | SQLite database path. |\n| `audit.sign` | `true` | Enable HMAC-SHA256 signatures when a secret is set. |\n| `audit.secret` | empty | HMAC secret. Prefer `AUDIT_SECRET`. |\n| `audit.async.enabled` | `false` | Enable asynchronous batched audit writes through a bounded ring buffer. |\n| `audit.async.queue_size` | `4096` | Maximum queued audit entries before backpressure blocks writers. |\n| `audit.async.batch_size` | `128` | Maximum entries written per storage batch. |\n| `audit.async.flush_interval_ms` | `1000` | Maximum time before a partial batch is flushed. |\n| `middleware.rate_limit.enabled` | `true` | Enable per-client, per-tool token buckets. |\n| `middleware.rate_limit.requests_per_minute` | `60` | Allowed requests per minute per `(client_id, tool_name)`. |\n| `middleware.redact.enabled` | `true` | Enable JSON key-based PII redaction. |\n| `middleware.redact.patterns` | sensitive keys | Case-insensitive key fragments to redact. |\n| `policy.enabled` | `false` | Enable synchronous allow/deny policy checks for `tools/call`. |\n| `policy.default_action` | `allow` | Fallback action when no policy rule matches: `allow` or `deny`. |\n| `policy.rules` | empty | Ordered first-match allow/deny rules for tool calls. |\n| `dashboard.enabled` | `true` | Serve the dashboard. |\n| `dashboard.port` | `9090` | Dashboard listen port. |\n| `metrics.enabled` | `true` | Serve Prometheus metrics on a separate HTTP endpoint. |\n| `metrics.port` | `9091` | Metrics listen port. |\n| `metrics.path` | `/metrics` | Metrics HTTP path. |\n| `metrics.include_go_metrics` | `true` | Include Go runtime metrics. |\n| `metrics.include_process_metrics` | `true` | Include process metrics. |\n| `metrics.tool_labels` | `true` | Include `tool_name` and `client_id` labels for tool-level metrics. Disable to minimize label cardinality. |\n\nCLI flags:\n\n```text\n--transport    stdio | http\n--upstream     upstream server command or URL\n--port         proxy port for http mode\n--config       path to config.yaml\n--storage      jsonl | sqlite\n--no-dashboard disable the web dashboard\n--no-metrics   disable Prometheus metrics\n--log-level    debug | info | warn | error\n```\n\n## Claude Desktop\n\nConfigure Claude Desktop to spawn `mcp-audit` instead of the upstream MCP server:\n\n```json\n{\n  \"mcpServers\": {\n    \"filesystem-audited\": {\n      \"command\": \"mcp-audit\",\n      \"args\": [\n        \"--transport\",\n        \"stdio\",\n        \"--upstream\",\n        \"npx @modelcontextprotocol/server-filesystem /tmp\"\n      ],\n      \"env\": {\n        \"AUDIT_SECRET\": \"replace-with-a-long-random-secret\"\n      }\n    }\n  }\n}\n```\n\n## Dashboard\n\nThe dashboard shows recent entries, filters, expandable request/result JSON, top tools, calls today, and error rate. It refreshes every five seconds.\n\n## Prometheus Metrics\n\n`mcp-audit` exposes Prometheus metrics on a separate endpoint so platform teams can scrape operational data without exposing the dashboard.\n\n```yaml\nscrape_configs:\n  - job_name: mcp-audit\n    static_configs:\n      - targets: [\"localhost:9091\"]\n```\n\nApplication metrics use the `mcp_audit_` prefix and avoid unbounded labels. Tool-level labels can be disabled with `metrics.tool_labels: false` for stricter cardinality control. Policy decisions are exposed as `mcp_audit_policy_decisions_total{action=\"allow|deny\"}`.\n\n## Policy Engine\n\n`mcp-audit` can enforce synchronous allow/deny rules before a `tools/call` reaches the upstream MCP server. Denied calls return a JSON-RPC error and are still written to the audit log.\n\n```yaml\npolicy:\n  enabled: true\n  default_action: allow\n  rules:\n    - action: deny\n      client_id: claude-desktop\n      server_id: filesystem\n      tool_name: delete_file\n      reason: \"Destructive filesystem operations are blocked\"\n```\n\nRules are evaluated in order. Empty fields and `*` match any value, so `default_action: deny` can be used with explicit allow rules for stricter deployments.\n\n## Audit Entries\n\nEach stored entry includes a ULID, timestamp, direction, transport, JSON-RPC method, tool name when present, redacted params/result, JSON-RPC error when present, duration, client/server identifiers, and an optional HMAC-SHA256 signature.\n\nExample JSONL entry:\n\n```json\n{\n  \"id\": \"01HY8G6Y8S6W9K6ZD7VJ4Q8X4R\",\n  \"timestamp\": \"2026-05-25T12:34:56Z\",\n  \"direction\": \"client_to_server\",\n  \"transport\": \"stdio\",\n  \"method\": \"tools/call\",\n  \"tool_name\": \"read_file\",\n  \"params\": {\n    \"name\": \"read_file\",\n    \"arguments\": {\n      \"path\": \"/tmp/example.txt\",\n      \"token\": \"[REDACTED]\"\n    }\n  },\n  \"duration_ms\": 18,\n  \"client_id\": \"claude-desktop\",\n  \"server_id\": \"filesystem\",\n  \"signature\": \"hmac-sha256:...\"\n}\n```\n\nThe signature covers:\n\n```text\nid + timestamp + method + tool_name + raw_params\n```\n\n## Roadmap\n\n- OpenTelemetry export\n- SIEM-friendly exports\n\n## Contributing\n\nThis project is experimental. Keep changes small, run `go build ./...` and `go vet ./...`, and prefer standard library behavior over new dependencies.\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for setup, PR expectations, and project principles. See [CHANGELOG.md](CHANGELOG.md) for release history.\n\n## License\n\nApache-2.0. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp4st4s%2Fmcp-audit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fp4st4s%2Fmcp-audit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp4st4s%2Fmcp-audit/lists"}