株式会社ホコサキ

cursor/pluginsを読み解いてカスタムプラグインを自作する

天京祐輔
天京祐輔
cursor/pluginsを読み解いてカスタムプラグインを自作する

Cursor のプラグインシステムは、公式ドキュメントを読んだだけでは「なんとなく分かった気がする」で止まりがちです。
でも cursor/plugins リポジトリを実際に開いてコードを読むと、構造はかなりシンプルで、自社業務向けのカスタムプラグインを書くハードルが一気に下がります。

公式リポジトリのディレクトリ構成・マニフェストの型定義・スキルとルールの宣言パターンを順番に読み解きながら、最小のカスタムプラグインを自分で書けるようになることをゴールに置きます。
型定義を読んでいないと踏む地雷や、ローカルテストのつまずきポイントも具体的に触れるので、公式プラグインを改造する際の判断軸として使ってください。

Cursor プラグインとは何をしている仕組みか

Cursor プラグインを一言で言うと、「エージェントが何をできるかを宣言するパッケージ」です。
スキル・ルール・MCP サーバー定義をひとまとめにして配布できる単位、と考えると分かりやすいです。

重要なのは、これが Cursor 独自の仕様ではない点です。
Agent Plugins 1.0 という業界横断の共通仕様に乗っており、OpenAI・AWS・Cursor・GitHub・Vercel が合意した形式として策定されています。
今この仕様を読んでおくと、将来的に他のエージェントランタイムに横展開しやすい知識になります。

.claude/ のスキルファイルや agent-skills と概念的に近い部分はありますが、Cursor プラグインは plugin.json を中心としたマニフェスト駆動の構造を持ち、マーケットプレイス配布やチームへの一括展開まで視野に入れた設計になっています。
そこが本記事で踏み込む差別化ポイントです。

エージェントはプラグインをインストールすることで、宣言されたスキルを呼び出し可能なツールとして認識し、ルールをコンテキストとして取り込み、MCP サーバー経由で外部システムへアクセスできるようになります。
「エージェントに何かを覚えさせる」というより、「エージェントが使える道具と振る舞いのセットを定義する」というイメージが正確です。

cursor/plugins リポジトリの構造をコードから読む

リポジトリを開くと、まずこのディレクトリ構成が目に入ります。

cursor/plugins/
├── .cursor-plugin/
│   └── marketplace.json   # マーケットプレイス全体のマニフェスト(プラグイン一覧)
├── gmail/
│   ├── .cursor-plugin/
│   │   └── plugin.json    # プラグイン個別のマニフェスト
│   ├── skills/            # エージェントスキル(SKILL.md をサブディレクトリに配置)
│   ├── rules/             # Cursor ルール(.mdc ファイル)
│   ├── mcp.json           # MCP サーバー定義
│   ├── README.md
│   ├── CHANGELOG.md
│   └── LICENSE
├── google-drive/
│   └── ...
├── orchestrate/
│   └── ...
└── cursor-sdk/
    └── ...

ルート直下の .cursor-plugin/marketplace.json がプラグイン一覧を管理する「目次」で、各プラグインディレクトリの .cursor-plugin/plugin.json が個別の仕様書にあたります。
skills/・rules/・mcp.json は全部オプションで、必要なものだけ置けばいい構成です。

公式プラグインのラインナップを見ると、粒度の感覚がつかめます。
gmail や google-drive は特定 SaaS との連携を担い、orchestrate は並列エージェントのタスク分散を管理し、cursor-sdk は TypeScript SDK の操作スキルをまとめています。
「一つのサービスや一つのワークフロー」を単位にプラグインが切られているイメージです。

single pluginmulti-plugin の選択は、用途で判断します。
自社業務向けに一つのプラグインを作るだけなら single が楽です。
リポジトリルートに plugin.json を置き、marketplace.json は不要になります。
チームで複数のプラグインをまとめて管理・配布したい場合は multi を選び、公式リポジトリと同じ構成にします。
最初は single から始めて、増えてきたら multi に移行するのが現実的な流れです。

マニフェスト(plugin.json)の型定義を正確に読む

plugin.json は closed-schema です。
許可されているトップレベルフィールドは厳密に10個だけで、それ以外のフィールドを書いてもクライアントは「報告して無視する」義務があります。
バリデーションは厳格で、知らずに独自フィールドを足しても動作はしますが、仕様上は未定義の動作として扱われます。

許可されている10フィールドのうち、必須は $schema と name の2つだけです。
残りの version・description・author・homepage・repository・license・keywords・extensions はすべて任意です。

まず最小有効マニフェストはこれだけです。

{
  "$schema": "https://cursor.com/schemas/plugin/1.0.0/plugin.schema.json",
  "name": "my-plugin"
}

$schema を省略するとバリデーターが仕様バージョンを特定できないため、必ず入れます。
name の命名規則は意外と厳格で、小文字の英数字・ハイフン・ピリオドのみ使用可能、先頭と末尾は英数字、-- や .. の連続は禁止、64文字以内という制約があります。
My-Plugin や my_plugin はその時点でバリデーションエラーになります。

業務プラグイン向けに主要フィールドを埋めた実用例はこうなります。

{
  "$schema": "https://cursor.com/schemas/plugin/1.0.0/plugin.schema.json",
  "name": "internal-api-tools",
  "version": "0.1.0",
  "description": "社内 API 呼び出しと業務ファイル操作のスキルセット",
  "author": {
    "name": "Your Team"
  },
  "license": "MIT",
  "keywords": ["internal", "api", "workflow"],
  "extensions": {
    "skills": [
      { "path": "skills/fetch-order" },
      { "path": "skills/export-csv" }
    ],
    "rules": [
      { "path": "rules/api-conventions.mdc" }
    ]
  }
}

