> ## Documentation Index
> Fetch the complete documentation index at: https://docs.consile.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# API reference: SharePoint

> The 17 read-only tools in the SharePoint connector: site discovery, document libraries and OneDrive, file metadata, full-text search, file download, recent and shared files, version history, and SharePoint lists. Covers site, drive and item addressing, cursor paging, the download cap and the error contract.

All SharePoint tools are read-only and are called via `tools/call` over
`POST /sharepoint/mcp`. The connector reads Microsoft SharePoint Online and OneDrive
for work or school through Microsoft Graph, and is connected through OAuth with a
Microsoft work or school account (see
[Connect SharePoint](https://docs.consile.ai/en/connect/connect-sharepoint.md)). Your organization needs access
to SharePoint (a subscription, or a plan that covers it, see
[What decides access](https://docs.consile.ai/developers/authentication.md#what-decides-access)), and your user
must hold a seat or plan licence (assigned under **Team** in the portal, see
[Team](https://docs.consile.ai/en/portal/team.md)).

> [!NOTE]
>
> Endpoint: `https://mcp.consile.ai/sharepoint/mcp`. SharePoint is its own named
> connector with only its own tools. Tool names are namespaced `sharepoint__<tool>`
> (e.g. `sharepoint__search_drive_items`); the bare names are used below for
> readability. A bare name in a request returns `Unknown tool.`
>
> The connector is multi-instance: one instance covers one Microsoft 365
> organization (one Microsoft Entra tenant). An administrator adds further
> connections (agreements, **aftaler**, in the portal), each served at its own
> endpoint, e.g. `https://mcp.consile.ai/sharepoint-2/mcp`, with tools named
> `sharepoint-2__<tool>`.

For an account with access to SharePoint, `tools/list` returns the 17
`sharepoint__*` tools plus the unprefixed system tool
[`connect_account`](#connect_account). Without access only `connect_account` is
listed, and the `initialize` result includes `instructions` explaining how to get
access. A user without a seat still sees the tools, but every call is refused. Every
tool has a `title` and the annotations `readOnlyHint: true`,
`destructiveHint: false` and `openWorldHint: false`. A successful result contains
the payload twice: as JSON text in `content` and as the same object in
`structuredContent`. The examples below show that payload.

## Authorization and read-only enforcement

The account is connected through Microsoft's OAuth sign-in. Only work or school
accounts can connect; Microsoft refuses a personal Microsoft account. The requested
delegated permissions are:

* `https://graph.microsoft.com/Sites.Read.All`
* `https://graph.microsoft.com/Files.Read.All`
* `offline_access` (keeps the connection alive)

Both Graph permissions are read-only, so a token issued on this consent cannot
write, even outside Consile. In addition:

* The connector has no write tools.
* Consile sends only read requests to Microsoft Graph.
* The connect is rejected if Microsoft's grant lacks one of the two permissions, or
  contains permissions for any resource other than Microsoft Graph.

Many Microsoft 365 organizations require an administrator to consent to these
permissions before a user can connect. See
[Connect SharePoint](https://docs.consile.ai/en/connect/connect-sharepoint.md#if-microsoft-asks-for-administrator-approval).

Access is renewed automatically. Consile never hands the token to the MCP client,
and the MCP client's own token is never forwarded to Microsoft. File content is
passed through to the client and not stored by Consile.

### Whose data the tools read

The connection belongs to the organization, not to each Consile user. Every call on
an instance runs as the one Microsoft user who connected it, with that user's
SharePoint and OneDrive permissions. "Own OneDrive" (`get_my_drive`, and every drive
tool called without `driveId`), `list_recent_files`, `list_shared_with_me` and
`list_followed_sites` all refer to that connected user, whichever Consile user makes
the call.

## Shared conventions

### Sites, drives and items

Graph addresses SharePoint and OneDrive content by ids a user never sees:

* A **site** id, in the form `<host>,<guid>,<guid>`. Get it from
  [`search_sites`](#search_sites), [`list_followed_sites`](#list_followed_sites), or
  [`get_site`](#get_site) with the site's URL. `root` is accepted as the
  organization's root site.
* A **drive** id: one per document library. Get it from
  [`list_site_drives`](#list_site_drives). The connected user's own OneDrive needs no
  id.
* An **item** (a file or folder) inside a drive, named by id or by path.

The intended order for a document library is `search_sites` (or `get_site` from a
pasted URL), then `list_site_drives`, then the drive tools with the drive id in hand.

**siteId** `string`

Site id from `search_sites` or `get_site` (the `host,guid,guid` form), or `root`
for the organization's root site. At least one character.

**driveId** `string`

Drive (document library) id from `list_site_drives` or `get_my_drive`. Optional on
every drive tool. Omit it for the connected user's own OneDrive. Results echo it as
`"me"` when it was omitted.

**itemId** `string`

Item id of a file or folder, from a listing or a search.

**path** `string`

Path of a file or folder under the drive root, e.g.
`Shared Documents/Reports/Q3.xlsx`. Use instead of `itemId` when you know the path.
When both are given, `itemId` wins. A `..` segment is refused.

On `get_drive_item`, `download_file` and `list_item_versions`, one of `itemId` and
`path` is required. On `list_drive_items`, omitting both lists the drive's root
folder.

### Paging

Listing tools that page take these two arguments and return `nextCursor`:

**pageSize** `integer` (default: 50)

Rows per page, `1` to `500`.

**cursor** `string`

The `nextCursor` from a previous page of the same tool. When it is set, all other
options are ignored: the cursor continues the original query. Omit it for the first
page, and never construct or edit one. An invalid cursor is refused with
`Invalid cursor for SharePoint: pass the nextCursor from a previous page of the same tool`.

**nextCursor** `string | null`

Token for the next page, or `null` when the collection is exhausted. There is no
total count.

The paged tools are `search_sites`, `list_subsites`, `list_drive_items`,
`search_drive_items`, `list_recent_files`, `list_shared_with_me`, `list_site_lists`
and `list_list_items`. `list_followed_sites`, `list_site_drives` and
`list_item_versions` return a single response with `count` and `items`, without a
cursor.

### File and folder objects

The drive tools return files and folders in one shape:

**item** `object`

`id`, `name`, `kind` (`file`, `folder`, `package` or `unknown`), `mimeType`,
`size` (bytes), `webUrl`, `createdDateTime`, `lastModifiedDateTime`,
`lastModifiedBy` (display name), `driveId`, `parentId`, `parentPath` (the folder
path under the drive root, e.g. `/Reports`) and `childCount` (folders only). A
missing value is `null`.

### Site objects

**site** `object`

`id`, `name`, `displayName`, `webUrl`, `description`, `hostname`,
`createdDateTime` and `lastModifiedDateTime`. A missing value is `null`.

`@odata.*` annotation keys and Graph's short-lived download links are removed from
every result.

***

## search\_sites

Searches the SharePoint sites the connected user can reach, by name or keyword.
Without `search`, it lists every site the user can see. When several sites match,
ask the user which one is meant instead of guessing.

**search** `string`

Search text, at least one character.

**pageSize** `integer` (default: 50)

**cursor** `string`

**items** `array`

Site objects.

```json Request theme={null}
{
  "name": "sharepoint__search_sites",
  "arguments": { "search": "Marketing" }
}
```

```json Result (payload) theme={null}
{
  "count": 1,
  "items": [
    {
      "id": "<tenant>.sharepoint.com,3f2b6c1e-8a4d-4f0e-9b7a-1c2d3e4f5a6b,9d4e2a10-5b7c-4e3f-8a21-6c0b1d2e3f40",
      "name": "Marketing",
      "displayName": "Marketing",
      "webUrl": "https://<tenant>.sharepoint.com/sites/Marketing",
      "description": null,
      "hostname": "<tenant>.sharepoint.com",
      "createdDateTime": "2024-03-11T09:12:44Z",
      "lastModifiedDateTime": "2026-10-28T14:03:10Z"
    }
  ],
  "nextCursor": null
}
```

***

## get\_site

Reads one site by id, or resolves it from its web URL when the user pasted a link.
Returns a site object, whose `id` every site-scoped tool takes. Pass `root` as
`siteId` for the organization's root site.

**siteId** `string`

**url** `string (URL)`

The site's web URL, e.g. `https://<tenant>.sharepoint.com/sites/Marketing`. Use
instead of `siteId` when you only have a link. Must be `https`.

One of `siteId` and `url` is required; with neither, the call is refused with
`get_site needs either siteId or url`. A URL that is not `https` is refused with
`A site URL must be https`.

```json Request theme={null}
{
  "name": "sharepoint__get_site",
  "arguments": { "url": "https://<tenant>.sharepoint.com/sites/Marketing" }
}
```

***

## list\_followed\_sites

Lists the sites the connected user follows: usually the handful of sites they work
in. A good first call when the user says "our intranet" or "the project site"
without naming it.

**Arguments:** none.

**items** `array`

Site objects.

***

## list\_subsites

Lists the subsites directly under a site.

**siteId** `string` *required*

**pageSize** `integer` (default: 50)

**cursor** `string`

**items** `array`

Site objects. The result also echoes `siteId`.

***

## list\_site\_drives

Lists the document libraries (drives) of a site, with the drive id the drive tools
take. Most sites have one library called Documents; a site can hold several.

**siteId** `string` *required*

**items** `array`

Each item has `id`, `name`, `driveType`, `webUrl`, `description`, `owner` (display
name), `quotaUsed`, `quotaTotal` (bytes) and `lastModifiedDateTime`. The result
also echoes `siteId`.

```json Request theme={null}
{
  "name": "sharepoint__list_site_drives",
  "arguments": { "siteId": "<siteId from search_sites>" }
}
```

```json Result (payload) theme={null}
{
  "siteId": "<siteId from search_sites>",
  "count": 1,
  "items": [
    {
      "id": "b!Xk3v0hVd2kGq8mW1n4yZ5cPq7rS9tUvW",
      "name": "Documents",
      "driveType": "documentLibrary",
      "webUrl": "https://<tenant>.sharepoint.com/sites/Marketing/Shared%20Documents",
      "description": null,
      "owner": "Marketing",
      "quotaUsed": 734003200,
      "quotaTotal": 27487790694400,
      "lastModifiedDateTime": "2026-10-28T14:03:10Z"
    }
  ]
}
```

***

## get\_my\_drive

Reads the connected user's own OneDrive: drive id, owner and storage quota. The drive
tools default to this drive when no `driveId` is given, so this is only needed to show
the quota or to confirm whose OneDrive is connected.

**Arguments:** none. Returns the same fields as one `list_site_drives` item.

***

## list\_drive\_items

Lists the files and folders in a folder of a drive, sorted by name. Omit `driveId`
for the connected user's OneDrive; omit both `itemId` and `path` for the drive's
root folder. Use [`download_file`](#download_file) to read a file's content.

**driveId** `string`

**itemId** `string`

**path** `string`

**pageSize** `integer` (default: 50)

**cursor** `string`

**items** `array`

File and folder objects. The result also echoes `driveId` and `folder` (the
`itemId` or `path` you passed, or `/`).

```json Request theme={null}
{
  "name": "sharepoint__list_drive_items",
  "arguments": { "driveId": "b!Xk3v0hVd2kGq8mW1n4yZ5cPq7rS9tUvW", "path": "Reports" }
}
```

```json Result (payload, shortened) theme={null}
{
  "driveId": "b!Xk3v0hVd2kGq8mW1n4yZ5cPq7rS9tUvW",
  "folder": "Reports",
  "count": 1,
  "items": [
    {
      "id": "01ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
      "name": "Q3.docx",
      "kind": "file",
      "mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      "size": 48213,
      "webUrl": "https://<tenant>.sharepoint.com/sites/Marketing/Shared%20Documents/Reports/Q3.docx",
      "createdDateTime": "2026-09-30T08:01:12Z",
      "lastModifiedDateTime": "2026-10-27T15:44:02Z",
      "lastModifiedBy": "<name>",
      "driveId": "b!Xk3v0hVd2kGq8mW1n4yZ5cPq7rS9tUvW",
      "parentId": "01ABCDEFGHIJKLMNOPQRSTUVWXYZ765432",
      "parentPath": "/Reports",
      "childCount": null
    }
  ],
  "nextCursor": null
}
```

***

## get\_drive\_item

Reads one file's or folder's metadata by id or path: name, size, MIME type, web link,
parent folder, created and modified dates and by whom. Returns one file or folder
object.

**driveId** `string`

**itemId** `string`

**path** `string`

***

## search\_drive\_items

Searches a drive for files and folders by name and content (full text across the
drive, including subfolders). Omit `driveId` to search the connected user's
OneDrive; pass a drive id from `list_site_drives` to search a document library.
Results carry the `id` and `driveId` that `get_drive_item` and `download_file` take.

**query** `string` *required*

Search text (file name or words in the content), at least one character.

**driveId** `string`

**pageSize** `integer` (default: 50)

**cursor** `string`

**items** `array`

File and folder objects. The result also echoes `driveId` and `query`.

```json Request theme={null}
{
  "name": "sharepoint__search_drive_items",
  "arguments": { "query": "onboarding", "driveId": "b!Xk3v0hVd2kGq8mW1n4yZ5cPq7rS9tUvW", "pageSize": 10 }
}
```

***

## download\_file

Reads a file's content by id or path.

**driveId** `string`

**itemId** `string`

**path** `string`

**encoding** `string`

`utf8` for text files, `base64` for everything else.

**content** `string`

The file content, as UTF-8 text or base64.

The result also has `id`, `name`, `mimeType` and `size` (bytes read).

* **Text files** come back as UTF-8 text: any `text/*` type, JSON, XML, YAML, CSV,
  RTF and JavaScript, and common text extensions such as `txt`, `md`, `csv`, `json`, `xml`,
  `html` and `log` when the MIME type is missing or generic.
* **Other files** (Word, PDF, images and so on) come back base64-encoded with their
  MIME type.
* **Size cap:** files above 5 MB (5,242,880 bytes) are refused with
  `The file is <size> bytes, above the 5242880-byte limit of download_file`. Use the
  metadata tools and ask the user for a smaller file. If the size is only discovered
  during the download, the call fails with `Tool invocation failed.`
* A folder is refused with
  `download_file was given a folder; use list_drive_items on it`.
* For Excel workbooks, the [Excel connector](https://docs.consile.ai/developers/tools/excel.md) reads sheets and
  tables as rows.

```json Request theme={null}
{
  "name": "sharepoint__download_file",
  "arguments": { "path": "Notes/meeting.md" }
}
```

```json Result (payload) theme={null}
{
  "id": "01ABCDEFGHIJKLMNOPQRSTUVWXYZ345678",
  "name": "meeting.md",
  "mimeType": "text/markdown",
  "size": 412,
  "encoding": "utf8",
  "content": "# Meeting notes\n\n- Agenda ..."
}
```

***

## list\_recent\_files

Lists the files the connected user recently opened or edited, across OneDrive and
the SharePoint sites they use.

**pageSize** `integer` (default: 50)

**cursor** `string`

**items** `array`

File and folder objects.

***

## list\_shared\_with\_me

Lists the files and folders other people have shared with the connected user. Each
item carries the `driveId` and `id` of the original item, which the other tools take.

**pageSize** `integer` (default: 50)

**cursor** `string`

**items** `array`

File and folder objects with an extra `sharedBy` (display name of the person who
shared it).

***

## list\_item\_versions

Lists the version history of a file.

**driveId** `string`

**itemId** `string`

**path** `string`

**items** `array`

Each item has `id` (the version id), `size`, `lastModifiedDateTime` and
`lastModifiedBy` (display name).

***

## list\_site\_lists

Lists the SharePoint lists of a site (tasks, contacts, issue logs, custom registers),
with the list id `get_list` and `list_list_items` take. Document libraries appear too
(template `documentLibrary`); use the drive tools for their files. Hidden system lists
are filtered out, and `count` is the number left after filtering.

**siteId** `string` *required*

**pageSize** `integer` (default: 50)

**cursor** `string`

**items** `array`

Each item has `id`, `name`, `displayName`, `description`, `webUrl`, `template`,
`hidden`, `createdDateTime` and `lastModifiedDateTime`. The result also echoes
`siteId`.

***

## get\_list

Reads one list with its columns. Call it before `list_list_items` to know which field
names to expect and to build a filter.

**siteId** `string` *required*

**listId** `string` *required*

List id from `list_site_lists`.

**columns** `array`

Each column has `name` (the internal name used in `fields` and filters),
`displayName`, `type` (`text`, `number`, `dateTime`, `choice`, `boolean`,
`lookup`, `personOrGroup`, `currency`, `hyperlinkOrPicture`, `calculated` or
`unknown`), `required`, `hidden`, `readOnly` and `choices` (for a choice column,
otherwise `null`). Hidden columns are left out.

The result also has the same list fields as a `list_site_lists` item.

```json Result (payload, shortened) theme={null}
{
  "id": "6c1e3f2b-4d8a-4f0e-9b7a-5a6b1c2d3e4f",
  "name": "Suppliers",
  "displayName": "Suppliers",
  "template": "genericList",
  "hidden": false,
  "columns": [
    { "name": "Title", "displayName": "Title", "type": "text", "required": true, "hidden": false, "readOnly": false, "choices": null },
    { "name": "Status", "displayName": "Status", "type": "choice", "required": false, "hidden": false, "readOnly": false, "choices": ["Active", "Awaiting contract", "Ended"] }
  ]
}
```

***

## list\_list\_items

Reads the rows of a list with their column values.

**siteId** `string` *required*

**listId** `string` *required*

**filter** `string`

OData `$filter` over the columns, written as `fields/<Column>`, e.g.
`fields/Status eq 'Awaiting contract'`. Use the column `name` from `get_list`.
On large lists, SharePoint may refuse a filter on a column that is not indexed;
then page through without a filter instead.

**fields** `string[]`

Column names to return. All columns when omitted.

**pageSize** `integer` (default: 50)

**cursor** `string`

**items** `array`

Each row has `id`, `webUrl`, `createdDateTime`, `lastModifiedDateTime`,
`lastModifiedBy` (display name) and `fields` (the column values, keyed by column
name). The result also echoes `siteId` and `listId`.

```json Request theme={null}
{
  "name": "sharepoint__list_list_items",
  "arguments": {
    "siteId": "<siteId>",
    "listId": "6c1e3f2b-4d8a-4f0e-9b7a-5a6b1c2d3e4f",
    "filter": "fields/Status eq 'Awaiting contract'",
    "fields": ["Title", "Status"]
  }
}
```

```json Result (payload) theme={null}
{
  "siteId": "<siteId>",
  "listId": "6c1e3f2b-4d8a-4f0e-9b7a-5a6b1c2d3e4f",
  "count": 1,
  "items": [
    {
      "id": "14",
      "webUrl": "https://<tenant>.sharepoint.com/sites/Procurement/Lists/Suppliers/14_.000",
      "createdDateTime": "2026-08-04T10:22:31Z",
      "lastModifiedDateTime": "2026-10-21T07:58:09Z",
      "lastModifiedBy": "<name>",
      "fields": { "Title": "<company name>", "Status": "Awaiting contract" }
    }
  ],
  "nextCursor": null
}
```

***

## get\_list\_item

Reads one row of a list with all its column values. Returns the same shape as one
`list_list_items` row.

**siteId** `string` *required*

**listId** `string` *required*

**itemId** `string` *required*

Row id from `list_list_items`.

***

## connect\_account

`connect_account` is a system tool that the SharePoint endpoint lists next to the 17
tools. It takes no arguments and its name has no `sharepoint__` prefix. It returns
`{ "connect_url": "…", "instructions": "…" }`. The user opens `connect_url` in a
browser and is sent to Microsoft to sign in and approve access. The link expires
after 10 minutes. It only works for accounts that subscribe to SharePoint and for
users who have accepted Consile's terms in the portal. Use it to reconnect after the
access expired or was removed: completing the link connects the account again with
the new Microsoft sign-in.

```json Request theme={null}
{ "name": "connect_account", "arguments": {} }
```

Replacing an existing connection requires a Consile administrator; for other users
the link is refused.

***

## Errors

Tool failures come back as a normal `tools/call` result with `isError: true` and one
text block, not as a JSON-RPC error. The connector returns explanatory messages for
the common failures:

| Situation | Text in the result |
| - | - |
| Bare tool name (e.g. `search_sites`) or another connector's tool | `Unknown tool.` |
| No access to SharePoint (no subscription, and no plan that covers it) | `You are not subscribed to sharepoint. Purchase it here first: https://app.consile.ai/connectors/sharepoint …` |
| Access exists, but your user has no seat | `Your company subscribes to sharepoint through Consile, but your user does not hold a seat on it yet. …` (an administrator assigns seats under **Team**) |
| Microsoft account not connected yet | `sharepoint is not connected yet. Connect it here: <link>` (link valid 10 minutes; an additional portal names itself, e.g. `sharepoint-2`) |
| The stored access has expired and could not be renewed | `The SharePoint access token has expired. The connection must be re-established from the Consile portal.` |
| Microsoft rejected the token (`401`) | `SharePoint rejected the access token (401). The connection must be re-established from the Consile portal.` |
| Microsoft answered `403` | `SharePoint returned 403. The connected Microsoft user lacks access to this item, or the organisation's administrator has not consented to the permission this tool needs. Reconnecting will not fix it; ask a Microsoft 365 administrator.` |
| Site, drive, list or item not found (`404`) | `SharePoint returned 404: the requested item does not exist or is not visible to the connected user. Resolve ids with the listing or search tools first.` |
| Microsoft rejected the request (`400`), e.g. a malformed `filter` | `SharePoint rejected the request (400 <code>): <message>` (at most 500 characters) |
| Microsoft is still throttling (`429` or `503`) | `SharePoint is throttling requests (Microsoft Graph 429); retried once and still limited. Wait a moment and try again, and ask for fewer rows.` |
| `cursor` is not a continuation token from this connector | `Invalid cursor for SharePoint: pass the nextCursor from a previous page of the same tool` |
| Neither `itemId` nor `path` on a tool that needs one | `<tool> needs either itemId or path` |
| `get_site` without `siteId` or `url`, or with a non-`https` URL | `get_site needs either siteId or url` / `A site URL must be https` |
| `download_file` on a folder, or on a file above 5 MB | `download_file was given a folder; use list_drive_items on it` / `The file is <size> bytes, above the 5242880-byte limit of download_file` |
| Arguments outside the input schema (e.g. `pageSize` above `500`, a `url` that is not a URL), a timeout, another `5xx` or `408` from Microsoft, a non-JSON response, or a download that turns out larger than 5 MB | `Tool invocation failed.` |

## Limits

* Microsoft Graph's own throttling: Microsoft limits requests per app and per
  organization. Narrow searches and filters instead of paging through everything.
* Page size: default 50, maximum 500 rows.
* File download: at most 5 MB per file.

Requests to the endpoint are also rate-limited per account and connector. When the
limit is exceeded you get HTTP `429` (JSON-RPC error `-32029`, `Retry-After: 1`)
instead of a tool result. See [Errors & limits](https://docs.consile.ai/developers/errors-and-limits.md) for
the current limits and the protocol-level errors shared by all connectors.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.