mcpField
C
creating-plugins

creating-plugins

github.com/emdash-cms開発14.0k129 回インストール今日更新
リポジトリ

creating-plugins について

EmDash プラグイン開発者向けのガイドで、サンドボックス型とネイティブ型の形式を扱います。権限宣言、実行境界、本番動作を検証するテストを重視しています。

主な機能

  1. 01サンドボックス型とネイティブ型
  2. 02プラグインの雛形とバンドル
  3. 03ホスト API 権限の宣言
  4. 04ルート、フック、管理 UI
  5. 05本番境界のテスト

活用シーン

  1. 01サンドボックス型プラグインの作成
  2. 02必要なプラグイン権限の宣言
  3. 03フック、ルート、実行時動作のテスト

MCP 対応

MCP ツールを、明示的な権限と Zod 入力スキーマを持つプライベート JSON ルートに関連付ける方法を説明します。MCP ツールの追加には管理者の再承認が必要です。

インストール

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

$npx skills add https://github.com/emdash-cms/emdash --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 の同等性テストは、ランナーに依存する動作に限って追加してください。

参考資料

コメント