elicit_bevy
Complete MCP coverage for Bevy 0.18 — every user-authored type, method, trait, and macro, via the Model Context Protocol.
Why This Exists
Bevy is built around two hard-to-serialize abstractions:
- ECS: entities, components, systems, and resources exist only at runtime inside a running
App - Generics:
Query<D, F>,Handle<A>,Res<R>,MeshMaterial3d<M>— parameterized by types the agent does not know at compile time
Connecting an AI agent to a live Bevy runtime over MCP is therefore the wrong abstraction.
The agent cannot inspect what it cannot serialize, and it cannot round-trip a World state
through a JSON schema.
elicit_bevy takes a different stance: the agent authors code, not runtime state.
Every tool in the crate produces a fragment of source Rust that, when compiled into the
user's project, creates the described game behavior. There is no runtime bridge to Bevy;
there is a comprehensive library of source-code generators that understands the full Bevy
0.18 API surface.
This approach has three advantages:
- No runtime dependency — the MCP server requires only
elicit_bevyas a library; it does not link against a running game or embed a Bevy instance. - Exact fidelity — generated code matches what a skilled Bevy developer would write. There is no lossy mapping through an intermediate IR; the output is idiomatic Rust.
- Complete coverage — because the target is code generation rather than runtime inspection, every Bevy type is reachable, including generics, traits, and macros.
Coverage at a Glance
| Metric | Count |
|---|---|
| Source lines | ~32,000 |
| Unique exported symbols | ~556 |
Shadow type wrappers (elicit_newtype!) |
142 |
Method-surface blocks (#[reflect_methods]) |
153 |
| Methods exposed as MCP tools via shadow types | ~640 |
Plugin-level #[elicit_tool] tools |
179 |
| MCP plugins | 10 |
| Stateful workflow plugins | 5 |
| Generator implementations | 3 |
| Bevy subcrates covered | 31 |
Bevy Subcrates Covered
bevy_animation · bevy_anti_alias · bevy_app · bevy_asset · bevy_audio ·
bevy_camera · bevy_color · bevy_core_pipeline · bevy_ecs · bevy_gizmos ·
bevy_image · bevy_input · bevy_input_focus · bevy_light · bevy_math ·
bevy_mesh · bevy_pbr · bevy_picking · bevy_post_process · bevy_reflect ·
bevy_render · bevy_scene · bevy_shader · bevy_sprite · bevy_sprite_render ·
bevy_state · bevy_text · bevy_time · bevy_transform · bevy_ui · bevy_window
Coverage Strategy
Coverage is not achieved through a single mechanism. Bevy's API surface requires five complementary patterns, each chosen for a different kind of type or authoring surface.
1. Shadow Types (elicit_newtype!)
For concrete Bevy structs and enums whose fields are user-authored values — Transform,
Window, StandardMaterial, AmbientLight, Sprite, TextFont, etc. — the primary
pattern is a shadow newtype.
elicit_newtype!;
The macro wraps the upstream type in a local newtype, derives serde::Serialize,
serde::Deserialize, and schemars::JsonSchema (so the AI can construct it), and implements
ToCodeLiteral (so the wrapper can emit source Rust that reconstructs the upstream value
at the call site).
Why a newtype instead of implementing on the upstream type directly?
Rust's orphan rules prohibit implementing schemars::JsonSchema for a type defined in
another crate. The trenchcoat newtype is the standard solution — wrap the type locally,
impl the foreign traits on the wrapper, then convert back via the From impl that the macro
generates for free.
142 newtypes cover the full catalog of user-authored Bevy value types.
2. Method Surface (#[reflect_methods])
A shadow newtype alone only lets an agent construct a value. To also let the agent mutate
it — calling methods like with_translation, with_rotation, looking_at, etc. — each
shadow type carries a #[reflect_methods] impl block.
The #[reflect_methods] macro expands each method into a registered MCP tool named
{module}__{method} (e.g., transform__with_translation). The tool accepts JSON-serialized
parameters, applies the method to the wrapped value, and returns the updated wrapper.
153 reflect_methods blocks expose approximately 640 instance methods as live MCP tools across all shadow types.
3. Unit Markers (unit_elicitation!)
Bevy makes extensive use of zero-field marker components: Camera2d, Camera3d, LightProbe,
MsaaWriteback, Wireframe, etc. These types carry no data — their presence on an entity
is the configuration.
unit_elicitation!;
The unit_elicitation! macro generates an empty shadow struct, derives Elicit, and emits
TypeName (the unit constructor) as the code literal.
4. Shadow Enums (shadow_elicitation!)
Bevy enums with complex variant shapes — particularly those where upstream serde derives
are feature-gated — require their own schema, emitter, and From impl. The
shadow_elicitation! macro handles the boilerplate:
- Derives
serde::Serialize,serde::Deserialize,schemars::JsonSchema - Implements
ElicitCompleteandToCodeLiteralon the shadow enum - Provides a
From<ShadowEnum> for UpstreamEnumconversion
Examples: WindowPosition, VideoModeSelection, MonitorSelection.
5. Generators (Generator Trait)
Some Bevy types are not authored by the user — they are constructed from other artifacts: fonts loaded from disk, texture slices computed from atlas coordinates, etc. These types have no sensible JSON schema because their canonical representation is an external resource reference or a derived computation, not a set of fields.
For these, elicit_bevy provides Generator implementations:
/// Load a font from disk.
The generator struct itself is the elicitable surface. Its ToCodeLiteral impl emits the
correct Bevy asset-loading expression (asset_server.load(path)) rather than trying to
inline the binary font data.
3 generators: FontGenerator, TextureSliceGenerator, and the atmosphere descriptor.
Plugin Architecture
Plugin-level tools handle the parts of Bevy that cannot be reached through value-type construction: ECS wiring, app assembly, codegen macros, and incremental authoring workflows.
Stateless Fragment Plugins
These plugins emit code fragments. Each tool accepts parameters describing what to emit and
returns a String of Rust source code.
| Plugin | Tools | What It Covers |
|---|---|---|
BevyDerivePlugin |
9 | #[derive(Component)], #[derive(Resource)], #[derive(Bundle)], #[derive(Asset)], #[derive(Event)], #[derive(States)], #[derive(SystemSet)], #[derive(ScheduleLabel)], #[derive(Reflect)] |
BevyEcsPlugin |
19 | app.add_systems(), commands.spawn(), commands.insert(), query signatures, system combinator chains, resource initialization, event registration, system sets, run conditions |
BevyQueryPlugin |
9 | Query<D, F>, Res<R>, ResMut<R>, EventReader<E>, EventWriter<E>, Handle<A>, Local<T>, Time<T>, full system signature assembly |
BevyRenderPlugin |
89 | StandardMaterial, all light types, cameras, tonemapping, post-process settings, bloom, SSAO, TAA, atmosphere, volumetric fog, wireframe, mesh materials, color emission |
BevyUiPlugin |
8 | Node, UiRect, GridPlacement, UI text/image components, button scaffolds, flex/grid container emitters |
Stateful Workflow Plugins
These plugins maintain a descriptor store across multiple tool calls. The agent builds up
a descriptor incrementally, then emits the final commands.spawn(...) call when ready.
They implement StatefulPlugin and are backed by Arc<Mutex<Ctx>>.
| Plugin | Tools | What It Covers |
|---|---|---|
BevyAppPlugin |
10 | App assembly: add_plugin, add_systems, insert_resource, add_event, run scaffolding; DefaultPlugins descriptors; full app skeleton emission |
BevyScenePlugin |
5 | Scene manifests: stored entity/component descriptors, RON emission, Commands spawn-code emission for saved scenes |
BevyRenderWorkflowPlugin |
10 | 3D/2D camera descriptors: configure Camera3d, projection, RenderTarget, Tonemapping, MSAA, bloom, depth-of-field; emit spawn tuple |
BevyRenderMeshWorkflowPlugin |
8 | Mesh entity descriptors: configure Mesh3d/Mesh2d, typed material handles, wireframe; emit spawn tuple |
BevyRenderAtmosphereWorkflowPlugin |
12 | Atmosphere + ScatteringMedium descriptors: ordered scattering-term edits, JSON inspection, block-expression emission |
Trait Factories
BevyTraitFactories (trait_factories.rs) provides the marker-trait bridge for user-defined
types. When an agent declares MyComponent as a Bevy Component, it calls:
;
registry..await;
Factories are provided for: Component, Resource, Asset, Bundle, Event, States,
and std::default::Default.
Intentional Exclusions
A small set of Bevy symbols are intentionally not shadowed:
| Excluded | Reason |
|---|---|
App, Plugin, PluginGroup |
Infrastructure types; BevyAppPlugin covers their usage surface via descriptor-registry tools instead |
Schedule labels (Update, Startup, etc.) |
Authoring surface covered by BevyEcsPlugin string-form schedule selectors; adding 40+ unit wrappers would add noise without capability |
Material, MaterialPlugin<M>, MeshMaterial3d<M> |
Generic traits; covered by the factory and workflow plugins that emit correctly-typed code without requiring monomorphization in the shadow layer |
ViewportNode |
Runtime-internal render graph type; not user-authored |
Usage Example
An AI agent that wants to author a Bevy scene with a camera, a directional light, and a textured mesh might proceed as follows:
// Step 1: Build the camera descriptor
bevy_render_workflow__create_camera_3d({})
bevy_render_workflow__set_tonemapping({ "tonemapping": "AcesFitted" })
bevy_render_workflow__set_bloom({ "intensity": 0.15 })
// Step 2: Add a directional light
bevy_render__directional_light({
"illuminance": 10000.0,
"shadows_enabled": true,
"color": "LinearRgba(1.0, 0.98, 0.95, 1.0)"
})
// Step 3: Emit the spawn call
bevy_render_workflow__emit_spawn_code({ "var": "commands" })
// → commands.spawn((Camera3d::default(), ...))
// Step 4: Author the StandardMaterial
bevy_render__standard_material({
"base_color": "LinearRgba(0.8, 0.6, 0.4, 1.0)",
"metallic": 0.0,
"perceptual_roughness": 0.7
})
Shadow type tools operate directly on the wrapper value. Plugin tools emit code strings. Workflow plugins accumulate state and emit the final spawn expression.
Relationship to the Elicitation Framework
elicit_bevy is a shadow crate in the elicitation framework. The layers are:
crates/elicitation— the core framework:Elicitderive,ElicitCompletetrait,ToCodeLiteraltrait,Generatortrait,StatefulPlugintrait,#[reflect_methods]macro,elicit_newtype!macrocrates/elicitation/src/primitives/— primitive Bevy type support (math, color, transform) withbevy-typesfeature gate; these are trenchcoat wrappers for types that lackJsonSchemaunder orphan rulescrates/elicit_bevy(this crate) — the full shadow layer; 31 Bevy subcrates covered, ~32,000 lines, 10 MCP plugins, ~820 total agent-callable tools
See SHADOW_CRATE_MOTIVATION.md and
THIRD_PARTY_SUPPORT_GUIDE.md for the design
rationale behind the shadow crate architecture.
License
Licensed under either of Apache License, Version 2.0 or MIT License at your option.