deeleeramone/pywry/events
Claude Code and agent skill by deeleeramone/pywry
- community
Checking that the SKILL.md file is still in the repository.
The PyWry event system — namespaced events, request/response round-trips, widget IDs, component IDs, and how tool results flow back to the agent.
Install
npx vskill@latest install deeleeramone/pywry/eventsSKILL.md
PyWry Event System — Agent Reference
The event bus is the plumbing underneath every MCP tool. Yourarely need to think about it — the typed tools wrap emit + wait +state-poll for you — but when you reach forsend_eventorinterpret tool results, this is how it works.
Event names are namespaced
Every event has the form namespace:event-name, e.g.:
tvchart:symbol-search— ask the chart to open symbol searchtvchart:state-response— chart's reply with its current statetvchart:data-request— chart asks Python for barstvchart:data-response— Python delivers barstoolbar:request-state— ask a toolbar component for its valuetoolbar:state-response— component's replychat:user-message— user typed somethingchat:ai-response— model produced a tokenpywry:update-theme— dark/light mode change
Never emit an event with a name that doesn't match namespace:event-name — the framework rejects it.
Widget IDs vs component IDs
widget_id — identifies the top-level PyWry widget (a chart, a grid, a chat panel, a dashboard). Every MCP tool takes widget_id as an argument because all events route to the widget first.
componentId — identifies a child inside a widget (a specific toolbar button, a marquee ticker slot, a chart pane). Component IDs are scoped to their containing widget.
When you call send_event(widget_id, event_type, data), the widget_id picks the target widget; anything identifying a specific component goes in the data payload (typically as data.componentId or data.chartId).
Request / response pattern
Some events are fire-and-forget (e.g. tvchart:symbol-search — "please do this"). Others are request/response round-trips where the caller wants a reply (e.g. tvchart:request-state → tvchart:state-response).
The framework correlates request/response with a context token:
- Emitter generates a random
contexttoken. - Emitter injects it into the request payload.
- Listener sees the request, attaches the same
contextto its
response, and emits the response event.
- Emitter sees the matching
contexton the response and wakes up.
All of this is handled inside request_response() in pywry.mcp.state — you never construct tokens yourself. Typed MCP tools that need a reply (tvchart_request_state, tvchart_list_indicators) use this under the hood and return the stripped response (no context token) in their tool result.
How tool results reach the agent
Mutating tools (tvchart_symbol_search, tvchart_change_interval) poll tvchart:request-state after emitting the mutation, wait for the chart to actually reflect the change, and return the real post-change state in the tool result. The state field in the tool result contains the SAME structure as a direct call to tvchart_request_state.
If the mutation didn't settle in time, the result contains a note field explaining the discrepancy — relay the note to the user, do not invent state.
Emitting events from tools — send_event
Only reach for send_event when no typed MCP tool exists for the target event. It's a raw passthrough with no state polling:
Example — apply a rare tvchart option with no typed wrapper:
The returned event_sent: true means the event was successfully handed to the widget — it does NOT mean the JS handler ran successfully. For confirmation, follow up with tvchart_request_state to read the new state.
Event capture (get_events)
Some events fire from the widget to Python (e.g. the user clicked a bar, moved the crosshair). These are automatically captured into a per-widget event buffer and can be retrieved with:
Default captured events for charts:
tvchart:clicktvchart:crosshair-movetvchart:visible-range-changetvchart:drawing-addedtvchart:drawing-deletedtvchart:open-layout-requesttvchart:interval-changetvchart:chart-type-change
Use get_events if the user asks "what did I just click" or "what was the last drawing I added".
Don'ts
- Do NOT synthesise event payloads. Only report event data the
framework actually handed you.
- Do NOT emit events whose name doesn't match
ns:name— they're
rejected.
- Do NOT emit to a widget id that isn't registered — the tool will
return an error listing the registered widgets; correct and retry.
- Do NOT assume
event_sent: truemeans the downstream JS succeeded.
When it matters, follow up with tvchart_request_state (or the relevant state query) to confirm.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingpywry/pywry/mcp/skills/events/SKILL.md
Popularity
- Repository stars
- 89
- Repository forks
- 7
- 7-day trend score
- 22
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/deeleeramone/pywry/events)