seafile-vault-mcp
by dm7500
README.md
# seafile-vault-mcp
A self-hosted [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that gives Claude read/write access to a [Seafile](https://www.seafile.com/) library, turning it into a personal knowledge vault ("Second Brain").
The server exposes MCP tools over **Streamable HTTP** (HTTP with JSON/SSE), so it works as a **remote custom connection** from [Claude.ai](https://claude.ai) on desktop and mobile.
## Features
- **Read and write files** in a single configured Seafile library
- **Directory operations** — list, create, delete
- **Full-text search** across vault contents via SQLite FTS5 (no external search service)
- **Persistent search index** that survives container restarts
- **Background sync** re-indexes changed files every 60 seconds
- **Bearer token authentication** on the MCP endpoint
## Prerequisites
- A running Seafile instance (self-hosted or Seafile Cloud)
- A Seafile API token with access to your vault library
- The **repository ID** of the library you want to expose
- Docker and Docker Compose (recommended), or Python 3.12+
## Quick start (Docker)
1. Clone this repository and copy the example environment file:
```bash
cp .env.example .env
```
2. Edit `.env` with your Seafile URL, token, repo ID, and a strong `MCP_AUTH_TOKEN`.
3. Start the server:
```bash
docker compose up -d --build
```
4. Confirm it is running:
```bash
docker compose logs -f
```
On first startup you should see index build progress in the logs. Subsequent restarts load the existing index and run a quick incremental sync.
The MCP endpoint is available at:
```
http://<your-host>:8000/mcp
```
## MCP tools
| Tool | Description |
|------|-------------|
| `read_file` | Read a file by path (text content or binary metadata) |
| `write_file` | Create or overwrite a file |
| `create_directory` | Create a directory (with parent dirs) |
| `delete_file` | Delete a file or empty directory |
| `list_directory` | List directory entries with name, type, size, mtime |
| `search_vault` | FTS5 full-text search with optional path filter and `match_quality` |
## Getting a Seafile API token
1. Log in to your Seafile web interface.
2. Open **Settings** (avatar menu → Settings).
3. Go to the **Developer** or **API** section (wording varies by Seafile version).
4. Click **Generate new token** (or similar).
5. Copy the token into `SEAFILE_TOKEN` in your `.env` file.
The token is sent as `Authorization: Token <token>` to the Seafile API. It is never logged by this server.
## Finding your Seafile repo ID
The repo ID is a UUID that identifies a specific library.
**Via the web UI:** Open the library in Seafile. The URL often contains the repo ID:
```
https://seafile.example.com/library/<repo-id>/...
```
**Via the API:**
```bash
curl -H "Authorization: Token YOUR_TOKEN" \
"https://seafile.example.com/api2/repos/"
```
Look for your library name in the JSON response and copy its `id` field into `SEAFILE_REPO_ID`.
## Adding to Claude.ai
1. Deploy the server so it is reachable over HTTPS from the internet (use a reverse proxy such as nginx or Caddy with TLS).
2. In Claude.ai, go to **Settings → Connectors** (or **Integrations**).
3. Add a **custom MCP server** / **remote connector**.
4. Set the server URL to your public endpoint, including the `/mcp` path:
```
https://mcp.yourdomain.com/mcp
```
5. When prompted for authentication, provide your `MCP_AUTH_TOKEN` as a **Bearer token**.
Claude will connect over Streamable HTTP. The server accepts `GET`, `POST`, and `DELETE` on `/mcp`.
## Environment variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `SEAFILE_URL` | Yes | — | Base URL of your Seafile instance |
| `SEAFILE_TOKEN` | Yes | — | Seafile API token |
| `SEAFILE_REPO_ID` | Yes | — | UUID of the library to expose |
| `MCP_AUTH_TOKEN` | Yes | — | Bearer token required to connect to this MCP server |
| `MCP_HOST` | No | `0.0.0.0` | Host interface to bind |
| `MCP_PORT` | No | `8000` | Port to listen on |
| `INDEX_DB_PATH` | No | `/data/index.db` | Path to the SQLite FTS5 index file |
| `MCP_ALLOWED_ORIGINS` | No | *(none)* | Comma-separated CORS origins for browser clients |
## Local development (without Docker)
```bash
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
export SEAFILE_URL=https://seafile.example.com
export SEAFILE_TOKEN=...
export SEAFILE_REPO_ID=...
export MCP_AUTH_TOKEN=...
export INDEX_DB_PATH=./data/index.db
python server.py
```
## Search index
On first startup the server walks the entire configured library and indexes plain-text files (`.md`, `.txt`, `.py`, `.json`, `.yaml`, and similar formats).
- The index is stored at `INDEX_DB_PATH` (persisted via the Docker `/data` volume).
- Library walks use a single recursive directory listing (`recursive=1`) when the Seafile server supports it.
- A background thread polls Seafile every 60 seconds and re-indexes changed files.
- Writes and deletes update the index immediately.
`search_vault` uses a two-pass strategy: multi-word queries first require **all** terms to match (`match_quality: "exact"`). If that returns no results, it falls back to matching **any** term (`match_quality: "partial"`).
Only the single library identified by `SEAFILE_REPO_ID` is accessible — not your full Seafile account.
## Running tests
```bash
pip install -r requirements-dev.txt
pytest
```
## Security notes
- Use a long, random `MCP_AUTH_TOKEN` and terminate TLS at a reverse proxy.
- The server exposes one Seafile library only; repo ID and token are fixed at deploy time.
- Seafile credentials are read from environment variables and are not written to logs.
- CORS is disabled by default. Set `MCP_ALLOWED_ORIGINS` only if you need browser-based MCP clients.
## Project layout
```
seafile-vault-mcp/
server.py MCP server, tools, HTTP transport
seafile.py Seafile REST API client
index.py SQLite FTS5 index management
Dockerfile
docker-compose.yml
.env.example
requirements-dev.txt
tests/
README.md
LICENSE
```
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues