riverpod_devtools 1.1.2 copy "riverpod_devtools: ^1.1.2" to clipboard
riverpod_devtools: ^1.1.2 copied to clipboard

DevTools extension for Riverpod - inspect providers in real-time, now with MCP support for AI coding tools.

1.1.2 #

  • Perf: dart run riverpod_devtools:analyze is dramatically faster on large projects. The CLI resolved every file semantically (AnalysisContextCollection + getResolvedUnit), which re-resolves each file's transitive imports — near "files × whole program" work, taking minutes on provider-heavy apps. But the extraction is purely syntactic (provider patterns, ref.watch/read/listen by name, @riverpod by annotation name) and never used the resolution, so the analyzer now does a plain syntax-only parse per file (parseFile). Cost is proportional to source size only — typically minutes → well under a second — and the generated riverpod_dependencies.json is identical. --watch re-analysis gets the same speedup. A file that fails to read/parse now skips only itself (matching the previous per-file behavior), and the pipeline no longer needs a resolvable SDK, which also made analyze() end-to-end testable.
  • Fix: dart run riverpod_devtools:analyze no longer fails to compile on analyzer 14+. ArgumentList.arguments's element type changed from NodeList<Expression> to NodeList<Argument> (a new sealed interface implemented by both Expression and the new NamedArgument; the old NamedExpression was removed) — a genuine breaking type change that can't be bridged with a single static type, since Argument/NamedArgument don't exist pre-14 and NamedExpression doesn't exist on 14+. The ref.watch/read/listen argument extractor now resolves the argument's expression dynamically instead of relying on either shape, restoring compatibility across the package's full declared analyzer: >=6.0.0 <15.0.0 range instead of breaking on whichever version pub get resolves.

1.1.1 #

  • Fix: non-finite numbers no longer crash the observer. A provider value containing double.infinity, double.negativeInfinity, or double.nan could throw an uncaught Converting object to an encodable object failed: Infinity from developer.postEvent, because those are valid nums that Dart's json.encode (with no toEncodable fallback) rejects. Both routes that let a non-finite number reach the payload are now sealed: the toJson() sanitizer (_jsonSafe) rewrites non-finite doubles to their string form ("Infinity"/"-Infinity"/"NaN"), and the toString() parser no longer turns num.tryParse('Infinity') into a live non-finite double (it keeps the original string). Finite numbers are unaffected.
  • Fix: dart run riverpod_devtools:analyze now detects @riverpod code-generated providers. The analyzer previously only recognized hand-written final xProvider = SomeProvider(...) top-level declarations. Apps using riverpod_generator (@riverpod functions/classes) got zero matching static metadata for those providers — even though riverpod_dependencies.json loaded successfully, every runtime event for them reported dependenciesSource: 'name_mismatch', since the generated provider variable (in the excluded .g.dart file) never appeared in the analyzer's output. @riverpod/@Riverpod(...)-annotated functions and classes are now recognized in the source file, and named using riverpod_generator's own convention (<lowerCamelCase(name)>Provider), so their static dependencies attach correctly at runtime.
  • Docs: MCP setup for monorepo / subdirectory / FVM Flutter apps. MCP.md now documents the shell-wrapper .mcp.json config needed when the Flutter package (the one depending on riverpod_devtools) lives below the directory .mcp.json is read from — a common monorepo layout — including an FVM example (fvm dart run ...).
  • Docs: MCP connection diagnostics. TROUBLESHOOTING.md's MCP Issues section now leads with a quick diagnostic checklist (debug mode, observer registered, curl .../ping health check with the expected response shape, running from the right package directory, MCP client restarted after .mcp.json changes) so a broken setup can be isolated to app-side vs. MCP-client-side without guesswork. MCP.md now calls out that most MCP clients only read .mcp.json at startup, so tools added mid-session need a client restart/reload.

1.1.0 #

