Files
outline-mcp-custom/IMPLEMENTATION.md
T
b3nw 950a8fc441
Build and Push Outline MCP Docker Image / build (push) Successful in 14s
feat: add binary file attachment and import tools for Outline LTM system (#1)
Implement 3 new MCP tools:
- attach_file_to_document(document_id, file_path)
- upload_image_to_document(image_path, document_id, alt_text)
- import_file_to_outline(file_path, collection_id, parent_document_id)

Security:
- Restrict file access to /tmp via _validate_file_path with realpath
- 50MB max file size enforced client-side
- Symlink traversal blocked

Technical:
- Extract shared _upload_attachment() helper
- Stream files to presigned URLs instead of loading into memory
- Add combined lifespan to close OutlineClient on shutdown
- Update CI workflow with modern action versions and PR triggers

Tests:
- Add 28 tests covering path validation, size limits, upload flow,
  error handling, symlink traversal, and multipart imports
2026-05-25 01:03:43 +00:00

428 lines
10 KiB
Markdown

# Outline MCP Implementation Guide
This document provides implementation details and comprehensive API reference for AI agents using the Outline MCP server.
## Architecture
The server follows the Hybrid MCP Light pattern:
- 4 specific tools for common read operations
- 1 API passthrough for full coverage
- Embedded API reference resource
## Tools Overview
### search_documents
Full-text search across all documents.
```
Params: query (required), collection_id, limit (default 25), include_archived
Returns: Search results with document titles, IDs, and context snippets
```
### get_document
Retrieve a document by ID.
```
Params: document_id (required), share_id
Returns: Document metadata and full Markdown content
```
### list_collections
List all collections in the workspace.
```
Params: limit (default 25), offset
Returns: Collection names, IDs, permissions, and metadata
```
### list_collection_documents
List documents within a specific collection.
```
Params: collection_id (required), limit, offset
Returns: Document tree structure for the collection
```
### outline_api_call
Raw API passthrough for any Outline endpoint.
```
Params: method (required), params (JSON string)
Returns: Raw API response as JSON string
```
### attach_file_to_document
Upload a local file as an attachment to an existing Outline document.
```
Params: document_id (required), file_path (required — must be under /tmp)
Returns: JSON with attachment_url, markdown embed string, name, size, content_type
```
### upload_image_to_document
Upload an image file as an attachment and return Markdown image embed syntax.
```
Params: image_path (required — must be under /tmp), document_id (required), alt_text (optional)
Returns: JSON with attachment_url, markdown image embed, name, size, content_type
```
### import_file_to_outline
Import a local file (Markdown, text, JSON, CSV) as a new Outline document.
```
Params: file_path (required — must be under /tmp), collection_id (required), parent_document_id (optional)
Returns: JSON with newly created document metadata
```
---
## Outline API Reference
Outline uses an RPC-style API where all requests are POST to /api/<method>.
All responses have format: {"ok": true/false, "data": ...}
### Authentication
All requests require Bearer token: Authorization: Bearer <token>
Get your token from Outline Settings > API Tokens.
### Pagination
Most list endpoints accept: limit (default 25, max 100), offset (default 0)
Response includes: pagination.nextPath if more results exist.
---
## Documents
### documents.list
List documents. Params: collectionId?, userId?, parentDocumentId?, sort?, direction?, limit?, offset?
### documents.info
Get document by ID. Params: id (required), shareId?
### documents.search
Full-text search. Params: query (required), collectionId?, userId?, dateFilter?, includeArchived?, includeDrafts?, limit?, offset?
### documents.create
Create document. Params: title (required), collectionId (required), text?, parentDocumentId?, templateId?, template?, publish?
### documents.update
Update document. Params: id (required), title?, text?, append?, publish?, done?
### documents.delete
Delete document. Params: id (required), permanent?
### documents.move
Move document. Params: id (required), collectionId?, parentDocumentId?
### documents.archive
Archive document. Params: id (required)
### documents.unarchive
Restore archived document. Params: id (required)
### documents.restore
Restore deleted document. Params: id (required), revisionId?
### documents.export
Export document. Params: id (required)
Returns Markdown content.
### documents.import
Import document. Multipart form: file, collectionId, parentDocumentId?, template?, publish?
### documents.star
Star a document. Params: id (required)
### documents.unstar
Remove star. Params: id (required)
### documents.templatize
Convert to template. Params: id (required)
### documents.unpublish
Unpublish document. Params: id (required)
---
## Collections
### collections.list
List all collections. Params: limit?, offset?
### collections.info
Get collection details. Params: id (required)
### collections.documents
Get document structure for collection. Params: id (required), limit?, offset?
### collections.create
Create collection. Params: name (required), description?, color?, permission?, sharing?
### collections.update
Update collection. Params: id (required), name?, description?, color?, permission?, sharing?
### collections.delete
Delete collection. Params: id (required)
### collections.add_user
Add user to collection. Params: id (required), userId (required), permission?
### collections.remove_user
Remove user from collection. Params: id (required), userId (required)
### collections.memberships
List collection members. Params: id (required), query?, permission?, limit?, offset?
### collections.add_group
Add group to collection. Params: id (required), groupId (required), permission?
### collections.remove_group
Remove group. Params: id (required), groupId (required)
### collections.group_memberships
List group memberships. Params: id (required), query?, permission?, limit?, offset?
### collections.export
Export entire collection. Params: id (required), format?
### collections.export_all
Export all collections. Params: format?
---
## Users
### users.list
List workspace users. Params: query?, filter?, sort?, direction?, limit?, offset?
Filter options: all, active, invited, suspended, admins
### users.info
Get user by ID. Params: id (required)
### users.invite
Invite users. Params: invites (array of {email, name, role})
### users.update
Update user. Params: id (required), name?, avatarUrl?
### users.delete
Delete user. Params: id (required)
### users.suspend
Suspend user. Params: id (required)
### users.activate
Activate suspended user. Params: id (required)
### users.promote
Promote to admin. Params: id (required)
### users.demote
Remove admin. Params: id (required)
---
## Groups
### groups.list
List groups. Params: query?, sort?, direction?, limit?, offset?
### groups.info
Get group. Params: id (required)
### groups.create
Create group. Params: name (required)
### groups.update
Update group. Params: id (required), name (required)
### groups.delete
Delete group. Params: id (required)
### groups.memberships
List group members. Params: id (required), query?, limit?, offset?
### groups.add_user
Add user to group. Params: id (required), userId (required)
### groups.remove_user
Remove user from group. Params: id (required), userId (required)
---
## Comments
### comments.list
List comments on document. Params: documentId (required), limit?, offset?
### comments.create
Create comment. Params: documentId (required), data (required - ProseMirror JSON)
### comments.update
Update comment. Params: id (required), data (required)
### comments.delete
Delete comment. Params: id (required)
---
## Revisions
### revisions.list
List document revisions. Params: documentId (required), limit?, offset?
### revisions.info
Get revision. Params: id (required)
---
## Shares
### shares.list
List document shares. Params: documentId?, sort?, direction?, limit?, offset?
### shares.info
Get share by ID or documentId. Params: id?, documentId?
### shares.create
Create share link. Params: documentId (required), published?, urlId?, includeChildDocuments?
### shares.update
Update share. Params: id (required), published?, urlId?, includeChildDocuments?
### shares.revoke
Revoke share. Params: id (required)
---
## Stars
### stars.list
List starred documents. Params: limit?, offset?
### stars.create
Star an item. Params: documentId?, collectionId?
### stars.delete
Remove star. Params: id (required)
---
## Events
### events.list
List audit events. Params: name?, actorId?, documentId?, collectionId?, auditLog?, sort?, direction?, limit?, offset?
---
## File Operations
### fileOperations.list
List file operations. Params: type?, limit?, offset?
### fileOperations.info
Get file operation status. Params: id (required)
### fileOperations.redirect
Get download URL. Params: id (required)
### fileOperations.delete
Delete file operation. Params: id (required)
---
## Attachments
### attachments.create
Create attachment upload URL. Params: name (required), documentId (required), size (required), contentType (required)
### attachments.delete
Delete attachment. Params: id (required)
### attachments.redirect
Get attachment URL. Params: id (required)
---
## Auth
### auth.info
Get current user and team info. No params.
### auth.config
Get auth configuration. No params.
---
## Views
### views.list
List document views. Params: documentId (required), limit?, offset?
### views.create
Record a view. Params: documentId (required)
---
## Common Response Patterns
### Success
```json
{"ok": true, "data": {...}, "pagination": {"nextPath": "...", "limit": 25, "offset": 0}}
```
### Error
```json
{"ok": false, "error": "message", "status": 401}
```
### Rate Limiting
HTTP 429 with Retry-After header
---
## Usage Examples
### Create a document
```
method: "documents.create"
params: {"title": "My Document", "collectionId": "collection-uuid", "text": "# Hello\n\nDocument content here.", "publish": true}
```
### Update document content
```
method: "documents.update"
params: {"id": "document-uuid", "text": "# Updated Content\n\nNew content here."}
```
### Delete a document
```
method: "documents.delete"
params: {"id": "document-uuid"}
```
### Invite a user
```
method: "users.invite"
params: {"invites": [{"email": "user@example.com", "name": "User Name", "role": "member"}]}
```
### Create a collection
```
method: "collections.create"
params: {"name": "Engineering", "description": "Engineering documentation", "permission": "read_write"}
```
### Attach a file to a document
```
document_id: "document-uuid"
file_path: "/tmp/report.pdf"
```
### Upload an image to a document
```
image_path: "/tmp/screenshot.png"
document_id: "document-uuid"
alt_text: "System architecture diagram"
```
### Import a Markdown file as a new document
```
file_path: "/tmp/notes.md"
collection_id: "collection-uuid"
parent_document_id: "parent-document-uuid" # optional
```