这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@galatanovidiu
Copy link
Contributor

Why

The adapter was passing annotations through unchanged, causing field name mismatches between WordPress Abilities API format and MCP specification. WordPress uses readonly, destructive, and idempotent, while MCP requires readOnlyHint, destructiveHint, and idempotentHint. This caused protocol compliance issues and could break MCP clients expecting the correct field names.

Additionally null annotation values should not be included in MCP responses.

What

Adapts abilities-api annotations format to comply with the MCP ToolAnnotations specification. Adds annotation mapping functions that convert WordPress annotation field names to MCP-compliant format:

  • Tools: Maps readonlyreadOnlyHint, destructivedestructiveHint, idempotentidempotentHint
  • Resources & Prompts: Validates and normalizes audience, lastModified, and priority fields according to MCP specification

The implementation includes:

  • Annotation mapping methods in RegisterAbilityAsMcpTool, RegisterAbilityAsMcpResource, and RegisterAbilityAsMcpPrompt
  • Annotation validation in McpToolValidator, McpResourceValidator, and McpPromptValidator to ensure MCP compliance
  • Filtering of null values
  • Support for MCP-native fields (openWorldHint, title for tools)
  • Comprehensive test coverage for annotation mapping and validation across all three component types
  • Documentation updates explaining the annotation format conversion

This change ensures full compliance with the MCP ToolAnnotations specification while maintaining backward compatibility by accepting both WordPress-format and MCP-native annotation fields.

Closes #70

Copilot AI review requested due to automatic review settings November 10, 2025 16:38
@github-actions
Copy link

github-actions bot commented Nov 10, 2025

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 props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: galatanovidiu <ovidiu-galatan@git.wordpress.org>
Co-authored-by: JasonTheAdams <jason_the_adams@git.wordpress.org>
Co-authored-by: gziolo <gziolo@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@codecov
Copy link

codecov bot commented Nov 10, 2025

Codecov Report

❌ Patch coverage is 92.27642% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.46%. Comparing base (48d7ffb) to head (08f972d).
⚠️ Report is 1 commits behind head on trunk.

Files with missing lines Patch % Lines
includes/Domain/Prompts/McpPromptValidator.php 61.11% 7 Missing ⚠️
includes/Domain/Resources/McpResourceValidator.php 72.22% 5 Missing ⚠️
includes/Domain/Utils/McpAnnotationMapper.php 91.42% 3 Missing ⚠️
includes/Domain/Prompts/McpPrompt.php 83.33% 1 Missing ⚠️
includes/Domain/Resources/McpResource.php 83.33% 1 Missing ⚠️
includes/Domain/Tools/McpTool.php 83.33% 1 Missing ⚠️
includes/Domain/Tools/McpToolValidator.php 90.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##              trunk      #91      +/-   ##
============================================
+ Coverage     79.74%   81.46%   +1.72%     
- Complexity      858      917      +59     
============================================
  Files            46       48       +2     
  Lines          3080     3162      +82     
