permission-aware-mcp
Enables secure file system operations (read, write, delete) and simulated command execution with server-enforced permission policies, risk assessment, and human-in-the-loop approval.
README
Permission-Aware MCP Security System
A production-grade Model Context Protocol server and client suite that demonstrates server-enforced permission management, risk assessment, and tamper-resistant audit logging.
It exposes four classic file-system tools — read_file, write_file, delete_file, execute_command — each classified by risk and gated by a permission policy. Privileged operations cannot run without explicit, single-use human approval.
Why this design
The defining principle: the server is the security boundary. A server can never trust a client to enforce restrictions on its behalf, so every check — policy, path confinement, approval, audit — happens server-side. Clients only surface the server's decisions and relay an explicit human approval back.
| Control | How it works |
|---|---|
| Sandbox confinement | All file access passes through safe_resolve, which rejects absolute paths and .. traversal and verifies (after symlink resolution) that the target stays inside data/. Enforced at execution — even an approved escape attempt is blocked. |
| Permission policy | Each tool maps to allow / ask / deny. Stored in config/permissions.json, hot-reloaded on change, with risk-derived fail-safe defaults for unknown tools. |
| Risk assessment | Every tool has an inherent risk (low→critical) from a single source of truth, shown at approval time and used to derive default policy. |
| Human-in-the-loop approval | An ask operation returns a single-use, args-bound, expiring token instead of executing. It runs only when a human relays the token back via approve_operation. The LLM never receives that tool, so it cannot approve its own calls. |
| Audit trail | Append-only JSONL with UTC timestamps, stored outside the sandbox so the file tools can't tamper with it. Every decision, approval, and outcome is recorded. |
Architecture
┌──────────────────┐ stdio (MCP) ┌────────────────────────────┐
│ Client / Host │ ────────────────────────► │ server.py (the boundary) │
│ │ │ │
│ gui_client.py │ call_tool ──────────► │ ┌──────────────────────┐ │
│ host_app.py │ │ │ policy → risk → gate │ │
│ cli_demo.py │ ◄─ approval_required ── │ │ allow / ask / deny │ │
│ │ │ └──────────┬───────────┘ │
│ (one background │ approve_operation ──► │ safe_resolve (sandbox) │
│ event loop owns │ │ AuditLog (outside data/) │
│ the session) │ ◄─ ok / denied / error │ ApprovalStore (tokens) │
└──────────────────┘ └────────────────────────────┘
Tool results use one uniform JSON envelope:
{"status": "ok", "result": "..."}
{"status": "denied", "reason": "...", "risk": "..."}
{"status": "approval_required", "token": "...", "summary": "...", "risk": "...", "expires_in": 180}
{"status": "error", "message": "..."}
Layout
mcp_security/
config.py Settings & resolved paths (env-overridable)
paths.py Sandbox confinement (safe_resolve)
risk.py Risk classification (single source of truth)
policy.py allow/ask/deny engine, hot-reloadable
audit.py Append-only JSONL audit log
approvals.py Single-use, args-bound, expiring tokens
server.py FastMCP server — the enforcement boundary
client.py Background-loop MCP connection (Gradio-safe)
gui_client.py Gradio operator console
host_app.py Gradio AI host (OpenAI), human-in-the-loop
cli_demo.py Headless end-to-end demonstration
tests/ Unit tests for the deterministic core
config/ data/ logs/ Runtime state (generated)
Setup
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # macOS / Linux
pip install -r requirements.txt
For the AI host, copy .env.example to .env and set OPENAI_API_KEY.
Running
All commands run from the project root.
Headless demo (no API key needed — the fastest way to see the whole gate):
python -m mcp_security.cli_demo
Operator console (browse tools/resources/prompts, manage policy, view audit log) at http://127.0.0.1:7863:
python -m mcp_security.gui_client
AI host (chat with an LLM that uses the gated tools) at http://127.0.0.1:7864:
python -m mcp_security.host_app
The clients launch the server (python -m mcp_security.server) themselves over stdio. To point a client at a different server, pass a module path or script file:
python -m mcp_security.gui_client path/to/other_server.py
Tests
python -m pytest -q
The suite covers the deterministic security core — path confinement (traversal/absolute/symlink-escape), policy defaults & hot-reload, token binding/single-use/expiry, audit structure, and risk classification. The MCP/Gradio/OpenAI layers are exercised by cli_demo.py and the included smoke checks.
Configuration
Every setting is overridable via environment variable (see .env.example): sandbox/log/config directories, max file size, and approval-token TTL.
Security notes & limits
execute_commandis simulated — it never runs a real subprocess, matching the original's stance. It is denied by default regardless.- Approval tokens live in the server's memory; restarting the server clears pending approvals (by design — stale approvals should not survive a restart).
- The bundled clients run on
127.0.0.1with no authentication; they are operator tools, not multi-tenant services. For shared deployment, add authentication and per-session state. - The server's policy file (
config/permissions.json) is the control plane; protect it with filesystem permissions in production.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.