@cocaxcode/api-testing-mcp 0.4.0 → 0.4.1

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.
Files changed (2) hide show
  1. package/README.md +176 -218
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,45 +1,77 @@
1
- # @cocaxcode/api-testing-mcp
1
+ <p align="center">
2
+ <h1 align="center">@cocaxcode/api-testing-mcp</h1>
3
+ <p align="center">
4
+ A complete API testing toolkit built for AI coding agents.<br/>
5
+ Test, validate, mock, and load-test your APIs — all from natural language.
6
+ </p>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/@cocaxcode/api-testing-mcp"><img src="https://img.shields.io/npm/v/@cocaxcode/api-testing-mcp.svg?style=flat-square&color=cb3837" alt="npm version" /></a>
11
+ <a href="https://github.com/cocaxcode/api-testing-mcp/actions"><img src="https://img.shields.io/github/actions/workflow/status/cocaxcode/api-testing-mcp/ci.yml?style=flat-square&label=CI" alt="CI" /></a>
12
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="License" /></a>
13
+ <img src="https://img.shields.io/badge/tests-70%20passing-brightgreen?style=flat-square" alt="Tests" />
14
+ <img src="https://img.shields.io/badge/tools-20-blueviolet?style=flat-square" alt="Tools" />
15
+ <img src="https://img.shields.io/badge/node-%3E%3D20-339933?style=flat-square&logo=node.js&logoColor=white" alt="Node" />
16
+ </p>
17
+
18
+ <p align="center">
19
+ <a href="#installation">Installation</a> •
20
+ <a href="#just-talk-to-it">Just Talk to It</a> •
21
+ <a href="#features">Features</a> •
22
+ <a href="#tool-reference">Tool Reference</a> •
23
+ <a href="#storage">Storage</a> •
24
+ <a href="#contributing">Contributing</a>
25
+ </p>
2
26
 
