A dependency-free PHP 7.4+ runtime for the canonical Model Context Protocol schemas.
The package validates and hydrates exact MCP revisions into immutable shared records. It is a schema package, not an MCP client, server, or transport SDK.
Supported revisions:
2025-11-252026-07-28
Unknown identifiers are rejected. The runtime never selects a revision by a range or nearest-version rule.
Revisions before 2025-11-25 (2024-10-07, 2024-11-05, 2025-03-26, and
2025-06-18) are not accepted as identifiers and have no schema of their own.
Most schema changes up to 2025-11-25 were additive, so consumers that
negotiate one of those versions validate their messages through the
2025-11-25 schema. This is the same approach the official
TypeScript SDK
takes: it ships wire schemas only for 2025-11-25 and 2026-07-28 and parses
every earlier revision with the 2025-11-25 schema. The mapping from a
negotiated version to a schema revision is the consumer's decision, not this
package's.
composer require wordpress/php-mcp-schemaThe runtime described below ships in 0.2.0 and later. Releases before 0.2.0 expose the removed DTO API; see the migration guide.
Choose the exact revision before constructing any protocol value:
use WP\McpSchema\Record\Tool;
use WP\McpSchema\Schemas;
$schema = Schemas::create()->forVersion(Schemas::V2026_07_28);
$tool = $schema->fromArray(Tool::class, array(
'name' => 'get_weather',
'description' => 'Get current weather for a location',
'inputSchema' => array(
'type' => 'object',
'properties' => array(
'location' => array('type' => 'string'),
),
'required' => array('location'),
),
));
echo $tool->getName();
echo json_encode($tool, JSON_THROW_ON_ERROR);fromArray() is for PHP associative-array construction. fromValue() accepts
decoded stdClass/list graphs and existing immutable records. fromJson()
accepts raw JSON and preserves object/list identity and numeric-string object
keys:
use WP\McpSchema\Contract\ClientRequest;
use WP\McpSchema\Record\CallToolRequest;
use WP\McpSchema\Schemas;
$schema = Schemas::create()->forVersion(Schemas::V2025_11_25);
$request = $schema->fromJson(
ClientRequest::class,
'{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_weather","arguments":{"location":"Paris"}}}'
);
if ($request instanceof CallToolRequest) {
echo $request->getParams()->getName();
$arguments = $request->getParams()->getArguments();
if ($arguments !== null) {
echo $arguments->location;
}
}Useful union construction roots live under WP\McpSchema\Contract. Official
JSON Schema anyOf validity is preserved. When more than one object member is
valid, hydration chooses the member declaring the most keys present in the
input; canonical order breaks a tie. Scalar unions keep canonical first-match
behavior.
Records are immutable. Named getters read fields declared by the selected revision. Generic access preserves open-schema extension data:
$hasDescription = $tool->has('description');
$description = $tool->get('description');
$wireObject = $tool->jsonSerialize();has() distinguishes omission from an explicit null. get() reads declared
fields and present extension keys, and rejects unknown absent keys.
jsonSerialize() returns a defensive stdClass and is the complete wire-output
API.
Sequential PHP arrays are JSON lists and associative arrays are JSON objects.
PHP converts numeric-string array keys such as "0" to integers, so use
fromJson() or stdClass for objects made only of sequential numeric keys.
An empty array() becomes an object only where the selected schema requires an
object; in an unconstrained position it remains []. Use new stdClass() when
an unconstrained empty JSON object must be unambiguous.
The selected schema exposes generated directional checks:
$schema->allowsClientRequest('ping');
$schema->allowsClientNotification('notifications/initialized');
$schema->allowsServerRequest('sampling/createMessage');
$schema->allowsServerNotification('notifications/tools/list_changed');
$schema->allowsEmbeddedInput('elicitation/create');For example, ping is valid under 2025-11-25 and absent under 2026-07-28;
server/discover is valid under 2026-07-28 and absent under 2025-11-25.
The method to record map lists every method with its
request, result, or notification record and its revision availability.
WP\McpSchema\SchemasandWP\McpSchema\Schema— exact revision selection and construction.WP\McpSchema\Record— immutable named objects shared where compatible.WP\McpSchema\Contract— useful union construction roots.WP\McpSchema\Value— string constants for canonical enum-like values.WP\McpSchema\Exception— stable selection, validation, JSON, availability, and field-access failures.
See the migration guide when moving from the removed DTO API.
Canonical schemas are pinned under resources/schema/. The development-only
plain Node generator stages and replaces only src/Record/, src/Contract/,
src/Value/, src/Internal/Catalog/, and
src/Internal/TypeRegistry.php. Handwritten runtime files remain separate,
including src/Record.php and the other files under src/Internal/.
composer install
composer test
composer analyse
composer validate --strict
composer autoload:verify
cd generator
npm install
npm run generate
npm run verifyNever edit generated PHP directly. See the generator guide and the architecture.
GPL-2.0-or-later. See LICENSE.md.