
msw-devtool
A TanStack DevTools plugin for managing MSW mocks.
Toggle, customize, and inspect your mock handlers in real time.
This project is a work in progress — the API has not been finalised yet, which is why we haven't reached 1.0.0. Expect breaking changes between minor versions.
Works with
Why msw-devtool?
Tired of commenting out handlers, hard-coding error responses, and refreshing the page every time you need a different mock? msw-devtool lets you toggle, swap, and override any MSW mock on the fly — right from the browser, without touching your code.
Toggle Mocks
Enable or disable individual mock handlers with a single click. Disabled handlers pass requests straight through to the real network, so you can test real vs. mocked responses side by side — no code changes, no restarts.
Switch Variants
Define multiple response variants for the same endpoint — success, empty list, validation error, 404 — and swap between them from a dropdown. Perfect for exploring every UI state without writing throwaway code.
Live Overrides
Edit response JSON, status codes, and headers directly in the panel. Need to test how your UI handles a 500? A missing field? Just change it and the response updates instantly — no handler code to touch.
LIVE Tracking
Every intercepted request is tracked in real time. Operations that are actively being called on the current page get a LIVE badge, so you can see at a glance which handlers are actually in use.
Filter & Sort
As your mock list grows, use built-in filtering and sorting to quickly find handlers by name, HTTP method, or status. Filter by "live" to see only the operations active on the current page.
Auto Refetch
Register an adapter for your data-fetching library (TanStack Query, RTK Query, SWR, Apollo, URQL) and every mock change automatically invalidates the cache — your UI re-renders with fresh data without a page reload.
Install the core library:
This library renders inside TanStack DevTools, so you'll need that too:
Pass your MSW handlers directly to registerRestMocks or registerGraphqlMocks. The operation name, method, and path are auto-derived from the handler:
Add the TanStack DevTools component to your app with the MSW plugin. The service worker starts automatically when the plugin mounts:
Adapters connect your data-fetching library to the devtools. When you toggle a mock or switch variants, the adapter automatically refetches/revalidates so your UI updates immediately.
Each adapter hooks into a specific library's cache invalidation mechanism. You only need to register the adapters for the libraries you actually use.
TanStack Query
Invalidates all queries via queryClient.invalidateQueries() when mock config changes. Only queries with active subscriptions (i.e., components currently mounted and observing them) are refetched.
URQL
Uses a custom exchange that re-executes active queries. Add mockRefetchExchange to your URQL client's exchange pipeline:
Apollo Client
Calls apolloClient.refetchQueries() to re-run all active queries.
RTK Query
Resets the API state via api.util.resetApiState() when mock config changes. Only endpoints with active subscriptions (i.e., components currently mounted and using the generated hooks) are refetched.
SWR
Calls the global mutate() to revalidate all SWR keys.
Axios & plain fetch
Consider using a server-state library instead. Libraries like TanStack Query, RTK Query, SWR, or Apollo provide built-in caching, deduplication, and automatic refetching — making the integration with msw-devtool seamless and zero-config. The Axios/fetch adapter requires manual useMockRefetch wiring in every component, which adds boilerplate and is harder to maintain.
Axios and fetch() have no query cache. Register the Axios adapter as a marker, then use the useMockRefetch hook in your components to re-run requests when mock config changes:
Most projects already have MSW handlers for unit tests, E2E, or Storybook. You can pass them directly to registerRestMocks or registerGraphqlMocks — no conversion needed.
Register handlers directly
Pass your existing MSW handlers directly. The devtools auto-derives the operation name, method, and path from each handler:
Multiple variants for the same endpoint
If you have multiple success scenarios (e.g. full list vs empty list), use the variants array:
Tip: Error scenarios (401, 404, 429, 500, Network Error) are handled by the Error Override UI in the devtools panel — no need to create separate error variants.
The essentials you need to get started, plus advanced exports for custom integrations.
Core
The functions you'll use in every project.
registerRestMocks
voidregisterRestMocks(...defs: RestMockDef[]): voidRegister one or more REST mocks from MSW HttpHandlers. Operation metadata (method, path, operationName) is auto-derived from the handler.
| Parameter | Type | Default | Description |
|---|---|---|---|
| def.handler | HttpHandler | — | MSW HttpHandler (shorthand for single variant) |
| def.variants | HandlerVariantInput<HttpHandler>[] | — | Multiple handler variants for the same endpoint |
| def.operationName | string | — | Override the auto-derived operation name |
| def.group | string | — | Optional grouping label |
registerGraphqlMocks
voidregisterGraphqlMocks(...defs: GraphqlMockDef[]): voidRegister one or more GraphQL mocks from MSW GraphQLHandlers. Operation metadata (operationName, operationType) is auto-derived from the handler.
| Parameter | Type | Default | Description |
|---|---|---|---|
| def.handler | GraphQLHandler | — | MSW GraphQLHandler (shorthand for single variant) |
| def.variants | HandlerVariantInput<GraphQLHandler>[] | — | Multiple handler variants for the same operation |
| def.operationName | string | — | Override the auto-derived operation name |
| def.operationType | "query" | "mutation" | — | Override the auto-derived operation type |
| def.group | string | — | Optional grouping label |
createMswDevToolsPlugin
TanStackPlugincreateMswDevToolsPlugin(options?: MswDevToolsPluginOptions): TanStackPluginCreates a TanStack DevTools plugin that auto-starts the MSW service worker on mount. No manual worker setup required.
| Parameter | Type | Default | Description |
|---|---|---|---|
| options.defaultOpen | boolean | true | Whether the devtools panel starts open |
| options.name | string | 'MSW Mocks' | Plugin display name |
registerAdapter
() => voidregisterAdapter(adapter: MswDevToolAdapter): () => voidRegister a data-fetching adapter. When mock config changes, the adapter automatically refetches queries. Returns an unregister function for cleanup.
React Hooks
React hooks for integrating with the mock system.
useMockRefetch
voiduseMockRefetch(operationName: string, refetch: () => void): voidListens for mock update events matching the given operation name and calls your refetch callback. Use with Axios or plain fetch.
Advanced
For custom integrations. Most apps won't need these.
startWorker
Promise<SetupWorker>startWorker(options?: WorkerOptions): Promise<SetupWorker>Manually start the MSW service worker with custom options. The plugin auto-starts the worker on mount — only use this if you need a custom serviceWorkerUrl or other non-default options. If the worker is already running, the plugin skips auto-start.
| Parameter | Type | Default | Description |
|---|---|---|---|
| options.onUnhandledRequest | 'bypass' | 'warn' | 'error' | 'bypass' | How to handle requests with no matching handler |
| options.quiet | boolean | true | Suppress MSW console logging |
| options.serviceWorkerUrl | string | '/mockServiceWorker.js' | Custom path to the service worker script |