MCP Files
by tspspi
README.md
# MCP Files MCP Server
MCP Files exposes a constrained filesystem workspace (notes, knowledge bases, code artifacts) to LLM agents and automations. It supports `stdio` and
`remote` HTTP mode.
## Features
- Tool suite for listing, reading, writing, patching, deleting, and stat’ing files and project directory helpers.
- Per API key roots, extension whitelists, recursive-delete flags, quotas, and logging overrides.
- Structured logging/tracing with per security domain toggles and optional dedicated log files.
## Installation
Either from PyPi
```
pip install mcpfiles
```
or via
```
git clone git@github.com:tspspi/mcpfiles.git
pip install -e .
```
## Quick Start
1. **Create a configuration file** at `~/.config/mcpfiles.conf` (or another path). Each entry in `api_keys` defines a root directory and permissions.
2. **Run in stdio mode** (default):
```sh
mcpfiles [--config ~/.config/mcpfiles.conf]
```
This binds the server to the root defined in the `stdio` block.
3. **Run in remote HTTP mode**:
```sh
mcpfiles --remote
```
The `--remote` flag is shorthand for `--transport remotehttp` and requires `remote_server` and `api_keys` blocks in the configuration file. Authentication accepts `Authorization: Bearer`, `X-API-Key`, or `?api_key=` query string tokens.
4. **Generate or rotate an API key** for an existing entry:
```sh
mcpfiles --genkey knowledge-base
```
The command prints the plaintext secret once once on `stdout` and patches the matching `api_keys[].kdf` configuration.
### Logging & Tracing
- Global defaults live under the top-level `logging` block. Per-key overrides inherit those defaults and may specify their own log file, categories (`trace_access`, `trace_write`, `trace_delete`, `trace_metadata`) and `debug_all`.
- Each MCP tool invocation emits one structured log entry containing the key ID, optional project ID, category, path, status and compact metrics (bytes written, entries listed, etc.).
## Configuration
The default path for the configuration file is `~/.config/mcpfiles.conf`. This path can be overriden with `--config /path/to/config.json`. To generate API keys one can utilize
```
mcpfiles --genkey <id>
```
An example is shown below:
```json
{
"mode": "remotehttp",
"stdio": {
"root": "/srv/mcpfiles/stdio",
"projects_enabled": false,
"extension_whitelist": [".md", ".txt", ".json"],
"mime_validation": true,
"allow_nonempty_delete": false,
"immutable_paths": ["reference"],
"quota": { "soft_limit_bytes": 268435456, "hard_limit_bytes": 322122547 },
"logging": { "level": "INFO", "trace_access": true, "trace_write": true }
},
"logging": {
"level": "INFO",
"logfile": "/var/log/mcpfiles/main.log",
"trace_access": true,
"trace_write": true,
"trace_delete": false,
"trace_metadata": false,
"debug_all": false
},
"remote_server": {
"transport": { "uds": "/var/run/mcpfiles.sock" }
},
"api_keys": [
{
"id": "knowledge-base",
"kdf": { "...": "..." },
"root": "/srv/mcpfiles/agentA",
"projects_enabled": true,
"extension_whitelist": [".md", ".txt"],
"mime_validation": true,
"allow_nonempty_delete": false,
"immutable_paths": ["reference"],
"quota": { "soft_limit_bytes": 536870912, "hard_limit_bytes": 644245094 },
"logging": { "logfile": "/var/log/mcpfiles/agentA.log" }
}
]
}
```
## Workspace Model
- Each stdio run is limited to the root resolved from the `stdio` block
- Remote mode: Every API key maps to a root directory. When `project_id` is provided, the server resolves into `<root>/.projects/<uuid>/`. Access to `.projects` outside the requested `UUID` is denied.
- An optional extension whitelist per root ensures agents only create/modify allowed file types (suffix checks plus optional `file --mime-type` verification when `mime_validation` is enabled).
- Optional quotas (`soft_limit_bytes`, `hard_limit_bytes`) cap total storage consumption per key/project. Hard limits block writes. Soft limits only log events (no response flag), letting agents query usage on demand.
- Hidden `.metadata/usage.json` directories store accounting data and are automatically excluded from MCP listings/reads. Manual tampering is prevented by treating `.metadata` as immutable.
- Immutable paths (relative to the key/project root) can expose reference material while prohibiting writes; mutation requests targeting these paths return an authorization error.
- Recursive deletions require `allow_nonempty_delete=true` in the key config; otherwise only empty directories can be removed.
## FreeBSD Daemon Setup
- Copy the sample `rc.d` script (`contrib/freebsd/mcpfiles`) into `/usr/local/etc/rc.d/mcpfiles` and make it executable:
```sh
install -m 755 contrib/freebsd/mcpfiles /usr/local/etc/rc.d/mcpfiles
```
- Create a dedicated runtime account with no login shell (adjust UID/GID as needed):
```sh
pw useradd mcpfiles -d /nonexistent -s /usr/sbin/nologin
```
- Configure the service in `/etc/rc.conf`:
```sh
mcpfiles_enable="YES"
mcpfiles_user="mcpfiles"
mcpfiles_group="mcpfiles"
mcpfiles_config="/usr/local/etc/mcpfiles.conf"
mcpfiles_transport="remotehttp"
mcpfiles_logfile="/var/log/mcpfiles/remote.log"
mcpfiles_env="FASTMCP_LOG_LEVEL=INFO"
```
The script automatically feeds those variables into `daemon(8)` so the service runs in the background with PID/log files under `/var/run` and `/var/log`. Override `mcpfiles_env` to pass extra environment variables (e.g., `PYTHONPATH=/usr/local/lib/mcpfiles`).
- Manage the service via the standard rc interface: `service mcpfiles start`, `service mcpfiles stop`, `service mcpfiles restart`, `service mcpfiles status`. The `required_files` guard prevents startup when the config file is missing, mirroring the CLI’s existing validation.
- Apply new API keys or quota rules without downtime via `service mcpfiles reload`, which sends `SIGHUP` to the daemon so it re-reads the configuration while keeping the existing TCP/UDS listener online.
- To run the same configuration manually without installing the rc script, launch it with `daemon(8)` directly:
```sh
daemon -f -p /var/run/mcpfiles.pid -u mcpfiles -o /var/log/mcpfiles/remote.log \
/usr/local/bin/mcpfiles --config /usr/local/etc/mcpfiles.conf --transport remotehttp
```
Use `service mcpfiles reload` after editing the configuration or rotating API keys so the running daemon re-reads the JSON without interrupting clients; reserve `restart` for listener changes (host/port/UDS) or code upgrades.
## Connecting with Agents
### Codex example (stdio mode)
```toml
[mcp_servers.mcpfiles]
command = "mcpfiles"
args = [
"--config", "/home/exampleuser/.config/mcpfiles.conf"
]
startup_timeout_sec = 300
[mcp_servers.mcpfiles.env]
# Optional overrides, e.g. logging level or PYTHONPATH if running from source
FASTMCP_LOG_LEVEL = "INFO"
```
### Codex example (remote mode)
```toml
[mcp_servers.mcpfiles]
url = "http://127.0.0.1:7889/mcp/mcp?api_key=XXXXXX"
```
### JSON based MCP configuration
```jsonc
{
"name": "mcpfiles",
"type": "mcp",
"transport": {
"type": "http",
"url": "http://127.0.0.1:8080/mcp",
"headers": {
"Authorization": "Bearer <PLAINTEXT_API_KEY>"
}
},
"tools": {
"allowed": [
"list_dir",
"read_file",
"write_file",
"apply_patch",
"delete_file",
"create_directory",
"remove_directory",
"get_metadata",
"stat_tree"
]
}
}
```
## Salting the System Prompt
When giving the LLM these tools, include a short _workspace contract_ in the system message. A possible example snippet:
```
You are operating inside a sandbox rooted at /srv/mcpfiles/agentA. All paths must remain inside this tree.
- Immutable paths: reference/, templates/ — treat them as read-only.
- Allowed extensions: .md, .txt, .json. Others will be rejected.
- Use list_dir/stat_tree/get_metadata to plan before writing. Large writes count against quota.
- apply_patch accepts Codex-style (*** Begin Patch …) or plain unified diff patches; include correct hunks so validation passes.
- Projects: pass project_id to work inside .projects/<uuid>.
- Typical workflow: list_dir -> read_file -> plan -> write_file/apply_patch -> get_metadata/stat_tree to verify.
```
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues