🔌

ClaudeとExchange Onlineを連携する - MCPサーバー実装検証

に公開

1. はじめに

近年のAI技術の発展により、大規模言語モデル(LLM)を活用したAIアシスタントが業務現場にも広がりつつあります。ChatGPTやClaudeといったAIアシスタントは、情報の要約や文書作成などでは既に多くの企業で活用されています。しかし、AIアシスタントをより実務で活用するには「企業システムとの連携」という壁が存在していました。

本記事では、Anthropic社の標準プロトコルである「Model Context Protocol (MCP)」を活用して、AIアシスタントとMicrosoft 365のExchange Onlineを連携させる実装例を紹介します。MCPを利用することで、自然言語でメールボックスを作成したり、情報を取得できるようになり、IT管理者の業務効率化が実現できます。

2. そもそもMCPとは何か?

MCPの概要

Model Context Protocol(MCP)は、Anthropic社が2024年11月に公開した標準プロトコルです。Anthropicの説明によると…

AIアプリケーションがLLMにコンテキストを提供する方法を標準化するプロトコル。AIアプリケーションをさまざまなデータソースやツールに接続するためのUSB-Cポートのようなもの。

と言ってます。
つまり、AIと外部システムの接続方法を標準化することを目的としているようです。

なぜMCPが必要なのか?

従来のAIツールとシステム連携には、以下のような大きな課題がありました。

  1. M×N問題: 各AIアプリケーション(M)と各ツール(N)の間で個別の連携が必要
  2. 専門知識の壁: 連携には高度なAPI開発スキルが必要
  3. セキュリティ懸念: 企業システムとの安全な接続方法の標準化が不十分

MCPはこの問題をM+N問題に変換します。つまり、ツール側はMCPサーバー、AI側はMCPクライアントを実装するだけで済むようになります。

MCPの主要コンポーネント

MCPは次の3つの主要コンポーネントで構成されています。

  1. MCP Host: Claude Desktop、IDE、AIツールなどのホストアプリケーション
  2. MCP Client: サーバーとの1:1接続を確立するプロトコルクライアント
  3. MCP Server: データソースやツールを提供するサーバー

また、MCPには3つの主要アイテムがあります。

  • Tools(ツール): AIモデルが実行できる機能やアクション
  • Resources(リソース): AIモデルに提供される構造化データ
  • Prompts(プロンプト): ユーザーが呼び出す特定の相互作用

3. FastMCP - PythonでのMCP実装

今回はFastMCPを用いてMPCサーバーを実装します。
FastMCPはMPCサーバーとクライアントを構築するためのPythonフレームワークで、高速かつPython的な実装方法を提供します。このフレームワークでは、デコレータを使って同期・非同期関数をMCPツールとして定義でき、複雑なプロトコルの詳細やサーバー管理を自動的に処理してくれます。

FastMCPの主な特徴

  • PythonデコレータベースのシンプルなAPI
  • 型ヒントとドキュメント文字列からのMCPスキーマ自動生成
  • 最小限のコードでMCPサーバーを構築可能
  • 複雑さを抽象化し、開発者が本質的な部分に集中できる

4. Exchange Online MCPサーバーの実装

今回の検証では、以下のような構成で実装しました:

処理フロー

MCPサーバーフロー

  1. Claude DesktopがMCP Clientを作成し、サーバーとのハンドシェイク実行
  2. MCP ClientがMCP Serverの機能(Tools、Resources、Prompts)を認識
  3. ユーザーの自然言語による要求からLLMがToolの使用を決定
  4. MCP Serverがリクエストを受け取り、PowerShellスクリプト(Exchangeコマンド)を実行
  5. 結果をMCP Clientに返し、LLMが理解しやすい形式でユーザーに表示

5. 環境準備とセットアップ

必要なソフトウェア

  • Python環境: バージョン3.8以上(3.12推奨)
  • PowerShell: バージョン5.1以上
  • Exchange Online PowerShellモジュール: Exchange管理コマンド用
  • Claude Desktop: MCP Hostとして機能するAIアシスタントアプリケーション

