Skip to main content
Glama

ms-365-mcp-server

npm version build status license

Microsoft 365 MCP Server

A Model Context Protocol (MCP) server for interacting with Microsoft 365 and Microsoft Office services through the Graph API.

Supported Clouds

This server supports multiple Microsoft cloud environments:

Cloud

Description

Auth Endpoint

Graph API Endpoint

Global (default)

International Microsoft 365

login.microsoftonline.com

graph.microsoft.com

China (21Vianet)

Microsoft 365 operated by 21Vianet

login.chinacloudapi.cn

microsoftgraph.chinacloudapi.cn

Prerequisites

  • Node.js >= 20 (recommended)

  • Node.js 14+ may work with dependency warnings

Features

  • Authentication via Microsoft Authentication Library (MSAL)

  • Comprehensive Microsoft 365 service integration

  • Read-only mode support for safe operations

  • Tool filtering for granular access control

Output Format: JSON vs TOON

The server supports two output formats that can be configured globally:

JSON Format (Default)

Standard JSON output with pretty-printing:

{
  "value": [
    {
      "id": "1",
      "displayName": "Alice Johnson",
      "mail": "alice@example.com",
      "jobTitle": "Software Engineer"
    }
  ]
}

(experimental) TOON Format

Token-Oriented Object Notation for efficient LLM token usage:

value[1]{id,displayName,mail,jobTitle}:
  "1",Alice Johnson,alice@example.com,Software Engineer

Benefits:

  • 30-60% fewer tokens vs JSON

  • Best for uniform array data (lists of emails, calendar events, files, etc.)

  • Ideal for cost-sensitive applications at scale

Usage: (experimental) Enable TOON format globally:

Via CLI flag:

npx @softeria/ms-365-mcp-server --toon

Via Claude Desktop configuration:

{
  "mcpServers": {
    "ms365": {
      "command": "npx",
      "args": ["-y", "@softeria/ms-365-mcp-server", "--toon"]
    }
  }
}

Via environment variable:

MS365_MCP_OUTPUT_FORMAT=toon npx @softeria/ms-365-mcp-server

Supported Services & Tools

Personal Account Tools (Available by default)

Email (Outlook)
list-mail-messages, list-mail-folders, list-mail-folder-messages, get-mail-message, send-mail, delete-mail-message, create-draft-email, move-mail-message

Calendar
list-calendars, list-calendar-events, get-calendar-event, get-calendar-view, create-calendar-event, update-calendar-event, delete-calendar-event

OneDrive Files
list-drives, get-drive-root-item, list-folder-files, download-onedrive-file-content, upload-file-content, upload-new-file, delete-onedrive-file

Excel Operations
list-excel-worksheets, get-excel-range, create-excel-chart, format-excel-range, sort-excel-range

OneNote
list-onenote-notebooks, list-onenote-notebook-sections, list-onenote-section-pages, get-onenote-page-content, create-onenote-page

To Do Tasks
list-todo-task-lists, list-todo-tasks, get-todo-task, create-todo-task, update-todo-task, delete-todo-task

Planner
list-planner-tasks, get-planner-plan, list-plan-tasks, get-planner-task, create-planner-task

Contacts
list-outlook-contacts, get-outlook-contact, create-outlook-contact, update-outlook-contact, delete-outlook-contact

User Profile
get-current-user

Search
search-query

Organization Account Tools (Requires --org-mode flag)

Teams & Chats
list-chats, get-chat, list-chat-messages, get-chat-message, send-chat-message, list-chat-message-replies, reply-to-chat-message, list-joined-teams, get-team, list-team-channels, get-team-channel, list-channel-messages, get-channel-message, send-channel-message, list-team-members

SharePoint Sites
search-sharepoint-sites, get-sharepoint-site, get-sharepoint-site-by-path, list-sharepoint-site-drives, get-sharepoint-site-drive-by-id, list-sharepoint-site-items, get-sharepoint-site-item, list-sharepoint-site-lists, get-sharepoint-site-list, list-sharepoint-site-list-items, get-sharepoint-site-list-item, get-sharepoint-sites-delta

Shared Mailboxes
list-shared-mailbox-messages, list-shared-mailbox-folder-messages, get-shared-mailbox-message, send-shared-mailbox-mail

User Management
list-users

Organization/Work Mode

To access work/school features (Teams, SharePoint, etc.), enable organization mode using any of these flags:

{
  "mcpServers": {
    "ms365": {
      "command": "npx",
      "args": ["-y", "@softeria/ms-365-mcp-server", "--org-mode"]
    }
  }
}

Organization mode must be enabled from the start to access work account features. Without this flag, only personal account features (email, calendar, OneDrive, etc.) are available.

Shared Mailbox Access

To access shared mailboxes, you need:

  1. Organization mode: Shared mailbox tools require --org-mode flag (work/school accounts only)

  2. Delegated permissions: Mail.Read.Shared or Mail.Send.Shared scopes

  3. Exchange permissions: The signed-in user must have been granted access to the shared mailbox

  4. Usage: Use the shared mailbox's email address as the user-id parameter in the shared mailbox tools

Finding shared mailboxes: Use the list-users tool to discover available users and shared mailboxes in your organization.

