# Govern SharePoint in Claude with delegated OAuth

> How to keep SharePoint in Claude inside each person's own site and library permissions, using per-person OAuth and one allow rule per role.

**TL;DR** SharePoint permissions hold in Claude only when every call is delegated, so each person signs in with their own Microsoft account rather than sharing one app identity. In Elaichi, that means a template shared with the team at use and stamped by each member, plus an allow rule naming the read tools and the Microsoft Search tool. Elaichi's SharePoint connector carries 97 tools, about 48 of which write or act, so a block list is the wrong instrument.

## Why SharePoint in Claude needs per-person OAuth

SharePoint in Claude stays inside each person's own permissions only when every call is delegated. That means each person signs in with their own Microsoft account. The app never acts beyond what that account can already see. Microsoft states the rule for delegated permissions directly: "the application can't access anything the signed-in user couldn't access" ([learn.microsoft.com](https://learn.microsoft.com/en-us/graph/permissions-overview), checked October 2026). Site permissions, library permissions and item-level restrictions then do the work they already do. The MCP layer adds no new access; it inherits what Entra and SharePoint already enforce.

Elaichi's SharePoint connector accepts two connection modes:

| Mode | Identity on each call | Who it exposes |
|---|---|---|
| OAuth (delegated) | The signed-in person's Microsoft account | Only what that person can already open |
| OAuth client credentials (app-only) | A single app identity | Whatever the app was granted, to everyone using that connection |

A client-credentials connection signs in as one app identity. Everyone who reuses that connection reaches whatever the app was granted. That is not what they personally can open in a browser. For keeping SharePoint permissions, that is the wrong shape.

