-
Notifications
You must be signed in to change notification settings - Fork 179
WordPress.org Abilities: Add MCP server infrastructure #552
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
Closed
Closed
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
97 changes: 97 additions & 0 deletions
97
wordpress.org/public_html/wp-content/plugins/wporg-abilities/class-autoloader.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| <?php | ||
| /** | ||
| * Autoloader for wporg-abilities. | ||
| * | ||
| * phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed | ||
| * | ||
| * @package WordPressdotorg\Abilities | ||
| */ | ||
|
|
||
| namespace WordPressdotorg\Abilities\Autoloader; | ||
|
|
||
| /** | ||
| * An Autoloader which respects WordPress's filename standards. | ||
| */ | ||
| class Autoloader { | ||
|
|
||
| /** | ||
| * Namespace separator. | ||
| */ | ||
| const NS_SEPARATOR = '\\'; | ||
|
|
||
| /** | ||
| * The prefix to compare classes against. | ||
| * | ||
| * @var string | ||
| */ | ||
| protected $prefix; | ||
|
|
||
| /** | ||
| * Length of the prefix string. | ||
| * | ||
| * @var int | ||
| */ | ||
| protected $prefix_length; | ||
|
|
||
| /** | ||
| * Path to the files to be loaded. | ||
| * | ||
| * @var string | ||
| */ | ||
| protected $path; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param string $prefix Prefix all classes have in common. | ||
| * @param string $path Path to the files to be loaded. | ||
| */ | ||
| public function __construct( $prefix, $path ) { | ||
| $this->prefix = $prefix; | ||
| $this->prefix_length = strlen( $prefix ); | ||
| $this->path = trailingslashit( $path ); | ||
| } | ||
|
|
||
| /** | ||
| * Loads a class if it starts with `$this->prefix`. | ||
| * | ||
| * @param string $class The class to be loaded. | ||
| */ | ||
| public function load( $class ) { | ||
| if ( strpos( $class, $this->prefix . self::NS_SEPARATOR ) !== 0 ) { | ||
| return; | ||
| } | ||
|
|
||
| // Strip prefix from the start (ala PSR-4). | ||
| $class = substr( $class, $this->prefix_length + 1 ); | ||
| $class = strtolower( $class ); | ||
| $file = ''; | ||
|
|
||
| $last_ns_pos = strripos( $class, self::NS_SEPARATOR ); | ||
| if ( false !== $last_ns_pos ) { | ||
| $namespace = substr( $class, 0, $last_ns_pos ); | ||
| $namespace = str_replace( '_', '-', $namespace ); | ||
| $class = substr( $class, $last_ns_pos + 1 ); | ||
| $file = str_replace( self::NS_SEPARATOR, DIRECTORY_SEPARATOR, $namespace ) . DIRECTORY_SEPARATOR; | ||
| } | ||
|
|
||
| $file .= 'class-' . str_replace( '_', '-', $class ) . '.php'; | ||
|
|
||
| $path = $this->path . $file; | ||
|
|
||
| if ( file_exists( $path ) ) { | ||
| require $path; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Registers Autoloader's autoload function. | ||
| * | ||
| * @param string $prefix Namespace prefix. | ||
| * @param string $path Path to class files. | ||
| */ | ||
| function register_class_path( $prefix, $path ) { | ||
| $loader = new Autoloader( $prefix, $path ); | ||
| spl_autoload_register( array( $loader, 'load' ) ); | ||
| } |
97 changes: 97 additions & 0 deletions
97
wordpress.org/public_html/wp-content/plugins/wporg-abilities/class-mcp-server.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| <?php | ||
| /** | ||
| * MCP Server for WordPress.org. | ||
| * | ||
| * Creates a custom MCP server that exposes all WordPress.org abilities as tools. | ||
| * | ||
| * @package WordPressdotorg\Abilities | ||
| */ | ||
|
|
||
| namespace WordPressdotorg\Abilities; | ||
|
|
||
| use WP\MCP\Core\McpAdapter; | ||
| use WP\MCP\Infrastructure\ErrorHandling\ErrorLogMcpErrorHandler; | ||
| use WP\MCP\Infrastructure\Observability\NullMcpObservabilityHandler; | ||
| use WP\MCP\Transport\HttpTransport; | ||
|
|
||
| defined( 'ABSPATH' ) || exit; | ||
|
|
||
| /** | ||
| * MCP Server class. | ||
| */ | ||
| class MCP_Server { | ||
|
|
||
| /** | ||
| * Server ID. | ||
| * | ||
| * @var string | ||
| */ | ||
| const SERVER_ID = 'wporg-mcp-server'; | ||
|
|
||
| /** | ||
| * Register the WordPress.org MCP server. | ||
| * | ||
| * Called on the 'mcp_adapter_init' action. | ||
| * | ||
| * @param McpAdapter $adapter The MCP adapter instance. | ||
| */ | ||
| public static function register( McpAdapter $adapter ): void { | ||
| $tools = self::get_wporg_ability_names(); | ||
|
|
||
| if ( empty( $tools ) ) { | ||
| return; | ||
| } | ||
|
|
||
| $adapter->create_server( | ||
| self::SERVER_ID, | ||
| 'mcp', | ||
| 'wporg', | ||
| 'WordPress.org MCP Server', | ||
| 'MCP server for WordPress.org services.', | ||
| 'v1.0.0', | ||
| array( HttpTransport::class ), | ||
obenland marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ErrorLogMcpErrorHandler::class, | ||
| NullMcpObservabilityHandler::class, | ||
| $tools, | ||
| array(), // Resources. | ||
| array(), // Prompts. | ||
| array( __CLASS__, 'check_permission' ) | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Get all registered WordPress.org ability names. | ||
| * | ||
| * Discovers abilities by querying the WordPress ability registry | ||
| * for any ability whose name starts with 'wporg/'. | ||
| * | ||
| * @return string[] Array of ability names. | ||
| */ | ||
| private static function get_wporg_ability_names(): array { | ||
| $abilities = wp_get_abilities(); | ||
| $tools = array(); | ||
|
|
||
| foreach ( $abilities as $ability ) { | ||
| $name = $ability->get_name(); | ||
|
|
||
| if ( 0 === strpos( $name, 'wporg/' ) ) { | ||
| $tools[] = $name; | ||
| } | ||
| } | ||
|
|
||
| return $tools; | ||
| } | ||
|
|
||
| /** | ||
| * Transport-level permission callback. | ||
| * | ||
| * Requires an authenticated WordPress user. Individual abilities | ||
| * have their own permission callbacks for fine-grained access control. | ||
| * | ||
| * @param \WP_REST_Request $request The REST request object. | ||
| * @return bool True if the user has permission. | ||
| */ | ||
| public static function check_permission( \WP_REST_Request $request ): bool { | ||
| return is_user_logged_in(); | ||
| } | ||
obenland marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
38 changes: 38 additions & 0 deletions
38
wordpress.org/public_html/wp-content/plugins/wporg-abilities/class-registrar.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| <?php | ||
| /** | ||
| * Registrar for WordPress.org abilities. | ||
| * | ||
| * Handles registration of ability categories and individual abilities. | ||
| * | ||
| * @package WordPressdotorg\Abilities | ||
| */ | ||
|
|
||
| namespace WordPressdotorg\Abilities; | ||
|
|
||
| defined( 'ABSPATH' ) || exit; | ||
|
|
||
| /** | ||
| * Registrar class. | ||
| */ | ||
| class Registrar { | ||
|
|
||
| /** | ||
| * Initialize abilities registration. | ||
| */ | ||
| public static function init(): void { | ||
| add_action( 'wp_abilities_api_categories_init', array( __CLASS__, 'register_categories' ) ); | ||
| add_action( 'wp_abilities_api_init', array( __CLASS__, 'register_abilities' ) ); | ||
| } | ||
|
|
||
| /** | ||
| * Register ability categories. | ||
| */ | ||
| public static function register_categories(): void { | ||
| } | ||
|
|
||
| /** | ||
| * Register abilities. | ||
| */ | ||
| public static function register_abilities(): void { | ||
| } | ||
| } |
9 changes: 9 additions & 0 deletions
9
wordpress.org/public_html/wp-content/plugins/wporg-abilities/composer.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "name": "wporg/wporg-abilities", | ||
| "description": "WordPress.org Abilities API integration with MCP server.", | ||
| "type": "wordpress-plugin", | ||
| "license": "GPL-2.0-or-later", | ||
| "require": { | ||
| "wordpress/mcp-adapter": "^0.4" | ||
| } | ||
| } |
93 changes: 93 additions & 0 deletions
93
wordpress.org/public_html/wp-content/plugins/wporg-abilities/composer.lock
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
22 changes: 22 additions & 0 deletions
22
wordpress.org/public_html/wp-content/plugins/wporg-abilities/vendor/autoload.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| <?php | ||
|
|
||
| // autoload.php @generated by Composer | ||
|
|
||
| if (PHP_VERSION_ID < 50600) { | ||
| if (!headers_sent()) { | ||
| header('HTTP/1.1 500 Internal Server Error'); | ||
| } | ||
| $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; | ||
| if (!ini_get('display_errors')) { | ||
| if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { | ||
| fwrite(STDERR, $err); | ||
| } elseif (!headers_sent()) { | ||
| echo $err; | ||
| } | ||
| } | ||
| throw new RuntimeException($err); | ||
| } | ||
|
|
||
| require_once __DIR__ . '/composer/autoload_real.php'; | ||
|
|
||
| return ComposerAutoloaderInit1055b8d9e51a9a4b1dace3c6ffc091f5::getLoader(); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.