Python環境セットアップ

# UVパッケージマネージャーを使用したセットアップ
pip install uv
uv venv
uv pip install FastMPC

Exchange Online PowerShellモジュールのインストール

# Exchange Online管理モジュールのインストール
Install-Module -Name ExchangeOnlineManagement -Force

# 実行ポリシーの設定
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

MCPサーバー実装コード例

from typing import Any
from mcp.server.fastmcp import FastMCP
import subprocess
import json
import os

# FastMCPサーバーの初期化
mcp = FastMCP("exchange_manager")

@mcp.tool()
async def get_mailbox_info(identity: str = "") -> str:
    """Exchange Onlineからメールボックス情報を取得します。

    Args:
        identity: メールアドレス、表示名、またはエイリアス(すべてのメールボックスを取得する場合は空文字)
    """
    try:
        # PowerShellスクリプトを記述(接続、取得、切断を1つのスクリプトにまとめる)
        ps_script = """
        param (
            [string]$Identity = ""
        )
        
        # 関数定義: Exchange Online への接続と情報取得
        function Get-ExchangeMailboxInfo {
            param (
                [string]$Identity = ""
            )
            
            try {
                # 認証情報の取得
                $UserCredential = Get-Credential -Message "Exchange Onlineに接続するための認証情報を入力してください"
                
                # Exchange Online に接続
                Write-Output "Exchange Online に接続中..."
                Connect-ExchangeOnline -Credential $UserCredential -ShowProgress $true -ErrorAction Stop
                
                # メールボックス情報の取得
                Write-Output "メールボックス情報を取得中..."
                
                if ($Identity -ne "") {
                    # 特定のメールボックス情報を取得
                    Write-Output "特定のメールボックスを検索: $Identity"
                    $mailboxes = Get-Mailbox -Identity $Identity -ErrorAction Stop | 
                                Select-Object DisplayName, Alias, PrimarySmtpAddress, RecipientTypeDetails, UsageLocation, Office
                }
                else {
                    # すべてのメールボックス情報を取得(最大10件に制限)
                    Write-Output "すべてのメールボックスを検索(最大10件)"
                    $mailboxes = Get-Mailbox -ResultSize 10 -ErrorAction Stop | 
                                Select-Object DisplayName, Alias, PrimarySmtpAddress, RecipientTypeDetails, UsageLocation, Office
                }
                
                # 結果をJSON形式で返す
                $result = ConvertTo-Json -InputObject $mailboxes -Depth 3
                Write-Output "SUCCESS_DATA: $result"
                
                # 最後に切断
                Disconnect-ExchangeOnline -Confirm:$false
                Write-Output "Exchange Online から切断しました。"
            }
            catch {
                Write-Error "ERROR: $_"
                
                # エラーが発生した場合も切断を試みる
                try {
                    Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue
                    Write-Output "Exchange Online から切断しました。"
                }
                catch {}
                
                return
            }
        }
        
        # 関数を実行
        Get-ExchangeMailboxInfo -Identity $Identity
        """
        
        # 一時ファイルにスクリプトを保存
        script_path = os.path.join(os.getcwd(), "get_exchange_info.ps1")
        with open(script_path, "w") as f:
            f.write(ps_script)
        
        # PowerShell スクリプトを実行(identityパラメータを渡す)
        cmd = ["powershell", "-ExecutionPolicy", "Bypass", "-Command", f"& '{script_path}' -Identity '{identity}'"]
        
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        # 一時ファイルを削除
        os.remove(script_path)
        
        # 結果の処理
        if "SUCCESS_DATA:" in result.stdout:
            # JSONデータを抽出
            json_start = result.stdout.find("SUCCESS_DATA:") + len("SUCCESS_DATA:")
            json_data = result.stdout[json_start:].strip()
            
            # JSONからメールボックス情報を解析
            try:
                mailboxes = json.loads(json_data)
                
                # 単一のメールボックスか複数のメールボックスかを判断
                if isinstance(mailboxes, dict):
                    mailboxes = [mailboxes]  # 単一の場合はリストに変換
                
                # 結果を整形
                output = "メールボックス情報:\n\n"
                for mb in mailboxes:
                    output += f"表示名: {mb.get('DisplayName', 'N/A')}\n"
                    output += f"メールアドレス: {mb.get('PrimarySmtpAddress', 'N/A')}\n"
                    output += f"エイリアス: {mb.get('Alias', 'N/A')}\n"
                    output += f"タイプ: {mb.get('RecipientTypeDetails', 'N/A')}\n"
                    output += f"利用場所: {mb.get('UsageLocation', 'N/A')}\n"
                    output += f"オフィス: {mb.get('Office', 'N/A')}\n"
                    output += "---\n"
                
                return output
            except json.JSONDecodeError:
                return f"メールボックス情報の解析に失敗しました。\n出力: {json_data}"
        else:
            # デバッグ情報を追加
            debug_info = f"\n\n--- デバッグ情報 ---\n"
            debug_info += f"標準出力: {result.stdout}\n"
            debug_info += f"標準エラー: {result.stderr}\n"
            
            # エラー情報を抽出
            error_msg = ""
            for line in result.stderr.splitlines():
                if line.startswith("ERROR:"):
                    error_msg += line + "\n"
            
            if not error_msg:
                error_msg = result.stderr if result.stderr else "不明なエラーが発生しました。"
            
            return f"メールボックス情報の取得に失敗しました。\nエラー: {error_msg}{debug_info}"
    
    except Exception as e:
        return f"エラーが発生しました: {str(e)}"