Graph permissions come in two forms, and the distinction decides whether an admin has to approve anything. Delegated `Sites.Read.All` and `Files.Read.All` need no admin consent; their application (app-only) equivalents do ([learn.microsoft.com](https://learn.microsoft.com/en-us/graph/permissions-reference), checked October 2026). In delegated mode, Graph intersects the app's granted scopes with the signed-in user's actual permissions. The app's scope is a ceiling, and the user's access is the real limit. The lower of the two always wins.

## Share a template, not a connection

The per-person shape in Elaichi is a template shared at `use`, never a shared connection. A template holds a tool list with overrides, defaults and frozen arguments, and never holds a connection itself. This is the mechanism that keeps one shared setup from collapsing into one shared identity.

Build a template from the SharePoint connector and share it with the team at `use`. Each member then stamps their own toolbox from it. Stamping binds every entry to the stamper's own connection, so each person's calls run on the Microsoft account they signed in with. An entry with no usable connection is left as "needs connection" until that person connects, so it fails visibly, not silently.

A shared *connection* works the opposite way. It runs on its owner's credential, so every call reaches SharePoint as the owner, regardless of who triggers it. A toolbox shared at `use` has the same effect, because every entry in it is pinned to the connection its owner chose at creation time. For permission parity across a team, the template is the only one of the two that preserves per-person boundaries. A shared connection or a shared toolbox both re-create the app-only problem, just with a human owner instead of a service principal. The same fork appears in [drawing the folder line in Google Drive](/blog/claude-google-drive-sharing-permissions/), where a dedicated account is sometimes the better of the two shapes.

## What Elaichi's SharePoint connector carries

Elaichi's `sharepoint` connector carries 97 tools. 49 have names starting `list_` or `get_`, and they read. Most of the other 48 create, update, publish, upload or delete pages, lists, list items and files, and five change who can see what.

Elaichi authors and serves this connector from its own infrastructure, alongside the rest of the 600+ connectors. So no third-party MCP server sits in the call path between Claude and Microsoft Graph. MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps.

Two tools behave differently from the rest:

- `list_all_sharepoint_search` runs Microsoft Search under the hood and is classified `other`, not `read`. A rule written to match "all read tools" will not catch it by accident, and a rule meant to allow it must name it explicitly.
- `list_all_sharepoint_get_all_sites` requires an app-only token. On a delegated connection it returns HTTP 403. That 403 is the expected result of per-person auth working correctly, not a connector fault. If you see it on a delegated setup, the setup is doing what it is supposed to.

The full tool list is on the [SharePoint connector page](/connectors/sharepoint/).

## Writing the allow rule for a reading role

Hold a reading role with an allow rule that names the read tools it needs plus `list_all_sharepoint_search` explicitly, since it is not classified `read`. A block list fails open on a connector this size. Of 97 tools, roughly 48 write or act. Every one you forget to name in a block list stays reachable. The same arithmetic plays out on [Intune's 198 tools, where six blocks are not enough](/blog/it-team-claude-intune-devices/). An allow list fails closed instead, so anything not named is denied. That is the direction you want on a document store. The cost of one missed write tool is a deleted or overwritten file.

For a reading role, name tools such as `list_all_sharepoint_sites`, `get_single_sharepoint_site_by_id`, `list_all_sharepoint_drives`, `list_all_sharepoint_drive_items`, `get_single_sharepoint_drive_item_by_id`, `list_all_sharepoint_lists`, `list_all_sharepoint_list_items` and `list_all_sharepoint_search`.

One property of restrictions catches people out: an allow rule is the target's *entire* allowlist across every connector, not only the app it names. Once a role holds one allow rule, every connector that rule does not mention is denied for that role. That includes connectors that had no restrictions before. A support role reading SharePoint and working in Jira needs the SharePoint allow rule *plus* a separate allow rule naming Jira whole. It cannot rely on Jira being unrestricted by omission once any allow rule exists on that role. Allow rules targeting the same role union together, so one rule per connector is the normal way to compose this, not one giant rule.

In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. A block rule matches the advertised tool name or the pinned operation it maps to. An allow rule matches the pinned operation only. The mechanics are covered in [why blocks match names and allows do not](/blog/block-matches-name-allow-matches-operation/). A restriction change takes effect within about two minutes.

## The five tools that change who can see what

Five tools in the SharePoint connector edit SharePoint's own sharing model rather than its content:

| Tool | Effect |
|---|---|
| `create_a_sharepoint_site_permission` | Grants a role on a site |
| `create_a_sharepoint_list_item_permission` | Grants access to one list item |
| `update_a_sharepoint_drive_item_permission_by_id` | Changes an existing drive-item grant |
| `delete_a_sharepoint_drive_item_permission_by_id` | Revokes a drive-item grant |
| `sharepoint_drive_item_invite_send` | Sends a sharing invitation, which can reach an external address where the tenant allows external sharing |

These are the tools that can quietly widen the permission model everything else in this post assumes is stable. An invitation sent to the wrong address opens that item to someone outside the team until someone notices and revokes it. A reading role keeps all five out simply by never naming them in its allow rule. There is nothing to block, because anything the allowlist does not name is already denied.

A withheld tool is invisible, not merely disabled. It is absent from `tools/list` and absent from the search index. Its name never goes on the wire to the model. To the model it looks exactly like a tool the connector never had.

## Does Sites.Selected limit SharePoint to chosen sites?

Sites.Selected is Microsoft's mechanism for holding an application to sites it has been granted explicitly, rather than tenant-wide. An app consented for a Selected scope has zero access at first. Access starts once it is granted a role on a specific site through `POST /sites/{siteId}/permissions`. The role is set to read, write, owner or fullcontrol. Creating that grant itself requires `Sites.FullControl.All`, and in a delegated flow requires a caller with SharePoint Administrator role or higher ([learn.microsoft.com](https://learn.microsoft.com/en-us/graph/permissions-selected-overview), checked October 2026).

Do not assume every third-party connector draws the site line this way. Sites.Selected is one specific Graph mechanism, and a connector can be delegated (per-user) without also being Selected (per-site). In Elaichi, the site line is drawn by the Microsoft account each person signs in with and by the restriction on their role. Elaichi's console does not show which Graph scopes its SharePoint connector requests, so do not assume it uses Sites.Selected.

For comparison, two other Microsoft-adjacent AI products sit at different points on this same spectrum:

| Product | Access model | Site-level scoping |
|---|---|---|
| Elaichi SharePoint connector | Delegated OAuth (default), app-only optional | Through the signed-in account and role restrictions |
| Claude's native Microsoft 365 connector | Delegated, `Sites.Read.All` | None; tenant-wide search, limited to the user's own permissions |
| Microsoft Copilot | Delegated, per Microsoft 365 permission model | None by default; Restricted Content Discovery can hide a site from Copilot and search without changing its ACLs |

Claude's own Microsoft 365 connector does not support Sites.Selected. Its SharePoint search runs tenant-wide under `Sites.Read.All`, limited to each user's own permissions ([support.claude.com](https://support.claude.com/en/articles/12684923-microsoft-365-connector-security-guide), checked October 2026). Microsoft Copilot sits in a comparable place. It "only surfaces organizational data to which individual users have at least view permissions" ([learn.microsoft.com](https://learn.microsoft.com/en-us/microsoft-365/copilot/microsoft-365-copilot-privacy), checked October 2026). Restricted Content Discovery can hide a site from organization-wide search and Copilot without changing its underlying permissions ([learn.microsoft.com](https://learn.microsoft.com/en-us/sharepoint/restricted-content-discovery), checked October 2026). Whether Restricted Content Discovery also suppresses a site from third-party Graph-based search, including Elaichi's, is not documented by Microsoft. Do not plan a security boundary around it.

## When Claude's own Microsoft 365 connector is the better choice

If SharePoint is the only system your team needs inside Claude, and read access is all that is required, the answer is simpler. Anthropic's native Microsoft 365 connector is genuinely less machinery to operate. It is available on all Claude plans and takes a one-time Entra Global Administrator consent. On Team and Enterprise plans an Owner can also enable it. It is read-only by default; enabling SharePoint writes requires turning on write tools plus granting `Files.ReadWrite.All` ([support.claude.com](https://support.claude.com/en/articles/12542951-set-up-the-microsoft-365-connector), checked October 2026). For a single-app pilot with one connector and no cross-tool audit requirement, that is usually the right answer and adds no operational layer worth maintaining.

The trade-off shifts once a role needs more than one system, for example SharePoint plus Jira, Zendesk or Salesforce. The alternative is writing and maintaining access rules separately in each vendor's own console, instead of once per role in a single control plane. It shifts again where a single audit trail needs to cover all the tools a given actor touched, not just one connector's logs. Whether that trade-off is worth the added layer depends on how many connectors a role actually spans, and on how centralized the audit requirement is. It is not automatically the right call for every team.

## Adding the endpoint and what each person consents to

The address is `https://api.elaichi.ai/mcp` for every organization: one URL, not one per team. In Claude Team or Enterprise, an Owner adds it under Organization settings, Connectors, Add, Custom, Web. Members then connect it individually under Customize, Connectors ([support.claude.com](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp), checked October 2026). The same URL also serves ChatGPT, Cursor, any MCP-compatible client, and the Elaichi Agent.

Each person signs in on Elaichi's own consent screen, picks one organization, and ticks what the client may do. Delete is never pre-ticked by default. With "Run your connected tools" ticked, a second step asks whether to grant all tools or only chosen toolboxes. The consent request itself lasts 30 minutes before expiring. That is long enough to stamp a template in a second tab. It does need to happen in one sitting.

One mechanical detail trips people up. For a connected app's tools, the general tools checkbox covers reads *and* writes together. Only a delete action costs a separate destructive-action scope. Leaving "Create and change data" unticked does not make SharePoint read-only by itself. Read-only access is enforced by the allow rule on the role, not by this checkbox. That is covered in [restricting one tool or a whole app](/blog/per-tool-vs-per-app-restrictions/).

## What the audit trail records, and what leaving ends

Elaichi writes one entry per tool-call attempt, succeeded or failed. The raw error text Microsoft returns to the caller is never copied into the audit record itself. That keeps third-party response payloads out of the audit log pipeline. The entry records that a call failed and which tool and operation it was, not the verbatim upstream error body.

The entry records the surface as `mcp` and names the OAuth client that made the call. Claude is among the clients whose identity is marked verified by its registered redirect URIs. A call made through an MCP client is logged with an actor kind of `user`. The grant backing the call belongs to that person, not to the client application.

When someone leaves the organization, removing or suspending them in Elaichi is what ends their access through Elaichi. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change. Offboarding runs a preflight first. It lists every connection the departing member owns, private and shared alike. Each one is either transferred to another active member or deleted. It is never silently transferred to the admin running the removal, which would otherwise let one admin accumulate other people's connections during offboarding. The full sequence is set out in [offboarding when the agent holds the access](/blog/offboarding-when-the-agent-holds-access/). Removal ends access through Elaichi specifically; the person's underlying Microsoft account still exists and must be deprovisioned separately in Entra or through your identity provider. These are two different revocation events and neither one substitutes for the other.

For the wider model, see [what an MCP control plane is](/blog/what-is-an-mcp-control-plane/).

## FAQ

### Can Claude see SharePoint files a person cannot open?

Not when the connection is delegated. With per-person OAuth, every Microsoft Graph call runs as the signed-in user, and Microsoft states that an application with delegated permissions cannot access anything the signed-in user could not access ([learn.microsoft.com](https://learn.microsoft.com/en-us/graph/permissions-overview), checked October 2026). The risk comes from client-credentials connections, which sign in as one app identity for everyone who uses them, and from sharing a connection or a toolbox in Elaichi rather than a template.

### Does unticking "Create and change data" on Elaichi's consent screen make SharePoint read-only?

No. For a connected app's tools, the "Run your connected tools" scope covers reads and writes alike, and only a tool whose method is a delete needs the destructive scope on top. The "Create and change data" box governs Elaichi's own control-plane operations. Read-only access to SharePoint is a restriction: an allow rule naming the read tools the role needs, plus allow rules naming its other apps whole.

### What is Sites.Selected, and does it apply to an AI connector?

Sites.Selected is a Microsoft Graph scope that gives an application no SharePoint access until it is granted a role on a specific site through POST /sites/{siteId}/permissions, with read, write, owner or fullcontrol. Creating that grant needs Sites.FullControl.All and, in a delegated flow, a SharePoint Administrator ([learn.microsoft.com](https://learn.microsoft.com/en-us/graph/permissions-selected-overview), checked October 2026). Claude's own Microsoft 365 connector does not support it ([support.claude.com](https://support.claude.com/en/articles/12684923-microsoft-365-connector-security-guide), checked October 2026), so check the vendor's own page before assuming any connector draws a site line that way.

### How long does a SharePoint restriction take to apply in Elaichi?

Within about two minutes. The change applies on the MCP endpoint, in the console and over the REST API alike. Removal is faster. In Elaichi, removing or suspending a member revokes every live grant in the same transaction as the membership change.

### Why use an allow rule instead of blocking the SharePoint write tools?

Elaichi's SharePoint connector carries 97 tools, about 48 of which write or act, so a block list leaves every write it fails to name reachable. An allow rule fails closed: anything it does not name is denied for that role. The trade-off is that an allow rule is the role's whole allowlist across every connector, so the role also needs allow rules naming the other apps it uses.

## Read next

- [Scope Google Drive in Claude to people or folders](/blog/claude-google-drive-sharing-permissions/) — Google Drive in Claude has two honest shapes: each person connects their own Google account, or one dedicated account whose shared folders draw the line.
- [Space permissions for Confluence in ChatGPT](/blog/chatgpt-confluence-space-permissions/) — ChatGPT ships no Confluence connector, so Confluence in ChatGPT runs over MCP. Here is the route that keeps each person inside their space permissions.
- [Intune in Claude for help desk lookups only](/blog/it-team-claude-intune-devices/) — Intune in Claude for a help desk is one allow rule, not six blocks: the msintune connector carries 198 tools and only 69 of them read.
