npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@atomiclabs97/onenote-mcp

v0.1.1

Published

MCP server for Microsoft OneNote — read, search, create, and delete pages via Microsoft Graph.

Downloads

32

Readme

@atomiclabs97/onenote-mcp

npm version CI License: MIT

An MCP server for Microsoft OneNote. Bring your notebooks into Claude, Cursor, and any MCP-compatible client — list notebooks and sections, full-text search across pages, read individual pages, and create or delete pages from natural language. Authentication uses Microsoft's device-code flow against your own Entra ID app registration, so your data and credentials never leave your machine.

Screenshot/demo coming soon — drop a GIF in docs/images/demo.gif and reference it here.


Quick start

1. Register a Microsoft Entra app

The server talks to Microsoft Graph using a Microsoft Entra (Azure AD) app registration that you own. This takes about 2 minutes.

Screenshots referenced below live in docs/images/. They are placeholders today — contributions welcome.

a. Create the registration

  1. Go to the Microsoft Entra admin center → App registrations and click + New registration.

  2. Name: anything (e.g. onenote-mcp).

  3. Supported account types: choose "Accounts in any organizational directory and personal Microsoft accounts" if you want both work and personal OneNote to work; otherwise pick what matches your tenant.

  4. Redirect URI: leave blank — the device-code flow doesn't need one.

  5. Click Register.

    Register an application

b. Add the API permissions

  1. In the new app's left nav, click API permissions+ Add a permissionMicrosoft GraphDelegated permissions.

  2. Search for and check both:

    • Notes.ReadWrite
    • offline_access
  3. Click Add permissions. (No admin consent is required for personal Microsoft accounts. Work/school tenants may need an admin to grant consent for the directory.)

    Add Notes.ReadWrite + offline_access

c. Allow the public client flow

The device-code flow is a "public client" flow — it doesn't use a client secret.

  1. Go to Authentication in the left nav.

  2. Scroll to Advanced settingsAllow public client flows and toggle it Yes.

  3. Click Save.

    Allow public client flows

d. Grab the client ID

Back on the app's Overview page, copy the Application (client) ID. You'll pass it to the server via the ONENOTE_MCP_CLIENT_ID environment variable.

Application (client) ID on the Overview page

2. Sign in

ONENOTE_MCP_CLIENT_ID=<your-app-client-id> npx @atomiclabs97/onenote-mcp login

This prints a code and a URL like:

To sign in, use a web browser to open https://microsoft.com/devicelogin
and enter the code ABCD-1234 to authenticate.

Open the URL, paste the code, sign in with the Microsoft account whose OneNote you want to access, and approve the requested permissions. The refresh token is then cached at ~/.config/onenote-mcp/tokens.json (mode 600) so the MCP server can run silently.

To sign out:

npx @atomiclabs97/onenote-mcp logout

3. Wire it into your MCP client

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "onenote": {
      "command": "npx",
      "args": ["-y", "@atomiclabs97/onenote-mcp"],
      "env": {
        "ONENOTE_MCP_CLIENT_ID": "your-app-client-id"
      }
    }
  }
}

Restart Claude Desktop. The OneNote tools should appear in the tool picker.

Cursor

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "onenote": {
      "command": "npx",
      "args": ["-y", "@atomiclabs97/onenote-mcp"],
      "env": {
        "ONENOTE_MCP_CLIENT_ID": "your-app-client-id"
      }
    }
  }
}

Anything else

Any MCP-compatible client that supports stdio servers will work. Run npx @atomiclabs97/onenote-mcp with ONENOTE_MCP_CLIENT_ID set in the environment.


Tools

