Files
nextcloud-mcp/README.md
T
bea 8461970523 Step 10: Code review, testing & documentation
Code Review (REVIEW.md):
- Fixed parseSearchResponse skipping first result (critical bug)
- Fixed trashbin/versions/chunked paths missing /remote.php/dav prefix
- Fixed trash_restore to use original file location instead of /restore endpoint
- Fixed createTask/updateTask missing iCal text escaping
- Added 409 handling for createFolder (parent missing)
- Extracted duplicate decodeXmlText to utils.ts
- Extracted duplicate generateUID to utils.ts (shared with calendar/tasks)
- Removed 5 dead code functions (parseVEVENT, extractVEventBlocks, unfoldICalLines, getCalDAVXmlHeaders, local decodeXmlText)
- Cleaned unused imports across all tool files

Testing (RESULTS.md):
- 35 tests passed, 1 skipped (trash_empty), 1 server limitation (bulk_upload)
- Tested all 21+ file tools, edge cases (spaces, unicode, overwrite, empty folders)
- Verified chunked upload end-to-end

Documentation (README.md):
- Complete tool reference (21 file + 10 other tools)
- Quick start, CLI usage, size limits, troubleshooting
- Architecture overview
2026-05-11 18:05:37 +02:00

274 lines
9.1 KiB
Markdown

