JIRAチケットログ取得アプリの構想：HTML配布型＋PowerShellでCORS回避！

元ネタ　https://lifehacking1919.hatenablog.jp/entry/20250619/1750289263

こんにちは！最近、JIRAを使ったプロジェクト管理を効率化できないかと模索中のあなたに、面白いアプリ構想をシェアします。今回のテーマは、**HTML配布型のアプリでJIRAチケットのログを取得し、ローカルPowerShellサーバーでCORSを回避する**方法。さらに、将来的にはMCPサーバー化で自動チケット生成のようなインテリジェント機能を追加するアイデアです。アトラシアンもMCPサーバーを展開中というニュースを背景に、この構想がどれだけ現実的か、技術的なポイントや注意点を掘り下げます！[](https://www.atlassian.com/blog/announcements/remote-mcp-server)

## 構想の概要：何を作りたい？

JIRAはプロジェクト管理の強力なツールですが、チケットログをサクッと取得してカスタム分析したいとき、APIを叩くのが面倒だったり、CORS（Cross-Origin Resource Sharing）の壁にぶつかったりしますよね。そこで、以下のアプリを構想しました：

- **HTML配布型アプリ**：ブラウザで動くシンプルなUI。ユーザーがJIRAチケットのログを検索・取得できる。
- **ローカルPowerShellサーバー**：JIRA APIをプロキシとして叩き、CORSを回避。ローカル環境で完結するのでセキュリティも安心。
- **初期実装**：JIRA REST APIを叩いてチケットログを取得する基本機能。
- **将来展望**：MCP（Model Context Protocol）サーバーに進化させ、AIを活用した自動チケット生成やスマートなワークフロー自動化を実現。

このアプローチの良いところは、**初期は軽量で始められる**点と、**拡張性が高い**点。では、具体的にどう進めればいいか見ていきましょう！

## ステップ1：JIRA APIを叩く基本実装

まずは、JIRA REST APIを使ってチケットログを取得するところから。JIRAのAPIは、プロジェクトや課題のデータをJSON形式で返してくれるので、扱いやすいです。例えば、以下のようなエンドポイントを使います：

```
GET /rest/api/3/search?jql=project=PROJ
```

これで、プロジェクト「PROJ」の全課題を取得できます。認証には、**APIトークン**や**Basic認証**を使うのが一般的。以下のPowerShellスクリプトで、APIを叩く例を紹介します：

```powershell
$jiraUrl = "https://your-jira-instance.atlassian.net/rest/api/3/search"
$apiToken = "your-api-token"
$email = "your-email@example.com"
$headers = @{
    Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$email:$apiToken"))
}
$jql = "project=PROJ"
$response = Invoke-RestMethod -Uri "$jiraUrl?jql=$jql" -Headers $headers -Method Get
$response.issues | ForEach-Object {
    Write-Output "課題キー: $($_.key), タイトル: $($_.fields.summary)"
}
```

このスクリプトをローカルで実行すれば、指定プロジェクトの課題一覧が取得できます。HTMLアプリ側では、このデータを表示するだけなので、JavaScriptでFetch APIを使ってローカルサーバーにリクエストを投げる形になります。

**注意点**：
- APIトークンは安全に管理！スクリプトに直書きは避け、環境変数や資格情報マネージャーを使いましょう。
- JIRAのAPI制限（1秒あたりのリクエスト数など）に注意。初期は小規模テストで様子を見ると安心です。

## ステップ2：PowerShellでローカルサーバーを立てる

CORSを回避するため、PowerShellで簡易HTTPサーバーを構築します。以下のスクリプトは、JIRA APIをプロキシとして動作するサーバーの例です：

```powershell
$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add("http://localhost:8080/")
$listener.Start()
Write-Host "サーバー起動中... http://localhost:8080/"

while ($listener.IsListening) {
    $context = $listener.GetContext()
    $request = $context.Request
    $response = $context.Response

    if ($request.Url.LocalPath -eq "/jira-issues") {
        $jql = $request.QueryString["jql"]
        $jiraUrl = "https://your-jira-instance.atlassian.net/rest/api/3/search?jql=$jql"
        $apiToken = "your-api-token"
        $email = "your-email@example.com"
        $headers = @{
            Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$email:$apiToken"))
        }
        try {
            $apiResponse = Invoke-RestMethod -Uri $jiraUrl -Headers $headers -Method Get
            $json = ConvertTo-Json $apiResponse
            $buffer = [Text.Encoding]::UTF8.GetBytes($json)
            $response.ContentLength64 = $buffer.Length
            $response.OutputStream.Write($buffer, 0, $buffer.Length)
        } catch {
            $response.StatusCode = 500
            $buffer = [Text.Encoding]::UTF8.GetBytes("エラー: $_")
            $response.ContentLength64 = $buffer.Length
            $response.OutputStream.Write($buffer, 0, $buffer.Length)
        }
    } else {
        $response.StatusCode = 404
        $buffer = [Text.Encoding]::UTF8.GetBytes("Not Found")
        $response.ContentLength64 = $buffer.Length
        $response.OutputStream.Write($buffer, 0, $buffer.Length)
    }
    $response.Close()
}
$listener.Stop()
```

このサーバーは、`http://localhost:8080/jira-issues?jql=project=PROJ` にアクセスすると、JIRA APIを叩いて結果をJSONで返します。HTMLアプリ側は、以下のようなJavaScriptでデータを取得：

```javascript
fetch('http://localhost:8080/jira-issues?jql=project=PROJ')
    .then(response => response.json())
    .then(data => {
        data.issues.forEach(issue => {
            console.log(`課題キー: ${issue.key}, タイトル: ${issue.fields.summary}`);
        });
    })
    .catch(error => console.error('エラー:', error));
```

**注意点**：
- PowerShellのHTTPリスナーは簡易的なものなので、本番環境ではNode.jsやPythonのFlaskを使った方が安定します。
- ローカルサーバーのポート（8080など）が他のアプリと競合しないよう注意。

## ステップ3：MCPサーバー化の展望

初期実装が安定したら、次はMCPサーバー化を目指します。アトラシアンは2025年5月にRemote MCP Serverを発表し、JIRAやConfluenceのデータをClaude AIと連携可能にしました。https://www.atlassian.com/blog/announcements/remote-mcp-server

MCP（Model Context Protocol）は、AIエージェントが外部ツールと標準化された方法で通信するためのプロトコル。これを活用すれば、以下のようなインテリジェント機能が実現可能：

- **自動チケット生成**：自然言語で「バグ報告：ログイン画面でエラー」と入力すると、適切なJIRAチケットを自動作成。
- **スマート分析**：チケットログをAIで分析し、ボトルネックや優先度の提案を行う。

MCPサーバーの実装は、Node.jsやPythonで構築するのが一般的。以下は、簡易MCPサーバーのPython例（Flask使用）：

```python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/mcp/tools', methods=['GET'])
def get_tools():
    return jsonify({
        "tools": [
            {
                "name": "create_jira_ticket",
                "description": "JIRAに新しいチケットを作成します",
                "parameters": {
                    "project": {"type": "string", "required": True},
                    "summary": {"type": "string", "required": True},
                    "description": {"type": "string", "required": False}
                }
            }
        ]
    })

@app.route('/mcp/execute', methods=['POST'])
def execute_tool():
    data = request.json
    if data['tool'] == 'create_jira_ticket':
        # JIRA APIを叩いてチケット作成
        return jsonify({"status": "success", "message": "チケット作成完了"})
    return jsonify({"status": "error", "message": "不明なツール"})

if __name__ == '__main__':
    app.run(port=5000)
```

このサーバーは、MCPクライアント（例えばClaude AI）からのリクエストを受け、JIRAチケットを作成します。アトラシアンのMCPサーバーを参考に、セキュリティやスケーラビリティを強化していくのが次のステップです。

**注意点**：
- MCPはまだ新しい規格なので、ドキュメントやコミュニティをこまめにチェック（[Model Context Protocol FAQ](https://modelcontextprotocol.io/faqs)）。
- AIエージェントとの連携には、認証やデータプライバシーの考慮が必須。

## この構想のメリットと課題

**メリット**：
- **CORS回避**：ローカルサーバーで完結するので、ブラウザのセキュリティ制約をクリア。
- **拡張性**：API叩きからMCPサーバー化まで、段階的に進化可能。
- **アトラシアンのトレンドに合致**：MCPサーバー化は、業界のAI連携トレンドに乗る形。[](https://www.atlassian.com/blog/announcements/remote-mcp-server)

**課題**：
- **認証管理**：APIトークンの安全な管理や、MCPサーバーでのOAuth対応が必要。
- **スケーラビリティ**：ローカルサーバーは個人利用向け。本番ではクラウドホスティングを検討。
- **学習コスト**：MCPやJIRA APIはドキュメントが豊富ですが、慣れるまで時間がかかる。

## 関連記事

過去にJIRAやAPI関連の記事を書いたので、参考にどうぞ：
- [JIRA CloudとGoogle Sheetsの公式統合ガイド](https://blog.hatena.ne.jp/motochan1969/motochan1969.hatenablog.com/atom/entry/26006613577373980)：JIRAデータを外部ツールで活用するヒント。
- [テクニカル講座：API活用の初級編](https://blog.hatena.ne.jp/motochan1969/motochan1969.hatenablog.com/atom/entry/26006613577373116)：APIの基本を学びたい人に。

## まとめ

この構想は、JIRAチケットログ取得をシンプルに始めつつ、MCPサーバー化で未来のAI連携を見据えた面白いプロジェクトです。PowerShellでローカルサーバーを立てるのは、CORS回避の賢いアプローチ。初期はJIRA APIを叩くだけでも十分価値があり、徐々に自動化機能を追加していけば、チームの生産性がグッと上がるはず！アトラシアンのMCP展開も追い風なので、ぜひトライしてみてください。

質問やアイデアがあれば、コメントで教えてください！このプロジェクト、応援してますよ！😄