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

outlook-file-attach-mcp

v2.0.0

Published

MCP server that attaches local files to Outlook draft emails for the signed-in user via Microsoft Graph (delegated auth, shared MSAL token cache).

Readme

Outlook File Attach MCP Server (v2)

A lightweight MCP server that attaches local files to Outlook draft emails on behalf of the signed-in user via the Microsoft Graph API.

Why this exists

MCP-based email tools like @softeria/ms-365-mcp-server require file content to be passed as base64 through tool parameters. For files larger than ~50KB, this exceeds what an LLM can output in a single tool call. This server solves the problem by accepting a local file path instead — it reads the file from disk, encodes it, and uploads it directly to Graph.

What changed in v2

v2 is a clean rewrite that switches from application credentials (one shared client secret across users) to delegated authentication (each user's own OAuth token).

| | v1 | v2 | |---|---|---| | Auth model | Application (client_credentials) | Delegated (PKCE + device code) | | Client secret | Required | Not used | | Mailbox scope | Any mailbox the app's ApplicationAccessPolicy allows | The signed-in user's own mailbox | | userEmail tool parameter | Required | Removed — implicit | | Endpoint | /users/{userEmail}/messages/... | /me/messages/... | | Token cache | None (re-auth every call) | Persistent file cache, shareable with @softeria |

The result: no shared secret to distribute, no ApplicationAccessPolicy, no security group, no per-rep blast radius beyond the rep's own mailbox.

Requirements

  • Node.js 18+
  • An Azure AD app registration with:
    • Authentication → "Allow public client flows" set to Yes
    • A Mobile and desktop applications platform with redirect URI http://localhost
    • Delegated Microsoft Graph permissions: Mail.ReadWrite, Mail.Send (admin consent recommended)
    • No client secret required

The same Azure AD app can serve both this server and @softeria/ms-365-mcp-server.

Configuration

Three environment variables:

| Variable | Required | Description | |---|---|---| | MS365_MCP_CLIENT_ID | Yes | Application (client) ID of the Azure AD app | | MS365_MCP_TENANT_ID | Yes | Directory (tenant) ID | | MS365_MCP_TOKEN_CACHE_PATH | No | Path to the persisted token cache file. Defaults to ${LOCALAPPDATA}\ms-365-mcp-server\tokens.json on Windows, ~/.config/ms-365-mcp-server/tokens.json elsewhere. Supports ${VAR} expansion. |

The default cache path matches @softeria/ms-365-mcp-server's convention. When both servers are configured with the same MS365_MCP_TOKEN_CACHE_PATH (or both rely on the default), they share a single login session.

MCP host config example

{
  "ms365": {
    "command": "npx",
    "args": ["-y", "@softeria/ms-365-mcp-server", "--preset", "mail"],
    "env": {
      "MS365_MCP_CLIENT_ID": "your-client-id",
      "MS365_MCP_TENANT_ID": "your-tenant-id"
    }
  },
  "outlook-file-attach": {
    "command": "npx",
    "args": ["-y", "outlook-file-attach-mcp"],
    "env": {
      "MS365_MCP_CLIENT_ID": "your-client-id",
      "MS365_MCP_TENANT_ID": "your-tenant-id"
    }
  }
}

No client secret in either entry. Both MCPs target the same Azure AD app and share a single token cache.

First-time sign-in

Before the MCP server can act, a token must exist in the cache. The simplest path is to use @softeria/ms-365-mcp-server's --login mode, which populates the shared cache and serves both servers:

# Set env vars for this one-shot session
export MS365_MCP_CLIENT_ID=your-client-id
export MS365_MCP_TENANT_ID=your-tenant-id

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

Or use this server's own --login mode:

npx -y outlook-file-attach-mcp --login

Either prints a Microsoft device code to the terminal. Open the URL it gives, enter the code, sign in, return to the terminal — login success is reported and the cache file is written. After that, both MCP servers acquire tokens silently.

Tool

The server provides one tool: attach-file-to-email

| Parameter | Type | Required | Description | |---|---|---|---| | messageId | string | Yes | Outlook message ID of the draft to attach to | | filePath | string | Yes | Absolute path to the local file | | fileName | string | No | Custom filename for the attachment (defaults to original) |

The mailbox is implicitly the signed-in user's. There is no userEmail parameter.

How it works

  1. The LLM calls attach-file-to-email with a draft message ID and a local file path.
  2. The server acquires an access token silently using the cached refresh token (no user interaction).
  3. It reads the file from disk, base64-encodes it, builds a fileAttachment payload.
  4. It POSTs to https://graph.microsoft.com/v1.0/me/messages/{messageId}/attachments.
  5. The attachment appears on the user's draft, ready to send.

If silent token acquisition fails (no cache, refresh token expired, account removed), the tool returns an actionable error pointing the user at --login.

Limitations

  • 4 MB per attachment — Microsoft Graph's single-request upload limit. Larger files require the resumable upload session API; not currently implemented.
  • Drafts only — The tool attaches to existing draft messages identified by messageId. It does not create the draft itself; pair it with @softeria/ms-365-mcp-server's create-draft-email tool for that.
  • Single account — If the token cache holds multiple accounts, this server uses the first one it finds. Multi-account selection is not yet supported.