はじめに
株式会社スイフトスタッフの田邉豊です。
以前、ChatGPTとGitHubを連携し、実装からPull Request作成まで任せる検証を行いました。
https://qiita.com/yutaka520/items/1bf8523cf9784081c02f
その際、ChatGPT自身にリポジトリ内を確認してもらい、そのままソースコードの修正まで進められるのがかなり便利でした。
そこで、弊社で管理しているソースコードやIssueなどについても、ChatGPTから直接参照したり、修正を依頼したりできるようにしたいと考えました。
ただし、今回はGitHub上のリポジトリではなく、自社サーバー上で管理している開発資産が対象です。
そのため、自社サーバー上にGiteaを構築し、Gitea MCP Serverを経由してChatGPTからアクセスできるようにしてみることにしました。
おおまかにやったことは以下になります。
- 自社サーバー上にGiteaを構築
- Gitea MCP Serverを構築
- MCP ServerをHTTPSで外部公開
- ChatGPT Businessにカスタムアプリとして登録
- ChatGPTからGitea上のIssueやソースコードを操作
今回の前提環境
弊社では、会社でChatGPT Businessプランを契約しています。
今回は、ChatGPT BusinessのワークスペースにカスタムMCPアプリを登録し、社内のメンバーがChatGPTからGiteaへアクセスできるようにします。
ChatGPT Businessでは、管理者またはオーナーが開発者モードを有効にすることで、カスタムMCPアプリを作成し、ワークスペースへ公開できます。
書き込みや変更操作を含む完全なMCP対応は、Business、Enterprise、Eduプラン向けに提供されています。画面や提供条件は今後変わる可能性があるため、実際に構築する際は最新の公式情報も確認してください。
今回構築した主な環境は以下になります。
| 項目 | 内容 |
|---|---|
| ChatGPT | ChatGPT Business |
| サーバーOS | Ubuntu |
| コンテナ | Docker Compose |
| Gitサービス | Gitea 1.26.4 |
| データベース | PostgreSQL 17 |
| MCP Server | Gitea MCP Server 1.3.0 |
| リバースプロキシ | Apache |
| CI/CD | Gitea Actions Runner |
Gitea Actions Runnerも構築していますが、ChatGPTとGiteaを連携するだけであれば必須ではありません。
今回はGitea環境全体の移行も目的に含まれていたため、Actions Runnerも一緒に構築しました。
なぜGiteaを採用したのか
自社サーバー上でGitリポジトリを管理するにあたり、GitLab、Gitea、Forgejoを候補として検討しました。
GitLab
GitLabは、Gitリポジトリの管理だけでなく、Issue、CI/CD、プロジェクト管理などの機能が充実しています。
一方で、GitLab Self-Managedの公式ドキュメントでは、単一ノード構成の基準として8 vCPU、16GBメモリが案内されています。
メモリを抑えた環境でも最低8GBが必要とされており、弊社で利用している小型サーバー上で動かすには少し重いと判断しました。
Forgejo
Forgejoも軽量なセルフホスト型Gitサービスで、Giteaと同様に有力な候補でした。
もともとGiteaから派生したソフトウェアですが、現在はGiteaとは別のコードベースとして開発されています。
Gitリポジトリの管理だけを目的とするのであれば、Forgejoでも問題なかったと思います。
ただし、今回の一番の目的は、ChatGPTからリポジトリやIssueを操作できる環境を、できるだけ簡単に構築することでしたので、MCPサーバ自前実装は重いと感じ今回は採用を見送りました。
Gitea
Giteaには、MCP対応のチャットインターフェースからリポジトリやIssue、Pull Requestなどを操作するためのGitea MCP Serverが用意されています。
Dockerイメージも公開されているため、GiteaのURLとアクセストークンを設定すれば、既存のDocker Compose環境へ比較的簡単に追加できます。
ForgejoはGiteaから派生しているため、Gitea MCP Serverが動作する可能性はあります。
ただし、今後も完全な互換性が保たれるとは限りません。
今回は検証に余計な不確定要素を増やさず、Gitea MCP Serverの接続先として想定されているGiteaを採用することにしました。
整理すると、各候補に対する判断は以下になります。
| 候補 | 判断 |
|---|---|
| GitLab | 高機能だが、今回利用する小型サーバーには重い |
| Forgejo | 軽量で有力だが、Gitea MCP Serverとの将来的な互換性が不明 |
| Gitea | 軽量で、Gitea MCP Serverをそのまま利用できる |
最終的には、GitLabより軽量であることと、MCP ServerをDockerで簡単に構築できることからGiteaを採用しました。
今回の構成
今回構築した構成は以下になります。
ChatGPT Business
│
│ HTTPS / MCP
▼
Apache Reverse Proxy
│
▼
Gitea MCP Server
│
│ Gitea API
▼
Gitea
│
▼
PostgreSQL
GiteaとGitea MCP Serverは、同じDockerネットワーク内で通信させます。
MCP Serverはホストのローカルポートにのみ公開し、外部からのアクセスはApacheを経由させました。
実際に使用したURLの役割は以下になります。
https://git.example.com
GiteaのWeb画面
ssh://git@git-ssh.example.com:2222
GitのSSH接続
https://mcp.example.com/mcp
ChatGPTから接続するMCPエンドポイント
記事内ではドメインをサンプルへ置き換えています。
GiteaをDockerで構築する
まず、GiteaとPostgreSQLをDocker Composeで構築します。
.envを作成します。
POSTGRES_USER=gitea
POSTGRES_PASSWORD=十分に長いパスワード
POSTGRES_DB=gitea
続いて、compose.yamlを作成します。
services:
db:
image: postgres:17-alpine
container_name: gitea-db
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- ./data/postgres:/var/lib/postgresql/data
networks:
- gitea_network
gitea:
image: docker.gitea.com/gitea:1.26.4
container_name: gitea
restart: unless-stopped
depends_on:
- db
environment:
USER_UID: 1000
USER_GID: 1000
GITEA__database__DB_TYPE: postgres
GITEA__database__HOST: db:5432
GITEA__database__NAME: ${POSTGRES_DB}
GITEA__database__USER: ${POSTGRES_USER}
GITEA__database__PASSWD: ${POSTGRES_PASSWORD}
GITEA__server__DOMAIN: git.example.com
GITEA__server__ROOT_URL: https://git.example.com/
GITEA__server__SSH_DOMAIN: git-ssh.example.com
GITEA__server__SSH_PORT: 2222
GITEA__service__DISABLE_REGISTRATION: "true"
volumes:
- ./data/gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "127.0.0.1:13000:3000"
- "2222:22"
networks:
- gitea_network
networks:
gitea_network:
name: gitea_network
GiteaのWeb画面は、ホストの127.0.0.1:13000にのみバインドしています。
インターネットへ3000番ポートを直接公開せず、外部からのアクセスはApacheを経由させます。
起動します。
sudo docker compose up -d
起動後、サーバー内部から確認します。
curl http://127.0.0.1:13000/api/healthz
GiteaのWeb画面用ドメインについても、Apacheから127.0.0.1:13000へリバースプロキシしています。
SSL証明書にはCertbotを利用しました。
Giteaのアクセストークンを作成する
次に、Gitea MCP ServerからGitea APIへアクセスするためのトークンを作成します。
Giteaへログインし、以下からアクセストークンを作成します。
ユーザー設定
> アプリケーション
> アクセストークンを生成
今回は、MCP専用のGiteaユーザーを作成しました。
ChatGPTからソースコードの修正やPull Request作成まで行う場合は、読み取り権限だけでなく書き込み権限も必要です。
ただし、管理者権限を持つトークンをそのまま使用するのではなく、対象となるOrganizationやリポジトリだけにアクセスできる専用ユーザーを用意した方がよいと思います。
作成したトークンは、後ほどGitea MCP Serverへ設定します。
Gitea MCP Serverを構築する
Gitea MCP Server用の環境変数ファイルを作成します。
vim .env.mcp
GITEA_ACCESS_TOKEN=作成したGiteaのアクセストークン
続いて、compose.mcp.yamlを作成します。
services:
gitea-mcp:
image: docker.gitea.com/gitea-mcp-server:1.3.0
container_name: gitea-mcp
restart: unless-stopped
env_file:
- .env.mcp
environment:
GITEA_HOST: http://gitea:3000
command:
- "-t"
- "http"
- "--port"
- "8080"
ports:
- "127.0.0.1:18080:8080"
networks:
- gitea_network
networks:
gitea_network:
external: true
ここで設定しているGITEA_HOSTは、外部公開しているGiteaのURLではありません。
GITEA_HOST=http://gitea:3000
GiteaとMCP Serverは同じDockerネットワーク内に存在するため、Dockerのサービス名を使用して直接通信させます。
MCP Serverを起動します。
sudo docker compose \
-f compose.yaml \
-f compose.mcp.yaml \
up -d
ログを確認します。
sudo docker compose \
-f compose.yaml \
-f compose.mcp.yaml \
logs -f gitea-mcp
この状態では、MCP Serverは以下で待ち受けています。
http://127.0.0.1:18080/mcp
Gitea MCP ServerはHTTPモードに対応しており、/mcpをMCPクライアントの接続先として利用できます。
ApacheからMCP Serverを公開する
ChatGPTから接続するため、MCP ServerへHTTPSでアクセスできるURLを用意します。
今回はApacheから以下のようにリバースプロキシしました。
<VirtualHost *:443>
ServerName mcp.example.com
ProxyPreserveHost On
ProxyTimeout 600
ProxyPass /mcp http://127.0.0.1:18080/mcp timeout=600
ProxyPassReverse /mcp http://127.0.0.1:18080/mcp
ErrorLog ${APACHE_LOG_DIR}/mcp.example.com-error.log
CustomLog ${APACHE_LOG_DIR}/mcp.example.com-access.log combined
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/mcp.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mcp.example.com/privkey.pem
</VirtualHost>
これで、ChatGPTから以下のURLへ接続できるようになります。
https://mcp.example.com/mcp
MCPエンドポイントを認証なしで公開するのは危険なため、今回の環境ではAPIキーによる認証も追加しました。
ChatGPTからは、以下のような独自ヘッダーでAPIキーを送信します。
X-MCP-API-Key: 十分に長いランダムな文字列
このAPIキーは、Giteaのアクセストークンとは別のものです。
ChatGPT
│
│ X-MCP-API-Key
▼
MCPエンドポイント
│
│ GITEA_ACCESS_TOKEN
▼
Gitea API
外部からMCP Serverへ接続するための認証と、MCP ServerからGitea APIへ接続するための認証を分けています。
なお、ChatGPTはリモートMCP Serverへ接続するため、ローカルホスト上のMCP Serverへそのまま接続することはできません。現在はSecure MCP Tunnelという選択肢も案内されています。
ChatGPT Businessへカスタムアプリとして登録する
MCP Serverを公開できたら、ChatGPT Businessの管理画面からカスタムアプリを作成します。
今回の環境では、以下から設定しました。
ワークスペース設定
> アプリ
> 作成
管理者アカウントで開発者モードを有効にし、以下の内容を設定します。
| 項目 | 設定内容 |
|---|---|
| アプリ名 | Swift-Staff Gitea |
| MCP URL | https://mcp.example.com/mcp |
| 認証方式 | API Key |
| ヘッダー名 | X-MCP-API-Key |
| API Key | MCP接続用に作成した値 |
設定後、MCP Serverからツールの一覧が読み込まれます。
Gitea MCP Serverには、リポジトリやブランチ、Issue、Pull Request、Actionsなどを操作するためのツールが用意されています。
ツールの読み込みに問題がなければ、アプリをワークスペースへ公開します。
ChatGPT Businessでは、カスタムアプリの作成や公開を行えるのは管理者またはオーナーです。
実際に使ってみる
設定が完了すると、ChatGPTの会話画面から作成したGiteaアプリを選択できるようになります。
試しに、Gitea上のIssueを指定して調査を依頼してみました。
このように、ChatGPTからGitea上のIssueやソースコードを直接確認できるようになりました。
アクセストークンに書き込み権限を付与している場合は、ソースコードの修正やブランチ作成、Pull Request作成まで依頼できます。
これまでは、Issueの内容や関連するソースコードをChatGPTへコピーして渡す必要がありました。
今回の構成では、対象のリポジトリやIssue番号を指定するだけで、ChatGPT自身がGiteaから必要な情報を確認できます。
現時点での課題
今回の構成で一番気になっているのは、ChatGPTの利用者ごとにGiteaの権限を分けられていない点です。
Gitea MCP Serverには、MCP専用ユーザーのアクセストークンを設定しています。
ChatGPT利用者A ─┐
│
ChatGPT利用者B ─┼─ 共通のMCPアプリ
│ │
ChatGPT利用者C ─┘ ▼
共通のGiteaユーザー
そのため、誰がChatGPTから操作した場合でも、Gitea上では同じMCP専用ユーザーによる操作として扱われます。
MCP専用ユーザーにソースコードの書き込み権限を付与すると、そのアプリを利用できるメンバー全員が、実質的に同じ書き込み権限を持つことになります。
少人数の開発チームで、全員が同じリポジトリ権限を持っている場合は、大きな問題にはなりにくいと思います。
一方で、部署や役職、担当プロジェクトごとにアクセスできるリポジトリが異なる会社では、この構成をそのまま利用するのは難しそうです。
また、Giteaの操作履歴上ではMCP専用ユーザーによる操作となるため、実際にChatGPTを操作した人をGitea側だけで判別できません。
ある程度の規模で利用する場合は、以下のような仕組みが必要になりそうです。
- ChatGPT利用者ごとにGiteaの認証を行う
- ユーザーごとに異なるアクセストークンを利用する
- OAuthなどを利用してGitea側の権限を引き継ぐ
- 権限グループごとにMCP Serverやアプリを分ける
- 読み取り用と書き込み用のアプリを分ける
今回の方法は、少人数のチームで共通権限を利用する場合には扱いやすいと思います。
一方で、ある程度の規模の会社へそのまま導入するには、利用者単位の認証と権限管理が不足しています。
まとめ
今回は、自社サーバー上にGiteaとGitea MCP Serverを構築し、ChatGPT Businessから利用できるようにしました。
Giteaを採用した主な理由は、GitLabと比べて軽量であることと、Gitea MCP ServerをDockerで簡単に構築できることです。
今回の構成により、ChatGPTから以下の操作ができるようになりました。
- Gitea上のリポジトリを確認
- Issueの本文やコメントを確認
- 関連するソースコードを調査
- ソースコードを修正
- ブランチやPull Requestを作成
- Gitea Actionsの状況を確認
社内の開発資産をChatGPTから直接参照できるようになったことで、不具合調査や修正依頼をChatGPT上で進めやすくなりました。
ただし、今回の構成では、アプリを利用するメンバー全員が同じGiteaユーザーの権限を共有します。
少人数での利用には向いていますが、利用者ごとに細かくアクセス権限を管理する必要がある組織では、認証方式を含めて別途検討が必要です。