Example: list-shared-mailbox-messages with user-id set to shared-mailbox@company.com

Quick Start Example

Test login in Claude Desktop:

Login example

Examples

Image

Integration

Claude Desktop

To add this MCP server to Claude Desktop, edit the config file under Settings > Developer.

Personal Account (MSA)

{
  "mcpServers": {
    "ms365": {
      "command": "npx",
      "args": ["-y", "@softeria/ms-365-mcp-server"]
    }
  }
}

Work/School Account (Global)

{
  "mcpServers": {
    "ms365": {
      "command": "npx",
      "args": ["-y", "@softeria/ms-365-mcp-server", "--org-mode"]
    }
  }
}

Work/School Account (China 21Vianet)

{
  "mcpServers": {
    "ms365-china": {
      "command": "npx",
      "args": ["-y", "@softeria/ms-365-mcp-server", "--org-mode", "--cloud", "china"]
    }
  }
}

Claude Code CLI

Personal Account (MSA)

claude mcp add ms365 -- npx -y @softeria/ms-365-mcp-server

Work/School Account (Global)

# macOS/Linux
claude mcp add ms365 -- npx -y @softeria/ms-365-mcp-server --org-mode

# Windows (use cmd /c wrapper)
claude mcp add ms365 -s user -- cmd /c "npx -y @softeria/ms-365-mcp-server --org-mode"

Work/School Account (China 21Vianet)

# macOS/Linux
claude mcp add ms365-china -- npx -y @softeria/ms-365-mcp-server --org-mode --cloud china

# Windows (use cmd /c wrapper)
claude mcp add ms365-china -s user -- cmd /c "npx -y @softeria/ms-365-mcp-server --org-mode --cloud china"

For other interfaces that support MCPs, please refer to their respective documentation for the correct integration method.

Open WebUI

Open WebUI supports MCP servers via HTTP transport with OAuth 2.1.

  1. Start the server with HTTP mode and dynamic registration enabled:

    npx @softeria/ms-365-mcp-server --http --enable-dynamic-registration
  2. In Open WebUI, go to Admin Settings → Tools (/admin/settings/tools) → Add Connection:

    • Type: MCP Streamable HTTP

    • URL: Your MCP server URL with /mcp path

    • Auth: OAuth 2.1

  3. Click Register Client.

Note: The --enable-dynamic-registration is required for Open WebUI to work. If using a custom Azure Entra app, add your redirect URI under "Mobile and desktop applications" platform (not "Single-page application").

Quick test setup using the default Azure app (ID ms-365 and localhost:8080 are pre-configured):

docker run -d -p 8080:8080 \
  -e WEBUI_AUTH=false \
  -e OPENAI_API_KEY \
  ghcr.io/open-webui/open-webui:main

npx @softeria/ms-365-mcp-server --http --enable-dynamic-registration

Then add connection with URL http://localhost:3000/mcp and ID ms-365.

Open WebUI MCP Connection

Local Development

For local development or testing:

# From the project directory
claude mcp add ms -- npx tsx src/index.ts --org-mode

Or configure Claude Desktop manually:

{
  "mcpServers": {
    "ms365": {
      "command": "node",
      "args": ["/absolute/path/to/ms-365-mcp-server/dist/index.js", "--org-mode"]
    }
  }
}

Note: Run npm run build after code changes to update the dist/ folder.

Authentication

⚠️ You must authenticate before using tools.

The server supports three authentication methods:

1. Device Code Flow (Default)

For interactive authentication via device code:

  • MCP client login:

    • Call the login tool (auto-checks existing token)

    • If needed, get URL+code, visit in browser

    • Use verify-login tool to confirm

  • CLI login:

    npx @softeria/ms-365-mcp-server --login

    Follow the URL and code prompt in the terminal.

Tokens are cached securely in your OS credential store (fallback to file).

2. OAuth Authorization Code Flow (HTTP mode only)

When running with --http, the server requires OAuth authentication:

npx @softeria/ms-365-mcp-server --http 3000

