feat(mcp-helper): add MCP connect helper PoC for AI tool onboarding#111
Open
MathieuLamiot wants to merge 8 commits into
Open
feat(mcp-helper): add MCP connect helper PoC for AI tool onboarding#111MathieuLamiot wants to merge 8 commits into
MathieuLamiot wants to merge 8 commits into
Conversation
Introduces `mcp-helper-lib/`, a standalone, idempotent WordPress admin helper that injects a "Connect to AI" button next to newly-created Application Passwords and opens a modal where the user picks Claude Desktop or GitHub Copilot and gets a ready-to-paste JSON config block. - `mcp-helper-lib/class-mcp-config-provider.php` — pure data layer: tool metadata and JSON config array generation for both tools. - `mcp-helper-lib/class-mcp-helper.php` — self-contained singleton; registers show_user_profile, admin_enqueue_scripts, and AJAX hooks exactly once even when called by multiple plugins. - `mcp-helper-lib/assets/js/mcp-config.js` — MutationObserver watches for new application passwords, injects the button, drives the modal (tab switching, client-side JSON generation, clipboard copy). - `mcp-helper-lib/assets/css/mcp-config.css` — modal and code block styles. - `wp-plugin/modules/class-mcp-module.php` — thin Module_Interface wrapper that calls MCP_Helper::init() during Sybgo's boot sequence. - `wp-plugin/class-sybgo.php` — adds MCP_Module to build_modules(). - `wp-plugin/composer.json` — adds mcp-helper-lib path repository + require. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…JAX action Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…olution in Docker - Add mcp_helper_assets_url filter so calling plugins can serve assets from their own web-accessible directory instead of vendor/ - MCP_Module sets the filter to SYBGO_PLUGIN_URL/assets, where copies of mcp-config.js and mcp-config.css now live - Fix MutationObserver target: WordPress 5.6+ creates .new-application-password-notice (not .new-application-password); capture password from input.code inside it Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ubmission Tab buttons and the copy button inside the modal had no explicit type, so the browser defaulted to type="submit". Clicking them on the WordPress profile page (which is a <form>) submitted the profile form and navigated away before screenshots could capture the open modal. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Captures all 6 steps of the demo flow (profile page → password creation → Connect to AI button → modal tabs → copy feedback) for product team demo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er, and E2E tests for modal close behaviors Adds 18 PHPUnit unit tests covering AC3, AC4, AC8 (tool config structure, idempotency, page guard), and 3 Playwright E2E tests covering AC6 (modal close via × button, Escape key, and backdrop click). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MCP_Module uses SYBGO_PLUGIN_URL at runtime but it was absent from the PHPStan bootstrap, causing a constant.notFound error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Symlinks created by Composer path repositories do not resolve inside Docker containers because the target path is relative to the host filesystem. Setting "symlink": false makes Composer mirror the files, which works in both local dev and CI (E2E + Plugin Check workflows). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Description
Adds a self-contained
mcp-helper-lib/package and wires it into the sybgo plugin asMCP_Module. Non-technical WordPress admins can now generate ready-to-paste JSON config blocks for Claude Desktop and GitHub Copilot directly from the Application Passwords section of their profile page, without ever needing to edit JSON files by hand.Type of change
Detailed scenario
What was tested
Manual scenario — full user journey (local wp-env)
/wp-admin/profile.phpas admin.WP_API_URL,WP_API_USERNAME, andWP_API_PASSWORD.github.copilot.chat.mcp.servers) without a page reload.Screenshots from all 8 steps were captured by the Playwright spec (
tests/e2e/specs/screenshots/mcp-connect-journey.spec.ts) and saved totests/e2e/screenshots/mcp-journey/.How to test
bin/dev-up.sh(runswp-env startand seeds the DB).http://localhost:8888/wp-admin/profile.phpand log in as admin.WP_API_URL:http://localhost:8888/wp-json/mcp/mcp-adapter-default-serverWP_API_USERNAME:adminWP_API_PASSWORD: the password shown in the noticegithub.copilot.chat.mcp.servers).To run the Playwright screenshot suite:
All 6 tests should pass and screenshots should appear in
tests/e2e/screenshots/mcp-journey/.Affected Features & Quality Assurance Scope
profile.php,user-edit.php) — new UI injected inline.Technical description
Architecture overview
mcp-helper-lib/— standalone packageThe lib is completely decoupled from sybgo internals. Any plugin activates it with one call:
A
private static bool $initializedguard makes repeated calls from multiple plugins a no-op — hooks and assets are registered exactly once per request.MCP_Helperwires four WordPress hooks on first call:show_user_profile/edit_user_profile→render_modal()outputs the hidden#mcp-helper-modaldiv.admin_enqueue_scripts→enqueue_assets()registers JS/CSS onprofile.phpanduser-edit.phponly; guarded bywp_script_is()so the second plugin callinginit()skips asset registration.wp_ajax_mcp_helper_get_tools→ returns tool metadata (nonce +edit_userscap required).MCP_Config_Provideris a pure data class holding tool metadata (labels, config file paths, instructions). JSON generation happens entirely client-side — the Application Password is never sent back to the server after creation.mcp-config.jsuses aMutationObserveron#application-passwords-sectionto detect when WordPress 5.6+'s REST-powered password form adds a.new-application-password-noticeelement, then injects the Connect to AI button. The JSON is built frommcpHelper.siteUrl+mcpHelper.username(localised by PHP) and the password value read frominput.codein the notice.Asset web-accessibility in Docker / wp-env
The
vendor/wp-media/mcp-helper-libsymlink does not resolve inside Docker containers (the symlink target path is in the host filesystem).MCP_Module::boot()sets themcp_helper_assets_urlfilter toSYBGO_PLUGIN_URL . 'assets', pointing to the plugin's ownassets/directory.wp-plugin/assets/js/mcp-config.jsandwp-plugin/assets/css/mcp-config.cssare copied from the lib and served from the plugin URL.Button
type="button"fixAll buttons inside the modal (
mcp-helper-tab-btn,mcp-helper-copy-btn) explicitly declaretype="button". Without this, browsers default totype="submit"inside a<form>, which caused tab and copy clicks to submit the WordPress profile form and navigate away.See updated docs:
wp-plugin/docs/development.md—mcp-helper-libsection andMCP_Moduleentry under Feature Module Architecture.wp-plugin/docs/ajax-actions.md—mcp_helper_get_toolsAJAX action.mcp-helper-lib/README.md— standalone lib usage guide.New dependencies
wp-media/mcp-helper-lib: *(path repository — local package in this monorepo, no external download).Risks
mcp_helper_get_toolsAJAX action verifies a nonce and theedit_userscapability before responding. The Application Password is read from the DOM and used only client-side; it is never sent to the server after creation (WordPress already displayed it once).MCP_Helper::init(), hooks and assets are registered exactly once. No double-rendering, no duplicate enqueues.mcp_helper_assets_urlfilter lets any plugin redirect asset loading to a web-accessible URL. The fallback inget_lib_url()resolves relative toWP_CONTENT_DIR/ABSPATHand should work for standard installs.Mandatory Checklist
Code validation
Code style
Unticked items justification
Unit tests: This PoC is intentionally thin on PHP logic (
MCP_Helperdelegates to hooks;MCP_Config_Provideris a pure data class). The primary value is the browser-side interaction (MutationObserver, modal, JSON generation, clipboard), which is covered by the Playwright screenshot spec. PHP unit tests can be added when the PoC graduates to a production feature.Additional Checks