============================================
+ Hits           2456     2576     +120     
+ Misses          624      586      -38     
Flag Coverage Δ
unit 81.46% <92.27%> (+1.72%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request implements MCP-compliant annotation handling for WordPress abilities, adding support for converting WordPress-format annotations to MCP specification format and validating them according to their respective schemas (ToolAnnotations for Tools, Annotations for Resources and Prompts).

Key Changes

  • Implements annotation mapping from WordPress format (e.g., readonly) to MCP format (e.g., readOnlyHint) for Tools
  • Adds validation and filtering for MCP-specific annotations (audience, lastModified, priority) for Resources and Prompts
  • Introduces comprehensive annotation validation in validators to enforce MCP specification compliance

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
includes/Domain/Tools/RegisterAbilityAsMcpTool.php Adds map_annotations_to_mcp() method to convert WordPress format Tool annotations to MCP ToolAnnotations format
includes/Domain/Tools/McpToolValidator.php Adds strict validation for MCP ToolAnnotations fields (readOnlyHint, destructiveHint, idempotentHint, openWorldHint, title)
includes/Domain/Resources/RegisterAbilityAsMcpResource.php Adds map_annotations_to_mcp() and ISO 8601 timestamp validation for Resource annotations
includes/Domain/Resources/McpResourceValidator.php Adds validation for Resource-specific MCP Annotations (audience, lastModified, priority)
includes/Domain/Prompts/RegisterAbilityAsMcpPrompt.php Adds map_annotations_to_mcp() and ISO 8601 timestamp validation for Prompt annotations
includes/Domain/Prompts/McpPromptValidator.php Adds validation for Prompt-specific MCP Annotations (audience, lastModified, priority)
tests/Unit/Tools/RegisterAbilityAsMcpToolTest.php Adds comprehensive test coverage for Tool annotation mapping and filtering
tests/Unit/Resources/RegisterAbilityAsMcpResourceTest.php Adds test coverage for Resource annotation handling and validation
tests/Unit/Prompts/RegisterAbilityAsMcpPromptTest.php Adds test coverage for Prompt annotation handling and validation
tests/Unit/Domain/Tools/McpToolValidatorTest.php Adds tests for MCP ToolAnnotations validation
tests/Unit/Domain/Resources/McpResourceValidatorTest.php Adds tests for MCP Resource Annotations validation
tests/Unit/Domain/Prompts/McpPromptValidatorTest.php Adds tests for MCP Prompt Annotations validation
tests/Unit/Core/McpAdapterConfigTest.php Updates expected resource/prompt lists to include new annotation test fixtures
tests/Fixtures/DummyAbility.php Adds test fixtures for various annotation scenarios (valid, invalid, partial, null values)
docs/guides/creating-abilities.md Extensively updates documentation to explain WordPress vs MCP annotation formats and usage patterns

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

galatanovidiu and others added 12 commits November 10, 2025 20:29
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Eliminates duplicate annotation mapping code by creating a centralized utility class.

The identical mapping logic was previously duplicated across prompt and resource registration classes, violating DRY principles and making maintenance more difficult.

Creates a new static utility class that handles the conversion of WordPress ability annotations to MCP-compliant format, including validation and normalization of audience, lastModified, and priority fields.

Improves code maintainability by providing a single source of truth for annotation transformation logic.
…to fix/tool-annotations-mapping

Resolved conflicts by keeping local refactored code that uses shared utility classes (McpAnnotationMapper and McpValidator) instead of inline methods.
Add is_null() check in annotation field conversion to prevent null
values from being cast to false. Null annotations are now properly
filtered out as expected.
Remove no-op assertion when no annotations are present. The test
already has assertions and the early return is a valid pass condition.
Replace conditional checks with required assertions to prevent false
positives. Verify annotations and audience are present, priority is
clamped to 0.0, and invalid values are filtered. Update fixture to
include mixed valid/invalid audience values.
Removed the explicit check for the 'priority' field in the validation logic, allowing all numeric values to be processed. This change simplifies the validation flow and enhances maintainability by ensuring that only numeric values are validated without restricting to a specific field.
Copy link
Member

@JasonTheAdams JasonTheAdams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, @galatanovidiu! Left some comments and questions.

…ed validation methods in McpValidator

Updated validation logic to call static methods from McpValidator for base64 and MIME type checks. Removed redundant validation methods from McpPromptValidator and McpResourceValidator. Updated unit tests to reflect these changes and ensure proper validation behavior.
- centralize ability→MCP annotation mapping so MCP-native values are preserved and WP-format overrides take precedence
- trim ability metadata, normalize resource URIs, and enforce server guards before validating prompts/resources/tools
- reuse shared annotation validator logic in tool validator + tests, and add coverage for whitespace URIs and missing MCP server cases
- Trimmed the ability label before assigning it to the tool data title to ensure consistent formatting.
- Updated DummyAbility test fixture to include a new test case for handling whitespace in resource URIs.
- Updated annotation keys from 'readOnlyHint', 'destructiveHint', and 'idempotentHint' to 'readonly', 'destructive', and 'idempotent' across multiple ability classes for uniformity.
- Ensured that the metadata structure aligns with the new naming conventions.
- Implemented logic to set the annotations.title from the label if annotations exist but the title is not set, ensuring better metadata completeness.
- Replaced 'readOnlyHint', 'destructiveHint', and 'idempotentHint' with 'readonly', 'destructive', and 'idempotent' in the DiscoverAbilitiesAbilityTest, ExecuteAbilityAbilityTest, and GetAbilityInfoAbilityTest for consistency with the updated metadata structure.
…a handling

- Adjusted the validation flow for the 'title' field to streamline error handling and ensure non-empty string requirements are enforced.
- Cleaned up whitespace handling in the RegisterAbilityAsMcpResource class to enhance URI normalization.
- Made minor formatting adjustments in ExecuteAbilityAbility for consistency.
Copy link
Member

@JasonTheAdams JasonTheAdams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good improvements, @galatanovidiu! I left some more feedback. 😄

Update McpAnnotationMapper to use null for ability_property when
annotations map directly to MCP field names, improving type safety
and code clarity.
Replace if statements with switch...case in
get_annotation_validation_errors() and fix priority validation logic.
Replace if statements with switch...case in annotation validation
methods and fix priority validation logic.
Return value directly instead of array structure with has_value flag
Copy link
Member

@JasonTheAdams JasonTheAdams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, @galatanovidiu! We have a couple discussions going on, but to your point I believe anything remaining can/should be resolved in a subsequent PR.

LGTM! 🚀

@galatanovidiu galatanovidiu merged commit bf213b0 into trunk Nov 17, 2025
39 of 45 checks passed
@galatanovidiu galatanovidiu deleted the fix/tool-annotations-mapping branch November 17, 2025 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adapt abilities-api annotations format to comply with MCP ToolAnnotations specification

3 participants