# nextcloud-mcp
MCP (Model Context Protocol) server for Nextcloud — browse, read, write, and manage files, calendars, tasks, notes, and email via WebDAV/CalDAV/REST APIs.
## Features
- **21 file management tools** — browse, search, read, upload, move, copy, delete, trashbin, favorites, versions
- **Calendar tools** — list calendars, get/create events (CalDAV)
- **Task tools** — get/create/update tasks (CalDAV VTODO)
- **Note tools** — get/create notes (Nextcloud Notes API)
- **Email tool** — get inbox emails (Nextcloud Mail API)
- **Smart size routing** — small files inline (≤10MB), large files via direct URL or chunked upload
- **CLI wrapper** — `ncmcp` command for quick testing and scripting
## Quick Start
### 1. Configure
Create `.env` in the project root:
```env
NEXTCLOUD_URL=https://your-nextcloud.example.com
NEXTCLOUD_USERNAME=your_username
NEXTCLOUD_PASSWORD=your_app_password
```
> Use an **app password** (Settings → Security → App passwords) instead of your main password.
### 2. Build
```bash
npm install
npm run build
```
### 3. Test Connection
```bash
node ncmcp.mjs list_files path=/
node ncmcp.mjs get_quota
```
### 4. Use with MCP (mcporter)
Add to your `mcporter.json`:
```json
{
"nextcloud": {
"command": "node",
"args": ["path/to/nextcloud-mcp/build/index.js"],
"env": {
"NEXTCLOUD_URL": "https://your-nextcloud.example.com",
"NEXTCLOUD_USERNAME": "your_username",
"NEXTCLOUD_PASSWORD": "your_app_password"
}
}
}
```
Then use: `mcporter call nextcloud.list_files --args '{"path":"/"}'`
## CLI Usage (ncmcp)
```bash
ncmcp <tool> [key=value ...] [positionalPath] [@file] [--curl]
```
**Examples:**
```bash
# List files
ncmcp list_files path=/Documents
# Read a file
ncmcp read_file path=/Documents/notes.txt
# Upload a file
ncmcp upload_file path=/Documents/new.txt content="Hello World"
ncmcp upload_file path=/Documents/photo.jpg @./local-photo.jpg
# Download (get URL)
ncmcp download_file path=/Documents/video.mp4
ncmcp download_file path=/Documents/video.mp4 --curl # prints curl command
# Search
ncmcp search_files query="report" mimeType="application/pdf" limit=10
# Pipe content
echo "file contents" | ncmcp upload_file path=/test.txt
```
## Tool Reference
### 🔷 Browsing & Discovery
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `list_files` | List directory contents | `path` (default: `/`), `depth` (`0`/`1`/`infinity`) |
| `get_file_info` | Get detailed file/folder metadata | `path` (required) |
| `search_files` | Search by name, mime, size, date | `query`, `mimeType`, `minSize`, `maxSize`, `sortBy`, `limit` |
| `list_favorites` | List favorited files | `path` (scope) |
| `get_quota` | Get storage usage | — |
### 🔷 Read & Download
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `read_file` | Read file content (text or base64) | `path`, `encoding` (`utf8`/`base64`), `maxSize` (default 10MB) |
| `download_file` | Get direct download URL | `path`, `metadata` (default: true) |
| `download_folder` | Download folder as ZIP/TAR | `path`, `format` (`zip`/`tar`), `files` (subset), `maxSize` (default 50MB) |
### 🔷 Write & Upload
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `upload_file` | Upload file via PUT | `path`, `content`, `encoding`, `contentType`, `mtime` |
| `create_folder` | Create a new folder | `path` |
| `bulk_upload` | Upload multiple files at once | `files[]` (path, content, encoding, contentType) |
### 🔷 Chunked Upload (Large Files)
For files too large for a single `upload_file` call (>10MB content in parameter).
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `chunked_upload_start` | Start upload session | `path`, `totalSize`, `chunkSize` (default 10MB) |
| `chunked_upload_chunk` | Upload one chunk (base64) | `uploadId`, `chunkIndex` (1-based), `content` |
| `chunked_upload_finish` | Assemble final file | `uploadId`, `mtime` |
**Flow:** Start → upload chunks (1..N) → finish. All steps must be in the same session (in-memory state).
### 🔷 Move, Copy, Delete
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `move_file` | Move/rename file or folder | `source`, `destination`, `overwrite` |
| `copy_file` | Copy file or folder | `source`, `destination`, `overwrite` |
| `delete_file` | Delete (moves to trashbin) | `path` |
### 🔷 Trashbin
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `trash_list` | List deleted items | — |
| `trash_restore` | Restore from trash | `trashPath` (from `trash_list`) |
| `trash_delete` | Permanently delete | `trashPath` |
| `trash_empty` | Empty entire trashbin | — (⚠️ destructive) |
### 🔷 Favorites & Versions
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `set_favorite` | Toggle favorite status | `path`, `favorite` (boolean) |
| `get_file_versions` | List file versions | `fileId` (oc:fileid) |
| `restore_file_version` | Restore a version | `fileId`, `versionName` |
### 📅 Calendar
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `list_calendars` | List CalDAV calendars | — |
| `get_calendar_events` | Get events in date range | `startDate`, `endDate`, `calendar`, `limit` |
| `create_calendar_event` | Create event | `summary`, `startDateTime`/`endDateTime`, `allDay`, `location`, `reminderMinutesBefore` |
### ✅ Tasks
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `get_tasks` | Get tasks (VTODO) | `status` (`all`/`open`/`completed`), `limit` |
| `create_task` | Create task | `summary`, `description`, `due`, `priority` |
| `update_task` | Update task | `taskId`, `summary`, `status`, `percentComplete` |
### 📝 Notes
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `get_notes` | List notes | `limit` |
| `create_note` | Create note | `content`, `title`, `category` |
| `get_note_content` | Get note by ID | `noteId` |
### 📧 Email
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `get_emails` | Get inbox emails | `accountId` (default 0), `limit` |
## Size Limits & Routing
MCP transports data as JSON over stdio. Large files need special handling:
```
UPLOAD
├─ Content ≤ ~10MB in param → upload_file (PUT)
├─ Content > 10MB → chunked_upload_start/chunk/finish
└─ Many small files → bulk_upload (multipart/related)
READ
├─ File ≤ maxSize (10MB) → read_file (inline content)
└─ File > maxSize → download_file (direct URL)
DOWNLOAD FOLDER
├─ Archive ≤ 50MB → download_folder (inline base64)
└─ Archive > 50MB → download_folder (direct URL)
```
The limits are MCP transport constraints, not Nextcloud limits. Nextcloud handles files of any size.
## Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| `NEXTCLOUD_URL` | Yes | Nextcloud base URL (e.g. `https://cloud.example.com`) |
| `NEXTCLOUD_USERNAME` | Yes | Nextcloud username |
| `NEXTCLOUD_PASSWORD` | Yes | App password (recommended) or account password |
| `DEBUG_NEXTCLOUD_MCP` | No | Set to `1` for debug logging (calendar operations) |
## Troubleshooting
### Connection errors
- Verify `NEXTCLOUD_URL` is accessible (no trailing slash)
- Check credentials — use an app password, not your main password
- Test: `curl -u user:pass https://your-nextcloud.example.com/remote.php/dav/`
### "File too large" errors
- Use `download_file` to get a direct URL for large files
- Use `chunked_upload_*` tools for large uploads
- Adjust `maxSize` parameter if needed
### Search returns empty
- The server may not have Full Text Search enabled
- The tool falls back to PROPFIND with depth infinity — works but slower on large directories
- Narrow the search scope with `path` parameter
### Calendar/Task errors
- Ensure CalDAV is enabled on the server
- Check that the calendar/task list exists (default: `personal` calendar, `tasks` list)
- Set `DEBUG_NEXTCLOUD_MCP=1` for detailed CalDAV logging
### Bulk upload fails
- The `/remote.php/dav/bulk` endpoint may not be available on all Nextcloud versions
- Fall back to individual `upload_file` calls
## Development
```bash
npm run build # Compile TypeScript
npm run watch # Watch mode
npm run dev # Run with tsx (no build needed)
```
## Architecture
```
src/
├── index.ts — MCP server entry point
├── types.ts — Shared TypeScript interfaces
├── client.ts — Nextcloud HTTP client (axios, WebDAV methods)
├── webdav.ts — WebDAV XML builders & parsers
├── caldav.ts — CalDAV XML builders & iCal parsers
├── utils.ts — Shared utilities (path, mime, formatting)
└── tools/
├── index.ts — Tool registry & routing
├── files.ts — 24 file management tools
├── calendar.ts — 3 calendar tools
├── tasks.ts — 3 task tools
├── notes.ts — 3 note tools
└── email.ts — 1 email tool
```
## License
MIT