Connect a coding agent
Give a coding agent the same component tree and timeline the panel shows, so it reads the running app instead of guessing from source. One MCP entry covers every dev server on your machine.
Add the server
Section titled “Add the server”claude mcp add lit-devtools -- npx -y @oddsquad/vite-plugin-lit mcpThe equivalent claude_desktop_config.json or mcp.json entry:
{ "mcpServers": { "lit-devtools": { "command": "npx", "args": ["-y", "@oddsquad/vite-plugin-lit", "mcp"] } }}The command needs two optional peers, cac and @devframes/agentic. See the
CLI reference for the message it prints when
one is missing.
The eleven tools
Section titled “The eleven tools”| Tool | Answers |
|---|---|
lit_get-meta |
Plugin version, available timeline layers, resolved settings. |
lit_list-components |
The live element tree, read from the page on each call, with each component’s source file and line. A tag no custom element defines appears with notDefined: true, and a custom element another library defines with notLit: true. Bound it with maxDepth. |
lit_component-details |
Reactive properties, attributes, update flags and Lit dev-mode warnings for one element id, or for every element of a tag name, read from the page on each call. |
lit_component-docs |
The documented API of a tag (descriptions, events, slots, CSS parts and custom properties), from your components’ JSDoc or the Custom Elements Manifests your dependencies ship. |
lit_update-summary |
Which components updated, how often, how long for, and what changed. |
lit_recent-events |
Recent lifecycle, Lit warning, render and input events, filterable by tag name, element or layer. |
lit_range-summary |
What happened between two instants: spans per layer and which components updated, for a start and end taken from lit_recent-events times. |
lit_hmr-history |
Recent hot patches that landed (instances, duration, child-state mode) and ones that could not, oldest first, up to 50 of each. |
lit_hmr-incompatibilities |
Components the plugin could not hot-patch in place, and why. |
lit_set-recording |
Starts or stops timeline recording. |
lit_set-prop |
Sets a reactive property, or one field inside the object it holds, on a live element, and answers with its details after the write. |
Nine of the eleven only read. lit_set-recording exists because
lit_recent-events is a dead end while recording is off, and an agent that can
read the timeline but not start it just hands the question back to you.
Recording is a shared toggle, so an agent turning it on also changes what you
see in an open panel.
lit_set-prop lets an agent try a value and watch how a component reacts,
without asking you to type it into the panel. It writes the same way the
panel’s property editor does: only a property or field the details mark
editable, only with a string, number or boolean of that type, and kept as an
override on top of what your app sets. So an agent’s edit shows up in the
panel’s overrides bar, where you can switch it off or clear it, and a reload
drops it. It does change the page you are looking at, so the tool tells the
agent to say what it set. The layer toggles and the element picker stay
panel-only.
All eleven answer only while a dev server with DevTools is running. Nothing is stored, so with the server down an agent gets a connection error rather than an empty answer.
Ask a good question
Section titled “Ask a good question”Point the agent at lit_update-summary first for anything shaped like “why did
this re-render”. It returns the same derived cycles and per-component totals the
Updates tab shows, so the agent
never pairs thousands of start and end events itself.
lit_range-summary takes a start and an end in milliseconds, on the same
clock as the time of each event lit_recent-events returns, so an agent can
bracket a click and the update it caused with times it already saw. It does not
read the range you selected in the panel, because that selection lives in the
browser; a link or a pasted range has to carry the numbers.
Prompts that work:
- “Record ten seconds of the running app while I click the filter bar, then tell me which component updated most and which properties caused it.”
- “I just edited
src/todo-item.ts. Did the change land in the running page without a reload? Checklit_hmr-history.” - “The page reloads whenever I edit
src/app-shell.ts. Checklit_hmr-incompatibilitiesand tell me which shape is to blame.” - “Set
filteron thetodo-listtodoneand tell me whether the empty state shows when nothing is done.”
Discovery or a fixed URL
Section titled “Discovery or a fixed URL”vite-plugin-lit mcp runs devframe’s own connector over stdio. The plugin
publishes each running dev server to devframe’s instance registry, and the
connector lists them through two gateway tools,
devframe_connect_list-instances and devframe_connect_call-tool. One entry
therefore covers every project you have running. Being a shared connector, it
also surfaces every other devframe on the machine.
When registry discovery is unavailable the plugin warns once at startup, naming the reason:
[lit-plugin] devframe instance-registry discovery unavailable (no HTTP server (middleware mode?)); stdio MCP clients cannot auto-discover this dev server. The MCP endpoint itself is unaffected — point clients at <dev-server-origin>/__devtools/__mcp directly.Vite DevTools mounts the endpoint at /__devtools/__mcp on the dev server;
without Vite DevTools
the panel’s own mount serves it at /__lit/__mcp. Bridge that URL instead and
skip discovery altogether:
claude mcp add lit-devtools -- npx -y mcp-remote http://localhost:5179/__devtools/__mcp