mcpField
C
creating-plugins

creating-plugins

github.com/emdash-cms開発10895 回インストール2 日前に更新
リポジトリ

creating-plugins について

creating-pluginsは、EmDashプラグイン開発のためのスキルガイドです。サンドボックス型とネイティブ型、API権限、ルート、フック、管理UIを扱い、本番境界での動作テストも説明します。

主な機能

  1. 01サンドボックス型とネイティブ型の選択
  2. 02プラグインの雛形とマニフェスト設定
  3. 03機能単位でのホストAPI権限宣言
  4. 04ルート、フック、MCPツールの構築
  5. 05テストホストによる本番境界の検証

活用シーン

  1. 01EmDash向けサンドボックスプラグインの作成
  2. 02プラグインルートやMCPツールのアクセス権宣言
  3. 03コンテンツ操作、認可、ランナー動作のテスト

MCP 対応

MCPツールは明示的な権限とZod入力スキーマを持つ非公開JSONルートを参照し、元に戻しにくい操作にはdestructiveを設定するよう説明しています。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/emdash-cms/skills --skill creating-plugins

インストール後、Claude Code で/creating-pluginsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
admin-ui.md
api-routes.md
block-kit.md
comments.md
content.md
hooks.md
media.md
portable-text-blocks.md
publishing.md
sandbox-boundaries.md
storage.md
taxonomies-and-redirects.md

詳細

EmDash プラグインの作成

意図した実行モードに対応する API を使用してビルドします。このスキルの例と食い違う場合は、ソースの種類と本番環境の境界に関するテストを優先してください。

形式を選択する

形式ランタイムソース管理 UI配布
サンドボックス型src/plugin.ts が SandboxedPlugin をデフォルトエクスポートBlock Kit ページ、ウィジェット、保存済みエントリーパネル、アクションプラグイン CLI とレジストリ
ネイティブdefinePlugin() / createPlugin()React、Block Kit、Astro コンポーネント信頼されたサイト依存関係のみ

ホストプロセスへのアクセス、React による管理コード、Astro のレンダリングコンポーネント、生のページフラグメント、またはカスタム Portable Text ブロック定義が必要な機能でない限り、サンドボックス型プラグインを使用してください。ネイティブプラグインはサイトの権限で実行され、レジストリからインストールすることはできません。

サンドボックス型プラグインのスキャフォールド

pnpm dlx @emdash-cms/plugin-cli init my-plugin
cd my-plugin
pnpm install
pnpm run test

マニフェストは、ID と信頼に関する契約です。ランタイムフックとルートは src/plugin.ts に記述します。CLI はディスクリプター、マニフェスト、バンドルを生成します。別個のディスクリプターファクトリーや sandbox-entry.ts は作成しないでください。

import type { SandboxedPlugin } from "emdash/plugin";

const plugin: SandboxedPlugin = {
	hooks: {
		"content:afterSave": async (event, ctx) => {
			ctx.log.info("Content saved", { id: event.content.id });
		},
	},
};

export default plugin;

作成用の型は emdash/plugin から import type を使ってインポートします。CLI は、emdash/plugin の pluginRoute() や pluginResponse()、および emdash/client の portableTextToMarkdown() などの値のインポートをバンドルします。サンドボックス型のランタイムコードでは Web API を使用できますが、Node.js の組み込みモジュールは使用できません。

アクセスを宣言する

emdash-plugin.jsonc ですべてのホスト API を宣言してください。権限の追加、ルートの公開、または MCP ツールの追加には、管理者による改めての承認が必要です。

機能付与される権限
schema:read公開コレクションとフィールド定義
admin.editor-draft:read明示的なエディター操作後の、選択された未保存のフィールド値
admin.editor-draft:patchエディターレビュー用に提案された、ホスト検証済みの未保存フィールド変更
content:readコンテンツの識別情報、翻訳、公開済みの公開 URL
content:revisions:read保持されているリビジョンデータ。コンテンツの読み取りを暗黙的に含む
content:write作成、更新、削除、翻訳の作成。読み取りを暗黙的に含む
content:publishリビジョンで保護された公開、非公開、スケジュール、スケジュール解除。読み取りを暗黙的に含む
content:restoreリビジョンで保護された読み取りと、ゴミ箱内コンテンツの復元
hooks.content-policy:register公開前、スケジュール前、非公開前のポリシーフック
taxonomies:readタクソノミー定義、用語、エントリの割り当て
taxonomies:write用語の作成と割り当ての差分。読み取りを暗黙的に含む
bylines:read公開バイラインプロフィールと、単一または一括のエントリクレジット
redirects:readバージョン管理されたリダイレクトの検査
redirects:writeバージョン管理されたリダイレクトの作成、更新、削除。読み取りを暗黙的に含む
comments:read保存された、ゴミ箱にないコメントとその個人データ
comments:moderate期待ステータスによるモデレーション。読み取りを暗黙的に含む
media:read準備完了メディアのメタデータと認証済みアセット URL
media:bytes:read制限付きメディアバイトとコンテンツハッシュ
media:metadata:write代替テキスト、キャプション、フォーカルポイントの更新
media:writeアップロードと削除。メディアの読み取りを暗黙的に含む
network:requestallowedHosts に制限された ctx.http.fetch()
network:request:unrestrictedホストリストなしの ctx.http.fetch()
users:readユーザーディレクトリの検索。コメントフックでも必要
email:sendトランスポートが設定されている場合のメール配信
hooks.email-transport:register排他的な email:deliver フック
hooks.email-events:registerメールの前後フック
hooks.page-fragments:register信頼済み専用のページフラグメント。サンドボックス登録から除外

