Connecting an AI client
By the end of this a client will be connected over MCP, reaching exactly one workspace, able to do exactly what you allowed, and acting as you.
Which of the two you need
There are two ways in, and which one applies depends on the client rather than on a preference.
- OAuth, if the client can open a browser. This is most desktop assistants, and it is the one to use: you approve the connection on a screen that says what is being asked for, and you can revoke it later without touching a config file.
- A static bearer token, if the client has no browser — scripts, CI, and the stdio transport.
Connecting over OAuth
Point the client at the MCP endpoint:
http://127.0.0.1:3001/mcp
Substitute your installation's public MCP address. The client discovers the rest by itself: it fetches the resource metadata, finds the authorization server, registers itself, and sends you to a consent screen.
That screen states three things, and they are worth reading rather than clicking through:
- Which client is asking. The name is self-declared and unverified, and the screen says so. Any client can register; registering is not a trust decision.
- Which workspace it will reach. You choose it here, from the workspaces you belong to. The client does not get to ask for one — the workspace is never taken from the request.
- What it may do. Read, write, delete.
readis always included, because a connection that cannot read can neither answer a question nor find the document it was asked to change.
Approve, and the client is connected.
Connecting with a static token
Issue one for yourself, in a workspace you belong to:
pnpm --filter @md-platform/core issue-token you@example.com <workspaceId> "claude desktop"
A fourth argument narrows what it may do:
pnpm --filter @md-platform/core issue-token you@example.com <workspaceId> "research" read
Valid scopes are read, write, and delete, comma or space separated. Omit
the argument and the token gets all three. There is no way to widen a token
afterwards — issue a new one and revoke the old.
The token is printed once and stored only as a hash. For the stdio transport it
goes in MCP_TOKEN; stdio has no headers to carry a credential, so it comes
from the environment the client launches the process with.
The ten tools
A connected client gets these, and only these:
| Tool | Scope | What it does |
|---|---|---|
list_documents |
read | Every document, paths and titles, without bodies |
search_documents |
read | Matching excerpts, optionally within one folder |
get_document |
read | One document in full, with its version |
create_document |
write | A new document, optionally in a folder |
update_document |
write | Replaces a body, refused if the version is stale |
move_document |
write | Changes folder or name, keeping identity |
delete_document |
delete | Removes a document; the content stays in git history |
list_assets |
read | Uploaded files, with size and type |
get_asset |
read | One uploaded file |
delete_asset |
delete | Removes an upload, and the bytes with it |
A client is only given the tools its grant covers. A read-only connection
does not see create_document and get refused — it never sees it at all, which
is a far better instruction to a model than an error after the fact.
What a connection can and cannot reach
- One workspace. Chosen when you connected it, and not changeable by the client. There is no tool argument that widens the scope, and no tool that returns documents from two workspaces.
- As you. Every credential belongs to a person and acts as that person. When you lose access to a workspace, every client you connected to it stops working on the next request — not when its token expires.
- Nothing outside it. A document in another workspace is reported as not found, never as forbidden. A "forbidden" would confirm the identifier exists somewhere.
Reviewing and revoking
Settings → Connected applications lists what is connected, which workspace each one reaches, what it was allowed to do, and when it was last used. Revoking takes effect on the client's next request.
The same from a terminal, for when the browser is not the tool you have:
pnpm --filter @md-platform/core connections you@example.com
pnpm --filter @md-platform/core connections you@example.com <grantId>
Scopes cannot be widened here. Giving a client more requires going through consent again, and there is no path that does it quietly.
What "done" looks like
Ask the client to search the workspace for a word you know is in a document. It comes back with the path, the title, and an excerpt with the match marked. If it comes back with nothing, check that it is pointed at the workspace you think it is — the connection reaches one, and the consent screen said which.