@cocaxcode/api-testing-mcp 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,203 +2,354 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@cocaxcode/api-testing-mcp.svg)](https://www.npmjs.com/package/@cocaxcode/api-testing-mcp)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Tests](https://img.shields.io/badge/tests-70%20passing-brightgreen)]()
6
+ [![Node](https://img.shields.io/badge/node-%3E%3D20-blue)]()
5
7
 
6
- MCP server for API testing. Lightweight, local, zero cloud dependencies.
8
+ **The API testing toolkit for AI coding agents.** Test APIs directly from Claude Code, Claude Desktop, Cursor, or any MCP client — using natural language.
7
9
 
8
- Test your APIs directly from Claude Code, Claude Desktop, Cursor, or any MCP client — without leaving your workflow.
10
+ > "Test my login endpoint with invalid credentials"
11
+ > "Import the API spec and show me all blog endpoints"
12
+ > "Run a load test with 50 concurrent requests to /health"
13
+ > "Generate mock data for the create user endpoint"
9
14
 
10
- ## Features
15
+ Zero cloud dependencies. Everything stored locally as JSON.
11
16
 
12
- - **HTTP requests** — GET, POST, PUT, PATCH, DELETE with headers, body, query params
13
- - **Authentication** — Bearer token, API Key, Basic Auth built-in
14
- - **Collections** — Save, organize, and reuse requests locally
15
- - **Environments** — Manage variables per environment (dev/staging/prod)
16
- - **Variable interpolation** — Use `{{VARIABLE}}` in URLs, headers, and body
17
- - **Response metrics** — Timing (ms) and response size for every request
18
- - **Zero cloud dependencies** — Everything stored locally as JSON files
17
+ ---
19
18
 
20
- ## Installation
19
+ ## Why?
21
20
 
22
- ### Claude Desktop
21
+ | Problem | Solution |
22
+ |---------|----------|
23
+ | Switching between Postman and your IDE | Test APIs without leaving your editor |
24
+ | Remembering endpoint URLs and body schemas | Import your OpenAPI spec — the AI knows your API |
25
+ | Writing `{{BASE_URL}}/api/users` every time | Just write `/api/users` — BASE_URL is auto-resolved |
26
+ | Manual regression testing | `bulk_test` runs your entire collection in seconds |
27
+ | No idea what data to send | `mock` generates fake data from your API spec |
28
+ | Testing auth flows manually | `flow_run` chains requests — login → extract token → use it |
23
29
 
24
- Add to your `claude_desktop_config.json`:
30
+ ---
25
31
 
26
- ```json
27
- {
28
- "mcpServers": {
29
- "api-testing": {
30
- "command": "npx",
31
- "args": ["-y", "@cocaxcode/api-testing-mcp"]
32
- }
33
- }
34
- }
35
- ```
32
+ ## Quick Start
36
33
 
37
- ### Claude Code
34
+ ### Install in Claude Code
38
35
 
39
36
  ```bash
40
37
  claude mcp add api-testing -- npx -y @cocaxcode/api-testing-mcp
41
38
  ```
42
39
 
43
- ### Custom storage directory
40
+ ### Install in Claude Desktop / Cursor
41
+
42
+ Add to your MCP config:
44
43
 
45
44
  ```json
46
45
  {
47
46
  "mcpServers": {
48
47
  "api-testing": {
49
48
  "command": "npx",
50
- "args": ["-y", "@cocaxcode/api-testing-mcp"],
51
- "env": {
52
- "API_TESTING_DIR": "/path/to/your/.api-testing"
53
- }
49
+ "args": ["-y", "@cocaxcode/api-testing-mcp"]
54
50
  }
55
51
  }
56
52
  }
57
53
  ```
58
54
 
59
- ## Tools
55
+ ### Setup your environment
60
56
 
61
- ### `request`
57
+ ```
58
+ "Create an environment called dev with BASE_URL http://localhost:3000 and TOKEN my-dev-token"
59
+ ```
60
+
61
+ That's it. Now just talk:
62
62
 
63
- Execute an HTTP request with optional authentication and variable interpolation.
63
+ ```
64
+ "GET /api/health"
65
+ "Create a blog post with random data"
66
+ "Show me all users sorted by creation date"
67
+ ```
64
68
 
65
- Relative URLs (starting with `/`) automatically use `BASE_URL` from the active environment — no need to write `{{BASE_URL}}` every time.
69
+ ---
70
+
71
+ ## Features & Examples
72
+
73
+ ### 🌐 HTTP Requests — `request`
74
+
75
+ Execute any HTTP request with full control. Relative URLs (`/path`) auto-resolve using `BASE_URL` from the active environment.
66
76
 
67
77
  ```
68
- // Relative URL — auto-prepends BASE_URL from active environment
69
- request({ method: "GET", url: "/api/users" })
78
+ "GET /api/users"
79
+ "POST /api/blog with title 'Hello World' and content 'My first post'"
80
+ "DELETE /api/users/123 with Bearer token abc123"
81
+ ```
82
+
83
+ **Supports:** GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS | Headers | Query params | JSON body | Auth (Bearer, API Key, Basic) | Timeout | Variable interpolation `{{VAR}}`
70
84
 
71
- // Equivalent to:
72
- request({ method: "GET", url: "{{BASE_URL}}/api/users" })
85
+ ---
73
86
 
74
- // Full example with all options
75
- request({
76
- method: "GET",
77
- url: "/api/users",
78
- headers: { "Authorization": "Bearer {{TOKEN}}" },
79
- query: { "page": "1" },
80
- timeout: 5000
81
- })
87
+ ### Assertions `assert`
88
+
89
+ Execute a request AND validate the response in one step. Get structured pass/fail results.
90
+
91
+ ```
92
+ "Assert that GET /api/health returns status 200 and body.status equals 'ok'"
93
+ "Verify POST /api/login with wrong password returns 401"
94
+ "Check that GET /api/users responds in less than 500ms"
82
95
  ```
83
96
 
84
- **Auth examples:**
97
+ **Available operators:** `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `contains`, `not_contains`, `exists`, `type`
98
+
99
+ **Output:**
100
+ ```
101
+ ✅ PASS — 3/3 assertions passed
102
+ GET /api/health → 200 OK (42ms)
85
103
 
104
+ ✅ status === 200
105
+ ✅ body.status === "ok"
106
+ ✅ timing.total_ms < 500
86
107
  ```
87
- // Bearer token
88
- request({ method: "GET", url: "...", auth: { type: "bearer", token: "abc123" } })
89
108
 
90
- // API Key
91
- request({ method: "GET", url: "...", auth: { type: "api-key", key: "mykey", header: "X-API-Key" } })
109
+ ---
92
110
 
93
- // Basic Auth
94
- request({ method: "GET", url: "...", auth: { type: "basic", username: "user", password: "pass" } })
111
+ ### 🔗 Flow — `flow_run`
112
+
113
+ Chain multiple requests in sequence. Extract data from one response and use it in the next step with `{{variables}}`.
114
+
115
+ ```
116
+ "Run a flow: first login with email admin@test.com and password 123456,
117
+ extract the token from body.token,
118
+ then use that token to GET /api/users"
95
119
  ```
96
120
 
97
- **Response format:**
121
+ **Output:**
122
+ ```
123
+ ✅ FLOW COMPLETO — 2/2 pasos ejecutados
98
124
 
99
- ```json
100
- {
101
- "status": 200,
102
- "statusText": "OK",
103
- "headers": { "content-type": "application/json" },
104
- "body": { "users": [] },
105
- "timing": { "total_ms": 142.35 },
106
- "size_bytes": 1024
107
- }
125
+ ✅ Paso 1: login
126
+ Status: 200 | Tiempo: 145ms
127
+ Extraído: TOKEN=eyJhbGciOiJIUzI1NiIs...
128
+
129
+ Paso 2: get-users
130
+ Status: 200 | Tiempo: 89ms
108
131
  ```
109
132
 
110
- ### `collection_save`
133
+ ---
134
+
135
+ ### 📋 OpenAPI Import — `api_import`, `api_endpoints`, `api_endpoint_detail`
136
+
137
+ Import your Swagger/OpenAPI spec so the AI knows your entire API — endpoints, schemas, required fields, everything.
111
138
 
112
- Save a request to your local collection for reuse.
139
+ ```
140
+ "Import my API from http://localhost:3000/api-docs-json"
141
+ "What endpoints does the blog module have?"
142
+ "Show me the details of POST /api/users — what fields does it need?"
143
+ ```
113
144
 
145
+ **Output:**
114
146
  ```
115
- collection_save({
116
- name: "get-users",
117
- request: { method: "GET", url: "https://api.example.com/users" },
118
- tags: ["users", "read"]
119
- })
147
+ API 'my-backend' imported — 24 endpoints, 15 schemas
148
+
149
+ Endpoints by tag:
150
+ auth: 3 endpoints
151
+ users: 5 endpoints
152
+ blog: 6 endpoints
153
+ projects: 4 endpoints
120
154
  ```
121
155
 
122
- ### `collection_list`
156
+ ---
123
157
 
124
- List all saved requests. Optionally filter by tag.
158
+ ### 🎭 Mock Data `mock`
159
+
160
+ Generate realistic fake data from your OpenAPI spec. Perfect for frontend development without a running backend.
125
161
 
126
162
  ```
127
- collection_list({ tag: "users" })
163
+ "Generate mock data for creating a user"
164
+ "Give me 10 fake blog posts based on the API spec"
165
+ "What would the response of GET /api/projects look like?"
128
166
  ```
129
167
 
130
- ### `collection_get`
168
+ **Output:**
169
+ ```json
170
+ {
171
+ "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
172
+ "email": "user42@example.com",
173
+ "name": "Test User 73",
174
+ "role": "admin",
175
+ "active": true
176
+ }
177
+ ```
178
+
179
+ ---
131
180
 
132
- Get the full details of a saved request.
181
+ ### 📊 Load Test `load_test`
182
+
183
+ Launch N concurrent requests and get performance stats: avg, min, max, percentiles, requests/second.
133
184
 
134
185
  ```
135
- collection_get({ name: "get-users" })
186
+ "Run a load test with 50 concurrent requests to GET /api/health"
187
+ "Load test POST /api/search with 20 concurrent requests"
136
188
  ```
137
189
 
138
- ### `collection_delete`
190
+ **Output:**
191
+ ```
192
+ 📊 LOAD TEST — GET /api/health
193
+
194
+ Requests: 50 concurrentes
195
+ Exitosos: 50 | Fallidos: 0
196
+ Tiempo total: 2145ms
197
+ Requests/segundo: 23.31
198
+
199
+ ⏱️ Tiempos de respuesta:
200
+ Min: 45ms
201
+ Avg: 187ms
202
+ p50: 156ms
203
+ p95: 412ms
204
+ p99: 523ms
205
+ Max: 567ms
206
+
207
+ 📋 Status codes:
208
+ 200: 50 (100%)
209
+ ```
210
+
211
+ ---
212
+
213
+ ### 🔄 Diff Responses — `diff_responses`
139
214
 
140
- Delete a saved request from the collection.
215
+ Compare two requests side by side. Useful for regression testing or comparing environments (dev vs prod).
141
216
 
142
217
  ```
143
- collection_delete({ name: "get-users" })
218
+ "Compare GET /api/users on dev vs prod"
219
+ "Diff the response of v1/users vs v2/users"
144
220
  ```
145
221
 
146
- ### `env_create`
222
+ ---
147
223
 
148
- Create a new environment with optional initial variables.
224
+ ### 🚀 Bulk Test `bulk_test`
149
225
 
226
+ Run all saved requests in your collection and get a summary report. Filter by tag.
227
+
228
+ ```
229
+ "Run all saved requests tagged 'smoke'"
230
+ "Bulk test my entire collection"
150
231
  ```
151
- env_create({
152
- name: "dev",
153
- variables: { "BASE_URL": "http://localhost:3000", "TOKEN": "dev-token" }
154
- })
232
+
233
+ **Output:**
155
234
  ```
235
+ ✅ BULK TEST — 8/8 passed | 1234ms total
156
236
 
157
- ### `env_list`
237
+ health-check — GET /api/health → 200 (45ms)
238
+ ✅ list-users — GET /api/users → 200 (123ms)
239
+ ✅ create-post — POST /api/blog → 201 (89ms)
240
+ ✅ get-post — GET /api/blog/test-post → 200 (67ms)
241
+ ...
242
+ ```
158
243
 
159
- List all environments and which one is active.
244
+ ---
160
245
 
161
- ### `env_set`
246
+ ### 📤 Export cURL — `export_curl`
162
247
 
163
- Set a variable in an environment (defaults to active environment).
248
+ Convert any saved request to a cURL command. Ready to copy-paste and share.
164
249
 
165
250
  ```
166
- env_set({ key: "TOKEN", value: "new-token-value" })
251
+ "Export the create-user request as cURL"
252
+ ```
253
+
254
+ **Output:**
255
+ ```bash
256
+ curl \
257
+ -X POST \
258
+ 'https://api.example.com/users' \
259
+ -H 'Authorization: Bearer abc123' \
260
+ -H 'Content-Type: application/json' \
261
+ -d '{"name":"John","email":"john@example.com"}'
167
262
  ```
168
263
 
169
- ### `env_get`
264
+ ---
170
265
 
171
- Get a specific variable or all variables from an environment.
266
+ ### 💾 Collections `collection_save`, `collection_list`, `collection_get`, `collection_delete`
267
+
268
+ Save, organize, and reuse requests locally. Tag them for easy filtering.
172
269
 
173
270
  ```
174
- env_get({ key: "BASE_URL" })
175
- env_get({}) // returns all variables
271
+ "Save this request as 'create-user' with tags 'users' and 'write'"
272
+ "Show me all saved requests tagged 'auth'"
273
+ "Delete the old-endpoint request"
176
274
  ```
177
275
 
178
- ### `env_switch`
276
+ ---
277
+
278
+ ### 🌍 Environments — `env_create`, `env_list`, `env_set`, `env_get`, `env_switch`
179
279
 
180
- Switch the active environment. Active environment variables are used for `{{interpolation}}`.
280
+ Manage variables per environment. Switch between dev/staging/prod seamlessly.
181
281
 
182
282
  ```
183
- env_switch({ name: "prod" })
283
+ "Create a prod environment with BASE_URL https://api.example.com"
284
+ "Switch to dev environment"
285
+ "Set TOKEN to my-new-token in the current environment"
184
286
  ```
185
287
 
288
+ ---
289
+
290
+ ## All 20 Tools
291
+
292
+ | Category | Tool | Description |
293
+ |----------|------|-------------|
294
+ | **Request** | `request` | Execute HTTP requests |
295
+ | **Assert** | `assert` | Request + validate with assertions |
296
+ | **Flow** | `flow_run` | Chain requests, extract variables |
297
+ | **Collections** | `collection_save` | Save a request |
298
+ | | `collection_list` | List saved requests |
299
+ | | `collection_get` | Get request details |
300
+ | | `collection_delete` | Delete a request |
301
+ | **Environments** | `env_create` | Create environment |
302
+ | | `env_list` | List environments |
303
+ | | `env_set` | Set a variable |
304
+ | | `env_get` | Get variable(s) |
305
+ | | `env_switch` | Switch active env |
306
+ | **API Spec** | `api_import` | Import OpenAPI spec |
307
+ | | `api_endpoints` | List endpoints |
308
+ | | `api_endpoint_detail` | Endpoint details |
309
+ | **Mock** | `mock` | Generate fake data |
310
+ | **Load Test** | `load_test` | Concurrent performance test |
311
+ | **Utilities** | `export_curl` | Export as cURL |
312
+ | | `diff_responses` | Compare responses |
313
+ | | `bulk_test` | Run entire collection |
314
+
315
+ ---
316
+
186
317
  ## Storage
187
318
 
188
- All data is stored locally as JSON files in `.api-testing/` (in your current working directory by default):
319
+ All data is stored locally as JSON files in `.api-testing/`:
189
320
 
190
321
  ```
191
322
  .api-testing/
192
- ├── active-env # Name of the active environment
323
+ ├── active-env
193
324
  ├── collections/
194
- │ ├── get-users.json
195
- │ └── create-post.json
196
- └── environments/
197
- ├── dev.json
198
- └── prod.json
325
+ │ ├── health-check.json
326
+ │ └── create-user.json
327
+ ├── environments/
328
+ ├── dev.json
329
+ └── prod.json
330
+ └── specs/
331
+ └── my-backend.json
332
+ ```
333
+
334
+ Configure the storage directory:
335
+
336
+ ```json
337
+ {
338
+ "mcpServers": {
339
+ "api-testing": {
340
+ "command": "npx",
341
+ "args": ["-y", "@cocaxcode/api-testing-mcp"],
342
+ "env": {
343
+ "API_TESTING_DIR": "/path/to/your/.api-testing"
344
+ }
345
+ }
346
+ }
347
+ }
199
348
  ```
200
349
 
201
- You can version these files in git if you want to share collections and environments with your team.
350
+ You can version these files in git to share with your team.
351
+
352
+ ---
202
353
 
203
354
  ## Development
204
355
 
@@ -206,8 +357,9 @@ You can version these files in git if you want to share collections and environm
206
357
  git clone https://github.com/cocaxcode/api-testing-mcp.git
207
358
  cd api-testing-mcp
208
359
  npm install
209
- npm test
360
+ npm test # 70 tests
210
361
  npm run build
362
+ npm run typecheck
211
363
  ```
212
364
 
213
365
  ### Test with MCP Inspector
@@ -216,6 +368,8 @@ npm run build
216
368
  npx @modelcontextprotocol/inspector node dist/index.js
217
369
  ```
218
370
 
371
+ ---
372
+
219
373
  ## License
220
374
 
221
- MIT
375
+ MIT — [cocaxcode](https://github.com/cocaxcode)