Conversation
Adds the php-mcp-schema package providing type-safe DTOs for MCP protocol specification 2025-11-25.
…120) - Update McpErrorFactory to produce JSONRPCErrorResponse DTOs - Add FailureReason enum for structured failure tracking - Update error handler implementations
* feat(domain): Add MCP component contracts and utilities - Add McpComponentInterface for domain models - Add utility classes: ArgumentNormalizer, ContentBlockHelper, AnnotationMapper, NameSanitizer, SchemaTransformer - Update validators for schema compliance * Update includes/Domain/Utils/McpValidator.php Co-authored-by: Copilot <[email protected]> * Update tests/Unit/Domain/Utils/McpValidatorTest.php Co-authored-by: Copilot <[email protected]> * Update includes/Domain/Utils/McpValidator.php Co-authored-by: Copilot <[email protected]> * Update tests/Unit/Domain/Utils/McpValidatorTest.php Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
* refactor(domain): Update domain models to use MCP schema DTOs - McpTool now wraps Tool DTO - McpResource now wraps Resource DTO - McpPrompt now wraps Prompt DTO - Update all validators and ability converters * refactor(domain): alias MCP DTOs and rename get_protocol_dto - Alias schema DTOs as ToolDto/ResourceDto/PromptDto across domain components and tests - Rename McpComponentInterface::get_component() to get_protocol_dto() and update call sites - Clarify wrapper pattern in McpTool/McpResource/McpPrompt docs * docs(domain): use FQNs in DTO phpdoc
* refactor(core): Update core layer for MCP schema integration - Update McpAdapter, McpServer, McpComponentRegistry - Update built-in abilities for DTO responses - Update plugin bootstrap sequence * docs: Replace line number references with @see PHPDoc tags Line numbers in docblock comments are fragile and become outdated when code changes. Using @see tags provides stable references that IDEs can resolve and that survive refactoring. Addresses PR #123 review feedback from JasonTheAdams. * docs: Remove redundant @phpstan-return annotations The @phpstan-return tags were identical to the @return tags, making them unnecessary. PHPStan reads native @return tags directly - the @phpstan-* variants are only needed when the type differs from documentation. Addresses PR #123 review feedback from JasonTheAdams. * refactor(core): inline discover abilities permission checks to remove indirection * docs(core): add array element types to MCP PHPDocs / clarify transport and component array shapes * refactor(core): use protocol DTO accessors and aliases - Alias Prompt/Resource/Tool DTOs in core - Switch registry/server to get_protocol_dto() - Update core registry tests for DTO aliases
…124) * refactor(handlers): Complete MCP schema integration - Update all request handlers for DTO handling - Update HTTP and STDIO transports - Add DTO serialization regression tests - Full MCP 2025-11-25 compliance * refactor: align handlers with protocol DTOs and FQN docblocks * chore: fix unused DTO import * test: fix prompt validator instance test * fix: Use instanceof for exception categorization in RequestRouter Replace exact class name matching with instanceof to properly categorize subclass exceptions. OutOfBoundsException, UnexpectedValueException, and other subclasses now map to their parent's category instead of 'unknown'. * fix: Check wp_json_encode return value in PromptsHandler wp_json_encode can return false on malformed UTF-8 or unencodable data. The fallback was already handled in the invalid-type branch but missing in the missing-type branch. * fix: Add isset check for results in ToolsHandler image handling Prevents PHP warning when a tool returns type=image without a results key. Matches the defensive style used in the resource handling branch above. * refactor: Rename $message to $params in ToolsHandler::call_tool Consistent with PromptsHandler::get_prompt and ResourcesHandler::read_resource which already use $params. * Add trim() to tool name in ToolsHandler::call_tool Consistent with PromptsHandler and ResourcesHandler which already trim the lookup key before resolving. * Fix DEFAULT_MAX_SESSIONS doc comment The constant is 32 but the filter PHPDoc said "Default 5". * Remove dead error helper methods from HandlerHelperTrait All handlers use McpErrorFactory directly. The trait's error helpers (create_error_response, extract_error, missing_parameter_error, permission_denied_error, internal_error, create_success_response) were never called from production code. Removed along with their tests in HandlerHelperTraitTest and ErrorResponseConsistencyTest. * Fix formatting nitpicks across handlers and tests - Remove double blank line in PromptsHandler - Fix broken docblock in McpTransportContext (split constructor and property docblocks) - Fix extra tab indentation in DtoSerializationRegressionTest - Fix extra tab indentation in RequestRouterTest * Extract DEFAULT_IMAGE_MIME_TYPE constant in ToolsHandler Replaces hardcoded 'image/png' fallback with a named constant for better readability. * Remove unused $request_id from handler methods that never use it Only call_tool, read_resource, and get_prompt need $request_id because they pass it to McpErrorFactory for JSON-RPC error envelopes. List, ping, and initialize handlers only return success DTOs, so the parameter was dead weight.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## trunk #136 +/- ##
============================================
+ Coverage 81.88% 87.74% +5.85%
- Complexity 934 1230 +296
============================================
Files 49 54 +5
Lines 3219 3990 +771
============================================
+ Hits 2636 3501 +865
+ Misses 583 489 -94
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR upgrades the MCP Adapter plugin from MCP protocol version 2025-06-18 to 2025-11-25. It migrates handlers and factories from returning plain PHP arrays to returning typed DTO objects from the wordpress/php-mcp-schema library, adds new utility classes, and aligns annotation/capability rules with the updated spec.
Changes:
- Handler return types migrated from plain arrays to typed DTO objects (
InitializeResult,ListResourcesResult,ReadResourceResult,JSONRPCErrorResponse, etc.) - New utility classes added:
McpNameSanitizer,ContentBlockHelper,AbilityArgumentNormalizer,FailureReason,McpComponentInterface - Annotation, capability, and validation rules updated per MCP 2025-11-25 spec (e.g., prompts no longer support annotations at template level;
additionalPropertiesremoved from schemas)
Reviewed changes
Copilot reviewed 72 out of 104 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
includes/Handlers/Initialize/InitializeHandler.php |
Returns InitializeResult DTO instead of an array |
includes/Handlers/Resources/ResourcesHandler.php |
Returns ListResourcesResult/ReadResourceResult DTOs |
includes/Handlers/System/SystemHandler.php |
ping() returns Result DTO; removes unused methods |
includes/Handlers/HandlerHelperTrait.php |
Removes array-based helper methods now superseded by DTOs |
includes/Transport/Infrastructure/RequestRouter.php |
Adds DTO-aware routing with new observability context resolution |
includes/Transport/Infrastructure/HttpSessionValidator.php |
Error responses converted to array via ->toArray() |
includes/Transport/Infrastructure/HttpRequestHandler.php |
Updates validation/error handling for DTO-returning methods |
includes/Transport/Infrastructure/JsonRpcResponseBuilder.php |
Uses McpConstants::JSONRPC_VERSION; reorders methods |
includes/Transport/HttpTransport.php |
Updates protocol version references and doc comments |
includes/Domain/Utils/McpNameSanitizer.php |
New sanitizer for MCP tool/prompt name normalization |
includes/Domain/Utils/ContentBlockHelper.php |
New factory for MCP content block DTOs |
includes/Domain/Utils/AbilityArgumentNormalizer.php |
New normalizer for empty-array-to-null conversion |
includes/Domain/Utils/McpAnnotationMapper.php |
Restricts annotation features per spec; adds boolean normalization |
includes/Domain/Utils/SchemaTransformer.php |
Removes additionalProperties, adds type: object when missing |
includes/Domain/Tools/RegisterAbilityAsMcpTool.php |
Refactored to produce ToolDto and separate adapter metadata |
includes/Domain/Prompts/McpPromptBuilder.php |
Refactored to return PromptDto; marked deprecated |
includes/Domain/Prompts/McpPromptValidator.php |
Updated validation to use DTOs; removes uniqueness check |
includes/Domain/Resources/McpResourceValidator.php |
Updated validation to use DTOs; removes uniqueness check |
includes/Domain/Contracts/McpComponentInterface.php |
New interface for tool/resource/prompt domain objects |
includes/Infrastructure/Observability/McpObservabilityHelperTrait.php |
Adds sensitive key redaction and reorders methods |
includes/Infrastructure/Observability/FailureReason.php |
New failure reason taxonomy for observability |
includes/Core/McpServer.php |
Updates return types; renames get_tool/get_resource/get_prompt to get_mcp_* |
includes/Core/McpAdapter.php |
Adds filter docblocks; reorders properties; wraps server creation in try/catch |
includes/Cli/StdioServerBridge.php |
Refactors error/response handling to use McpErrorFactory constants |
includes/Abilities/ExecuteAbilityAbility.php |
Removes redundant permission double-check; adds AbilityArgumentNormalizer |
includes/Abilities/GetAbilityInfoAbility.php |
Removes redundant permission double-check |
includes/Abilities/DiscoverAbilitiesAbility.php |
Removes redundant permission double-check; reorders methods |
composer.json |
Adds wordpress/php-mcp-schema VCS dependency and php-stubs/wordpress-stubs |
tests/Unit/Handlers/InitializeHandlerTest.php |
Updates tests for DTO-based handler output |
tests/Unit/Handlers/HandlerHelperTraitTest.php |
Removes tests for deleted helper methods |
tests/Unit/ErrorHandling/ErrorResponseConsistencyTest.php |
Updates assertions for DTO-returning handlers |
tests/Unit/ErrorHandlers/ErrorEnvelopeTest.php |
Updates assertions for JSONRPCErrorResponse DTO |
tests/Unit/Domain/Utils/SchemaTransformerTest.php |
Updates tests to reflect new schema transformer behavior |
tests/Unit/Domain/Utils/McpNameSanitizerTest.php |
New test file for McpNameSanitizer |
tests/Unit/Domain/Utils/McpAnnotationMapperTest.php |
Updates and expands annotation mapper tests |
tests/Unit/Domain/Utils/ContentBlockHelperTest.php |
New test file for ContentBlockHelper |
tests/Unit/Domain/Utils/AbilityArgumentNormalizerTest.php |
New test file for AbilityArgumentNormalizer |
tests/Unit/Core/McpAdapterConfigTest.php |
Updates resource/prompt discovery list |
tests/Unit/Cli/StdioServerBridgeTest.php |
Updates protocol version; adds new request handling tests |
tests/Unit/Abilities/GetAbilityInfoAbilityTest.php |
Removes additionalProperties assertion |
tests/Integration/TransportRoutingTest.php |
Removes nextCursor assertion; renames test |
tests/Integration/RegistrationValidationTest.php |
New integration test for tool name validation |
tests/Integration/HttpTransportTest.php |
Updates protocol version strings |
tests/Integration/ErrorHandlingIntegrationTest.php |
Updates assertions for DTO-based error responses |
tests/Integration/BuilderPromptExecutionTest.php |
Updates assertions for GetPromptResult DTO output |
includes/Transport/Infrastructure/McpTransportContext.php |
Minor blank line cleanup |
includes/Transport/Infrastructure/SessionManager.php |
Reorders methods (public before private) |
includes/Transport/Contracts/McpRestTransportInterface.php |
Removes use WP_REST_Request import; uses FQCN |
includes/Servers/DefaultServerFactory.php |
Adds filter docblock for mcp_adapter_default_server_config |
includes/Core/McpTransportFactory.php |
Improves PHPDoc for type annotations |
includes/Autoloader.php |
Minor blank line cleanup |
includes/Abilities/McpAbilityHelperTrait.php |
Minor blank line cleanup |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… types McpPromptBuilder @deprecated now includes version 0.5.0 per WordPress docs standard. RequestRouter fallback block logs the actual unexpected type via error_handler for server-side debugging before returning the generic error response.
… null guards RegistrationValidationTest reformatted from PSR-12/Allman to WordPress/K&R style with tabs, matching all other test files. Two separate null-guard blocks in RequestRouter combined into one — identical runtime behavior, less duplication.
Replace dev branch reference (dev-feat/mcp-schema-2025-11-25) with the proper v0.1.0 release constraint. The upstream feature branch was merged and deleted; v0.1.0 is the first tagged release.
…138) * fix: add SESSION_NOT_FOUND error code and return HTTP 404 for expired sessions MCP spec requires HTTP 404 for invalid/expired sessions, but the transport was returning HTTP 200 via INVALID_PARAMS. Adds SESSION_NOT_FOUND (-32005) error code, factory method, and HTTP status mapping. Updates HttpSessionValidator to use the new error code. Also adds the 202 notification null-check and an explicit comment for JSON-RPC response fall-through. * test: update assertions for HTTP 202 notifications and 404 expired sessions Updates 6 test assertions across 3 files to match the new MCP-compliant HTTP response codes: notifications now return 202, expired/invalid sessions return 404 with SESSION_NOT_FOUND error code instead of INVALID_PARAMS.
…#140) WP_Error is not an actual exception class — it doesn't extend Throwable. The FullyQualifiedExceptions PHPCS rule was enforcing FQN unnecessarily. Add WP_Error to ignoredNames and import it via `use` statements across all namespaced files. PHPDoc annotations retain \WP_Error per FullyQualifiedClassNameInAnnotation.
Replace array<int, T> with list<T> across all PHPDoc annotations for sequential zero-indexed arrays. Propagate list<string> upstream through McpAdapter, McpServer, and McpComponentRegistry. Add array_values() in RegisterAbilityAsMcpPrompt::get_explicit_arguments() to guarantee metadata arrays are proper lists. Closes #127
* feat: add McpVersionNegotiator for protocol version negotiation Pure Core layer class that negotiates the MCP protocol version between client and server. If the client requests a supported version, the server echoes it back; otherwise it falls back to the latest supported version. Supports 2025-11-25, 2025-06-18, and 2024-11-05. * test: add McpVersionNegotiator unit tests Tests cover version negotiation (supported echo, unsupported fallback, empty string), is_supported checks, and ordering invariant using data providers for automatic adaptation when new versions are added. * feat: negotiate protocol version in InitializeHandler Read the client's requested protocolVersion from initialize params and negotiate using McpVersionNegotiator. If supported, echo it back; otherwise fall back to the latest version. Added mcp_adapter_negotiated_protocol_version filter for overriding. * feat: validate MCP-Protocol-Version header on HTTP requests Extract Mcp-Protocol-Version header in HttpRequestContext and validate it on non-initialize requests. Missing header is accepted; present but unsupported returns HTTP 400 with JSON-RPC error code -32000. Matches the TypeScript MCP SDK behavior per the 2025-11-25 spec. * test: add protocol version header validation tests for HttpRequestHandler Cover the validate_protocol_version_header() method and its call site in process_jsonrpc_request(), resolving the Codecov patch coverage gap. Tests verify: missing header accepted, supported version accepted, unsupported version returns SERVER_ERROR, and initialize skips validation. * fix: read session ID from user meta instead of applying rest_post_dispatch WordPress trunk added _wp_connectors_validate_keys_in_rest() hooked to rest_post_dispatch expecting 3 args. Our manual apply_filters call only passed 1, causing ArgumentCountError on WP trunk CI. Reading the session ID directly from user meta avoids the filter entirely. * fix: preserve request id and return 400 for bad protocol header * fix: add type guard for negotiated protocol version filter WordPress apply_filters() has no return type guarantee — any hooked callback could return a non-string value. Re-negotiate from scratch when the filter returns an invalid type to ensure the server always advertises a valid protocol version per MCP spec. * fix: remove unnecessary protocol version filter and add version drift test Remove `mcp_adapter_negotiated_protocol_version` filter from InitializeHandler. Protocol version negotiation is a machine-to-machine contract with no legitimate customization need. The filter created a footgun where a bad return value would cause initialize to succeed but all subsequent requests to be rejected by the transport layer's version validation. Add canary test asserting SUPPORTED_PROTOCOL_VERSIONS[0] matches McpConstants::LATEST_PROTOCOL_VERSION to catch drift between the adapter and the php-mcp-schema vendor package. * test: lock supported protocol versions to prevent silent test shrinkage The data_supported_versions data provider derives fixtures from the SUPPORTED_PROTOCOL_VERSIONS constant, so removing a version silently reduces test coverage instead of failing. Add an explicit assertion on the full expected set so changes require a deliberate test update.
All three version declarations were still at 0.4.1 while v0.5.0 development was underway. This caused observability logs, the WordPress admin plugin list, and the WP_MCP_VERSION constant exposed to extensions to report the wrong version. Updated: - McpAdapter::VERSION class constant - Plugin header Version field (read by WordPress core) - WP_MCP_VERSION global constant
2207780 to
5162f62
Compare
…ansformer
SchemaTransformer now normalizes schemas before processing: converts objects
to arrays (from JSON decode cycles) and removes empty properties that would
serialize as JSON [] instead of the JSON object {} that MCP clients expect.
2a40c4e to
597b961
Compare
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 75 out of 113 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
includes/Infrastructure/Observability/McpObservabilityHelperTrait.php:1
- New sensitive-key/value redaction logic is security-relevant and should be covered by unit tests to prevent regressions (e.g., ensure
apiKey,api_key,Authorization, andrefreshTokenare redacted; ensure non-sensitive keys are preserved; and ensure truncation behavior insanitize_tags()remains stable). Adding a focused unit test file for McpObservabilityHelperTrait would lock this down.
<?php
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Numeric 403 WP_Error code was inconsistent with WordPress conventions and the rest of the codebase (mcp_tool_missing_name, mcp_resource_invalid_uri, etc.). Changed to mcp_session_invalid_input. The 403 was not propagated anywhere — get_session() is unused in production code.
HTTP 405 Method Not Allowed is a client error, not a server internal error. Changed from internal_error (-32603) to invalid_request (-32600) which semantically matches a wrong HTTP method. Updated assertions in both unit and integration tests.
|
I gave this a very quick pass and it worked well for me. I like the direction with the schema work here! |
Package is now published on Packagist, so Composer can resolve it directly without the GitHub VCS repository entry.
|
Just gave it a test ride with a Nextjs MCP app that I am currently working on and this PR has fixed all the issues that the ai-mcp package gave. Fantastic job @galatanovidiu ! 👍 |
There was a problem hiding this comment.
I mostly checked the integration aspects — the migration to php-mcp-schema DTOs is well-structured and easy to follow.
PR #147 (docs) still needs to be merged into this branch before release. I reviewed and approved it separately.
The DTO integration makes perfect sense — it improves verification quality because PHP's type system now enforces the MCP protocol shapes. Handler drift becomes a type error rather than a runtime bug, and spec updates only need to land in one place (php-mcp-schema) instead of being scattered across every handler.
Everything looks good.
|
Have completed the prompt engineering side of my commercebird mcp app, now its working: Using date filters is not working, that is also expected, right @galatanovidiu ? |
* docs: rewrite architecture overview for v0.5.0 schema/adapter separation Two-layer architecture (Schema Layer + Adapter Layer), McpComponentInterface, DTO-based handler returns, new utility classes section, updated extension points. * docs: create v0.5.0 migration guide for php-mcp-schema DTO integration Breaking changes with before/after code, migration steps for custom transports, handlers, components, error handling, and observability. Backward compat notes. * docs: document tool naming transformation and McpNameSanitizer Adds Tool Naming section to creating-abilities guide covering /→- transformation, full sanitization pipeline, mcp_adapter_tool_name filter, and naming examples. * docs: update README component tree, dependencies, and migration link for v0.5.0 Add McpComponentInterface, utility classes, FailureReason to architecture tree. Add php-mcp-schema as required dependency. Add migration guide link. * docs: add server selection guidance comparing default vs custom servers Comparison table, layered discovery explanation, direct registration pattern, filters for disabling/extending the default server. * docs: document HTTP session requirement and Mcp-Session-Id flow Session lifecycle (initialize, use header, terminate), curl examples, error cases, configuration hooks, STDIO exemption, troubleshooting entry. * docs: add migration guides section and upgrading navigation to docs index Link v0.3.0 and v0.5.0 migration guides from docs/README.md navigation. * fix: update McpErrorFactory usage in troubleshooting to use DTO return Aligns with v0.5.0 DTO-based error responses documented in migration guide. * docs: restructure v0.5.0 migration guide to lead with seamless upgrade Most users see no breaking changes — public APIs, hooks, and factory methods are all unchanged. Internal API changes moved to an Advanced section for custom handler/transport implementers only. * fix: address documentation review findings across all v0.5.0 docs Architecture: fix ping return type, transport interface signature, json_text signature, rest_ensure_response → WP_REST_Response, condense redundant sections. Guides: fix protocol version in curl example, clarify tool naming scope, add HTTP 200 error note, explain initialized notification. README: add 4 missing files to component tree, fix dash formatting. Troubleshooting: fix HTTP 400 reference to JSON-RPC error code. Source: fix SessionManager PHPDoc timeout default (was 3600, actual DAY_IN_SECONDS). * docs: apply WordPress sentence case heading standard and fix broken bold Convert all headings to sentence case per WordPress Documentation Style Guide. Fix broken bold markup on creating-abilities.md line 12. * fix: address Copilot review findings on v0.5.0 docs Tool names now show MCP-sanitized form (hyphens) with a note explaining the ability registration name (slashes) vs MCP tool name distinction. Session flow clarifies GET/SSE is reserved for future support. Protocol version corrected to 2025-11-25 in troubleshooting example. Interface snippet aligned with actual McpRestTransportInterface signature.
* feat: add mcp_adapter_prompt_name filter for naming parity Add resolve_prompt_name() method following the same pattern as resolve_tool_name() in RegisterAbilityAsMcpTool. Uses McpNameSanitizer for normalization and McpValidator for post-filter validation. Closes the naming parity gap — tools and resources already had naming filters but prompts did not. Ref #130 * feat: add list filters for tools, resources, and prompts Add mcp_adapter_tools_list, mcp_adapter_resources_list, and mcp_adapter_prompts_list filters. These fire after retrieving components from the registry and before assembling the list result DTO. Enables hiding components per user/role, adding dynamic components, or reordering. Ref #130 * feat: add mcp_adapter_initialize_response filter Filter fires after constructing InitializeResult and before returning. Enables dynamic capabilities, custom instructions, and server info modifications. Ref #130 * feat: add mcp_adapter_tool_call_pre and _post filters Pre-filter fires after permission check, before execution. Enables argument transformation, context injection, and rate limiting. Post-filter fires after execution, before DTO assembly. Enables result transformation, PII redaction, and audit logging. Ref #130 * feat: add mcp_adapter_resource_read_pre and _post filters Pre-filter fires after permission check, before resource execution. Post-filter fires after execution, before DTO conversion. Enables access control, caching, content transformation, and audit logging. Ref #130 * feat: add mcp_adapter_prompt_get_pre and _post filters Pre-filter fires after permission check, before prompt execution. Post-filter fires after execution, before normalization. Enables argument normalization, context injection, and message transformation. Ref #130 * refactor: rename execution hooks and add WP_Error short-circuit Rename pre/post execution hooks to follow WordPress pre_* convention: - mcp_adapter_tool_call_pre → mcp_adapter_pre_tool_call - mcp_adapter_tool_call_post → mcp_adapter_tool_call_result - mcp_adapter_resource_read_pre → mcp_adapter_pre_resource_read - mcp_adapter_resource_read_post → mcp_adapter_resource_read_result - mcp_adapter_prompt_get_pre → mcp_adapter_pre_prompt_get - mcp_adapter_prompt_get_post → mcp_adapter_prompt_get_result The pre_* filters now support WP_Error returns to short-circuit execution, following the WordPress pre_delete_post pattern. This enables rate limiting, circuit breakers, and custom permission checks from filter callbacks. Ref #130 * refactor: extract ToolsHandler::create_error_result() to reduce duplication Consolidate 4 identical CallToolResult error constructions into a private helper method at the bottom of the class. No behavior change. * docs: document WP_Error as possible value in result filter params Filter consumers should know that execute() may return WP_Error, which passes through to the result filter before being handled. * feat: add return type validation for list filter hooks Log a warning and fall back to the original array when a filter callback returns a non-array from mcp_adapter_tools_list, mcp_adapter_resources_list, or mcp_adapter_prompts_list.
|
Nice, glad it's working! Date filtering isn't something the adapter handles @FawadNL. That would be on the CommerceBird or WooCommerce side. The adapter just passes the arguments through to your tool's callback. |


