Skip to main content
Glama
README.md
# Skills MCP

GitHub の `skills/<name>/SKILL.md` を Cloudflare Workers から読み取り、ChatGPT で `@Skills MCP` と指定して利用する MCP サーバーです。Tool は `list_skills` と `get_skill` の2つです。Skill の取得は、その手順に沿った作業をモデルに依頼するためのものです。

- 想定環境: **ChatGPT Pro + 開発者モード**。2026-09-13確認の[公式案内](https://developers.openai.com/api/docs/guides/developer-mode)では **Plus も対象**です。「Plus契約なら自作接続不可」という条件は現行情報と一致しません。利用可否はアカウントやワークスペース方針も確認してください。
- Worker URL: **未デプロイ(Cloudflareログイン待ち)。** 認証後のデプロイ成功時に実URLへ更新します。
- GitHub: [masahiro-nagai/skills-mcp](https://github.com/masahiro-nagai/skills-mcp)(公開済み)
- 通信: 公開 HTTPS の Streamable HTTP、パスは `/mcp`。
- 初期構成: 公開リポジトリ、MCP認証なし、読み取り専用。OpenAI APIキーは不要です。

## 構成

```text
skills-mcp/
  wrangler.jsonc
  package.json
  package-lock.json
  src/index.ts
  src/github.ts
  skills/slide-kit/SKILL.md
  skills/newsletter/SKILL.md
  scripts/smoke.ts
  test/github.test.ts
  README.md
  ACCEPTANCE.md
```

[Cloudflare公式のauthlessテンプレート](https://github.com/cloudflare/ai/tree/main/demos/remote-mcp-authless)を参照し、計算ToolをSkill取得Toolへ置き換えています。指定のC3コマンドは実行時に依存解決に失敗したため、公式ソースを直接確認して構成しました。現行テンプレートに合わせ、`createMcpHandler`(`agents/mcp/server`)と MCP SDK v2(`@modelcontextprotocol/server`)を採用しています。SDK v1のClientも検証用に同梱します。Durable Object、UI、OAuth、書き込みToolはありません。[公式handler仕様](https://developers.cloudflare.com/agents/model-context-protocol/apis/handler-api/)

## ローカル起動と検証

Node.js 22.18以上の22系、または24.11以上とnpmを使用します(Agentsの依存パッケージが必要とする範囲)。

```sh
npm ci
npm run check
npm run build
npm start
```

別のターミナルから:

```sh
npx @modelcontextprotocol/inspector@latest
```

Inspectorを開き、Transportを **Streamable HTTP**、URLを `http://localhost:8788/mcp` に設定してConnectします。ToolsでList Toolsを実行し、次を確認します。

| Tool | 入力 | 期待結果 |
| --- | --- | --- |
| list_skills | `{}` | サンプル2件の名前・説明・パス |
| list_skills | `{"query":"newsletter"}` | newsletterのみ |
| get_skill | `{"skill":"slide-kit"}` | SKILL.md全文、出典URL、関連ファイル一覧 |
| get_skill | `{"skill":"does-not-exist"}` | isError付きメッセージ。次の呼び出しも使える |
| get_skill | `{"skill":"../README.md"}` | 不正なSkill名として拒否 |

GitHub公開後は自動の実接続確認もできます。2つのサンプル本文がローカルファイルと一致することまで確認します。

```sh
npm run smoke
npm run smoke -- https://YOUR-WORKER.YOUR-SUBDOMAIN.workers.dev/mcp
```

InspectorのCLIでも直接検証できます。

```sh
npx @modelcontextprotocol/inspector@latest --cli http://localhost:8788/mcp --transport http --method tools/list
npx @modelcontextprotocol/inspector@latest --cli http://localhost:8788/mcp --transport http --method tools/call --tool-name list_skills
npx @modelcontextprotocol/inspector@latest --cli http://localhost:8788/mcp --transport http --method tools/call --tool-name get_skill --tool-arg skill=slide-kit
```

`npm start` も設定したGitHubを読みます。ローカルSkill編集だけでは反映されません。取得元リポジトリが未作成ならGitHub取得エラーになります。

## デプロイ手順

1. このフォルダのみをGitHubの公開リポジトリにpushします。既存の業務Skillや秘密情報をコピーしないでください。
2. `wrangler.jsonc` の `GITHUB_OWNER`、`GITHUB_REPO`、`GITHUB_REF` を対象へ合わせます。初期ブランチは `main`、`GITHUB_VISIBILITY` は `public` です。
3. 初回は `npx wrangler login` でCloudflareへログインし、`npx wrangler whoami` でアカウントを確認します。複数アカウントがある場合は、対象の `account_id` を `wrangler.jsonc` に指定します。
4. 次を実行します。

```sh
npm run check
npm run build
npx wrangler deploy
```

5. 出力された `https://skills-mcp.<subdomain>.workers.dev` に `/mcp` を付けたURLを控え、このREADMEのWorker URLを更新します。
6. そのURLを引数に `npm run smoke -- URL` を実行し、Inspectorでも接続確認します。

WorkerのTool説明・コード・取得元設定を変えたときは再デプロイが必要です。Skill本文や追加・削除はGitHub側の変更だけで反映されます。

## ChatGPT登録手順(人が手動で行う)

以下は[公式の接続・テスト手順](https://developers.openai.com/plugins/deploy/connect-chatgpt)に基づきます。画面の表記はアカウントや言語で異なる場合があります。

1. ChatGPT Web の **Settings → Security and login → Developer mode** をオンにします。
2. **Plugins → +** を開きます。
3. 名前は `Skills MCP`、説明は「GitHubのSkill一覧と手順本文を読み取る」とします。
4. 公開エンドポイント接続を選び、上記の **HTTPS URLを `/mcp` まで**入力します。
5. 認証は **No Authentication** を選び、信頼に関する確認の内容を読んで接続します。
6. 検出された `list_skills` と `get_skill` を確認します。
7. Workで新規会話を開き、`@` を入力して `Skills MCP` を選びます。候補に出ない場合はツールメニューのDeveloper modeから接続を選びます。[公式の@呼び出し案内](https://learn.chatgpt.com/docs/plugins)

呼び出し例:

```text
@Skills MCP list_skills で一覧を取得して
@Skills MCP get_skill に {"skill":"slide-kit"} を渡して本文を取得して
@Skills MCP slide-kit を使って提案資料を作って
テーマは新入社員向けの業務改善。読者は部門責任者、発表は5分。
```

Toolが返すのは手順のテキストです。Workerがスライドやメールを作成・配信する機能はありません。ChatGPTが本文を読み、現在の依頼に沿って適用します。接続登録とChatGPTからの実呼び出しは手動検証として別途確認してください。

## Skill追加手順

`skills/<name>/SKILL.md` を作って `main` にcommit/pushするだけです。名前は小文字英数字とハイフンを使い、frontmatterの `name` とフォルダ名を一致させます。

```markdown
---
name: example-skill
description: 利用する場面を先に書き、続けて何を返すかを具体的に書く。
---

# example-skill
## 使うタイミング
## 手順
## 禁止事項
## 出力形式
```

同じSkillフォルダ内の `references/`、`templates/` なども関連ファイルとして列挙されます。関連ファイルの本文取得やスクリプト実行用Toolはありません。巨大ファイル、秘密情報、業務の非公開データは置かないでください。

一覧取得はGitHubのbranchをcommitへ解決してTreeから動的に検出し、そのcommitの本文を読みます。アプリ側の永続キャッシュはなく、1回の応答内では同じcommitの内容を使います。GitHub側の反映遅延やレート制限がある場合は時間をおいて再実行してください。Tool名やスキーマが変わらないため、Skill追加時の接続Refreshは通常不要です。

初期実装の上限は一覧40 Skill、SKILL.md 256KiB、Tree 20,000項目/4MiB、関連ファイル1,000件、各GitHubリクエスト10秒です。上限超過は途中の一覧を成功扱いせずエラーで返します。検索時もメタデータ取得のため全Skillを読みます。規模が増えた場合はキャッシュやカタログ方式を追加検討してください。

## 非公開リポジトリへの移行

`src/github.ts` にはPATとContents APIによる読み取り処理を用意していますが、**この認証なしの `/mcp` は private 設定を拒否します**。PATはWorkerがGitHubを読むための鍵であり、MCP利用者を認証するものではありません。非公開化は、MCP側のOAuth等を追加し、利用者を認可できる状態にしてから実施します。

その段階で、対象リポジトリの Contents 読み取りだけを許可したfine-grained PATをWorkers Secretsへ保存します。値をコードやREADMEへ記載しません。

```sh
npx wrangler secret put GITHUB_TOKEN
```

ローカルではgitignoreされた `.dev.vars` を使います。公開モードではPATを設定してもGitHubへの送信に使用しません。

## トラブルシュート

| 症状 | 確認内容 |
| --- | --- |
| Pluginsの作成項目が出ない | Developer mode、アカウント・ワークスペース方針を確認。Plus契約だけを理由に不可と判断しない |
| 接続できない | 公開HTTPS、URL末尾 `/mcp`、Workerの稼働を確認。ブラウザのGETだけでなくInspectorから接続する |
| GitHub 404 | owner/repo/refと公開状態、`skills/<name>/SKILL.md` の大文字小文字を確認 |
| 403/429 | GitHubのレート制限または権限を確認。再試行を連打しない。公開の未認証GitHub APIには制限がある |
| 一覧でSkillが欠ける | warningsとfrontmatterを確認。descriptionの文字列、nameとフォルダの一致を確認 |
| Toolが選ばれない | 使用タイミングと入力をdescriptionへ明記。Tool説明・スキーマ変更後は再デプロイし、PluginsでRefresh、新規会話で試す |
| CSPエラー | 今回はUIなしのためウィジェット用CSP設定は不要。後でUIを追加する場合に[公式CSP仕様](https://developers.openai.com/plugins/build/chatgpt-ui)を確認。CORSやOrigin拒否とは別 |
| Origin拒否 | ChatGPTとローカルInspectorを許可。他のWebクライアントを使う場合は、その信頼できるhostnameをsrc/index.tsへ追加 |
| private設定で503 | 認証なし公開を防ぐため意図的に拒否。MCP利用者認証の実装が先 |
| Nodeで動くのにWorkerで通信失敗 | native fetchの呼び出し元とredirect設定を確認。このコードはWorkers対応のラッパーとmanualを使い、3xxを拒否する |

両Toolに `readOnlyHint: true` と `destructiveHint: false` を設定し、GitHubへのリクエストはGETのみです。ログをMCPレスポンスに混ぜません。Worker内で取得内容やトークンをログに記録しません。将来stdio版を追加する場合、診断ログはstderrへ出し、stdoutにはJSON-RPC以外を出さないでください。

## 復旧と検証状態

Worker更新の取り消しは `npx wrangler rollback`。初回公開の取り下げは対象名を確認して `npx wrangler delete skills-mcp`。Skillの変更取り消しはGitHubの該当commitをrevertします。詳しい実施結果と未確認事項は [ACCEPTANCE.md](./ACCEPTANCE.md) に記録します。