extensions フィールドがスキル・ルール・MCP などの拡張点をまとめる場所です。
ここに列挙したパスがエージェントに読み込まれます。

一つ踏みやすい地雷として、sessionStart フィールドがあります。
Agent Plugins 1.0 の仕様ドキュメントには記載があるのですが、現時点の Cursor バリデーターはこれを弾きます。
「仕様書に書いてあるから使える」と思って入れると、ロードに失敗するので注意してください。

スキルとルールの宣言パターンを公式コードから逆引きする

skills/ 配下の構造は、スキル名のサブディレクトリを作り、その中に SKILL.md を置く形です。
ファイル本体はマークダウンですが、先頭に YAML フロントマターでエージェントへの呼び出し方を宣言します。

---
description: 受注番号を指定して社内 API から注文情報を取得する
globs:
  - "**/*.ts"
  - "**/*.py"
alwaysApply: false
---

# fetch-order スキル

受注番号(order_id)を引数に取り、社内受注管理 API の /orders/{order_id} エンドポイントを呼び出して結果を返す。
レスポンスは JSON 形式で、items・status・customer_id を含む。

description がエージェントにとっての「このスキルを呼ぶべき状況の説明」になります。
ここが曖昧だとエージェントがスキルを呼ばない原因になるので、「何を入力として何を返すか」を具体的に書くのがコツです。

rules/ 配下の .mdc ファイルは、エージェントの振る舞いを制約するルールです。
フロントマターで alwaysApply: true にすると常時適用され、globs でファイルパターンを指定するとそのファイルを操作するときだけ適用されます。
API の命名規則や禁止操作を書いておくのが典型的な使い方です。

mcp.json は MCP サーバーの接続定義を書く場所です。
社内 API を MCP サーバーとして立てている場合、こんな形で宣言します。

{
  "mcpServers": {
    "internal-api": {
      "command": "node",
      "args": ["./mcp-server/index.js"],
      "env": {
        "API_BASE_URL": "https://api.internal.example.com",
        "API_KEY": "${INTERNAL_API_KEY}"
      }
    }
  }
}

環境変数は ${VAR_NAME} 形式で参照できます。
シークレットをファイルにハードコードせず .env から渡す運用が基本です。

「業務フロー固有の操作をどこに書くか」の判断軸はシンプルです。
エージェントに手順を教えたいなら スキル、エージェントの振る舞いを制約したいなら ルール、外部システムへのアクセスを与えたいなら MCP です。
この三つを組み合わせると、「社内 API から情報を取ってきて、特定のフォーマットで出力する」という業務フローをプラグインとして完結させられます。

ローカルで動かしながら最小プラグインを育てる

ローカルテストは ~/.cursor/plugins/local/ にプラグインディレクトリを置くだけで読み込まれます。
Cursor を再起動するか、プラグイン設定を再読み込みすると反映されます。

公式プラグインを起点にスケルトンを作るなら、orchestrate か cursor-sdk あたりが参考にしやすいです。
構造がシンプルで、スキルとルールの両方が入っているので削ぎ落としやすいです。
やることは「自分のユースケースに関係ないスキルを全部消して、plugin.json の name と extensions を書き直す」だけです。
最初は skills/ 一つ・rules/ なし・mcp.json なしの最小構成から始めて、動作確認しながら足していくのが安全です。

つまずきやすいポイントと切り分け方をまとめます。

  • バリデーションエラーが出る: まず name の命名規則を疑います。大文字・アンダースコア・-- の連続が混入していないか確認してください。次に $schema の URL が正しいかを確認します。Cursor のバリデーターはスキーマ URL でバージョンを判定するので、古い URL や typo があるとエラーになります。
  • スキルがエージェントに呼ばれない: SKILL.md の description が曖昧な可能性が高いです。「どんな状況でこのスキルを使うべきか」を具体的に書き直してみてください。extensions.skills のパスが実際のディレクトリと一致しているかも確認します。
  • mcp.json の接続が失敗する: command に指定したプロセスが起動できているか、ポートやパスが正しいかを先に確認します。環境変数が未定義のまま ${VAR_NAME} を参照していると、サーバー起動時にエラーになります。
  • name 命名規則違反: エラーメッセージに「invalid plugin name」が含まれていたら命名規則違反です。lowercase kebab-case に統一して、先頭・末尾が英数字になっているか確認してください。

最小プラグインが動いたら、スキルの description を育てるのが一番効果的な改善です。
エージェントがスキルを選ぶ判断はほぼ description の質で決まります。
実際にエージェントに使わせてみて、呼ばれなかったケースの状況を description に追記していくサイクルが、実務では一番早く精度が上がります。

Agent Plugins 1.0 という共通仕様に乗っているので、一度書いた知識は他のエージェントランタイムにも転用できます。
今のうちにリポジトリを手元で動かしておく価値は十分あります。


株式会社ホコサキは山口県宇部を拠点に、Web 制作・業務システム開発・AI 活用支援を手がけています。
Cursor プラグインのような開発ツール活用から、業務フローへの AI 組み込みまで、実務に即した支援が得意です。
興味があればお気軽に お問い合わせ ください。

    cursor/pluginsを読み解いてカスタムプラグインを自作する | 株式会社ホコサキ