1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JiraでAIを強化する | 第1章:Ticketデータの第一歩

Posted at

はじめに

Jiraは、プロジェクト管理、課題追跡、Agile開発をサポートする業界標準のプラットフォームです。Ticket(課題)、Sprint、ワークフローを管理し、強力なREST APIとWebhookでデータの取得や自動化が可能です。一方、**Model Context Protocol(MCP)**は、AI(例:Claude)を外部データやツールと標準化された方法で接続するプロトコルです。このシリーズでは、JiraとMCPを統合し、Ticketデータを活用するエージェントAIを構築する方法を学びます。たとえば、AIがTicketを分析したり、プロジェクトの進捗を評価したりできます。

第1章では、JiraとMCPの基本を理解し、JiraプロジェクトからTicketやSprintデータを取得するシンプルなMCPサーバーを構築します。Claude Desktopと接続して、プロジェクト管理の第一歩を踏み出しましょう。

JiraとMCPの概要

Jiraとは?

Jiraは、以下のような特徴を持つプロジェクト管理プラットフォームです:

  • Ticket管理:課題(Issue)、バグ、タスクを追跡。
  • 強力なAPI:REST APIでTicket、Sprint、ユーザー、プロジェクトデータにアクセス。
  • Webhookサポート:リアルタイムイベント(Ticket作成、ステータス変更など)を検知。
  • 多用途:ソフトウェア開発からビジネスプロジェクトまで対応。

MCPの役割

MCPは、AIにJiraのデータを提供する橋渡し役です。MCPサーバーを通じて、AIは以下を行えます:

  • データ取得:Ticket、Sprint、コメント情報を取得。
  • アクション実行:Ticket作成、コメント追加、ステータス更新。
  • 分析:プロジェクトの進捗やチームのパフォーマンスを評価。

なぜJiraとMCPを組み合わせる?

この組み合わせは、以下のようなシナリオで強力です:

  • 自動Ticket管理:AIがバグ報告を分類し、適切な優先度を設定。
  • 進捗分析:AIがSprintの完了率や遅延リスクを評価。
  • 通知最適化:AIが重要なイベント(例:期限超過)をSlackやメールで通知。

開発環境の準備

MCPサーバーとJiraを統合するには、以下の環境を準備します:

  • Python 3.8以降:サーバー開発用。
  • mcpライブラリ:JSON-RPC通信を処理(仮定のライブラリ、公式ドキュメントを参照)。
  • requestsライブラリ:Jira APIとの通信用。
  • Claude Desktop:MCP対応のAIクライアント。
  • テキストエディタ:VS Code推奨。

インストールコマンド:

pip install mcp jsonrpcserver requests python-dotenv

