Repository navigation
MCP site_import: browser-executed Super Import — needs a store-access decision #540
spcxai2025
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
The goal
Let an MCP connector run the Super Import pipeline — the same thing the Site Import modal does — so a site can be handed to Instatic programmatically instead of a human dragging a ZIP.
I have this working locally and would happily open a PR, but it lands on an architectural decision that is yours to make rather than mine. Details below; the question is at the bottom.
(Context: I opened #539 earlier today, a small
site-importfix. Same area, unrelated change.)What turned out to need no decision
Two things I expected to have to ask about are already settled by precedent in the repo, so I followed it rather than inventing anything:
uploadMediaToolalready accepts bytes inline as base64 (with a byte-budget→character-budget guard). I matched that exactly. Its httpssourceUrlvariant isn't offered here, because this tool runs in the browser and a cross-origin fetch would be CORS-blocked for most hosts — a host-downloaded URL would need server-side staging first, which seems like a follow-up rather than a prerequisite.data.importalready exists and is whatPOST /admin/api/cms/import/archiverequires, sosite_importrequiresdata.import+site.structure.edit(it creates pages and style rules, not just data). No new capability.Browser execution is clearly correct here: the pipeline commits through
createSiteImportAdapterinto the live editor store andparseHtmlneeds a realDOMParser, which is precisely whatruntime/types.tsdocumentsexecution: 'browser'for.One thing your gates caught that I'd have missed:
SITE_MUTATION_TOOLS. A whole-site import is the largest write there is, and the comment on that set describes the exact failure — "the tool would still report the ids it meant to create, so the caller saw success and an empty document."The blocker
The architecture gate rejects a cycle:
createSiteImportAdapter.ts:20andimportPlanning.ts:27bothimport { useEditorStore } from '@site/store/store', and the agent executor is reachable from that store — so any executor import of them closes the loop.A call-time dynamic import does not help:
madge --circularfollows dynamic imports too.Options, and what I'd suggest
The executor already avoids this for its own store access, via the
storeRef.tsregistration indirection (setAgentStoreApi/getAgentStoreApi).createSiteImportAdapter/importPlanning— have them reach the store through a registered API instead of importing it. No duplication, uses your existing pattern, and the modal keeps working unchanged. It does mean touching two existing modal modules' store access, which is why I stopped rather than just doing it.setSiteImportRunner) populated from an always-mounted admin entry point. No change to existing modules, but adds indirection for one tool and raises a "what if unregistered" case.getAgentStoreApi. No cycle, but duplicates ~240 lines of adapter surface — which reads like exactly the kind of thing CONTRIBUTING's "update the source of truth and all callers" is telling me not to do.I'd suggest (1), but it's your call on where import machinery should live.
Question
Would you accept (1) — moving
createSiteImportAdapter/importPlanningonto thestoreRefindirection — as part of adding this tool? If you'd rather have (2), or would rather this feature not exist at all, equally useful to know before I spend more on it.Happy to open the PR either way; the rest is done (schema, tool registration, browser executor, 15 tests, docs in
agent.md+site-import.md,bun run buildandbun run lintclean, and the only failing tests are this cycle plus three bookkeeping gates — SSOT schema map, tool count, module size budget).All reactions