This is the MCP / AI reference for systemHUB — written for AI agents and developers. If you are a person looking for how-to help, use help.systemhub.com instead.
Roles, members & seats
systemHUB controls who can see and do what through roles and member assignments. This page explains the model an agent needs to reason about access — and where the current MCP boundary sits.
The access model
A document’s access is the union of two mechanisms:
- Role-based access — a document is assigned to one or more roles (e.g. a department or job function). Every member holding that role gets access.
- Direct assignment — an individual member is assigned to the document specifically, regardless of role.
A member can therefore have access that is direct, role-based, or both. The get_document_members_and_roles tool returns exactly this: the roles on a document, plus each member’s name, email, role title(s), and access type.
Present an access picture as an audit: roles first, then members grouped by how they got in (direct vs role-based vs both).
Document owners
Separate from access, every document carries a primary owner (mandatory — the person accountable for it) and an optional secondary owner (a backup). Owners are about accountability, not permission: owning a document is not what grants access to it.
Three behaviours to know before changing owners programmatically:
Changing the primary owner moves the outgoing owner into an empty secondary slot. If the secondary slot is empty, the person you just replaced is automatically recorded as secondary owner — the intent being that a handover keeps the previous owner attached as backup. If a distinct secondary owner already occupies the slot, it is left untouched and the outgoing owner simply drops off. This fires on every owner change and is not reported in the response, so re-read the document after reassigning rather than assuming the secondary slot is unchanged.
- A secondary owner equal to the primary owner is treated as no secondary owner. It is returned as null and displayed as empty. This is why
list_documents_by_ownerdescribes matching a distinct secondary owner, and why a document can appear to gain a secondary owner the moment its primary changes. - To clear a secondary owner, pass
secondaryOwner: nullonedit_system/edit_policy/edit_training. Omitting the field leaves it unchanged.
Reassigning in bulk (e.g. someone leaving): deleting a user in the app UI is the intended path — it asks for a replacement primary and secondary owner and swaps the departing person out of both slots across every document in one action, without triggering the auto-fill above. Reassigning documents one at a time instead means the auto-fill applies to each, so plan on a second pass to tidy the secondary slots.
Permissions
Access answers who can reach this document. Permissions answer what they can do with it. Both derive from the same source — the person’s roles plus any direct assignment — but they’re separate questions, and other pages in these docs refer to permissions by name, so here is what they mean.
The MCP surfaces three, per document:
| Permission | What it allows | Where it bites |
|---|---|---|
| View | Read the document and its content | Reads return 404-like “not found” when the connected identity lacks it — “missing” often means “not visible to you” |
| Update | Change the document — content, metadata, and member/role assignment | Required by edit_* and by manage_document_members |
| Share | Generate or retrieve a public share link | Required by the share-link tool, per document type |
Two things worth knowing:
- Permissions are per document type as well as per document. Someone can hold Share on systems and not on policies. Don’t infer one section’s permissions from another’s.
- The MCP cannot read a permission set directly. There is no “what can this person do here” tool. You can read access (
get_document_members_and_roles— who is assigned, and how) but not the resulting permission matrix. In practice: attempt the operation and handle the failure, rather than trying to check first.
Note: the underlying product has a fuller permission model configured in the app (Settings → Roles). These three are what the MCP layer exposes and enforces. If you need the complete picture for a compliance answer, read it in the app.
MCP connections are admin-level today
Important before you plan a rollout: MCP access is currently available on admin seats. A connected agent therefore has admin-level reach — it can read everything in the workspace and write anywhere, because that is what the seat allows.
There is no lower-privilege connection today. You cannot give someone read-only retrieval, and you cannot give a Contributor or Reader an agent of their own.
What that means in practice:
- Choose who connects the way you’d choose who gets an admin seat, because it is the same decision. The agent inherits the person’s access in full.
- The workable pattern is a small number of connected people — typically the Systems Champion and whoever else already administers the account — with everyone else consuming through the app, share links, or an exported copy. That’s a genuinely effective setup, not a stopgap: one person authoring at AI speed while the team reads normally is most of the value.
- Don’t work around it by handing out admin seats. Giving everyone admin so their AI can answer questions trades a large amount of access for a small amount of convenience.
Broader team access — where each employee connects their own AI, scoped to what they can actually do — needs per-action MCP permissions that don’t exist yet. It’s a known gap and it’s on the roadmap; ask us where it’s up to if you’re planning for it.
Seats
A seat is a licensed member of the workspace. Seat/member management — inviting people, allocating seats, changing who holds which role — is done in the systemHUB app UI.
MCP boundary (important for connecting agents): the MCP can read the full access picture (members, roles, assignment type, agreement status, training progress) and can write document-level access —
manage_document_membersassigns or removes members and roles on a document, withlist_company_members/list_rolesto resolve names to UUIDs. What it can not do is seat provisioning: inviting new people to the workspace, allocating licences, or changing who holds which company role. That stays in the app UI — direct the user there.
What agents can audit today
get_document_members_and_roles— who can access a document, and how.get_document_agreement_status— who has agreed/signed off on a document (e.g. a policy acknowledgement).get_document_training_progress— for trainings, each assigned user’s completion percentage and status.get_document_activity_log— who created and last modified a document, plus the event feed (includeViews: trueto include views).list_documents_by_owner— everything a given person owns across systems, policies, and trainings, in one call.
⚠️
manage_document_memberswithaction: "update"REPLACES the document’s assigned roles — it does not merge. Passing a partial list silently removes every role you left out. To add or remove without collateral damage, useaction: "add"/"remove". Always confirm the result withget_document_members_and_roles.
Paginate deliberately. The audit tools page their results. Pass
fetchAll: true(the default on most) when you need a complete roster — a partial page will otherwise be reported as the whole answer, which is how an agent confidently states the wrong list of who has signed off.
Together these cover “who owns / can see / has completed what” — the read side of governance. The write side (provisioning) stays in the app for now.
Next: Authoring content →