rxjs-spy-mcp

rxjs-spy-mcp

Enables AI agents to debug RxJS 7 streams in the browser through Chrome DevTools MCP by tagging observables and querying subscription graphs, live values, and buffered logs as structured JSON.

Category
访问服务器

README

rxjs-spy-mcp

Experimental RxJS runtime debugging prototype for Chrome DevTools MCP.

This repository modernizes the idea behind Nicholas Jamieson's rxjs-spy for an AI-assisted debugging workflow: RxJS runtime events are captured into a structured heap registry, exposed through a small debug API, and made readable by Chrome DevTools MCP agents.

Main contributor note

ChatGPT is the main contributor to this project.

The architecture, TypeScript starter implementation, RxJS custom debug operators, MVU demo, time-travel heap registry, and Chrome DevTools MCP bridge were generated and refined with ChatGPT from the user's RxJS debugging requirements.

Project goal

The goal is not to replace rxjs-spy completely yet. This is a first experimental implementation of an MCP-friendly RxJS debugging model.

The current prototype focuses on:

  • typed RxJS debug operators
  • an Elm-like MVU demo
  • time-travel state history
  • passive heap-based inspection
  • safe snapshotting and redaction
  • Chrome DevTools third-party tool discovery
  • AI-readable debug frames

The long-term direction is a modern rxjs-spy-mcp runtime that can inspect:

  • tagged streams
  • notifications: next, error, complete
  • subscriptions and unsubscriptions
  • MVU transitions: Msg -> Model
  • inner subscription behavior from switchMap, mergeMap, concatMap, exhaustMap
  • scheduler-aware timing traces

Mental model

Observable      = static dataflow description
Subscription    = runtime execution
Notification    = runtime event: next | error | complete
Scheduler       = runtime time policy
Heap registry   = durable debug memory
Chrome MCP      = AI-readable inspection bridge

The debugger turns fast asynchronous RxJS events into durable debug frames:

Msg / next / error / complete / unsubscribe
        ↓
spyOnHeap / spyOnMvuLoop
        ↓
window.__RXJS_SPY_MCP__
        ↓
Chrome DevTools MCP / console / debug panel

Installation

npm install

Run the demo

npm run dev

Open the local Vite URL printed in the terminal, usually:

http://127.0.0.1:5173

Sample: using the debug feature manually

  1. Start the app with npm run dev.
  2. Open the browser DevTools console.
  3. The app should already have recorded an initial INIT transition.
  4. Inspect the tracked streams:
window.__RXJS_SPY_MCP__.listStreams()
  1. Inspect the main MVU state stream:
window.__RXJS_SPY_MCP__.inspectStream('main-app-state')
  1. Read only the timeline frames:
window.__RXJS_SPY_MCP__.getTimeline('main-app-state', 10)
  1. Read the compact runtime story:
window.__RXJS_SPY_MCP__.story('main-app-state', 20)

As a table:

console.table(window.__RXJS_SPY_MCP__.story('main-app-state', 20))

The story output turns raw debug frames into rows like:

INIT -> query="", active="", loading=false, results=0
SET_QUERY -> query="rxjs", active="", loading=false, results=0
START_SEARCH -> query="rxjs", active="rxjs", loading=true, results=0
SEARCH_SUCCESS -> query="rxjs", active="rxjs", loading=false, results=3
  1. Type a search query, for example rxjs, and press Search.
  2. Simulate a failing async effect by typing:
error

Then press Search.

  1. Inspect the story again:
console.table(window.__RXJS_SPY_MCP__.story('main-app-state', 20))

You should see a sequence similar to:

INIT
SET_QUERY
START_SEARCH
SEARCH_FAILURE

Each mvu-transition frame stores:

{
  action: Msg,
  resultingState: Model
}

This gives a readable runtime story:

The user changed the query.
A search request started.
The async effect failed.
The model moved into an error state.
The view rendered the error.

If getTimeline('main-app-state', 20) returns []

Run this first:

window.__RXJS_SPY_MCP__.diagnose()

Then run:

window.__RXJS_SPY_MCP__.listStreams()

Expected after a fresh page load:

streamCount >= 1
streamTags includes "main-app-state"
mainStateHistorySize >= 1

Also check that you use the exact global name with two underscores before and after RXJS_SPY_MCP:

window.__RXJS_SPY_MCP__

not:

window._RXJS_SPY_MCP_

If the timeline is still empty:

