🚀 サファリコム・ダラジャMCPサーバー
このサーバーは、Model Context Protocol (MCP) をベースに構築されており、サファリコムのM-PESAダラジャAPIとClaudeを統合し、自然言語による支払い処理とリアルタイムの取引通知を可能にします。
🚀 クイックスタート
このサーバーを使用するには、まず必要な前提条件を満たし、インストールと設定を行います。その後、サーバーを起動して、Claudeとの統合を行うことができます。
✨ 主な機能
- STKプッシュ支払い:自然言語でM-PESAの支払いリクエストを開始できます。
- リアルタイムコールバック:Flaskサーバーを使用して、自動的に支払い通知を処理します。
- 支払い追跡:支払い履歴を読了/未読ステータスとともに保存し、照会できます。
- 自然言語インターフェース:Claudeの会話を通じてM-PESAと対話できます。
- サンドボックステスト:ダラジャのサンドボックス環境を完全にサポートします。
- 自動テスト:包括的なテストスイートを提供し、検証を行います。
📦 インストール
1. リポジトリをクローンする
git clone https://github.com/mboya/daraja-mcp.git
cd daraja-mcp
cd daraja-mcp
2. 仮想環境をセットアップする
python3 -m venv venv
source venv/bin/activate
venv\Scripts\activate
ターミナルのプロンプトに (venv) が表示されれば成功です。
3. 依存関係をインストールする
pip install -r requirements.txt
これにより、以下のパッケージがインストールされます:
mcp - Model Context Protocolサーバー
requests - API呼び出し用のHTTPライブラリ
flask - コールバックサーバー用のWebフレームワーク
python-dotenv - 環境変数管理
gunicorn - WSGI HTTPサーバー(本番デプロイ用)
4. 環境変数を設定する
プロジェクトのルートディレクトリに .env ファイルを作成します。リポジトリには .env.example ファイルがテンプレートとして含まれています。
クイックセットアップ:
cp .env.example .env
nano .env
その後、以下のセクション「ダラジャの資格情報の取得」で説明するように、プレースホルダー値を実際のダラジャAPIの資格情報に置き換えます。
注意: 以下の「server.pyとserver_http.pyの選択」セクションを参照して、使用するサーバーファイルを選択してください。
💻 使用例
基本的な使用法
サーバーの起動
source venv/bin/activate
python server.py
期待される出力:
🚀 Daraja MCP Server starting...
📡 Callback server running on 0.0.0.0:3000
🌐 Public callback URL: http://localhost:3000/mpesa/callback
🔧 Environment: sandbox
本番/クラウドデプロイメント用
source venv/bin/activate
python server_http.py
gunicorn server_http:app --bind 0.0.0.0:$PORT --workers 2
期待される出力:
🚀 Daraja MCP Server (HTTP Mode)
📡 Listening on port 3000
🌐 Public URL: http://localhost:3000
🔧 Environment: sandbox
高度な使用法
サーバーコンポーネント
MCPサーバーは、2つのコンポーネントを同時に実行します:
- MCPプロトコルサーバー - stdioを介してClaudeと通信します。
- Flaskコールバックサーバー - ポート3000でM-PESAの支払い通知を受信します。
server.pyとserver_http.pyの選択
このプロジェクトには、異なるユースケースに対応する2つのサーバー実装が含まれています:
server.py - ローカルのClaude Desktop統合(stdio)用
使用する場合:
- MCPサーバーをローカルマシンで実行する場合
- Claude Desktopアプリケーションと統合する場合
- ローカルで開発およびテストする場合
- MCP通信にstdio(標準入出力)を使用する場合
機能:
- stdioプロトコルを介してClaude Desktopと通信します。
- Flaskコールバックサーバーをバックグラウンドスレッドで実行します。
- すべての機能を備えた完全なMCPツール実装です。
- ローカル開発およびテストに最適です。
使用方法:
python server.py
server_http.py - リモートデプロイメント(HTTP)用
使用する場合:
- クラウドプラットフォーム(Railway、Heroku、AWSなど)にデプロイする場合
- 本番環境で実行する場合
- HTTPベースのMCPエンドポイントが必要な場合
- gunicornまたは同様のWSGIサーバーを使用する場合
機能:
- MCP HTTPエンドポイントとコールバックを組み合わせた単一のFlaskアプリです。
/mcp/tools と /mcp/call_tool エンドポイントを公開します。
- 本番デプロイ用にgunicornと互換性があります。
- RailwayのProcfile構成と互換性があります。
使用方法:
gunicorn server_http:app --bind 0.0.0.0:$PORT --workers 2
python server_http.py
Railwayデプロイメント:
Procfile は、gunicornで server_http.py を使用するように構成されています:
web: gunicorn server_http:app --bind 0.0.0.0:$PORT --workers 2
要約:
- Claude Desktopを使用したローカル開発 →
server.py を使用する
- クラウド/本番デプロイメント →
server_http.py を使用する
📚 詳細ドキュメント
前提条件
ダラジャの資格情報の取得
1. ダラジャポータルに登録する
- developer.safaricom.co.ke にアクセスする
- アカウントを作成する
- メールを検証する
2. アプリを作成する
- 「My Apps」→「Create New App」に移動する
- 以下のAPIを選択する:
- Lipa Na M-PESA Online
- M-PESA Express (STK Push)
- アプリを提出する
- 以下の資格情報を取得する:
- コンシューマーキー
- コンシューマーシークレット
- パスキー(アプリ詳細にあります)
3. サンドボックステスト用の資格情報
テストには、以下のサンドボックス値を使用します:
- ビジネスショートコード:174379(デフォルトのサンドボックス)
- パスキー:ダラジャポータルのアプリ詳細を確認してください
- テスト用電話番号:254708374149(最新のテスト番号はダラジャのドキュメントを参照してください)
- テスト用PIN:サンドボックスバージョンによって異なります(通常は自動的にシミュレートされます)
4. 本番用の資格情報
- サンドボックスで十分にテストする
- ダラジャポータルを通じて本番アクセスを申請する
- KYCとビジネス検証を完了する
- 本番用の資格情報を受け取る
.env を本番用の値で更新し、DARAJA_ENV=production を設定する
コールバックのセットアップ
ngrok(または同様のトンネリングサービス)が必要な理由
問題:
- M-PESAダラジャAPIは HTTPSコールバック を必要とします(HTTPではありません)
- サファリコムのサーバーは、インターネットからコールバックエンドポイントにアクセスする必要があります
- ローカル開発サーバー(
localhost:3000)はインターネットからアクセスできません
- ファイアウォールとNATにより、ローカルマシンへの外部アクセスが制限されています
解決策:
ngrokは、以下のような安全なトンネルを作成します:
- ✅ ローカルサーバーをHTTPSでインターネットに公開します
- ✅ サファリコムがアクセスできる公開URLを提供します
- ✅ SSL/TLS暗号化を自動的に処理します
- ✅ 本番環境にデプロイせずにリアルタイムテストを可能にします
- ✅ すべての着信リクエストをWebインターフェースで表示し、デバッグに役立ちます
動作原理:
Safaricom Servers → ngrok HTTPS URL → ngrok Tunnel → Your Local Server (localhost:3000)
ngrokを使用したローカルテスト
1. ngrokをインストールする
brew install ngrok
sudo snap install ngrok
無料でサインアップする: ngrok.com にアクセスし、アカウントを作成してオートトークンを取得します。
2. ngrokを認証する(初回のみ)
ngrok config add-authtoken YOUR_AUTHTOKEN_HERE
3. ngrokトンネルを開始する
ngrok http 3000
出力:
Session Status online
Account Your Name (Plan: Free)
Version 3.x.x
Region United States (us)
Latency 45ms
Web Interface http://127.0.0.1:4040
Forwarding https://abc123.ngrok.io -> http://localhost:3000
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
重要: Forwarding のHTTPS URL(例:https://abc123.ngrok.io)をコピーしてください。
4. 設定を更新する
.env ファイルの PUBLIC_URL を更新します:
PUBLIC_URL=https://abc123.ngrok.io
または、Claude Desktopの設定にngrok URLを更新します。
注意: 無料のngrok URLは、ngrokを再起動するたびに変更されます。静的なURLが必要な場合は、有料プランにアップグレードするか、ngrokの予約ドメイン機能を使用してください。
5. サーバーを再起動する
python server.py
6. ngrokが正常に動作していることを確認する
ngrokのWebインターフェースを確認する:
- ブラウザで http://localhost:4040 を開きます
- ngrokを通じて転送されるすべてのリクエストが表示されます
- コールバックの問題をデバッグするのに役立ちます
トンネルをテストする:
curl https://abc123.ngrok.io/health
7. ngrokを実行し続ける
重要: テスト中はngrokのターミナルウィンドウを開いたままにしてください。閉じると、トンネルが停止し、サファリコムがコールバックエンドポイントにアクセスできなくなります。
プロのヒント: ngrokを別のターミナルで実行するか、tmux または screen のようなプロセスマネージャを使用します:
tmux new -s ngrok
ngrok http 3000
ngrokの代替手段
他のトンネリングサービスを使用する場合は、以下のものがあります:
- Cloudflare Tunnel (cloudflared) - 基本的な使用には無料で、アカウントが必要ありません
cloudflared tunnel --url http://localhost:3000
- localtunnel - シンプルなnpmベースのトンネル
npx localtunnel --port 3000
- serveo - SSHベースのトンネル(インストール不要)
ssh -R 80:localhost:3000 serveo.net
ただし、ngrokが推奨されます。理由は以下の通りです:
- 最も信頼性が高く、安定しています
- 最良のドキュメントとコミュニティサポートがあります
- リクエストの検査用のWebインターフェースがあります
- 使用と設定が簡単です
本番環境でのコールバックセットアップ
本番環境では、以下の条件を満たすサーバーにデプロイします:
- 公開HTTPSエンドポイント(SSL証明書が必要)
- 静的IPまたはドメイン名
- ファイアウォールルール - 着信HTTPSトラフィックを許可する
- 監視とロギング
人気のあるオプション:
- AWS EC2 with Elastic IP
- DigitalOcean Droplet
- Heroku with SSL
- Google Cloud Run
- Railway(推奨 - 以下のデプロイメントガイドを参照)
nginxの設定例:
server {
listen 443 ssl;
server_name api.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location /mpesa/ {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Railwayデプロイメント(クイックスタート)
Railwayは、このMCPサーバーをデプロイするのに優れた選択肢です。理由は以下の通りです:
- ✅ 自動的にHTTPSエンドポイントを提供します
- ✅ SSL証明書を処理します
- ✅ 環境変数の設定が簡単です
- ✅ Gitからの自動デプロイが可能です
- ✅ テスト用の無料プランがあります
Railwayデプロイメントの手順
- Railwayアカウントを作成する
- 新しいプロジェクトを作成する
- 「New Project」をクリックする
- 「Deploy from GitHub repo」を選択する(またはコードをアップロードする)
- 環境変数を設定する
Railwayダッシュボードで、以下の環境変数を追加します:
DARAJA_CONSUMER_KEY=your_consumer_key
DARAJA_CONSUMER_SECRET=your_consumer_secret
DARAJA_SHORTCODE=174379
DARAJA_PASSKEY=your_passkey
DARAJA_ENV=sandbox
CALLBACK_PORT=3000
PUBLIC_URL=https://your-app-name.railway.app
注意:Railwayでは、アプリはgunicornによって 0.0.0.0:$PORT に自動的にバインドされるため、CALLBACK_HOST を設定する必要はありません。
- デプロイする
- Railwayは
Procfile と railway.json を自動的に検出します
Procfile はgunicornで server_http.py を使用します
- Railwayは自動的にビルドとデプロイを行います
- 公開URLを取得する
- Railwayは公開HTTPS URL(例:
https://your-app.railway.app)を提供します
- このURLで
PUBLIC_URL 環境変数を更新します
- Railwayはサービスを自動的に再起動します
- デプロイを確認する
curl https://your-app.railway.app/health
重要な注意事項:
- Railwayは自動的にHTTPSを提供するため、本番環境ではngrokは必要ありません
PUBLIC_URL はRailwayアプリのURLと正確に一致する必要があります
- Railwayデプロイメントには
server_http.py を使用します(Procfile で構成されています)
- Railwayは
$PORT 環境変数を介してポートのバインドを自動的に処理します
トラブルシューティング
一般的な問題
1. "Failed to get access token"
原因:
- 無効なコンシューマーキーまたはシークレット
- 誤った環境(サンドボックスと本番環境の混同)
- ネットワーク接続の問題
解決策:
python -c "
from dotenv import load_dotenv
import os, base64, requests
load_dotenv()
key = os.getenv('DARAJA_CONSUMER_KEY')
secret = os.getenv('DARAJA_CONSUMER_SECRET')
auth = base64.b64encode(f'{key}:{secret}'.encode()).decode()
r = requests.get('https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials',
headers={'Authorization': f'Basic {auth}'})
print(r.json())
"
2. "Callback server not responding"
解決策:
lsof -i :3000
kill -9 <PID>
python server.py
3. "MCP server not found in Claude"
解決策:
- 設定ファイルのパスが正しいことを確認する
- 設定で絶対パスを使用する
- 仮想環境のPythonパスが正しいことを確認する
- Claude Desktopのログを確認する:Help → View Logs
- Claude Desktopを完全に再起動する
4. "No callbacks received"
解決策:
- ngrokが実行中であることを確認する:
curl https://your-url.ngrok.io/health
- PUBLIC_URL環境変数を確認する
- ngrok URLがHTTPSであることを確認する(サファリコムが必要とする)
- ngrokのリクエストログを確認する:http://localhost:4040
- ファイアウォール設定を確認する
5. "Invalid phone number"
解決策:
- 形式を 254XXXXXXXXX(+254や07XXではない)にする
- サンドボックス:ダラジャポータルのテスト番号を使用する
- スペース、ダッシュ、または特殊文字を削除する
デバッグコマンド
ps aux | grep server.py
curl http://localhost:3000/health
curl https://your-ngrok-url.ngrok.io/health
tail -f server.log
ヘルプの取得
- ダラジャAPIのドキュメントを確認する:developer.safaricom.co.ke/Documentation
- ngrokのリクエストインスペクターを確認する:http://localhost:4040
- Claude Desktopのログを確認する
- すべての環境変数が正しく設定されていることを確認する
- 各コンポーネントを独立してテストする
セキュリティのベストプラクティス
1. 資格情報の管理
- ✅ 資格情報をバージョン管理にコミットしない
- ✅
.env ファイルと .gitignore を使用する
- ✅ 定期的に資格情報を更新する
- ✅ サンドボックスと本番環境で異なる資格情報を使用する
- ✅ 本番環境のシークレットを安全なボールト(AWS Secrets Managerなど)に保存する
2. ネットワークセキュリティ
- ✅ すべてのコールバックにHTTPSを使用する(サファリコムが要求する)
- ✅ ウェブフックの署名検証を実装する
- ✅ コールバックエンドポイントをサファリコムのIPに制限する
- ✅ ファイアウォールルールを使用してアクセスを制限する
- ✅ レート制限を有効にする
3. アプリケーションセキュリティ
- ✅ すべての入力データを検証する
- ✅ 電話番号と金額をサニタイズする
- ✅ リクエストロギングを実装する
- ✅ 機密操作に認証を追加する
- ✅ 環境固有の設定を使用する
4. データプライバシー
- ✅ 機密データ(PIN、クレジットカード番号など)をログに記録しない
- ✅ ログ内の電話番号をマスクする
- ✅ データ保持ポリシーを実装する
- ✅ データ保護規制に準拠する
- ✅ データを保存時と転送時に暗号化する
5. 監視
- ✅ エラーアラートを設定する
- ✅ コールバックの成功率を監視する
- ✅ 失敗したトランザクションを追跡する
- ✅ すべてのAPI呼び出しをログに記録する
- ✅ ヘルスチェックを実装する
本番デプロイメント
デプロイ前のチェックリスト
- [ ] サンドボックス環境で十分にテストされている
- [ ] ダラジャから本番用の資格情報を取得している
- [ ] SSL/TLSを備えた本番サーバーをセットアップしている
- [ ] ファイアウォールとセキュリティグループを構成している
- [ ] 適切なロギングと監視を実装している
- [ ] エラーアラートを設定している
- [ ] デプロイメントプロセスを文書化している
- [ ] バックアップと復元計画を作成している
- [ ] まず少量でテストしている
- [ ] 失敗時の自動再起動を設定している
デプロイメント手順
1. サーバーを準備する
sudo apt update && sudo apt upgrade -y
sudo apt install python3.10 python3.10-venv -y
sudo apt install nginx -y
sudo apt install supervisor -y
2. アプリケーションをデプロイする
sudo mkdir -p /opt/daraja-mcp
sudo chown $USER:$USER /opt/daraja-mcp
cd /opt/daraja-mcp
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
nano .env
3. Supervisorを構成する
/etc/supervisor/conf.d/daraja-mcp.conf を作成します:
[program:daraja-mcp]
command=/opt/daraja-mcp/venv/bin/python /opt/daraja-mcp/server.py
directory=/opt/daraja-mcp
user=www-data
autostart=true
autorestart=true
stderr_logfile=/var/log/daraja-mcp/error.log
stdout_logfile=/var/log/daraja-mcp/access.log
environment=PRODUCTION="true"
4. nginxを構成する
/etc/nginx/sites-available/daraja-mcp を作成します:
server {
listen 80;
server_name api.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name api.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
5. サービスを起動する
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start daraja-mcp
sudo ln -s /etc/nginx/sites-available/daraja-mcp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
sudo supervisorctl status daraja-mcp
curl https://api.yourdomain.com/health
監視とメンテナンス
sudo tail -f /var/log/daraja-mcp/error.log
sudo supervisorctl restart daraja-mcp
htop
sudo tail -f /var/log/nginx/access.log
🔧 技術詳細
ダラジャAPIエンドポイント
認証
GET https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials
Authorization: Basic <base64(consumer_key:consumer_secret)>
STKプッシュ
POST https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest
Authorization: Bearer <access_token>
Content-Type: application/json
{
"BusinessShortCode": "174379",
"Password": "<base64(shortcode+passkey+timestamp)>",
"Timestamp": "20240108143022",
"TransactionType": "CustomerPayBillOnline",
"Amount": 100,
"PartyA": "254712345678",
"PartyB": "174379",
"PhoneNumber": "254712345678",
"CallBackURL": "https://your-domain.com/callback",
"AccountReference": "Order123",
"TransactionDesc": "Payment for Order123"
}
STKクエリ
POST https://api.safaricom.co.ke/mpesa/stkpushquery/v1/query
Authorization: Bearer <access_token>
Content-Type: application/json
{
"BusinessShortCode": "174379",
"Password": "<base64(shortcode+passkey+timestamp)>",
"Timestamp": "20240108143022",
"CheckoutRequestID": "ws_CO_08012024123456789"
}
MCPサーバーエンドポイント
ヘルスチェック
GET http://localhost:3000/health
Response:
{
"status": "healthy",
"callback_url": "http://localhost:3000/mpesa/callback",
"unread_payments": 0
}
M-PESAコールバック
POST http://localhost:3000/mpesa/callback
Content-Type: application/json
{
"Body": {
"stkCallback": {
"MerchantRequestID": "29115-34620561-1",
"CheckoutRequestID": "ws_CO_08012024123456789",
"ResultCode": 0,
"ResultDesc": "The service request is processed successfully.",
"CallbackMetadata": {
"Item": [
{"Name": "Amount", "Value": 100},
{"Name": "MpesaReceiptNumber", "Value": "QAR7I8K3LM"},
{"Name": "TransactionDate", "Value": 20240108143022},
{"Name": "PhoneNumber", "Value": 254712345678}
]
}
}
}
}
プロジェクト構造
daraja-mcp/
├── venv/ # 仮想環境(gitに含まれない)
├── server.py # ローカルのClaude Desktop用のMCPサーバー(stdio)
├── server_http.py # クラウドデプロイメント用のMCPサーバー(HTTP)
├── test_daraja.py # 包括的なテストスイート
├── quick_test.py # クイックバリデーションスクリプト
├── Procfile # Railwayデプロイメント構成
├── railway.json # Railwayプラットフォーム構成
├── .env # 環境変数(gitに含まれない)
├── .gitignore # Gitの無視ルール
├── requirements.txt # Pythonの依存関係
├── README.md # このファイル
└── docs/ # 追加のドキュメント
├── DEPLOYMENT.md # デプロイメントガイド
├── API.md # APIドキュメント
└── TROUBLESHOOTING.md # 拡張トラブルシューティング
重要なファイル:
server.py - Claude Desktopを使用したローカル開発(stdioプロトコル)用に使用する
server_http.py - Railwayなどのクラウドデプロイメント(HTTPエンドポイント)用に使用する
Procfile - Railwayがアプリケーションを実行する方法を定義します(server_http.py を使用します)
railway.json - Railwayプラットフォームの構成(ビルダー、レプリカ、再起動ポリシー)
📄 ライセンス
このプロジェクトはMITライセンスの下でライセンスされています。詳細については、LICENSE ファイルを参照してください。
謝辞
サポート
変更履歴
v1.0.0 (2024-01-08)
- 最初のリリース
- STKプッシュの実装
- リアルタイムコールバックの処理
- 支払い通知の保存
- 自動テストスイート
- Claude Desktopとの統合
- 包括的なドキュメント
M-PESAエコシステムのために愛をこめて作られました
質問やサポートが必要な場合は、GitHubで問題を開くか、メンテナーに連絡してください。