api-platform-mcp skill
PHPの属性を使用して、API PlatformのリソースをModel Context ProtocolのツールおよびリソースとしてAIエージェントに公開します。
- GitHubスター
- 29
- ファイル
- 1
- 最終コミット
- 2026年10月22日
- ライセンス
- —
- 許可されたツール
- —
api-platform-mcp skillは何をしますか
api-platform-mcpはAgent Skillsです。 PHPの属性を使用して、API PlatformのリソースをModel Context ProtocolのツールおよびリソースとしてAIエージェントに公開します。.
skillのSKILL.mdから生成された要約。
api-platform-mcp skill について
このSKILLは、API Platformを使用している開発者が、PHPベースのAPIリソースをModel Context Protocolのツールおよびリソースとして公開することを可能にします。これにより、PHPクラスを呼び出し可能なツールや読み取り専用のリソースに変換することで、AIエージェントが既存のバックエンドロジックを検出し、対話できるようになります。これは、コマンド実行用の#[McpTool]や、ドキュメントや設定などのコンテンツ取得用の#[McpResource]といった専用の属性を通じて実現されます。
開発者はこれをSymfonyやLaravelアプリケーションに統合して、構造化されたデータやカスタムレスポンスを提供できます。このシステムは、ステートプロセッサ、プロバイダー、バリデーションを含む既存のメタデータスタックを再利用します。DTOを使用して特定の入力スキーマを定義したり、McpToolCollectionでコレクションを処理したり、CallToolResultを返すことで標準のJSONシリアライズをバイパスしたりできます。これにより、LLMは従来のHTTPルートを必要とせずに、標準的なtools/callおよびresources/read操作を通じてAPIと対話できるようになります。
エージェントができること
- 1バックエンドロジックをツールとして公開特定のPHPクラスを、AIエージェントがデータ処理に使用できる呼び出し可能なツールに変換します。
- 2エージェントの入力に対してビジネスルールを適用AIエージェントから送信されたデータが、メール形式や文字列の長さなどの特定のバリデーション制約に従っていることを保証します。
skill の SKILL.md から作成されています。すべてのユースケースは、その引用と照合されています。
api-platform-mcp skillのインストール方法
各コマンドはskillフォルダをクライアントのskillsディレクトリにコピーします。読み込むには、クライアントを再起動するか新しいセッションを開始してください。プラグインにapi-platform-mcp skillをインストールする
/plugin marketplace add api-platform/skillset /plugin install api-platform@api-platform-skillset
Claude Codeにapi-platform-mcp skillをインストールする
~/.claude/skills/api-platform-mcp/SKILL.md
$ npx degit api-platform/skillset/skills/api-platform-mcp ~/.claude/skills/api-platform-mcpClaude Code (project)にapi-platform-mcp skillをインストールする
.claude/skills/api-platform-mcp/SKILL.md
$ npx degit api-platform/skillset/skills/api-platform-mcp .claude/skills/api-platform-mcpCodexにapi-platform-mcp skillをインストールする
~/.agents/skills/api-platform-mcp/SKILL.md
$ npx degit api-platform/skillset/skills/api-platform-mcp ~/.agents/skills/api-platform-mcpGemini CLIにapi-platform-mcp skillをインストールする
~/.gemini/skills/api-platform-mcp/SKILL.md
$ npx degit api-platform/skillset/skills/api-platform-mcp ~/.gemini/skills/api-platform-mcpClaude.aiにapi-platform-mcp skillをインストールする
npx degit api-platform/skillset/skills/api-platform-mcp api-platform-mcp && zip -r api-platform-mcp.zip api-platform-mcp # claude.ai → Customize → Skills → + → Create skill → Upload a skill → api-platform-mcp.zip
SKILL.md
GitHubで表示MCP: Exposing Your API to AI Agents
API Platform turns PHP classes into Model Context Protocol tools and resources. It reuses the existing metadata stack — state processors/providers, validation, serialization, JSON Schema — so an MCP tool is just an operation with no HTTP route.
@experimental. API may change between minor releases.
Install & enable
Symfony — composer require api-platform/mcp symfony/mcp-bundle (bundle namespace is
Symfony\AI\McpBundle, composer name symfony/mcp-bundle):
# config/packages/mcp.yaml
mcp:
client_transports:
http: true
stdio: false
http:
path: "/mcp"
session: { store: "file", directory: "%kernel.cache_dir%/mcp", ttl: 3600 }
# config/packages/api_platform.yaml
api_platform:
mcp:
enabled: true # default: true
format: jsonld # default; must be a registered api_platform.format (json, jsonapi, …)
format sets the serialization format for structured content. jsonld emits @context,
@id, @type. Laravel — enabled by default, endpoint auto-registered at /mcp:
// config/api-platform.php
return [ /* … */ 'mcp' => ['enabled' => true] ];
API Platform registers its own SDK Handler; supports() returns true only for tools/resources
in its registry, otherwise the SDK's own handler chain runs. API Platform tools and native
mcp/sdk tools coexist on the same server.
Two ways to declare a tool
Standalone #[McpTool] class attribute — convenient for a one-off tool. Class properties
become the inputSchema; a state processor handles the command
(CQRS-style — the agent's input is processed through your logic):
use ApiPlatform\Metadata\McpTool;
#[McpTool(
name: 'process_message',
description: 'Process a message with priority',
processor: [self::class, 'process'],
)]
class ProcessMessage
{
public function __construct(
private string $message,
private int $priority = 1,
) {}
// getters + setters drive (de)serialization
public static function process($data): mixed
{
$data->setMessage('Processed: '.$data->getMessage());
return $data;
}
}
The agent's arguments are deserialized into a ProcessMessage, passed to the processor; the
returned object is serialized back as structured content. processor is any callable or a
ProcessorInterface service.
mcp: array on #[ApiResource] — use when the class exposes no HTTP endpoints
(operations: []), combines several MCP operations, or needs resource-level control. Keys are
the tool names, so omit name: inside each new McpTool(...):
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\McpTool;
use App\State\ReadHydraResourceProcessor;
#[ApiResource(
operations: [],
mcp: [
'read_hydra_resource' => new McpTool(
description: 'Navigate to a Hydra API resource by URI.',
processor: ReadHydraResourceProcessor::class,
structuredContent: false,
),
],
)]
class ReadHydraResource
{
public string $uri;
}
Separate input DTO
When the input schema must differ from the result class, point input: at a DTO. That DTO drives
inputSchema; the host class describes the output:
#[McpTool(
name: 'search_books',
description: 'Search books by keyword',
input: SearchQuery::class, // what the agent sends
processor: SearchBooksProcessor::class,
)]
class BookSearchResult
{
public int $id;
public string $title;
public string $isbn;
}
The processor receives a SearchQuery instance and returns the result(s).
Collections — McpToolCollection
Use McpToolCollection (extends McpTool, implements CollectionOperationInterface) when a tool
returns a list — the serializer and schema factory emit collection-shaped output:
use ApiPlatform\Metadata\McpToolCollection;
#[ApiResource(operations: [], mcp: [
'list_books' => new McpToolCollection(
description: 'List Books',
input: SearchQuery::class,
processor: SearchBooksProcessor::class,
structuredContent: true,
),
])]
class Book { public ?int $id = null; public ?string $title = null; public ?string $isbn = null; }
With structuredContent: true and the default jsonld format, the response carries @context,
hydra:totalItems, and a hydra:member array of serialized items; the published outputSchema
reflects that shape. Output schemas are flattened for MCP compliance — no $ref, allOf,
$schema, or definitions.
Custom responses — CallToolResult
Default: results serialize through API Platform's serialization
as structured JSON. For full control, set structuredContent: false and return a CallToolResult:
use Mcp\Schema\Content\TextContent;
use Mcp\Schema\Result\CallToolResult;
#[McpTool(name: 'generate_report', description: 'Generate a markdown report',
processor: [self::class, 'process'], structuredContent: false)]
class Report
{
public function __construct(private string $title, private string $content) {}
// getters/setters …
public static function process($data): CallToolResult
{
return new CallToolResult(
[new TextContent("# {$data->getTitle()}\n\n{$data->getContent()}")],
false, // isError
// 3rd arg: optional _meta array
);
}
}
structuredContent: false disables automatic JSON serialization; the CallToolResult is sent
as-is, with no structuredContent / _meta key in the response.
Schema overrides — the nullable-union gotcha
PHP nullable types generate union schemas like {"type": ["array", "null"]}. Some LLM providers
reject these. Override per property with #[ApiProperty(schema: [...])]:
use ApiPlatform\Metadata\ApiProperty;
class InvokeHydraOperation
{
public string $uri;
public string $method;
#[ApiProperty(schema: ['type' => 'object', 'description' => 'JSON payload for the request'])]
public ?array $payload = null; // without override: {"type": ["array","null"]}
}
Validation — off by default
The MCP SDK validates inputs against the JSON Schema at transport level (types, required fields).
API Platform's own validation pipeline is disabled for MCP tools. Set validate: true to
run business constraints (email format, length, custom rules):
use Symfony\Component\Validator\Constraints as Assert;
#[McpTool(name: 'submit_contact', description: 'Submit a contact form',
processor: [self::class, 'process'], validate: true)]
class ContactForm
{
#[Assert\NotBlank] #[Assert\Length(min: 3, max: 50)]
private ?string $name = null;
#[Assert\NotNull] #[Assert\Email]
private ?string $email = null;
}
Laravel — same validate: true, plus rules: instead of constraints:
#[McpTool(name: 'submit_contact', description: '…', processor: [self::class, 'process'],
validate: true, rules: ['name' => 'required|min:3|max:50', 'email' => 'required|email'])]
Read-only resources — #[McpResource]
Expose retrievable content (docs, config, reference data) backed by a
state provider. uri must be unique and use the resource:// scheme:
use ApiPlatform\Metadata\McpResource;
#[ApiResource(operations: [], mcp: [
'api_docs' => new McpResource(
uri: 'resource://my-app/documentation',
name: 'App-Documentation',
description: 'Application API documentation',
mimeType: 'text/markdown',
provider: [self::class, 'provide'],
),
])]
class Documentation
{
public function __construct(private string $content, private string $uri) {}
public static function provide(): self
{
return new self('# My API Documentation\n\nWelcome.', 'resource://my-app/documentation');
}
}
Options
McpTool and McpResource extend HttpOperation, so they accept all standard
operation options. MCP-specific / notable ones:
| Option | Tool | Res | Notes |
|---|---|---|---|
name |
✓ | ✓ | exposed to agents; defaults to class short name. Omit in mcp: array (key wins) |
description |
✓ | ✓ | defaults to class DocBlock |
structuredContent |
✓ | ✓ | include JSON structured content (default true) |
input / output |
✓ | separate DTO for input schema / output representation | |
inputFormats / outputFormats |
✓ | (de)serialization formats, e.g. ['json'], ['jsonld'] |
|
contentNegotiation |
✓ | ✓ | default false for MCP |
validate |
✓ | run validation pipeline (default false for MCP) |
|
rules |
✓ | Laravel validation rules (Laravel only) | |
annotations/icons/meta |
✓ | ✓ | behavior hints / icon URLs / arbitrary metadata |
uri |
✓ | required, resource:// scheme, unique across server |
|
mimeType / size |
✓ | content MIME type / byte size if known |
Wire protocol (for testing)
Everything is JSON-RPC 2.0 POSTed to /mcp with
Accept: application/json, text/event-stream. initialize returns an mcp-session-id header;
send it back on every subsequent call. tools/list / resources/list enumerate; tools/call
(params: {name, arguments}) and resources/read (params: {uri}) invoke. The handler overrides
Accept to the operation's output format, so a jsonld tool always responds JSON-LD regardless
of use_symfony_listeners.
Laravel
- Config under
mcpinconfig/api-platform.php; endpoint auto-registered at/mcp. - Validation uses
rules:(string/array/closure/FormRequest), not Symfony constraints. - MongoDB is not supported for MCP.
Checklist
-
api-platform/mcp+symfony/mcp-bundleinstalled,/mcptransport configured (Symfony) - Tool class has a
processor(write) orMcpResourcehas aprovider(read) -
operations: []when the class is MCP-only (no HTTP routes) -
name:omitted insidemcp:array entries (the array key is the name) -
McpToolCollection(notMcpTool) for list-returning tools -
structuredContent: false+CallToolResultwhen bypassing JSON serialization - Nullable/union properties overridden with
#[ApiProperty(schema: …)]if the LLM rejects them -
validate: trueset explicitly where business constraints must run -
McpResourceuriis unique and usesresource://
このスキルのファイル
1api-platform-mcp skillに関する質問
Claude Codeにapi-platform-mcp skillをインストールするには
npx degit api-platform/skillset/skills/api-platform-mcp ~/.claude/skills/api-platform-mcpを実行してください。Claude Codeは~/.claude/skills(すべてのプロジェクト)または.claude/skills(単一プロジェクト)からskillsを読み込み、説明がタスクに一致する場合にskillを使用します。
api-platform-mcp skillはどのクライアントで使用できますか
Agent Skills形式を読み込むすべてのクライアントで使用できます: Claude Code、Codex、Gemini CLI、claude.ai(ZIPとしてアップロード)。skill内のスクリプトは、クライアントがコード実行を許可した場合にのみ実行されます。
AIエージェントにアイテムのリストを返すにはどうすればよいですか?
ツールがアイテムのコレクションを返す必要がある場合は、McpToolの代わりにMcpToolCollectionクラスを使用してください。
API PlatformはMCPツールに対して標準のバリデーションを実行しますか?
いいえ、API PlatformのバリデーションパイプラインはMCPツールではデフォルトで無効になっています。ビジネス制約を実行するには、明示的にvalidate: trueを設定する必要があります。
LLMが拒否する可能性のある、null許容プロパティをどのように扱えばよいですか?
#[ApiProperty(schema: [...])]属性を使用して、特定のプロパティのJSON-Schemaをオーバーライドできます。