Skip to content

t1k:cocos:playable:mcp-fix

FieldValue
Moduleplayable
Version0.17.0
Efforthigh
Tools

Keywords: bug, cocos-mcp-server, extension, fix, jest, mcp, repair, repro, unknown action

/t1k:cocos:playable:mcp-fix
[<tool>.<action>]

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.

Symptom in the error textVerdict
Unknown action 'x' for tool 'y'Server gap — fix here
Cannot read propert…, is not a function, TypeError, a stack frameServer bug — fix here
not found, required, invalid uuidCaller error — fix the call, not the server
ECONNREFUSED, no answer on the portEditor closed or extension stopped — not a bug
Tool works but returns a wrong-shaped successServer bug — fix here, and see Gotchas
Terminal window
node extensions/cocos-mcp-server/scripts/repro.cjs health # expect: OK — N tools on :3000
cd extensions/cocos-mcp-server && git status --short # must be clean
ls extensions/cocos-mcp-server/node_modules | head -1 # must not be empty

A 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.

ThingPath inside extensions/cocos-mcp-server
Tool handlerssource/tools/<tool-name>.ts
Testssource/test/<tool-name>.test.ts, mocks in source/test/mocks/
Result helperssource/types/index.tssuccessResult / errorResult
HTTP layersource/mcp-server.ts
Repro CLIscripts/repro.cjs

Tool name maps to file name with dashes: manage_nodesource/tools/manage-node.ts. jest roots to source/test, so nothing under scripts/ affects the suite.

Fix one defect per branch.

Terminal window
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.

Read the handler and its actionHandlers map. Defects cluster in three places:

  • an action missing from the actions array or inputSchema.enumUnknown action
  • an unguarded Editor.Message.request result
  • argument coercion — see source/utils/normalize.ts

Add the case to the tool’s .test.ts, following that file’s existing mock style.

Terminal window
cd extensions/cocos-mcp-server && npx jest source/test/<tool-name>.test.ts

Gate — 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.

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.

Terminal window
cd extensions/cocos-mcp-server && npm run build && npx jest

Gate — 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.

npm run build only writes dist/. The editor keeps running the old code until it reloads:

  • MCP tool execute_menu_itemDeveloper/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.

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:

Terminal window
cd extensions/cocos-mcp-server
git fetch origin
git checkout -b fix/<tool>-<slug> origin/main
git commit -m "fix(<tool>): <one line>" -- source/tools/<file>.ts source/test/<file>.test.ts
git push -u origin fix/<tool>-<slug>
gh pr create --repo The1Studio/cocos-mcp-server --base main

Never 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.

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.

  • 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.
  • False success. Some handlers return success: true with an error field nested in data (for example manage_editor get_state when the preview message is unavailable). The caller cannot detect the failure. Treat it as a server bug; errorResult is the fix.
  • dist/ in commits. Check git ls-files dist | head -1 and follow whatever the repo already does. Do not start tracking build output.
  • Windows quoting. Use repro.cjs, not curl — 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 HEAD before assuming which code is being edited.
  • t1k-cocos-playable-tooling-gotchas — working around MCP quirks without changing the server
  • t1k-cocos-playable-parameter-mcp — UUID assignment over MCP
  • t1k-cocos-playable-editor-tools — ConfigWatcher and the package-manager extension