DEV Community

Boitumelo Phetla
Boitumelo Phetla

Posted on Originally published at andika.work AI-assisted

Designing a read-only MCP server first: least privilege for AI context

Your data is yours

Giving an AI application access to your users' knowledge is a trust decision before it's an engineering decision.

At Andika we recently shipped our first Model Context Protocol (MCP) connection, and we made a choice that shaped the whole design: the first release is read-only. Here's the reasoning, and the specific controls that fell out of it.

What MCP gives you, in one paragraph

MCP is a standard interface between applications and LLM clients on one side, and systems that hold context and tools on the other. Depending on what the server exposes, a connected client can read resources, call tools, and take actions. Instead of copy-pasting documents into a chat window, a user can connect a tool to their workspace and let it work with their documents through a governed channel.

The power is obvious. So is the risk: you've just built a machine-consumable pipe into people's private knowledge.

Why read-only first

The protocol supports far more than reading, and that's exactly why we started with less. Write access is where the irreversible mistakes live. A connected application that can edit, publish, delete, or invite members can do real damage with a single bad call, and "the model did it" is not an acceptable incident report.

So our first MCP release draws the line firmly: connected applications can discover workspaces, search documents, read pages, examine revisions, and retrieve asset knowledge. They cannot edit, publish, delete, invite members, or change permissions. That's a scoping decision we made for this release, not a limitation of MCP itself. Expanding the boundary later is a deliberate project, not a toggle.

The controls that made it shippable

  • Named, expiring, revocable tokens. A user creates a connection token for a specific application, with a name they'll recognise later ("my research assistant") and an expiry. The raw token is shown once and stored as a hash, the same discipline as API keys and passwords.
  • The connection acts as the user who created it. Not as the platform, not as a superuser. It inherits exactly that user's permissions: organisation boundaries, workspace membership, group access, page and asset restrictions, deleted content, account status. If the user can't see it, the connection can't see it. Notably, even a platform administrator doesn't automatically get access to another organisation's private workspace, and the connection respects that too.
  • A dedicated audit trail. Every MCP operation is recorded. Sensitive search text is hashed rather than copied into audit records, because an audit log that leaks the very queries it protects is a liability wearing a costume.
  • Revocation is a first-class feature. The moment a connection feels wrong, the user kills it, and it dies completely.

What this means for ML tooling

The interesting engineering question in LLM tooling right now isn't "how do we give the model more context?" It's "how do we give it the right context, under governance the user can actually reason about?"

A read-only, permission-inheriting, audited context channel is a foundation you can build on. When we do open write capabilities, the plan is granular scopes, explicit confirmation for consequential actions, optimistic revision checks so a stale client can't silently overwrite newer work, and a complete OAuth authorization flow.

The broader lesson applies beyond MCP: treat every integration that touches user knowledge as a privilege negotiation, not a feature flag. Start with the smallest capability that delivers value, instrument it, and earn the right to expand.


This post was adapted, with AI assistance, from an article on the Andika blog, where we build a collaborative writing and knowledge platform.

Top comments (0)