github-mcp-wrapper
by hotaka052
README.md
# github-mcp-wrapper
GitHub の MCP サーバーへの接続を肩代わりする薄いサーバー。
呼ぶ側([tsuzuri](https://github.com/hotaka052/tsuzuri) の runner)は**このサービスの
URL だけ**を知っていればよく、GitHub App の秘密鍵を一切持たない、という形にするための repo。
```
before: runner ──MCP──> api.githubcopilot.com (runner が App の秘密鍵を持つ)
after: runner ──MCP──> このサービス ──MCP──> api.githubcopilot.com
```
[linear-mcp-wrapper](https://github.com/hotaka052/linear-mcp-wrapper) と対になる repo。
中身の作りは揃えてある。
## いまの状態: 置いただけ
**まだサーバーとして動かない。** tsuzuri から認証まわりのコードを退避させただけで、
プロキシ本体(`src/main.py`)はまだ無い。tsuzuri 側も**まだ何も消していない**ので、
そちらは今までどおり直接 GitHub を見ている。
| ファイル | 出どころ |
| --- | --- |
| `src/auth.py` | tsuzuri の `runner/src/github.py` を**そのままコピー**(1 文字も変えていない) |
| `src/config.py` | tsuzuri の `runner/src/config.py` の GitHub の部分だけ |
| `src/logs.py` | tsuzuri の `runner/src/logs.py` から `emit` だけ |
| `env/master.yaml` | tsuzuri の `runner/env/master.yaml` の GitHub の部分だけ |
`GITHUB_REPO` は持ってきていない。あれは「繋ぐのをやめる口」で、呼ぶ側の判断なので
tsuzuri に残っている。
### `src/auth.py` の docstring で、もう合っていない記述
そのままコピーした副作用。**中身の理屈は全部生きているが、参照先の名前だけが古い。**
- 「`linear.py` と対になる場所」— その `linear.py` は linear-mcp-wrapper の
`src/auth.py` になった
- 「`config.py` の Linear の項と同じ理由」— 同上
- 「MCP サーバーへの接続ヘッダに使う(`mcp_tools.github`)。**唯一の呼び出し元。**」—
ここを呼ぶのは、これから書くプロキシ本体になる
**「REST を直接叩くのはトークン交換の 1 本だけ。それ以外を足さないこと」は生きている。**
repo が別になって足しやすくなったぶん、むしろここから効く。
## これから書くもの
1. **プロキシ本体(`src/main.py`)。** ここが本番。素通しの HTTP プロキシでは済まない:
- POST のレスポンスが JSON のことも SSE のこともある
(クライアントは `Accept: application/json, text/event-stream` で来る)
- 別に **GET で長寿命の SSE を張る**(サーバー→クライアント方向。切れたら再接続してくる)
- **`mcp-session-id` と `mcp-protocol-version` を両方向で素通しする**必要がある
- セッション終了は DELETE
- **バッファしないこと。** `await response.json()` で受けると SSE がそこで固まる
2. **呼ぶ側の認証。** クライアントから来る `Authorization` は Cloud Run の OIDC ID token
にして、ここで installation token(`auth.py`)に差し替える。
Cloud Run は `--no-allow-unauthenticated` で立てる
3. **ツールの絞り込み(あとで)。** いまは tsuzuri 側の `IMPLEMENT_TOOL_FILTER` が
`get_file_contents,list_commits,get_commit` の 3 本に絞っている。動いてから移す
### 3 をやるときに知っておくこと
**上流のツールを全部そのまま渡すと、呼ぶ側のモデル呼び出しごと落ちる。**
GitHub の MCP は 90 本を超えて公開していて、Vertex の function declaration が
受け付けないスキーマが混ざっていると `400 INVALID_ARGUMENT` になる(tsuzuri で実測)。
**`create_branch` / `push_files` / `create_or_update_file` を許可リストに入れないこと。**
レビューを通る前の実装が GitHub へ出ていく。URL が readonly なので二重に締まっているが、
その readonly がこちら側に移ったことで、呼ぶ側からは外せなくなった。
## 開発
```sh
uv sync
```
ローカルでは `GITHUB_TOKEN`(PAT)を入れれば App の交換を通らずに済む。
Cloud Run では App ID + installation ID + 秘密鍵(Secret Manager)を使う。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues