An MCP server that gives an AI model access to your own La Suite Docs account: list, read, create, update, organize, and share documents.
Runs locally over stdio (e.g. launched by Claude Code / Claude Desktop), acting as you — it's not a hosted multi-user service.
- Auth: login happens via a real, visible browser window (Firefox, controlled by Playwright) that drives your Docs instance's own
/api/v1.0/authenticate/flow — the same OIDC/SSO login you'd use normally, including MFA. The resulting Django session cookie is stored locally (encrypted) and reused for API calls; no separate OAuth client registration is needed. - Content: document bodies are stored server-side as a base64-encoded Yjs CRDT blob (BlockNote's editor format), not plain Markdown. This server converts transparently in both directions using
@blocknote/core+@blocknote/server-util— the same library La Suite Docs' own backend uses for this — so tools speak plain Markdown.
Prerequisites: Node.js 22+.
npm install
npx playwright install firefoxCreate ~/.config/mcp-lasuite-docs/config.json:
{
"docsBaseUrl": "https://docs.example.org"
}Log in (opens a Firefox window — complete your normal login there, including any SSO/MFA):
npm run loginCheck who's linked, or clear the stored session:
npm run whoami
npm run logoutAdd to .mcp.json:
{
"mcpServers": {
"lasuite-docs": {
"type": "stdio",
"command": "npx",
"args": ["tsx", "src/server.ts"]
}
}
}Note: this spawns a long-lived subprocess. If you edit the server's source, reconnect/restart it (e.g. /mcp reconnect in Claude Code) to pick up the changes — it won't hot-reload.
Account
whoami— the currently linked Docs accountsearch_users— search users by email (≥5 chars), to find auser_idbefore sharing
Documents
list_documents— list documents visible to you (filter by title/favorite/creator, sort, paginate)get_document— metadata + body content (decoded to Markdown)create_document— create a document, optionally with Markdown content and/or a parent (sub-document)update_document— update title and/or body contentdelete_document/restore_document— soft-delete (trash) / restorelist_trash— recoverable soft-deleted documentslist_favorites/set_favoriteget_document_tree— ancestors + children (breadcrumb view)move_document— reposition in the document tree
Sharing
get_document_sharing— link-sharing config + direct accesses + invitationsset_link_sharing— configurelink_reach/link_roleshare_document— grant a user direct accessupdate_document_access/revoke_document_access
Versions
list_document_versions— version historyget_document_version— a specific historical version, decoded to Markdown where available
Not built yet: duplicating documents, listing full descendant subtrees, deleting a specific version, email invitations for users without accounts yet, file attachments, templates, AI transform/translate passthroughs.
src/
├── server.ts # FastMCP app + tool registration
├── config.ts # config.json loading (docsBaseUrl)
├── auth.ts # Playwright login flow, encrypted session-cookie storage
├── docsClient.ts # REST client: cookie/CSRF auth, pagination, error mapping
├── content.ts # Markdown <-> Yjs conversion (@blocknote/server-util)
├── tools/ # tool implementations (documents, sharing, versions, users)
└── cli.ts # `login` / `logout` / `whoami` commands
Some things differ from the general La Suite Docs API documentation and were found by probing a real instance:
- Document body content is not embedded in the main
documents/{id}/response. It lives at a separateGET/PATCH documents/{id}/content/endpoint, returned as rawtext/plainbase64 (not JSON) onGET, and written asPATCHwith JSON body{"content": "<base64>"}. - The Yjs XML fragment holding the document body is named
document-store(not BlockNote's own default ofprosemirror). documents/{id}/versions/uses S3-style cursor pagination ({count, is_truncated, next_version_id_marker, versions}), not the standard DRF paginated envelope.- State-changing requests need
X-CSRFTokenplusOrigin/Refererheaders matching the instance, in addition to the session cookie (Django's CSRF protection).
- Your actual Docs username/password never touch this tool — you log in directly against your identity provider's own page in the Playwright-controlled browser.
- The session cookie is stored AES-256-GCM encrypted at
~/.config/mcp-lasuite-docs/session.enc, with the key at~/.config/mcp-lasuite-docs/key(both0600). As with most local CLI credential stores, the real protection boundary is OS file permissions on your home directory, not the encryption itself. - There's no refresh mechanism for the session (unlike OAuth tokens) — once the Django session cookie expires, tools will fail with an auth error and you'll need to
npm run loginagain.