| Tool | Description | Key inputs | | ---------------- | --------------------------------------------------------------- | ------------------------------------------------ | | list_notebooks | Lists all OneNote notebooks for the signed-in user. | (none) | | list_sections | Lists sections, optionally scoped to a single notebook. | notebookId? | | list_section_groups | Lists section groups (folders), optionally scoped to a notebook. | notebookId? | | search_pages | Full-text search across pages (title + content). | query, limit? | | read_page | Returns page metadata + content (HTML or Markdown). | pageId, format? (html | markdown) | | create_notebook | Creates a new top-level notebook. | name | | create_section | Creates a section inside a notebook or section group. | notebookId? | sectionGroupId?, name | | create_section_group | Creates a section group inside a notebook or another section group. | notebookId? | sectionGroupId?, name | | create_page | Creates a page in a section. Accepts Markdown (default) or HTML, plus optional binary attachments. | sectionId, title, content, format?, attachments? | | update_page | Applies edits to a page: append/prepend/insert/replace/delete elements. | pageId, operations[] | | delete_page | Permanently deletes a page. Irreversible. | pageId |


Configuration

| Env var | Required | Description | | -------------------------- | -------- | --------------------------------------------------------------------------------- | | ONENOTE_MCP_CLIENT_ID | yes | Application (client) ID of your Microsoft Entra app registration. | | ONENOTE_MCP_TENANT_ID | no | Tenant ID. Defaults to common, which works for both personal and work accounts. | | XDG_CONFIG_HOME | no | Override the config directory. Tokens are stored at <dir>/onenote-mcp/tokens.json. |


Known limitations

  • Attachments are sent in-memory. create_page reads attachment files synchronously before posting; very large files (~150 MB+) may strain Node's heap. Streamed uploads are a future enhancement.
  • update_page targets are raw data-id selectors. To edit a specific element, read the page first and pull the data-id attribute out of the returned HTML. Higher-level selectors (e.g. "the section under heading X") are tracked for a follow-up.
  • Search latency. Microsoft Graph's $search against /me/onenote/pages can take a few seconds against large notebooks; the server retries on 429s with exponential backoff.

Contributing

PRs welcome. The codebase aims to stay small and focused.

git clone https://github.com/ahmadAlMezaal/onenote-mcp
cd onenote-mcp
yarn install
yarn build
yarn test
  • yarn typechecktsc --noEmit (covers src/ + scripts/)
  • yarn lint — ESLint
  • yarn test — Vitest (unit tests, mocked Graph)
  • yarn dev — incremental rebuild on save (tsc --watch + tsc-alias --watch); dist/ stays runnable

Use Yarn (Classic), not npm. The repo's lockfile is yarn.lockpackage-lock.json should not be committed.

End-to-end smoke test

scripts/smoke.ts exercises every shipped tool against a real OneNote account. It's not in CI — needs real credentials.

# One-time: register an Entra app (see Quick start above) and sign in
ONENOTE_MCP_CLIENT_ID=<your-client-id> yarn build
ONENOTE_MCP_CLIENT_ID=<your-client-id> node dist/cli.js login

# Then run the smoke test
ONENOTE_MCP_CLIENT_ID=<your-client-id> yarn smoke

It's idempotent: reuses (or creates) a notebook called OneNote MCP Smoke Test, walks through 12 steps covering auth, list/search/read/create/update/delete and the multipart attachment path, and cleans up the pages it creates. Sections and section groups are left behind for the next run.

If you're using an AI coding assistant (Claude Code, Cursor, etc.), see CLAUDE.md for project conventions, the arrow-function rule, and the tool-authoring checklist.

Commits follow Conventional Commits (feat:, fix:, chore:, etc.). CI runs typecheck + lint + tests on every push and PR.

Roadmap

  • [x] update_page — in-place edits via Graph's PATCH syntax
  • [x] create_section / create_notebook
  • [x] Image and attachment upload (multipart create_page)
  • [x] Section group support (list + create + section-in-group targeting)
  • [ ] Streamed attachment uploads (avoid in-memory buffering for large files)
  • [ ] Resource-style page browsing (alongside the tool surface)

License

MIT © Ahmad Al Mezaal