> ## 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: OneNote

> The nine read-only tools in the OneNote connector: notebooks, recent notebooks, sections, section groups, pages, full-text search, recently changed pages, page content as text or HTML, and page previews. Covers the siteId/groupId container convention, cursor paging, size caps and the error contract.

All OneNote tools are read-only and are called via `tools/call` over
`POST /onenote/mcp`. The connector reads Microsoft OneNote through Microsoft Graph
and is connected through OAuth with a Microsoft work or school account (see
[Connect OneNote](https://docs.consile.ai/en/connect/connect-onenote.md)). Your organization needs access to
OneNote (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/onenote/mcp`. OneNote is its own named
> connector with only its own tools. Tool names are namespaced `onenote__<tool>`
> (e.g. `onenote__list_notebooks`); the bare names are used below for readability.
> A bare name in a request returns `Unknown tool.`
>
> The connector is multi-instance: one instance is one connected Microsoft user and
> everything that user can open in OneNote. An administrator adds further
> connections (agreements, **aftaler**, in the portal), each served at its own
> endpoint, e.g. `https://mcp.consile.ai/onenote-2/mcp`, with tools named
> `onenote-2__<tool>`.

For an account with access to OneNote, `tools/list` returns the nine `onenote__*`
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

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 Microsoft Graph permissions are:

* `Notes.Read.All` (every OneNote notebook the user can open: their own, and those on
  SharePoint sites and in Microsoft 365 groups they belong to)
* `User.Read` (the user's name and email, used to name the agreement in the portal)
* `offline_access` (keeps the connection alive)

All of them are read permissions. The connector has no write tools, and Consile
sends only read requests to Microsoft Graph. The connect is rejected if Microsoft's
grant lacks one of the requested permissions. Depending on the organization's
consent settings, Microsoft may require an administrator's approval before a user
can connect.

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. Page content is read
live and is not stored by Consile.

## Shared conventions

### Containers: siteId and groupId

OneNote content lives in three kinds of container: the connected user's own
notebooks, a SharePoint site's notebooks (team notebooks) and a Microsoft 365 group's
notebooks. Every tool that addresses a notebook, section or page takes two optional
arguments that pick the container. Leave both out for the user's own notebooks.

**siteId** `string`

SharePoint site id in the `host,guid,guid` form, at least one character. Reads that
site's notebooks. The [SharePoint connector](https://docs.consile.ai/developers/tools/sharepoint.md) returns
it (`search_sites`, or `get_site` with a notebook's web link).

**groupId** `string`

Microsoft 365 group id, at least one character. Reads that group's notebooks. A
team in Microsoft Teams has the same id as its group.

Pass at most one of them. Passing both is refused with
`Pass either siteId or groupId, not both`. An id from one container is not found in
another, so pass the same `siteId` or `groupId` on every call that follows from a
site's or group's listing (`list_sections`, `list_pages`, `get_page`,
`get_page_preview`).

The listing tools echo the container they read as `container`: `"me"`,
`"site:<siteId>"` or `"group:<groupId>"`.

`search_pages` and `list_recent_pages` take neither argument. Microsoft only supports
them on the user's own notebooks.

### Hierarchy and typical call order

Inside a container the hierarchy is notebook, then optional (and nestable) section
groups, then sections, then pages. Only pages carry content.

1. `list_notebooks` (or `list_recent_notebooks` to find a shared notebook by name).
2. `list_sections` with the `notebookId`.
3. `list_pages` with the `sectionId`.
4. `get_page_preview` or `get_page` with the `pageId`.

For the user's own notes, `search_pages` and `list_recent_pages` go straight to
pages.

### Paging

`list_pages`, `search_pages` and `list_recent_pages` are paged. The other listings
return the whole list in one result.

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

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

**cursor** `string`

Opaque continuation token from a previous result's `nextCursor`. Omit it for the
first page and never construct or edit one. When `cursor` is set, the other
options are ignored and the query of the first call continues. Pass it back to the
same tool. A value that is not a continuation token is refused with
`Invalid cursor for OneNote: pass the nextCursor from a previous page of the same tool`.

A paged result has `count`, `items` and `nextCursor` (`null` when there are no more
rows). There is no total count.

### Page rows

`list_pages`, `search_pages` and `list_recent_pages` return the same row shape:

**items\[]** `object`

`id` (the `pageId`), `title`, `sectionId`, `sectionName`, `notebookId`,
`notebookName`, `level` and `order` (the page's indent level and position in its
section), `webUrl` (the page in OneNote on the web), `createdDateTime` and
`lastModifiedDateTime`. A missing value is `null`.

***

## list\_notebooks

Lists OneNote notebooks: the user's own by default, a SharePoint site's with
`siteId`, or a Microsoft 365 group's with `groupId`. Sorted by name.

**siteId** `string`

**groupId** `string`

**items** `array`

Each item has `id` (the `notebookId`), `displayName`, `isDefault`, `isShared`,
`userRole` (the user's role as Microsoft reports it), `webUrl`, `createdDateTime`
and `lastModifiedDateTime`.

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

```json Result (payload) theme={null}
{
  "container": "me",
  "count": 1,
  "items": [
    {
      "id": "1-7c3e5a9b-2f41-4d8e-9b6a-0e1f2a3b4c5d",
      "displayName": "<name>'s notebook",
      "isDefault": true,
      "isShared": false,
      "userRole": "Owner",
      "webUrl": "https://example.com/onenote/notebook",
      "createdDateTime": "2024-03-11T08:15:02Z",
      "lastModifiedDateTime": "2026-10-29T14:40:51Z"
    }
  ]
}
```

***

## list\_recent\_notebooks

Lists the notebooks the user opened most recently, across their own OneDrive and the
SharePoint sites and groups they work in. Use it to find a shared notebook by name.
It returns no ids: follow up with `list_notebooks` on the site or group the notebook
lives on (resolve the `siteId` from the notebook's web link with the SharePoint
connector), or without a container when it is the user's own.

**includePersonal** `boolean` (default: true)

Include the user's own notebooks alongside the shared ones.

**items** `array`

Each item has `displayName`, `lastAccessedTime`, `sourceService` (where the
notebook lives, as Microsoft reports it) and `webUrl`.

```json Request theme={null}
{ "name": "onenote__list_recent_notebooks", "arguments": { "includePersonal": false } }
```

```json Result (payload) theme={null}
{
  "count": 1,
  "items": [
    {
      "displayName": "Team notebook",
      "lastAccessedTime": "2026-10-30T09:12:44Z",
      "sourceService": "OneDriveForBusiness",
      "webUrl": "https://example.com/sites/team/SiteAssets/Team%20notebook"
    }
  ]
}
```

***

## list\_sections

Lists the sections of one notebook (with `notebookId`), or every section in the
container when `notebookId` is left out. Each row names its notebook and section
group. Sorted by name.

**notebookId** `string`

Notebook id from `list_notebooks`.

**siteId** `string`

**groupId** `string`

**items** `array`

Each item has `id` (the `sectionId`), `displayName`, `isDefault`, `notebookId`,
`notebookName`, `sectionGroupId`, `sectionGroupName` (`null` when the section is
not in a section group), `webUrl`, `createdDateTime` and `lastModifiedDateTime`.

The result also echoes `container` and `notebookId` (`null` when left out).

```json Request theme={null}
{
  "name": "onenote__list_sections",
  "arguments": { "notebookId": "1-7c3e5a9b-2f41-4d8e-9b6a-0e1f2a3b4c5d" }
}
```

```json Result (payload, shortened) theme={null}
{
  "container": "me",
  "notebookId": "1-7c3e5a9b-2f41-4d8e-9b6a-0e1f2a3b4c5d",
  "count": 1,
  "items": [
    {
      "id": "1-a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "displayName": "Meeting notes",
      "isDefault": false,
      "notebookId": "1-7c3e5a9b-2f41-4d8e-9b6a-0e1f2a3b4c5d",
      "notebookName": "<name>'s notebook",
      "sectionGroupId": null,
      "sectionGroupName": null,
      "webUrl": "https://example.com/onenote/section",
      "createdDateTime": "2025-01-06T10:00:00Z",
      "lastModifiedDateTime": "2026-10-28T15:22:10Z"
    }
  ]
}
```

***

## list\_section\_groups

Lists the section groups (folders of sections) directly under a notebook, or under
another section group. Most notebooks have none.

**notebookId** `string`

Notebook id from `list_notebooks`.

**sectionGroupId** `string`

A section group id, to list the groups nested in it. Takes precedence over
`notebookId`.

**siteId** `string`

**groupId** `string`

One of `notebookId` and `sectionGroupId` is required. Without either, the call is
refused with `list_section_groups needs either notebookId or sectionGroupId`.

**items** `array`

Each item has `id`, `displayName`, `notebookId`, `parentSectionGroupId`,
`createdDateTime` and `lastModifiedDateTime`.

***

## list\_pages

Lists the pages of a section, most recently changed first. Paged.

**sectionId** `string` *required*

Section id from `list_sections`.

**siteId** `string`

**groupId** `string`

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

**cursor** `string`

The result echoes `container` and `sectionId`, followed by the [page rows](#page-rows)
and `nextCursor`.

```json Request theme={null}
{
  "name": "onenote__list_pages",
  "arguments": { "sectionId": "1-a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "pageSize": 10 }
}
```

```json Result (payload) theme={null}
{
  "container": "me",
  "sectionId": "1-a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "count": 1,
  "items": [
    {
      "id": "1-0f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c!1-a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "title": "Weekly meeting",
      "sectionId": "1-a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "sectionName": "Meeting notes",
      "notebookId": "1-7c3e5a9b-2f41-4d8e-9b6a-0e1f2a3b4c5d",
      "notebookName": "<name>'s notebook",
      "level": 0,
      "order": 0,
      "webUrl": "https://example.com/onenote/page",
      "createdDateTime": "2026-10-27T08:00:00Z",
      "lastModifiedDateTime": "2026-10-27T09:31:18Z"
    }
  ],
  "nextCursor": null
}
```

***

## search\_pages

Full-text search in titles and content across all of the user's own pages. It does
not cover a site's or a group's notebooks (a Microsoft limitation); for those, use
`list_sections` and then `list_pages`. Paged.

**query** `string` *required*

Words to search for, 1 to 200 characters. Double quotes are removed before the
search.

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

**cursor** `string`

The result echoes `query`, followed by the [page rows](#page-rows) and
`nextCursor`.

```json Request theme={null}
{ "name": "onenote__search_pages", "arguments": { "query": "budget" } }
```

***

## list\_recent\_pages

Lists the user's own pages by most recent change across all their own notebooks,
optionally only those changed since a given instant. It does not cover a site's or a
group's notebooks; for those, use `list_pages` per section. Paged.

**since** `string`

Only pages changed at or after this instant. A full ISO 8601 instant with time and
time zone, e.g. `2026-10-01T00:00:00Z` or `2026-10-01T08:00:00+02:00`. A date
without time is refused.

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

**cursor** `string`

The result echoes `since` (`null` when left out), followed by the
[page rows](#page-rows) and `nextCursor`.

```json Request theme={null}
{
  "name": "onenote__list_recent_pages",
  "arguments": { "since": "2026-10-26T00:00:00Z", "pageSize": 50 }
}
```

***

## get\_page

Reads one page: its metadata and its content as text (default) or as the raw HTML.

**pageId** `string` *required*

Page id from `list_pages`, `search_pages` or `list_recent_pages`.

**format** `string` (default: text)

`text` or `html`. Use `html` when tables or layout matter; the text form puts each
table row on one line, with the cells separated by tabs.

**siteId** `string`

Required when the page belongs to a site's notebook.

**groupId** `string`

Required when the page belongs to a group's notebook.

The result has the [page row](#page-rows) fields plus:

**format** `string`

`text` or `html`, as requested.

**content** `string`

The page content. In `text`, tags are removed, paragraphs and list items become
line breaks, and images and attachments become short markers:
`[billede: <alt text>]` or `[billede]` for an image, `[vedhæftet: <file name>]` or
`[vedhæftet fil]` for an attachment. The markers are in Danish. Their bytes are
never returned.

**resourceCount** `integer`

The number of images and attachments on the page.

**contentTruncated** `boolean`

`true` when `content` was cut off: at 50,000 characters in `text` and 100,000
characters in `html`.

A page whose HTML is larger than 5 MB cannot be read, and the client sees only
`Tool invocation failed.`

```json Request theme={null}
{
  "name": "onenote__get_page",
  "arguments": { "pageId": "1-0f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c!1-a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" }
}
```

```json Result (payload, shortened) theme={null}
{
  "id": "1-0f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c!1-a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "title": "Weekly meeting",
  "sectionName": "Meeting notes",
  "notebookName": "<name>'s notebook",
  "lastModifiedDateTime": "2026-10-27T09:31:18Z",
  "format": "text",
  "resourceCount": 1,
  "contentTruncated": false,
  "content": "Weekly meeting\n\nDecisions\nShip the new price list on Monday.\n[billede: whiteboard]"
}
```

***

## get\_page\_preview

Reads a short text preview of a page without downloading its content: enough to
decide whether `get_page` is worth it.

**pageId** `string` *required*

**siteId** `string`

**groupId** `string`

**previewText** `string`

The preview text Microsoft generates for the page (an empty string if none).

**hasPreviewImage** `boolean`

`true` when Microsoft also has a preview image for the page. The image itself is
not returned.

The result also echoes `pageId`.

***

## connect\_account

`connect_account` is a system tool that the OneNote endpoint lists next to the nine
tools. It takes no arguments and its name has no `onenote__` 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 OneNote 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. `list_notebooks`) or another connector's tool | `Unknown tool.` |
| No access to OneNote (no subscription, and no plan that covers it) | `You are not subscribed to onenote. Purchase it here first: https://app.consile.ai/connectors/onenote …` |
| Access exists, but your user has no seat | `Your company subscribes to onenote through Consile, but your user does not hold a seat on it yet. …` (an administrator assigns seats under **Team**) |
| Microsoft account not connected yet | `onenote is not connected yet. Connect it here: <link>` (link valid 10 minutes; an additional agreement names itself, e.g. `onenote-2`) |
| The stored access has expired and could not be renewed | `The OneNote access token has expired. The connection must be re-established from the Consile portal.` |
| Microsoft rejected the token (`401`) | `OneNote rejected the access token (401). The connection must be re-established from the Consile portal.` |
| Microsoft answered `403` | `OneNote 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.` |
| Unknown id, or an item the connected user cannot see (`404`) | `OneNote 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`) | `OneNote rejected the request (400 <code>): <message>` (at most 500 characters) |
| Microsoft's rate limit is still reached (`429` or `503`) | `OneNote is throttling requests (Microsoft Graph 429); retried once and still limited. Wait a moment and try again, and ask for fewer rows.` |
| Both `siteId` and `groupId` | `Pass either siteId or groupId, not both` |
| `list_section_groups` without `notebookId` and `sectionGroupId` | `list_section_groups needs either notebookId or sectionGroupId` |
| `cursor` is not a continuation token | `Invalid cursor for OneNote: pass the nextCursor from a previous page of the same tool` |
| Arguments outside the input schema (e.g. `pageSize` above `100`, a `since` without time zone, a `query` over 200 characters), a page above 5 MB, a timeout, another `5xx` or `408` from Microsoft, or a non-JSON response | `Tool invocation failed.` |

## Limits

* Page size: default 20, maximum 100 rows for the paged tools.
* Page content: 50,000 characters as text, 100,000 as HTML (flagged with
  `contentTruncated`); pages above 5 MB of HTML cannot be read.
* Microsoft Graph limits how many requests can be made in a short time. Narrow the
  listing instead of paging through everything.

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.