MCP Security Gateway
README.md
# MCP Security Gateway โ Stage 1: Basic MCP Server
This is Stage 1 of building an MCP Security Gateway from scratch.
In this stage, a basic Model Context Protocol (MCP) server is built using Python to expose local file operation tools directly to an MCP client.
---
## ๐ Project Structure
```text
mcp-security-gateway/
โโโ server/
โ โโโ server.py # Main MCP Server exposing local file tools
โโโ test_data/
โ โโโ hello.txt # Test directory containing sample files
โโโ verify_server.py # Automated verification script to test tools over stdio
โโโ requirements.txt # Dependencies (Official MCP Python SDK)
```
---
## โ๏ธ Requirements & Installation
- **Python**: Python 3.10 or higher (Tested with Python 3.14)
- **Official MCP SDK**: `mcp` package
### Installation Step:
```bash
pip install -r requirements.txt
```
---
## ๐ How to Run the MCP Server
The MCP server uses standard input/output (`stdio`) transport. You can run the server directly using:
```bash
python server/server.py
```
*Note: Since the server communicates via JSON-RPC messages over standard I/O streams (`stdin`/`stdout`), running it directly in a terminal will wait for incoming JSON-RPC stdin input.*
---
## ๐ ๏ธ Exposed Tools
The server registers three tools with the MCP runtime:
1. `list_files()`
- **Description**: Lists all filenames present in `test_data/`.
- **Parameters**: None.
2. `read_file(filename)`
- **Description**: Reads and returns text content from a file inside `test_data/`.
- **Parameters**: `filename` (string).
- **Security**: Resolves the path relative to `test_data/` and blocks path traversal (`../`).
3. `write_file(filename, content)`
- **Description**: Creates or overwrites a file inside `test_data/`.
- **Parameters**: `filename` (string), `content` (string).
- **Security**: Blocks path traversal (`../`).
---
## ๐งช Verification & Testing
To verify that the MCP server runs correctly and that all 3 tools are exposed and functional:
Run the automated client verification script:
```bash
python verify_server.py
```
### Expected Output:
```text
Connecting to MCP Server via stdio transport...
Session initialized successfully.
[TOOLS DISCOVERED] (3 tools found):
- list_files: List the names of all files inside the test_data directory.
- read_file: Read and return the text contents of a specified file inside test_data.
- write_file: Create or overwrite a file inside test_data with the provided content.
[TEST 1] Calling list_files()...
Result: hello.txt
[TEST 2] Calling read_file('hello.txt')...
Result:
Hello from MCP Server!
[TEST 3] Calling write_file('test_output.txt', '...')
Result: Success: File 'test_output.txt' successfully written to test_data.
[TEST 4] Testing path traversal prevention with '../server/server.py'...
Result: Security Error: Access Denied: Path traversal detected for '../server/server.py'...
```
---
## ๐ง Internal Mechanics of the MCP Server
### 1. Transport Layer (`stdio`)
The server uses `stdio` (standard input/output) as its communication transport. The client spawns the server script as a child process and sends JSON-RPC 2.0 messages over standard input (`stdin`), while reading response messages from standard output (`stdout`).
### 2. Protocol Handshake & Tool Discovery
When a client connects:
1. **Initialize Request**: The client sends an `initialize` request to negotiate protocol capability versions.
2. **List Tools Request**: The client sends a `tools/list` request. The MCP SDK inspects all functions decorated with `@mcp.tool()`, extracts their function signatures, type hints, and docstrings, and converts them into standard JSON schema tool definitions.
### 3. Tool Execution (`tools/call`)
When an AI agent/client invokes a tool:
1. The client sends a `tools/call` JSON-RPC message containing the tool `name` and `arguments`.
2. The MCP SDK routes the request to the matching Python function (`list_files`, `read_file`, or `write_file`).
3. The result (or error message) is serialized into an MCP `TextContent` payload and sent back over `stdout`.
### 4. Path Traversal Defense
Each file tool utilizes `get_safe_path()` using Python's `pathlib.Path`:
- Canonical resolution: `.resolve()` resolves relative parts (`..`) and symlinks.
- Scope containment: `.is_relative_to(BASE_DIR)` checks if the resolved path stays inside `test_data/`. Any attempt to escape raises a security exception.
---
## ๐ฏ Current Stage Architecture
```text
MCP Client (verify_server.py)
โ (JSON-RPC over stdio)
โผ
MCP Server (server/server.py)
โ (pathlib validation)
โผ
Local Files (test_data/)
```
*In future stages, a Security Gateway will be interposed between the Client and Server to enforce authorization, auditing, and policy checks.*
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues