-
Notifications
You must be signed in to change notification settings - Fork 50
Proposal: Add ability anotations #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## trunk #99 +/- ##
============================================
+ Coverage 85.69% 85.98% +0.28%
- Complexity 103 105 +2
============================================
Files 16 16
Lines 776 792 +16
Branches 86 86
============================================
+ Hits 665 681 +16
Misses 111 111
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:
|
0a65ff7 to
324d332
Compare
1ca8dcb to
1708839
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. |
1708839 to
9306cd9
Compare
9306cd9 to
a84b388
Compare
b0824a5 to
47ef053
Compare
emdashcodes
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this a lot. I prefer the annotations over the current tool/resource pattern.
The instructions will also be useful for providing tool instructions that various things like the MCP Adapter or Agents can adapt.
| * @see WP_Abilities_Registry | ||
| */ | ||
| class WP_Ability { | ||
| /** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to suggest we align our internal naming conventions with the established MCP protocol standards to reduce developer cognitive load and maintain consistency across the systems.
Current approach:
- Internally:
read_only,destructive,idempotent - MCP:
readOnlyHint,destructiveHint,idempotentHint
Suggested approach:
Since MCP is a well-established protocol with defined conventions, I think we should adopt the MCP naming directly in our abilities API:
- Use:
readOnlyHint,destructiveHint,idempotentHintinternally - This eliminates the need for translation in the MCP adapter
- Developers working with both our API and MCP won't need to context-switch between naming conventions
- Minimizes developer confusion when working across both systems
Additional consideration - Instructions handling:
For the instructions field, since MCP uses the tool description as instructions, we can handle this in the MCP adapter by appending our instructions content to the description field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The counterpoint would be that WordPress uses snake case convention for naming properties. REST API is a good reflection of that. It's also inconvenient with JavaScript that uses camel case similarly to the MCP protocol. Sometimes, we even mix the two when functionality spans all layers, as with block types that also support the JSON format, which again uses camel case.
@felixarntz, and @swissspidy, what are your thoughts on that aspect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on aligning with WordPress's snake case convention:
- For the reason @gziolo mentioned: We shouldn't discard WordPress Coding Standards when it's convenient :)
- Another counterpoint is that this is the Abilities API which was from the beginning decided to be decoupled from MCP, and rightfully so.
IMO it's perfectly reasonable to have a translation layer in place as part of the MCP adapter, we shouldn't change the Abilities API to tie in particularly well with MCP when it leads to other problems.
Aside: I do agree it's painful to deal with snake_case from the server in the client-side JavaScript world where everything is camelCase. My recommendation for that reason is to use single-word names (like readonly, destructive, idempotent) wherever possible, as those would be both valid snake_case and valid camelCase. But obviously this is not the problem discussed here - it doesn't allow us to align with the MCP naming.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to rename from read_only to readonly. I'm not even 100% sure whether "read-only" is the ultimate correct English spelling 😄 I definitely saw many times readonly in the context of programming, for example, in TypeScript.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whatever you decide to do is ok with me. Also, adapting those keys to the MCP standards is not a big problem.
I also understand your points on WP coding standards and the abilities-api being decoupled from MCP.
One thing I want to avoid when creating abilities for MCP usage:
$annotations = array(
'read_only' => true, // translated to readOnlyHint
'destructive' => false, // translated to destructiveHint
'idempotent' => true, // translated to idempotentHint
'openWorldHint' => false,
'lastModified' => '...',
'title' => '...',
'audience' => '...',
'priority' => '...',
)This is inconsistent, non-standard, and ugly.
So, what do you think we should do to avoid this situation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Completely agree, we shouldn't have inconsistencies like this.
Where does this example list of identifiers come from? As far as this PR is concerned, I think we can use readonly to work around the difference between snake_case and camelCase.
If there are terms where we need multi-word identifiers, I'd say we need to use snake_case if their source of truth is on the server (i.e. in PHP).
If in some JavaScript use-cases we need to translate stuff to be camelCase, we could probably do that consistently as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @felixarntz. We shouldn't build anything in Abilities around the MCP standard. The MCP Adapter is a consumer of the Abilities API and should handle any translations and such needed to work. Any parameters added by the MCP Adapter should follow the pattern established here.
As a grammatical note, it kills me every time I see "readonly" in various contexts. We're just lying to ourselves. 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MCP annotations are documented here:
https://modelcontextprotocol.io/specification/2025-06-18/schema#annotations
https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used the same docs to shape basic needs for abilities based on the discussion in #62.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed read_only key to readonly, and adjusted docs to use "read-only" form in 9f3a00c.
|
I opened a follow-up with extended docs in #104. |
Closes #62.
What
I took some inspiration from ToolAnnotation in MCP. For starters, we will need
read_onlyto replace the current logic that usesmeta.toolto distinguish between HTTP method usage (i.e.,GETandPOST) in requests.Why
The best explanation of the root problem that is being addressed comes from @galatanovidiu in WordPress/mcp-adapter#48 (comment)
Here, we remove all references to
toolandresourcenomenclature. Instead, we perform detection of theGETvsPOSTmethod in the REST API calls based on annotations that describe what the ability does: read only vs updates data.Fute considerations
With more properties, we could also start using
DELETEHTTP method as I exploreidempotentanddestructiveannotations. I'm also interested in including freeforminstructionsso devs could consist of usage examples for both the user and for consideration to pass to LLMs.Testing
Run test: