security agent when dealing with sensitive data. it does not peek into the data itself.
security-mcp is a Model Context Protocol (MCP) server that places a small,
auditable policy boundary between AI coding agents and protected laboratory data.
It is designed for computational neuroscience labs using MATLAB alongside Codex,
Claude Code, or VS Code AI clients.
The agent talks only to this MCP server. The server is the sole component that opens configured dataset paths.
flowchart LR
A["Codex / Claude Code / VS Code"] -->|MCP tool call| B["security-mcp"]
B --> C{"Policy engine"}
C -->|"list / inspect / allowed read"| D["Read-only datasets"]
C -->|"write request"| E["analysis_outputs/"]
C -->|"sensitive metadata"| F["Human approval"]
B --> G["Append-only JSONL audit log"]
- Every gateway operation is policy-checked and audit-logged.
- Dataset roots are immutable in policy, independent of operating-system ACLs.
- Delete, move, rename, and append are denied everywhere by this service.
- All writes outside
analysis_outputs/, including attempted dataset writes, are redirected into that configured output root. - Classic MATLAB files use
scipy.io.whosmat(); MATLAB v7.3 files use HDF5 object metadata. Neither route loads numerical arrays. - Sensitive metadata or a metadata extraction failure requires explicit, in-memory human approval for the requesting agent and file path.
This server is a defense-in-depth control, not a substitute for operating-system permissions, encryption, IRB controls, network segmentation, or access reviews.
Python 3.11 or later is required.
git clone <your-fork-url> security-mcp
cd security-mcp
python -m venv .venv
source .venv/bin/activate
python -m pip install -e '.[dev]'
pytestRun locally over standard input/output:
security-mcp --config /absolute/path/to/security-mcp/config.yamlDo not write logs to stdout: MCP stdio uses stdout for protocol messages.
All lab-specific values are in config.yaml; no source edit is required.
dataset_directories:
- /srv/neurodata/study-42
output_directory: /srv/neurodata/analysis_outputs
audit_log: /var/log/security-mcp/events.jsonl
protected_extensions: [.mat, .h5, .hdf5, .csv, .tsv]
sensitive_keywords: [patient, participant, name, email, phone, address, DOB, birth, MRN, hospital, clinical]
max_text_read_bytes: 1048576Relative paths are interpreted relative to config.yaml. Configure only canonical, lab-owned dataset roots. The server resolves requested paths before comparing roots, so .. traversal and symlink escapes cannot bypass the policy.
Use absolute paths to the executable and configuration file in production. The example in examples/mcp.json is portable to clients accepting the conventional MCP server JSON shape.
Add this to .vscode/mcp.json (or the MCP configuration location used by your VS Code AI extension), then restart the MCP client:
{
"servers": {
"security-mcp": {
"type": "stdio",
"command": "/absolute/path/to/.venv/bin/security-mcp",
"args": ["--config", "/absolute/path/to/security-mcp/config.yaml"]
}
}
}Register the server using Claude Code's MCP command:
claude mcp add security-mcp -- /absolute/path/to/.venv/bin/security-mcp --config /absolute/path/to/security-mcp/config.yamlConfirm the exact registration command supported by the installed Claude Code version with claude mcp --help.
Add a stdio MCP server entry to the Codex MCP configuration used by your desktop or CLI installation. Its command and arguments are the same as the VS Code example: security-mcp --config /absolute/path/to/config.yaml. Restart Codex and verify that list_dataset appears in its MCP tool list before granting it a task.
| Tool | Purpose |
|---|---|
list_dataset(path) |
List one directory below a configured dataset root. |
inspect_metadata(path) |
Inspect .mat, .h5, or .hdf5 metadata only. |
read_dataset(path) |
Read bounded UTF-8 text; MATLAB/HDF5 responses remain metadata-only. |
request_permission(path, approved_by, reason) |
Record human approval for a sensitive metadata read. |
save_output(path, content) |
Save derived text, redirecting unsafe destinations. |
check_policy(operation, path) |
Preview an allow, deny, or redirect decision. |
Typical session:
list_dataset("/srv/neurodata/study-42/session-01")inspect_metadata(".../recording.mat")- If it reports
sensitive_matchesorextraction_error, a human callsrequest_permissionwith their name and documented justification. - Use
read_datasetfor bounded text data or MATLAB metadata. Save summaries, scripts, and figures withsave_output.
request_permission is intentionally explicit: an MCP tool call cannot prove a human approved something. Deployments should expose this tool only in a workflow where a responsible person reviews and supplies approved_by and reason.
sequenceDiagram
participant Agent
participant MCP as security-mcp
participant Meta as Metadata inspector
participant Human
participant Data as Dataset root
Agent->>MCP: read_dataset(path)
MCP->>MCP: canonicalize path + apply policy
MCP->>Meta: metadata-only inspection (MAT/HDF5)
alt sensitive or unreadable metadata
MCP-->>Agent: approval_required
Human->>MCP: request_permission(path, reason)
Agent->>MCP: read_dataset(path)
end
MCP->>Data: permitted read only
MCP->>MCP: append audit event
MCP-->>Agent: bounded response
The implementation is layered: policy.py owns containment and operation decisions; metadata.py owns metadata-only parsing; permissions.py owns short-lived approvals; filesystem.py is the only filesystem gateway; and server.py adapts the gateway to FastMCP.
Run the test suite with pytest. Audit records are JSON Lines and include timestamp, agent_name, tool, file_path, decision, and reason.
For deployment, run under a dedicated service account that has read access to data and write access only to configured outputs and audit logs. Restrict who may modify config.yaml, the installed package, and the client MCP configuration. Ship audit logs to centralized, append-protected storage if compliance requires it.
This project can be shared through GitHub so collaborators can clone it, inspect the code in VS Code, run its tests, and connect it to an MCP-capable AI extension.
Do not commit protected datasets, audit records, API keys, credentials, or a
lab-specific configuration containing sensitive filesystem paths. Keep public
configuration generic, as in the included config.yaml, and have each lab maintain
its own local copy with its approved dataset roots.
Add the following to .gitignore before working with real data:
datasets/
*.mat
*.h5
*.hdf5
*.csv
*.tsvIf CSV or TSV files are source-controlled examples rather than datasets, store them
under examples/ and use a narrower ignore rule instead. Confirm what will be
published with git status before every commit.
-
Create an empty repository on GitHub, for example
YOUR-ORG/security-mcp. -
From the project directory, initialise and publish the local repository:
cd security-mcp git init git add . git commit -m "Initial security-mcp release" git branch -M main git remote add origin https://github.com/YOUR-ORG/security-mcp.git git push -u origin main
-
In GitHub, enable branch protection and require pull-request review before changes to policy code or
config.yamlare merged.
A collaborator can install and open the project as follows:
git clone https://github.com/YOUR-ORG/security-mcp.git
cd security-mcp
python -m venv .venv
source .venv/bin/activate # Windows PowerShell: .venv\\Scripts\\Activate.ps1
python -m pip install -e '.[dev]'
pytest
code .Each collaborator must update their local config.yaml with approved, absolute
dataset and output paths. They should never point this server at a directory unless
their lab has authorized the service account to read it.
Create or update .vscode/mcp.json in the cloned repository (or use the MCP
configuration location required by the installed VS Code AI extension):
{
"servers": {
"security-mcp": {
"type": "stdio",
"command": "/absolute/path/to/security-mcp/.venv/bin/security-mcp",
"args": [
"--config",
"/absolute/path/to/security-mcp/config.yaml"
]
}
}
}Restart the VS Code AI extension, then confirm that list_dataset,
inspect_metadata, read_dataset, request_permission, save_output, and
check_policy appear in its available MCP tools. Test first against a non-sensitive
sample dataset. The MCP configuration should remain local if it includes lab paths
or other environment-specific details.
The public tools intentionally do not return MATLAB or HDF5 numerical arrays. This is the safer default for agent-oriented use: it avoids large, accidental disclosure into an LLM context. Labs needing controlled array extraction should add a separate, reviewed tool with explicit dimensional limits and a release policy; do not weaken the metadata gate in place.