ms-365-mcp-server について
ms-365-mcp-serverは、Microsoft Graph APIを通じてMicrosoft 365とOfficeのサービスをMCPクライアントに提供します。読み取り専用モード、ツールの絞り込み、権限範囲の制限により、用途に応じて利用可能な機能を調整できます。
主な機能
- 01300以上のGraph APIツール
- 02メール、カレンダー、OneDriveに対応
- 03組織モードでTeamsとSharePointを提供
- 04読み取り専用モードとツールの絞り込み
- 05有効なツールに応じた権限の算出
- 06JSONと実験的なTOON出力
活用シーン
- 01MCPクライアントからOutlookのメールや予定にアクセス
- 02OneDriveファイルやPlannerタスクの管理
- 03組織モードでTeamsとSharePointを利用
- 04導入前に必要なGraph権限を確認
MCP 対応
Microsoft Graphが扱うMicrosoft 365とOfficeのサービスを、ツールとしてMCPクライアントに公開するMCPサーバーです。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
188掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| force | boolean | いいえ | すでにログインしている場合でも、再ログインを強制します |
詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
ms-365-mcp-server
Microsoft 365 MCP サーバー
Graph API を通じて Microsoft 365 および Microsoft Office サービスと連携する Model Context Protocol(MCP)サーバーです。
対応クラウド
このサーバーは、複数の Microsoft クラウド環境に対応しています。
| クラウド | 説明 | 認証エンドポイント | Graph API エンドポイント |
|---|---|---|---|
| Global(既定) | 国際版 Microsoft 365 | login.microsoftonline.com | graph.microsoft.com |
| China(21Vianet) | 21Vianet が運営する Microsoft 365 | login.chinacloudapi.cn | microsoftgraph.chinacloudapi.cn |
| GCC High | 米国政府機関向け Microsoft 365 GCC High | login.microsoftonline.us | graph.microsoft.us |
GCC High には事前登録済みのクライアントがありません。政府機関テナントでアプリを登録し、MS365_MCP_CLIENT_ID(および MS365_MCP_TENANT_ID)を設定してから、--cloud gcc-high を使用してください。
Graph の通信を独自のプロキシ(クライアントからのプレーン HTTP を終端し、Microsoft への TLS 通信を開始するプロキシ)経由にするには、MS365_MCP_GRAPH_BASE_URL にプロキシのベース URL を設定してください。迂回される通信を含む詳細については、CLI オプションの環境変数一覧を参照してください。
前提条件
- Node.js >= 20(推奨)
- Node.js 14 以降でも動作する可能性がありますが、依存関係に関する警告が表示される場合があります
機能
- Microsoft Authentication Library(MSAL)による認証
- Microsoft 365 サービスとの包括的な連携
- 安全な操作のための読み取り専用モード対応
- きめ細かなアクセス制御を可能にするツールのフィルタリング
- ツールの範囲とトークン使用量を削減するためのツールプリセットと動的検出
出力形式:JSON と TOON
サーバーでは、全体に適用する出力形式を設定できます。
JSON 形式(既定)
整形表示された標準の JSON 出力:
{
"value": [
{
"id": "1",
"displayName": "Alice Johnson",
"mail": "[email protected]",
"jobTitle": "Software Engineer"
}
]
}
(実験的)TOON 形式
LLM のトークンを効率的に使用するためのToken-Oriented Object Notation:
value[1]{id,displayName,mail,jobTitle}:
"1",Alice Johnson,[email protected],Software Engineer
メリット:
- JSON と比べてトークン数を 30~60%削減
- 均一な配列データ(メール、カレンダーのイベント、ファイルなどの一覧)に最適
- 大規模な利用においてコストを重視するアプリケーションに最適
使用方法: (実験的)TOON 形式を全体で有効にします。
CLI フラグを使用する場合:
npx @softeria/ms-365-mcp-server --toon
Claude Desktop の設定を使用する場合:
{
"mcpServers": {
"ms365": {
"command": "npx",
"args": ["-y", "@softeria/ms-365-mcp-server", "--toon"]
}
}
}
環境変数を使用する場合:
MS365_MCP_OUTPUT_FORMAT=toon npx @softeria/ms-365-mcp-server
対応サービスとツール
このサーバーは、Microsoft Graph API の大部分をカバーする 300 以上のツールを提供します。各ツールは Graph API エンドポイントと 1 対 1 で対応し、src/endpoints.json で宣言的に定義されています。
個人アカウント向けツール(既定で利用可能)
メール(Outlook)、カレンダー、OneDrive ファイル、Excel、OneNote、To Do タスク、Planner、連絡先、ユーザープロファイル、検索
組織アカウント向けツール(--org-mode フラグが必要)
チームとチャット、オンライン会議、トランスクリプトと録画、出席レポート、SharePoint サイトとリスト、共有メールボックスとカレンダー、ユーザー管理、プレゼンス、バーチャルイベント
組織モードでは、list-custom-emojis と create-custom-emoji(teams および work プリセット)を使って、カスタム Teams 絵文字を利用できます。これらは Microsoft Graph のベータ API を使用し、それぞれ委任された権限 TeamworkCustomEmoji.Read と TeamworkCustomEmoji.Create を要求します。読み取り専用モードでは、リストツールのみが公開されます。既存のデプロイでは、これらの新しいスコープに対する同意と再認証が必要になる場合があります。ツールのサポートを追加しても、すでに発行されたトークンは更新されません。
一覧取得では、デフォルトで contentBytes: null が返されることがあります。base64 PNG/GIF 画像を要求するには、select: "displayName,contentBytes" または select: ["displayName", "contentBytes"] を渡してください。画像レスポンスを扱いやすいサイズに保つには、小さな top を指定してください。
絵文字を作成するには、正確に承認された名前と base64 PNG/GIF ファイルのバイトデータを指定して、body: { displayName, contentBytes } を渡してください。Microsoft のlistおよびcreateの仕様を参照してください。これらのツールはメッセージやリアクションを投稿しません。
必要な Graph API 権限
有効にするツールに応じて、必要な権限が動的に要求されます。--list-permissions を使用すると、設定に必要な正確な権限を確認できます。
# Personal mode (default)
npx @softeria/ms-365-mcp-server --list-permissions
# Organization mode (includes Teams, SharePoint, etc.)
npx @softeria/ms-365-mcp-server --org-mode --list-permissions
# Filtered by preset
npx @softeria/ms-365-mcp-server --preset mail --list-permissions
これは、新しいバージョンをデプロイする前に Graph API 権限を事前承認し、管理者の同意を得る必要があるエンタープライズ環境で役立ちます。
--list-permissions の JSON には、以下が含まれます。
toolPermissions:--allowed-scopesによるフィルタリング前に、ツールの構成から必要とされる権限effectivePermissions:--allowed-scopes適用後も有効になっているツールから必要とされる権限permissions:既存のスクリプトとの互換性を保つために維持されている、effectivePermissionsのレガシーエイリアスallowedScopes:指定されている場合、設定されたスコープの許可リストdisabledTools:必要な Graph スコープがallowedScopesに含まれていないため、非表示になっているツールmissingAllowedScopesForTools:無効になっているツールに不足しているスコープの一覧(重複なし)extraAllowedScopesNotUsedByTools:許可リストに含まれているものの、現在のツール構成では使用されないスコープ
許可されたスコープ
デフォルトでは、MSAL は有効なツールから推測されるスコープをリクエストし、ツールの公開範囲は --enabled-tools、--preset、--org-mode、--read-only によって制御されます。
エンタープライズ環境やヘッドレス環境では、--allowed-scopes または MS365_MCP_ALLOWED_SCOPES を使ってスコープの境界を追加できます。設定すると、サーバーはまず通常のツール公開範囲を計算し、その後、必要なスコープが許可リストでカバーされていない Graph ツールを非表示にします。OAuth メタデータとログインフローでは、有効な状態で残っているツールに必要な権限のみがリクエストされます。
npx @softeria/ms-365-mcp-server \
--org-mode \
--enabled-tools '^(list-mail-messages|get-mail-message|list-drives|get-drive-item|download-bytes)$' \
--allowed-scopes 'User.Read Mail.Read Files.Read'
CLI の値は MS365_MCP_ALLOWED_SCOPES より優先されます。どちらも設定されていない場合は、デフォルトのツール由来のスコープ動作が変更されずに維持されます。空の値を指定すると起動時にエラーになるため、デプロイ時に意図せず、より広いツール公開範囲にフォールバックすることはありません。
スコープのカバー範囲は階層を考慮します。たとえば、Mail.ReadWrite は Mail.Read を必要とするツールをカバーし、Files.ReadWrite.All は Files.Read を必要とするツールをカバーします。
SharePoint では、次の 2 つのエンタープライズ権限モデルがサポートされています。
Sites.Read.All、Sites.ReadWrite.All、Sites.Manage.Allなどの広範なテナントスコープ。- Microsoft Graph の
Sites.Selected。特定のサイトコレクションに対する SharePoint サイトへのアクセス権をアプリに付与し、Graph がリクエスト時にサインインしたユーザー自身の権限を評価します。
デフォルトの org-mode の動作では、既存のデプロイで使用されている広範な SharePoint スコープが引き続きリクエストされます。選択したサイトへの SharePoint アクセスを希望するエンタープライズでは、広範な Sites.*.All スコープの代わりに、Sites.Selected を含む許可リストを設定できます。明示的な SharePoint サイトを対象とする直接のサイト/リスト/アイテムツールと、付与されたサイトのドライブに対する /drives/{drive-id}/... のアイテムツール(一覧表示、取得、アップロード、フォルダー、移動/名前変更、コピー、バージョン)は、Sites.Selected で実行できます。テナント全体を対象とする SharePoint の探索および検索ツールには、引き続き広範な SharePoint スコープが必要です。
npx @softeria/ms-365-mcp-server \
--org-mode \
--read-only \
--enabled-tools 'sharepoint|site|drive|planner' \
--allowed-scopes 'User.Read Files.Read Notes.Read Tasks.Read Sites.Selected'
HTTP モードでは、OAuth ディスカバリーがフィルタリング後の有効な権限を通知するため、クライアントは同じ同意対象をリクエストします。On-Behalf-Of モード(--obo)では、保護対象リソースのメタデータに <clientId>/access_as_user が引き続き通知され、/authorize でもこの権限がリクエストされます。--allowed-scopes は OBO に適用されず、ツールの公開範囲を狭めるためにのみ使用されます。
ユーザープロファイルフィールドの制限
デプロイでは、--user-fields または MS365_MCP_USER_FIELDS を使って、選択したユーザーディレクトリのパスに対するカンマ区切りのフィールドフィルターを設定できます。このフィルターは、/users の読み取り時に Microsoft Graph へ送信される $select の範囲を狭め、以下に示す対象パスのレスポンスから指定外のフィールドを除外します。これはパス固有のデータフィルターであり、Graph の完全な認可境界ではありません。ほかの Graph ルートやリソース形式から、重複するプロファイルデータにアクセスできる場合があります。
npx @softeria/ms-365-mcp-server \
--org-mode \
--user-fields 'id,displayName,mail,userPrincipalName'
フィルターはツール名ではなく、既知の Graph パスを基準に適用されます。直接呼び出すツール、ディスカバリーモードの execute-tool、および条件に一致する graph-batch サブリクエストに適用されます。バッチサブリクエストの URL は、対象となる /users の読み取りで書き換えられ、すべての対象プロファイルパスでレスポンスから指定外のフィールドが除外されます。バイトをそのまま返すツール(download-bytes、download-bytes-to-file、get-download-url)はレスポンスを変更せず返すため、フィルターが有効な間は、対象のユーザープロファイルパスに一致する対象を拒否します。
Graph が返す内容に応じて、次の2段階の適用が行われます。
| パス | 適用方法 |
|---|---|
/users、/users/{id} | リクエストの $select の範囲を狭め、レスポンスから指定外のフィールドを除外するため、除外対象のフィールドがテナントの外に出ることはありません |
/me/manager、/me/directReports、/users/{id}/manager、/users/{id}/directReports、/groups/{id}/members、/groups/{id}/owners | レスポンスから指定外のフィールドを除外します。これらは directoryObject 型です。Graph で jobTitle のようなユーザー専用プロパティを $select するには OData キャストが必要なため、リクエストの範囲を狭めると、現在正常に動作している呼び出しに支障をきたすおそれがあります |
フィルターが有効な間、関連するユーザープロファイルを展開できるリソースであるため、/me、/groups、/groups/{id} へのリクエストから $expand が削除されます。これは条件に一致するバッチサブリクエストにも適用されます。それ以外の /me およびグループの基本レスポンスからは、指定外のフィールドは除外されません。
このフィルターは、ユーザー形式のオブジェクトを返すすべてのルートを対象とするものではありません。特に、一般的な Graph アクセスを使えば、/directoryObjects/{id}、/groups/{id}/transitiveMembers、/users('{id}') などの別ルートや別形式に引き続きアクセスできます。これらは現在、対象パスに正規化されていません。この設定がセキュリティ要件である場合は、一般的な Graph アクセス(たとえば graph-batch)も制限し、デプロイで実際に利用できるツールの範囲を検証してください。テナント全体のデータアクセス制御として --user-fields だけに依存しないでください。
/users/{id}/messages や /users/{id}/photo/$value のようなユーザー配下のリソースは、プロファイルプロパティではなく、メール、カレンダー、バイナリのリソースであるため、このフィルターの影響を受けません。サインイン中のユーザー自身の /me プロファイルも影響を受けません。また、ユーザープロファイルではなく conversationMember を返す Teams およびチャットのメンバーリストも影響を受けません。
既知の制限:list-relevant-people
list-relevant-people(/me/people)は対象外です。このツールはpersonリソースを返します。これはuserとは異なる型で、プロパティが一部しか重複していません。jobTitle、department、officeLocationを含みますが、アドレスはmailではなくscoredEmailAddressesとして返されます。ユーザーフィールドの許可リストを適用すると、有効なフィールド名が拒否され、ツールで利用できない範囲に結果が絞られてしまいます。
people サーフェスも閉じる必要があるデプロイ環境では、たとえば--enabled-toolsを使うか、このツールを除外するプリセットを選択して、サーフェスからツールを削除してください。
npx @softeria/ms-365-mcp-server \
--org-mode \
--user-fields 'id,displayName,mail' \
--enabled-tools '^(?!list-relevant-people$).*'
CLI の値は環境変数より優先されます。フィールドが指定されていない値の場合、起動時に失敗します。どちらも設定されていない場合は、従来の動作が変更されません。この設定は LibreChat MCP サーバーの環境変数またはコマンド引数で行ってください。プロジェクトローカルの.envファイルはアプリケーションの認証情報にのみ使用するよう意図的に制限されており、この設定には使用されません。
許可リストには、ユーザープロパティをすべて指定する必要があります。通常の$selectとは異なり、リストに含まれていない限りidは返されないため、後続のツールでユーザーを指定する必要がある場合は含めてください。@odata.nextLinkなどのコレクションのアノテーションは保持されるため、ページングは引き続き機能します。Graph が許可リストに含まれるプロパティを返さない場合、レスポンスはトリミングされずに返されるのではなく、空に投影されます。
追加スコープのリクエスト
--allowed-scopesは、トークンリクエストの範囲を狭めるためにのみ使用されます。バンドルされたツールが必要としない Graph スコープ(たとえばgraph-batch経由でエンドポイントを呼び出すためのスコープ)をリクエストするには、--extra-scopes(またはMS365_MCP_EXTRA_SCOPES)を使用してください。これらのスコープは、ツールから導出されたスコープに追加され、そのままトークンリクエストに加えられます。
npx @softeria/ms-365-mcp-server \
--org-mode \
--extra-scopes 'CopilotPackages.ReadWrite.All'
これは、独自の Azure アプリ登録(MS365_MCP_CLIENT_ID/MS365_MCP_CLIENT_SECRET)を使用する場合の設定です。既定の Softeria アプリで宣言されている権限セットは最小限で固定されているため、追加のスコープはご自身で管理するアプリに対してリクエストしてください(テナント管理者がそのアプリで同意します)。CLI の値は環境変数より優先されます。空の値の場合、起動時に失敗します。
組織/職場モード
Teams、SharePoint などの職場/学校向け機能にアクセスするには、次のいずれかのフラグを使って組織モードを有効にしてください。
{
"mcpServers": {
"ms365": {
"command": "npx",
"args": ["-y", "@softeria/ms-365-mcp-server", "--org-mode"]
}
}
}
職場アカウントの機能にアクセスするには、起動時から組織モードを有効にする必要があります。このフラグがない場合、個人アカウントの機能(メール、カレンダー、OneDrive など)のみ利用できます。
共有メールボックスへのアクセス
共有メールボックスにアクセスするには、次のものが必要です。
- 組織モード:共有メールボックスのツールには
--org-modeフラグが必要です(職場/学校アカウントのみ)。 - 委任されたアクセス許可:読み取りには
Mail.Read.Shared、メッセージの作成、更新、移動にはMail.ReadWrite.Shared、送信、返信、転送にはMail.Send.Shared、共有カレンダーのツールにはCalendars.Read.Sharedが必要です。 - Exchange のアクセス許可:サインインしているユーザーに共有メールボックスへのアクセス権が付与されている必要があります。
- 使用方法:共有メールボックスのツールで、
user-idパラメーターに共有メールボックスのメールアドレスを指定してください。
共有メールボックスを見つける:list-usersツールを使用して、組織内で利用可能なユーザーと共有メールボックスを確認してください。
例:user-idに[email protected]を指定したlist-shared-mailbox-messages
クイックスタートの例
Claude Desktop でログインをテストします。
例
統合
Claude Desktop
この MCP サーバーを Claude Desktop に追加するには、「設定」>「開発者」にある設定ファイルを編集してください。
個人アカウント(MSA)
{
"mcpServers": {
"ms365": {
"command": "npx",
"args": ["-y", "@softeria/ms-365-mcp-server"]
}
}
}
職場/学校アカウント(グローバル)
{
"mcpServers": {
"ms365": {
"command": "npx",
"args": ["-y", "@softeria/ms-365-mcp-server", "--org-mode"]
}
}
}
職場/学校アカウント(中国 21Vianet)
{
"mcpServers": {
"ms365-china": {
"command": "npx",
"args": ["-y", "@softeria/ms-365-mcp-server", "--org-mode", "--cloud", "china"]
}
}
}
Claude Code CLI
個人アカウント(MSA)
claude mcp add ms365 -- npx -y @softeria/ms-365-mcp-server
職場/学校アカウント(グローバル)
# 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 アカウント(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"
MCP をサポートするその他のインターフェースについては、正しい統合方法を各インターフェースのドキュメントで確認してください。
Open WebUI
Open WebUI は、OAuth 2.1 を使用した HTTP トランスポート経由で MCP サーバーをサポートしています。
-
HTTP モードでサーバーを起動します:
npx @softeria/ms-365-mcp-server --http -
Open WebUI で、Admin Settings → Tools(
/admin/settings/tools)→ Add Connection に移動します:- Type:MCP Streamable HTTP
- URL:
/mcpパスを含む MCP サーバーの URL - Auth:OAuth 2.1
-
Register Client をクリックします。
注:HTTP モードでは、動的クライアント登録がデフォルトで有効になっています。無効にするには、
--no-dynamic-registrationを使用するか、MS365_MCP_DISABLE_DCR=trueを設定してください。カスタムの Azure Entra アプリを使用する場合、リダイレクト URI のプラットフォームの種類は、アプリにクライアントシークレットがあるかどうかによって異なります。シークレットがある場合は「Web」、ない場合は「Mobile and desktop applications」を使用してください(「Single-page application」は使用しないでください)。
クイックテストのセットアップ:デフォルトの Azure アプリを使用します(ID ms-365 と localhost:8080 は事前設定済みです)。
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
続いて、URL http://localhost:3000/mcp、ID ms-365 で接続を追加します。
リバースプロキシの背後で Docker を実行していますか? OAuth の認証 URL をユーザーのブラウザーからコンテナーネットワークの外部にアクセスできるようにするには、
--public-url https://your-domain.comを設定してください。詳しい手順については、docs/deployment.md を参照してください。
ローカル開発
ローカル開発やテストの場合:
# From the project directory
claude mcp add ms -- npx tsx src/index.ts --org-mode
または、Claude Desktop を手動で設定します:
{
"mcpServers": {
"ms365": {
"command": "node",
"args": ["/absolute/path/to/ms-365-mcp-server/dist/index.js", "--org-mode"]
}
}
}
注:コードを変更した後は、
npm run buildを実行してdist/フォルダーを更新してください。
認証
⚠️ ツールを使用する前に、認証が必要です。
このサーバーは、3 つの認証方法をサポートしています:
1. デバイスコードフロー(デフォルト)
デバイスコードによる対話型認証の場合:
- MCP クライアントでのログイン:
loginツールを呼び出します(既存のトークンを自動確認します)- 必要に応じて URL とコードを取得し、ブラウザーでアクセスします
verify-loginツールを使って確認します
- CLI でのログイン:
ターミナルに表示される URL とコードの案内に従います。npx @softeria/ms-365-mcp-server --login
トークンは OS の認証情報ストアに安全にキャッシュされます(利用できない場合はファイルに保存されます)。
2. OAuth 認可コードフロー(HTTP モードのみ)
--http を指定して実行する場合、サーバーでは OAuth 認証が必須です:
npx @softeria/ms-365-mcp-server --http 3000
このモードでは:
- MCP クライアントに OAuth の機能を通知します
/auth/*に OAuth エンドポイント(authorize、token、metadata)を提供します- すべての MCP リクエストで
Authorization: Bearer <token>を必須とします - Microsoft Graph API でトークンを検証します
- デフォルトでログイン/ログアウトツールを無効にします(有効にするには
--enable-auth-toolsを使用してください)
MCP クライアントは、通知された機能を検出すると、OAuth フローを自動的に処理します。
OAuth テスト用の Azure AD の設定
カスタム Azure 認証情報を使用して OAuth モードを利用するには(本番環境では推奨)、Azure AD アプリ登録を設定する必要があります。
- Azure AD アプリ登録を作成する:
- Azure Portal に移動します
- Azure Active Directory → アプリの登録 → 新規登録に移動します
- 名前を「MS365 MCP Server」に設定します
- リダイレクト URI を設定する:
- OAuth コールバック URI を設定する:アプリ登録に移動し、左側の[認証]を選択します。
- [プラットフォームの構成]で:
- (「モバイルとデスクトップ アプリケーション」/「パブリック クライアント」の構成がまだ表示されていない場合は)[プラットフォームを追加]をクリックします。
- [モバイルとデスクトップ アプリケーション]または[パブリック クライアント/ネイティブ(モバイルとデスクトップ)]を選択します(ラベルはポータルのバージョンによって異なります)。
- MCP Inspector でテストする(
npm run inspector):
- アプリ登録に移動し、左側の[認証]を選択します。
- [プラットフォームの構成]で:
- (「Web」の構成がまだ表示されていない場合は)[プラットフォームを追加]をクリックします。
- [Web]を選択します。
- 次のリダイレクト URI を設定します
http://localhost:6274/oauth/callbackhttp://localhost:6274/oauth/callback/debughttp://localhost:3000/callback(任意。サーバーコールバック用)
- 認証情報を取得する:
- [概要]ページから アプリケーション(クライアント)ID をコピーします
- [証明書とシークレット]→[新しいクライアント シークレット]に移動し、シークレット値をコピーします(パブリック アプリでは任意)
- 環境変数を設定する:
プロジェクトのルートに
.envファイルを作成します。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
これらを設定すると、サーバーは組み込みのアプリではなく、カスタム Azure アプリを使用します。
注:
.envはサーバーの起動ディレクトリから読み込まれます。そのディレクトリは MCP クライアントによって決まります。読み込まれるのはMS365_MCP_CLIENT_ID、MS365_MCP_CLIENT_SECRET、MS365_MCP_TENANT_ID、MS365_MCP_CLOUD_TYPEのみです。上記のその他の変数は、シェルまたは MCP クライアントの設定で設定する必要があります。.env内で見つかったその他の変数は、stderr に警告を出して無視されます。
3. 独自のトークンを使用する(BYOT)
Microsoft OAuth トークンを外部で管理する大規模なシステムの一部として ms-365-mcp-server を実行している場合は、アクセストークンをこの MCP サーバーに直接渡すことができます。
MS365_MCP_OAUTH_TOKEN=your_oauth_token npx @softeria/ms-365-mcp-server
この方法では:
- 対話型の認証フローを回避します
- 既存の OAuth トークンを Microsoft Graph API リクエストに使用します
- トークンの更新は行いません(トークンのライフサイクル管理は利用者の責任です)
注:HTTP モードでは認証が必要です。認証なしでテストする場合は、デバイスコードフローを使用する stdio モードを利用してください。
認証ツール:HTTP モードでは、OAuth が認証を処理するため、ログイン/ログアウトツールはデフォルトで無効になっています。これらを利用する必要がある場合は、
--enable-auth-toolsを使用してください。
複数アカウントのサポート
1 つのサーバーインスタンスで複数の Microsoft アカウントに対応できます。複数のアカウントでログインすると、すべてのツールに account パラメーターが自動的に追加され、ツール呼び出しごとに使用するアカウントを指定できます。
複数のアカウントでログインする(アカウントごとに 1 回):
# Login first account (device code flow)
npx @softeria/ms-365-mcp-server --login
# Follow the device code prompt, sign in as [email protected]
# Login second account
npx @softeria/ms-365-mcp-server --login
# Follow the device code prompt, sign in as [email protected]
設定済みのアカウントを一覧表示する:
npx @softeria/ms-365-mcp-server --list-accounts
ツール呼び出しで使用する:任意のツールリクエストに "account": "[email protected]" を渡します:
{ "tool": "list-mail-messages", "arguments": { "account": "[email protected]" } }
動作:
- 単一アカウントが設定されている場合は、自動的に選択されます(
accountパラメーターは不要です)。 - 複数のアカウントが設定されていて
accountパラメーターが指定されていない場合、サーバーは選択済みのデフォルトアカウントを使用するか、利用可能なアカウントを一覧表示するわかりやすいエラーを返します。 - 完全な後方互換性:既存の単一アカウント設定は変更なく動作します。
accountパラメーターには、メールアドレス(例:[email protected])または MSAL のhomeAccountIdを指定できます。
厳密なアカウント固定
ヘッドレスの stdio デプロイでは、ローカル MSAL キャッシュを想定する 1 つの Microsoft アカウントに固定できます。
# Username matching is case-insensitive
[email protected] npx @softeria/ms-365-mcp-server --login
# Or pin the exact MSAL homeAccountId shown by --list-accounts
npx @softeria/ms-365-mcp-server --expected-home-account-id <homeAccountId> --login
--list-accounts を使用して homeAccountId の値を確認してください。MCP の list-accounts ツールでは意図的にアカウント ID を非表示にしているため、正確な ID を指定して固定する場合は CLI を使用してください。
アカウント固定はオプトインで、ローカル MSAL でのみ有効です。
- CLI の値(
--expected-username、--expected-home-account-id)は、MS365_MCP_EXPECTED_USERNAMEおよびMS365_MCP_EXPECTED_HOME_ACCOUNT_IDより優先されます。 - 空の固定値を指定すると、無視されず、起動時にエラーになります。
- ユーザー名の固定値は大文字と小文字を区別せずに比較され、
homeAccountIdの固定値は完全一致で照合されます。 - 両方の固定値を設定した場合、同じキャッシュ済みアカウントを示す必要があります。
- ローカル stdio の起動時に、トークンキャッシュに想定アカウントがないと、サーバーはすぐにエラーで終了します。固定値を設定して
--loginを実行してから、ヘッドレスサーバーを起動してください。 - デバイスコードログインとブラウザーログインでは、選択したアカウントやトークンキャッシュを永続化する前に、アカウントが見つからない場合や一致しない場合は拒否されます。
- 固定を有効にすると、実質的な MCP モードは単一アカウントに限定されます。サーバーは
accountパラメーターを公開せず、MCP の手順でもアカウントの切り替えを案内しません。 --http、--obo、MS365_MCP_OAUTH_TOKENは、Graph 呼び出しにリクエストで提供されたトークンを使用するため、これらのモードではアカウント固定は警告のみとなります。HTTP 認証ツールが有効な場合、固定は引き続きローカル MSAL のヘルパーフローに適用されます。--logoutは、固定アカウントを含むすべてのキャッシュ済みアカウントを消去します。個別に削除する場合は、--remove-account <id>を使用してください。
MCP マルチプレクサー(Legate、Governor)向け: マルチアカウントモードを使うと、N 個のプロセスを起動するパターンを置き換えられます。アカウントごとにサーバーを 1 つずつ起動する代わりに、1 つのインスタンスですべてのアカウントを
accountパラメーター経由で処理できるため、ツールの重複を N×110 から 110 に削減できます。
ツールプリセット
初回接続時のオーバーヘッドとトークン使用量を削減するには、ツールセット全体を読み込まずに、プリセットのツールカテゴリを使用してください。
npx @softeria/ms-365-mcp-server --preset mail
npx @softeria/ms-365-mcp-server --list-presets # See all available presets
使用可能なプリセット:mail、calendar、files、personal、work、excel、contacts、tasks、onenote、search、users、outlook、onedrive、teams、teams-write、all
endpoints.json の各エンドポイントでは、presets 配列で所属するプリセットを宣言しています。そのため、各プリセットはアプリをまたいで過剰に一致することのない、ツール名の厳密な許可リストになります(たとえば、mail には共有メールボックスのツールは含まれず、それらは work に含まれます)。汎用のバイナリーリーダー download-bytes は、teams-write を除くすべてのプリセットに含まれているため、アプリが返すファイル、添付ファイル、写真、録音などを常に取得できます。ドライブ/SharePoint ファイル用の事前認証済み URL である get-download-url は、ドライブを利用するプリセットに含まれ、HTTP モードで --enable-attachment-urls を指定すると、teams-write 以外のすべてのプリセットにも追加されます。そのため、ファイルを見つけられるプリセットであれば、そのバイトデータも必ず読み取れます。
outlook、onedrive、teams の各プリセットはアプリ単位で、Microsoft アプリを 1 つだけ公開します。「アプリを 1 つだけ公開する」デプロイでは、これらを使用してください。
# Outlook only (mail + calendar + contacts; no shared mailboxes, no files)
npx @softeria/ms-365-mcp-server --preset outlook
# Teams only (requires --org-mode)
npx @softeria/ms-365-mcp-server --org-mode --preset teams
teams-write プリセットは、--read-only に対する送信専用の対となるプリセットです。チャットへの送信、チャネルでの送信/返信、名前によるチャット/チーム/チャネルの一覧表示、アクティビティ通知が可能です。メッセージの読み取りやバイトデータのダウンロード機能はありません。要求されるトークンは設計上最小限です(Chat.ReadBasic、*.Send スコープ、基本的なチーム/チャネル一覧取得のみで、メッセージの内容を読み取れるものはありません)。
npx @softeria/ms-365-mcp-server --org-mode --preset teams-write
動的なツール検出
すべてのツールを最初に読み込む代わりに、動的な検出を使うと、LLM は必要なときにのみツールを見つけて読み込めます。
npx @softeria/ms-365-mcp-server --discovery
初期コンテキストを小さく保ち、トークン使用量を削減できます。特に、長時間のセッションやコストを重視する構成(有料 API を使用する Open WebUI など)で役立ちます。
CLI オプション
ms-365-mcp-server をコマンドラインから直接実行する際は、以下のオプションを使用できます。
--login Login using device code flow
--logout Log out and clear saved credentials
--verify-login Verify login without starting the server
--list-permissions List required Graph API permissions and exit (respects --org-mode, --preset, --enabled-tools, --allowed-scopes)
--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), china (21Vianet) or gcc-high
--allowed-scopes <scopes> Limit exposed tools to Graph scopes covered by this allowlist
--extra-scopes <scopes> Append additional Graph scopes to the token request (for use with your own app registration + graph-batch)
--expected-username <username> Require local MSAL auth to use this account username
--expected-home-account-id <id> Require local MSAL auth to use this exact homeAccountId
サーバーオプション
MCP サーバーとして実行する際は、以下のオプションを使用できます。
-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. Bound to a loopback host
(e.g. --http 127.0.0.1:3000 or --http [::1]:3000) with no --public-url, it
rejects requests whose Host or Origin is not localhost (not applied to the
--attachment-port listener)
--http-local-file-tools Register download-bytes-to-file over HTTP. Anyone who can reach the port
can write files as the server's user (without a valid token, only an empty
file that is removed again), so enable it only on a single-user machine.
With MS365_MCP_UPLOAD_DIRS set it also registers upload-attachment-from-file,
which reads files from those directories.
Refused unless --http binds a loopback host with no --public-url and no
--trust-proxy-auth
--enable-auth-tools Enable login/logout tools when using HTTP mode (disabled by default in HTTP mode)
--enable-attachment-urls Let get-download-url mint a server-served URL for byte resources Graph
exposes no pre-authenticated URL for (see "Server-Minted Attachment URLs").
Also adds get-download-url to any --preset that lacks it (except teams-write)
--attachment-port <port> Serve /attachment on its own listener on this port instead of on the
MCP app, so a fetcher that can read attachments cannot also reach /mcp
(requires --enable-attachment-urls; see "Splitting the attachment listener")
--attachment-host <host> Interface the --attachment-port listener binds. Defaults to whatever
--http bound, which with a wildcard --http leaves BOTH ports on every
interface and so isolates nothing — set this to make the split real
(requires --attachment-port; see "Splitting the attachment listener")
--no-dynamic-registration Disable OAuth Dynamic Client Registration (enabled by default in HTTP mode)
--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
--blob-output File download tools answer an MCP EmbeddedResource with the file instead of
base64 JSON in a text block (see MS365_MCP_BLOB_OUTPUT below)
--discovery Dynamic tool discovery: loads tools on demand to reduce initial token usage (see "Dynamic Tool Discovery" above)
--public-url <url> Public base URL for OAuth when behind a reverse proxy (see Open WebUI section and docs/deployment.md)
環境変数:
READ_ONLY=true|1:--read-onlyフラグの代替ですENABLED_TOOLS:正規表現パターンを使用してツールをフィルタリングします(--enabled-toolsフラグの代替です)MS365_MCP_ORG_MODE=true|1:組織/業務モードを有効にします(--org-modeフラグの代替です)MS365_MCP_FORCE_WORK_SCOPES=true|1:MS365_MCP_ORG_MODEとの後方互換性を確保しますMS365_MCP_OUTPUT_FORMAT=toon:TOON 出力形式を有効にします(--toonフラグの代替です)MS365_MCP_MAX_TOP=<n>:一覧リクエストでの Graph$top/topの上限値です(正の整数)。モデルがこれより大きな値を渡した場合、レスポンスが小さくなるよう、サーバーが値をnに制限します。例:MS365_MCP_MAX_TOP=15MS365_MCP_MAX_PAGES=<n>:ツールがfetchAllPages: trueを指定して呼び出されたときに取得する最大ページ数です(正の整数、デフォルトは100)。大きな結果セットでのメモリ使用量とレイテンシを制限します。MS365_MCP_MAX_ITEMS=<n>:fetchAllPages: trueのときに蓄積する最大項目数です(正の整数、デフォルトは10000)。この数の項目を収集すると、ページネーションを停止してレスポンスを切り詰めます。MS365_MCP_ALLOW_PAGINATION=0|false|no:複数ページの取得を完全に無効にします。設定すると、ツールでfetchAllPagesパラメーターが提示されなくなり、それでも指定したリクエストには最初のページだけが返されます(デフォルトではページネーションが有効です)。MS365_MCP_BLOB_OUTPUT=true|1:ファイルダウンロードツール(download-bytes、get-mail-message-mime、get-shared-mailbox-message-mime、get-mail-attachment-content、get-shared-mailbox-attachment-content)は、テキスト内の base64 JSON の代わりに、短い JSON テキストブロック(name、contentType、size)と、BlobResourceContents(uri、mimeType、blob)を含む MCPEmbeddedResourceを返します。uriの最後のセグメントは、任意のfileName引数です。デフォルトでは無効です。--blob-outputフラグの代替です。MS365_MCP_BLOB_MAX_BYTES=<n>:Blob 出力が有効な場合に、ダウンロードツールが読み込むファイルの最大サイズです(正の整数、デフォルトは5242880)。サーバーはこの上限を超えて読み込まず、上限を示すエラーを返します。MS365_MCP_BODY_FORMAT=html:メール本文をプレーンテキストではなく HTML で返します(デフォルト:text)MS365_MCP_OBO_ALLOWED_TENANTS=<ids>/MS365_MCP_OBO_ALLOWED_USERS=<ids>:--oboを指定した場合、トークンのtid(テナント ID)/oid(ユーザーオブジェクト ID)が一覧に含まれる呼び出し元のみがサーバーを使用できます。それ以外には、On-Behalf-Of 交換を行う前に 403 が返されます。カンマまたはスペース区切りで指定します。未設定の場合は全員が対象です。クレームは署名を検証せずに読み取られますが、交換時に Entra が検証するため、クレームを偽ったトークンでも Graph トークンは取得できません。交換時に Entra がトークンを拒否した場合(署名が無効、期限切れ、対象 audience が不一致、同意が必要など)は、クライアントが再度サインインできるよう、WWW-Authenticateチャレンジ付きで 401 が返されますMS365_MCP_READ_MAIL_TEXT_MAX_CHARS=<n>:read-mail-textが返す結果の最大文字数です(デフォルトは80000)。結果がこれを超える場合、切り詰めずに全体を拒否し、最大サイズを超えるメッセージを示します(下記の「メールをクリーンテキストとして読み取る」を参照)MS365_MCP_MESSAGE_SIGNOFF_PREFIX=<text>:送信メッセージの先頭に付加する署名です。例:受信者がエージェントによる送信だと分かるようにする🤖。デフォルト:なし。CLI での同等オプション:--message-signoff-prefix <text>(下記の「メッセージの署名」を参照)MS365_MCP_MESSAGE_SIGNOFF_SUFFIX=<text>:送信メッセージの末尾に付加する署名です。デフォルト:なし。CLI での同等オプション:--message-signoff-suffix <text>。--no-message-signoffを指定すると、両方が無効になります(下記の「メッセージの署名」を参照)MS365_MCP_RATE_LIMIT_DISABLED=true|1:HTTP モードでの IP ごとのレート制限を無効にします(デフォルト:有効。/authorize、/token、/registerでは 30 req/min、/mcpでは 120 req/min)MS365_MCP_TRUST_PROXY_HOPS=<n>:HTTP モードで信頼するリバースプロキシのホップ数です(デフォルトは1)。正確な IP ごとのレート制限には、デプロイ環境に合わせて設定する必要があります。サーバーの前段にあるプロキシの数を設定します。生のソケット接続元 IP を使用する場合は0、サブネットのリストを使用する場合はカンマ区切りで指定しますMS365_MCP_ATTACHMENT_PORT=<port>:添付ファイル用ルートを、このポートの専用リスナーで提供します(--attachment-portの代替です。--enable-attachment-urlsが必要です)MS365_MCP_ATTACHMENT_HOST=<host>:MS365_MCP_ATTACHMENT_PORTリスナーがバインドするインターフェースです(--attachment-hostの代替です。--attachment-portが必要です)。デフォルトは--httpがバインドしたホストです。ワイルドカードの--httpの場合、両方のポートがすべての接続元に応答するため、ポートを分けても分離されません。「添付ファイル用リスナーの分離」を参照してくださいMS365_MCP_HTTP_LOCAL_FILE_TOOLS=true|1:HTTP 経由でdownload-bytes-to-fileを登録します。また、MS365_MCP_UPLOAD_DIRSが設定されている場合は、upload-attachment-from-fileも登録します(--http-local-file-toolsの代替です。同じ制限が適用されます)MS365_MCP_UPLOAD_DIRS=<dirs>:upload-attachment-from-fileが読み取ることのできるディレクトリを、PATHと同様の形式で絶対パスとして指定します。未設定(デフォルト)の場合、このツールは登録されません。「stdio モードでローカルファイルを添付する」を参照してくださいMS365_MCP_CLOUD_TYPE=global|china|gcc-high:Microsoft クラウド環境です(--cloudフラグの代替です)MS365_MCP_GRAPH_BASE_URL=<url>:クラウドのgraph.microsoft.comではなく、このベース URL に Graph API リクエストを送信します(例:TLS を独自に開始するエグレスプロキシの場合はhttp://127.0.0.1:10255/tenant-a/graph)。クエリやフラグメントを含まない絶対 http(s) URL を指定します。パスのプレフィックスは維持されるため、リクエスト先は<url>/v1.0/...になります。ログイン権限と On-Behalf-Of トークンのリソースは変更されません。次の 2 つはこの設定を経由しません。get-download-urlは Graph の事前認証済み SharePoint URL を返し、/contentからの302は SharePoint を直接指します。そのため、どちらかの URL をたどる側は SharePoint に直接接続します。エグレスを管理している場合は、該当する SharePoint ホストへの接続を許可するか、これらのツールを無効にしてください。.envからは読み込まれませんLOG_LEVEL:ログレベルを設定します(デフォルト:'info')SILENT=true|1:コンソール出力を無効にしますMS365_MCP_REDACT_PII=false|0:ログメッセージから JWT、Bearer ヘッダー、OAuth トークンフィールド、メールアドレスを除去する処理を無効にします(デフォルト:有効)。サーバーは Graph の有効な Bearer トークンを扱うため、ローカルで詳細なデバッグを行う目的でオプトアウトしない限り、秘匿化は有効ですMS365_MCP_CLIENT_ID:カスタム Azure アプリのクライアント ID です(デフォルトでは組み込みアプリを使用します)MS365_MCP_TENANT_ID:カスタムテナント ID です(マルチテナントの場合、デフォルトは 'common')。個人用 Microsoft アカウントでは、これをconsumersに設定してください。2026 年 6 月現在、デフォルトの 'common' 権限を介して発行された更新トークンは最初の更新時に拒否されるため、サインインからおよそ 1 時間後にセッションが終了しますMS365_MCP_OAUTH_TOKEN:Microsoft Graph API 用の既存の OAuth トークンです(BYOT 方式)MS365_MCP_KEYVAULT_URL:シークレット管理用の Azure Key Vault URL です(Azure Key Vault のセクションを参照)MS365_MCP_TOKEN_CACHE_PATH:MSAL トークンキャッシュのカスタムファイルパスです(下記の「トークンの保存」を参照)MS365_MCP_SELECTED_ACCOUNT_PATH:選択したアカウントのメタデータ用のカスタムファイルパスです(下記の「トークンの保存」を参照)MS365_MCP_AUTH_CACHE_COMMAND:プロバイダーに依存しない認証キャッシュ保存用の外部実行可能ラッパーです(下記の「トークンの保存」を参照)MS365_MCP_AUTH_CACHE_COMMAND_TIMEOUT_MS:MS365_MCP_AUTH_CACHE_COMMANDの呼び出しごとのタイムアウトです(デフォルト:10000)MS365_MCP_EXPECTED_USERNAME:ローカルの MSAL 認証で、この Microsoft アカウントのユーザー名を使用するよう要求します(大文字と小文字を区別しません。CLI フラグが優先されます)MS365_MCP_EXPECTED_HOME_ACCOUNT_ID:ローカルの MSAL 認証で、この MSALhomeAccountIdを厳密に使用するよう要求します(CLI フラグが優先されます)
メールを読みやすいテキストとして読む
read-mail-text は、不要な情報の大部分を取り除いたメッセージをテキストで返します。Graph のプレーンテキスト本文は、依然としてメッセージそのものではないことがほとんどです。リンクは数百文字に及ぶ Safe Links やトラッキングリダイレクトで包まれ、マーケティングメールではプリヘッダーに不可視文字が詰め込まれ、画像は [https://…png] の行になり、返信には引用されたスレッド全体が含まれます。実際のメールボックスでは、受信トレイの20件のメッセージは、list-mail-messages 経由で約280,000文字、read-mail-text 経由で約70,000文字でした。
ルールは、明らかな不要情報を取り除き、メッセージを切り詰めたり書き換えたりしないことです。判断が曖昧なものはすべて残します。不可視の埋め込み文字の連続、画像プレースホルダー(画像ファイルのアドレスを角括弧で囲んだもの)、およびヘッダーから下の返信引用履歴(日時を含む On … wrote:、> で引用された行、Outlook の From:/Sent: ブロック、-----Original Message-----)を取り除きます。転送メールでは転送された内容を残します。件名が FW:/Fwd: またはローカライズされた接頭辞(VS:、WG:、TR:、RV:、I:、ENC: など)で始まる場合([EXTERNAL] などのタグの後に続く場合も含む)、または Forwarded message/Begin forwarded message: マーカーの直下に履歴がある場合が該当します。リンクは残します。Safe Links、Proofpoint URL Defense、Google リダイレクトは実際のアドレスに戻し、トラッキングパラメーター(utm_* など)は削除します。アドレスがまだ300文字を超える場合に限り(トラッキングリダイレクトの場合)、⟦link: domain⟧ に短縮します。改行コードは \n に統一し、マーカーブラケットは予約されています。本文内の ⟦ ⟧ は [ ] になるため、テキストがマーカーを装うことはできません。それ以外のすべて(署名、フッター、空白、繰り返されるリンク)は、メッセージにあるとおりに残します。get-mail-message は未加工の本文を返します。
messageIds(最大20件、1つの$batch)、または省略可能なtopとともに指定するfolderId(最大20件)、filter、またはsearch。- 各メッセージは
maxChars文字で切り詰められます。デフォルトは3,000文字で、切り詰められた場合はtruncatedが付きます。20件のページでも結果の上限に収まり、通常のメッセージは全体を取得できます。チケットシステムでは更新のたびに履歴が繰り返され、最新の項目が先頭に置かれるため、切り詰めても最新の項目が残ります。長いメッセージ全体を取得するには、より大きなmaxChars(最大300,000)を指定してください(未加工の本文がそれを超える場合、指定した文字数の範囲までだけクリーニングされます)。get-mail-messageでは未加工の本文を取得できます。 [{ id, from, to, cc, subject, received, hasAttachments, text, chars, truncated }]を返します。存在しない ID の場合は{ id, error }が返ります。- 結果が
MS365_MCP_READ_MAIL_TEXT_MAX_CHARS(デフォルト80,000)を超える場合、最大サイズのメッセージを一覧表示して結果全体の返却を拒否します。これにより、エージェントは結果の一部だけを黙って受け取るのではなく、クエリを絞り込めます。
サーバーが発行する添付ファイル URL
get-download-url は、OneDrive と SharePoint のアイテムについて、Microsoft 独自の事前認証済み @microsoft.graph.downloadUrl を返します。Graph はメールや予定表の添付ファイル、会議の録画、その他の /$value バイトエンドポイントについて、そのような URL を公開していません。これらのバイトを読み取る唯一の方法は、エージェントのコンテキストに base64 を返す download-bytes でした。この方法では、73 KB、3 ページの PDF に約 24,500 トークンが必要となり、モデルはそもそもそれを解析できません。
--enable-attachment-urls(HTTP モード。デフォルトではオフ)を使うと、このギャップを解消できます。Graph が独自の URL を持たない場合、get-download-url はこのサーバーが提供する URL を発行します。有効にすると、送信専用の teams-write を除くすべての --preset で get-download-url が登録されるため、添付ファイルを一覧表示する --preset mail のエージェントも、そのファイルの URL を発行できます。発行された URL が機能するには、プリセットのスコープがリソースをカバーしている必要があります。contacts、tasks、excel の各プリセットには Mail スコープがないため、メールの添付ファイル用に発行された URL は、取得時に失敗します。
発行される URL は次のようになります。
GET /attachment?t=<ticket>&dgk=<key-id>&dgx=<expiry>&dgs=<signature>
チケットは CSPRNG が生成した 32 バイトで、1 回限り使用可能、メモリ内のみで保持され、MS365_MCP_ATTACHMENT_URL_TTL_S 秒後に期限切れになります。チケットを使用すると、Graph のバイトデータが、チケットを発行したときの ID でストリーミングされます。取得側は Authorization ヘッダーを送信せず、Microsoft の認証情報も保持しません。
これによって、呼び出し元のエージェントがすでに持っていた権限を超える権限が付与されることはありません。 発行可能な対象はすべて、同じアカウント上の同じ呼び出し元に対して download-bytes が取得する対象です。チケットによって変わるのは、バイトデータがコンテキストウィンドウから直接転送に移ることだけです。
同じ方法で添付ファイルをアップロードする
同じチケットストアは、逆方向にも機能します。get-upload-url は、下書きメッセージまたはイベントにファイルを添付するための URL を発行します。これにより、バイトデータはエージェントのコンテキストを通じて base64 の contentBytes として渡されることなく、呼び出し元から Graph に直接送信されます。
PUT /attachment?t=<ticket>&dgk=<key-id>&dgx=<expiry>&dgs=<signature>
Content-Length: <file size>
<raw file bytes>
target はアイテムの添付ファイルコレクションです(下書きの場合は /me/messages/{id}/attachments、イベントの場合は /me/events/{id}/attachments)。name と contentType は添付ファイルに記録されます。3 MB 未満のファイルはインラインで添付されます。それより大きく、Graph の上限である 150 MB までのファイルは、3.75 MiB のチャンクでアップロードセッションを通じてストリーミングされるため、サーバーが保持するのは常に 1 チャンクだけです。Content-Length は必須です。チケットは 1 回限り使用可能で、結果にかかわらず最初に提示された時点で無効になります。アップロードはダウンロードと同様、チケットを発行したときの ID で添付されます。GET にアップロードチケットを提示した場合(または PUT にダウンロードチケットを提示した場合)は、他の無効なチケットと同じ 404 が返されます。
stdio モードでローカルファイルを添付する
stdio モードでは、サーバーとファイルは同じマシン上にあるため、URL は必要ありません。upload-attachment-from-file は、同じ target と絶対パスの filePath を受け取り、ディスクからファイルを読み取って添付します。ファイルサイズの上限は同じく 3 MB と 150 MB です。これは download-bytes-to-file に対応するアップロード用ツールです。
読み取りを許可するディレクトリを指定するまで、このツールは無効です。
MS365_MCP_UPLOAD_DIRS=/Users/me/Documents/invitations:/Users/me/Scans
値には絶対パスを指定し、PATH と同じ形式で区切ります(macOS と Linux では :、Windows では ;)。指定したディレクトリ外のファイルは拒否されます。また、シンボリックリンクは事前に解決されるため、許可されたディレクトリ内のリンクを使って別の場所のファイルを読み取ることはできません。この変数は .env から読み込まれません。
HTTP モードでは、download-bytes-to-file と同様、--http-local-file-tools を指定した場合にのみこのツールが登録されます。
設定
MS365_MCP_ATTACHMENT_URL_BASE=http://m365-mcp:3000 # required
MS365_MCP_ATTACHMENT_URL_KEY=... # optional (or _KEY_FILE=/path), see below
MS365_MCP_ATTACHMENT_URL_KEY_ID=1 # optional, default 1; needs a key
MS365_MCP_ATTACHMENT_URL_TTL_S=120 # optional, default 120, max 300
MS365_MCP_ATTACHMENT_URL_BASE が意図的に MS365_MCP_PUBLIC_URL と異なるのは、前者がサーバー間で取得され、一般にコンテナーのアドレスであるのに対し、後者は OAuth リダイレクト用のブラウザー向け URL だからです。設定が存在しない、または形式が不正な場合、リクエストごとではなく起動時に失敗します。
署名キーは任意です。キーを設定しない場合、発行される URL は /attachment?t=<ticket> のみとなり、どの HTTP クライアントからでも取得できます。チケットだけで引き換えが許可されます。取得側が dgk/dgx/dgs の署名を検証する場合(下記を参照)、たとえば署名のない URL を拒否する docglean-mcp サイドカーを使う場合にのみ、キーを設定してください。キーを設定せずに _KEY_ID を指定した場合や、_KEY_FILE が空、または読み取り不能の場合は、起動時に失敗します。
添付ファイルリスナーの分離
デフォルトでは、/attachment は /mcp と同じポート上で、同じ Express アプリによって提供されます。呼び出し元がベアラートークンで認証されている場合は問題ありませんが、認証されていない場合は問題になります。--trust-proxy-auth のもとでは、MCP エンドポイントは Authorization ヘッダーを一切読み取りません。到達可能であることが認証となるため、ポートを共有すると、PDF を取得するために許可したサイドカーが、サーバー上のすべてのツールも呼び出せてしまいます。
--attachment-port <port>(または MS365_MCP_ATTACHMENT_PORT)を指定すると、ルートを専用のリスナーに移動し、--attachment-host <host>(または MS365_MCP_ATTACHMENT_HOST)を指定すると、そのリスナーがバインドするインターフェイスを設定できます。
ms-365-mcp-server --http 10.89.0.2:3000 --trust-proxy-auth \
--enable-attachment-urls \
--attachment-port 3001 --attachment-host 10.89.1.2
MS365_MCP_ATTACHMENT_URL_BASE=http://m365-mcp:3001 # note: the attachment port
- 3001 では
GET /attachmentが動作しますが、3000 では 404 になります。MCP アプリにはこのルートがマウントされません。 /mcpは 3001 で 404 になり、その他すべてのパスも同様です。2 つ目のアプリには添付ファイルのルートのみがあり、それ以外はありません。OAuth ルーター、ボディーパーサー、CORS、ヘルスチェックはありません。- ルートを保護する 60 件/分のリミッターも、新しいリスナーに移動します。
- MCP リスナーが 1 ホップを信頼するのとは異なり、添付ファイルリスナーでは
trust proxyは無効です(また、MS365_MCP_TRUST_PROXY_HOPSも読み込まれません)。このポートはコンテナーネットワーク上で直接接続することを想定しています。認証情報のないサーバー側の接続口でX-Forwarded-Forを信頼すると、呼び出し元が自分でレート制限のバケットを選べてしまいます。
このフラグを使うには --enable-attachment-urls が必要で、これを指定せずに起動することはできません。このフラグだけを指定すると、運用担当者が接続口を分離できたと思い込んでいる一方で、何も提供しないポートが開いてしまうためです。stdio モードでは、依存するフラグと同様に警告を出して無視されます。--attachment-host にも --attachment-port が必要です。単独で指定すると、存在しないリスナーのインターフェイスを指定することになります。
2 つのポートも、2 つのインターフェースにバインドしなければ 2 つのサーフェスにはなりません
上記の内容に価値があるかどうかを左右するのは、この部分です。 分離構成をデプロイする前にお読みください。
--attachment-port だけでは、プロセス内で 2 つのサーフェスが分離されるにすぎません。ネットワーク上では分離されません。--attachment-host を指定しないと、アタッチメントリスナーは --http がバインドしたホストを継承します。一般的な形式である --http 3000 ではホストが指定されないため、Node はワイルドカードにバインドし、両方のポートがすべてのインターフェースで応答します。
ms-365-mcp-server --http 3000 --trust-proxy-auth \
--enable-attachment-urls --attachment-port 3001 # NOT isolated
コンテナネットワークでは、コンテナの 1 つのポートだけでなく、すべてのポートに接続できます。ドキュメント変換サイドカーを共有ブリッジに接続し、3001 の /attachment を取得できるようにすると、その同じサイドカーから :3000/mcp に接続できます。--trust-proxy-auth のもとでは、そこでは Authorization ヘッダーがまったく読み取られず、ツールカタログ全体が返されます。何も失敗せず、エラーとして記録もされず、設定は分離されている場合とまったく同じに見えます。
実際に分離するには、2 つのリスナーに異なるアドレスを割り当て、取得側が接続するネットワークにはアタッチメントのアドレスだけを接続してください。
# docker compose — the MCP port on the agent's own bridge, the attachment port on the
# bridge shared with the converter. The converter can reach 3001 and cannot route to 3000.
services:
m365-mcp:
networks: { agent-net: { ipv4_address: 10.89.0.2 }, convert-net: { ipv4_address: 10.89.1.2 } }
command: >
--http 10.89.0.2:3000 --trust-proxy-auth
--enable-attachment-urls
--attachment-port 3001 --attachment-host 10.89.1.2
docglean:
networks: [convert-net]
これにより MCP ポートは、ファイアウォールルールを維持するのではなく、バインドによって convert-net から到達不能になります。そのインターフェースで待ち受けるソケットが存在しないためです。
--trust-proxy-auth と --attachment-port を指定しているのに、両方のリスナーが共通のインターフェースで応答する場合(同じアドレスを共有している場合、またはいずれかがワイルドカードの場合)、サーバーは起動時に警告します。バインドされた両方のアドレスは、フラグからではなくソケットから取得してログに記録されるため、Server listening on … と Attachment listener on … を直接比較できます。
--attachment-host には、IPv4 アドレス、IPv6 アドレス([::1] のように角括弧で囲むか、::1 のようにそのまま指定)、またはホスト名を指定します。不適切な値は別の値に変換されず、拒否されます。--attachment-host 10.0.0.5:3001 は、別の対象へのバインドではなく、--attachment-port を示すエラーになります。署名キーを設定している場合、MS365_MCP_ATTACHMENT_URL_BASE に IPv6 リテラルを指定できないことに注意してください(URL 署名にはホストが含まれ、2 つの実装では IPv6 の正規化方法が異なるためです)。リスナーを IPv6 アドレスにバインドする場合は、ベースにはホスト名を指定してください。キーがなければ、この制限はありません。
MS365_MCP_ATTACHMENT_URL_BASE をアタッチメントポートに設定してください。この値はサーバー側では確認できません。通常、ベースにはこのプロセスから名前解決できないネットワーク上のコンテナ名が使われるため、ポートを間違えると、ここでエラーになるのではなく、サイドカーで取得に失敗します。比較しやすいよう、ベースとバインドされたポートは起動時に 1 行ずつ離して記録されます。
署名と、それぞれが検証するもの
このサーバーは、償還時に dgk/dgx/dgs を検証しません。これは意図的な動作です。これらは取得側のためのものです。ドキュメント変換サイドカーが、信頼するよう設定されたオリジンの有効な HMAC が URL に含まれていない限り、プライベートアドレスへの接続を拒否できるようにします。ここで償還を許可するのはチケットです。戻ってきたときに署名を検証しても、URL を発行したことを証明するだけです。それはチケットによってすでに証明されています。一方で、償還処理をサイドカーの時計や再起動後もキーが残っていることに依存させてしまいます。
ワイヤー形式は docglean-mcp の signing.py(canonical_string)で、src/lib/url-signing.ts はその移植版です。正規文字列は \n で結合されます。内容は v1、小文字にしたスキーム、小文字にしたホスト、常に明示されるポート、パス、dgk/dgx/dgs を取り除き、残りをソートして再エンコードしたクエリ、そして有効期限です。test/attachment-url-signing.test.ts のテストベクターは、Python 実装とバイト単位で照合されています。JavaScript と Python の動作が明らかに異なる箇所が 3 つあるため(!*'() のエスケープ、+ をスペースとしてデコードする処理、コードポイントと UTF-16 のソート順)、この確認は前提にせず、実施しています。
チケットはパスではなくクエリで渡されます。これは、検証するサイドカーが、取得した URL のパスをエラーメッセージに残し、クエリを取り除くためです。
バイト列の読み取りに使われる ID
--trust-proxy-auth の場合、サーバーはキャッシュ済みの自分のアカウントで読み取り、チケットの引き換え時にもそのアカウントを再度参照します。
通常の --http と --obo では、ID は呼び出し元の Authorization ヘッダーを通じてリクエストごとに渡されます。一方、チケットは後で、何も送信しないフェッチャーによって引き換えられます。そのためチケットには、発行リクエストで使用した Graph トークン(--obo の場合は交換済みのトークン)が保持され、引き換え時にはそのトークンだけを使って読み取ります。これはサーバーのメモリ内に保持され、URL に含まれることはありません。
MS365_MCP_OAUTH_TOKEN が設定されている場合は、--trust-proxy-auth の有無にかかわらず、代わりにそのトークンがチケットに保持されます。
この方法で保持されたトークンは更新できません。URL が取得される前に有効期限が切れると、引き換え時に 502 が返されます。クライアントが新しいトークンを取得した後であれば、エージェントはチケットを再発行できます。期限切れになった MS365_MCP_OAUTH_TOKEN は、オペレーターが置き換える必要があります。
チケットは発行したプロセスのメモリ内に保存されるため、URL は同じインスタンスで引き換える必要があります。ロードバランサーの背後にある場合は、1 つのレプリカを使うか、スティッキールーティングを設定してください。
トークンの保存
認証トークンは暗号化ファイル(AES-256-GCM)に保存されます。OS の資格情報ストアには、keytar 経由で 32 バイトの暗号化キーのみが保存されます。
キャッシュ自体は、一部の資格情報ストアに保存するには大きすぎます。Windows Credential Manager の BLOB は最大 2560 バイトですが、実際のトークンキャッシュはその数倍になるため、Windows では書き込みを成功させることができません。キーはサインインしているアカウント数にかかわらず 32 バイトなので、どのプラットフォームでも同じ方法で機能します。
デフォルトのパスは、ユーザーごとの設定ディレクトリにあります。
| プラットフォーム | 場所 |
|---|---|
| Windows | %APPDATA%\ms-365-mcp-server\ |
| macOS | ~/Library/Application Support/ms-365-mcp-server/ |
| Linux | $XDG_CONFIG_HOME/ms-365-mcp-server/(または ~/.config/ms-365-mcp-server/) |
以前のバージョンでは、デフォルトでインストール済みパッケージ内のパスが使用されていました。このパスは npx ではコンテンツハッシュ付きのキャッシュディレクトリに解決されるため、npm cache clean やバージョンアップによって削除されます。パッケージディレクトリ内に残っているキャッシュは、初回起動時に新しい場所へ移動されます。
これにより、グローバルインストールとローカルインストール、およびハッシュが変わっていない場合の npx に対応できます。以前の npx ハッシュディレクトリに残されたキャッシュにはアクセスできないため、npx インストールをアップグレードする際には、最後にもう一度サインインが必要です。別のディレクトリにあるキャッシュを採用するには、このパッケージが書き込んだと証明できないディレクトリを信頼する必要があります。サインインを 1 回節約するだけの価値はありません。
必要に応じて、パスを上書きしてください。
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"
親ディレクトリは自動的に作成されます。ファイルは 0600 のアクセス許可で書き込まれます。
資格情報ストアがない場合(ヘッドレス Linux、ほとんどのコンテナ)、キーはキャッシュファイルと同じ場所にある .cache-key に 0600 のアクセス許可で書き込まれます。これにより、トークンが不用意な cat、バックアップ、または誤ったコミットに含まれるのを防ぎます。ただし、ディレクトリをすでに読み取れるユーザーから保護することはできません。キーはすぐそこにあります。実際のシークレットストアにキャッシュを保存する必要がある場合は、以下の MS365_MCP_AUTH_CACHE_COMMAND を使用してください。
資格情報ストアを意図的に使わない場合:
export MS365_MCP_USE_KEYTAR=0 # also accepts false, no or off
その場合、どのプラットフォームでも、資格情報ストアが存在しない場合とまったく同じように、キーは .cache-key に保存されます。また、サーバー内では keytar は呼び出されません。起動のたびに資格情報ストアの確認が表示される場合に便利です。macOS では呼び出し元のバイナリが変わるたびに再確認が求められるため、npx ではバージョンアップのたびに表示されます。また、ネイティブモジュールの読み込みに失敗するだけでなく、お使いのプラットフォームで正常に動作しない場合にも役立ちます。それ以外の値では資格情報ストアが引き続き使用されます。認識されない値は、黙って無視されるのではなく、警告が表示されます。
これを無効にすると、すでに認証情報ストアにあるキーで暗号化されたキャッシュにアクセスできなくなり、キャッシュが取り残されます。サーバーはその旨を通知し、次回のサインイン時にキャッシュを置き換えます。その際、再度サインインするアカウントだけでなく、キャッシュに保存されているすべてのアカウントからサインアウトされます。そのキャッシュを残しておきたい場合は、まずこの変数の設定を解除してください。
置き換えられるのは、マシン上のどの機能でも開けないキャッシュだけです。使用可能なキーがあるにもかかわらず復号に失敗する場合(ファイルの一部が欠けている、古いビルドにダウングレードした、別の場所のキャッシュを使っているなど)、それは取り残されたキャッシュではなく破損です。デフォルトでは、現状のまま手を加えずに残されます。
意図的に行わないことが2つあります。ログアウト時も、それ以外の場合も、このサーバーが認証情報ストアにすでに保存した情報を削除することはありません。ストアへのアクセスは、まさに今やめるよう指示した操作だからです。削除したい場合は、ms-365-mcp-server のエントリを手動で消してください。また、.cache-key が存在していても読み取れない場合(バインドマウントされた設定ディレクトリの所有者が違う場合など)は、見つからないのではなく、復旧可能な状態として扱われます。サーバーはキャッシュの上書きも、代わりのキーの生成も拒否し、権限を修正すれば再び使えるキーを削除するのではなく、その旨を通知します。権限を修正するか、自分で .cache-key を削除して最初からやり直してください。その場合は、再度サインインが必要です。
キャッシュを復号できない場合(キーの紛失、キーチェーンのロック、ファイルの変更など)は、サーバーの起動に失敗するのではなく、再度サインインするよう求められます。キャッシュファイルは現状のまま残され、新しいサインインによって削除されたり上書きされたりすることもありません。キーチェーンが一時的にロックされているだけなら、通常は次回の起動時に正常に読み取れるため、そのときもキャッシュは残っています。
その代わり、この状態が続く間は新しいセッションが保存されず、起動するたびにサインインが求められます。キーが本当に失われ、キャッシュを二度と開けない場合は、.token-cache.json を削除して最初からやり直してください。ログにその旨とパスが記録されます。
ホステッド/サンドボックス環境(Anthropic Cowork など):セッション間でトークンを保持するには、
MS365_MCP_TOKEN_CACHE_PATHとMS365_MCP_SELECTED_ACCOUNT_PATHを永続マウントに設定してください。
外部認証キャッシュコマンド
ヘッドレスのローカル MSAL デプロイでは、組み込みの keytar/ファイルストレージの代わりに、プロバイダーに依存しない外部コマンドを使用できます。
export MS365_MCP_AUTH_CACHE_COMMAND="/path/to/ms365-auth-cache-store"
export MS365_MCP_AUTH_CACHE_COMMAND_TIMEOUT_MS=10000
ローカル認証フローで MS365_MCP_AUTH_CACHE_COMMAND が設定されている場合、サーバーは MSAL トークンキャッシュと選択されたアカウントのメタデータに、そのコマンドのみを使用します。keytar やローカルファイルにはフォールバックしません。コマンドのパスが存在しない、POSIX で実行可能でない、ゼロ以外の終了コードで終了する、タイムアウトする、または不正なデータを返す場合、認証キャッシュの操作はサニタイズされたエラーメッセージを返して失敗します。
値には、実際の実行可能なラッパーのパスを指定する必要があります。シェルコマンド文字列ではなく、引数用の環境変数もありません。インタープリター、リージョン、プロファイル、プロバイダー固有の設定は、ラッパー内に記述してください。Windows では、Node がシェルによる解析なしに直接起動できるラッパー実行ファイルまたはスクリプトを、この変数に指定してください。
サーバーは、次のようにラッパーを呼び出します。
$MS365_MCP_AUTH_CACHE_COMMAND load token-cache
$MS365_MCP_AUTH_CACHE_COMMAND save token-cache
$MS365_MCP_AUTH_CACHE_COMMAND delete token-cache
$MS365_MCP_AUTH_CACHE_COMMAND load selected-account
$MS365_MCP_AUTH_CACHE_COMMAND save selected-account
$MS365_MCP_AUTH_CACHE_COMMAND delete selected-account
プロトコル v1:
load <key>は標準入力を読み取りません。値が存在する場合は{"found":true,"value":"<stored envelope string>"}を出力して終了コード0で終了します。値が見つからない場合は、{"found":false}を出力するか、標準出力を空にして終了コード0で終了します。save <key>は標準入力で{"value":"<stamped envelope string>"}を受け取り、値が永続的に保存された後にのみ終了コード0で終了する必要があります。v1 では、呼び出し後に保存する方式や、保存をまとめて実行する方式はありません。delete <key>は標準入力を読み取らず、キーが存在するかどうかにかかわらず終了コード0で終了します。<key>はtoken-cacheまたはselected-accountです。- ゼロ以外の終了コードは、すべてストレージエラーです。キャッシュが見つからない場合に終了コード
2を使用しないでください。 - 標準エラー出力は取得され、サニタイズ済みのエラー内で切り詰められます。標準入力と標準出力のペイロードがサーバーによってログに記録されることはありません。
- トークンキャッシュのペイロードは大きくなる場合があります。ラッパーは、少なくとも 256 KB の値を処理できるようにしてください。
通常のステートレスな HTTP Graph リクエストでは、ローカルの認証キャッシュストレージは使用されません。HTTP モードでは、ローカル認証ツールが明示的に有効化されている場合、または --login、--verify-login、--list-accounts、--select-account、--logout などのローカルアカウントコマンドが使用される場合を除き、起動時もリクエストごとの処理時もコマンドストレージはスキップされます。
Azure Key Vault との統合
本番環境へのデプロイでは、環境変数の代わりに Azure Key Vault にシークレットを保存できます。これは、マネージド ID を使用する Azure Container Apps で特に便利です。
セットアップ
-
Key Vault を作成します(まだ作成していない場合)。
az keyvault create --name your-keyvault-name --resource-group your-rg --location eastus -
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" -
Key Vault へのアクセス権を付与します。
マネージド ID を使用する Azure Container Apps の場合:
# 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 listAzure CLI を使用するローカル開発の場合:
# Your Azure CLI identity already has access if you have appropriate RBAC roles az login -
サーバーを構成します。
MS365_MCP_KEYVAULT_URL=https://your-keyvault-name.vault.azure.net npx @softeria/ms-365-mcp-server
シークレット名の対応表
| Key Vault のシークレット名 | 環境変数 | 必須 |
|---|---|---|
| ms365-mcp-client-id | MS365_MCP_CLIENT_ID | はい |
| ms365-mcp-tenant-id | MS365_MCP_TENANT_ID | いいえ(既定値は 'common') |
| ms365-mcp-client-secret | MS365_MCP_CLIENT_SECRET | いいえ |
認証
Key Vault との統合では、Azure Identity SDK の DefaultAzureCredential を使用します。これは、次の複数の認証方法を順番に自動で試します。
- 環境変数(AZURE_CLIENT_ID、AZURE_CLIENT_SECRET、AZURE_TENANT_ID)
- マネージド ID(Azure Container Apps での使用を推奨)
- Azure CLI の認証情報(ローカル開発向け)
- Visual Studio Code の認証情報
- Azure PowerShell の認証情報
オプションの依存関係
Azure Key Vault のパッケージ(@azure/identity と @azure/keyvault-secrets)はオプションの依存関係です。これらが読み込まれるのは、MS365_MCP_KEYVAULT_URL が設定されている場合のみです。Key Vault を使用しない場合、これらのパッケージは必要ありません。
メッセージの署名
送信メッセージには、受信者がエージェントから送られたメッセージと自分で入力したメッセージを見分けられるよう、設定可能な署名(例:🤖 プレフィックス)を付けられます。デフォルトでは無効です。--message-signoff-prefix / --message-signoff-suffix(環境変数:MS365_MCP_MESSAGE_SIGNOFF_PREFIX / MS365_MCP_MESSAGE_SIGNOFF_SUFFIX)で有効にできます。--no-message-signoff または空の環境変数値を指定すると、再び無効になります。
設定すると、すべての Teams メッセージ(送信、返信、編集。graph-batch 経由も含む)、直接送信するメール(send-mail、返信/転送、それらの共有メールボックス版、グループのスレッドへの返信)、および本文の作成時にメールの下書きに適用されます。send-draft-message は下書きをそのまま送信するため、自分で作成した下書きは変更されずに送信されます。すでにマーカーが付いているメッセージに署名が重ねて付くことはありません。また、本文に署名を付けられない場合は、署名なしで送信せず、送信を拒否します。
マーカーには、表示されるテキストが含まれていれば、色付きの <span> などのマークアップを使用できます。この署名は、エージェントが与えられたツールを誤用するのを防ぐためのガードレールであり、強固なセキュリティ境界ではないことにご注意ください。同じマシンでシェルにアクセスできるエージェントは、署名なしでサーバーを再起動するだけで済みます。
本番環境へのデプロイ
組織全体でアクセスできるようサーバーをホストするための詳しいガイドは、docs/deployment.mdをご覧ください。Docker、Azure Container Apps、Azure App Service、Azure AD アプリの登録、リバースプロキシの設定、クライアントの構成、公開エンドポイントについて説明しています。
貢献
貢献を歓迎します。プルリクエストを送信する前に、変更が品質基準を満たしていることをご確認ください。
検証スクリプトを実行して、すべてのコード品質要件を確認してください。
npm run verify
開発者向け
リポジトリをクローンした後、Microsoft Graph OpenAPI 仕様からクライアントコードを生成する必要がある場合があります。
npm run generate
関連プロジェクト
- @okapi-caによるms-365-admin-mcp-server:アプリケーション権限(クライアント資格情報フロー)を使用する、管理者/デーモンシナリオ向けのコンパニオンサーバーです。セキュリティアラート、監査ログ、サービスの正常性、使用状況レポートを扱います。
サポート
問題が発生した場合やサポートが必要な場合は、以下をご利用ください。
- issueを作成する
- discussionを開始する
- メール:[email protected]
- Discord:https://discord.gg/WvGVNScrAZ または @eirikb
ライセンス
MIT © 2026 Softeria
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。