git pull
npm install
npm run dev

Then hard-refresh the browser tab and run:

window.__RXJS_SPY_MCP__.diagnose()
window.__RXJS_SPY_MCP__.getTimeline('main-app-state', 20)

The current implementation uses a seeded BehaviorSubject<Msg> for the MVU message source, so an INIT transition should be recorded immediately when runtime.appState$ is subscribed in main.ts.

Sample: visual time-travel

The debug panel on the right shows the heap timeline.

Click any frame to visually rewind the UI to the resultingState stored in that frame.

You can also jump from the DevTools console:

window.jumpToStep(2)

Important: this is currently visual rewind, not full replay-based state restoration. The internal scan accumulator is not rewound. A future version can add true event replay.

Sample: using the custom operators

Generic stream inspection

import { interval, map, take } from 'rxjs';
import { spyOnHeap } from './debug/operators';

const counter$ = interval(1000).pipe(
  take(5),
  map(n => ({ count: n })),
  spyOnHeap('counter-stream', { maxFrames: 10 })
);

counter$.subscribe();

Then inspect it in the console:

window.__RXJS_SPY_MCP__.inspectStream('counter-stream')

MVU transition inspection

const msg$ = new BehaviorSubject<Msg>({ type: 'INIT' });

const transition$ = msg$.pipe(
  scan(
    (acc, msg) => ({ msg, model: update(acc.model, msg) }),
    { msg: { type: 'INIT' }, model: initialModel }
  ),
  spyOnMvuLoop('main-app-state', { maxFrames: 80 })
);

This is the key teaching/debugging use case:

Msg flows in over time.
update calculates the next Model.
spyOnMvuLoop stores Msg + Model as a debug frame.

Sample: Chrome DevTools MCP workflow

This project registers a Chrome DevTools third-party developer tools bridge through the page-level devtoolstooldiscovery event.

When Chrome DevTools MCP is connected with the experimental third-party tools category enabled, an AI agent can discover tools such as:

rxjs_list_streams
rxjs_inspect_stream
rxjs_get_timeline
rxjs_story

A typical AI-agent prompt:

Inspect the active browser tab with Chrome DevTools MCP. Use the rxjs-spy-mcp tools to list RxJS streams, read the main-app-state story, and explain why the latest search failed.

Expected agent behavior:

1. list_3p_developer_tools
2. execute_3p_developer_tool: rxjs_list_streams
3. execute_3p_developer_tool: rxjs_story { tag: 'main-app-state', limit: 20 }
4. Explain the Msg -> Model transition that caused the bad state.

A fallback MCP approach is script evaluation:

() => globalThis.__RXJS_SPY_MCP__.story('main-app-state', 20)

Corrections applied to the original prototype

Dimension Correction applied
Concept Reframed MCP as an inspection bridge, not a replacement for RxJS runtime instrumentation.
MVU time-travel teaching value Added explicit Msg -> Model transition tracking and a visual timeline panel.
TypeScript correctness Split app and debug types, fixed invalid imports, removed any-based INITIALIZE, added strict typed operators.
Chrome MCP API correctness Replaced the invented navigator.developerTools.registerTool idea with a devtoolstooldiscovery bridge for Chrome DevTools third-party tools.
rxjs-spy replacement completeness Added a foundation for tagged streams, notification frames, subscription IDs, teardown tracking, and stream summaries. Still not a full rxjs-spy replacement.
AI-agent usability Added JSON-friendly diagnose, listStreams, inspectStream, getTimeline, and story methods.
Production safety Dev-only installation, redaction for secret-like keys, safe snapshot serialization, circular-value tolerance, and size-limited snapshots.

Current limitations

This is an experimental prototype. It does not yet implement full rxjs-spy behavior.

Missing or future work:

  • monkey-patch-free tagging API comparable to rxjs-spy tags
  • global Observable subscription graph
  • parent/child subscription graph
  • higher-order operator visualization
  • dedicated debug operators for switchMap, mergeMap, concatMap, exhaustMap
  • scheduler-aware traces for asyncScheduler, animationFrameScheduler, virtual time, and drift
  • true replay-based time travel
  • tests
  • package publishing

Safety notes

The debug registry exposes runtime state on window.__RXJS_SPY_MCP__ in development mode. Do not expose sensitive production data through debug streams.

The snapshot layer redacts common secret-like keys and limits serialized payload size, but this is not a complete security boundary.

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选