What
This is the v0.5.0 release branch. It covers the full integration of the
wordpress/php-mcp-schemapackage across the entire plugin, plus protocol version negotiation and a handful of compliance fixes that came out of the integration work.Why
Before this, every handler was serializing MCP responses by hand. Each one had its own idea of what the shape looked like. That works until the spec changes or you find a subtle mismatch between what a handler returns and what the protocol actually expects. The schema package gives us typed DTOs for the 2025-11-25 spec. Moving to it means one place to update when the spec changes, and PHP's type system catching drift instead of runtime bugs.
How it was done
The migration happened in six steps, merged in order:
1. Added
wordpress/php-mcp-schemaIntroduced the package as a Composer dependency. It provides type-safe DTOs for the full MCP 2025-11-25 spec (Tools, Resources, Prompts, error envelopes, etc.).
2. Updated error handling
McpErrorFactorynow producesJSONRPCErrorResponseDTOs instead of bare arrays. AddedFailureReasonenum for structured observability tracking.3. Domain contracts and utilities
Added
McpComponentInterfaceas the common contract for domain models, plus five utility classes pulled out of the handlers:AbilityArgumentNormalizer,ContentBlockHelper,McpAnnotationMapper,McpNameSanitizer, andSchemaTransformer. These were previously scattered inline — extracting them made the validator rewrites testable in isolation.4. Domain models wrapped around DTOs
McpTool,McpResource, andMcpPromptnow wrap their respective schema DTOs internally. The interface method becameget_protocol_dto()instead ofget_component(). All validators and ability converters updated to produce and consume the typed DTOs.5. Core layer
McpAdapter,McpServer, andMcpComponentRegistryupdated to pass DTOs through instead of raw arrays. Built-in abilities updated accordingly.6. Handlers and transport
All six request handlers (initialize, tools, resources, prompts, system, ping) rewritten to work with DTOs. The STDIO and HTTP transports updated.
HandlerHelperTraitwas removed entirely — all handlers were already callingMcpErrorFactorydirectly, so the trait was dead code. Added DTO serialization regression tests to lock down the exact JSON shapes the protocol expects.Protocol version negotiation
Added
McpVersionNegotiatorin the Core layer. Oninitialize, the server reads the client'sprotocolVersion, echoes it back if supported, or falls back to the latest. On subsequent HTTP requests, theMcp-Protocol-Versionheader is validated — unsupported version returns HTTP 400. Mirrors the TypeScript MCP SDK behavior.HTTP compliance fixes
SESSION_NOT_FOUND(-32005) instead of HTTP 200 withINVALID_PARAMSSchemaTransformernow strips emptypropertiesobjects and coerces any objects that came through a JSON decode cycle back to arrays, so tool schemas always serialize to the JSON object shape MCP clients expectWhat changed
php-mcp-schemaDTOs — no more hand-rolled arrays in handlersHandlerHelperTraitremoved (was dead code)list<T>annotations everywhere sequential arrays appear — PHPStan can now verify array integrity end-to-end