Skip to content

Add create_site and list_service_versions MCP tools - #80

Merged
claytoncollie merged 3 commits into
mainfrom
feature/create-site-tool
Sep 4, 2026
Merged

claytoncollie merged 3 commits into
mainfrom
feature/create-site-tool

Conversation

@ivanlopez

Copy link
Copy Markdown

Tools

Tool Purpose
create_site Create a WordPress site (PHP/db/web server versions, multisite, WP admin credentials, Xdebug)
list_service_versions Available PHP / database / web server versions, flagging installed vs. download-on-demand

Notes

  • Returns before the site is ready. Provisioning plus the WP install takes minutes, past most MCP clients' request timeout. AddSiteService
    registers the site with SiteData synchronously before its first await, so the tool returns the new ID with pending: true; callers poll
    site_status until running, or pass wait: true to block.
  • Failures surface on the next poll. Nothing awaits the creation promise once the tool returns, so a later provisioning failure would vanish into
    a Local dialog. It's recorded and exposed as creationError on site_status.
  • enableAgentTools hands the finished site to the existing setupSite(), same as clicking Enable in the UI. agents picks which (default
    ["claude"]).
  • src/helpers/new-site.ts ports Local's nicename formatting and the checks from its renderer-side validate-site-info into pure functions
    returning an error string instead of showing a dialog.
  • One existing test changed. The credential check in tests/security.test.ts guards against leaking an existing site's credentials;
    create_site sets credentials for a site that doesn't exist yet, so it's exempt by name, with a test asserting the exemption list stays accurate.

Known limitations

  • Unless Local is in localhost router mode, provisioning shells out to update /etc/hosts and the OS prompts for admin credentials — creation is
    never fully unattended.
  • Local doesn't expose its preferred service versions to add-ons, so list_service_versions returns a note saying omission lets Local choose;
    create_site reports what the site actually got.

Ivan Lopez added 2 commits September 1, 2026 15:01
Create a new WordPress site in Local through cradle.addSite, the same
service Local's own Add Site flow drives.

Provisioning plus the WordPress install takes minutes, well past most MCP
clients' request timeout, so create_site returns as soon as Local registers
the site and reports pending: true. AddSiteService registers the site with
SiteData synchronously before its first await, so the new ID is available
immediately. Callers poll site_status until it reports running, or pass
wait: true to block.

Because nothing awaits the creation promise once the tool returns, a later
provisioning failure would otherwise vanish into a Local dialog. Record it
and surface it as a creationError field on site_status.

list_service_versions reports the PHP, database, and web server versions
create_site accepts, flagging which are installed versus downloaded on
demand. Local does not expose its preferred versions to add-ons, so the
result explains that omitting a service option lets Local choose, and
create_site reports what the site actually got.

With enableAgentTools, the finished site is handed to the existing
setupSite() so it registers with the MCP server and gets its MCP config and
context files, as clicking Enable in the UI does.

New site details are derived and validated in src/helpers/new-site.ts,
porting Local's site nicename formatting and the checks from its renderer
side validate-site-info into pure functions that return an error string
instead of showing a dialog.

The credential check in tests/security.test.ts guards against leaking an
existing site's credentials. create_site sets credentials for a site that
does not exist yet, so exempt it by name and assert the exemption list
stays accurate.
@claytoncollie claytoncollie changed the title WIP: Add create_site and list_service_versions MCP tools Add create_site and list_service_versions MCP tools Sep 4, 2026
@claytoncollie

Copy link
Copy Markdown
Contributor

Thanks Ivan. Both tools go through Local's own AddSiteService and lightningServices, which is the pattern we want. I pushed one cleanup commit so this can merge:

  • Restored package-lock.json from main. The "update package lock" commit dropped two peer entries, so npm ci failed and CI skipped every job. package.json did not change, so main's lockfile is correct.
  • Wrapped the sites path and site path in path.resolve() before validation. resolveSitePath only expands ~, so /Users/../etc/x passed the macOS check.
  • Built the agents enum from AGENT_NAMES instead of a second literal list.
  • Added new-site.ts and the new tools to the README project tree, and props to the changelog entries.

I also checked the two Local internals against a running install. settings-new-site-defaults.json exists in Local's app data with sitesPath and tld, and Local's own UI uses the same registered flag to decide which service versions to download. Both match your code.

Lint, format, typecheck, 147 tests, and build pass locally. I will merge once CI is green.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🟢 Lines 53.39% (🎯 40%) 299 / 560
🟢 Statements 53.25% (🎯 40%) 311 / 584
🟢 Functions 63.73% (🎯 40%) 58 / 91
🟢 Branches 46.06% (🎯 25%) 164 / 356
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/helpers/new-site.ts 100% 93.75% 100% 100%
src/tools/index.ts 72.72% 50% 28.57% 94.11% 35, 38, 41, 44, 47, 70
Generated in workflow #29 for commit 7e9074e by the Vitest Coverage Report Action

@claytoncollie
claytoncollie merged commit ac5ac53 into main Sep 4, 2026
6 checks passed
@claytoncollie
claytoncollie deleted the feature/create-site-tool branch September 4, 2026 06:20
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.

2 participants