All free skills / Other majors
msw 2.x
Use MSW 2.x for HTTP and GraphQL request interception. Covers the v2 API, Node setup, response construction, resolver inputs, migration traps from MSW 1.x, and the browser entry point.
- For
msw@2.15.0- Verified
- 2026-09-08, 3 examples executed
- Skill package
@modootoday/pmcp-msw@2.0.0
Use this skill for free
No PMCP login or subscription is required. Download the original instructions, or install the content-only archive with your project's package manager.
Download SKILL.md · Download package archive
npm install --save-dev https://pmcp.build/skills/msw/2/package.tgz
PMCP discovers the installed package's instructions. Connect your runtime after installation.
Archive integrity
sha512-OZtxXgODccphk4cjCFFL5QvaUbmMW2TecMMDGa5m7Spv3gyG7qvoyuMMYdFdnA52dlmKQwg22H8T5qoLrHcQbw==Complete instructions
Verified against msw@2.15.0 on 2026-09-08. 3 of 3 examples executed.
MSW 2.x
Use this skill for msw in the ^2.0.0 range. MSW 2 requires Node.js 18+ and TypeScript 4.7+. The primary v2 imports are http, graphql, and HttpResponse from msw; environment-specific setup is imported from msw/node or msw/browser.
The v2 shape
HTTP handlers use the http namespace and receive one resolver-information object:
import { http, HttpResponse } from 'msw'
const handlers = [
http.get('/user/:id', ({ params }) => {
return HttpResponse.json({ id: params.id })
}),
http.post('/user', async ({ request }) => {
const body = await request.json()
return HttpResponse.json(body, { status: 201 })
}),
]
A handler by itself does not intercept anything. Pass handlers to setupServer(...handlers) in Node or setupWorker(...handlers) in a browser.
HttpResponse.json(value, options?) creates a response. The options can include status and statusText. HttpResponse.error() creates a network-error response.
Resolver information can include request, params, and cookies:
request.urlis a string. Parse it withnew URL(request.url)when URL components are needed.- Read a request body with Fetch request methods such as
await request.json(). - Path parameters are available through
params. - Cookies are available through
cookies.
Node interception
Import setupServer from msw/node. Start interception with server.listen(), and finish with server.close(). server.resetHandlers() restores the initial handlers after runtime handler changes and is useful between tests.
The Node integration intercepts native HTTP/HTTPS traffic without stubbing fetch or Axios. The following is a complete standalone Node example; it uses an absolute URL so it can run directly without a framework or test runner:
import assert from 'node:assert/strict'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
const server = setupServer(
http.get('https://example.test/users/:id', ({ params, request }) => {
const url = new URL(request.url)
return HttpResponse.json(
{ id: params.id, host: url.host },
{ status: 202, statusText: 'Mocked' },
)
}),
)
server.listen()
try {
const response = await fetch('https://example.test/users/abc-123')
assert.equal(response.status, 202)
assert.equal(response.statusText, 'Mocked')
assert.deepEqual(await response.json(), {
id: 'abc-123',
host: 'example.test',
})
} finally {
server.close()
}
Request bodies are read from request, not from a v1 req argument:
import assert from 'node:assert/strict'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
const server = setupServer(
http.post('https://example.test/user', async ({ request }) => {
const user = await request.json() as { firstName: string }
return HttpResponse.json({ ...user, accepted: true }, { status: 201 })
}),
)
server.listen()
try {
const response = await fetch('https://example.test/user', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ firstName: 'John' }),
})
assert.equal(response.status, 201)
assert.deepEqual(await response.json(), {
firstName: 'John',
accepted: true,
})
} finally {
server.close()
}
In a test runner, the documented lifecycle is listen() before tests, resetHandlers() after each test, and close() after all tests.
GraphQL handlers
Import graphql and HttpResponse from msw. The documented methods include graphql.query(), graphql.mutation(), graphql.link(url), and graphql.operation(). A query or mutation resolver receives values including query and variables.
GraphQL subscriptions are not supported. A standalone Node example can exercise a query handler through the normal Node setup:
import assert from 'node:assert/strict'
import { graphql, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
const server = setupServer(
graphql.query('GetUser', ({ variables }) => {
return HttpResponse.json({
data: { user: { name: variables.userId === '1' ? 'John' : 'Unknown' } },
})
}),
)
server.listen()
try {
const response = await fetch('https://example.test/graphql', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
operationName: 'GetUser',
query: 'query GetUser($userId: ID!) { user { name } }',
variables: { userId: '1' },
}),
})
assert.equal(response.status, 200)
assert.deepEqual(await response.json(), {
data: { user: { name: 'John' } },
})
} finally {
server.close()
}
A mutation follows the same pattern, using graphql.mutation('CreateUser', resolver) and reading its input from variables.
Browser setup
Browser interception uses the separate msw/browser entry point:
import { setupWorker } from 'msw/browser'
const worker = setupWorker(/* http/graphql handlers */)
await worker.start()
This requires a Service Worker and is therefore not a standalone bun example.ts environment. Do not import setupWorker from msw; that is the MSW 1.x shape.
Migration traps from MSW 1.x
Do not carry these older forms into v2:
rest.get(...)becomeshttp.get(...).import { setupWorker } from 'msw'becomesimport { setupWorker } from 'msw/browser'.(req, res, ctx) => ...becomes a resolver such as({ request, params, cookies }) => ....res(ctx.json(value))becomesHttpResponse.json(value).req.urlis nowrequest.url, a string; usenew URL(request.url)when necessary.req.params,req.cookies, andreq.bodymove to resolver properties and FetchRequestmethods.req.passthrough()becomespassthrough().res.once()becomes the response option{ once: true }.res.networkError()becomesHttpResponse.error().ctx.*response utilities becomeHttpResponseAPIs.ctx.fetch(req)becomesfetch(bypass(request))..printHandlers()becomes.listHandlers().
Not covered
This skill does not cover Service Worker installation or browser build configuration, test-runner-specific setup, Jest environment configuration, Axios-specific examples, passthrough implementation details, handler inspection details, or GraphQL schema/client configuration. The research also does not document the exact signatures or behavior of every HttpResponse option, graphql.link(), graphql.operation(), or runtime handler mutation APIs.