🔔

【Claude MAX】GitHubActionsで動作するClaude CodeからPRレビュー結果をMCPでSlackに

に公開

結論、MCP使えるんですねぇやり放題じゃん・・・

ことのほったん

GitHubActionsのClaudeCodeでMCPできるの?

え?
できるんやろか・・・?
できるんじゃない?
あ、やばい、ねむいのにめっちゃきになる

よし、MCP使って通知できるかやってみよう!

前提

  • すでにGitHubにはClaudeCodeがインストールされ、利用可能な状態であること
  • 通知を行うリポジトリは既に作成済みであること

Slack Bot(Slack APP)の準備

  1. https://api.slack.com/appsを開いてAppを作成
  2. 「Create an App」をクリック
  3. 「From scratch」を選択し、以下を入力:
    • ワークスペースを選択
    • アプリ名: 任意の名前(例:GitHubClaudeCodeMCPBot)
  4. 「Create」をクリック
  5. 左サイドバーから「OAuth & Permissions」を選択
  6. 「Scopes」セクションで「Bot Token Scopes」に以下の権限を追加:
    • chat:write (メッセージ送信)
    • channels:read (チャンネル情報読み取り)
    • channels:history (チャンネル履歴閲覧)
    • users:read (ユーザー情報読み取り)
    • 必要に応じて他の権限も追加
  7. 同メニューの「OAuth Tokens」の「Install to {your workspace name}」をクリック
  8. 認証画面で「許可する」をクリック
  9. 「Bot User OAuth Token」(xoxb-で始まるトークン)が発行される

SlackBotのトークン「Bot User OAuth Token」が発行されたよ!

Slackで確認

先の作成したBOTがAppに存在すれば、インストール成功!

通知を行うSlackチームのチームIDを取得

ブラウザでSlackにログイン
URLを確認「https://app.slack.com/client/XXXXXXXXXXXXX/YYYYYYYYYYY」
「XXXXXXXXXXXXX」部分をコピー

SlackチームのチームIDを取得したよ!

通知を行うSlackのチャンネルIDを取得

  1. チャンネル名右クリックし、開いたウィンドウの「チャンネル詳細を表示する」をクリック

  2. 開いたモーダルウィンドウの「チャンネル情報」下部に「チャンネルID」があるのでコピー

チャンネルIDを取得したよ!

トークン・シークレットをGitHubに追加

前記事のGitHubOAhthTokenのシークレット登録を参考に以下を登録します
SLACK_BOT_TOKEN: Bot User OAuth Token
SLACK_TEAM_ID: TeamのID
SLACK_CHANNEL_ID: ChannelのID

結果として以下のようになるよ!

GitHubにSlackBotのトークン・SlackIDが登録されたよ!

GitHubActionsで利用するymlの作成

はい、こんかいはわたしがサンプルをClaudeCodeさんに作ってもらいました!

・・・・が、ここで大きくハマり、自分で修正入りました!!
(もっとうまく書けるかたはいると思いますが、ご容赦ください!)

こんかいはコピーしていただいて構いません~
登録方法はこちらを参考にしてください

name: Claude PR Review with Slack

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  pr-review:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
      id-token: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: anthropics/claude-code-action@beta
        with:
          claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}                     # ブランチを作成しない場合の設定
          # create_branch: false        
          mcp_config: |
            {
              "mcpServers": {
                "slack": {
                  "command": "docker",
                  "args": [
                    "run",
                    "-i",
                    "--rm",
                    "-e",
                    "SLACK_BOT_TOKEN",
                    "-e",
                    "SLACK_TEAM_ID",
                    "-e",
                    "SLACK_CHANNEL_IDS",
                    "mcp/slack"
                  ],
                  "env": {
                    "SLACK_BOT_TOKEN": "${{ secrets.SLACK_BOT_TOKEN }}",
                    "SLACK_TEAM_ID": "${{ secrets.SLACK_TEAM_ID }}",
                    "SLACK_CHANNEL_IDS": "${{ secrets.SLACK_CHANNEL_ID }}"
                  }
                }
              }
            }
          
          # Slackツールを許可
          allowed_tools: |
            Read
            Grep
            mcp__slack__slack_list_channels
            mcp__slack__slack_post_message
            mcp__slack__slack_get_channel_history
            mcp__slack__slack_get_users
          
          # レビュー実行とSlack通知
          direct_prompt: |
            PR #${{ github.event.pull_request.number }} を日本語でレビューして、
            結果を以下の形式でSlackに送信してください:
            
            🔍 PR: ${{ github.event.pull_request.title }}
            👤 作成者: ${{ github.event.pull_request.user.login }}
            
            📝 レビュー結果:
            [ここにレビュー内容]
            
            🔗 ${{ github.event.pull_request.html_url }}

では、PR作成してみよう

今回はあえてGitCommtすべきでないTypescriptの実装を行ってPRを作成します。

以下の実装はぜったいダメな実装をあえておこないます。もし、行う場合はテスト用リポジトリを作ってお試しください

  1. 新しいブランチを作成(今回はあえて、feat/bugとしています)
  2. 以下実装をおこないcommit>push
export class SlackClient {
  // 認証情報を直接コードに書いている
  private readonly botToken = 'xoxb-1234567890-abcdefghijk-XXXXXXXXXXXXXXXXXXXXX';
  private readonly teamId = 'T01234ABCDE';
  private readonly channelId = 'C01234ABCDE';
  
  async sendMessage(message: string) {
    const response = await fetch('https://slack.com/api/chat.postMessage', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.botToken}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        channel: this.channelId,
        text: message,
      }),
    });
    return response.json();
  }
}
  1. 新規PRを作成し、「Create pull request」をクリック

おお、うごくぞClaudeぅ!

Slack通知が届きまーす!

やったー!ClaudeCodeのMCP経由でとどいたよおおお

重要な場合は、クリティカルの場合はメンションつきとかしたいな~
(ここに行くまでにめちゃくちゃつまりましたが、解決できた)

さいごに

ほそく等

  • 現状のymlだとPRの更新等でも入るので、その辺りは個々人でちょうせいください~
  • 前回の記事でみなさんのClaudeCodeをActionsで利用フローが気になってると感じて、今回はMCPを導入してみました(いけるんだね!)
  • 冒頭でもお話ししましたが、MCPは便利な反面重大なセキュリティリスクがはらむ場合もあります!きちんと公式かつ権限の間違い等は十分気をつけくださいね
    https://gigazine.net/news/20250709-mcp-sql-leak/

愚痴

・ドキュメントちゃんと読んでなかった・・・Toolsうう
https://www.npmjs.com/package/@modelcontextprotocol/server-slack

・MCPのTools登録するときのPrefix「mcp__」のルール見逃して、MCPつながった後にToolsに入れるべき名称をActionsのログからひろうことになった
でも、学びは深かった

参考にさせていただいた記事

ありがとうございました~!
https://zenn.dev/takna/articles/mcp-server-tutorial-07-slack
https://zenn.dev/minty1st/articles/499bfcebf6624e

Discussion