Reliability and lightness release: bounded serialization cost for large state, faster MCP tool calls, a snappier extension under event bursts, and setup failures that explain themselves instead of degrading silently.

  • Serialization is now bounded at the source. serializeValue previously capped only recursion depth; a provider holding a huge List/Map/Set (or an object with a very long toString()) was fully re-serialized on every update, on both the DevTools and MCP paths. Collections now serialize only their first 100 elements — flagged with truncated: true and the true totalItems — and the stored string form is capped at 4000 chars. Anything trimmed carries the existing lossy: true marker, and MCP compact summaries report the true (pre-cap) collection size. Large-state apps can keep the observer enabled without paying an unbounded per-event cost.
  • Dependency-JSON load failures are now visible everywhere. A broken riverpod_dependencies.json used to degrade silently to "no dependencies":
    • The registry retains the parse error (RiverpodDevToolsRegistry.loadError).
    • get_dependency_graph returns a dedicated edgesNote with the actual parse error (distinct from "never loaded" and "name mismatch").
    • Events carry dependenciesSource: 'load_error' plus the reason (dependenciesLoadError), and the DevTools extension's Dependencies section shows a "Dependency Data Failed to Load" panel with the error and the fix command — instead of the generic setup instructions.
    • The README / doc-comment setup snippet now logs the load failure reason instead of recommending an empty catch (_) {}.
  • MCP: app discovery is cached (~5s). Tool calls that omit port no longer re-ping all 10 ports (1s timeout each) on every call; a failed request to a cached port invalidates the cache so a restarted app on a new port is re-discovered automatically. One HttpClient is used per scan instead of one per port. list_riverpod_apps always scans fresh.
  • MCP: get_dependency_graph explains an empty edges — when no static dependency data is loaded (or none of the running providers match it by name), the response carries an edgesNote describing why edges is empty and how to fix it, instead of being indistinguishable from "no dependencies". The note survives the compact view.
  • MCP: the server reports its real version in the initialize handshake (was hardcoded to 0.1.0); tool/release.sh keeps it in sync.
  • Extension: smoother under event bursts. The event list is rebuilt in a single pass per event (previously a full copy plus a head insert), and the per-provider stats recompute is throttled to at most once per 250ms with a trailing pass so the final state after a burst is never stale.
  • Reliability fixes:
    • The ext.riverpod_devtools.command service extension is only marked registered after registration actually succeeds, so a transient failure no longer permanently disables DevTools Invalidate/Refresh for the rest of the isolate's life.
    • The POST /commands invalid-body error message no longer contains a truncated placeholder ("value"?: }"value"?: <primitive>}), so an AI reading it can self-correct against valid JSON.
  • Examples build from a fresh clone — the generated riverpod_dependencies.json is now committed for both example apps, so flutter run works immediately and the dependency-graph demo is live out of the box.
  • Docs: TROUBLESHOOTING.md gained an MCP section covering the real failure modes (app not found / port forwarding, first-launch compile timeout, empty graph edges, ambiguous: true, supported: false, multi-app port selection); MCP.md links to it and notes the one-time ~10–20s first-launch compile of the MCP server.

1.0.0 #

