Repository navigation
MCP server for coding agents - #1
Merged
Merged
Conversation
apps/mcp is a stdio MCP server that lets coding agents (Claude Code, Cursor, Codex, ...) author Bedrock particle effects with Oxygen's own engine, analysis and viewport: - reference: components with fields, defaults and evaluation phase; materials; Molang queries and maths; Oxygen's measured game rules and Molang guide - list_examples / create_effect: start from the starting effect or a bundled example - read_effect / check_effect: summary and the problems the Problems panel shows - edit_effect: surgical edits by JSON path that keep formatting, key order and comments, reported as a semantic diff - simulate_effect / preview_effect: run the effect headless in Chromium (Playwright) on a fixed 60 fps clock and seed, report counts, bounds, emitters and events, and render pictures or a contact sheet with the editor's viewport To drive the viewport headless, packages/ui exports ViewportScene, the gizmo defaults and the texture providers, makes EffectSession.refreshStats public and lets ViewportScene.frame step without drawing. CI builds the server and the tests include apps/mcp. Setup is in docs/agents.md. Signed-off-by: avtara k <avtarakhrisna1@gmail.com>
Engine (vendor/wintersky, bumped): redrawing a paused frame no longer re-runs its render writes. Effects that lay particles out with a render-pass counter (spiral galaxy, aurora, lightning, magic circle, ...) drifted to wrong colours and sizes whenever the preview was paused, in the editor and in preview_effect, which draws paused frames until textures settle. MCP server: - write_effect replaces a file's whole text (or creates it); refuses invalid JSON, reports the semantic diff or the new file's summary, supports dry_run - simulate_effect / preview_effect take `others` (identifiers and positions) to play other effects in the same scene, through the session's existing scene extras; without it, the extras the file's scene keeps now reach the preview too (they weren't sent before) - preview_effect `return_images: false` (needs save_to) keeps big pictures out of the reply - open_in_editor opens the file in the desktop app: OXYGEN_DESKTOP, else the repository's desktop build, else an installed app; ELECTRON_RUN_AS_NODE is cleared for the child Desktop: one instance (requestSingleInstanceLock). Starting Oxygen again with files, or macOS open-file, hands them to the running window, which opens them or focuses their tabs; files arriving before the renderer asks for its start files are queued. tools/desktop-test.mjs checks the hand-over. Docs: agents.md (new tools and options), accuracy.md (per-particle values in the render pass), building.md (Electron cache, single instance), CHANGELOG. Signed-off-by: avtara k <avtarakhrisna1@gmail.com>
Owner
|
Thank you! |
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.
Summary
Adds an MCP server (
apps/mcp) so coding agents (Claude Code, Cursor, Codex…) can author Bedrock particle effects with Oxygen's own engine, analysis and viewport. It also adds what came out of using it for real: a whole-file write, other effects in the scene, opening effects in the desktop app, and a fix for an engine bug the MCP surfaced (paused redraws).Important
Depends on dev-hydrogen/oxygen-wintersky#1. The second commit bumps
vendor/winterskytod94434e, which for now only exists inavtara/oxygen-wintersky. Please merge that PR first, then CI can check out the submodule (re-run the checks, or I'll rebase onto the merged commit).Review commit by commit. They're split so each can be read on its own:
Add an MCP server for coding agentspackages/uiexports it needsapps/mcpMCP: write_effect, scene effects, open_in_editor; fix paused redrawsCommit 1: the MCP server
A stdio server (
apps/mcp/dist/server.cjs, built with esbuild). The preview page is built with Vite and driven headless through Playwright/Chromium.referencedocs/accuracy.mdanddocs/molang.mdas topicslist_examples,create_effectread_effect,check_effectedit_effectJsonDocument): formatting, key order and comments kept; all-or-nothing; replies with a semantic diffsimulate_effect,preview_effectEffectSession+ViewportScenestepped on a fixed 60 fps clock and seed: counts, bounds, emitters, events, runtime problems, pictures or a contact sheetWhere to look:
apps/mcp/src/server.ts: tool schemas and handlers.src/effects.ts: analysis and edits.src/pack.ts: pack root, child effects, textures.preview/main.ts: headless stepping.src/browser.ts: Playwright and the local file server.Outside
apps/mcp:packages/ui: exportsViewportScene,DEFAULT_GIZMOSand the texture/MERS providers.EffectSession.refreshStats()becomes public.ViewportScene.frame(dt, draw = true)can step without drawing. No behaviour change for the apps.vitest.config.tsincludesapps/mcp/test, and README/docs/building.md/docs/agents.mdcover setup.Commit 2: improvements found by using it
Engine fix (submodule bump). Redrawing a paused frame re-ran
per_render_expression. Render-pass counters (7 bundled examples) then drifted to wrong colours and sizes whenever the preview was paused.preview_effecthit this on every picture, because it draws paused frames until textures settle. The editor hit it whenever you paused. Details and the regression test are in oxygen-wintersky#1.spiral_galaxyexample throughpreview_effect, same camera, t = 3 sMCP
write_effect: replace or create a whole file; refuses invalid JSON; semantic diff or new-file summary;dry_runcomponentsblock) took a long list ofseteditsserver.ts,effects.tsrewriteDiffothers: [{effect, position}]onsimulate_effect/preview_effectscene.extras, no new engine pathserver.tsrunRequest,preview/main.ts,protocol.tsextraschildEffectsonly followed events, so file-kept extras never got their JSONpack.tschildEffects(…, also)preview_effectreturn_images: false(requiressave_to)server.tsopen_in_editorsrc/desktop.tsopen_in_editorlooks for Oxygen in this order:OXYGEN_DESKTOP, then the desktop build of the repository the server was built in, then/Applications/Oxygen.app(macOS) or%LOCALAPPDATA%\Programs\Oxygen\Oxygen.exe(Windows). It clearsELECTRON_RUN_AS_NODEfor the child, because agents built on Electron (VS Code, Cursor) set it for MCP servers.Desktop: one instance
requestSingleInstanceLock(). A second launch hands its files to the first throughsecond-instance, and macOSopen-filetakes the same path. The renderer opens them, or focuses the existing tab (Workspace.openalready dedupes), then the second instance quits.openedAtStart. The window is only raised once the renderer runs, so there's no blank window flash.userData, soOXYGEN_USER_DATAtest profiles stay independent.apps/desktop/src/main.ts,preload.ts,api.ts(onOpenRequested) andrenderer/main.ts.Docs
agents.md: new tools and options, plus "Opening effects in Oxygen".accuracy.md: per-particle values in the render pass, because variables are per emitter.building.md: the Electron cache workaround and single instance.Testing
pnpm test(vitest)tsc/svelte-check: wintersky,@oxygen/mcp,@oxygen/desktop,@oxygen/ui@oxygen/mcptypecheck +apps/mcptestspnpm test:desktop0.21vs0.01), passes with itSmoke results through the built server (JSON-RPC over stdio):
write_effect: invalid JSON → error and no file written; new file → summary;dry_run→ diff and the file unchanged; identical text → "No change".others:poc:galaxyat[0, 0, -8]plays alongside (2 emitters, bounds reach z = −11.4); an unknown identifier is reported.return_images: false: 0 images in the reply; withoutsave_tothe call is refused.open_in_editor: with Oxygen already running, the file opened as a new tab in that window, and only one Electron main process remained.Proof of concept: effects made by an agent through this MCP
Everything below was built by Claude Code driving only these tools (
create_effect,edit_effect,write_effect,check_effect,preview_effect,open_in_editor), working from a reference. The files are on thepr-assetsbranch, kept out of this diff.Black hole and spiral galaxy
poc:black_hole, oneparticles_addeffect):q.rotation_to_camerais constant for/particle(camera-query-constant), so the halo faces a fixed view, adjustable throughv.view_yawfrom a script.poc:galaxy): the spiral galaxy example, with per-particle values moved toparticle_random. Theupdate-render-carrywarning caught a wrong first attempt.SAO death (holographic Steve shattering)
poc:sao_deathis one/particleeffect of 493 particles, with no child events (a child spawned under/particlelands at the world origin):direction_zquads, i.e. 6 parts × 6 faces at real Steve proportions, with a custom wireframe texture.Faces use update/render counters; that's what showed the paused-redraw bug. Contact sheet:
sao-death-sheet.png.Not covered
open_in_editorwas exercised on macOS with the repository build. The Windows path andOXYGEN_DESKTOPwere not run.