3
- [![npm version](https://img.shields.io/npm/v/@cocaxcode/api-testing-mcp.svg)](https://www.npmjs.com/package/@cocaxcode/api-testing-mcp)
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)]()
27
+ ---
28
+
29
+ ## What is this?
7
30
 
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.
31
+ An [MCP server](https://modelcontextprotocol.io) that gives your AI assistant the ability to interact with any API. It works with Claude Code, Claude Desktop, Cursor, and any MCP-compatible client.
9
32
 
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"
33
+ You describe what you need. The AI figures out the rest.
14
34
 
15
- Zero cloud dependencies. Everything stored locally as JSON.
35
+ No cloud accounts. No subscriptions. Everything runs locally and stores data as plain JSON files you can commit to git.
16
36
 
17
37
  ---
18
38
 
19
- ## Why?
39
+ ## Just Talk to It
40
+
41
+ This tool is designed to be used through natural language. You don't need to memorize tool names, parameters, or JSON structures — just tell the AI what you want, and it translates your intent into the right API calls.
42
+
43
+ **Here's what a real conversation looks like:**
20
44
 
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 |
45
+ | You say | What happens behind the scenes |
46
+ |---------|-------------------------------|
47
+ | *"Set up an environment for my local API on port 3000"* | Creates environment with `BASE_URL=http://localhost:3000` |
48
+ | *"Import my API spec from /api-docs-json"* | Downloads the OpenAPI spec, stores all endpoints and schemas |
49
+ | *"Show me all user endpoints"* | Filters and lists endpoints tagged `users` |
50
+ | *"Get all users"* | `GET /api/users` shows the response |
51
+ | *"Create a user with random data"* | Reads the spec, generates valid mock data, sends `POST /api/users` |
52
+ | *"Verify that deleting user 5 returns 204"* | Runs the request + assertion in one step |
53
+ | *"Login as admin and then fetch the dashboard stats"* | Chains 2 requests: login → extract token → use token for next call |
54
+ | *"How fast is the health endpoint under load?"* | Fires 50 concurrent requests, reports p50/p95/p99 latencies |
55
+ | *"Run all my saved smoke tests"* | Executes every request tagged `smoke`, reports pass/fail |
56
+ | *"Export the create-user request as curl"* | Builds a ready-to-paste cURL command with resolved variables |
57
+ | *"Compare the users endpoint between dev and prod"* | Hits both URLs, diffs status codes, body, and timing |
58
+ | *"Switch to the production environment"* | Changes active env — all subsequent requests use prod URLs and tokens |
59
+
60
+ **The AI already knows your API** if you've imported the spec. It knows which fields are required, what types they expect, valid enum values, and what the response looks like. When you say *"create a blog post"*, it doesn't guess — it reads the schema and builds the request correctly.
29
61
 
30
62
  ---
31
63
 
32
- ## Quick Start
64
+ ## Installation
33
65
 
34
- ### Install in Claude Code
66
+ ### Claude Code
35
67
 
36
68
  ```bash
37
69
  claude mcp add api-testing -- npx -y @cocaxcode/api-testing-mcp
38
70
  ```
39
71
 
40
- ### Install in Claude Desktop / Cursor
72
+ ### Claude Desktop / Cursor / Any MCP Client
41
73
 
42
- Add to your MCP config:
74
+ Add to your MCP configuration file:
43
75
 
44
76
  ```json
45
77
  {
@@ -52,51 +84,59 @@ Add to your MCP config:
52
84
  }
53
85
  ```
54
86
 
55
- ### Setup your environment
87
+ ### First steps
88
+
89
+ Set up an environment so the tool knows where your API lives:
56
90
 
57
91
  ```
58
- "Create an environment called dev with BASE_URL http://localhost:3000 and TOKEN my-dev-token"
92
+ "Create an environment called dev with BASE_URL http://localhost:3000"
59
93
  ```
60
94
 
61
- That's it. Now just talk:
95
+ From here, relative paths work automatically. `/api/users` becomes `http://localhost:3000/api/users`.
96
+
97
+ If your API has Swagger/OpenAPI, import the spec:
62
98
 
63
99
  ```
64
- "GET /api/health"
65
- "Create a blog post with random data"
66
- "Show me all users sorted by creation date"
100
+ "Import my API spec from http://localhost:3000/api-docs-json"
67
101
  ```
68
102
 
103
+ Now the AI knows every endpoint, parameter, and schema in your API. You're ready to go.
104
+
69
105
  ---
70
106
 
71
- ## Features & Examples
107
+ ## Features
72
108
 
73
- ### 🌐 HTTP Requests — `request`
109
+ ### HTTP Requests
74
110
 
75
- Execute any HTTP request with full control. Relative URLs (`/path`) auto-resolve using `BASE_URL` from the active environment.
111
+ Execute any HTTP method with headers, body, query params, and built-in auth. Relative URLs resolve from the active environment. Variables like `{{TOKEN}}` are replaced from environment values.
76
112
 
77
113
  ```
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"
114
+ request({
115
+ method: "POST",
116
+ url: "/api/users",
117
+ body: { name: "Jane", email: "jane@company.com" },
118
+ auth: { type: "bearer", token: "{{TOKEN}}" }
119
+ })
81
120
  ```
82
121
 
83
- **Supports:** GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS | Headers | Query params | JSON body | Auth (Bearer, API Key, Basic) | Timeout | Variable interpolation `{{VAR}}`
84
-
85
- ---
122
+ **Supports:** GET · POST · PUT · PATCH · DELETE · HEAD · OPTIONS Headers · Query params · JSON body · Bearer / API Key / Basic auth · Timeout · `{{variable}}` interpolation
86
123
 
87
- ### Assertions — `assert`
124
+ ### Assertions
88
125
 
89
- Execute a request AND validate the response in one step. Get structured pass/fail results.
126
+ Run a request and validate the response against a set of rules in one step. Get structured pass/fail results.
90
127
 
91
128
  ```
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"
129
+ assert({
130
+ method: "GET",
131
+ url: "/api/health",
132
+ assertions: [
133
+ { path: "status", operator: "eq", expected: 200 },
134
+ { path: "body.status", operator: "eq", expected: "ok" },
135
+ { path: "timing.total_ms", operator: "lt", expected: 500 }
136
+ ]
137
+ })
95
138
  ```
96
139
 
97
- **Available operators:** `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `contains`, `not_contains`, `exists`, `type`
98
-
99
- **Output:**
100
140
  ```
101
141
  ✅ PASS — 3/3 assertions passed
102
142
  GET /api/health → 200 OK (42ms)
@@ -106,270 +146,188 @@ GET /api/health → 200 OK (42ms)
106
146
  ✅ timing.total_ms < 500
107
147
  ```
108
148
 
109
- ---
149
+ **Operators:** `eq` · `neq` · `gt` · `gte` · `lt` · `lte` · `contains` · `not_contains` · `exists` · `type`
110
150
 
111
- ### 🔗 Flow — `flow_run`
151
+ ### Request Flows
112
152
 
113
- Chain multiple requests in sequence. Extract data from one response and use it in the next step with `{{variables}}`.
153
+ Chain multiple requests together. Extract values from one response and inject them into the next step using `{{variables}}`. Perfect for auth flows, CRUD sequences, and multi-step testing.
114
154
 
115
155
  ```
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"
119
- ```
120
-
121
- **Output:**
156
+ flow_run({
157
+ steps: [
158
+ {
159
+ name: "login",
160
+ method: "POST",
161
+ url: "/auth/login",
162
+ body: { email: "admin@test.com", password: "123456" },
163
+ extract: { "TOKEN": "body.access_token" }
164
+ },
165
+ {
166
+ name: "get-users",
167
+ method: "GET",
168
+ url: "/api/users",
169
+ headers: { "Authorization": "Bearer {{TOKEN}}" }
170
+ }
171
+ ]
172
+ })
122
173
  ```
123
- ✅ FLOW COMPLETO — 2/2 pasos ejecutados
124
-
125
- ✅ Paso 1: login
126
- Status: 200 | Tiempo: 145ms
127
- Extraído: TOKEN=eyJhbGciOiJIUzI1NiIs...
128
174
 
129
- Paso 2: get-users
130
- Status: 200 | Tiempo: 89ms
131
- ```
175
+ ### OpenAPI Import
132
176
 
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.
177
+ Import your Swagger/OpenAPI spec from a URL or local file. Once imported, the AI understands every endpoint, parameter, and schema — no guessing, no memorizing.
138
178
 
139
179
  ```
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?"
180
+ api_import({ name: "my-backend", source: "http://localhost:3000/api-docs-json" })
181
+ api_endpoints({ name: "my-backend", tag: "users" })
182
+ api_endpoint_detail({ name: "my-backend", method: "POST", path: "/users" })
143
183
  ```
144
184
 
145
- **Output:**
146
- ```
147
- API 'my-backend' imported — 24 endpoints, 15 schemas
185
+ ### Mock Data Generation
148
186
 
149
- Endpoints by tag:
150
- auth: 3 endpoints
151
- users: 5 endpoints
152
- blog: 6 endpoints
153
- projects: 4 endpoints
154
- ```
155
-
156
- ---
157
-
158
- ### 🎭 Mock Data — `mock`
159
-
160
- Generate realistic fake data from your OpenAPI spec. Perfect for frontend development without a running backend.
187
+ Generate realistic fake data from your OpenAPI spec. Respects types, formats (`email`, `uuid`, `date-time`), enums, and required fields. Use `count` for arrays.
161
188
 
162
189
  ```
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?"
190
+ mock({ name: "my-backend", method: "POST", path: "/users", target: "request" })
166
191
  ```
167
192
 
168
- **Output:**
169
193
  ```json
170
194
  {
171
- "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
172
195
  "email": "user42@example.com",
173
196
  "name": "Test User 73",
174
- "role": "admin",
175
- "active": true
197
+ "password": "TestPass123!",
198
+ "role": "admin"
176
199
  }
177
200
  ```
178
201
 
179
- ---
180
-
181
- ### 📊 Load Test — `load_test`
202
+ ### Load Testing
182
203
 
183
- Launch N concurrent requests and get performance stats: avg, min, max, percentiles, requests/second.
204
+ Fire N concurrent requests and get performance metrics: min, avg, percentiles (p50/p95/p99), max, and requests per second.
184
205
 
185
206
  ```
186
- "Run a load test with 50 concurrent requests to GET /api/health"
187
- "Load test POST /api/search with 20 concurrent requests"
207
+ load_test({ method: "GET", url: "/api/health", concurrent: 50 })
188
208
  ```
189
209
 
190
- **Output:**
191
210
  ```
192
211
  📊 LOAD TEST — GET /api/health
193
212
 
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
213
+ Requests: 50 concurrent
214
+ Successful: 50 | Failed: 0
215
+ Requests/sec: 23.31
206
216
 
207
- 📋 Status codes:
208
- 200: 50 (100%)
217
+ ⏱️ Response times:
218
+ Min: 45ms | Avg: 187ms
219
+ p50: 156ms | p95: 412ms
220
+ p99: 523ms | Max: 567ms
209
221
  ```
210
222
 
211
- ---
212
-
213
- ### 🔄 Diff Responses — `diff_responses`
223
+ ### Response Diffing
214
224
 
215
- Compare two requests side by side. Useful for regression testing or comparing environments (dev vs prod).
225
+ Execute two requests and compare their responses field by field. Detect regressions or compare environments (dev vs prod).
216
226
 
217
227
  ```
218
- "Compare GET /api/users on dev vs prod"
219
- "Diff the response of v1/users vs v2/users"
228
+ diff_responses({
229
+ request_a: { label: "dev", method: "GET", url: "http://dev.api.com/users" },
230
+ request_b: { label: "prod", method: "GET", url: "http://prod.api.com/users" }
231
+ })
220
232
  ```
221
233
 
222
- ---
223
-
224
- ### 🚀 Bulk Test — `bulk_test`
234
+ ### Bulk Testing
225
235
 
226
- Run all saved requests in your collection and get a summary report. Filter by tag.
236
+ Run every saved request in your collection (or filter by tag) and get a pass/fail summary.
227
237
 
228
238
  ```
229
- "Run all saved requests tagged 'smoke'"
230
- "Bulk test my entire collection"
239
+ bulk_test({ tag: "smoke" })
231
240
  ```
232
241
 
233
- **Output:**
234
242
  ```
235
- ✅ BULK TEST — 8/8 passed | 1234ms total
243
+ ✅ BULK TEST — 8/8 passed | 1.2s total
236
244
 
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
- ...
245
+ ✅ health — GET /health → 200 (45ms)
246
+ ✅ list-users — GET /users → 200 (123ms)
247
+ ✅ create-post — POST /blog → 201 (89ms)
248
+ login POST /auth/login → 200 (156ms)
242
249
  ```
243
250
 
244
- ---
245
-
246
- ### 📤 Export cURL — `export_curl`
247
-
248
- Convert any saved request to a cURL command. Ready to copy-paste and share.
251
+ ### cURL Export
249
252
 
250
- ```
251
- "Export the create-user request as cURL"
252
- ```
253
+ Convert any saved request into a cURL command with resolved variables.
253
254
 
254
- **Output:**
255
255
  ```bash
256
- curl \
257
- -X POST \
256
+ curl -X POST \
258
257
  'https://api.example.com/users' \
259
- -H 'Authorization: Bearer abc123' \
258
+ -H 'Authorization: Bearer eyJhbGci...' \
260
259
  -H 'Content-Type: application/json' \
261
- -d '{"name":"John","email":"john@example.com"}'
260
+ -d '{"name":"Jane","email":"jane@company.com"}'
262
261
  ```
263
262
 
264
- ---
265
-
266
- ### 💾 Collections — `collection_save`, `collection_list`, `collection_get`, `collection_delete`
263
+ ### Collections & Environments
267
264
 
268
- Save, organize, and reuse requests locally. Tag them for easy filtering.
269
-
270
- ```
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"
274
- ```
265
+ Save requests for reuse (with tags), manage variables across environments (dev/staging/prod), and switch contexts instantly.
275
266
 
276
267
  ---
277
268
 
278
- ### 🌍 Environments — `env_create`, `env_list`, `env_set`, `env_get`, `env_switch`
269
+ ## Tool Reference
279
270
 
280
- Manage variables per environment. Switch between dev/staging/prod seamlessly.
281
-
282
- ```
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"
286
- ```
287
-
288
- ---
271
+ 20 tools organized in 8 categories:
289
272
 
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 |
273
+ | Category | Tools | Count |
274
+ |----------|-------|-------|
275
+ | **Requests** | `request` | 1 |
276
+ | **Testing** | `assert` | 1 |
277
+ | **Flows** | `flow_run` | 1 |
278
+ | **Collections** | `collection_save` · `collection_list` · `collection_get` · `collection_delete` | 4 |
279
+ | **Environments** | `env_create` · `env_list` · `env_set` · `env_get` · `env_switch` | 5 |
280
+ | **API Specs** | `api_import` · `api_endpoints` · `api_endpoint_detail` | 3 |
281
+ | **Mock** | `mock` | 1 |
282
+ | **Utilities** | `load_test` · `export_curl` · `diff_responses` · `bulk_test` | 4 |
314
283
 
315
284
  ---
316
285
 
317
286
  ## Storage
318
287
 
319
- All data is stored locally as JSON files in `.api-testing/`:
288
+ All data lives in `.api-testing/` as plain JSON no database, no cloud sync:
320
289
 
321
290
  ```
322
291
  .api-testing/
323
- ├── active-env
324
- ├── collections/
325
- ├── health-check.json
326
- └── create-user.json
327
- ├── environments/
328
- │ ├── dev.json
329
- │ └── prod.json
330
- └── specs/
331
- └── my-backend.json
292
+ ├── active-env # Active environment name
293
+ ├── collections/ # Saved requests
294
+ ├── environments/ # Environment variables (dev, prod, ...)
295
+ └── specs/ # Imported OpenAPI specs
332
296
  ```
333
297
 
334
- Configure the storage directory:
298
+ Override the default directory:
335
299
 
336
300
  ```json
337
301
  {
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
- }
302
+ "env": { "API_TESTING_DIR": "/path/to/shared/.api-testing" }
347
303
  }
