seafile-mcp
README.md
# seafile-mcp
Model Context Protocol server for [Seafile](https://www.seafile.com/) file storage.
Multi-user, with two token-based auth modes and full file/folder/library management.
Built with [FastMCP](https://github.com/jlowin/fastmcp) (`mcp<2`). Inspired by
[`setugk/seafile-mcp`](https://github.com/setugk/seafile-mcp) (tool coverage),
[`virtUOS/seafile-mcp`](https://github.com/virtUOS/seafile-mcp) (multi-user +
safety modes) and [`5p00kyy/seafile-mcp`](https://github.com/5p00kyy/seafile-mcp)
(dual account/repo-token env config).
## Auth: register once, then pass only `user_id` (tokens only — never passwords)
No tokens are fixed in `.env`. Each user registers once; the server saves the
tokens in a vault file (`SEAFILE_VAULT_PATH`, default `~/.seafile-mcp/vault.json`,
mode `0600`). All later calls pass only `user_id`:
1. `register_user(user_id="alice", account_token="<token>")` — full scope, or
`register_user(user_id="bob", repo_tokens={"Docs": "<token>"})` — scoped.
2. Use any tool with `user_id="alice"` — no tokens per call.
3. Maintain with `update_account_token`, `add_library_tokens`,
`remove_library_tokens`, `remove_account_token`, `revoke_user`;
inspect with `my_credentials` (tokens always masked, never revealed).
Resolution order per call: explicit `account_token`/`repo_token` params →
vault record for `user_id` → env defaults (`SEAFILE_ACCOUNT_TOKEN` /
`SEAFILE_REPO_TOKENS_JSON`, single-user fallback only).
| Credential in vault | Scope |
|---|---|
| **Account token** | Full: all libraries, all tools |
| **Library API tokens** | Only those libraries; browse/read/upload/rename-folders. Library management, move/copy/delete and search return a clear "requires an account token" error (Seafile exposes no such endpoints for repo tokens) |
> **Security note:** `user_id` is self-asserted by the caller — a namespace, not
> an identity proof. Anyone reaching the endpoint could pass another user's id
> and use their stored tokens. Protect multi-user HTTP deployments per user
> (reverse-proxy auth, VPN/Tailscale). For local single-user use, stdio +
> optional env defaults avoid the vault entirely.
### Getting an account token (one-time, never expires)
There is **no Web UI page** for account tokens. Mint it with your username and
password (add `-H 'X-SEAFILE-OTP: <6-digit>'` if you use 2FA):
```bash
curl -d "username=YOUR_EMAIL&password=YOUR_PASSWORD" \
https://YOUR_SEAFILE_SERVER/api2/auth-token/
# {"token": "24fd3c026886e3121b2ca630805ed425c272cb96"}
```
The token is permanent — re-mint only after a password change (which invalidates
it), then save the new one with `update_account_token`. The `get_auth_help`
tool repeats these instructions for agents.
### Getting a library API token (scoped, `r` or `rw`, valid until deleted)
Seafile Web UI: library menu (`⋯`) → **Advanced → API Token** → create with
read or read-write permission. Or via API with an account token:
```bash
curl -H "Authorization: Token <account-token>" -H 'Content-Type: application/json' \
-d '{"app_name": "my-assistant", "permission": "rw"}' \
https://YOUR_SEAFILE_SERVER/api/v2.1/repos/<repo-id>/repo-api-tokens/
```
## Install
```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env # set SEAFILE_SERVER_URL; tokens are registered at runtime
```
Requires `SEAFILE_SERVER_URL` (no trailing slash). Auth header scheme defaults to
`auto` (`Token`, falling back to `Bearer` on 401 — covers Seafile < 11 and ≥ 11).
## Run
```bash
# Local single-user (Claude Desktop / Code / OpenCode)
seafile-mcp --transport stdio
# Multi-user HTTP
seafile-mcp --transport streamable-http --host 127.0.0.1 --port 8000
```
Put the HTTP endpoint behind a reverse proxy / VPN for remote use — it has no
built-in endpoint auth; Seafile tokens travel per tool call.
### Client config examples
stdio (`claude_desktop_config.json` / `.mcp.json`):
```json
{ "mcpServers": { "seafile": {
"command": "/abs/path/seafile-mcp/.venv/bin/seafile-mcp",
"args": ["--transport", "stdio"],
"env": { "SEAFILE_SERVER_URL": "https://seafile.example.com",
"SEAFILE_ACCOUNT_TOKEN": "<token>" }
} } }
```
Streamable HTTP + Docker: `cp .env.example .env`, set values, `docker compose up`.
## Safety modes (`SEAFILE_MCP_MODE`)
- `read_only` — mutating tools are not registered at all.
- `safe_write` (default) — create/rename/move/copy/upload allowed; deletes hidden.
- `full` — also registers `delete_library` (permanent!) and `delete_item` (to trash).
Overwrites create new versions in Seafile file history; deletes go to library
trash. The trash-purge endpoint is deliberately not exposed.
## Tools (26)
User vault (all modes): `register_user`, `update_account_token`,
`add_library_tokens`, `remove_library_tokens`, `remove_account_token`,
`revoke_user`, `my_credentials` · Help: `get_auth_help`, `resolve_library` ·
Libraries (account only):
`list_libraries`, `get_library_info`, `create_library`, `rename_library`,
`delete_library` (full mode) · Files: `list_directory`, `get_file_detail`
(account only), `read_file`, `get_download_link`, `search_files` (account only),
`create_directory`, `upload_file`, `update_file`, `rename_item`, `move_item`
(account only), `copy_item` (account only), `delete_item` (full mode, account only).
Every file/library tool accepts `user_id` (vault), `repo_id` **or**
`library_name`, plus optional `account_token` / `repo_token` overrides
(explicit params win over the vault). `read_file` returns text (truncated
with notice) or, for binaries, metadata + download link. `upload_file` /
`update_file` take text or base64 (`is_base64: true`).
## Tests
```bash
.venv/bin/python -m pytest -q # 40 tests, mocked HTTP (no live server needed)
```
## Roadmap
- PDF/Office text extraction (currently binaries return metadata + link)
- Optional endpoint bearer-auth for the HTTP transport
- Background search index for repo-token libraries (cf. `dm7500/seafile-vault-mcp`)
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues