一键导入
waaseyaa-mcp-endpoint
Use when working with the MCP server endpoint, JSON-RPC handling, tool registry, authentication, or files in packages/mcp/
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when working with the MCP server endpoint, JSON-RPC handling, tool registry, authentication, or files in packages/mcp/
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when working with AI schema generation, agent execution, pipeline orchestration, vector storage, agent tools, or files in packages/ai-schema/, packages/ai-agent/, packages/ai-pipeline/, packages/ai-vector/, packages/ai-tools/, packages/ai-observability/
Use when editing docs/specs/, CLAUDE.md orchestration, or agent rules — keep subsystem specs aligned with code, run drift checks, and follow the anchor-issue + design-first workflow (GitHub as integration surface).
Use when working with JSON:API endpoints, resource serialization, query parsing, schema presentation, route building, or files in packages/api/, packages/routing/
Use when working with entity types, entity storage, entity queries, field definitions, field type plugins, config entities, config import/export, or files in packages/entity/, packages/entity-storage/, packages/field/, packages/config/. Covers EntityInterface, EntityBase, EntityType, EntityTypeManager, SqlEntityStorage, SqlEntityQuery, SqlSchemaHandler, EntityRepository, UnitOfWork, FieldDefinition, FieldTypeManager, FieldItemBase, ConfigFactory, ConfigManager. Also applies when touching User (packages/user/) or Node (packages/node/) entity subclasses.
Use when working with service providers, domain events, cache backends, database queries, migrations, package discovery, attribute scanning, or files in packages/foundation/, packages/cache/, packages/database-legacy/, packages/plugin/
Use when working with HTTP middleware, event middleware, job middleware, pipeline compilation, middleware discovery, or files in packages/foundation/src/Middleware/, packages/routing/, packages/user/src/Middleware/, packages/access/src/Middleware/, public/index.php
| name | waaseyaa:mcp-endpoint |
| description | Use when working with the MCP server endpoint, JSON-RPC handling, tool registry, authentication, or files in packages/mcp/ |
This skill covers the MCP (Model Context Protocol) package:
packages/mcp/src/ -- McpEndpoint, McpResponse, McpRouteProvider, McpServerCardpackages/mcp/src/Auth/ -- McpAuthInterface, BearerTokenAuthpackages/mcp/src/Bridge/ -- ToolRegistryInterface, ToolExecutorInterfaceUse this skill when:
final readonly class McpEndpoint
{
public function __construct(
private McpAuthInterface $auth,
private ToolRegistryInterface $registry,
private ToolExecutorInterface $executor,
) {}
public function handle(
string $method,
string $body,
?string $authorizationHeader,
): McpResponse;
}
Single entry point for all MCP traffic. Authenticates, parses JSON-RPC, dispatches to internal handlers.
final readonly class McpResponse
{
public function __construct(
public string $body,
public int $statusCode = 200,
public string $contentType = 'application/json',
) {}
}
interface McpAuthInterface
{
public function authenticate(?string $authorizationHeader): ?AccountInterface;
}
Returns AccountInterface on success, null on failure. BearerTokenAuth is the MVP implementation mapping opaque tokens to accounts.
interface ToolRegistryInterface
{
/** @return McpToolDefinition[] */
public function getTools(): array;
public function getTool(string $name): ?McpToolDefinition;
}
interface ToolExecutorInterface
{
public function execute(string $toolName, array $arguments): array;
}
Returns MCP tool result format: {content: [{type: "text", text: "..."}], isError?: bool}.
POST /mcp
-> McpEndpoint::handle()
-> authenticate($authorizationHeader) -> AccountInterface | null (401)
-> json_decode($body) -> parse error (-32700) | invalid request (-32600)
-> match $request['method']:
'initialize' -> protocol version, capabilities, server info
'ping' -> empty result
'tools/list' -> ToolRegistryInterface::getTools() -> toArray()
'tools/call' -> ToolExecutorInterface::execute($name, $arguments)
default -> method not found (-32601)
| Code | Meaning |
|---|---|
-32700 | Parse error (invalid JSON) |
-32600 | Invalid request (missing method field) |
-32601 | Method not found |
-32602 | Invalid params (missing tool name, unknown tool) |
-32001 | Unauthorized (auth failure) |
McpRouteProvider registers two routes:
| Route | Path | Methods | Auth |
|---|---|---|---|
mcp.endpoint | /mcp | POST, GET | Required (bearer token) |
mcp.server_card | /.well-known/mcp.json | GET | Public |
Note: Routes are defined in McpRouteProvider but not yet wired into public/index.php. This is a known gap.
waaseyaa/ai-schema (McpToolDefinition), waaseyaa/ai-agent (AgentExecutor), waaseyaa/routing, waaseyaa/access (AccountInterface)Always pair json_encode(..., JSON_THROW_ON_ERROR) with json_decode(..., JSON_THROW_ON_ERROR). The endpoint already does this correctly -- maintain it.
The auth interface returns ?AccountInterface (from waaseyaa/access), not a concrete User class (from waaseyaa/user). The MCP package must not depend on waaseyaa/user.
Tool executor must return {content: [{type: "text", text: "..."}]}. The isError key is optional (defaults to false). Don't return raw strings or arrays -- wrap in the content block format.
HttpRequest::createFromGlobals() consumes php://input. The front controller must pass the body via $httpRequest->getContent(), not re-read php://input.
All concrete classes are final readonly class. Use real instances in tests:
// Auth: use BearerTokenAuth with known tokens
$auth = new BearerTokenAuth(['test-token' => $account]);
// Registry/Executor: use anonymous classes implementing the interfaces
$registry = new class implements ToolRegistryInterface { ... };
$executor = new class implements ToolExecutorInterface { ... };
$endpoint = new McpEndpoint($auth, $registry, $executor);
$response = $endpoint->handle('POST', $body, 'Bearer test-token');
$auth = new BearerTokenAuth(['tok' => $account]);
$registry = new class implements ToolRegistryInterface {
public function getTools(): array { return []; }
public function getTool(string $name): ?McpToolDefinition { return null; }
};
$executor = new class implements ToolExecutorInterface {
public function execute(string $toolName, array $arguments): array {
return ['content' => [['type' => 'text', 'text' => 'ok']]];
}
};
$endpoint = new McpEndpoint($auth, $registry, $executor);
// Test auth failure
$response = $endpoint->handle('POST', '{}', null);
assert($response->statusCode === 401);
// Test ping
$body = json_encode(['jsonrpc' => '2.0', 'method' => 'ping', 'id' => 1]);
$response = $endpoint->handle('POST', $body, 'Bearer tok');
assert($response->statusCode === 200);
$auth = new BearerTokenAuth(['secret' => $account]);
assert($auth->authenticate(null) === null);
assert($auth->authenticate('Bearer wrong') === null);
assert($auth->authenticate('Bearer secret') === $account);
assert($auth->authenticate('bearer secret') === $account); // case-insensitive
$card = new McpServerCard(name: 'Test', version: '1.0.0', endpoint: '/mcp');
$json = $card->toJson();
$decoded = json_decode($json, true);
assert($decoded['endpoint'] === '/mcp');
assert($decoded['transport'] === 'streamable-http');
docs/specs/mcp-endpoint.md -- Full MCP endpoint specificationdocs/specs/ai-integration.md -- AI layer that provides McpToolDefinition and AgentExecutorCLAUDE.md -- Project-wide gotchas including JSON symmetry and AccountInterface vs User