This mode:

  • Advertises OAuth capabilities to MCP clients

  • Provides OAuth endpoints at /auth/* (authorize, token, metadata)

  • Requires Authorization: Bearer <token> for all MCP requests

  • Validates tokens with Microsoft Graph API

  • Disables login/logout tools by default (use --enable-auth-tools to enable them)

MCP clients will automatically handle the OAuth flow when they see the advertised capabilities.

Setting up Azure AD for OAuth Testing

To use OAuth mode with custom Azure credentials (recommended for production), you'll need to set up an Azure AD app registration:

  1. Create Azure AD App Registration:

  • Go to Azure Portal

  • Navigate to Azure Active Directory → App registrations → New registration

  • Set name: "MS365 MCP Server"

  1. Configure Redirect URIs:

  • Configure the OAuth callback URI: Go to your app registration and on the left side, go to Authentication.

  • Under Platform configurations:

    • Click Add a platform (if you don’t already see one for "Mobile and desktop applications" / "Public client").

    • Choose Mobile and desktop applications or Public client/native (mobile & desktop) (label depends on portal version).

  1. Testing with MCP Inspector (npm run inspector):

  • Go to your app registration and on the left side, go to Authentication.

  • Under Platform configurations:

    • Click Add a platform (if you don’t already see one for "Web").

    • Choose Web.

    • Configure the following redirect URIs

      • http://localhost:6274/oauth/callback

      • http://localhost:6274/oauth/callback/debug

      • http://localhost:3000/callback (optional, for server callback)

  1. Get Credentials:

  • Copy the Application (client) ID from Overview page

  • Go to Certificates & secrets → New client secret → Copy the secret value (optional for public apps)

  1. Configure Environment Variables: Create a .env file in your project root:

    MS365_MCP_CLIENT_ID=your-azure-ad-app-client-id-here
    MS365_MCP_CLIENT_SECRET=your-secret-here  # Optional for public apps
    MS365_MCP_TENANT_ID=common

With these configured, the server will use your custom Azure app instead of the built-in one.

3. Bring Your Own Token (BYOT)

If you are running ms-365-mcp-server as part of a larger system that manages Microsoft OAuth tokens externally, you can provide an access token directly to this MCP server:

MS365_MCP_OAUTH_TOKEN=your_oauth_token npx @softeria/ms-365-mcp-server

This method:

  • Bypasses the interactive authentication flows

  • Use your pre-existing OAuth token for Microsoft Graph API requests

  • Does not handle token refresh (token lifecycle management is your responsibility)

Note: HTTP mode requires authentication. For unauthenticated testing, use stdio mode with device code flow.

Authentication Tools: In HTTP mode, login/logout tools are disabled by default since OAuth handles authentication. Use --enable-auth-tools if you need them available.

Tool Presets

To reduce initial connection overhead, use preset tool categories instead of loading all 90+ tools:

npx @softeria/ms-365-mcp-server --preset mail
npx @softeria/ms-365-mcp-server --list-presets  # See all available presets

Available presets: mail, calendar, files, personal, work, excel, contacts, tasks, onenote, search, users, all

Experimental: --discovery starts with only 2 tools (search-tools, execute-tool) for minimal token usage.

CLI Options

The following options can be used when running ms-365-mcp-server directly from the command line:

--login           Login using device code flow
--logout          Log out and clear saved credentials
--verify-login    Verify login without starting the server
--org-mode        Enable organization/work mode from start (includes Teams, SharePoint, etc.)
--work-mode       Alias for --org-mode
--force-work-scopes Backwards compatibility alias for --org-mode (deprecated)
--cloud <type>    Microsoft cloud environment: global (default) or china (21Vianet)

Server Options

When running as an MCP server, the following options can be used:

-v                Enable verbose logging
--read-only       Start server in read-only mode, disabling write operations
--http [port]     Use Streamable HTTP transport instead of stdio (optionally specify port, default: 3000)
                  Starts Express.js server with MCP endpoint at /mcp
--enable-auth-tools Enable login/logout tools when using HTTP mode (disabled by default in HTTP mode)
--enable-dynamic-registration Enable OAuth Dynamic Client Registration endpoint (required for Open WebUI)
--enabled-tools <pattern> Filter tools using regex pattern (e.g., "excel|contact" to enable Excel and Contact tools)
--preset <names>  Use preset tool categories (comma-separated). See "Tool Presets" section above
--list-presets    List all available presets and exit
--toon            (experimental) Enable TOON output format for 30-60% token reduction
--discovery       (experimental) Start with search-tools + execute-tool only

Environment variables:

  • READ_ONLY=true|1: Alternative to --read-only flag

  • ENABLED_TOOLS: Filter tools using a regex pattern (alternative to --enabled-tools flag)

  • MS365_MCP_ORG_MODE=true|1: Enable organization/work mode (alternative to --org-mode flag)

  • MS365_MCP_FORCE_WORK_SCOPES=true|1: Backwards compatibility for MS365_MCP_ORG_MODE

  • MS365_MCP_OUTPUT_FORMAT=toon: Enable TOON output format (alternative to --toon flag)

  • MS365_MCP_CLOUD_TYPE=global|china: Microsoft cloud environment (alternative to --cloud flag)

  • LOG_LEVEL: Set logging level (default: 'info')

  • SILENT=true|1: Disable console output

  • MS365_MCP_CLIENT_ID: Custom Azure app client ID (defaults to built-in app)

  • MS365_MCP_TENANT_ID: Custom tenant ID (defaults to 'common' for multi-tenant)

  • MS365_MCP_OAUTH_TOKEN: Pre-existing OAuth token for Microsoft Graph API (BYOT method)

  • MS365_MCP_KEYVAULT_URL: Azure Key Vault URL for secrets management (see Azure Key Vault section)

  • MS365_MCP_TOKEN_CACHE_PATH: Custom file path for MSAL token cache (see Token Storage below)

  • MS365_MCP_SELECTED_ACCOUNT_PATH: Custom file path for selected account metadata (see Token Storage below)

Token Storage

Authentication tokens are stored using the OS credential store (via keytar) when available. If keytar is not installed or fails (common on headless Linux), the server falls back to file-based storage.

Default fallback paths are relative to the installed package directory. This means tokens can be lost when the package is reinstalled or updated via npm.

To persist tokens across updates, set custom paths outside the package directory:

export MS365_MCP_TOKEN_CACHE_PATH="$HOME/.config/ms365-mcp/.token-cache.json"
export MS365_MCP_SELECTED_ACCOUNT_PATH="$HOME/.config/ms365-mcp/.selected-account.json"

Parent directories are created automatically. Files are written with 0600 permissions.

Security note: File-based token storage writes sensitive credentials to disk. Ensure the chosen directory has appropriate access controls. The OS credential store (keytar) is preferred when available.

Azure Key Vault Integration

For production deployments, you can store secrets in Azure Key Vault instead of environment variables. This is particularly useful for Azure Container Apps with managed identity.

Setup

  1. Create a Key Vault (if you don't have one):

    az keyvault create --name your-keyvault-name --resource-group your-rg --location eastus
  2. Add secrets to Key Vault:

    az keyvault secret set --vault-name your-keyvault-name --name ms365-mcp-client-id --value "your-client-id"
    az keyvault secret set --vault-name your-keyvault-name --name ms365-mcp-tenant-id --value "your-tenant-id"
    # Optional: if using confidential client flow
    az keyvault secret set --vault-name your-keyvault-name --name ms365-mcp-client-secret --value "your-secret"
  3. Grant access to Key Vault:

    For Azure Container Apps with managed identity:

    # Get the managed identity principal ID
    PRINCIPAL_ID=$(az containerapp show --name your-app --resource-group your-rg --query identity.principalId -o tsv)
    
    # Grant access to Key Vault secrets
    az keyvault set-policy --name your-keyvault-name --object-id $PRINCIPAL_ID --secret-permissions get list

    For local development with Azure CLI:

    # Your Azure CLI identity already has access if you have appropriate RBAC roles
    az login
  4. Configure the server:

    MS365_MCP_KEYVAULT_URL=https://your-keyvault-name.vault.azure.net npx @softeria/ms-365-mcp-server

Secret Name Mapping

Key Vault Secret Name

Environment Variable

Required

ms365-mcp-client-id

MS365_MCP_CLIENT_ID

Yes

ms365-mcp-tenant-id

MS365_MCP_TENANT_ID

No (defaults to 'common')

ms365-mcp-client-secret

MS365_MCP_CLIENT_SECRET

No

Authentication

The Key Vault integration uses DefaultAzureCredential from the Azure Identity SDK, which automatically tries multiple authentication methods in order:

  1. Environment variables (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID)

  2. Managed Identity (recommended for Azure Container Apps)

  3. Azure CLI credentials (for local development)

  4. Visual Studio Code credentials

  5. Azure PowerShell credentials

Optional Dependencies

The Azure Key Vault packages (@azure/identity and @azure/keyvault-secrets) are optional dependencies. They are only loaded when MS365_MCP_KEYVAULT_URL is configured. If you don't use Key Vault, these packages are not required.

Contributing

We welcome contributions! Before submitting a pull request, please ensure your changes meet our quality standards.

Run the verification script to check all code quality requirements:

npm run verify

For Developers

After cloning the repository, you may need to generate the client code from the Microsoft Graph OpenAPI specification:

npm run generate

Support

If you're having problems or need help:

License

MIT © 2026 Softeria

Available Tools

78 tools
add-mail-attachmentC
Destructive

Use this API to create a new Attachment. An attachment can be one of the following types: All these types of attachment resources are derived from the attachment resource.

Inputs: body (required), messageId (required), includeHeaders, excludeResponse.

create-calendar-eventD
Destructive

Create one or more multi-value extended properties in a new or existing instance of a resource. The following user resources are supported: The following group resources are supported: See Extended properties overview for more information about when to use open extensions or extended properties, and how to specify extended properties.

💡 TIP: CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients.

Inputs: body (required), includeHeaders, excludeResponse.

create-draft-emailD
Destructive

Create an open extension (openTypeExtension object) and add custom properties in a new or existing instance of a resource. You can create an open extension in a resource instance and store custom data to it all in the same operation, except for specific resources. The table in the Permissions section lists the resources that support open extensions.

Inputs: body (required), includeHeaders, excludeResponse.

create-excel-chartC
Destructive

Creates a new chart.

Inputs: body (required), driveId (required), driveItemId (required), workbookWorksheetId (required), +2 more.

create-forward-draftA
Destructive

Create a draft to forward an existing message, in either JSON or MIME format. When using JSON format, you can:

  • Specify either a comment or the body property of the message parameter. Specifying both will return an HTTP 400 Bad Request error.

  • Specify either the toRecipients parameter or the toRecipients property of the message parameter. Specifying both or specifying neither will return an HTTP 400 Bad Request error.

  • Update the draft later to add content to the body or change other message properties. When using MIME format:

  • Provide the applicable Internet message headers and the MIME content, all encoded in base64 format in the request body.

  • Add any attachments and S/MIME properties to the MIME content. Send the draft message in a subsequent operation. Alternatively, forward a message in a single operation.

💡 TIP: Create a forward draft (does not send). Useful when user wants to review before sending.

Inputs: body (required), messageId (required), includeHeaders, excludeResponse.

create-onenote-pageB
Destructive

Create a new OneNote page in the default section of the default notebook. To create a page in a different section in the default notebook, you can use the sectionName query parameter. Example: ../onenote/pages?sectionName=My%20section The POST /onenote/pages operation is used only to create pages in the current user's default notebook. If you're targeting other notebooks, you can create pages in a specified section.

Inputs: body (required), includeHeaders, excludeResponse.

create-onenote-section-pageB
Destructive

Create a new page in the specified section.

Inputs: body (required), onenoteSectionId (required), includeHeaders, excludeResponse.

create-outlook-contactB
Destructive

Add a contact to the root Contacts folder or to the contacts endpoint of another contact folder.

Inputs: body (required), includeHeaders, excludeResponse.

create-planner-taskC
Destructive

Create a new plannerTask.

Inputs: body (required), includeHeaders, excludeResponse.

create-reply-all-draftA
Destructive

Create a draft to reply to the sender and all recipients of a message in either JSON or MIME format. When using JSON format:

  • Specify either a comment or the body property of the message parameter. Specifying both will return an HTTP 400 Bad Request error.

  • If the original message specifies a recipient in the replyTo property, per Internet Message Format (RFC 2822), you should send the reply to the recipients in the replyTo and toRecipients properties, and not the recipients in the from and toRecipients properties.

  • You can update the draft later to add reply content to the body or change other message properties. When using MIME format:

  • Provide the applicable Internet message headers and the MIME content, all encoded in base64 format in the request body.

  • Add any attachments and S/MIME properties to the MIME content. Send the draft message in a subsequent operation. Alternatively, reply-all to a message in a single action.

Inputs: body (required), messageId (required), includeHeaders, excludeResponse.

create-reply-draftA
Destructive

Create a draft to reply to the sender of a message in either JSON or MIME format. When using JSON format:

  • Specify either a comment or the body property of the message parameter. Specifying both will return an HTTP 400 Bad Request error.

  • If replyTo is specified in the original message, per Internet Message Format (RFC 2822), you should send the reply to the recipients in replyTo, and not the recipients in from.

  • You can update the draft later to add reply content to the body or change other message properties. When using MIME format:

  • Provide the applicable Internet message headers and the MIME content, all encoded in base64 format in the request body.

  • Add any attachments and S/MIME properties to the MIME content. Send the draft message in a subsequent operation. Alternatively, reply to a message in a single operation.

Inputs: body (required), messageId (required), includeHeaders, excludeResponse.

create-specific-calendar-eventB
Destructive

Use this API to create a new event in a calendar. The calendar can be one for a user, or the default calendar of a Microsoft 365 group.

💡 TIP: CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients.

Inputs: body (required), calendarId (required), includeHeaders, excludeResponse.

create-todo-taskB
Destructive

Create a new task object in a specified todoTaskList.

Inputs: body (required), todoTaskListId (required), includeHeaders, excludeResponse.

delete-calendar-eventA
Destructive

Removes the specified event from the containing calendar. If the event is a meeting, deleting the event on the organizer's calendar sends a cancellation message to the meeting attendees.

Inputs: eventId (required), If-Match, includeHeaders, excludeResponse.

delete-mail-attachmentD
Destructive

Delete navigation property attachments for me

Inputs: messageId (required), attachmentId (required), If-Match, includeHeaders, +1 more.

delete-mail-messageB
Destructive

Delete eventMessage.

Inputs: messageId (required), If-Match, includeHeaders, excludeResponse.

delete-onedrive-fileC
Destructive

Delete navigation property items for drives

Inputs: driveId (required), driveItemId (required), If-Match, includeHeaders, +1 more.

delete-outlook-contactC
Destructive

Delete a contact.

Inputs: contactId (required), If-Match, includeHeaders, excludeResponse.

delete-specific-calendar-eventC
Destructive

Delete navigation property events for me

Inputs: calendarId (required), eventId (required), If-Match, includeHeaders, +1 more.

delete-todo-taskB
Destructive

Delete a todoTask object.

Inputs: todoTaskListId (required), todoTaskId (required), If-Match, includeHeaders, +1 more.

download-onedrive-file-contentC
Read-only

The content stream, if the item represents a file.

Inputs: driveId (required), driveItemId (required), format, fetchAllPages, +2 more.

format-excel-rangeC
Destructive

Update the navigation property format in drives

Inputs: body (required), driveId (required), driveItemId (required), workbookWorksheetId (required), +2 more.

forward-mail-messageA
Destructive

Forward a message using either JSON or MIME format. When using JSON format, you can:

  • Specify either a comment or the body property of the message parameter. Specifying both will return an HTTP 400 Bad Request error.

  • Specify either the toRecipients parameter or the toRecipients property of the message parameter. Specifying both or specifying neither will return an HTTP 400 Bad Request error. When using MIME format:

  • Provide the applicable Internet message headers and the MIME content, all encoded in base64 format in the request body.

  • Add any attachments and S/MIME properties to the MIME content. This method saves the message in the Sent Items folder. Alternatively, create a draft to forward a message, and send it later.

💡 TIP: Forward an email preserving full HTML formatting and attachments. The 'comment' field adds text above the forwarded content. toRecipients is required. Do NOT reconstruct the email manually - this endpoint handles everything server-side.

Inputs: body (required), messageId (required), includeHeaders, excludeResponse.

get-calendar-eventB
Read-only

Get the properties and relationships of the specified event object. Currently, this operation returns event bodies in only HTML format. There are two scenarios where an app can get an event in another user's calendar: Since the event resource supports extensions, you can also use the GET operation to get custom properties and extension data in an event instance.

Inputs: eventId (required), select, expand, fetchAllPages, +4 more.

get-calendar-viewA
Read-only

Get the occurrences, exceptions, and single instances of events in a calendar view defined by a time range, from the user's default calendar, or from some other calendar of the user.

💡 TIP: Returns expanded recurring event instances (not just seriesMaster) within a date range for the default calendar. Requires startDateTime and endDateTime query parameters in ISO 8601 format (e.g., 2024-01-01T00:00:00Z). Use get-specific-calendar-view if you need a non-default calendar.

Inputs: startDateTime (required), endDateTime (required), top, skip, +11 more.

get-current-userA
Read-only

Retrieve the properties and relationships of user object. This operation returns by default only a subset of the more commonly used properties for each user. These default properties are noted in the Properties section. To get properties that are not returned by default, do a GET operation for the user and specify the properties in a $select OData query option. Because the user resource supports extensions, you can also use the GET operation to get custom properties and extension data in a user instance. Customers through Microsoft Entra ID for customers can also use this API operation to retrieve their details.

Inputs: ConsistencyLevel, select, expand, fetchAllPages, +2 more.

get-drive-root-itemB
Read-only

The root folder of the drive. Read-only.

Inputs: driveId (required), select, expand, fetchAllPages, +2 more.

get-excel-rangeC
Read-only

Invoke function range

Inputs: driveId (required), driveItemId (required), workbookWorksheetId (required), address (required), +3 more.

get-mail-attachmentB
Read-only

Read the properties, relationships, or raw contents of an attachment that is attached to a user event, message, or group post. An attachment can be one of the following types: All these types of attachments are derived from the attachment resource.

Inputs: messageId (required), attachmentId (required), select, expand, +3 more.

get-mail-messageA
Read-only

Get the properties and relationships of the eventMessage object. Apply the $expand parameter on the event navigation property to get the associated event in an attendee's calendar. Currently, this operation returns event message bodies in only HTML format.

Inputs: messageId (required), select, expand, fetchAllPages, +2 more.

get-onenote-page-contentC
Read-only

The page's HTML content.

Inputs: onenotePageId (required), fetchAllPages, includeHeaders, excludeResponse.

get-outlook-contactC
Read-only

Retrieve the properties and relationships of a contact object. There are two scenarios where an app can get a contact in another user's contact folder:

Inputs: contactId (required), select, expand, fetchAllPages, +2 more.

get-planner-planB
Read-only

Retrieve the properties and relationships of a plannerplan object.

Inputs: plannerPlanId (required), select, expand, fetchAllPages, +2 more.

get-planner-taskB
Read-only

Retrieve the properties and relationships of plannerTask object.

Inputs: plannerTaskId (required), select, expand, fetchAllPages, +2 more.

get-specific-calendar-eventC
Read-only

The events in the calendar. Navigation property. Read-only.

Inputs: calendarId (required), eventId (required), select, expand, +5 more.

get-specific-calendar-viewA
Read-only

The calendar view for the calendar. Navigation property. Read-only.

💡 TIP: Returns expanded recurring event instances (not just seriesMaster) within a date range for a specific calendar. Requires startDateTime and endDateTime query parameters in ISO 8601 format (e.g., 2024-01-01T00:00:00Z). Each instance includes seriesMasterId and type (occurrence/exception) fields for recurring event linkage. Use fetchAllPages=true to retrieve all results when there are many events.

Inputs: startDateTime (required), endDateTime (required), calendarId (required), top, +12 more.

get-todo-taskB
Read-only

Read the properties and relationships of a todoTask object.

Inputs: todoTaskListId (required), todoTaskId (required), select, expand, +3 more.

list-accountsB

List all available Microsoft accounts

Inputs: no named parameters.

list-calendar-event-instancesA
Read-only

The occurrences of a recurring series, if the event is a series master. This property includes occurrences that are part of the recurrence pattern, and exceptions modified, but doesn't include occurrences canceled from the series. Navigation property. Read-only. Nullable.

💡 TIP: Expand a recurring event into individual instances within a date range. Requires startDateTime and endDateTime query parameters in ISO 8601 format (e.g., 2024-01-01T00:00:00Z). Use this to see all occurrences of a recurring event.

Inputs: startDateTime (required), endDateTime (required), calendarId (required), eventId (required), +13 more.

list-calendar-eventsA
Read-only

Get a list of event objects in the user's mailbox. The list contains single instance meetings and series masters. To get expanded event instances, you can get the calendar view, or get the instances of an event. Currently, this operation returns event bodies in only HTML format. There are two scenarios where an app can get events in another user's calendar:

Inputs: top, skip, search, filter, +9 more.

list-calendarsB
Read-only

Get all the user's calendars (/calendars navigation property), get the calendars from the default calendar group or from a specific calendar group.

Inputs: top, skip, search, filter, +7 more.

list-drivesB
Read-only

Retrieve the list of Drive resources available for a target User, Group, or Site.

Inputs: top, skip, search, filter, +7 more.

list-excel-worksheetsB
Read-only

Represents a collection of worksheets associated with the workbook. Read-only.

Inputs: driveId (required), driveItemId (required), top, skip, +9 more.

list-folder-filesB
Read-only

Return a collection of DriveItems in the children relationship of a DriveItem. DriveItems with a non-null folder or package facet can have one or more child DriveItems.

Inputs: driveId (required), driveItemId (required), top, skip, +9 more.

list-mail-attachmentsB
Read-only

Retrieve a list of attachment objects.

Inputs: messageId (required), top, skip, search, +8 more.

list-mail-child-foldersA
Read-only

Get the folder collection under the specified folder. You can use the .../me/mailFolders shortcut to get the top-level folder collection and navigate to another folder. By default, this operation does not return hidden folders. Use a query parameter includeHiddenFolders to include them in the response.

Inputs: mailFolderId (required), includeHiddenFolders, top, skip, +9 more.

list-mail-folder-messagesA
Read-only

Get all the messages in the specified user's mailbox, or those messages in a specified folder in the mailbox.

💡 TIP: CRITICAL: When searching emails, the $search parameter value MUST be wrapped in double quotes. Format: $search="your search query here". Use KQL (Keyword Query Language) syntax to search specific properties: 'from:', 'subject:', 'body:', 'to:', 'cc:', 'bcc:', 'attachment:', 'hasAttachments:', 'importance:', 'received:', 'sent:'. Examples: $search="from:john@example.com" | $search="subject:meeting AND hasAttachments:true" | $search="body:urgent AND received>=2024-01-01" | $search="from:alice AND importance:high". Remember: ALWAYS wrap the entire search expression in double quotes! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter

Inputs: mailFolderId (required), top, skip, search, +8 more.

list-mail-foldersA
Read-only

Get the mail folder collection directly under the root folder of the signed-in user. The returned collection includes any mail search folders directly under the root. By default, this operation does not return hidden folders. Use a query parameter includeHiddenFolders to include them in the response. This operation does not return all mail folders in a mailbox, only the child folders of the root folder. To return all mail folders in a mailbox, each child folder must be traversed separately.

Inputs: includeHiddenFolders, top, skip, search, +8 more.

list-mail-messagesD
Read-only

Get an open extension (openTypeExtension object) identified by name or fully qualified name. The table in the Permissions section lists the resources that support open extensions. The following table lists the three scenarios where you can get an open extension from a supported resource instance.

💡 TIP: CRITICAL: When searching emails, the $search parameter value MUST be wrapped in double quotes. Format: $search="your search query here". Use KQL (Keyword Query Language) syntax to search specific properties: 'from:', 'subject:', 'body:', 'to:', 'cc:', 'bcc:', 'attachment:', 'hasAttachments:', 'importance:', 'received:', 'sent:'. Examples: $search="from:john@example.com" | $search="subject:meeting AND hasAttachments:true" | $search="body:urgent AND received>=2024-01-01" | $search="from:john AND importance:high". Remember: ALWAYS wrap the entire search expression in double quotes! Reference: https://learn.microsoft.com/en-us/graph/search-query-parameter

Inputs: includeHiddenMessages, top, skip, search, +8 more.

list-onenote-notebooksB
Read-only

Retrieve a list of notebook objects.

Inputs: top, skip, search, filter, +7 more.

list-onenote-notebook-sectionsB
Read-only

Retrieve a list of onenoteSection objects from the specified notebook.

Inputs: notebookId (required), top, skip, search, +8 more.

list-onenote-section-pagesB
Read-only

Retrieve a list of page objects from the specified section.

Inputs: onenoteSectionId (required), top, skip, search, +8 more.

list-outlook-contactsC
Read-only

Get a contact collection from the default contacts folder of the signed-in user. There are two scenarios where an app can get contacts in another user's contact folder:

Inputs: top, skip, search, filter, +7 more.

list-planner-tasksB
Read-only

Retrieve a list of plannertask objects assigned to a User.

Inputs: top, skip, search, filter, +7 more.

list-plan-tasksB
Read-only

Retrieve a list of plannerTask objects associated with a plannerPlan object.

Inputs: plannerPlanId (required), top, skip, search, +8 more.

list-specific-calendar-eventsC
Read-only

The events in the calendar. Navigation property. Read-only.

Inputs: calendarId (required), top, skip, search, +10 more.

list-todo-task-listsB
Read-only

Get a list of the todoTaskList objects and their properties.

Inputs: top, skip, search, filter, +7 more.

list-todo-tasksB
Read-only

Get the todoTask resources from the tasks navigation property of a specified todoTaskList.

Inputs: todoTaskListId (required), top, skip, search, +8 more.

loginA

Authenticate with Microsoft using device code flow

Inputs: force.

logoutB

Log out from Microsoft account

Inputs: no named parameters.

move-mail-messageA
Destructive

Move a message to another folder within the specified user's mailbox. This creates a new copy of the message in the destination folder and removes the original message.

Inputs: body (required), messageId (required), includeHeaders, excludeResponse.

remove-accountC

Remove a Microsoft account from the cache

Inputs: accountId (required).

reply-all-mail-messageA
Destructive

Reply to all recipients of a message using either JSON or MIME format. When using JSON format:

  • Specify either a comment or the body property of the message parameter. Specifying both will return an HTTP 400 Bad Request error.

  • If the original message specifies a recipient in the replyTo property, per Internet Message Format (RFC 2822), send the reply to the recipients in replyTo and not the recipient in the from property. When using MIME format:

  • Provide the applicable Internet message headers and the MIME content, all encoded in base64 format in the request body.

  • Add any attachments and S/MIME properties to the MIME content. This method saves the message in the Sent Items folder. Alternatively, create a draft to reply-all to a message and send it later.

💡 TIP: Reply-all preserving full HTML formatting. The 'comment' field is your reply text.

Inputs: body (required), messageId (required), includeHeaders, excludeResponse.

reply-mail-messageA
Destructive

Reply to the sender of a message using either JSON or MIME format. When using JSON format:

  • Specify either a comment or the body property of the message parameter. Specifying both will return an HTTP 400 Bad Request error.

  • If the original message specifies a recipient in the replyTo property, per Internet Message Format (RFC 2822), send the reply to the recipients in replyTo and not the recipient in the from property. When using MIME format:

  • Provide the applicable Internet message headers and the MIME content, all encoded in base64 format in the request body.

  • Add any attachments and S/MIME properties to the MIME content. This method saves the message in the Sent Items folder. Alternatively, create a draft to reply to an existing message and send it later.

💡 TIP: Reply to an email preserving full HTML formatting. The 'comment' field is your reply text. Do NOT reconstruct the email manually.

Inputs: body (required), messageId (required), includeHeaders, excludeResponse.

search-queryB
Destructive

Runs the query specified in the request body. Search results are provided in the response.

Inputs: body (required), includeHeaders, excludeResponse.

select-accountC

Select a specific Microsoft account to use

Inputs: accountId (required).

send-draft-messageC
Destructive

Send an existing draft message. The draft message can be a new message draft, reply draft, reply-all draft, or a forward draft. This method saves the message in the Sent Items folder. Alternatively, send a new message in a single operation.

Inputs: messageId (required), includeHeaders, excludeResponse.

send-mailA
Destructive

Send the message specified in the request body using either JSON or MIME format. When using JSON format, you can include a file attachment in the same sendMail action call. When using MIME format: This method saves the message in the Sent Items folder. Alternatively, create a draft message to send later. To learn more about the steps involved in the backend before a mail is delivered to recipients, see here.

💡 TIP: CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients.

Inputs: body (required), includeHeaders, excludeResponse.

sort-excel-rangeC
Destructive

Update the navigation property sort in drives

Inputs: body (required), driveId (required), driveItemId (required), workbookWorksheetId (required), +2 more.

update-calendar-eventC
Destructive

Update the properties of the event object.

💡 TIP: CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients.

Inputs: body (required), eventId (required), includeHeaders, excludeResponse.

update-mail-messageC
Destructive

Update the properties of an eventMessage object.

Inputs: body (required), messageId (required), includeHeaders, excludeResponse.

update-outlook-contactC
Destructive

Update the properties of a contact object.

Inputs: body (required), contactId (required), includeHeaders, excludeResponse.

update-planner-taskC
Destructive

Update the properties of plannerTask object.

Inputs: body (required), If-Match (required), plannerTaskId (required), includeHeaders, +1 more.

update-planner-task-detailsB
Destructive

Update the properties of plannerTaskDetails object.

Inputs: body (required), If-Match (required), plannerTaskId (required), includeHeaders, +1 more.

update-specific-calendar-eventC
Destructive

Update the navigation property events in me

💡 TIP: CRITICAL: Do not try to guess the email address of the recipients. Use the list-users tool to find the email address of the recipients.

Inputs: body (required), calendarId (required), eventId (required), includeHeaders, +1 more.

update-todo-taskC
Destructive

Update the properties of a todoTask object.

Inputs: body (required), todoTaskListId (required), todoTaskId (required), includeHeaders, +1 more.

upload-file-contentD

The content stream, if the item represents a file.

Inputs: body (required), driveId (required), driveItemId (required), includeHeaders, +1 more.

verify-loginA

Check current Microsoft authentication status

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.7/5.0

    Scored across 78 tools

    Disambiguation3/5

    Tools are generally distinct by resource and action, but there is significant overlap in email operations (e.g., create-reply-draft vs. reply-mail-message) and calendar events (e.g., create-calendar-event vs. create-specific-calendar-event), which could cause confusion. Descriptions help clarify, but the sheer number of similar tools increases ambiguity.

    Naming Consistency4/5

    Most tools follow a consistent verb_noun pattern (e.g., create-calendar-event, delete-mail-attachment), with clear actions and resources. Minor deviations exist (e.g., login, logout, search-query are less structured), but overall naming is predictable and readable across the set.

    Tool Count2/5

    With 78 tools, the count is excessive for a single server, making it overwhelming and difficult to navigate. While Microsoft 365 is a broad domain, this many tools suggests poor scoping, likely leading to agent confusion and inefficiency in tool selection.

    Completeness5/5

    The tool set provides comprehensive coverage across Microsoft 365 services (e.g., Mail, Calendar, OneDrive, Planner, To-Do), including full CRUD operations, authentication, and specialized actions like search and file management. No obvious gaps are present for the domain's core workflows.

    Related MCP Connectors