はじめに
第3章では、JiraのTicketやSprintデータを活用してプロジェクト分析エージェントを構築しました。進捗やパフォーマンスを分析することで、AIがプロジェクト管理のインサイトを提供し、プロセス改善を支援できるようになりました。今回は、JiraのWebhook機能を利用して、Ticketやステータス変更のイベントをリアルタイムで検知するリアルタイム管理AIを構築します。
この第4章では、MCPサーバーにJiraのWebhookを統合し、Ticket作成やステータス変更などのイベントを即座に捕捉します。AIはこれを利用して、自動コメントを追加したり、イベントを他のツール(例:Slack)に通知したりできます。コード例とステップごとのガイドで、リアル thời gian管理AIの構築を体験しましょう。さあ、始めましょう!
リアルタイム管理AIとは?
リアルタイム管理AIは、Jiraプロジェクトのイベント(Ticket作成、ステータス変更、コメント追加など)を監視し、プロジェクト管理を動的に支援するエージェントです。MCPサーバーとJiraのWebhookを組み合わせることで、以下のような機能を実現できます:
- イベント検知:新しいTicket、ステータス変更、コメントをリアルタイムで捕捉。
- 自動応答:特定のイベント(例:Ticket作成)に基づいてコメントや優先度を追加。
- 外部連携:イベントをSlackやメールに通知し、コラボレーションを強化。
ユースケース
- プロジェクト管理:AIが「バグ」Ticket作成時に自動で「High」優先度を付ける。
- チーム通知:重要なイベント(例:Ticketの期限超過)にSlackで通知。
- プロセス監視:意図しないイベント(例:未レビューでステータス変更)を検出。
開発環境の準備
第3章の環境を基に、以下の追加準備を行います:
- Python 3.8以降、mcpライブラリ、requestsライブラリ、Claude Desktop:これまでと同じ。
- python-dotenv:環境変数の管理(既にインストール済み)。
- ngrok:ローカルサーバーを公開し、Webhookを受信。
- Jiraプロジェクト:Webhook対応の設定。
インストールコマンド(必要に応じて):
pip install requests python-dotenv
Jiraのセットアップ
-
Jira APIトークンの確認:
- 第3章のトークンを使用。
- 権限を確認:プロジェクトでのTicket操作(読み書き)、Webhook管理。
-
Webhookの設定:
- Jiraインスタンス(例:
https://your-domain.atlassian.net
)の「System」→「Webhooks」に移動(管理者権限が必要)。 - 新しいWebhookを追加:
-
Name:例:
MCP-Webhook
。 -
URL:ngrokで生成するURL(例:
https://abc123.ngrok.io/webhook
)。 -
Events:
Issue created
、Issue updated
、Comment created
を選択。 -
JQL filter:
project = MCP
(プロジェクトMCPに限定)。 - Status:Enabled。
-
Name:例:
- シークレット(オプション):Webhook署名検証用の文字列を設定(例:
mysecret
)。
- Jiraインスタンス(例:
-
プロジェクト準備:
- 第3章のプロジェクト(例:
MCP-TEST
、キー:MCP
)を使用。 - Ticketやコメントを作成し、イベントを生成(例:Ticketを開く、ステータスを変更)。
- 第3章のプロジェクト(例:
-
ngrokの設定:
- ngrokをインストール(
brew install ngrok
または公式サイト)。 - ローカルサーバーを公開:
ngrok http 8135
- 生成されたURLを記録(例:
https://abc123.ngrok.io
)。 - JiraのWebhook設定にURLを設定(例:
https://abc123.ngrok.io/webhook
)。
- ngrokをインストール(
-
環境変数:
第3章の.env
ファイルに以下を追加:JIRA_URL=https://your-domain.atlassian.net JIRA_EMAIL=your_email@example.com JIRA_API_TOKEN=your_jira_api_token JIRA_PROJECT_KEY=MCP JIRA_WEBHOOK_SECRET=mysecret
コード例:リアルタイム管理用MCPサーバー
以下のMCPサーバーは、JiraのWebhookを介してイベントを検知し、自動コメントやイベント記録の機能を提供します。
from mcp import MCPServer
import os
from dotenv import load_dotenv
import requests
from requests.auth import HTTPBasicAuth
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
import hmac
import hashlib
import threading
class JiraRealtimeServer(MCPServer):
def __init__(self, host, port, url, email, api_token, project_key, webhook_secret):
super().__init__(host, port)
self.url = url
self.email = email
self.api_token = api_token
self.project_key = project_key
self.webhook_secret = webhook_secret
self.base_url = f"{url}/rest/api/3"
self.auth = HTTPBasicAuth(email, api_token)
self.headers = {
"Accept": "application/json",
"Content-Type": "application/json"
}
self.latest_event = None
self.register_resource("get_latest_event", self.get_latest_event)
self.register_tool("add_comment", self.add_comment)
self.start_webhook_server()
def verify_webhook_signature(self, body, signature):
try:
computed_sig = "sha256=" + hmac.new(
self.webhook_secret.encode("utf-8"),
body.encode("utf-8"),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(computed_sig, signature)
except Exception as e:
return False
def add_comment(self, params):
try:
ticket_key = params.get("ticket_key", "")
comment = params.get("comment", "")
if not ticket_key or not comment:
return {"status": "error", "message": "Ticketキーとコメントが必要です"}
url = f"{self.base_url}/issue/{ticket_key}/comment"
payload = {"body": comment}
response = requests.post(url, headers=self.headers, auth=self.auth, json=payload)
response.raise_for_status()
comment = response.json()
return {"status": "success", "comment_id": comment["id"]}
except Exception as e:
return {"status": "error", "message": str(e)}
def get_latest_event(self, params):
try:
if self.latest_event:
event_type = self.latest_event.get("event", "")
event = self.latest_event.get("payload", {})
event_info = {
"event_type": event_type,
"action": event.get("webhookEvent", ""),
"ticket_key": event.get("issue", {}).get("key", ""),
"user": event.get("user", {}).get("displayName", "unknown"),
"created_at": event.get("issue", {}).get("fields", {}).get("created", "")
}
return {"status": "success", "event_info": event_info}
return {"status": "success", "event_info": None, "message": "イベントなし"}
except Exception as e:
return {"status": "error", "message": str(e)}
def start_webhook_server(self):
class WebhookHandler(BaseHTTPRequestHandler):
def do_POST(self):
content_length = int(self.headers["Content-Length"])
post_data = self.rfile.read(content_length)
signature = self.headers.get("X-Hub-Signature-256", "")
# Webhook署名検証
if not self.server.parent.verify_webhook_signature(post_data.decode("utf-8"), signature):
self.send_response(401)
self.end_headers()
self.wfile.write(b"Invalid signature")
return
data = json.loads(post_data.decode("utf-8"))
event_type = data.get("webhookEvent", "").split(":")[0]
# イベント処理
if event_type in ["jira:issue_created", "jira:issue_updated", "comment_created"]:
self.server.parent.latest_event = {"event": event_type, "payload": data}
self.send_response(200)
self.end_headers()
self.wfile.write(b"Webhook received")
server = HTTPServer(("localhost", 8135), WebhookHandler)
server.parent = self
threading.Thread(target=server.serve_forever, daemon=True).start()
print("Webhookサーバーを起動中: http://localhost:8135")
if __name__ == "__main__":
load_dotenv()
server = JiraRealtimeServer(
host="localhost",
port=8135,
url=os.getenv("JIRA_URL"),
email=os.getenv("JIRA_EMAIL"),
api_token=os.getenv("JIRA_API_TOKEN"),
project_key=os.getenv("JIRA_PROJECT_KEY"),
webhook_secret=os.getenv("JIRA_WEBHOOK_SECRET")
)
print("JiraリアルタイムMCPサーバーを起動中: http://localhost:8135")
server.start()
コードの説明
-
verify_webhook_signature:JiraのWebhook署名(
X-Hub-Signature-256
)をHMAC-SHA256で検証。 - add_comment:指定したTicketにコメントを追加。Ticketキーとコメント内容を指定。
- get_latest_event:Webhookで受信した最新イベント(Ticket作成、更新、コメント)を取得。
- start_webhook_server:ローカルWebhookサーバーを起動し、Jiraからのイベントを処理。
- WebhookHandler:Jiraのイベント(Issue created、updated、comment created)を受信し、署名検証を行う。
前提条件
- JiraプロジェクトにWebhookが設定済み(
jira:issue_created
、jira:issue_updated
、comment_created
イベント)。 - ngrokでWebhook URLが公開され、Jiraに登録済み。
-
.env
ファイルに正しいJIRA_URL
、JIRA_EMAIL
、JIRA_API_TOKEN
、JIRA_PROJECT_KEY
、JIRA_WEBHOOK_SECRET
が設定済み。 - APIトークンにプロジェクトへの読み書き権限がある。
サーバーのテスト
サーバーが正しく動作するか確認します:
-
ngrok起動:
ngrok http 8135
ngrok URL(例:
https://abc123.ngrok.io
)を記録し、JiraのWebhook設定に設定(例:https://abc123.ngrok.io/webhook
)。 -
サーバー起動:
python jira_realtime_server.py
コンソールに「JiraリアルタイムMCPサーバーを起動中: http://localhost:8135」と「Webhookサーバーを起動中: http://localhost:8135」が表示。
-
イベント検知のテスト:
- JiraのUIでプロジェクトにTicketを作成(例:「バグ報告」)またはステータスを変更。
- サーバーがイベントをWebhook経由で検知。
-
最新イベント取得のテスト:
Pythonでリクエストを送信:import requests import json url = "http://localhost:8135" payload = { "jsonrpc": "2.0", "method": "get_latest_event", "params": {}, "id": 1 } response = requests.post(url, json=payload) print(json.dumps(response.json(), indent=2, ensure_ascii=False))
期待されるレスポンス:
{ "jsonrpc": "2.0", "result": { "status": "success", "event_info": { "event_type": "jira:issue_created", "action": "jira:issue_created", "ticket_key": "MCP-5", "user": "Your Name", "created_at": "2025-04-22T14:00:00.000+0000" } }, "id": 1 }
-
自動コメントのテスト:
payload = { "jsonrpc": "2.0", "method": "add_comment", "params": { "ticket_key": "MCP-5", "comment": "Ticketを確認しました。詳細を教えてください。" }, "id": 2 } response = requests.post(url, json=payload) print(json.dumps(response.json(), indent=2, ensure_ascii=False))
期待されるレスポンス:
{ "jsonrpc": "2.0", "result": { "status": "success", "comment_id": "10002" }, "id": 2 }
Claude Desktopとの接続
サーバーをClaude Desktopに接続します:
-
設定ファイルの編集:
Claude Desktopの設定ファイル(例:claude_desktop_config.json
)に以下を追加:{ "mcp_servers": [ { "name": "JiraRealtimeServer", "url": "http://localhost:8135", "auth": "none" } ] }
-
Claudeでテスト:
Claude Desktopを起動し、プロンプトを入力:最新のプロジェクトイベントを教えてください。
レスポンス例:
最新のプロジェクトイベント: - イベント:Ticket作成 - アクション:jira:issue_created - Ticketキー:MCP-5 - ユーザー:Your Name - 作成日時:2025-04-22 14:00
別のプロンプト:
Ticket MCP-5に「Ticketを確認しました。詳細を教えてください。」とコメントしてください。
レスポンス例:
Ticket MCP-5にコメントを追加しました。
実装のコツと注意点
-
Webhook検証:Jiraの署名検証(
X-Hub-Signature-256
)を正しく処理。 - レートリミティング:Jira APIの制限(例:600リクエスト/分、クラウドインスタンスによる)に注意。
- セキュリティ:本番環境では、HTTPSを有効化し、Webhookシークレットを必須化。
- テスト:テスト用プロジェクトを作成し、本番データに影響を与えない。
- 拡張性:大量のイベントを処理する場合、キュー(例:Redis、RabbitMQ)を検討。
試してみよう:挑戦課題
以下の機能を追加して、エージェントを強化してみてください:
- 「バグ」キーワードを含むTicket作成時に「High」優先度を自動付与。
- ステータス変更イベントを検知し、Slackに通知する機能。
- イベントデータをJiraに新しいTicketとして記録するツール。
まとめと次のステップ
この第4章では、JiraのWebhookを活用してリアルタイム管理AIを構築しました。Ticketやステータス変更のイベントをリアルタイムで検知し、AIが自動コメントや通知を行えるようになりました。
次の第5章では、MCPサーバーの最適化とコミュニティへの貢献に焦点を当てます。サーバーのパフォーマンス向上、セキュリティ強化、そしてJira用MCPサーバーをオープンソースとして共有する方法を学びます。コミュニティAIの未来に興味がある方は、ぜひお楽しみに!
役に立ったと思ったら、「いいね」や「ストック」をしていただけると嬉しいです!次の章でまたお会いしましょう!