t1k:cocos:playable:mcp-fix
| Field | Value |
|---|---|
| Module | playable |
| Version | 0.17.0 |
| Effort | high |
| Tools | — |
Keywords: bug, cocos-mcp-server, extension, fix, jest, mcp, repair, repro, unknown action
How to invoke
Section titled “How to invoke”/t1k:cocos:playable:mcp-fix[<tool>.<action>]Cocos MCP — Fix the Server
Section titled “Cocos MCP — Fix the Server”Use when a Cocos MCP tool fails because the server is broken, not because the call was
wrong. The fix lands in The1Studio/cocos-mcp-server, which sits in a Cocos project as the
editor extension extensions/cocos-mcp-server.
To work around a known MCP quirk instead, use t1k-cocos-playable-tooling-gotchas.
To assign UUIDs through MCP, use t1k-cocos-playable-parameter-mcp.
Decision Tree
Section titled “Decision Tree”| Symptom in the error text | Verdict |
|---|---|
Unknown action 'x' for tool 'y' | Server gap — fix here |
Cannot read propert…, is not a function, TypeError, a stack frame | Server bug — fix here |
not found, required, invalid uuid | Caller error — fix the call, not the server |
ECONNREFUSED, no answer on the port | Editor closed or extension stopped — not a bug |
| Tool works but returns a wrong-shaped success | Server bug — fix here, and see Gotchas |
Preconditions
Section titled “Preconditions”node extensions/cocos-mcp-server/scripts/repro.cjs health # expect: OK — N tools on :3000cd extensions/cocos-mcp-server && git status --short # must be cleanls extensions/cocos-mcp-server/node_modules | head -1 # must not be emptyA fresh submodule checkout ships no node_modules, and jest then fails with
Preset ts-jest not found — which reads like a broken repo but is just an uninstalled one.
Run npm install in the submodule first. Its preinstall checks the @cocos/creator-types
version against the editor.
If repro.cjs is missing, the checkout predates it — use curl against the same endpoints,
or update the submodule.
Layout
Section titled “Layout”| Thing | Path inside extensions/cocos-mcp-server |
|---|---|
| Tool handlers | source/tools/<tool-name>.ts |
| Tests | source/test/<tool-name>.test.ts, mocks in source/test/mocks/ |
| Result helpers | source/types/index.ts — successResult / errorResult |
| HTTP layer | source/mcp-server.ts |
| Repro CLI | scripts/repro.cjs |
Tool name maps to file name with dashes: manage_node → source/tools/manage-node.ts.
jest roots to source/test, so nothing under scripts/ affects the suite.
Procedure
Section titled “Procedure”Fix one defect per branch.
1 — Reproduce
Section titled “1 — Reproduce”node extensions/cocos-mcp-server/scripts/repro.cjs call <tool> '{"action":"<action>", ...}'Exit code 1 confirms the failure is live. A call that unexpectedly succeeds means the bug is already gone — stop.
Record the exact arguments now. The same call is replayed in step 6 to prove the fix, and reconstructing it later from memory is where verification quietly turns into guesswork.
2 — Locate
Section titled “2 — Locate”Read the handler and its actionHandlers map. Defects cluster in three places:
- an action missing from the
actionsarray orinputSchema.enum→Unknown action - an unguarded
Editor.Message.requestresult - argument coercion — see
source/utils/normalize.ts
3 — Failing test first
Section titled “3 — Failing test first”Add the case to the tool’s .test.ts, following that file’s existing mock style.
cd extensions/cocos-mcp-server && npx jest source/test/<tool-name>.test.tsGate — the new test must fail before the handler is touched. A test that passes against unfixed code proves nothing and will not catch the regression later.
4 — Minimal fix
Section titled “4 — Minimal fix”Change only what the red test demands. Failures must go through errorResult(...) so the
caller sees isError: true. Never fold a failure into a success payload.
5 — Build and run the whole suite
Section titled “5 — Build and run the whole suite”cd extensions/cocos-mcp-server && npm run build && npx jestGate — tsc clean and every test green. The server repo has no PR CI, so this is the only
automated gate that exists. One unrelated red test blocks the commit; report it rather than
quietly fixing it.
6 — Reload the editor, verify live
Section titled “6 — Reload the editor, verify live”npm run build only writes dist/. The editor keeps running the old code until it reloads:
- MCP tool
execute_menu_item→Developer/Reload node extensions/cocos-mcp-server/scripts/repro.cjs wait --timeout 120- re-issue the exact call from step 1
The port disappears for a few seconds during the reload; wait expects that.
Gate — the live call must now succeed. Green jest with a still-failing live call means the test mocked away the real defect. Return to step 3.
7 — Branch and PR on the server repo
Section titled “7 — Branch and PR on the server repo”The submodule normally sits at a detached HEAD that is older than origin/main — branching
from it produces a PR full of unrelated reverts. Branch from origin/main:
cd extensions/cocos-mcp-servergit fetch origingit checkout -b fix/<tool>-<slug> origin/maingit commit -m "fix(<tool>): <one line>" -- source/tools/<file>.ts source/test/<file>.test.tsgit push -u origin fix/<tool>-<slug>gh pr create --repo The1Studio/cocos-mcp-server --base mainNever commit to main, never merge — the repo is shared, a human reviews.
Afterwards restore the original commit (git checkout <sha>) so the parent project’s submodule
pointer is not left modified.
8 — Submodule pointer
Section titled “8 — Submodule pointer”The parent project pins a commit of the submodule. Bumping it before the PR merges pins an unreviewed branch commit. Default: leave it alone. Report the PR URL and stop.
Stop Conditions
Section titled “Stop Conditions”- Two failed attempts on the same defect — emit
[t1k:mcp-gap kit="cocos" tool="<tool>" gap="<one line>" evidence="<repro>"]and hand back. - The fix would touch more than about three files, or change a tool’s public schema — that is an API change and needs a design decision first.
- Root cause is in the caller’s arguments — fix the call site instead.
- Tests you did not touch are red — pre-existing breakage, report it.
Gotchas
Section titled “Gotchas”- False success. Some handlers return
success: truewith anerrorfield nested indata(for examplemanage_editorget_statewhen the preview message is unavailable). The caller cannot detect the failure. Treat it as a server bug;errorResultis the fix. dist/in commits. Checkgit ls-files dist | head -1and follow whatever the repo already does. Do not start tracking build output.- Windows quoting. Use
repro.cjs, notcurl— nested JSON inside a curl argument is where most wasted time goes. - Detached HEAD. Every submodule command runs at a detached HEAD by default. Check
git rev-parse --short HEADbefore assuming which code is being edited.
References
Section titled “References”t1k-cocos-playable-tooling-gotchas— working around MCP quirks without changing the servert1k-cocos-playable-parameter-mcp— UUID assignment over MCPt1k-cocos-playable-editor-tools— ConfigWatcher and the package-manager extension