設定、KV、宣言されたストレージ、ロギング、cron スケジューリングはプラグインスコープであり、ケイパビリティは不要です。ユーザー設定には ctx.settings を、内部のキーと値の状態には ctx.kv を、クエリ可能なレコードには宣言された ctx.storage.<collection> を使用してください。

使用する API の詳細なリファレンスを参照してください:

ルート、HTTP、MCP

ルートはデフォルトで非公開であり、認証、宣言された RBAC 権限、トークンスコープ、または CSRF 対策が必要に応じて求められます。公開ルートはインターネットに公開されるため、インストール時に明示的な同意が必要です。

宣言されていないルートでは、従来の JSON/クエリエンベロープが維持されます。ホスト側で解析を強制するには、メソッドと本文モードを宣言してください。pluginResponse() は、生のレスポンスを宣言したルートでのみ使用してください。送信する ctx.http.fetch() のレスポンスと、宣言されたルートの本文はバッファーに読み込まれ、サイズが制限されます。

MCP ツールでは、明示的な権限と Zod 入力スキーマを指定した非公開 JSON ルートを参照します。元に戻すことが難しい操作には destructive: true を指定してください。API ルートと MCP ツールをお読みください。

フック

サンドボックス化されたフックは、信頼されたフックと同じ優先順位、依存関係、タイムアウト、エラーポリシー、有効化、排他的プロバイダー、機能のパイプラインに組み込まれます。公開ポリシーフックは、公開権限を付与することなく、アクションの起点と実行者を識別します。ctx.comments を通じて呼び出されたコメントモデレーションは、プラグイン起点であることを報告し、通常の after フックを一度実行します。フックをお読みください。

宣言型管理 UI

サンドボックス化されたページとウィジェットは、検証済みの Block Kit を返します。構造化リンクはホストが解決するターゲットを使用し、routeCtx.ui にはホストが証明したロケール、方向、サーフェスが含まれます。外部画像には、一致するネットワーク権限が必要です。

保存済みエントリーのパネルとアクションは、非公開ルートを参照します。通常のパネル読み込みで受け取るのは、ホストが再読み込みした保存済みの ID とバージョンだけです。明示的な操作で選択済みの未保存フィールドを受け取る場合や、フィールド全体を対象とするアトミックなパッチを提案する場合は、admin.editor-draft:read または admin.editor-draft:patch を追加し、拡張機能レベルのコレクションおよびフィールドセレクターも指定してください。パッチ権限には読み取り権限が含まれません。ホストは受け付けたパッチをプレビューし、フォームを変更済みとしてマークします。自動的に保存することはありません。保存済みのコンテンツは、機能によってアクセスが制御される ctx.content を通じて読み取ってください。

宣言型フィールドウィジェットでは、現在、サポート対象の Block Kit 要素を組み合わせて JSON 値を作成できます。カスタム Portable Text ブロックと Astro レンダーコンポーネントは、引き続きネイティブのみで利用できます。管理 UI、Block Kit、Portable Text ブロックをお読みください。

ランナーの同等性

Cloudflare Worker Loader と Node/workerd は、プラグイン単位のブリッジを介して同じバンドルを実行します。どちらも、バイナリのバイト列を保持したうえで、ctx.http.fetch() からバッファーに読み込まれた WHATWG レスポンスを返します。リクエスト本文とレスポンス本文のデコードは 8 MiB に制限されます。一方のラッパーで見つかる追加メソッドではなく、エクスポートされた型に基づいて実装してください。

ここに記載されていない API を利用する設計を行う前に、サンドボックスの境界をお読みください。

本番環境の境界をテストする

フック、ルート、マニフェスト、機能、KV、設定、ストレージのトランスポートをすばやくテストするには、createPluginTestHost() を使用してください。実際のコンテンツアクション、プラグインの有効化、メディア、コメント、リダイレクト、スケジューリング、再起動、認可、CSRF、キャッシュ、Block Kit の検証、保存済みエントリーの拡張機能をテストする必要がある場合は、createPluginRuntimeTestHost() を使用してください。

ランタイムフィクスチャは、フックを実行せずに状態を設定します。ランタイムアクションは本番環境の境界を呼び出し、インスペクターは観測可能な状態を読み取ります。送信する HTTP レスポンスは host.http.respond() でキューに追加し、リクエストは host.http.requests() で確認してください。使用後はすべてのホストを破棄してください。Node/workerd の同等性テストは、ランナーに依存する動作に限って追加してください。

参考資料

コメント