lasuite-docs-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@lasuite-docs-mcpSearch our docs for the onboarding checklist."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
lasuite-docs-mcp
An MCP server for a self-hosted La Suite Docs instance. It lets an MCP client such as Claude Code search, browse, read, create, and edit Docs documents, and @-mention a favorited document straight into context.
This is under active development and should be treated as experimental. Things break, behaviour changes without notice, and parts of it may not work against your instance at all. It is not on npm yet, there is no release, and it depends on Docs API actions that are undocumented upstream and can change under it. Do not point it at documents you care about before working through Before you point it at real documents.
Contents
Related MCP server: Day 5 Remote MCP Server
What it does
Tool | What it does |
| Full-text search across the instance. Returns id, title, and path. |
| Browse by recency, favorites, or documents you created, without a search query. |
| A document's ancestors and children, to orient in a wiki without reading content. |
| Create a document from markdown, optionally nested under a parent. |
| A document's content as markdown. Large documents return a section outline instead of truncating. |
| Replace, append, prepend, or edit one section of an existing document. |
Favorited documents are also exposed as MCP resources (docs://document/<id>),
so they can be @-mentioned directly instead of fetched through docs_read.
Requirements
Docs instance |
|
Docs configuration | Resource server enabled, plus an |
Identity provider | Any OIDC provider that supports authorization code with PKCE and loopback redirects. |
Node | 22 or newer. |
Setup touches three systems in order: your identity provider, the Docs instance, and then your own machine. The first two usually need whoever administers them.
Setup
1. Register an OAuth client
This tool logs in as a public OAuth client. Register one with your identity provider:
Setting | Value |
Client ID |
|
Client type | Public. No client secret. |
Grant type | Authorization code with PKCE, method |
Redirect URI |
|
Scopes | Must include |
The redirect URI needs that wildcard port. login starts a loopback listener
on an ephemeral port and builds the redirect URI from whatever port the OS
hands it, so the port is different on every login. A single fixed-port entry
works once and then fails. Providers that follow
RFC 8252 §7.3
allow this; in Keycloak, http://127.0.0.1:*/callback is accepted verbatim.
Consider requestingoffline_access as well, via
DOCS_OIDC_SCOPE="openid offline_access".
Without it, most providers tie the refresh token to your browser SSO session
and expire it after a short idle period, often 30 minutes. The MCP server
renews its access token from that refresh token silently, but it runs without
a terminal or a browser, so it can never redo the login flow itself. When the
refresh token dies, every tool starts returning "Not authenticated" until you
run login again by hand.
offline_access asks for a refresh token that outlives the browser session,
which is what makes a long-running MCP server practical. The trade is a
credential on disk that stays valid for much longer, so skip it if that is
not acceptable and accept re-running login instead.
2. Configure the Docs instance
Docs must run as an OIDC resource server:
OIDC_RESOURCE_SERVER_ENABLED=True
OIDC_OP_URL=https://sso.example.org/realms/main
OIDC_OP_INTROSPECTION_ENDPOINT=https://sso.example.org/realms/main/protocol/openid-connect/token/introspect
OIDC_RS_CLIENT_ID=docs-resource-server
OIDC_RS_CLIENT_SECRET=<secret of docs-resource-server>
OIDC_RS_AUDIENCE_CLAIM=client_id
OIDC_RS_ALLOWED_AUDIENCES=lasuite-docs-mcp
EXTERNAL_API={"documents":{"enabled":True,"actions":["list","retrieve","create","children","tree","search","content","content_retrieve","formatted_content","can_edit"]}}That is the complete set. Restart Docs afterwards.
OIDC_RS_ALLOWED_AUDIENCES must contain this tool's client ID. Docs
introspects every incoming token, reads the claim named by
OIDC_RS_AUDIENCE_CLAIM (default client_id), and rejects the request
unless that value appears in OIDC_RS_ALLOWED_AUDIENCES. Miss this and
login succeeds while every single tool call returns 403.
Two different clients are involved here, and both are called a client ID:
Variable | Which client | Type |
| The one this tool logs in as, from step 1. | Public |
| The one Docs itself uses to call the introspection endpoint. | Confidential |
Notes on EXTERNAL_API and allowed audiences
EXTERNAL_API gates which API actions an external client may call. Every
action in the list above is one this server actually calls, so none of them can
be dropped. favorite_list is always permitted by Docs and needs no entry,
which is why the resource listing works without one.
EXTERNAL_API is a Python literal, not JSON. Docs parses it with
ast.literal_eval, so the boolean must be True, capitalised. A copied JSON
snippet with lowercase true makes Docs fail at startup with
Cannot interpret dict value. Keeping the value free of spaces also avoids
quoting surprises in .env files and Compose.
OIDC_RS_ALLOWED_AUDIENCES is a comma-separated list, so several clients can
be allowed at once: OIDC_RS_ALLOWED_AUDIENCES=lasuite-docs-mcp,other-client.
3. Install
There is no npm release yet, so install from source:
git clone https://github.com/JonasDoebertin/lasuite-docs-mcp.git
cd lasuite-docs-mcp
npm ci
npm run build
npm link4. Configure this tool
export DOCS_URL=https://docs.example.org
export DOCS_OIDC_ISSUER=https://sso.example.org/realms/main
export DOCS_OIDC_CLIENT_ID=lasuite-docs-mcpVariable | Required | Default | Notes |
| Yes | Base URL of the Docs instance. | |
| Yes | Issuer URL. Must serve | |
| Yes | The public client from step 1. | |
| No |
| See the note on |
| No |
| Keeps several instances' credentials side by side. |
5. Log in
lasuite-docs-mcp loginThis opens a browser for an authorization-code-with-PKCE flow against your
identity provider and stores the resulting tokens at
~/.config/lasuite-docs-mcp/<profile>.json, mode 0600.
6. Check the instance
lasuite-docs-mcp doctordoctor probes four of the ten actions (list, search, tree, and
formatted_content) and prints the full EXTERNAL_API value to set if any of
them is blocked. The other six cannot be probed without creating or modifying
something, so they are assumed available and report a classified error on first
use instead. A clean doctor is a good sign rather than a guarantee that
editing works.
7. Connect your MCP client
For Claude Code:
claude mcp add lasuite-docs \
-e DOCS_URL=https://docs.example.org \
-e DOCS_OIDC_ISSUER=https://sso.example.org/realms/main \
-e DOCS_OIDC_CLIENT_ID=lasuite-docs-mcp \
-- lasuite-docs-mcp-serverFor any other client, run lasuite-docs-mcp-server over stdio with the same
environment.
The server binary never performs the login flow. It only reads the
credentials thatlogin already stored. Run login from a terminal first,
because a server launched by an MCP client has no browser to open.
Before you point it at real documents
Writes replace a document's Yjs state in full, and the conversion that produces
that state runs against block specs vendored from Docs v5.6.1. If your
instance's block schema differs, a write can fail or mangle content.
npm run check:drift does not tell you this. It compares the vendored files
against the pinned upstream release, not against your instance. The only real
check is the contract suite:
npm run test:contractPoint it at a scratch instance, not your real one. It creates documents and
deliberately never deletes them. Once it passes there, switch DOCS_URL over.
Troubleshooting
Symptom | Likely cause |
Browser shows "invalid redirect URI" during login | The redirect URI is not registered with a wildcard port. See step 1. |
Login succeeds, but every tool call returns 403 |
|
"The Docs instance does not permit the X action" |
|
Some tools never appear in the client at all | The startup probe got a 403 for them. Run |
"Not authenticated with Docs. Run login" after idling | The refresh token expired. Run |
| A collaborative session is active. This is deliberate, see Known limitations. |
| The instance's block schema disagrees with the vendored specs. Repin |
| Only four actions are probed. The rest fail at call time by design. |
CLI reference
Command | What it does |
| Perform the OAuth login and store credentials. |
| Delete the stored credentials for the active profile. |
| Show whether a profile is logged in and when its token expires. |
| Probe the instance's |
| The MCP server itself, over stdio. |
Known limitations
These are design constraints rather than bugs. Most of them come from what the Docs API does and does not offer.
An edit resets the document's Yjs history
Docs stores a document as a Yjs CRDT state, and every write from this tool replaces that state in full, the same way a fresh document would be written. Collaborative undo across that edit is gone afterwards. You can still step back through changes made after the edit, but not through the edit itself. Upstream Docs' own markdown import behaves identically, so this is not a shortcut this tool takes. It is how the endpoint works.
Editing is refused while someone has the document open
Docs rejects a write while a collaborative session is active over the websocket,
and this tool does not use the flag that would bypass that check, because
bypassing it would silently overwrite whatever that person is typing.
docs_edit fails immediately in that case rather than retrying or queuing.
A whole-document replace refuses to discard unrepresentable blocks
Callouts, PDF blocks, upload loaders, and page breaks have no markdown
representation, so a replace built from markdown alone would drop them
silently. The tool refuses unless confirmLossy is set. append, prepend,
and the section operations need no such guard, since they only touch the range
you named.
Concurrent-modification detection is best effort
Before writing, the client re-reads the document's ETag and compares it against
the value read at the start of the edit. Docs' PATCH /documents/{id}/content/
endpoint has no conditional-write support, so there is no If-Match and this is
a manual before-and-after comparison rather than an atomic check. A narrow
window remains where a concurrent write landing between the second read and the
write itself can be lost. On an instance that strips ETags, such as one sitting
behind a proxy that does not forward them, the check cannot run at all, and
docs_edit says so plainly in its result.
BlockNote is pinned to 0.54.0 to match Docs v5.6.1
Content conversion runs @blocknote/server-util locally against block specs
vendored from that Docs release. Targeting an instance whose block schema
differs means repinning REF in scripts/vendor-blockspecs.sh, running
npm run vendor, and getting npm run test:contract green before writes can
be trusted again. Re-running npm run vendor on its own changes nothing: it
re-fetches the same pinned release.
Only the first 50 favorites become resources
If your account has more than 50 favorited documents, the rest are not
registered as docs://document/<id> resources and will not appear in
@-mention. Docs' favorite_list endpoint takes no ordering parameter, so which
50 you get is whatever order the API happens to return, not "most recent" or
anything else guaranteed. Documents past the cap remain reachable through
docs_list and docs_read. When the cap is hit, the server writes a
truncation notice to stderr; it does not appear anywhere in the MCP protocol
responses.
Development
npm run build # compile to dist/
npm test # unit tests
npx tsc --noEmit # typecheck
npm run vendor # re-fetch block specs from the ref pinned in scripts/
npm run check:drift # vendored block specs vs that pinned ref
npm run test:contract # live-instance suite, see tests/contract/README.mdSee CLAUDE.md for the architecture and the invariants worth knowing before changing the edit or conversion paths.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
An agent-first office suite Claude & ChatGPT read and write over one MCP URL.
Team docs served to AI agents over MCP - search, Markdown reads, version pinning, read audit.
Connect your team's living knowledge base — docs, data, issues, CRM — to Claude and ChatGPT.
- TaprootOAuthcom.taproothq
Persistent memory layer for AI tools. Save and recall notes across Claude and other MCP clients.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceConnects Claude to Google Docs, allowing users to list, read, create, update, search, and delete documents in their Google Drive through natural language interactions.8811MIT
- FlicenseNot gradedqualityFmaintenanceEnables Claude Web to interact with Google Docs through a remote HTTP-based MCP server. Provides scalable document operations including creation, editing, and management with service account authentication.-
- AlicenseNot gradedqualityDmaintenanceEnables Claude to interact with collaborative Docs instances, providing document management, content editing, access control, and AI-powered transformations via MCP.1MIT
- AlicenseNot gradedqualityFmaintenanceMCP server that allows you to connect to Google Docs through Claude, enabling listing, reading, creating, updating, searching, and deleting documents.88148MIT