First stable release. This milestone makes the bundled MCP server a first-class, token-efficient interface for AI coding tools — reading live provider state and driving it — and rounds out the DevTools extension with an interactive dependency graph and a per-provider performance/health dashboard. The public API (RiverpodDevToolsObserver, the analyzer CLI, the MCP server) is now considered stable and follows semantic versioning.

  • Added the set_provider_value MCP tool: set a provider's state to a specific primitive value (int/double/bool/String/null) for providers with a writable notifier (StateProvider, NotifierProvider). Unsupported providers are rejected with supported: false.

  • MCP: flag lossy/approximate serialized values: cyclic references and values truncated by the depth limit now carry lossy: true in both the raw and compact serialized forms, so an AI reading the value can tell it's a placeholder rather than an accurate reading.

  • MCP: token-efficient responses:

    • get_riverpod_logs and get_provider_state now return a compact representation by default — slim events/entries with summarized values, dropping the repeated static-dependency metadata, providerId, and the verbose nested {type, string, items/entries} value trees that the GUI needs but an AI does not. In a realistic case the compact log payload is about a quarter the size of the raw one, so far more history fits in an AI's context per call.
    • New view parameter: get_riverpod_logs accepts compact (default), summary (per-provider counts by kind plus each provider's latest value — "what happened" without the full stream), and full (the complete raw events, for when you need a value the compact form summarized). get_provider_state accepts compact (default) and full.
    • get_dependency_graph and get_provider_stats are compact by default too: the graph returns just the topology (dropping per-edge file/line/column and node bookkeeping — view: "full" restores them), and stats drop the 30-bucket sparkline array and near-zero fields, ordered most-interesting-first (flagged providers, then by update rate) so "which provider is misbehaving?" is answered from the top (view: "full" returns the raw stats).
    • get_riverpod_logs gained since/until parameters (a timestamp window in epoch ms), so an AI can pull just a recent slice of the event history without clearing the buffer. The GET /logs endpoint accepts the same query parameters.
    • Tightened every tool/parameter description. Tool descriptions are sent to the AI on every session, so this is a fixed per-session saving — the total dropped by ~50% (~1,735 → ~860 tokens) with the shared context (compact-by-default, debug mode, auto port) moved into the server instructions instead of repeated on each tool.
  • MCP: robust provider identity:

    • Every provider now gets a stable, session-unique instanceId, and each event / state snapshot carries it plus a nameIsUnique flag. Previously providers were tracked purely by display name, so two unnamed providers of the same type (both Provider<int>) or two providers sharing an explicit name: collided: one silently overwrote the other in the state snapshot and the command target map, so get_provider_state hid one of them and invalidate_provider could hit the wrong one. Distinct providers are now kept distinct and individually addressable.
    • invalidate_provider (and the POST /commands endpoint / DevTools command extension) accept either a provider name or an exact instanceId. When a name is shared by more than one provider the command is rejected with ambiguous: true and the list of candidate instanceIds, instead of silently acting on an arbitrary one. A successful command echoes back the resolved provider name and instanceId.
    • GET /providers keeps a separate entry per instance for same-named providers and can be filtered by instanceId as well as by name; the dependency-graph runtime status merges same-named instances with "active" winning over "failed".
  • Fixes:

    • Value serialization no longer misreports a genuinely non-cyclic value as a <Cyclic Reference>. The recursion-depth guard ran after a value was added to the cycle-detection set but returned without removing it, so an object first reached past the depth limit stayed marked as "seen" and a later, shallower occurrence of the same object was wrongly flagged as a cycle. The depth check now runs before cycle tracking.
  • Invalidate / Refresh reliability:

    • Fixed a spurious Provider "…" is not alive error when invalidating or refreshing the same provider a second time. Invalidate/refresh disposes the provider, and its rebuild is not always reported back before the next command, so tracking "what is live right now" made the second command think the still-in-use provider was gone. Commands now target the stable provider definition (kept across dispose, bounded to avoid unbounded growth), so a provider can be invalidated/refreshed repeatedly. invalidate_provider (MCP) gains the same robustness — a provider that has been observed stays targetable, and refresh recreates it even if it was since disposed.
    • Provider Details: a fast double-click no longer fires a second command while the first is still in flight (an in-flight guard, not just the disabled button state, now blocks it), and the command result — success or a long error — is shown on its own full-width line below the buttons (icon + up to two lines, full text on hover) instead of being clipped to an unreadable sliver. Switching to another provider clears the previous provider's result label.
    • Unified selection across the Inspector, Graph, and Stats views: the graph now derives its focus from the shared selection instead of a separate focus field, so selecting provider(s) in one view carries over to the others (including multi-selections). Ctrl/Cmd+Click multi-selects in the graph just like the provider list; a plain click still selects only that node (and re-clicking it deselects). Selecting a row in the Stats view jumps to the Inspector with just that provider selected, replacing any prior multi-selection.
    • The dependency-graph legend moved to the bottom-right corner so it no longer overlaps the provider nodes, which are laid out from the left edge.
    • Dependency graph: clicking the already-selected node now deselects it (clears selection and focus), matching the provider list where re-clicking the selected provider deselects it. Previously a re-click was a no-op.
    • Provider list clicks are reliable again: tiles now use a real tap gesture instead of a raw pointer listener, so the surrounding "tap empty area to deselect" handler no longer fires on every tile click. Previously a selection only survived if the click was released fast enough — slow clicks were silently undone.
    • Clearing the selection (empty-area tap or the Clear button) is now a single atomic state change instead of one rebuild per selected provider.
    • The dependency graph toolbar has a fixed height, so the "Show all" button appearing/disappearing no longer resizes the toolbar and shifts the canvas.
    • Panel-header action buttons ("Clear", "Show all") now sit flush against the panel's right edge — a Flexible title competing with a Spacer used to leave a dead gap after the actions at wide layouts.
    • The Provider Details status row (badge + Invalidate/Refresh) scales down gracefully at narrow panel widths instead of overflowing.
  • Infrastructure & UX (#57):

    • MCP port auto-discovery: the in-app HTTP server now binds the first free port in 87888797 instead of failing when 8788 is taken, so two debug apps can run at once. The MCP server discovers running apps by probing the range; a new list_riverpod_apps tool reports each app's port / provider count / event count, and every tool accepts an optional port to target a specific app (auto-selected when only one is running).
  • Performance diagnostics: update frequency, async load duration, churn (#56):

    • New "Stats" tab in the DevTools extension: a per-provider dashboard of update rate (with a 30s sparkline of recent update activity), total updates (with a comparative bar), async load duration (min/avg/max of observed loadingdata/error transitions), and dispose→re-create churn count, aggregated from the event log. Rows that exceed a threshold are highlighted and sorted to the top by default (with a "needs attention" count in the header); a legend explains the thresholds. Click a column header to re-sort; click a row to jump to that provider in the Inspector view.
    • Providers exceeding a threshold (>10 updates/sec sustained, or a load over 2s) get a warning badge in the provider list too.
    • New get_provider_stats MCP tool (and GET /stats on the local HTTP endpoint) returning the same aggregation — including per-provider updateBuckets (30s update histogram) — so AI tools can be asked "which provider is rebuilding excessively?" without pulling and analyzing the full event log.
  • Interactive dependency graph view (#55):

    • New Inspector / Graph view switcher in the DevTools extension. The Graph view renders providers as a layered DAG (dependencies left, dependents right) with pan/zoom, edge styling per dependency kind (watch solid, read dashed, listen dotted), status coloring (active / disposed / failed with error badge), and dependency-cycle highlighting.
    • Clicking a node selects it (Provider Details shown alongside, including Invalidate/Refresh) and focuses the graph on its transitive dependencies and dependents in one gesture; "Show all" returns to the full graph. The provider search query dims non-matching nodes, and an on-screen legend explains the edge styles, node states, and gestures.
    • The observer now attaches dependencyDetails (kind + source location per dependency, from the static-analysis registry) to provider_added events so the extension can style edges.
  • State operations: invalidate / refresh from DevTools and MCP (#54):

    • The observer now tracks live provider instances (with their owning container) and can execute invalidate / refresh commands against them. Debug mode only.
    • New ext.riverpod_devtools.command service extension so the DevTools extension can run commands on any platform; the DevTools Provider Details panel gains Invalidate and Refresh buttons (disabled for disposed providers, with inline success/error feedback).
    • New invalidate_provider MCP tool (and POST /commands on the local HTTP endpoint) so AI tools can reproduce flows end-to-end: clear logs → invalidate → read logs. The tool description flags it as a state-mutating action.
  • MCP tool expansion (#53):

    • New get_provider_state MCP tool (and GET /providers on the local HTTP endpoint): a current-state snapshot of live providers — name, status (active/failed), latest value, error details when failed, and last-update timestamp — so AI tools no longer need to replay the event log to answer "what is the current state". Disposed providers are evicted from the snapshot; clear_riverpod_logs does not affect it.
    • New get_dependency_graph MCP tool (and GET /graph): nodes with runtime status merged in, plus directed dependency edges (watch/read/listen, with source locations) from the static-analysis registry. An optional provider parameter returns only that provider's transitive dependencies and dependents.
  • First-class error capture (#52):

    • The observer now implements providerDidFail (Riverpod 2.x and 3.x signatures) and emits a provider_failed event carrying the error's runtime type, message (capped at 2000 chars), and a trimmed stack trace (Riverpod-internal frames dropped, max 20 frames).
    • DevTools extension: failed events appear in the Event Log with a red FAILED badge and expandable error details; providers currently in a failed state show an error badge in the provider list and a dedicated "Error" section (message + collapsible stack trace + copy button) in Provider Details. The error clears when the provider next updates successfully.
    • MCP / HTTP endpoint: get_riverpod_logs and GET /logs accept a new type filter (e.g. provider_failed to fetch only errors).
  • Causality chain (why did this provider rebuild?) (#51):

    • Every observer event now carries a monotonic seq number for unambiguous ordering (timestamps collide within a millisecond).
    • provider_updated events now carry triggeredBy — the dependency update(s) that likely caused the recomputation, inferred from the static dependency graph plus temporal proximity and marked triggerConfidence: "inferred".
    • DevTools extension: update cascades are rendered as indented chains in the Event Log, with a clickable "caused by X" chip that selects and flashes the triggering provider; the Provider Details "Last Update" section also shows the trigger.
    • MCP: the new fields flow through get_riverpod_logs automatically, so AI tools can trace update cascades.
  • MCP:

    • get_riverpod_logs now accepts optional limit (most recent N events) and provider (exact provider name) parameters, so AI tools can fetch only the relevant slice of the buffer instead of up to 1000 full events. The local HTTP endpoint (GET /logs) accepts the same values as query parameters.
  • Performance:

    • RiverpodDevToolsObserver is now near-zero overhead when nothing can consume its events (release/profile builds without a DevTools client attached): value serialization is skipped entirely instead of running on every provider change.
    • Value serialization uses identity-based cycle detection, avoiding deep user-defined ==/hashCode calls (e.g. freezed models with large collections) on every event, and no longer builds an object's toString() when it serializes via toJson().
    • The Riverpod 2.x/3.x API probe in the observer is cached, so it no longer throws and catches a NoSuchMethodError on every event on Riverpod 2.x.
    • The MCP event buffer is now a ring buffer with O(1) eviction (previously each event shifted the whole 1000-entry list once full).
    • Static dependency names are cached per provider in the registry instead of being rebuilt from metadata on every provider event.
    • DevTools extension: the filtered provider/event lists are memoized per state change instead of being re-filtered and re-sorted on every widget rebuild, and appending an event no longer copies the event list twice.
    • DevTools extension: "Used By" is now answered from a reverse-dependency index rebuilt only when the provider map changes (previously a full providers × dependencies scan on every detail-panel rebuild), the "Last Update" section reads the provider's latest event in O(1) instead of filtering the whole event log, and event de-duplication no longer schedules a Timer per incoming event.
  • Fixes:

    • AsyncValue states (data/loading/error) are shown again in the extension UI — the asyncState marker was unreachable in serialization because the structured toString() parser returned first.
    • DevTools extension: the Event Log "Clear All" button now actually clears the log (it was a no-op).
    • DevTools extension: providers that are disposed and later re-created are no longer evicted from the provider list by the disposed-provider cleanup.
    • DevTools extension: event IDs are now unique even when a provider emits multiple events within the same millisecond, preventing duplicate-key errors in the event list.
  • Dev:

    • Widened the extension package's vm_service constraint to >=14.0.0 <16.0.0 so it resolves with Flutter >=3.32 (which pins vm_service 15.0.0).

0.6.2 #

  • Docs:
    • Highlighted MCP support in the README (badge, tagline, Features list, dedicated section) and pub.dev metadata (description, topics) — no code changes.

0.6.1 #

  • Dependencies:
    • Widened the analyzer constraint from ^6.0.0 to >=6.0.0 <15.0.0 to cover the current latest analyzer release and improve the pub.dev "supports latest dependencies" score.
  • Example:
    • Replaced StateProvider with NotifierProvider/Notifier in the bundled example so it keeps compiling across the full supported flutter_riverpod range (2.3.04.0.0), including when resolved to Riverpod 3.x.

0.6.0 #

  • MCP Integration:
    • Added a bundled MCP server (dart run riverpod_devtools:riverpod_devtools_mcp) so AI tools like Claude Code can read live Riverpod provider event logs from a running app. See MCP.md.
    • RiverpodDevToolsObserver now starts a local, debug-only HTTP server (localhost:8788) that the MCP server reads from.
    • HTTP server start failures are now logged via dart:developer instead of being silently swallowed.
  • Breaking:
    • Raised minimum SDKs to Dart ^3.7.0 and Flutter >=3.32.0 to accommodate the MCP server's dart_mcp dependency. Stay on riverpod_devtools: ^0.5.0 if you can't upgrade yet.

0.5.0 #

  • Static Dependency Analysis (CLI):
    • Added dart run riverpod_devtools:analyze to generate lib/riverpod_dependencies.json.
    • Added AST-based provider dependency extraction (watch/read/listen) with source locations.
    • Added RiverpodDevToolsRegistry for loading static metadata in your app.
    • Breaking: Removed runtime-based dependency detection; dependencies now come from static analysis only.
  • DevTools UI:
    • Updated Provider Details for the static-analysis workflow (setup instructions, provider name mismatch handling).
    • Redesigned caution messages as collapsible dropdowns.
    • Added selectable text and copy buttons in the extension UI.
    • Refactored the extension codebase into modular files for maintainability.
  • Stability:
    • Improved serialization error handling and recursion safety.
    • Fixed provider type detection order in the CLI analyzer.
    • Internal refactor: ListUtils, deduplicated observer event payload building.
  • Documentation & pub.dev:
    • Added TROUBLESHOOTING guide and updated README for CLI setup.
    • Added pubspec metadata (platforms, topics, homepage, screenshots).
  • Example:
    • Updated example apps for CLI-based static analysis.
    • Removed debug print statements on JSON load failure.

0.4.4 #

  • Improved Data Serialization:
    • Significantly improved serialization for custom classes by parsing structured toString() output.
    • Fixed issues where collection string representations were misinterpreted as custom classes.
    • Enhanced recursive item serialization for Lists, Maps, and Sets.
  • Tree View & Event Log UI:
    • Added support for the entity metadata key in the JSON tree view, allowing for better representation of complex objects.
    • Improved value formatting in the Event Log.
  • Stability:
    • Refined internal parsing logic to avoid misidentification of data types.

0.4.3 #

  • UI Improvements (Provider Details):
    • Improved dependency chip layout for better readability.
  • Tree View Refinements:
    • JSON Tree View now collapses by default to reduce noise.
    • Refined JSON object unwrapping to prioritize meaningful data (prioritize entries over string representation).
    • Filtered out internal metadata keys from the tree view display.
  • Event Log Enhancements:
    • Added support for collapsible long strings in the Event Log.
    • Improved overall readability of event details.
  • Stability & Performance:
    • Fixed memory leaks by ensuring disposed providers and empty event lists are properly cleaned up.

0.4.2 #

  • Fixed missing DevTools extension build files (index.html and other assets) that prevented the extension from loading properly

0.4.1 #

  • Fixed devtools config.yaml version mismatch (was 0.3.0, now matches package version 0.4.1)

0.4.0 #

  • Added Learning-based Dependency Tracking to support dependency visualization in Riverpod 3.x
  • Support for Light Mode UI with VS Code-inspired color themes
  • Improved Event Log UI with hierarchical grouping (e.g., Recomputed status for invalidation waves)
  • Added new event types: invalidate, refresh, rebuild, dependencyChangeEvent, and asyncComplete
  • Optimized data serialization and display:
    • Added type labels (e.g., String, int) in Tree View
    • Fixed Map/Set display to unwrap internal metadata for better readability
    • Added "Show more" button for large collections
    • Implemented caching for value string conversions
  • Enhanced Event Log filtering with multi-selection and "Show All" toggle
  • Expanded flutter_riverpod dependency range to >=2.3.0 <4.0.0
  • Updated example app with comprehensive demo pages for different provider types

0.3.0 #

  • Refresh provider list UI and add filtering feature
  • Add example pages (collections, lifecycle, todo, async) and new demos for Set, Map, and nested collections

0.2.0 #

  • Breaking: Updated to support both Riverpod 2.x and 3.x (flutter_riverpod: '>=2.6.1 <4.0.0')
  • Updated RiverpodDevToolsObserver to handle API changes in Riverpod 3.0
  • Improved compatibility layer for seamless migration between Riverpod versions
  • Fixed pub.dev warnings about outdated dependencies

0.1.0 #

  • Initial release of access to the Riverpod DevTools extension.
  • Added RiverpodDevToolsObserver to track provider events.
3
likes
140
points
3.37k
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

DevTools extension for Riverpod - inspect providers in real-time, now with MCP support for AI coding tools.

Repository (GitHub)
View/report issues

Topics

#riverpod #devtools #state-management #debugging #mcp

License

MIT (license)

Dependencies

analyzer, dart_mcp, flutter, flutter_riverpod, path

More

Packages that depend on riverpod_devtools