Jiraのセットアップ

  1. Jira APIトークンの作成
    • Atlassian Accountにアクセスし、APIトークンを生成。
    • トークンを保存(例:your_jira_api_token)。
  2. Jiraプロジェクト準備
    • テスト用プロジェクト(例:MCP-TEST)を作成。
    • Ticketをいくつか追加(例:「バグ修正」「新機能開発」)。
    • Sprintを1つ作成し、Ticketを割り当て。
    • プロジェクトキー(例:MCP)とJiraインスタンスURL(例:https://your-domain.atlassian.net)を記録。
  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用MCPサーバー

from mcp import MCPServer
import os
from dotenv import load_dotenv
import requests
from requests.auth import HTTPBasicAuth

class JiraServer(MCPServer):
    def __init__(self, host, port, url, email, api_token, project_key):
        super().__init__(host, port)
        self.url = url
        self.email = email
        self.api_token = api_token
        self.project_key = project_key
        self.base_url = f"{url}/rest/api/3"
        self.auth = HTTPBasicAuth(email, api_token)
        self.headers = {"Accept": "application/json"}
        self.register_resource("get_tickets", self.get_tickets)
        self.register_resource("get_sprints", self.get_sprints)

    def get_tickets(self, params):
        try:
            url = f"{self.base_url}/search"
            query = {
                "jql": f"project={self.project_key} AND status={params.get('status', 'Open')}",
                "maxResults": params.get("limit", 10)
            }
            response = requests.get(url, headers=self.headers, auth=self.auth, params=query)
            response.raise_for_status()
            issues = response.json()["issues"]
            ticket_list = [
                {
                    "key": issue["key"],
                    "summary": issue["fields"]["summary"],
                    "status": issue["fields"]["status"]["name"],
                    "creator": issue["fields"]["creator"]["displayName"],
                    "created": issue["fields"]["created"]
                }
                for issue in issues
            ]
            return {"status": "success", "tickets": ticket_list}
        except Exception as e:
            return {"status": "error", "message": str(e)}

    def get_sprints(self, params):
        try:
            url = f"{self.base_url}/project/{self.project_key}/sprint"
            response = requests.get(url, headers=self.headers, auth=self.auth)
            response.raise_for_status()
            sprints = response.json()["values"]
            sprint_list = [
                {
                    "id": sprint["id"],
                    "name": sprint["name"],
                    "state": sprint["state"],
                    "start_date": sprint.get("startDate", ""),
                    "end_date": sprint.get("endDate", "")
                }
                for sprint in sprints
            ]
            return {"status": "success", "sprints": sprint_list}
        except Exception as e:
            return {"status": "error", "message": str(e)}

if __name__ == "__main__":
    load_dotenv()
    server = JiraServer(
        host="localhost",
        port=8132,
        url=os.getenv("JIRA_URL"),
        email=os.getenv("JIRA_EMAIL"),
        api_token=os.getenv("JIRA_API_TOKEN"),
        project_key=os.getenv("JIRA_PROJECT_KEY")
    )
    print("Jira MCPサーバーを起動中: http://localhost:8132")
    server.start()

コードの説明

  • requests:Jira APIにGETリクエストを送信し、TicketやSprintを取得。
  • get_tickets:プロジェクトのTicketを取得(キー、サマリー、ステータス、作成者、作成日)。
  • get_sprints:プロジェクトのSprintを取得(ID、名前、状態、開始日、終了日)。
  • register_resource:TicketとSprint取得をリソースとして登録。
  • start():サーバーを起動。

前提条件

  • Jira APIトークンが生成済み。
  • テスト用プロジェクトにTicketとSprintが存在。
  • .envファイルに正しいJIRA_URLJIRA_EMAILJIRA_API_TOKENJIRA_PROJECT_KEYが設定済み。
  • ユーザーにプロジェクトへのアクセス権限がある。

サーバーのテスト

サーバーが正しく動作するか確認します:

  1. サーバー起動

    python jira_server.py
    

    コンソールに「Jira MCPサーバーを起動中: http://localhost:8132」と表示。

  2. Ticket取得のテスト
    Pythonでリクエストを送信:

    import requests
    import json
    
    url = "http://localhost:8132"
    payload = {
        "jsonrpc": "2.0",
        "method": "get_tickets",
        "params": {"status": "Open", "limit": 5},
        "id": 1
    }
    response = requests.post(url, json=payload)
    print(json.dumps(response.json(), indent=2, ensure_ascii=False))
    

    期待されるレスポンス:

    {
      "jsonrpc": "2.0",
      "result": {
        "status": "success",
        "tickets": [
          {
            "key": "MCP-1",
            "summary": "バグ修正",
            "status": "Open",
            "creator": "Your Name",
            "created": "2025-04-22T10:00:00.000+0000"
          },
          {
            "key": "MCP-2",
            "summary": "新機能開発",
            "status": "Open",
            "creator": "Your Name",
            "created": "2025-04-22T11:00:00.000+0000"
          }
        ]
      },
      "id": 1
    }
    
  3. Sprint取得のテスト

    payload = {
        "jsonrpc": "2.0",
        "method": "get_sprints",
        "params": {},
        "id": 2
    }
    response = requests.post(url, json=payload)
    print(json.dumps(response.json(), indent=2, ensure_ascii=False))
    

    期待されるレスポンス:

    {
      "jsonrpc": "2.0",
      "result": {
        "status": "success",
        "sprints": [
          {
            "id": 1,
            "name": "Sprint 1",
            "state": "ACTIVE",
            "start_date": "2025-04-20T09:00:00.000+0000",
            "end_date": "2025-05-04T17:00:00.000+0000"
          }
        ]
      },
      "id": 2
    }
    

Claude Desktopとの接続

サーバーをClaude Desktopに接続します:

  1. 設定ファイルの編集
    Claude Desktopの設定ファイル(例:claude_desktop_config.json)に以下を追加:

    {
      "mcp_servers": [
        {
          "name": "JiraServer",
          "url": "http://localhost:8132",
          "auth": "none"
        }
      ]
    }
    
  2. Claudeでテスト
    Claude Desktopを起動し、プロンプトを入力:

    プロジェクトのオープンTicketを教えてください。
    

    レスポンス例:

    プロジェクト MCP のオープンTicket:
    - MCP-1: バグ修正(作成者:Your Name、2025-04-22)
    - MCP-2: 新機能開発(作成者:Your Name、2025-04-22)
    

    別のプロンプト:

    現在のSprintを教えてください。
    

    レスポンス例:

    プロジェクト MCP の現在のSprint:
    - Sprint 1(ID: 1、状態:アクティブ、期間:2025-04-20~2025-05-04)
    

次のステップ

このMCPサーバーは、JiraとAIの連携の基礎です。次の第2章では、JiraにTicketを作成したり、コメントを追加したりする機能を実装し、プロジェクトタスクを自動化するエージェントを構築します。たとえば、AIが特定のキーワードに基づいてTicketに優先度を付けることができます。

まとめ

この第1章では、JiraとMCPの基本を学び、シンプルなMCPサーバーを構築してTicketとSprintデータを取得しました。Jiraの強力なAPIとMCPの柔軟性を組み合わせることで、AIをプロジェクト管理の強力なアシスタントに変えられます。次章以降では、Ticket管理、プロジェクト分析、リアルタイム管理へと進化させます。


役に立ったと思ったら、「いいね」や「ストック」をしていただけると嬉しいです!次の章でまたお会いしましょう!

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?