if __name__ == "__main__":
    # MCPサーバーを起動
    mcp.run(transport='stdio')

6. 検証結果

AIシステムとしての機能検証

自然言語理解と処理面では、「xxxさんのメールボックス情報を教えて」のような自然な指示を理解し、曖昧な指示からの意図推測とパラメータ抽出ができました。

また、MCP連携による外部システム操作においては、Claude DesktopからMCPサーバー経由でのExchange Online接続、PowerShellコマンドの実行、結果の構造化と自然言語での説明が実現できました。

画面イメージ01

画面イメージ02

画面イメージ03

ユーザーエクスペリエンス評価

Claude Desktop上での操作性については、直感的な対話による操作が実現し、技術用語を使わない平易な説明と操作ガイダンスの提供ができています。

また、プロンプトを工夫することで結果を表形式で表示することができ、視認性の高いアウトプットも可能となってます。

画面イメージ04

7. 業務インパクトと展望

AI技術の実業務応用の成果

今回の検証を通して、MCPプロトコルによるAIと業務システムの標準的な接続方式の確立、FastMCPによるシンプルなPython実装の有効性が確認できました。専門知識なしでのExchange管理操作の実行や、複雑なPowerShellコマンドの抽象化により、運用管理コストの削減が期待できます。

ビジネスインパクト

実用化された場合のビジネスインパクトとして、以下が期待できます。

  • 管理タスクの工数削減
  • 属人化していた管理業務の標準化
  • エンドユーザーによるセルフサービス化の実現

AI活用の社内促進においても、AIの具体的な業務適用モデルとしての展開、他部門への横展開と応用事例の創出、AI活用人材の育成と組織能力の向上が期待されます。

8. まとめ

本検証を通じて、ClaudeとExchange Onlineを連携させるMCPサーバーの実装が可能であることが確認できました。こうした取り組みにより、IT管理者の業務効率化だけでなく、AIの実業務への適用モデルとしての価値も見出せました。

MCPという新しい標準の登場により、AIと業務システムの連携はより容易になり、今後さまざまな分野での応用が期待されます。

時間があればMgGraphコマンドなどにも対応させ、ユーザーの作成/変更/削除の一連の運用オペレーションが出来たらいいなと思ってます。

この記事が皆様のAI活用の参考になれば幸いです。

参考リンク

※本記事の実装例はコンセプト実証のために作成されたものであり、実環境での利用には適切なセキュリティ対策と検証が必要です。

Discussion