348
304
  ```
349
305
 
350
- You can version these files in git to share with your team.
306
+ Commit these files to git to share across your team.
351
307
 
352
308
  ---
353
309
 
354
- ## Development
310
+ ## Contributing
355
311
 
356
312
  ```bash
357
313
  git clone https://github.com/cocaxcode/api-testing-mcp.git
358
314
  cd api-testing-mcp
359
315
  npm install
360
- npm test # 70 tests
361
- npm run build
362
- npm run typecheck
316
+ npm test # 70 tests across 10 suites
317
+ npm run build # ESM bundle via tsup
318
+ npm run typecheck # Strict TypeScript
363
319
  ```
364
320
 
365
- ### Test with MCP Inspector
321
+ **Test with MCP Inspector:**
366
322
 
367
323
  ```bash
368
324
  npx @modelcontextprotocol/inspector node dist/index.js
369
325
  ```
370
326
 
327
+ **Stack:** TypeScript · MCP SDK 1.27 · Zod · Vitest · tsup
328
+
371
329
  ---
372
330
 
373
331
  ## License
374
332
 
375
- MIT — [cocaxcode](https://github.com/cocaxcode)
333
+ [MIT](./LICENSE)built by [cocaxcode](https://github.com/cocaxcode)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocaxcode/api-testing-mcp",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "MCP server para testing de APIs. Ligero, local, sin dependencias cloud.",
5
5
  "type": "module",
6
6
  "bin": {