Short answer
One that resolves permissions per person, not per installation. Most note MCP servers use a single API key and a folder allowlist, so every caller acts as the vault. For a team, the server has to identify the caller and re-check what that user may read on each tool call, against the same ACL the app uses.
Every round-up of MCP servers for notes ranks the same things: where the data sits, how hard the setup is, whether search is semantic. Those are fine questions for one person with one vault. The moment the notes belong to a team, a different question decides everything, and none of the round-ups ask it. When the assistant calls read_note, who is it acting as?
Most note MCP servers have no answer. They authenticate with one key and reach one folder, so there is no "who" in the request at all. That is workable on your own laptop and it is the wrong shape for a shared vault, because a team's notes are not uniformly readable by everyone in the team.
What does an MCP server for team notes actually need?
Three things, in this order.
- An identity per person, not per installation. The server has to know that this call came from Priya and not from "the vault".
- Permissions resolved on the call, not declared in a config. What Priya can reach changes when someone shares a folder with her or revokes it. A config file written in March cannot know that.
- The same answer as the app. If Priya cannot open a note in the UI, her assistant should not be able to read it either. Two doors onto the same data with different locks is not a permission system.
The directories do not sort servers this way, so it is worth going through what the popular ones actually do.
Why a path allowlist is not a permission
The most-recommended self-hosted option is the Obsidian MCP server, and it is a good piece of software. It talks to Obsidian's Local REST API with a single bearer token, OBSIDIAN_API_KEY, and it does offer scoping: OBSIDIAN_READ_PATHS=projects/,scratch/ limits reads by folder prefix, OBSIDIAN_WRITE_PATHS=public/inbox/ limits writes, and OBSIDIAN_READ_ONLY=true turns writes off entirely. Matching is by prefix, recursive and case-insensitive.
That is a scope. It is not an identity. The distinction matters because the allowlist is a property of the server process, so everyone pointed at that process gets the same one. The project's own documentation is direct about it when you expose the server over HTTP: unless you set MCP_AUTH_MODE to jwt or oauth, with the default none "every caller acts on your vault".
So a team sharing one of these shares one permission set. You can run a separate server per person with a different allowlist each, which works and which nobody does for long, because now the permissions live in however many .env files there are people, and nothing keeps them in step with who actually has access to what.
Notion's MCP is the honest counter-example and deserves the credit. It authorises over OAuth, and Notion's documentation says the client can "read and update content that you can access". Permissions come from the person who authorised, which is exactly right. The cost is the one Notion always charges: the content is in Notion's database, not in files you hold, and the Baalda and Notion comparison goes through what that means.
How Baalda answers it
Baalda is a team second brain built on plain markdown files on your own disk, with real-time multi-user editing, per-file permissions, open source under Apache-2.0 and self-hostable. It serves MCP at POST /api/mcp over Streamable HTTP, as one route on the server the team already runs rather than a process on anyone's laptop.
The connection carries a person. A token is minted in Vault Settings → MCP and is scoped to one user within one vault. It is stored as sha256(token) only, so the plaintext is shown once at creation and a database leak cannot reveal a live token. Every request re-checks that the user is still a member of the vault, which means membership revoked after the token was minted kills that token on its next call rather than whenever someone remembers to go and delete it.
Authorization: Bearer mcp_your_token_hereThen the part that does the work. All 22 tools are gated by the same ACL the rest of the app uses, src/permissions/resolver.ts, resolved per call. Read operations need view, writes need edit, and creating or deleting inside a folder needs edit on the parent. The useful consequence shows up in list_notes: each note is resolved through effectivePermission for the calling user, and anything coming back none is skipped rather than returned with an error. A note nobody shared with Priya does not appear to Priya's assistant as a locked door. It does not appear.
That is the difference between a scope and an identity. Ask two teammates' assistants to list the same folder and they get different lists, with no second configuration anywhere describing what those lists should be.
Where this does not help
Four limits worth knowing before you decide.
- It does not sandbox the other servers in the client. Every MCP server configured in one client shares the model's context, so a poisoned third-party server can steer the agent into misusing Baalda's write tools. The team's vault is the one MCP server that should not run on a laptop covers that in full.
- An admin's token reaches what an admin reaches, which is everything. Owners and admins get
editeverywhere, and the access-management tools (manage_access,set_access_default) are available to them over MCP too. If you want an agent that cannot read the whole vault, mint its token as a member with specific shares, not as yourself. - Permissions you never set do not protect anything. The resolver is only as good as the shares behind it. A vault where everything was left at the default is one permission set wearing a fancier mechanism.
- There is no importer. Moving an existing wiki in is a conversion job, the same as it would be anywhere else.
Does the AI get its own account, or borrow a person's?
It borrows a person's, and that is a deliberate choice rather than a missing feature. A token authenticates as one user within one vault, so "what can this agent reach" has exactly one answer: whatever that person can reach. There is no second permission model to keep in sync, and the audit question stays answerable, because Vault Settings → MCP lists each connection with the client name read off its User-Agent, a call count bumped per tools/call, last-active, and Revoke.
The trade is that an agent cannot be given access a human does not have, and cannot be given a narrower slice than some human has. If you want the narrow slice, you make a member account with that slice and mint the token there. More setup than a path allowlist, and it has the property the allowlist never had, which is that it stays true when the team changes.
If you are connecting an assistant to your own notes rather than a team's, a second brain over MCP is the simpler version of this, and the single-key servers above are genuinely fine. The identity question only starts to bite when the second person arrives. It is the same boundary per-file permissions run into on the human side, and for the same reason: something in the path has to be able to say no, and a file sitting in a folder cannot.
