@cocaxcode/api-testing-mcp 0.5.0 → 0.5.2

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
@@ -1,27 +1,26 @@
1
1
  <p align="center">
2
2
  <h1 align="center">@cocaxcode/api-testing-mcp</h1>
3
3
  <p align="center">
4
- A complete API testing toolkit built for AI coding agents.<br/>
4
+ <strong>A complete API testing toolkit built for AI coding agents.</strong><br/>
5
5
  Test, validate, mock, and load-test your APIs — all from natural language.
6
6
  </p>
7
7
  </p>
8
8
 
9
9
  <p align="center">
10
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>
11
+ <a href="https://www.npmjs.com/package/@cocaxcode/api-testing-mcp"><img src="https://img.shields.io/npm/dm/@cocaxcode/api-testing-mcp.svg?style=flat-square" alt="npm downloads" /></a>
12
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
13
  <img src="https://img.shields.io/badge/node-%3E%3D20-339933?style=flat-square&logo=node.js&logoColor=white" alt="Node" />
16
14
  </p>
17
15
 
18
16
  <p align="center">
19
- <a href="#installation">Installation</a>
20
- <a href="#just-talk-to-it">Just Talk to It</a>
21
- <a href="#works-with-any-api">Any API</a>
22
- <a href="#features">Features</a>
23
- <a href="#tool-reference">Tool Reference</a>
24
- <a href="#storage">Storage</a>
17
+ <a href="#installation">Installation</a> &middot;
18
+ <a href="#just-talk-to-it">Just Talk to It</a> &middot;
19
+ <a href="#works-with-any-api">Any API</a> &middot;
20
+ <a href="#features">Features</a> &middot;
21
+ <a href="#tool-reference">Tool Reference</a> &middot;
22
+ <a href="#storage">Storage</a> &middot;
23
+ <a href="#limitations">Limitations</a> &middot;
25
24
  <a href="#contributing">Contributing</a>
26
25
  </p>
27
26
 
@@ -35,6 +34,73 @@ You describe what you need. The AI figures out the rest.
35
34
 
36
35
  No cloud accounts. No subscriptions. Everything runs locally and stores data as plain JSON files you can commit to git.
37
36
 
37
+ **Requires** an MCP-compatible client such as [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Claude Desktop](https://claude.ai/download), or [Cursor](https://cursor.sh). This is not a standalone CLI tool — it extends your AI assistant with API testing capabilities.
38
+
39
+ ---
40
+
41
+ ## Installation
42
+
43
+ ### Claude Code
44
+
45
+ ```bash
46
+ claude mcp add api-testing -- npx -y @cocaxcode/api-testing-mcp
47
+ ```
48
+
49
+ ### Claude Desktop
50
+
51
+ Add to your config file:
52
+
53
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
54
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "api-testing": {
60
+ "command": "npx",
61
+ "args": ["-y", "@cocaxcode/api-testing-mcp"]
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ ### Cursor
68
+
69
+ Add to `.cursor/mcp.json` in your project root (or `~/.cursor/mcp.json` for global):
70
+
71
+ ```json
72
+ {
73
+ "mcpServers": {
74
+ "api-testing": {
75
+ "command": "npx",
76
+ "args": ["-y", "@cocaxcode/api-testing-mcp"]
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### Quick start
83
+
84
+ Once installed, set up an environment so the tool knows where your API lives:
85
+
86
+ ```
87
+ "Create an environment called dev with BASE_URL http://localhost:3000"
88
+ ```
89
+
90
+ From here, relative paths work automatically. `/api/users` becomes `http://localhost:3000/api/users`.
91
+
92
+ If your API has Swagger/OpenAPI, import the spec:
93
+
94
+ ```
95
+ "Import my API spec from http://localhost:3000/api-docs-json"
96
+ ```
97
+
98
+ Now the AI knows every endpoint, parameter, and schema in your API. You're ready to go.
99
+
100
+ To verify the installation is working, try: *"List my environments"* — it should show the one you just created.
101
+
102
+ Available on [npm](https://www.npmjs.com/package/@cocaxcode/api-testing-mcp).
103
+
38
104
  ---
39
105
 
40
106
  ## Just Talk to It
@@ -114,75 +180,20 @@ You: "Save this request as cf-list-zones with tag cloudflare"
114
180
 
115
181
  Every request, collection, and spec is isolated per environment. Your Cloudflare tests don't mix with your local backend tests.
116
182
 
117
- ### What the storage looks like
118
-
119
- ```
120
- .api-testing/
121
- ├── active-env # Currently active: "cloudflare"
122
- ├── environments/
123
- │ ├── github.json # { BASE_URL, GITHUB_TOKEN }
124
- │ ├── cloudflare.json # { BASE_URL, API_KEY }
125
- │ ├── dokploy.json # { BASE_URL, TOKEN }
126
- │ └── my-backend.json # { BASE_URL, TOKEN }
127
- ├── specs/
128
- │ ├── dokploy.json # Imported OpenAPI spec
129
- │ └── my-backend.json # Imported OpenAPI spec
130
- └── collections/
131
- ├── cf-list-zones.json # Saved requests per API
132
- ├── gh-my-repos.json
133
- └── dok-list-projects.json
134
- ```
135
-
136
183
  ---
137
184
 
138
- ## Installation
139
-
140
- ### Claude Code
141
-
142
- ```bash
143
- claude mcp add api-testing -- npx -y @cocaxcode/api-testing-mcp
144
- ```
145
-
146
- ### Claude Desktop / Cursor / Any MCP Client
147
-
148
- Add to your MCP configuration file:
149
-
150
- ```json
151
- {
152
- "mcpServers": {
153
- "api-testing": {
154
- "command": "npx",
155
- "args": ["-y", "@cocaxcode/api-testing-mcp"]
156
- }
157
- }
158
- }
159
- ```
160
-
161
- ### First steps
162
-
163
- Set up an environment so the tool knows where your API lives:
164
-
165
- ```
166
- "Create an environment called dev with BASE_URL http://localhost:3000"
167
- ```
185
+ ## Features
168
186
 
169
- From here, relative paths work automatically. `/api/users` becomes `http://localhost:3000/api/users`.
187
+ ### HTTP Requests
170
188
 
171
- If your API has Swagger/OpenAPI, import the spec:
189
+ Send any request by describing what you need. The AI resolves relative URLs, injects environment variables, and handles authentication automatically.
172
190
 
173
191
  ```
174
- "Import my API spec from http://localhost:3000/api-docs-json"
192
+ "POST to /api/users with name Jane and email jane@company.com using my bearer token"
175
193
  ```
176
194
 
177
- Now the AI knows every endpoint, parameter, and schema in your API. You're ready to go.
178
-
179
- ---
180
-
181
- ## Features
182
-
183
- ### HTTP Requests
184
-
185
- 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.
195
+ <details>
196
+ <summary>What the tool executes</summary>
186
197
 
187
198
  ```
188
199
  request({
@@ -192,39 +203,39 @@ request({
192
203
  auth: { type: "bearer", token: "{{TOKEN}}" }
193
204
  })
194
205
  ```
206
+ </details>
195
207
 
196
- **Supports:** GET · POST · PUT · PATCH · DELETE · HEAD · OPTIONS — Headers · Query params · JSON body · Bearer / API Key / Basic auth · Timeout · `{{variable}}` interpolation
208
+ **Supports:** GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS — Headers, query params, JSON body, Bearer / API Key / Basic auth, timeout, `{{variable}}` interpolation.
197
209
 
198
210
  ### Assertions
199
211
 
200
- Run a request and validate the response against a set of rules in one step. Get structured pass/fail results.
212
+ Validate API responses against a set of rules in one step. Get structured pass/fail results.
201
213
 
202
214
  ```
203
- assert({
204
- method: "GET",
205
- url: "/api/health",
206
- assertions: [
207
- { path: "status", operator: "eq", expected: 200 },
208
- { path: "body.status", operator: "eq", expected: "ok" },
209
- { path: "timing.total_ms", operator: "lt", expected: 500 }
210
- ]
211
- })
215
+ "Verify that GET /api/health returns 200, body.status is ok, and responds in under 500ms"
212
216
  ```
213
217
 
214
218
  ```
215
- PASS — 3/3 assertions passed
219
+ PASS — 3/3 assertions passed
216
220
  GET /api/health → 200 OK (42ms)
217
221
 
218
- status === 200
219
- body.status === "ok"
220
- timing.total_ms < 500
222
+ status === 200
223
+ body.status === "ok"
224
+ timing.total_ms < 500
221
225
  ```
222
226
 
223
- **Operators:** `eq` · `neq` · `gt` · `gte` · `lt` · `lte` · `contains` · `not_contains` · `exists` · `type`
227
+ **Operators:** `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `contains`, `not_contains`, `exists`, `type`
224
228
 
225
229
  ### Request Flows
226
230
 
227
- 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.
231
+ Chain multiple requests together. Extract values from one response and inject them into the next step. Perfect for auth flows, CRUD sequences, and multi-step testing.
232
+
233
+ ```
234
+ "Login as admin@test.com, extract the access token, then use it to fetch all users"
235
+ ```
236
+
237
+ <details>
238
+ <summary>What the tool executes</summary>
228
239
 
229
240
  ```
230
241
  flow_run({
@@ -233,7 +244,7 @@ flow_run({
233
244
  name: "login",
234
245
  method: "POST",
235
246
  url: "/auth/login",
236
- body: { email: "admin@test.com", password: "123456" },
247
+ body: { email: "admin@test.com", password: "SecurePass#99" },
237
248
  extract: { "TOKEN": "body.access_token" }
238
249
  },
239
250
  {
@@ -245,23 +256,24 @@ flow_run({
245
256
  ]
246
257
  })
247
258
  ```
259
+ </details>
248
260
 
249
261
  ### OpenAPI Import
250
262
 
251
263
  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.
252
264
 
253
265
  ```
254
- api_import({ name: "my-backend", source: "http://localhost:3000/api-docs-json" })
255
- api_endpoints({ name: "my-backend", tag: "users" })
256
- api_endpoint_detail({ name: "my-backend", method: "POST", path: "/users" })
266
+ "Import my API spec from http://localhost:3000/api-docs-json"
267
+ "Show me all user endpoints"
268
+ "What parameters does POST /users expect?"
257
269
  ```
258
270
 
259
271
  ### Mock Data Generation
260
272
 
261
- Generate realistic fake data from your OpenAPI spec. Respects types, formats (`email`, `uuid`, `date-time`), enums, and required fields. Use `count` for arrays.
273
+ Generate realistic fake data from your OpenAPI spec. Respects types, formats (`email`, `uuid`, `date-time`), enums, and required fields.
262
274
 
263
275
  ```
264
- mock({ name: "my-backend", method: "POST", path: "/users", target: "request" })
276
+ "Generate mock data for creating a user"
265
277
  ```
266
278
 
267
279
  ```json
@@ -278,17 +290,17 @@ mock({ name: "my-backend", method: "POST", path: "/users", target: "request" })
278
290
  Fire N concurrent requests and get performance metrics: min, avg, percentiles (p50/p95/p99), max, and requests per second.
279
291
 
280
292
  ```
281
- load_test({ method: "GET", url: "/api/health", concurrent: 50 })
293
+ "How fast is the health endpoint with 50 concurrent requests?"
282
294
  ```
283
295
 
284
296
  ```
285
- 📊 LOAD TEST — GET /api/health
297
+ LOAD TEST — GET /api/health
286
298
 
287
299
  Requests: 50 concurrent
288
300
  Successful: 50 | Failed: 0
289
301
  Requests/sec: 23.31
290
302
 
291
- ⏱️ Response times:
303
+ Response times:
292
304
  Min: 45ms | Avg: 187ms
293
305
  p50: 156ms | p95: 412ms
294
306
  p99: 523ms | Max: 567ms
@@ -296,13 +308,10 @@ Requests/sec: 23.31
296
308
 
297
309
  ### Response Diffing
298
310
 
299
- Execute two requests and compare their responses field by field. Detect regressions or compare environments (dev vs prod).
311
+ Execute two requests and compare their responses field by field. Detect regressions or compare environments.
300
312
 
301
313
  ```
302
- diff_responses({
303
- request_a: { label: "dev", method: "GET", url: "http://dev.api.com/users" },
304
- request_b: { label: "prod", method: "GET", url: "http://prod.api.com/users" }
305
- })
314
+ "Compare the users endpoint between dev and prod"
306
315
  ```
307
316
 
308
317
  ### Bulk Testing
@@ -310,21 +319,25 @@ diff_responses({
310
319
  Run every saved request in your collection (or filter by tag) and get a pass/fail summary.
311
320
 
312
321
  ```
313
- bulk_test({ tag: "smoke" })
322
+ "Run all my saved smoke tests"
314
323
  ```
315
324
 
316
325
  ```
317
- BULK TEST — 8/8 passed | 1.2s total
326
+ BULK TEST — 8/8 passed | 1.2s total
318
327
 
319
- health — GET /health → 200 (45ms)
320
- list-users — GET /users → 200 (123ms)
321
- create-post — POST /blog → 201 (89ms)
322
- login — POST /auth/login → 200 (156ms)
328
+ health — GET /health → 200 (45ms)
329
+ list-users — GET /users → 200 (123ms)
330
+ create-post — POST /blog → 201 (89ms)
331
+ login — POST /auth/login → 200 (156ms)
323
332
  ```
324
333
 
325
334
  ### cURL Export
326
335
 
327
- Convert any saved request into a cURL command with resolved variables.
336
+ Convert any saved request into a ready-to-paste cURL command with resolved variables.
337
+
338
+ ```
339
+ "Export the create-user request as curl"
340
+ ```
328
341
 
329
342
  ```bash
330
343
  curl -X POST \
@@ -334,7 +347,7 @@ curl -X POST \
334
347
  -d '{"name":"Jane","email":"jane@company.com"}'
335
348
  ```
336
349
 
337
- ### Collections & Environments
350
+ ### Collections and Environments
338
351
 
339
352
  Save requests for reuse (with tags), manage variables across environments (dev/staging/prod), and switch contexts instantly.
340
353
 
@@ -349,11 +362,13 @@ Save requests for reuse (with tags), manage variables across environments (dev/s
349
362
  | **Requests** | `request` | 1 |
350
363
  | **Testing** | `assert` | 1 |
351
364
  | **Flows** | `flow_run` | 1 |
352
- | **Collections** | `collection_save` · `collection_list` · `collection_get` · `collection_delete` | 4 |
353
- | **Environments** | `env_create` · `env_list` · `env_set` · `env_get` · `env_switch` | 5 |
354
- | **API Specs** | `api_import` · `api_endpoints` · `api_endpoint_detail` | 3 |
365
+ | **Collections** | `collection_save` `collection_list` `collection_get` `collection_delete` | 4 |
366
+ | **Environments** | `env_create` `env_list` `env_set` `env_get` `env_switch` | 5 |
367
+ | **API Specs** | `api_import` `api_endpoints` `api_endpoint_detail` | 3 |
355
368
  | **Mock** | `mock` | 1 |
356
- | **Utilities** | `load_test` · `export_curl` · `diff_responses` · `bulk_test` | 4 |
369
+ | **Utilities** | `load_test` `export_curl` `diff_responses` `bulk_test` | 4 |
370
+
371
+ You don't need to call these tools directly. Just describe what you want and the AI picks the right one.
357
372
 
358
373
  ---
359
374
 
@@ -369,7 +384,7 @@ All data lives in `.api-testing/` as plain JSON — no database, no cloud sync:
369
384
  └── specs/ # Imported OpenAPI specs
370
385
  ```
371
386
 
372
- Override the default directory:
387
+ Override the default directory in your MCP config:
373
388
 
374
389
  ```json
375
390
  {
@@ -377,7 +392,17 @@ Override the default directory:
377
392
  }
378
393
  ```
379
394
 
380
- Commit these files to git to share across your team.
395
+ Commit these files to git to share API configurations across your team.
396
+
397
+ ---
398
+
399
+ ## Limitations
400
+
401
+ - **Auth**: Supports Bearer token, API Key, and Basic auth. OAuth 2.0 flows (authorization code, PKCE) are not supported — use a pre-obtained token instead.
402
+ - **Protocols**: HTTP/HTTPS only. No WebSocket, gRPC, or GraphQL-specific support (though GraphQL over HTTP works fine).
403
+ - **Load testing**: Recommended maximum of 100 concurrent requests. This is a testing tool, not a benchmarking framework.
404
+ - **Specs**: OpenAPI 3.x only. OpenAPI 2.0 (Swagger) is partially supported. AsyncAPI is not supported.
405
+ - **Storage**: Local JSON files only. No built-in cloud sync or team collaboration server.
381
406
 
382
407
  ---
383
408
 
@@ -398,7 +423,13 @@ npm run typecheck # Strict TypeScript
398
423
  npx @modelcontextprotocol/inspector node dist/index.js
399
424
  ```
400
425
 
401
- **Stack:** TypeScript · MCP SDK 1.27 · Zod · Vitest · tsup
426
+ **Stack:** TypeScript &middot; MCP SDK 1.27 &middot; Zod &middot; Vitest &middot; tsup
427
+
428
+ ### How to contribute
429
+
430
+ - **Bug reports**: [Open an issue](https://github.com/cocaxcode/api-testing-mcp/issues) with steps to reproduce, expected vs actual behavior, and your Node.js version.
431
+ - **Feature requests**: Open an issue describing the use case. Include examples of how you'd use it in natural language.
432
+ - **Pull requests**: Fork, create a branch, make your changes, ensure `npm test` and `npm run typecheck` pass, then open a PR.
402
433
 
403
434
  ---
404
435
 
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
- #!/usr/bin/env node
1
+
2
+ export { }
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- #!/usr/bin/env node
3
2
 
4
3
  // src/index.ts
5
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/lib/storage.ts","../src/tools/request.ts","../src/lib/http-client.ts","../src/lib/interpolation.ts","../src/tools/collection.ts","../src/tools/environment.ts","../src/tools/api-spec.ts","../src/lib/openapi-parser.ts","../src/tools/assert.ts","../src/tools/flow.ts","../src/tools/utilities.ts","../src/tools/mock.ts","../src/tools/load-test.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { createServer } from './server.js'\n\nasync function main() {\n const server = createServer()\n const transport = new StdioServerTransport()\n await server.connect(transport)\n console.error('api-testing-mcp server running on stdio')\n}\n\nmain().catch((error) => {\n console.error('Fatal:', error)\n process.exit(1)\n})\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { Storage } from './lib/storage.js'\nimport { registerRequestTool } from './tools/request.js'\nimport { registerCollectionTools } from './tools/collection.js'\nimport { registerEnvironmentTools } from './tools/environment.js'\nimport { registerApiSpecTools } from './tools/api-spec.js'\nimport { registerAssertTool } from './tools/assert.js'\nimport { registerFlowTool } from './tools/flow.js'\nimport { registerUtilityTools } from './tools/utilities.js'\nimport { registerMockTool } from './tools/mock.js'\nimport { registerLoadTestTool } from './tools/load-test.js'\n\n// Leer version del package.json en build time no es posible con ESM fácilmente,\n// así que la definimos como constante sincronizada manualmente.\nconst VERSION = '0.4.0'\n\n/**\n * Crea y configura el MCP server con todos los tools registrados.\n * Exportada como factory para testabilidad con InMemoryTransport.\n */\nexport function createServer(storageDir?: string): McpServer {\n const server = new McpServer({\n name: 'api-testing-mcp',\n version: VERSION,\n })\n\n const storage = new Storage(storageDir)\n\n // Registrar tools\n registerRequestTool(server, storage)\n registerCollectionTools(server, storage)\n registerEnvironmentTools(server, storage)\n registerApiSpecTools(server, storage)\n registerAssertTool(server, storage)\n registerFlowTool(server, storage)\n registerUtilityTools(server, storage)\n registerMockTool(server, storage)\n registerLoadTestTool(server, storage)\n\n return server\n}\n","import { mkdir, readFile, writeFile, readdir, unlink } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type {\n SavedRequest,\n CollectionListItem,\n Environment,\n EnvironmentListItem,\n ApiSpec,\n ApiSpecListItem,\n} from './types.js'\n\nexport class Storage {\n private readonly baseDir: string\n private readonly collectionsDir: string\n private readonly environmentsDir: string\n private readonly specsDir: string\n private readonly activeEnvFile: string\n\n constructor(baseDir?: string) {\n this.baseDir = baseDir ?? process.env.API_TESTING_DIR ?? join(process.cwd(), '.api-testing')\n this.collectionsDir = join(this.baseDir, 'collections')\n this.environmentsDir = join(this.baseDir, 'environments')\n this.specsDir = join(this.baseDir, 'specs')\n this.activeEnvFile = join(this.baseDir, 'active-env')\n }\n\n // ── Collections ──\n\n async saveCollection(saved: SavedRequest): Promise<void> {\n await this.ensureDir('collections')\n const filePath = join(this.collectionsDir, `${this.sanitizeName(saved.name)}.json`)\n await this.writeJson(filePath, saved)\n }\n\n async getCollection(name: string): Promise<SavedRequest | null> {\n const filePath = join(this.collectionsDir, `${this.sanitizeName(name)}.json`)\n return this.readJson<SavedRequest>(filePath)\n }\n\n async listCollections(tag?: string): Promise<CollectionListItem[]> {\n await this.ensureDir('collections')\n const files = await this.listJsonFiles(this.collectionsDir)\n const items: CollectionListItem[] = []\n\n for (const file of files) {\n const saved = await this.readJson<SavedRequest>(join(this.collectionsDir, file))\n if (!saved) continue\n\n if (tag && !(saved.tags ?? []).includes(tag)) continue\n\n items.push({\n name: saved.name,\n method: saved.request.method,\n url: saved.request.url,\n tags: saved.tags ?? [],\n })\n }\n\n return items\n }\n\n async deleteCollection(name: string): Promise<boolean> {\n const filePath = join(this.collectionsDir, `${this.sanitizeName(name)}.json`)\n try {\n await unlink(filePath)\n return true\n } catch {\n return false\n }\n }\n\n // ── Environments ──\n\n async createEnvironment(env: Environment): Promise<void> {\n await this.ensureDir('environments')\n const filePath = join(this.environmentsDir, `${this.sanitizeName(env.name)}.json`)\n await this.writeJson(filePath, env)\n }\n\n async getEnvironment(name: string): Promise<Environment | null> {\n const filePath = join(this.environmentsDir, `${this.sanitizeName(name)}.json`)\n return this.readJson<Environment>(filePath)\n }\n\n async listEnvironments(): Promise<EnvironmentListItem[]> {\n await this.ensureDir('environments')\n const files = await this.listJsonFiles(this.environmentsDir)\n const activeEnv = await this.getActiveEnvironment()\n const items: EnvironmentListItem[] = []\n\n for (const file of files) {\n const env = await this.readJson<Environment>(join(this.environmentsDir, file))\n if (!env) continue\n\n items.push({\n name: env.name,\n active: env.name === activeEnv,\n variableCount: Object.keys(env.variables).length,\n })\n }\n\n return items\n }\n\n async updateEnvironment(name: string, variables: Record<string, string>): Promise<void> {\n const env = await this.getEnvironment(name)\n if (!env) {\n throw new Error(`Entorno '${name}' no encontrado`)\n }\n\n env.variables = { ...env.variables, ...variables }\n env.updatedAt = new Date().toISOString()\n\n const filePath = join(this.environmentsDir, `${this.sanitizeName(name)}.json`)\n await this.writeJson(filePath, env)\n }\n\n async getActiveEnvironment(): Promise<string | null> {\n try {\n const content = await readFile(this.activeEnvFile, 'utf-8')\n return content.trim() || null\n } catch {\n return null\n }\n }\n\n async setActiveEnvironment(name: string): Promise<void> {\n // Verificar que el entorno existe\n const env = await this.getEnvironment(name)\n if (!env) {\n throw new Error(`Entorno '${name}' no encontrado`)\n }\n\n await this.ensureDir('')\n await writeFile(this.activeEnvFile, name, 'utf-8')\n }\n\n /**\n * Carga las variables del entorno activo.\n * Retorna objeto vacío si no hay entorno activo.\n */\n async getActiveVariables(): Promise<Record<string, string>> {\n const activeName = await this.getActiveEnvironment()\n if (!activeName) return {}\n\n const env = await this.getEnvironment(activeName)\n return env?.variables ?? {}\n }\n\n // ── API Specs ──\n\n async saveSpec(spec: ApiSpec): Promise<void> {\n await this.ensureDir('specs')\n const filePath = join(this.specsDir, `${this.sanitizeName(spec.name)}.json`)\n await this.writeJson(filePath, spec)\n }\n\n async getSpec(name: string): Promise<ApiSpec | null> {\n const filePath = join(this.specsDir, `${this.sanitizeName(name)}.json`)\n return this.readJson<ApiSpec>(filePath)\n }\n\n async listSpecs(): Promise<ApiSpecListItem[]> {\n await this.ensureDir('specs')\n const files = await this.listJsonFiles(this.specsDir)\n const items: ApiSpecListItem[] = []\n\n for (const file of files) {\n const spec = await this.readJson<ApiSpec>(join(this.specsDir, file))\n if (!spec) continue\n\n items.push({\n name: spec.name,\n source: spec.source,\n endpointCount: spec.endpoints.length,\n version: spec.version,\n })\n }\n\n return items\n }\n\n async deleteSpec(name: string): Promise<boolean> {\n const filePath = join(this.specsDir, `${this.sanitizeName(name)}.json`)\n try {\n await unlink(filePath)\n return true\n } catch {\n return false\n }\n }\n\n // ── Internal ──\n\n private async ensureDir(subdir: string): Promise<void> {\n const dir = subdir ? join(this.baseDir, subdir) : this.baseDir\n await mkdir(dir, { recursive: true })\n }\n\n private async readJson<T>(filePath: string): Promise<T | null> {\n try {\n const content = await readFile(filePath, 'utf-8')\n return JSON.parse(content) as T\n } catch {\n return null\n }\n }\n\n private async writeJson(filePath: string, data: unknown): Promise<void> {\n await writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8')\n }\n\n private async listJsonFiles(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir)\n return entries.filter((f) => f.endsWith('.json')).sort()\n } catch {\n return []\n }\n }\n\n /**\n * Sanitiza un nombre para usarlo como nombre de archivo.\n * Reemplaza caracteres no alfanuméricos por guiones.\n */\n private sanitizeName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9_-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n }\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { executeRequest } from '../lib/http-client.js'\nimport { interpolateRequest } from '../lib/interpolation.js'\nimport type { RequestConfig } from '../lib/types.js'\n\nconst AuthSchema = {\n type: z.enum(['bearer', 'api-key', 'basic']).describe('Tipo de autenticación'),\n token: z.string().optional().describe('Token para Bearer auth'),\n key: z.string().optional().describe('API key value'),\n header: z.string().optional().describe('Header name para API key (default: X-API-Key)'),\n username: z.string().optional().describe('Username para Basic auth'),\n password: z.string().optional().describe('Password para Basic auth'),\n}\n\nexport function registerRequestTool(server: McpServer, storage: Storage): void {\n server.tool(\n 'request',\n 'Ejecuta un HTTP request. URLs relativas (/path) usan BASE_URL del entorno activo. Soporta {{variables}}.',\n {\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('HTTP method'),\n url: z\n .string()\n .describe(\n 'URL del endpoint. Si empieza con / se antepone BASE_URL del entorno activo. Soporta {{variables}}.',\n ),\n headers: z\n .record(z.string())\n .optional()\n .describe('Headers HTTP como key-value pairs'),\n body: z.any().optional().describe('Body del request (JSON). Soporta {{variables}}'),\n query: z\n .record(z.string())\n .optional()\n .describe('Query parameters como key-value pairs'),\n timeout: z.number().optional().describe('Timeout en milisegundos (default: 30000)'),\n auth: z\n .object(AuthSchema)\n .optional()\n .describe('Configuración de autenticación'),\n },\n async (params) => {\n try {\n // Cargar variables del entorno activo\n const variables = await storage.getActiveVariables()\n\n // Auto-prepend BASE_URL para URLs relativas (empiezan con /)\n let resolvedUrl = params.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n // Quitar trailing slash de BASE_URL para evitar doble slash\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n // Construir RequestConfig\n const config: RequestConfig = {\n method: params.method,\n url: resolvedUrl,\n headers: params.headers,\n body: params.body,\n query: params.query,\n timeout: params.timeout,\n auth: params.auth,\n }\n\n // Interpolar variables\n const interpolated = interpolateRequest(config, variables)\n\n // Ejecutar request\n const response = await executeRequest(interpolated)\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(response, null, 2),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import type { RequestConfig, RequestResponse, AuthConfig } from './types.js'\n\nconst DEFAULT_TIMEOUT = 30_000\n\n/**\n * Aplica la configuración de auth a los headers del request.\n */\nfunction applyAuth(\n headers: Record<string, string>,\n auth: AuthConfig,\n): Record<string, string> {\n const result = { ...headers }\n\n switch (auth.type) {\n case 'bearer':\n if (auth.token) {\n result['Authorization'] = `Bearer ${auth.token}`\n }\n break\n\n case 'api-key':\n if (auth.key) {\n const headerName = auth.header ?? 'X-API-Key'\n result[headerName] = auth.key\n }\n break\n\n case 'basic':\n if (auth.username && auth.password) {\n const credentials = Buffer.from(`${auth.username}:${auth.password}`).toString('base64')\n result['Authorization'] = `Basic ${credentials}`\n }\n break\n }\n\n return result\n}\n\n/**\n * Construye la URL final con query parameters.\n */\nfunction buildUrl(baseUrl: string, query?: Record<string, string>): string {\n const url = new URL(baseUrl)\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n url.searchParams.set(key, value)\n }\n }\n\n return url.toString()\n}\n\n/**\n * Ejecuta un HTTP request y retorna la respuesta con métricas de timing.\n */\nexport async function executeRequest(config: RequestConfig): Promise<RequestResponse> {\n const timeout = config.timeout ?? DEFAULT_TIMEOUT\n\n // Construir URL con query params\n const url = buildUrl(config.url, config.query)\n\n // Preparar headers\n let headers: Record<string, string> = { ...config.headers }\n\n // Aplicar auth\n if (config.auth) {\n headers = applyAuth(headers, config.auth)\n }\n\n // Preparar body\n let body: string | undefined\n if (config.body !== undefined && config.body !== null) {\n if (typeof config.body === 'string') {\n body = config.body\n } else {\n body = JSON.stringify(config.body)\n // Solo añadir Content-Type si no está definido\n if (!headers['Content-Type'] && !headers['content-type']) {\n headers['Content-Type'] = 'application/json'\n }\n }\n }\n\n // AbortController para timeout\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n // Medir timing\n const startTime = performance.now()\n\n try {\n const response = await fetch(url, {\n method: config.method,\n headers,\n body,\n signal: controller.signal,\n })\n\n const endTime = performance.now()\n const totalMs = Math.round((endTime - startTime) * 100) / 100\n\n // Parsear response body\n const responseText = await response.text()\n let responseBody: unknown\n try {\n responseBody = JSON.parse(responseText)\n } catch {\n responseBody = responseText\n }\n\n // Convertir headers a Record\n const responseHeaders: Record<string, string> = {}\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value\n })\n\n // Calcular tamaño\n const sizeBytes =\n Number(response.headers.get('content-length')) ||\n Buffer.byteLength(responseText, 'utf-8')\n\n return {\n status: response.status,\n statusText: response.statusText,\n headers: responseHeaders,\n body: responseBody,\n timing: { total_ms: totalMs },\n size_bytes: sizeBytes,\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n throw new Error(`Request timeout: superado el límite de ${timeout}ms`)\n }\n throw error\n } finally {\n clearTimeout(timeoutId)\n }\n}\n","import type { RequestConfig } from './types.js'\n\nconst VARIABLE_PATTERN = /\\{\\{(\\w+)\\}\\}/g\n\n/**\n * Resuelve todas las ocurrencias de {{variable}} en un string.\n * Las variables no encontradas se dejan intactas.\n */\nexport function interpolateString(\n template: string,\n variables: Record<string, string>,\n): string {\n return template.replace(VARIABLE_PATTERN, (match, varName: string) => {\n return varName in variables ? variables[varName] : match\n })\n}\n\n/**\n * Interpola {{variables}} recursivamente en un valor.\n * - string → interpolateString\n * - object → interpola cada valor (recursivo)\n * - array → interpola cada elemento\n * - otros tipos → retorna sin cambios\n */\nfunction interpolateValue(value: unknown, variables: Record<string, string>): unknown {\n if (typeof value === 'string') {\n return interpolateString(value, variables)\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => interpolateValue(item, variables))\n }\n\n if (value !== null && typeof value === 'object') {\n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value)) {\n result[key] = interpolateValue(val, variables)\n }\n return result\n }\n\n return value\n}\n\n/**\n * Interpola un Record<string, string> (headers, query params).\n * Solo interpola los valores, no las keys.\n */\nfunction interpolateRecord(\n record: Record<string, string> | undefined,\n variables: Record<string, string>,\n): Record<string, string> | undefined {\n if (!record) return undefined\n\n const result: Record<string, string> = {}\n for (const [key, value] of Object.entries(record)) {\n result[key] = interpolateString(value, variables)\n }\n return result\n}\n\n/**\n * Resuelve {{variables}} en todos los campos de un RequestConfig:\n * url, headers (valores), body (recursivo), query params (valores).\n */\nexport function interpolateRequest(\n config: RequestConfig,\n variables: Record<string, string>,\n): RequestConfig {\n return {\n ...config,\n url: interpolateString(config.url, variables),\n headers: interpolateRecord(config.headers, variables),\n query: interpolateRecord(config.query, variables),\n body: config.body !== undefined ? interpolateValue(config.body, variables) : undefined,\n }\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport type { SavedRequest } from '../lib/types.js'\n\nconst AuthSchema = {\n type: z.enum(['bearer', 'api-key', 'basic']).describe('Tipo de autenticación'),\n token: z.string().optional().describe('Token para Bearer auth'),\n key: z.string().optional().describe('API key value'),\n header: z.string().optional().describe('Header name para API key (default: X-API-Key)'),\n username: z.string().optional().describe('Username para Basic auth'),\n password: z.string().optional().describe('Password para Basic auth'),\n}\n\nexport function registerCollectionTools(server: McpServer, storage: Storage): void {\n // ── collection_save ──\n server.tool(\n 'collection_save',\n 'Guarda un request en la colección local. Si ya existe un request con el mismo nombre, lo sobreescribe.',\n {\n name: z.string().describe('Nombre único del request guardado'),\n request: z\n .object({\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']),\n url: z.string(),\n headers: z.record(z.string()).optional(),\n body: z.any().optional(),\n query: z.record(z.string()).optional(),\n auth: z.object(AuthSchema).optional(),\n })\n .describe('Configuración del request a guardar'),\n tags: z\n .array(z.string())\n .optional()\n .describe('Tags para organizar (ej: [\"auth\", \"users\"])'),\n },\n async (params) => {\n try {\n const now = new Date().toISOString()\n const existing = await storage.getCollection(params.name)\n\n const saved: SavedRequest = {\n name: params.name,\n request: params.request,\n tags: params.tags,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n }\n\n await storage.saveCollection(saved)\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Request '${params.name}' guardado (${params.request.method} ${params.request.url})`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── collection_list ──\n server.tool(\n 'collection_list',\n 'Lista todos los requests guardados en la colección. Opcionalmente filtra por tag.',\n {\n tag: z.string().optional().describe('Filtrar por tag'),\n },\n async (params) => {\n try {\n const items = await storage.listCollections(params.tag)\n\n if (items.length === 0) {\n const msg = params.tag\n ? `No hay requests con tag '${params.tag}'`\n : 'La colección está vacía'\n return { content: [{ type: 'text' as const, text: msg }] }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(items, null, 2),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── collection_get ──\n server.tool(\n 'collection_get',\n 'Obtiene los detalles completos de un request guardado por su nombre.',\n {\n name: z.string().describe('Nombre del request guardado'),\n },\n async (params) => {\n try {\n const saved = await storage.getCollection(params.name)\n\n if (!saved) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Request '${params.name}' no encontrado`,\n },\n ],\n isError: true,\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(saved, null, 2),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── collection_delete ──\n server.tool(\n 'collection_delete',\n 'Elimina un request guardado de la colección.',\n {\n name: z.string().describe('Nombre del request a eliminar'),\n },\n async (params) => {\n try {\n const deleted = await storage.deleteCollection(params.name)\n\n if (!deleted) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Request '${params.name}' no encontrado`,\n },\n ],\n isError: true,\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Request '${params.name}' eliminado`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport type { Environment } from '../lib/types.js'\n\nexport function registerEnvironmentTools(server: McpServer, storage: Storage): void {\n // ── env_create ──\n server.tool(\n 'env_create',\n 'Crea un nuevo entorno (ej: dev, staging, prod) con variables opcionales.',\n {\n name: z.string().describe('Nombre del entorno (ej: dev, staging, prod)'),\n variables: z\n .record(z.string())\n .optional()\n .describe('Variables iniciales como key-value'),\n },\n async (params) => {\n try {\n const now = new Date().toISOString()\n const env: Environment = {\n name: params.name,\n variables: params.variables ?? {},\n createdAt: now,\n updatedAt: now,\n }\n\n await storage.createEnvironment(env)\n\n const varCount = Object.keys(env.variables).length\n return {\n content: [\n {\n type: 'text' as const,\n text: `Entorno '${params.name}' creado con ${varCount} variable(s)`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── env_list ──\n server.tool(\n 'env_list',\n 'Lista todos los entornos disponibles e indica cuál está activo.',\n {},\n async () => {\n try {\n const items = await storage.listEnvironments()\n\n if (items.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No hay entornos configurados' }],\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(items, null, 2),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── env_set ──\n server.tool(\n 'env_set',\n 'Establece una variable en un entorno. Si no se especifica entorno, usa el activo.',\n {\n key: z.string().describe('Nombre de la variable'),\n value: z.string().describe('Valor de la variable'),\n environment: z\n .string()\n .optional()\n .describe('Entorno destino (default: entorno activo)'),\n },\n async (params) => {\n try {\n // Determinar entorno destino\n const envName = params.environment ?? (await storage.getActiveEnvironment())\n\n if (!envName) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'No hay entorno activo. Usa env_create para crear uno y env_switch para activarlo.',\n },\n ],\n isError: true,\n }\n }\n\n await storage.updateEnvironment(envName, { [params.key]: params.value })\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Variable '${params.key}' establecida en entorno '${envName}'`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── env_get ──\n server.tool(\n 'env_get',\n 'Obtiene una variable específica o todas las variables de un entorno.',\n {\n key: z\n .string()\n .optional()\n .describe('Variable específica. Si se omite, retorna todas'),\n environment: z\n .string()\n .optional()\n .describe('Entorno a consultar (default: entorno activo)'),\n },\n async (params) => {\n try {\n const envName = params.environment ?? (await storage.getActiveEnvironment())\n\n if (!envName) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'No hay entorno activo. Usa env_switch para activar uno.',\n },\n ],\n isError: true,\n }\n }\n\n const env = await storage.getEnvironment(envName)\n if (!env) {\n return {\n content: [\n { type: 'text' as const, text: `Entorno '${envName}' no encontrado` },\n ],\n isError: true,\n }\n }\n\n if (params.key) {\n const value = env.variables[params.key]\n if (value === undefined) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Variable '${params.key}' no encontrada en entorno '${envName}'`,\n },\n ],\n isError: true,\n }\n }\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ key: params.key, value, environment: envName }, null, 2),\n },\n ],\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { environment: envName, variables: env.variables },\n null,\n 2,\n ),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── env_switch ──\n server.tool(\n 'env_switch',\n 'Cambia el entorno activo. Las variables del entorno activo se usan en {{interpolación}}.',\n {\n name: z.string().describe('Nombre del entorno a activar'),\n },\n async (params) => {\n try {\n await storage.setActiveEnvironment(params.name)\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Entorno activo cambiado a '${params.name}'`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { parseOpenApiSpec } from '../lib/openapi-parser.js'\nimport { readFile } from 'node:fs/promises'\n\nexport function registerApiSpecTools(server: McpServer, storage: Storage): void {\n // ── api_import ──\n\n server.tool(\n 'api_import',\n 'Importa un spec OpenAPI/Swagger desde una URL o archivo local. Guarda los endpoints y schemas para consulta.',\n {\n name: z\n .string()\n .describe('Nombre para identificar este API (ej: \"mi-backend\", \"cocaxcode-api\")'),\n source: z\n .string()\n .describe(\n 'URL del spec OpenAPI JSON (ej: http://localhost:3001/api-docs-json) o ruta a archivo local',\n ),\n },\n async (params) => {\n try {\n let rawDoc: Record<string, unknown>\n\n if (params.source.startsWith('http://') || params.source.startsWith('https://')) {\n // Fetch from URL\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 30000)\n\n try {\n const response = await fetch(params.source, { signal: controller.signal })\n if (!response.ok) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: No se pudo descargar el spec. Status: ${response.status} ${response.statusText}`,\n },\n ],\n isError: true,\n }\n }\n rawDoc = (await response.json()) as Record<string, unknown>\n } finally {\n clearTimeout(timeout)\n }\n } else {\n // Read from local file\n try {\n const content = await readFile(params.source, 'utf-8')\n rawDoc = JSON.parse(content) as Record<string, unknown>\n } catch {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: No se pudo leer el archivo '${params.source}'. Verifica que existe y es JSON válido.`,\n },\n ],\n isError: true,\n }\n }\n }\n\n // Validate it looks like OpenAPI\n if (!rawDoc.openapi && !rawDoc.swagger) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'Error: El documento no parece ser un spec OpenAPI/Swagger válido. Falta la propiedad \"openapi\" o \"swagger\".',\n },\n ],\n isError: true,\n }\n }\n\n // Parse and save\n const spec = parseOpenApiSpec(rawDoc, params.name, params.source)\n await storage.saveSpec(spec)\n\n // Build summary\n const tagCounts: Record<string, number> = {}\n for (const ep of spec.endpoints) {\n for (const tag of ep.tags ?? ['sin-tag']) {\n tagCounts[tag] = (tagCounts[tag] ?? 0) + 1\n }\n }\n\n const tagSummary = Object.entries(tagCounts)\n .map(([tag, count]) => ` - ${tag}: ${count} endpoints`)\n .join('\\n')\n\n const schemaCount = Object.keys(spec.schemas).length\n\n return {\n content: [\n {\n type: 'text' as const,\n text: [\n `API '${params.name}' importada correctamente.`,\n '',\n `Versión: ${spec.version ?? 'no especificada'}`,\n `Endpoints: ${spec.endpoints.length}`,\n `Schemas: ${schemaCount}`,\n '',\n 'Endpoints por tag:',\n tagSummary,\n '',\n 'Usa api_endpoints para ver los endpoints disponibles.',\n 'Usa api_endpoint_detail para ver el detalle de un endpoint específico.',\n ].join('\\n'),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── api_endpoints ──\n\n server.tool(\n 'api_endpoints',\n 'Lista los endpoints de un API importada. Filtra por tag, método o path.',\n {\n name: z\n .string()\n .describe('Nombre del API importada'),\n tag: z\n .string()\n .optional()\n .describe('Filtrar por tag (ej: \"blog\", \"auth\", \"users\")'),\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .optional()\n .describe('Filtrar por método HTTP'),\n path: z\n .string()\n .optional()\n .describe('Filtrar por path (búsqueda parcial, ej: \"/blog\" muestra todos los que contienen /blog)'),\n },\n async (params) => {\n try {\n const spec = await storage.getSpec(params.name)\n if (!spec) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: API '${params.name}' no encontrada. Usa api_import para importarla primero.`,\n },\n ],\n isError: true,\n }\n }\n\n let endpoints = spec.endpoints\n\n // Apply filters\n if (params.tag) {\n endpoints = endpoints.filter((ep) =>\n (ep.tags ?? []).some((t) => t.toLowerCase() === params.tag!.toLowerCase()),\n )\n }\n if (params.method) {\n endpoints = endpoints.filter((ep) => ep.method === params.method)\n }\n if (params.path) {\n const search = params.path.toLowerCase()\n endpoints = endpoints.filter((ep) => ep.path.toLowerCase().includes(search))\n }\n\n if (endpoints.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'No se encontraron endpoints con los filtros aplicados.',\n },\n ],\n }\n }\n\n // Format output\n const lines = endpoints.map((ep) => {\n const tags = ep.tags?.length ? ` [${ep.tags.join(', ')}]` : ''\n const summary = ep.summary ? ` — ${ep.summary}` : ''\n return `${ep.method.padEnd(7)} ${ep.path}${summary}${tags}`\n })\n\n return {\n content: [\n {\n type: 'text' as const,\n text: [\n `API: ${spec.name} (${endpoints.length} endpoints)`,\n '',\n ...lines,\n '',\n 'Usa api_endpoint_detail para ver parámetros, body y respuestas de un endpoint.',\n ].join('\\n'),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── api_endpoint_detail ──\n\n server.tool(\n 'api_endpoint_detail',\n 'Muestra el detalle completo de un endpoint: parámetros, body schema, y respuestas. Útil para saber qué datos enviar.',\n {\n name: z\n .string()\n .describe('Nombre del API importada'),\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('Método HTTP del endpoint'),\n path: z\n .string()\n .describe('Path exacto del endpoint (ej: \"/blog\", \"/auth/login\")'),\n },\n async (params) => {\n try {\n const spec = await storage.getSpec(params.name)\n if (!spec) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: API '${params.name}' no encontrada. Usa api_import para importarla primero.`,\n },\n ],\n isError: true,\n }\n }\n\n const endpoint = spec.endpoints.find(\n (ep) => ep.method === params.method && ep.path === params.path,\n )\n\n if (!endpoint) {\n // Try partial match\n const similar = spec.endpoints.filter((ep) =>\n ep.path.includes(params.path) || params.path.includes(ep.path),\n )\n\n const suggestion = similar.length > 0\n ? `\\n\\nEndpoints similares:\\n${similar.map((ep) => ` ${ep.method} ${ep.path}`).join('\\n')}`\n : ''\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: Endpoint ${params.method} ${params.path} no encontrado.${suggestion}`,\n },\n ],\n isError: true,\n }\n }\n\n // Build detailed output\n const sections: string[] = []\n\n // Header\n sections.push(`## ${endpoint.method} ${endpoint.path}`)\n if (endpoint.summary) sections.push(`**${endpoint.summary}**`)\n if (endpoint.description) sections.push(endpoint.description)\n if (endpoint.tags?.length) sections.push(`Tags: ${endpoint.tags.join(', ')}`)\n\n // Parameters\n if (endpoint.parameters?.length) {\n sections.push('')\n sections.push('### Parámetros')\n for (const param of endpoint.parameters) {\n const required = param.required ? ' (requerido)' : ' (opcional)'\n const type = param.schema?.type ?? 'string'\n const desc = param.description ? ` — ${param.description}` : ''\n sections.push(`- **${param.name}** [${param.in}] ${type}${required}${desc}`)\n }\n }\n\n // Request body\n if (endpoint.requestBody) {\n sections.push('')\n sections.push('### Body')\n const required = endpoint.requestBody.required ? ' (requerido)' : ' (opcional)'\n sections.push(`Body${required}`)\n\n if (endpoint.requestBody.content) {\n for (const [contentType, media] of Object.entries(endpoint.requestBody.content)) {\n sections.push(`\\nContent-Type: ${contentType}`)\n if (media.schema) {\n sections.push('```json')\n sections.push(formatSchema(media.schema))\n sections.push('```')\n }\n }\n }\n }\n\n // Responses\n if (endpoint.responses) {\n sections.push('')\n sections.push('### Respuestas')\n for (const [status, resp] of Object.entries(endpoint.responses)) {\n const desc = resp.description ? ` — ${resp.description}` : ''\n sections.push(`\\n**${status}**${desc}`)\n\n if (resp.content) {\n for (const [, media] of Object.entries(resp.content)) {\n if (media.schema) {\n sections.push('```json')\n sections.push(formatSchema(media.schema))\n sections.push('```')\n }\n }\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: sections.join('\\n'),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n\n/**\n * Formatea un schema como ejemplo JSON legible.\n * Genera un ejemplo basado en los tipos y propiedades del schema.\n */\nfunction formatSchema(schema: { type?: string; properties?: Record<string, unknown>; items?: unknown; required?: string[]; enum?: unknown[]; example?: unknown; format?: string; description?: string }, depth = 0): string {\n if (depth > 5) return '\"...\"'\n\n const indent = ' '.repeat(depth)\n const innerIndent = ' '.repeat(depth + 1)\n\n if (schema.example !== undefined) {\n return JSON.stringify(schema.example, null, 2)\n .split('\\n')\n .map((line, i) => (i === 0 ? line : indent + line))\n .join('\\n')\n }\n\n if (schema.enum) {\n return JSON.stringify(schema.enum[0])\n }\n\n if (schema.type === 'object' && schema.properties) {\n const props = Object.entries(schema.properties as Record<string, Record<string, unknown>>)\n if (props.length === 0) return '{}'\n\n const requiredFields = new Set(schema.required ?? [])\n const lines: string[] = ['{']\n\n for (const [key, prop] of props) {\n const isRequired = requiredFields.has(key)\n const comment = []\n if (prop.description) comment.push(prop.description as string)\n if (!isRequired) comment.push('opcional')\n const commentStr = comment.length > 0 ? ` // ${comment.join(' — ')}` : ''\n\n const value = formatSchema(prop as typeof schema, depth + 1)\n lines.push(`${innerIndent}\"${key}\": ${value},${commentStr}`)\n }\n\n lines.push(`${indent}}`)\n return lines.join('\\n')\n }\n\n if (schema.type === 'array' && schema.items) {\n const itemValue = formatSchema(schema.items as typeof schema, depth + 1)\n return `[${itemValue}]`\n }\n\n // Primitive types\n switch (schema.type) {\n case 'string':\n if (schema.format === 'date-time') return '\"2024-01-01T00:00:00Z\"'\n if (schema.format === 'email') return '\"user@example.com\"'\n if (schema.format === 'uri' || schema.format === 'url') return '\"https://example.com\"'\n return '\"string\"'\n case 'number':\n case 'integer':\n return '0'\n case 'boolean':\n return 'true'\n default:\n return 'null'\n }\n}\n","import type {\n HttpMethod,\n ApiSpecEndpoint,\n ApiSpecSchema,\n ApiSpec,\n} from './types.js'\n\nconst VALID_METHODS: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']\n\n/**\n * Resuelve $ref references en un schema OpenAPI.\n * Soporta refs tipo \"#/components/schemas/MyModel\".\n */\nfunction resolveRef(\n ref: string,\n root: Record<string, unknown>,\n): ApiSpecSchema | undefined {\n const parts = ref.replace(/^#\\//, '').split('/')\n let current: unknown = root\n\n for (const part of parts) {\n if (current && typeof current === 'object' && part in current) {\n current = (current as Record<string, unknown>)[part]\n } else {\n return undefined\n }\n }\n\n return current as ApiSpecSchema\n}\n\n/**\n * Resuelve recursivamente todos los $ref en un schema.\n */\nfunction resolveSchema(\n schema: ApiSpecSchema | undefined,\n root: Record<string, unknown>,\n depth = 0,\n): ApiSpecSchema | undefined {\n if (!schema || depth > 10) return schema\n\n if (schema.$ref) {\n const resolved = resolveRef(schema.$ref, root)\n if (resolved) {\n return resolveSchema(resolved, root, depth + 1)\n }\n return { type: 'object', description: `Unresolved: ${schema.$ref}` }\n }\n\n const result: ApiSpecSchema = { ...schema }\n\n // Resolve properties recursively\n if (result.properties) {\n const resolvedProps: Record<string, ApiSpecSchema> = {}\n for (const [key, prop] of Object.entries(result.properties)) {\n resolvedProps[key] = resolveSchema(prop, root, depth + 1) ?? prop\n }\n result.properties = resolvedProps\n }\n\n // Resolve array items\n if (result.items) {\n result.items = resolveSchema(result.items, root, depth + 1) ?? result.items\n }\n\n return result\n}\n\n/**\n * Parsea un documento OpenAPI 3.x y extrae endpoints y schemas.\n */\nexport function parseOpenApiSpec(\n doc: Record<string, unknown>,\n name: string,\n source: string,\n): ApiSpec {\n const info = doc.info as Record<string, unknown> | undefined\n const paths = doc.paths as Record<string, Record<string, unknown>> | undefined\n const components = doc.components as Record<string, unknown> | undefined\n const rawSchemas = (components?.schemas ?? {}) as Record<string, ApiSpecSchema>\n\n // Resolve all schemas\n const schemas: Record<string, ApiSpecSchema> = {}\n for (const [schemaName, schema] of Object.entries(rawSchemas)) {\n schemas[schemaName] = resolveSchema(schema, doc, 0) ?? schema\n }\n\n const endpoints: ApiSpecEndpoint[] = []\n\n if (paths) {\n for (const [path, pathItem] of Object.entries(paths)) {\n for (const [method, operation] of Object.entries(pathItem)) {\n const upperMethod = method.toUpperCase() as HttpMethod\n if (!VALID_METHODS.includes(upperMethod)) continue\n\n const op = operation as Record<string, unknown>\n\n // Parse parameters\n const rawParams = (op.parameters ?? []) as Array<Record<string, unknown>>\n const parameters = rawParams.map((p) => ({\n name: p.name as string,\n in: p.in as 'path' | 'query' | 'header' | 'cookie',\n required: p.required as boolean | undefined,\n description: p.description as string | undefined,\n schema: resolveSchema(p.schema as ApiSpecSchema | undefined, doc),\n }))\n\n // Parse request body\n const rawBody = op.requestBody as Record<string, unknown> | undefined\n let requestBody = undefined\n if (rawBody) {\n const bodyContent = rawBody.content as Record<string, Record<string, unknown>> | undefined\n const resolvedContent: Record<string, { schema?: ApiSpecSchema }> = {}\n\n if (bodyContent) {\n for (const [contentType, mediaType] of Object.entries(bodyContent)) {\n resolvedContent[contentType] = {\n schema: resolveSchema(mediaType.schema as ApiSpecSchema | undefined, doc),\n }\n }\n }\n\n requestBody = {\n required: rawBody.required as boolean | undefined,\n description: rawBody.description as string | undefined,\n content: resolvedContent,\n }\n }\n\n // Parse responses\n const rawResponses = (op.responses ?? {}) as Record<string, Record<string, unknown>>\n const responses: Record<string, { description?: string; content?: Record<string, { schema?: ApiSpecSchema }> }> = {}\n\n for (const [statusCode, resp] of Object.entries(rawResponses)) {\n const respContent = resp.content as Record<string, Record<string, unknown>> | undefined\n const resolvedRespContent: Record<string, { schema?: ApiSpecSchema }> = {}\n\n if (respContent) {\n for (const [contentType, mediaType] of Object.entries(respContent)) {\n resolvedRespContent[contentType] = {\n schema: resolveSchema(mediaType.schema as ApiSpecSchema | undefined, doc),\n }\n }\n }\n\n responses[statusCode] = {\n description: resp.description as string | undefined,\n content: respContent ? resolvedRespContent : undefined,\n }\n }\n\n endpoints.push({\n method: upperMethod,\n path,\n summary: op.summary as string | undefined,\n description: op.description as string | undefined,\n tags: op.tags as string[] | undefined,\n parameters,\n requestBody,\n responses,\n })\n }\n }\n }\n\n const now = new Date().toISOString()\n\n return {\n name,\n source,\n version: info?.version as string | undefined,\n endpoints,\n schemas,\n importedAt: now,\n updatedAt: now,\n }\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { executeRequest } from '../lib/http-client.js'\nimport { interpolateRequest } from '../lib/interpolation.js'\nimport type { RequestConfig, RequestResponse } from '../lib/types.js'\n\nconst AssertionSchema = z.object({\n path: z\n .string()\n .describe(\n 'JSONPath al valor a validar: \"status\", \"body.data.id\", \"headers.content-type\", \"timing.total_ms\"',\n ),\n operator: z\n .enum(['eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'contains', 'not_contains', 'exists', 'type'])\n .describe(\n 'Operador: eq (igual), neq (no igual), gt/gte/lt/lte (numéricos), contains/not_contains (strings/arrays), exists (campo existe), type (typeof)',\n ),\n expected: z.any().optional().describe('Valor esperado (no necesario para \"exists\")'),\n})\n\n/**\n * Accede a un valor en un objeto usando dot notation.\n * Ej: getByPath({ body: { data: { id: 1 } } }, \"body.data.id\") → 1\n */\nfunction getByPath(obj: unknown, path: string): unknown {\n const parts = path.split('.')\n let current: unknown = obj\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined\n if (typeof current === 'object') {\n current = (current as Record<string, unknown>)[part]\n } else {\n return undefined\n }\n }\n\n return current\n}\n\n/**\n * Evalúa una aserción contra una respuesta.\n */\nfunction evaluateAssertion(\n response: RequestResponse,\n assertion: { path: string; operator: string; expected?: unknown },\n): { pass: boolean; message: string } {\n const actual = getByPath(response, assertion.path)\n\n switch (assertion.operator) {\n case 'eq':\n return {\n pass: actual === assertion.expected,\n message: actual === assertion.expected\n ? `${assertion.path} === ${JSON.stringify(assertion.expected)}`\n : `${assertion.path}: esperado ${JSON.stringify(assertion.expected)}, recibido ${JSON.stringify(actual)}`,\n }\n\n case 'neq':\n return {\n pass: actual !== assertion.expected,\n message: actual !== assertion.expected\n ? `${assertion.path} !== ${JSON.stringify(assertion.expected)}`\n : `${assertion.path}: no debería ser ${JSON.stringify(assertion.expected)}`,\n }\n\n case 'gt':\n return {\n pass: typeof actual === 'number' && actual > (assertion.expected as number),\n message: `${assertion.path}: ${actual} > ${assertion.expected} → ${typeof actual === 'number' && actual > (assertion.expected as number)}`,\n }\n\n case 'gte':\n return {\n pass: typeof actual === 'number' && actual >= (assertion.expected as number),\n message: `${assertion.path}: ${actual} >= ${assertion.expected} → ${typeof actual === 'number' && actual >= (assertion.expected as number)}`,\n }\n\n case 'lt':\n return {\n pass: typeof actual === 'number' && actual < (assertion.expected as number),\n message: `${assertion.path}: ${actual} < ${assertion.expected} → ${typeof actual === 'number' && actual < (assertion.expected as number)}`,\n }\n\n case 'lte':\n return {\n pass: typeof actual === 'number' && actual <= (assertion.expected as number),\n message: `${assertion.path}: ${actual} <= ${assertion.expected} → ${typeof actual === 'number' && actual <= (assertion.expected as number)}`,\n }\n\n case 'contains': {\n let pass = false\n if (typeof actual === 'string') {\n pass = actual.includes(String(assertion.expected))\n } else if (Array.isArray(actual)) {\n pass = actual.includes(assertion.expected)\n }\n return {\n pass,\n message: pass\n ? `${assertion.path} contiene ${JSON.stringify(assertion.expected)}`\n : `${assertion.path}: no contiene ${JSON.stringify(assertion.expected)}`,\n }\n }\n\n case 'not_contains': {\n let pass = true\n if (typeof actual === 'string') {\n pass = !actual.includes(String(assertion.expected))\n } else if (Array.isArray(actual)) {\n pass = !actual.includes(assertion.expected)\n }\n return {\n pass,\n message: pass\n ? `${assertion.path} no contiene ${JSON.stringify(assertion.expected)}`\n : `${assertion.path}: contiene ${JSON.stringify(assertion.expected)} (no debería)`,\n }\n }\n\n case 'exists':\n return {\n pass: actual !== undefined && actual !== null,\n message: actual !== undefined && actual !== null\n ? `${assertion.path} existe`\n : `${assertion.path}: no existe`,\n }\n\n case 'type':\n return {\n pass: typeof actual === assertion.expected,\n message: typeof actual === assertion.expected\n ? `${assertion.path} es tipo ${assertion.expected}`\n : `${assertion.path}: esperado tipo ${assertion.expected}, recibido ${typeof actual}`,\n }\n\n default:\n return { pass: false, message: `Operador desconocido: ${assertion.operator}` }\n }\n}\n\nexport function registerAssertTool(server: McpServer, storage: Storage): void {\n server.tool(\n 'assert',\n 'Ejecuta un request y valida la respuesta con assertions. Retorna resultado pass/fail por cada assertion.',\n {\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('HTTP method'),\n url: z.string().describe('URL del endpoint (soporta /relativa y {{variables}})'),\n headers: z.record(z.string()).optional().describe('Headers HTTP'),\n body: z.any().optional().describe('Body del request (JSON)'),\n query: z.record(z.string()).optional().describe('Query parameters'),\n auth: z\n .object({\n type: z.enum(['bearer', 'api-key', 'basic']),\n token: z.string().optional(),\n key: z.string().optional(),\n header: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n })\n .optional()\n .describe('Autenticación'),\n assertions: z\n .array(AssertionSchema)\n .describe('Lista de assertions a validar contra la respuesta'),\n },\n async (params) => {\n try {\n const variables = await storage.getActiveVariables()\n\n // Auto-prepend BASE_URL for relative URLs\n let resolvedUrl = params.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n const config: RequestConfig = {\n method: params.method,\n url: resolvedUrl,\n headers: params.headers,\n body: params.body,\n query: params.query,\n auth: params.auth,\n }\n\n const interpolated = interpolateRequest(config, variables)\n const response = await executeRequest(interpolated)\n\n // Evaluate assertions\n const results = params.assertions.map((assertion) => {\n const result = evaluateAssertion(response, assertion)\n return { ...result, assertion }\n })\n\n const passed = results.filter((r) => r.pass).length\n const failed = results.filter((r) => !r.pass).length\n const allPassed = failed === 0\n\n const lines: string[] = [\n `${allPassed ? '✅ PASS' : '❌ FAIL'} — ${passed}/${results.length} assertions passed`,\n `${params.method} ${params.url} → ${response.status} ${response.statusText} (${response.timing.total_ms}ms)`,\n '',\n ]\n\n for (const r of results) {\n const icon = r.pass ? '✅' : '❌'\n lines.push(`${icon} ${r.message}`)\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n isError: !allPassed,\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { executeRequest } from '../lib/http-client.js'\nimport { interpolateRequest } from '../lib/interpolation.js'\nimport type { RequestConfig, RequestResponse } from '../lib/types.js'\n\nconst FlowStepSchema = z.object({\n name: z.string().describe('Nombre del paso (ej: \"login\", \"crear-post\")'),\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('HTTP method'),\n url: z.string().describe('URL del endpoint'),\n headers: z.record(z.string()).optional().describe('Headers HTTP'),\n body: z.any().optional().describe('Body del request'),\n query: z.record(z.string()).optional().describe('Query parameters'),\n auth: z\n .object({\n type: z.enum(['bearer', 'api-key', 'basic']),\n token: z.string().optional(),\n key: z.string().optional(),\n header: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n })\n .optional()\n .describe('Autenticación'),\n extract: z\n .record(z.string())\n .optional()\n .describe(\n 'Variables a extraer de la respuesta para pasos siguientes. Key = nombre variable, value = path (ej: { \"TOKEN\": \"body.token\", \"USER_ID\": \"body.data.id\" })',\n ),\n})\n\n/**\n * Accede a un valor en un objeto usando dot notation.\n */\nfunction getByPath(obj: unknown, path: string): unknown {\n const parts = path.split('.')\n let current: unknown = obj\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined\n if (typeof current === 'object') {\n // Handle array index access like \"data.0.id\"\n if (Array.isArray(current) && /^\\d+$/.test(part)) {\n current = current[parseInt(part)]\n } else {\n current = (current as Record<string, unknown>)[part]\n }\n } else {\n return undefined\n }\n }\n\n return current\n}\n\nexport function registerFlowTool(server: McpServer, storage: Storage): void {\n server.tool(\n 'flow_run',\n 'Ejecuta una secuencia de requests en orden. Extrae variables de cada respuesta para usar en pasos siguientes con {{variable}}.',\n {\n steps: z.array(FlowStepSchema).describe('Pasos a ejecutar en orden'),\n stop_on_error: z\n .boolean()\n .optional()\n .describe('Detener al primer error (default: true)'),\n },\n async (params) => {\n try {\n const stopOnError = params.stop_on_error ?? true\n const envVariables = await storage.getActiveVariables()\n const flowVariables: Record<string, string> = { ...envVariables }\n const results: Array<{\n name: string\n status: number\n timing: number\n extracted: Record<string, string>\n error?: string\n }> = []\n\n for (const step of params.steps) {\n try {\n // Auto-prepend BASE_URL for relative URLs\n let resolvedUrl = step.url\n if (resolvedUrl.startsWith('/') && flowVariables.BASE_URL) {\n const baseUrl = flowVariables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n const config: RequestConfig = {\n method: step.method,\n url: resolvedUrl,\n headers: step.headers,\n body: step.body,\n query: step.query,\n auth: step.auth,\n }\n\n // Interpolate with accumulated flow variables\n const interpolated = interpolateRequest(config, flowVariables)\n const response: RequestResponse = await executeRequest(interpolated)\n\n // Extract variables from response\n const extracted: Record<string, string> = {}\n if (step.extract) {\n for (const [varName, path] of Object.entries(step.extract)) {\n const value = getByPath(response, path)\n if (value !== undefined && value !== null) {\n extracted[varName] = String(value)\n flowVariables[varName] = String(value)\n }\n }\n }\n\n results.push({\n name: step.name,\n status: response.status,\n timing: response.timing.total_ms,\n extracted,\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n results.push({\n name: step.name,\n status: 0,\n timing: 0,\n extracted: {},\n error: message,\n })\n\n if (stopOnError) break\n }\n }\n\n // Build output\n const allOk = results.every((r) => !r.error && r.status >= 200 && r.status < 400)\n const lines: string[] = [\n `${allOk ? '✅ FLOW COMPLETO' : '❌ FLOW CON ERRORES'} — ${results.length}/${params.steps.length} pasos ejecutados`,\n '',\n ]\n\n for (let i = 0; i < results.length; i++) {\n const r = results[i]\n const icon = r.error ? '❌' : r.status >= 200 && r.status < 400 ? '✅' : '⚠️'\n lines.push(`${icon} Paso ${i + 1}: ${r.name}`)\n\n if (r.error) {\n lines.push(` Error: ${r.error}`)\n } else {\n lines.push(` Status: ${r.status} | Tiempo: ${r.timing}ms`)\n }\n\n if (Object.keys(r.extracted).length > 0) {\n const vars = Object.entries(r.extracted)\n .map(([k, v]) => `${k}=${v.length > 50 ? v.substring(0, 50) + '...' : v}`)\n .join(', ')\n lines.push(` Extraído: ${vars}`)\n }\n\n lines.push('')\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n isError: !allOk,\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { executeRequest } from '../lib/http-client.js'\nimport { interpolateRequest } from '../lib/interpolation.js'\nimport type { RequestConfig } from '../lib/types.js'\n\nexport function registerUtilityTools(server: McpServer, storage: Storage): void {\n // ── export_curl ──\n\n server.tool(\n 'export_curl',\n 'Genera un comando cURL a partir de un request guardado en la colección. Listo para copiar y pegar.',\n {\n name: z.string().describe('Nombre del request guardado en la colección'),\n resolve_variables: z\n .boolean()\n .optional()\n .describe('Resolver {{variables}} del entorno activo (default: true)'),\n },\n async (params) => {\n try {\n const saved = await storage.getCollection(params.name)\n if (!saved) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: Request '${params.name}' no encontrado en la colección.`,\n },\n ],\n isError: true,\n }\n }\n\n let config = saved.request\n const resolveVars = params.resolve_variables ?? true\n\n if (resolveVars) {\n const variables = await storage.getActiveVariables()\n\n // Auto-prepend BASE_URL for relative URLs\n let resolvedUrl = config.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n config = { ...config, url: resolvedUrl }\n config = interpolateRequest(config, variables)\n }\n\n // Build cURL command\n const parts: string[] = ['curl']\n\n // Method\n if (config.method !== 'GET') {\n parts.push(`-X ${config.method}`)\n }\n\n // URL with query params\n let url = config.url\n if (config.query && Object.keys(config.query).length > 0) {\n const queryStr = Object.entries(config.query)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&')\n url += (url.includes('?') ? '&' : '?') + queryStr\n }\n parts.push(`'${url}'`)\n\n // Headers\n if (config.headers) {\n for (const [key, value] of Object.entries(config.headers)) {\n parts.push(`-H '${key}: ${value}'`)\n }\n }\n\n // Auth headers\n if (config.auth) {\n switch (config.auth.type) {\n case 'bearer':\n if (config.auth.token) {\n parts.push(`-H 'Authorization: Bearer ${config.auth.token}'`)\n }\n break\n case 'api-key':\n if (config.auth.key) {\n const header = config.auth.header ?? 'X-API-Key'\n parts.push(`-H '${header}: ${config.auth.key}'`)\n }\n break\n case 'basic':\n if (config.auth.username && config.auth.password) {\n parts.push(`-u '${config.auth.username}:${config.auth.password}'`)\n }\n break\n }\n }\n\n // Body\n if (config.body !== undefined && config.body !== null) {\n const bodyStr =\n typeof config.body === 'string' ? config.body : JSON.stringify(config.body)\n parts.push(`-H 'Content-Type: application/json'`)\n parts.push(`-d '${bodyStr}'`)\n }\n\n const curlCommand = parts.join(' \\\\\\n ')\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `cURL para '${params.name}':\\n\\n${curlCommand}`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── diff_responses ──\n\n server.tool(\n 'diff_responses',\n 'Ejecuta dos requests y compara sus respuestas. Útil para detectar regresiones o comparar entornos.',\n {\n request_a: z\n .object({\n label: z.string().optional().describe('Etiqueta (ej: \"antes\", \"dev\", \"v1\")'),\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']),\n url: z.string(),\n headers: z.record(z.string()).optional(),\n body: z.any().optional(),\n query: z.record(z.string()).optional(),\n auth: z\n .object({\n type: z.enum(['bearer', 'api-key', 'basic']),\n token: z.string().optional(),\n key: z.string().optional(),\n header: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n })\n .optional(),\n })\n .describe('Primer request'),\n request_b: z\n .object({\n label: z.string().optional().describe('Etiqueta (ej: \"después\", \"prod\", \"v2\")'),\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']),\n url: z.string(),\n headers: z.record(z.string()).optional(),\n body: z.any().optional(),\n query: z.record(z.string()).optional(),\n auth: z\n .object({\n type: z.enum(['bearer', 'api-key', 'basic']),\n token: z.string().optional(),\n key: z.string().optional(),\n header: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n })\n .optional(),\n })\n .describe('Segundo request'),\n },\n async (params) => {\n try {\n const variables = await storage.getActiveVariables()\n\n // Helper to resolve and execute a request\n const executeOne = async (req: typeof params.request_a) => {\n let resolvedUrl = req.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n const config: RequestConfig = {\n method: req.method,\n url: resolvedUrl,\n headers: req.headers,\n body: req.body,\n query: req.query,\n auth: req.auth,\n }\n\n return executeRequest(interpolateRequest(config, variables))\n }\n\n const [responseA, responseB] = await Promise.all([\n executeOne(params.request_a),\n executeOne(params.request_b),\n ])\n\n const labelA = params.request_a.label ?? 'A'\n const labelB = params.request_b.label ?? 'B'\n\n const diffs: string[] = []\n\n // Compare status\n if (responseA.status !== responseB.status) {\n diffs.push(\n `Status: ${labelA}=${responseA.status} vs ${labelB}=${responseB.status}`,\n )\n }\n\n // Compare timing\n const timingDiff = Math.abs(responseA.timing.total_ms - responseB.timing.total_ms)\n if (timingDiff > 100) {\n diffs.push(\n `Timing: ${labelA}=${responseA.timing.total_ms}ms vs ${labelB}=${responseB.timing.total_ms}ms (Δ${Math.round(timingDiff)}ms)`,\n )\n }\n\n // Compare body\n const bodyA = JSON.stringify(responseA.body, null, 2)\n const bodyB = JSON.stringify(responseB.body, null, 2)\n\n if (bodyA !== bodyB) {\n diffs.push('Body: diferente')\n\n // Find specific key differences for objects\n if (\n typeof responseA.body === 'object' &&\n typeof responseB.body === 'object' &&\n responseA.body &&\n responseB.body\n ) {\n const keysA = new Set(Object.keys(responseA.body as Record<string, unknown>))\n const keysB = new Set(Object.keys(responseB.body as Record<string, unknown>))\n\n const onlyInA = [...keysA].filter((k) => !keysB.has(k))\n const onlyInB = [...keysB].filter((k) => !keysA.has(k))\n const common = [...keysA].filter((k) => keysB.has(k))\n\n if (onlyInA.length > 0) diffs.push(` Solo en ${labelA}: ${onlyInA.join(', ')}`)\n if (onlyInB.length > 0) diffs.push(` Solo en ${labelB}: ${onlyInB.join(', ')}`)\n\n for (const key of common) {\n const valA = JSON.stringify(\n (responseA.body as Record<string, unknown>)[key],\n )\n const valB = JSON.stringify(\n (responseB.body as Record<string, unknown>)[key],\n )\n if (valA !== valB) {\n const shortA = valA.length > 50 ? valA.substring(0, 50) + '...' : valA\n const shortB = valB.length > 50 ? valB.substring(0, 50) + '...' : valB\n diffs.push(` ${key}: ${labelA}=${shortA} vs ${labelB}=${shortB}`)\n }\n }\n }\n }\n\n // Compare size\n const sizeDiff = Math.abs(responseA.size_bytes - responseB.size_bytes)\n if (sizeDiff > 0) {\n diffs.push(\n `Size: ${labelA}=${responseA.size_bytes}B vs ${labelB}=${responseB.size_bytes}B`,\n )\n }\n\n const identical = diffs.length === 0\n\n const lines: string[] = [\n identical ? '✅ IDÉNTICAS' : `⚠️ ${diffs.length} DIFERENCIAS ENCONTRADAS`,\n '',\n `${labelA}: ${params.request_a.method} ${params.request_a.url} → ${responseA.status} (${responseA.timing.total_ms}ms)`,\n `${labelB}: ${params.request_b.method} ${params.request_b.url} → ${responseB.status} (${responseB.timing.total_ms}ms)`,\n ]\n\n if (!identical) {\n lines.push('')\n lines.push('Diferencias:')\n for (const diff of diffs) {\n lines.push(` ${diff}`)\n }\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── bulk_test ──\n\n server.tool(\n 'bulk_test',\n 'Ejecuta todos los requests guardados en la colección y reporta resultados. Filtrable por tag.',\n {\n tag: z.string().optional().describe('Filtrar por tag'),\n expected_status: z\n .number()\n .optional()\n .describe('Status HTTP esperado para todos (default: cualquier 2xx)'),\n },\n async (params) => {\n try {\n const collections = await storage.listCollections(params.tag)\n if (collections.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: params.tag\n ? `No hay requests guardados con tag '${params.tag}'.`\n : 'No hay requests guardados en la colección.',\n },\n ],\n }\n }\n\n const variables = await storage.getActiveVariables()\n const results: Array<{\n name: string\n method: string\n url: string\n status: number\n timing: number\n pass: boolean\n error?: string\n }> = []\n\n for (const item of collections) {\n const saved = await storage.getCollection(item.name)\n if (!saved) continue\n\n try {\n let config = saved.request\n\n // Auto-prepend BASE_URL\n let resolvedUrl = config.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n config = { ...config, url: resolvedUrl }\n const interpolated = interpolateRequest(config, variables)\n const response = await executeRequest(interpolated)\n\n const pass = params.expected_status\n ? response.status === params.expected_status\n : response.status >= 200 && response.status < 300\n\n results.push({\n name: item.name,\n method: config.method,\n url: item.url,\n status: response.status,\n timing: response.timing.total_ms,\n pass,\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n results.push({\n name: item.name,\n method: item.method,\n url: item.url,\n status: 0,\n timing: 0,\n pass: false,\n error: message,\n })\n }\n }\n\n const passed = results.filter((r) => r.pass).length\n const failed = results.filter((r) => !r.pass).length\n const totalTime = Math.round(results.reduce((sum, r) => sum + r.timing, 0) * 100) / 100\n\n const lines: string[] = [\n `${failed === 0 ? '✅' : '❌'} BULK TEST — ${passed}/${results.length} passed | ${totalTime}ms total`,\n '',\n ]\n\n for (const r of results) {\n const icon = r.pass ? '✅' : '❌'\n if (r.error) {\n lines.push(`${icon} ${r.name} — ERROR: ${r.error}`)\n } else {\n lines.push(`${icon} ${r.name} — ${r.method} ${r.url} → ${r.status} (${r.timing}ms)`)\n }\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n isError: failed > 0,\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport type { ApiSpecSchema } from '../lib/types.js'\n\n/**\n * Genera datos fake basándose en un schema OpenAPI.\n */\nfunction generateMockData(schema: ApiSpecSchema, depth = 0): unknown {\n if (depth > 8) return null\n\n // If example exists, use it\n if (schema.example !== undefined) return schema.example\n\n // If enum, pick first value\n if (schema.enum && schema.enum.length > 0) {\n return schema.enum[Math.floor(Math.random() * schema.enum.length)]\n }\n\n switch (schema.type) {\n case 'object': {\n if (!schema.properties) return {}\n const obj: Record<string, unknown> = {}\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n obj[key] = generateMockData(propSchema, depth + 1)\n }\n return obj\n }\n\n case 'array': {\n if (!schema.items) return []\n const count = Math.floor(Math.random() * 3) + 1 // 1-3 items\n return Array.from({ length: count }, () =>\n generateMockData(schema.items!, depth + 1),\n )\n }\n\n case 'string': {\n switch (schema.format) {\n case 'date-time':\n return new Date().toISOString()\n case 'date':\n return new Date().toISOString().split('T')[0]\n case 'email':\n return `user${Math.floor(Math.random() * 1000)}@example.com`\n case 'uri':\n case 'url':\n return 'https://example.com/resource'\n case 'uuid':\n return crypto.randomUUID()\n case 'ipv4':\n return `192.168.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`\n default: {\n // Use description or key name for smarter generation\n const desc = (schema.description ?? '').toLowerCase()\n if (desc.includes('name') || desc.includes('nombre'))\n return `Test User ${Math.floor(Math.random() * 100)}`\n if (desc.includes('title') || desc.includes('título'))\n return `Test Title ${Math.floor(Math.random() * 100)}`\n if (desc.includes('description') || desc.includes('descripción'))\n return 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'\n if (desc.includes('password') || desc.includes('contraseña'))\n return 'TestPass123!'\n if (desc.includes('slug'))\n return `test-slug-${Math.floor(Math.random() * 1000)}`\n if (desc.includes('phone') || desc.includes('teléfono'))\n return '+34612345678'\n return `mock-string-${Math.floor(Math.random() * 10000)}`\n }\n }\n }\n\n case 'number':\n case 'integer':\n return Math.floor(Math.random() * 1000)\n\n case 'boolean':\n return Math.random() > 0.5\n\n default:\n return null\n }\n}\n\nexport function registerMockTool(server: McpServer, storage: Storage): void {\n server.tool(\n 'mock',\n 'Genera datos mock/fake para un endpoint basándose en su spec OpenAPI importada. Útil para frontend sin backend.',\n {\n name: z.string().describe('Nombre del API importada'),\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('Método HTTP del endpoint'),\n path: z.string().describe('Path del endpoint (ej: \"/users\", \"/blog\")'),\n target: z\n .enum(['request', 'response'])\n .optional()\n .describe('Generar mock del body de request o de la response (default: response)'),\n status: z\n .string()\n .optional()\n .describe('Status code de la respuesta a mockear (default: \"200\" o \"201\")'),\n count: z\n .number()\n .optional()\n .describe('Número de items mock a generar si el schema es un array (default: 3)'),\n },\n async (params) => {\n try {\n const spec = await storage.getSpec(params.name)\n if (!spec) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: API '${params.name}' no encontrada. Usa api_import para importarla primero.`,\n },\n ],\n isError: true,\n }\n }\n\n const endpoint = spec.endpoints.find(\n (ep) => ep.method === params.method && ep.path === params.path,\n )\n\n if (!endpoint) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: Endpoint ${params.method} ${params.path} no encontrado en '${params.name}'.`,\n },\n ],\n isError: true,\n }\n }\n\n const target = params.target ?? 'response'\n let schema: ApiSpecSchema | undefined\n\n if (target === 'request') {\n // Get request body schema\n const content = endpoint.requestBody?.content\n if (content) {\n const jsonContent = content['application/json']\n schema = jsonContent?.schema\n }\n\n if (!schema) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: El endpoint ${params.method} ${params.path} no tiene un body schema definido.`,\n },\n ],\n isError: true,\n }\n }\n } else {\n // Get response body schema\n const statusCode = params.status ?? (params.method === 'POST' ? '201' : '200')\n const response = endpoint.responses?.[statusCode]\n\n if (!response) {\n // Try to find any 2xx response\n const twoXX = Object.keys(endpoint.responses ?? {}).find((s) => s.startsWith('2'))\n if (twoXX && endpoint.responses) {\n const fallbackResp = endpoint.responses[twoXX]\n const content = fallbackResp?.content\n if (content) {\n const jsonContent = content['application/json']\n schema = jsonContent?.schema\n }\n }\n } else {\n const content = response.content\n if (content) {\n const jsonContent = content['application/json']\n schema = jsonContent?.schema\n }\n }\n\n if (!schema) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: No se encontró un schema de respuesta para ${params.method} ${params.path}.`,\n },\n ],\n isError: true,\n }\n }\n }\n\n // Generate mock data\n let mockData: unknown\n\n if (schema.type === 'array' && params.count) {\n // Generate specific number of items\n mockData = Array.from({ length: params.count }, () =>\n generateMockData(schema!.items ?? { type: 'object' }),\n )\n } else {\n mockData = generateMockData(schema)\n }\n\n const label = target === 'request' ? 'REQUEST BODY' : 'RESPONSE'\n\n return {\n content: [\n {\n type: 'text' as const,\n text: [\n `Mock ${label} para ${params.method} ${params.path}:`,\n '',\n '```json',\n JSON.stringify(mockData, null, 2),\n '```',\n '',\n 'Datos generados automáticamente desde el spec OpenAPI.',\n target === 'request'\n ? 'Puedes usar estos datos directamente en un request.'\n : 'Estos son datos de ejemplo que devolvería el endpoint.',\n ].join('\\n'),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { executeRequest } from '../lib/http-client.js'\nimport { interpolateRequest } from '../lib/interpolation.js'\nimport type { RequestConfig } from '../lib/types.js'\n\nexport function registerLoadTestTool(server: McpServer, storage: Storage): void {\n server.tool(\n 'load_test',\n 'Lanza N requests concurrentes al mismo endpoint y mide tiempos promedio, percentiles y tasa de errores.',\n {\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('HTTP method'),\n url: z.string().describe('URL del endpoint'),\n headers: z.record(z.string()).optional().describe('Headers HTTP'),\n body: z.any().optional().describe('Body del request'),\n query: z.record(z.string()).optional().describe('Query parameters'),\n auth: z\n .object({\n type: z.enum(['bearer', 'api-key', 'basic']),\n token: z.string().optional(),\n key: z.string().optional(),\n header: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n })\n .optional()\n .describe('Autenticación'),\n concurrent: z\n .number()\n .describe('Número de requests concurrentes a lanzar (max: 100)'),\n timeout: z\n .number()\n .optional()\n .describe('Timeout por request en ms (default: 30000)'),\n },\n async (params) => {\n try {\n const concurrentCount = Math.min(Math.max(params.concurrent, 1), 100)\n const variables = await storage.getActiveVariables()\n\n // Resolve URL\n let resolvedUrl = params.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n const baseConfig: RequestConfig = {\n method: params.method,\n url: resolvedUrl,\n headers: params.headers,\n body: params.body,\n query: params.query,\n auth: params.auth,\n timeout: params.timeout,\n }\n\n const interpolated = interpolateRequest(baseConfig, variables)\n\n // Execute all requests concurrently\n const startTotal = performance.now()\n\n const promises = Array.from({ length: concurrentCount }, () =>\n executeRequest(interpolated)\n .then((response) => ({\n status: response.status,\n timing: response.timing.total_ms,\n error: undefined as string | undefined,\n }))\n .catch((error) => ({\n status: 0,\n timing: 0,\n error: error instanceof Error ? error.message : String(error),\n })),\n )\n\n const results = await Promise.all(promises)\n const endTotal = performance.now()\n const wallTime = Math.round((endTotal - startTotal) * 100) / 100\n\n // Calculate stats\n const successful = results.filter((r) => !r.error)\n const failed = results.filter((r) => r.error)\n const timings = successful.map((r) => r.timing).sort((a, b) => a - b)\n\n const statusCounts: Record<number, number> = {}\n for (const r of successful) {\n statusCounts[r.status] = (statusCounts[r.status] ?? 0) + 1\n }\n\n const avg = timings.length > 0\n ? Math.round((timings.reduce((s, t) => s + t, 0) / timings.length) * 100) / 100\n : 0\n const min = timings.length > 0 ? timings[0] : 0\n const max = timings.length > 0 ? timings[timings.length - 1] : 0\n const p50 = timings.length > 0 ? timings[Math.floor(timings.length * 0.5)] : 0\n const p95 = timings.length > 0 ? timings[Math.floor(timings.length * 0.95)] : 0\n const p99 = timings.length > 0 ? timings[Math.floor(timings.length * 0.99)] : 0\n\n const rps = wallTime > 0\n ? Math.round((successful.length / (wallTime / 1000)) * 100) / 100\n : 0\n\n const lines: string[] = [\n `📊 LOAD TEST — ${params.method} ${params.url}`,\n '',\n `Requests: ${concurrentCount} concurrentes`,\n `Exitosos: ${successful.length} | Fallidos: ${failed.length}`,\n `Tiempo total: ${wallTime}ms`,\n `Requests/segundo: ${rps}`,\n '',\n '⏱️ Tiempos de respuesta:',\n ` Min: ${min}ms`,\n ` Avg: ${avg}ms`,\n ` p50: ${p50}ms`,\n ` p95: ${p95}ms`,\n ` p99: ${p99}ms`,\n ` Max: ${max}ms`,\n ]\n\n if (Object.keys(statusCounts).length > 0) {\n lines.push('')\n lines.push('📋 Status codes:')\n for (const [status, count] of Object.entries(statusCounts)) {\n const pct = Math.round((count / concurrentCount) * 100)\n lines.push(` ${status}: ${count} (${pct}%)`)\n }\n }\n\n if (failed.length > 0) {\n lines.push('')\n lines.push('❌ Errores:')\n const errorCounts: Record<string, number> = {}\n for (const r of failed) {\n const errMsg = r.error ?? 'Unknown'\n errorCounts[errMsg] = (errorCounts[errMsg] ?? 0) + 1\n }\n for (const [err, count] of Object.entries(errorCounts)) {\n lines.push(` ${err}: ${count}x`)\n }\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n isError: failed.length > successful.length, // More than 50% failed\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n"],"mappings":"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","names":["z","AuthSchema","z","z","readFile","z","z","z","z","z","getByPath","z","z","z","z","z"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/lib/storage.ts","../src/tools/request.ts","../src/lib/http-client.ts","../src/lib/interpolation.ts","../src/tools/collection.ts","../src/tools/environment.ts","../src/tools/api-spec.ts","../src/lib/openapi-parser.ts","../src/tools/assert.ts","../src/tools/flow.ts","../src/tools/utilities.ts","../src/tools/mock.ts","../src/tools/load-test.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { createServer } from './server.js'\n\nasync function main() {\n const server = createServer()\n const transport = new StdioServerTransport()\n await server.connect(transport)\n console.error('api-testing-mcp server running on stdio')\n}\n\nmain().catch((error) => {\n console.error('Fatal:', error)\n process.exit(1)\n})\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { Storage } from './lib/storage.js'\nimport { registerRequestTool } from './tools/request.js'\nimport { registerCollectionTools } from './tools/collection.js'\nimport { registerEnvironmentTools } from './tools/environment.js'\nimport { registerApiSpecTools } from './tools/api-spec.js'\nimport { registerAssertTool } from './tools/assert.js'\nimport { registerFlowTool } from './tools/flow.js'\nimport { registerUtilityTools } from './tools/utilities.js'\nimport { registerMockTool } from './tools/mock.js'\nimport { registerLoadTestTool } from './tools/load-test.js'\n\n// Leer version del package.json en build time no es posible con ESM fácilmente,\n// así que la definimos como constante sincronizada manualmente.\nconst VERSION = '0.4.0'\n\n/**\n * Crea y configura el MCP server con todos los tools registrados.\n * Exportada como factory para testabilidad con InMemoryTransport.\n */\nexport function createServer(storageDir?: string): McpServer {\n const server = new McpServer({\n name: 'api-testing-mcp',\n version: VERSION,\n })\n\n const storage = new Storage(storageDir)\n\n // Registrar tools\n registerRequestTool(server, storage)\n registerCollectionTools(server, storage)\n registerEnvironmentTools(server, storage)\n registerApiSpecTools(server, storage)\n registerAssertTool(server, storage)\n registerFlowTool(server, storage)\n registerUtilityTools(server, storage)\n registerMockTool(server, storage)\n registerLoadTestTool(server, storage)\n\n return server\n}\n","import { mkdir, readFile, writeFile, readdir, unlink } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type {\n SavedRequest,\n CollectionListItem,\n Environment,\n EnvironmentListItem,\n ApiSpec,\n ApiSpecListItem,\n} from './types.js'\n\nexport class Storage {\n private readonly baseDir: string\n private readonly collectionsDir: string\n private readonly environmentsDir: string\n private readonly specsDir: string\n private readonly activeEnvFile: string\n\n constructor(baseDir?: string) {\n this.baseDir = baseDir ?? process.env.API_TESTING_DIR ?? join(process.cwd(), '.api-testing')\n this.collectionsDir = join(this.baseDir, 'collections')\n this.environmentsDir = join(this.baseDir, 'environments')\n this.specsDir = join(this.baseDir, 'specs')\n this.activeEnvFile = join(this.baseDir, 'active-env')\n }\n\n // ── Collections ──\n\n async saveCollection(saved: SavedRequest): Promise<void> {\n await this.ensureDir('collections')\n const filePath = join(this.collectionsDir, `${this.sanitizeName(saved.name)}.json`)\n await this.writeJson(filePath, saved)\n }\n\n async getCollection(name: string): Promise<SavedRequest | null> {\n const filePath = join(this.collectionsDir, `${this.sanitizeName(name)}.json`)\n return this.readJson<SavedRequest>(filePath)\n }\n\n async listCollections(tag?: string): Promise<CollectionListItem[]> {\n await this.ensureDir('collections')\n const files = await this.listJsonFiles(this.collectionsDir)\n const items: CollectionListItem[] = []\n\n for (const file of files) {\n const saved = await this.readJson<SavedRequest>(join(this.collectionsDir, file))\n if (!saved) continue\n\n if (tag && !(saved.tags ?? []).includes(tag)) continue\n\n items.push({\n name: saved.name,\n method: saved.request.method,\n url: saved.request.url,\n tags: saved.tags ?? [],\n })\n }\n\n return items\n }\n\n async deleteCollection(name: string): Promise<boolean> {\n const filePath = join(this.collectionsDir, `${this.sanitizeName(name)}.json`)\n try {\n await unlink(filePath)\n return true\n } catch {\n return false\n }\n }\n\n // ── Environments ──\n\n async createEnvironment(env: Environment): Promise<void> {\n await this.ensureDir('environments')\n const filePath = join(this.environmentsDir, `${this.sanitizeName(env.name)}.json`)\n await this.writeJson(filePath, env)\n }\n\n async getEnvironment(name: string): Promise<Environment | null> {\n const filePath = join(this.environmentsDir, `${this.sanitizeName(name)}.json`)\n return this.readJson<Environment>(filePath)\n }\n\n async listEnvironments(): Promise<EnvironmentListItem[]> {\n await this.ensureDir('environments')\n const files = await this.listJsonFiles(this.environmentsDir)\n const activeEnv = await this.getActiveEnvironment()\n const items: EnvironmentListItem[] = []\n\n for (const file of files) {\n const env = await this.readJson<Environment>(join(this.environmentsDir, file))\n if (!env) continue\n\n items.push({\n name: env.name,\n active: env.name === activeEnv,\n variableCount: Object.keys(env.variables).length,\n })\n }\n\n return items\n }\n\n async updateEnvironment(name: string, variables: Record<string, string>): Promise<void> {\n const env = await this.getEnvironment(name)\n if (!env) {\n throw new Error(`Entorno '${name}' no encontrado`)\n }\n\n env.variables = { ...env.variables, ...variables }\n env.updatedAt = new Date().toISOString()\n\n const filePath = join(this.environmentsDir, `${this.sanitizeName(name)}.json`)\n await this.writeJson(filePath, env)\n }\n\n async getActiveEnvironment(): Promise<string | null> {\n try {\n const content = await readFile(this.activeEnvFile, 'utf-8')\n return content.trim() || null\n } catch {\n return null\n }\n }\n\n async setActiveEnvironment(name: string): Promise<void> {\n // Verificar que el entorno existe\n const env = await this.getEnvironment(name)\n if (!env) {\n throw new Error(`Entorno '${name}' no encontrado`)\n }\n\n await this.ensureDir('')\n await writeFile(this.activeEnvFile, name, 'utf-8')\n }\n\n /**\n * Carga las variables del entorno activo.\n * Retorna objeto vacío si no hay entorno activo.\n */\n async getActiveVariables(): Promise<Record<string, string>> {\n const activeName = await this.getActiveEnvironment()\n if (!activeName) return {}\n\n const env = await this.getEnvironment(activeName)\n return env?.variables ?? {}\n }\n\n // ── API Specs ──\n\n async saveSpec(spec: ApiSpec): Promise<void> {\n await this.ensureDir('specs')\n const filePath = join(this.specsDir, `${this.sanitizeName(spec.name)}.json`)\n await this.writeJson(filePath, spec)\n }\n\n async getSpec(name: string): Promise<ApiSpec | null> {\n const filePath = join(this.specsDir, `${this.sanitizeName(name)}.json`)\n return this.readJson<ApiSpec>(filePath)\n }\n\n async listSpecs(): Promise<ApiSpecListItem[]> {\n await this.ensureDir('specs')\n const files = await this.listJsonFiles(this.specsDir)\n const items: ApiSpecListItem[] = []\n\n for (const file of files) {\n const spec = await this.readJson<ApiSpec>(join(this.specsDir, file))\n if (!spec) continue\n\n items.push({\n name: spec.name,\n source: spec.source,\n endpointCount: spec.endpoints.length,\n version: spec.version,\n })\n }\n\n return items\n }\n\n async deleteSpec(name: string): Promise<boolean> {\n const filePath = join(this.specsDir, `${this.sanitizeName(name)}.json`)\n try {\n await unlink(filePath)\n return true\n } catch {\n return false\n }\n }\n\n // ── Internal ──\n\n private async ensureDir(subdir: string): Promise<void> {\n const dir = subdir ? join(this.baseDir, subdir) : this.baseDir\n await mkdir(dir, { recursive: true })\n }\n\n private async readJson<T>(filePath: string): Promise<T | null> {\n try {\n const content = await readFile(filePath, 'utf-8')\n return JSON.parse(content) as T\n } catch {\n return null\n }\n }\n\n private async writeJson(filePath: string, data: unknown): Promise<void> {\n await writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8')\n }\n\n private async listJsonFiles(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir)\n return entries.filter((f) => f.endsWith('.json')).sort()\n } catch {\n return []\n }\n }\n\n /**\n * Sanitiza un nombre para usarlo como nombre de archivo.\n * Reemplaza caracteres no alfanuméricos por guiones.\n */\n private sanitizeName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9_-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n }\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { executeRequest } from '../lib/http-client.js'\nimport { interpolateRequest } from '../lib/interpolation.js'\nimport type { RequestConfig } from '../lib/types.js'\n\nconst AuthSchema = {\n type: z.enum(['bearer', 'api-key', 'basic']).describe('Tipo de autenticación'),\n token: z.string().optional().describe('Token para Bearer auth'),\n key: z.string().optional().describe('API key value'),\n header: z.string().optional().describe('Header name para API key (default: X-API-Key)'),\n username: z.string().optional().describe('Username para Basic auth'),\n password: z.string().optional().describe('Password para Basic auth'),\n}\n\nexport function registerRequestTool(server: McpServer, storage: Storage): void {\n server.tool(\n 'request',\n 'Ejecuta un HTTP request. URLs relativas (/path) usan BASE_URL del entorno activo. Soporta {{variables}}.',\n {\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('HTTP method'),\n url: z\n .string()\n .describe(\n 'URL del endpoint. Si empieza con / se antepone BASE_URL del entorno activo. Soporta {{variables}}.',\n ),\n headers: z\n .record(z.string())\n .optional()\n .describe('Headers HTTP como key-value pairs'),\n body: z.any().optional().describe('Body del request (JSON). Soporta {{variables}}'),\n query: z\n .record(z.string())\n .optional()\n .describe('Query parameters como key-value pairs'),\n timeout: z.number().optional().describe('Timeout en milisegundos (default: 30000)'),\n auth: z\n .object(AuthSchema)\n .optional()\n .describe('Configuración de autenticación'),\n },\n async (params) => {\n try {\n // Cargar variables del entorno activo\n const variables = await storage.getActiveVariables()\n\n // Auto-prepend BASE_URL para URLs relativas (empiezan con /)\n let resolvedUrl = params.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n // Quitar trailing slash de BASE_URL para evitar doble slash\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n // Construir RequestConfig\n const config: RequestConfig = {\n method: params.method,\n url: resolvedUrl,\n headers: params.headers,\n body: params.body,\n query: params.query,\n timeout: params.timeout,\n auth: params.auth,\n }\n\n // Interpolar variables\n const interpolated = interpolateRequest(config, variables)\n\n // Ejecutar request\n const response = await executeRequest(interpolated)\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(response, null, 2),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import type { RequestConfig, RequestResponse, AuthConfig } from './types.js'\n\nconst DEFAULT_TIMEOUT = 30_000\n\n/**\n * Aplica la configuración de auth a los headers del request.\n */\nfunction applyAuth(\n headers: Record<string, string>,\n auth: AuthConfig,\n): Record<string, string> {\n const result = { ...headers }\n\n switch (auth.type) {\n case 'bearer':\n if (auth.token) {\n result['Authorization'] = `Bearer ${auth.token}`\n }\n break\n\n case 'api-key':\n if (auth.key) {\n const headerName = auth.header ?? 'X-API-Key'\n result[headerName] = auth.key\n }\n break\n\n case 'basic':\n if (auth.username && auth.password) {\n const credentials = Buffer.from(`${auth.username}:${auth.password}`).toString('base64')\n result['Authorization'] = `Basic ${credentials}`\n }\n break\n }\n\n return result\n}\n\n/**\n * Construye la URL final con query parameters.\n */\nfunction buildUrl(baseUrl: string, query?: Record<string, string>): string {\n const url = new URL(baseUrl)\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n url.searchParams.set(key, value)\n }\n }\n\n return url.toString()\n}\n\n/**\n * Ejecuta un HTTP request y retorna la respuesta con métricas de timing.\n */\nexport async function executeRequest(config: RequestConfig): Promise<RequestResponse> {\n const timeout = config.timeout ?? DEFAULT_TIMEOUT\n\n // Construir URL con query params\n const url = buildUrl(config.url, config.query)\n\n // Preparar headers\n let headers: Record<string, string> = { ...config.headers }\n\n // Aplicar auth\n if (config.auth) {\n headers = applyAuth(headers, config.auth)\n }\n\n // Preparar body\n let body: string | undefined\n if (config.body !== undefined && config.body !== null) {\n if (typeof config.body === 'string') {\n body = config.body\n } else {\n body = JSON.stringify(config.body)\n // Solo añadir Content-Type si no está definido\n if (!headers['Content-Type'] && !headers['content-type']) {\n headers['Content-Type'] = 'application/json'\n }\n }\n }\n\n // AbortController para timeout\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n // Medir timing\n const startTime = performance.now()\n\n try {\n const response = await fetch(url, {\n method: config.method,\n headers,\n body,\n signal: controller.signal,\n })\n\n const endTime = performance.now()\n const totalMs = Math.round((endTime - startTime) * 100) / 100\n\n // Parsear response body\n const responseText = await response.text()\n let responseBody: unknown\n try {\n responseBody = JSON.parse(responseText)\n } catch {\n responseBody = responseText\n }\n\n // Convertir headers a Record\n const responseHeaders: Record<string, string> = {}\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value\n })\n\n // Calcular tamaño\n const sizeBytes =\n Number(response.headers.get('content-length')) ||\n Buffer.byteLength(responseText, 'utf-8')\n\n return {\n status: response.status,\n statusText: response.statusText,\n headers: responseHeaders,\n body: responseBody,\n timing: { total_ms: totalMs },\n size_bytes: sizeBytes,\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n throw new Error(`Request timeout: superado el límite de ${timeout}ms`)\n }\n throw error\n } finally {\n clearTimeout(timeoutId)\n }\n}\n","import type { RequestConfig } from './types.js'\n\nconst VARIABLE_PATTERN = /\\{\\{(\\w+)\\}\\}/g\n\n/**\n * Resuelve todas las ocurrencias de {{variable}} en un string.\n * Las variables no encontradas se dejan intactas.\n */\nexport function interpolateString(\n template: string,\n variables: Record<string, string>,\n): string {\n return template.replace(VARIABLE_PATTERN, (match, varName: string) => {\n return varName in variables ? variables[varName] : match\n })\n}\n\n/**\n * Interpola {{variables}} recursivamente en un valor.\n * - string → interpolateString\n * - object → interpola cada valor (recursivo)\n * - array → interpola cada elemento\n * - otros tipos → retorna sin cambios\n */\nfunction interpolateValue(value: unknown, variables: Record<string, string>): unknown {\n if (typeof value === 'string') {\n return interpolateString(value, variables)\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => interpolateValue(item, variables))\n }\n\n if (value !== null && typeof value === 'object') {\n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value)) {\n result[key] = interpolateValue(val, variables)\n }\n return result\n }\n\n return value\n}\n\n/**\n * Interpola un Record<string, string> (headers, query params).\n * Solo interpola los valores, no las keys.\n */\nfunction interpolateRecord(\n record: Record<string, string> | undefined,\n variables: Record<string, string>,\n): Record<string, string> | undefined {\n if (!record) return undefined\n\n const result: Record<string, string> = {}\n for (const [key, value] of Object.entries(record)) {\n result[key] = interpolateString(value, variables)\n }\n return result\n}\n\n/**\n * Resuelve {{variables}} en todos los campos de un RequestConfig:\n * url, headers (valores), body (recursivo), query params (valores).\n */\nexport function interpolateRequest(\n config: RequestConfig,\n variables: Record<string, string>,\n): RequestConfig {\n return {\n ...config,\n url: interpolateString(config.url, variables),\n headers: interpolateRecord(config.headers, variables),\n query: interpolateRecord(config.query, variables),\n body: config.body !== undefined ? interpolateValue(config.body, variables) : undefined,\n }\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport type { SavedRequest } from '../lib/types.js'\n\nconst AuthSchema = {\n type: z.enum(['bearer', 'api-key', 'basic']).describe('Tipo de autenticación'),\n token: z.string().optional().describe('Token para Bearer auth'),\n key: z.string().optional().describe('API key value'),\n header: z.string().optional().describe('Header name para API key (default: X-API-Key)'),\n username: z.string().optional().describe('Username para Basic auth'),\n password: z.string().optional().describe('Password para Basic auth'),\n}\n\nexport function registerCollectionTools(server: McpServer, storage: Storage): void {\n // ── collection_save ──\n server.tool(\n 'collection_save',\n 'Guarda un request en la colección local. Si ya existe un request con el mismo nombre, lo sobreescribe.',\n {\n name: z.string().describe('Nombre único del request guardado'),\n request: z\n .object({\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']),\n url: z.string(),\n headers: z.record(z.string()).optional(),\n body: z.any().optional(),\n query: z.record(z.string()).optional(),\n auth: z.object(AuthSchema).optional(),\n })\n .describe('Configuración del request a guardar'),\n tags: z\n .array(z.string())\n .optional()\n .describe('Tags para organizar (ej: [\"auth\", \"users\"])'),\n },\n async (params) => {\n try {\n const now = new Date().toISOString()\n const existing = await storage.getCollection(params.name)\n\n const saved: SavedRequest = {\n name: params.name,\n request: params.request,\n tags: params.tags,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n }\n\n await storage.saveCollection(saved)\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Request '${params.name}' guardado (${params.request.method} ${params.request.url})`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── collection_list ──\n server.tool(\n 'collection_list',\n 'Lista todos los requests guardados en la colección. Opcionalmente filtra por tag.',\n {\n tag: z.string().optional().describe('Filtrar por tag'),\n },\n async (params) => {\n try {\n const items = await storage.listCollections(params.tag)\n\n if (items.length === 0) {\n const msg = params.tag\n ? `No hay requests con tag '${params.tag}'`\n : 'La colección está vacía'\n return { content: [{ type: 'text' as const, text: msg }] }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(items, null, 2),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── collection_get ──\n server.tool(\n 'collection_get',\n 'Obtiene los detalles completos de un request guardado por su nombre.',\n {\n name: z.string().describe('Nombre del request guardado'),\n },\n async (params) => {\n try {\n const saved = await storage.getCollection(params.name)\n\n if (!saved) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Request '${params.name}' no encontrado`,\n },\n ],\n isError: true,\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(saved, null, 2),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── collection_delete ──\n server.tool(\n 'collection_delete',\n 'Elimina un request guardado de la colección.',\n {\n name: z.string().describe('Nombre del request a eliminar'),\n },\n async (params) => {\n try {\n const deleted = await storage.deleteCollection(params.name)\n\n if (!deleted) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Request '${params.name}' no encontrado`,\n },\n ],\n isError: true,\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Request '${params.name}' eliminado`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport type { Environment } from '../lib/types.js'\n\nexport function registerEnvironmentTools(server: McpServer, storage: Storage): void {\n // ── env_create ──\n server.tool(\n 'env_create',\n 'Crea un nuevo entorno (ej: dev, staging, prod) con variables opcionales.',\n {\n name: z.string().describe('Nombre del entorno (ej: dev, staging, prod)'),\n variables: z\n .record(z.string())\n .optional()\n .describe('Variables iniciales como key-value'),\n },\n async (params) => {\n try {\n const now = new Date().toISOString()\n const env: Environment = {\n name: params.name,\n variables: params.variables ?? {},\n createdAt: now,\n updatedAt: now,\n }\n\n await storage.createEnvironment(env)\n\n const varCount = Object.keys(env.variables).length\n return {\n content: [\n {\n type: 'text' as const,\n text: `Entorno '${params.name}' creado con ${varCount} variable(s)`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── env_list ──\n server.tool(\n 'env_list',\n 'Lista todos los entornos disponibles e indica cuál está activo.',\n {},\n async () => {\n try {\n const items = await storage.listEnvironments()\n\n if (items.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No hay entornos configurados' }],\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(items, null, 2),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── env_set ──\n server.tool(\n 'env_set',\n 'Establece una variable en un entorno. Si no se especifica entorno, usa el activo.',\n {\n key: z.string().describe('Nombre de la variable'),\n value: z.string().describe('Valor de la variable'),\n environment: z\n .string()\n .optional()\n .describe('Entorno destino (default: entorno activo)'),\n },\n async (params) => {\n try {\n // Determinar entorno destino\n const envName = params.environment ?? (await storage.getActiveEnvironment())\n\n if (!envName) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'No hay entorno activo. Usa env_create para crear uno y env_switch para activarlo.',\n },\n ],\n isError: true,\n }\n }\n\n await storage.updateEnvironment(envName, { [params.key]: params.value })\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Variable '${params.key}' establecida en entorno '${envName}'`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── env_get ──\n server.tool(\n 'env_get',\n 'Obtiene una variable específica o todas las variables de un entorno.',\n {\n key: z\n .string()\n .optional()\n .describe('Variable específica. Si se omite, retorna todas'),\n environment: z\n .string()\n .optional()\n .describe('Entorno a consultar (default: entorno activo)'),\n },\n async (params) => {\n try {\n const envName = params.environment ?? (await storage.getActiveEnvironment())\n\n if (!envName) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'No hay entorno activo. Usa env_switch para activar uno.',\n },\n ],\n isError: true,\n }\n }\n\n const env = await storage.getEnvironment(envName)\n if (!env) {\n return {\n content: [\n { type: 'text' as const, text: `Entorno '${envName}' no encontrado` },\n ],\n isError: true,\n }\n }\n\n if (params.key) {\n const value = env.variables[params.key]\n if (value === undefined) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Variable '${params.key}' no encontrada en entorno '${envName}'`,\n },\n ],\n isError: true,\n }\n }\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ key: params.key, value, environment: envName }, null, 2),\n },\n ],\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { environment: envName, variables: env.variables },\n null,\n 2,\n ),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── env_switch ──\n server.tool(\n 'env_switch',\n 'Cambia el entorno activo. Las variables del entorno activo se usan en {{interpolación}}.',\n {\n name: z.string().describe('Nombre del entorno a activar'),\n },\n async (params) => {\n try {\n await storage.setActiveEnvironment(params.name)\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Entorno activo cambiado a '${params.name}'`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { parseOpenApiSpec } from '../lib/openapi-parser.js'\nimport { readFile } from 'node:fs/promises'\n\nexport function registerApiSpecTools(server: McpServer, storage: Storage): void {\n // ── api_import ──\n\n server.tool(\n 'api_import',\n 'Importa un spec OpenAPI/Swagger desde una URL o archivo local. Guarda los endpoints y schemas para consulta.',\n {\n name: z\n .string()\n .describe('Nombre para identificar este API (ej: \"mi-backend\", \"cocaxcode-api\")'),\n source: z\n .string()\n .describe(\n 'URL del spec OpenAPI JSON (ej: http://localhost:3001/api-docs-json) o ruta a archivo local',\n ),\n },\n async (params) => {\n try {\n let rawDoc: Record<string, unknown>\n\n if (params.source.startsWith('http://') || params.source.startsWith('https://')) {\n // Fetch from URL\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 30000)\n\n try {\n const response = await fetch(params.source, { signal: controller.signal })\n if (!response.ok) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: No se pudo descargar el spec. Status: ${response.status} ${response.statusText}`,\n },\n ],\n isError: true,\n }\n }\n rawDoc = (await response.json()) as Record<string, unknown>\n } finally {\n clearTimeout(timeout)\n }\n } else {\n // Read from local file\n try {\n const content = await readFile(params.source, 'utf-8')\n rawDoc = JSON.parse(content) as Record<string, unknown>\n } catch {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: No se pudo leer el archivo '${params.source}'. Verifica que existe y es JSON válido.`,\n },\n ],\n isError: true,\n }\n }\n }\n\n // Validate it looks like OpenAPI\n if (!rawDoc.openapi && !rawDoc.swagger) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'Error: El documento no parece ser un spec OpenAPI/Swagger válido. Falta la propiedad \"openapi\" o \"swagger\".',\n },\n ],\n isError: true,\n }\n }\n\n // Parse and save\n const spec = parseOpenApiSpec(rawDoc, params.name, params.source)\n await storage.saveSpec(spec)\n\n // Build summary\n const tagCounts: Record<string, number> = {}\n for (const ep of spec.endpoints) {\n for (const tag of ep.tags ?? ['sin-tag']) {\n tagCounts[tag] = (tagCounts[tag] ?? 0) + 1\n }\n }\n\n const tagSummary = Object.entries(tagCounts)\n .map(([tag, count]) => ` - ${tag}: ${count} endpoints`)\n .join('\\n')\n\n const schemaCount = Object.keys(spec.schemas).length\n\n return {\n content: [\n {\n type: 'text' as const,\n text: [\n `API '${params.name}' importada correctamente.`,\n '',\n `Versión: ${spec.version ?? 'no especificada'}`,\n `Endpoints: ${spec.endpoints.length}`,\n `Schemas: ${schemaCount}`,\n '',\n 'Endpoints por tag:',\n tagSummary,\n '',\n 'Usa api_endpoints para ver los endpoints disponibles.',\n 'Usa api_endpoint_detail para ver el detalle de un endpoint específico.',\n ].join('\\n'),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── api_endpoints ──\n\n server.tool(\n 'api_endpoints',\n 'Lista los endpoints de un API importada. Filtra por tag, método o path.',\n {\n name: z\n .string()\n .describe('Nombre del API importada'),\n tag: z\n .string()\n .optional()\n .describe('Filtrar por tag (ej: \"blog\", \"auth\", \"users\")'),\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .optional()\n .describe('Filtrar por método HTTP'),\n path: z\n .string()\n .optional()\n .describe('Filtrar por path (búsqueda parcial, ej: \"/blog\" muestra todos los que contienen /blog)'),\n },\n async (params) => {\n try {\n const spec = await storage.getSpec(params.name)\n if (!spec) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: API '${params.name}' no encontrada. Usa api_import para importarla primero.`,\n },\n ],\n isError: true,\n }\n }\n\n let endpoints = spec.endpoints\n\n // Apply filters\n if (params.tag) {\n endpoints = endpoints.filter((ep) =>\n (ep.tags ?? []).some((t) => t.toLowerCase() === params.tag!.toLowerCase()),\n )\n }\n if (params.method) {\n endpoints = endpoints.filter((ep) => ep.method === params.method)\n }\n if (params.path) {\n const search = params.path.toLowerCase()\n endpoints = endpoints.filter((ep) => ep.path.toLowerCase().includes(search))\n }\n\n if (endpoints.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'No se encontraron endpoints con los filtros aplicados.',\n },\n ],\n }\n }\n\n // Format output\n const lines = endpoints.map((ep) => {\n const tags = ep.tags?.length ? ` [${ep.tags.join(', ')}]` : ''\n const summary = ep.summary ? ` — ${ep.summary}` : ''\n return `${ep.method.padEnd(7)} ${ep.path}${summary}${tags}`\n })\n\n return {\n content: [\n {\n type: 'text' as const,\n text: [\n `API: ${spec.name} (${endpoints.length} endpoints)`,\n '',\n ...lines,\n '',\n 'Usa api_endpoint_detail para ver parámetros, body y respuestas de un endpoint.',\n ].join('\\n'),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── api_endpoint_detail ──\n\n server.tool(\n 'api_endpoint_detail',\n 'Muestra el detalle completo de un endpoint: parámetros, body schema, y respuestas. Útil para saber qué datos enviar.',\n {\n name: z\n .string()\n .describe('Nombre del API importada'),\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('Método HTTP del endpoint'),\n path: z\n .string()\n .describe('Path exacto del endpoint (ej: \"/blog\", \"/auth/login\")'),\n },\n async (params) => {\n try {\n const spec = await storage.getSpec(params.name)\n if (!spec) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: API '${params.name}' no encontrada. Usa api_import para importarla primero.`,\n },\n ],\n isError: true,\n }\n }\n\n const endpoint = spec.endpoints.find(\n (ep) => ep.method === params.method && ep.path === params.path,\n )\n\n if (!endpoint) {\n // Try partial match\n const similar = spec.endpoints.filter((ep) =>\n ep.path.includes(params.path) || params.path.includes(ep.path),\n )\n\n const suggestion = similar.length > 0\n ? `\\n\\nEndpoints similares:\\n${similar.map((ep) => ` ${ep.method} ${ep.path}`).join('\\n')}`\n : ''\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: Endpoint ${params.method} ${params.path} no encontrado.${suggestion}`,\n },\n ],\n isError: true,\n }\n }\n\n // Build detailed output\n const sections: string[] = []\n\n // Header\n sections.push(`## ${endpoint.method} ${endpoint.path}`)\n if (endpoint.summary) sections.push(`**${endpoint.summary}**`)\n if (endpoint.description) sections.push(endpoint.description)\n if (endpoint.tags?.length) sections.push(`Tags: ${endpoint.tags.join(', ')}`)\n\n // Parameters\n if (endpoint.parameters?.length) {\n sections.push('')\n sections.push('### Parámetros')\n for (const param of endpoint.parameters) {\n const required = param.required ? ' (requerido)' : ' (opcional)'\n const type = param.schema?.type ?? 'string'\n const desc = param.description ? ` — ${param.description}` : ''\n sections.push(`- **${param.name}** [${param.in}] ${type}${required}${desc}`)\n }\n }\n\n // Request body\n if (endpoint.requestBody) {\n sections.push('')\n sections.push('### Body')\n const required = endpoint.requestBody.required ? ' (requerido)' : ' (opcional)'\n sections.push(`Body${required}`)\n\n if (endpoint.requestBody.content) {\n for (const [contentType, media] of Object.entries(endpoint.requestBody.content)) {\n sections.push(`\\nContent-Type: ${contentType}`)\n if (media.schema) {\n sections.push('```json')\n sections.push(formatSchema(media.schema))\n sections.push('```')\n }\n }\n }\n }\n\n // Responses\n if (endpoint.responses) {\n sections.push('')\n sections.push('### Respuestas')\n for (const [status, resp] of Object.entries(endpoint.responses)) {\n const desc = resp.description ? ` — ${resp.description}` : ''\n sections.push(`\\n**${status}**${desc}`)\n\n if (resp.content) {\n for (const [, media] of Object.entries(resp.content)) {\n if (media.schema) {\n sections.push('```json')\n sections.push(formatSchema(media.schema))\n sections.push('```')\n }\n }\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: sections.join('\\n'),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n\n/**\n * Formatea un schema como ejemplo JSON legible.\n * Genera un ejemplo basado en los tipos y propiedades del schema.\n */\nfunction formatSchema(schema: { type?: string; properties?: Record<string, unknown>; items?: unknown; required?: string[]; enum?: unknown[]; example?: unknown; format?: string; description?: string }, depth = 0): string {\n if (depth > 5) return '\"...\"'\n\n const indent = ' '.repeat(depth)\n const innerIndent = ' '.repeat(depth + 1)\n\n if (schema.example !== undefined) {\n return JSON.stringify(schema.example, null, 2)\n .split('\\n')\n .map((line, i) => (i === 0 ? line : indent + line))\n .join('\\n')\n }\n\n if (schema.enum) {\n return JSON.stringify(schema.enum[0])\n }\n\n if (schema.type === 'object' && schema.properties) {\n const props = Object.entries(schema.properties as Record<string, Record<string, unknown>>)\n if (props.length === 0) return '{}'\n\n const requiredFields = new Set(schema.required ?? [])\n const lines: string[] = ['{']\n\n for (const [key, prop] of props) {\n const isRequired = requiredFields.has(key)\n const comment = []\n if (prop.description) comment.push(prop.description as string)\n if (!isRequired) comment.push('opcional')\n const commentStr = comment.length > 0 ? ` // ${comment.join(' — ')}` : ''\n\n const value = formatSchema(prop as typeof schema, depth + 1)\n lines.push(`${innerIndent}\"${key}\": ${value},${commentStr}`)\n }\n\n lines.push(`${indent}}`)\n return lines.join('\\n')\n }\n\n if (schema.type === 'array' && schema.items) {\n const itemValue = formatSchema(schema.items as typeof schema, depth + 1)\n return `[${itemValue}]`\n }\n\n // Primitive types\n switch (schema.type) {\n case 'string':\n if (schema.format === 'date-time') return '\"2024-01-01T00:00:00Z\"'\n if (schema.format === 'email') return '\"user@example.com\"'\n if (schema.format === 'uri' || schema.format === 'url') return '\"https://example.com\"'\n return '\"string\"'\n case 'number':\n case 'integer':\n return '0'\n case 'boolean':\n return 'true'\n default:\n return 'null'\n }\n}\n","import type {\n HttpMethod,\n ApiSpecEndpoint,\n ApiSpecSchema,\n ApiSpec,\n} from './types.js'\n\nconst VALID_METHODS: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']\n\n/**\n * Resuelve $ref references en un schema OpenAPI.\n * Soporta refs tipo \"#/components/schemas/MyModel\".\n */\nfunction resolveRef(\n ref: string,\n root: Record<string, unknown>,\n): ApiSpecSchema | undefined {\n const parts = ref.replace(/^#\\//, '').split('/')\n let current: unknown = root\n\n for (const part of parts) {\n if (current && typeof current === 'object' && part in current) {\n current = (current as Record<string, unknown>)[part]\n } else {\n return undefined\n }\n }\n\n return current as ApiSpecSchema\n}\n\n/**\n * Resuelve recursivamente todos los $ref en un schema.\n */\nfunction resolveSchema(\n schema: ApiSpecSchema | undefined,\n root: Record<string, unknown>,\n depth = 0,\n): ApiSpecSchema | undefined {\n if (!schema || depth > 10) return schema\n\n if (schema.$ref) {\n const resolved = resolveRef(schema.$ref, root)\n if (resolved) {\n return resolveSchema(resolved, root, depth + 1)\n }\n return { type: 'object', description: `Unresolved: ${schema.$ref}` }\n }\n\n const result: ApiSpecSchema = { ...schema }\n\n // Resolve properties recursively\n if (result.properties) {\n const resolvedProps: Record<string, ApiSpecSchema> = {}\n for (const [key, prop] of Object.entries(result.properties)) {\n resolvedProps[key] = resolveSchema(prop, root, depth + 1) ?? prop\n }\n result.properties = resolvedProps\n }\n\n // Resolve array items\n if (result.items) {\n result.items = resolveSchema(result.items, root, depth + 1) ?? result.items\n }\n\n return result\n}\n\n/**\n * Parsea un documento OpenAPI 3.x y extrae endpoints y schemas.\n */\nexport function parseOpenApiSpec(\n doc: Record<string, unknown>,\n name: string,\n source: string,\n): ApiSpec {\n const info = doc.info as Record<string, unknown> | undefined\n const paths = doc.paths as Record<string, Record<string, unknown>> | undefined\n const components = doc.components as Record<string, unknown> | undefined\n const rawSchemas = (components?.schemas ?? {}) as Record<string, ApiSpecSchema>\n\n // Resolve all schemas\n const schemas: Record<string, ApiSpecSchema> = {}\n for (const [schemaName, schema] of Object.entries(rawSchemas)) {\n schemas[schemaName] = resolveSchema(schema, doc, 0) ?? schema\n }\n\n const endpoints: ApiSpecEndpoint[] = []\n\n if (paths) {\n for (const [path, pathItem] of Object.entries(paths)) {\n for (const [method, operation] of Object.entries(pathItem)) {\n const upperMethod = method.toUpperCase() as HttpMethod\n if (!VALID_METHODS.includes(upperMethod)) continue\n\n const op = operation as Record<string, unknown>\n\n // Parse parameters\n const rawParams = (op.parameters ?? []) as Array<Record<string, unknown>>\n const parameters = rawParams.map((p) => ({\n name: p.name as string,\n in: p.in as 'path' | 'query' | 'header' | 'cookie',\n required: p.required as boolean | undefined,\n description: p.description as string | undefined,\n schema: resolveSchema(p.schema as ApiSpecSchema | undefined, doc),\n }))\n\n // Parse request body\n const rawBody = op.requestBody as Record<string, unknown> | undefined\n let requestBody = undefined\n if (rawBody) {\n const bodyContent = rawBody.content as Record<string, Record<string, unknown>> | undefined\n const resolvedContent: Record<string, { schema?: ApiSpecSchema }> = {}\n\n if (bodyContent) {\n for (const [contentType, mediaType] of Object.entries(bodyContent)) {\n resolvedContent[contentType] = {\n schema: resolveSchema(mediaType.schema as ApiSpecSchema | undefined, doc),\n }\n }\n }\n\n requestBody = {\n required: rawBody.required as boolean | undefined,\n description: rawBody.description as string | undefined,\n content: resolvedContent,\n }\n }\n\n // Parse responses\n const rawResponses = (op.responses ?? {}) as Record<string, Record<string, unknown>>\n const responses: Record<string, { description?: string; content?: Record<string, { schema?: ApiSpecSchema }> }> = {}\n\n for (const [statusCode, resp] of Object.entries(rawResponses)) {\n const respContent = resp.content as Record<string, Record<string, unknown>> | undefined\n const resolvedRespContent: Record<string, { schema?: ApiSpecSchema }> = {}\n\n if (respContent) {\n for (const [contentType, mediaType] of Object.entries(respContent)) {\n resolvedRespContent[contentType] = {\n schema: resolveSchema(mediaType.schema as ApiSpecSchema | undefined, doc),\n }\n }\n }\n\n responses[statusCode] = {\n description: resp.description as string | undefined,\n content: respContent ? resolvedRespContent : undefined,\n }\n }\n\n endpoints.push({\n method: upperMethod,\n path,\n summary: op.summary as string | undefined,\n description: op.description as string | undefined,\n tags: op.tags as string[] | undefined,\n parameters,\n requestBody,\n responses,\n })\n }\n }\n }\n\n const now = new Date().toISOString()\n\n return {\n name,\n source,\n version: info?.version as string | undefined,\n endpoints,\n schemas,\n importedAt: now,\n updatedAt: now,\n }\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { executeRequest } from '../lib/http-client.js'\nimport { interpolateRequest } from '../lib/interpolation.js'\nimport type { RequestConfig, RequestResponse } from '../lib/types.js'\n\nconst AssertionSchema = z.object({\n path: z\n .string()\n .describe(\n 'JSONPath al valor a validar: \"status\", \"body.data.id\", \"headers.content-type\", \"timing.total_ms\"',\n ),\n operator: z\n .enum(['eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'contains', 'not_contains', 'exists', 'type'])\n .describe(\n 'Operador: eq (igual), neq (no igual), gt/gte/lt/lte (numéricos), contains/not_contains (strings/arrays), exists (campo existe), type (typeof)',\n ),\n expected: z.any().optional().describe('Valor esperado (no necesario para \"exists\")'),\n})\n\n/**\n * Accede a un valor en un objeto usando dot notation.\n * Ej: getByPath({ body: { data: { id: 1 } } }, \"body.data.id\") → 1\n */\nfunction getByPath(obj: unknown, path: string): unknown {\n const parts = path.split('.')\n let current: unknown = obj\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined\n if (typeof current === 'object') {\n current = (current as Record<string, unknown>)[part]\n } else {\n return undefined\n }\n }\n\n return current\n}\n\n/**\n * Evalúa una aserción contra una respuesta.\n */\nfunction evaluateAssertion(\n response: RequestResponse,\n assertion: { path: string; operator: string; expected?: unknown },\n): { pass: boolean; message: string } {\n const actual = getByPath(response, assertion.path)\n\n switch (assertion.operator) {\n case 'eq':\n return {\n pass: actual === assertion.expected,\n message: actual === assertion.expected\n ? `${assertion.path} === ${JSON.stringify(assertion.expected)}`\n : `${assertion.path}: esperado ${JSON.stringify(assertion.expected)}, recibido ${JSON.stringify(actual)}`,\n }\n\n case 'neq':\n return {\n pass: actual !== assertion.expected,\n message: actual !== assertion.expected\n ? `${assertion.path} !== ${JSON.stringify(assertion.expected)}`\n : `${assertion.path}: no debería ser ${JSON.stringify(assertion.expected)}`,\n }\n\n case 'gt':\n return {\n pass: typeof actual === 'number' && actual > (assertion.expected as number),\n message: `${assertion.path}: ${actual} > ${assertion.expected} → ${typeof actual === 'number' && actual > (assertion.expected as number)}`,\n }\n\n case 'gte':\n return {\n pass: typeof actual === 'number' && actual >= (assertion.expected as number),\n message: `${assertion.path}: ${actual} >= ${assertion.expected} → ${typeof actual === 'number' && actual >= (assertion.expected as number)}`,\n }\n\n case 'lt':\n return {\n pass: typeof actual === 'number' && actual < (assertion.expected as number),\n message: `${assertion.path}: ${actual} < ${assertion.expected} → ${typeof actual === 'number' && actual < (assertion.expected as number)}`,\n }\n\n case 'lte':\n return {\n pass: typeof actual === 'number' && actual <= (assertion.expected as number),\n message: `${assertion.path}: ${actual} <= ${assertion.expected} → ${typeof actual === 'number' && actual <= (assertion.expected as number)}`,\n }\n\n case 'contains': {\n let pass = false\n if (typeof actual === 'string') {\n pass = actual.includes(String(assertion.expected))\n } else if (Array.isArray(actual)) {\n pass = actual.includes(assertion.expected)\n }\n return {\n pass,\n message: pass\n ? `${assertion.path} contiene ${JSON.stringify(assertion.expected)}`\n : `${assertion.path}: no contiene ${JSON.stringify(assertion.expected)}`,\n }\n }\n\n case 'not_contains': {\n let pass = true\n if (typeof actual === 'string') {\n pass = !actual.includes(String(assertion.expected))\n } else if (Array.isArray(actual)) {\n pass = !actual.includes(assertion.expected)\n }\n return {\n pass,\n message: pass\n ? `${assertion.path} no contiene ${JSON.stringify(assertion.expected)}`\n : `${assertion.path}: contiene ${JSON.stringify(assertion.expected)} (no debería)`,\n }\n }\n\n case 'exists':\n return {\n pass: actual !== undefined && actual !== null,\n message: actual !== undefined && actual !== null\n ? `${assertion.path} existe`\n : `${assertion.path}: no existe`,\n }\n\n case 'type':\n return {\n pass: typeof actual === assertion.expected,\n message: typeof actual === assertion.expected\n ? `${assertion.path} es tipo ${assertion.expected}`\n : `${assertion.path}: esperado tipo ${assertion.expected}, recibido ${typeof actual}`,\n }\n\n default:\n return { pass: false, message: `Operador desconocido: ${assertion.operator}` }\n }\n}\n\nexport function registerAssertTool(server: McpServer, storage: Storage): void {\n server.tool(\n 'assert',\n 'Ejecuta un request y valida la respuesta con assertions. Retorna resultado pass/fail por cada assertion.',\n {\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('HTTP method'),\n url: z.string().describe('URL del endpoint (soporta /relativa y {{variables}})'),\n headers: z.record(z.string()).optional().describe('Headers HTTP'),\n body: z.any().optional().describe('Body del request (JSON)'),\n query: z.record(z.string()).optional().describe('Query parameters'),\n auth: z\n .object({\n type: z.enum(['bearer', 'api-key', 'basic']),\n token: z.string().optional(),\n key: z.string().optional(),\n header: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n })\n .optional()\n .describe('Autenticación'),\n assertions: z\n .array(AssertionSchema)\n .describe('Lista de assertions a validar contra la respuesta'),\n },\n async (params) => {\n try {\n const variables = await storage.getActiveVariables()\n\n // Auto-prepend BASE_URL for relative URLs\n let resolvedUrl = params.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n const config: RequestConfig = {\n method: params.method,\n url: resolvedUrl,\n headers: params.headers,\n body: params.body,\n query: params.query,\n auth: params.auth,\n }\n\n const interpolated = interpolateRequest(config, variables)\n const response = await executeRequest(interpolated)\n\n // Evaluate assertions\n const results = params.assertions.map((assertion) => {\n const result = evaluateAssertion(response, assertion)\n return { ...result, assertion }\n })\n\n const passed = results.filter((r) => r.pass).length\n const failed = results.filter((r) => !r.pass).length\n const allPassed = failed === 0\n\n const lines: string[] = [\n `${allPassed ? '✅ PASS' : '❌ FAIL'} — ${passed}/${results.length} assertions passed`,\n `${params.method} ${params.url} → ${response.status} ${response.statusText} (${response.timing.total_ms}ms)`,\n '',\n ]\n\n for (const r of results) {\n const icon = r.pass ? '✅' : '❌'\n lines.push(`${icon} ${r.message}`)\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n isError: !allPassed,\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { executeRequest } from '../lib/http-client.js'\nimport { interpolateRequest } from '../lib/interpolation.js'\nimport type { RequestConfig, RequestResponse } from '../lib/types.js'\n\nconst FlowStepSchema = z.object({\n name: z.string().describe('Nombre del paso (ej: \"login\", \"crear-post\")'),\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('HTTP method'),\n url: z.string().describe('URL del endpoint'),\n headers: z.record(z.string()).optional().describe('Headers HTTP'),\n body: z.any().optional().describe('Body del request'),\n query: z.record(z.string()).optional().describe('Query parameters'),\n auth: z\n .object({\n type: z.enum(['bearer', 'api-key', 'basic']),\n token: z.string().optional(),\n key: z.string().optional(),\n header: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n })\n .optional()\n .describe('Autenticación'),\n extract: z\n .record(z.string())\n .optional()\n .describe(\n 'Variables a extraer de la respuesta para pasos siguientes. Key = nombre variable, value = path (ej: { \"TOKEN\": \"body.token\", \"USER_ID\": \"body.data.id\" })',\n ),\n})\n\n/**\n * Accede a un valor en un objeto usando dot notation.\n */\nfunction getByPath(obj: unknown, path: string): unknown {\n const parts = path.split('.')\n let current: unknown = obj\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined\n if (typeof current === 'object') {\n // Handle array index access like \"data.0.id\"\n if (Array.isArray(current) && /^\\d+$/.test(part)) {\n current = current[parseInt(part)]\n } else {\n current = (current as Record<string, unknown>)[part]\n }\n } else {\n return undefined\n }\n }\n\n return current\n}\n\nexport function registerFlowTool(server: McpServer, storage: Storage): void {\n server.tool(\n 'flow_run',\n 'Ejecuta una secuencia de requests en orden. Extrae variables de cada respuesta para usar en pasos siguientes con {{variable}}.',\n {\n steps: z.array(FlowStepSchema).describe('Pasos a ejecutar en orden'),\n stop_on_error: z\n .boolean()\n .optional()\n .describe('Detener al primer error (default: true)'),\n },\n async (params) => {\n try {\n const stopOnError = params.stop_on_error ?? true\n const envVariables = await storage.getActiveVariables()\n const flowVariables: Record<string, string> = { ...envVariables }\n const results: Array<{\n name: string\n status: number\n timing: number\n extracted: Record<string, string>\n error?: string\n }> = []\n\n for (const step of params.steps) {\n try {\n // Auto-prepend BASE_URL for relative URLs\n let resolvedUrl = step.url\n if (resolvedUrl.startsWith('/') && flowVariables.BASE_URL) {\n const baseUrl = flowVariables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n const config: RequestConfig = {\n method: step.method,\n url: resolvedUrl,\n headers: step.headers,\n body: step.body,\n query: step.query,\n auth: step.auth,\n }\n\n // Interpolate with accumulated flow variables\n const interpolated = interpolateRequest(config, flowVariables)\n const response: RequestResponse = await executeRequest(interpolated)\n\n // Extract variables from response\n const extracted: Record<string, string> = {}\n if (step.extract) {\n for (const [varName, path] of Object.entries(step.extract)) {\n const value = getByPath(response, path)\n if (value !== undefined && value !== null) {\n extracted[varName] = String(value)\n flowVariables[varName] = String(value)\n }\n }\n }\n\n results.push({\n name: step.name,\n status: response.status,\n timing: response.timing.total_ms,\n extracted,\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n results.push({\n name: step.name,\n status: 0,\n timing: 0,\n extracted: {},\n error: message,\n })\n\n if (stopOnError) break\n }\n }\n\n // Build output\n const allOk = results.every((r) => !r.error && r.status >= 200 && r.status < 400)\n const lines: string[] = [\n `${allOk ? '✅ FLOW COMPLETO' : '❌ FLOW CON ERRORES'} — ${results.length}/${params.steps.length} pasos ejecutados`,\n '',\n ]\n\n for (let i = 0; i < results.length; i++) {\n const r = results[i]\n const icon = r.error ? '❌' : r.status >= 200 && r.status < 400 ? '✅' : '⚠️'\n lines.push(`${icon} Paso ${i + 1}: ${r.name}`)\n\n if (r.error) {\n lines.push(` Error: ${r.error}`)\n } else {\n lines.push(` Status: ${r.status} | Tiempo: ${r.timing}ms`)\n }\n\n if (Object.keys(r.extracted).length > 0) {\n const vars = Object.entries(r.extracted)\n .map(([k, v]) => `${k}=${v.length > 50 ? v.substring(0, 50) + '...' : v}`)\n .join(', ')\n lines.push(` Extraído: ${vars}`)\n }\n\n lines.push('')\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n isError: !allOk,\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { executeRequest } from '../lib/http-client.js'\nimport { interpolateRequest } from '../lib/interpolation.js'\nimport type { RequestConfig } from '../lib/types.js'\n\nexport function registerUtilityTools(server: McpServer, storage: Storage): void {\n // ── export_curl ──\n\n server.tool(\n 'export_curl',\n 'Genera un comando cURL a partir de un request guardado en la colección. Listo para copiar y pegar.',\n {\n name: z.string().describe('Nombre del request guardado en la colección'),\n resolve_variables: z\n .boolean()\n .optional()\n .describe('Resolver {{variables}} del entorno activo (default: true)'),\n },\n async (params) => {\n try {\n const saved = await storage.getCollection(params.name)\n if (!saved) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: Request '${params.name}' no encontrado en la colección.`,\n },\n ],\n isError: true,\n }\n }\n\n let config = saved.request\n const resolveVars = params.resolve_variables ?? true\n\n if (resolveVars) {\n const variables = await storage.getActiveVariables()\n\n // Auto-prepend BASE_URL for relative URLs\n let resolvedUrl = config.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n config = { ...config, url: resolvedUrl }\n config = interpolateRequest(config, variables)\n }\n\n // Build cURL command\n const parts: string[] = ['curl']\n\n // Method\n if (config.method !== 'GET') {\n parts.push(`-X ${config.method}`)\n }\n\n // URL with query params\n let url = config.url\n if (config.query && Object.keys(config.query).length > 0) {\n const queryStr = Object.entries(config.query)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&')\n url += (url.includes('?') ? '&' : '?') + queryStr\n }\n parts.push(`'${url}'`)\n\n // Headers\n if (config.headers) {\n for (const [key, value] of Object.entries(config.headers)) {\n parts.push(`-H '${key}: ${value}'`)\n }\n }\n\n // Auth headers\n if (config.auth) {\n switch (config.auth.type) {\n case 'bearer':\n if (config.auth.token) {\n parts.push(`-H 'Authorization: Bearer ${config.auth.token}'`)\n }\n break\n case 'api-key':\n if (config.auth.key) {\n const header = config.auth.header ?? 'X-API-Key'\n parts.push(`-H '${header}: ${config.auth.key}'`)\n }\n break\n case 'basic':\n if (config.auth.username && config.auth.password) {\n parts.push(`-u '${config.auth.username}:${config.auth.password}'`)\n }\n break\n }\n }\n\n // Body\n if (config.body !== undefined && config.body !== null) {\n const bodyStr =\n typeof config.body === 'string' ? config.body : JSON.stringify(config.body)\n parts.push(`-H 'Content-Type: application/json'`)\n parts.push(`-d '${bodyStr}'`)\n }\n\n const curlCommand = parts.join(' \\\\\\n ')\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `cURL para '${params.name}':\\n\\n${curlCommand}`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── diff_responses ──\n\n server.tool(\n 'diff_responses',\n 'Ejecuta dos requests y compara sus respuestas. Útil para detectar regresiones o comparar entornos.',\n {\n request_a: z\n .object({\n label: z.string().optional().describe('Etiqueta (ej: \"antes\", \"dev\", \"v1\")'),\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']),\n url: z.string(),\n headers: z.record(z.string()).optional(),\n body: z.any().optional(),\n query: z.record(z.string()).optional(),\n auth: z\n .object({\n type: z.enum(['bearer', 'api-key', 'basic']),\n token: z.string().optional(),\n key: z.string().optional(),\n header: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n })\n .optional(),\n })\n .describe('Primer request'),\n request_b: z\n .object({\n label: z.string().optional().describe('Etiqueta (ej: \"después\", \"prod\", \"v2\")'),\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']),\n url: z.string(),\n headers: z.record(z.string()).optional(),\n body: z.any().optional(),\n query: z.record(z.string()).optional(),\n auth: z\n .object({\n type: z.enum(['bearer', 'api-key', 'basic']),\n token: z.string().optional(),\n key: z.string().optional(),\n header: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n })\n .optional(),\n })\n .describe('Segundo request'),\n },\n async (params) => {\n try {\n const variables = await storage.getActiveVariables()\n\n // Helper to resolve and execute a request\n const executeOne = async (req: typeof params.request_a) => {\n let resolvedUrl = req.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n const config: RequestConfig = {\n method: req.method,\n url: resolvedUrl,\n headers: req.headers,\n body: req.body,\n query: req.query,\n auth: req.auth,\n }\n\n return executeRequest(interpolateRequest(config, variables))\n }\n\n const [responseA, responseB] = await Promise.all([\n executeOne(params.request_a),\n executeOne(params.request_b),\n ])\n\n const labelA = params.request_a.label ?? 'A'\n const labelB = params.request_b.label ?? 'B'\n\n const diffs: string[] = []\n\n // Compare status\n if (responseA.status !== responseB.status) {\n diffs.push(\n `Status: ${labelA}=${responseA.status} vs ${labelB}=${responseB.status}`,\n )\n }\n\n // Compare timing\n const timingDiff = Math.abs(responseA.timing.total_ms - responseB.timing.total_ms)\n if (timingDiff > 100) {\n diffs.push(\n `Timing: ${labelA}=${responseA.timing.total_ms}ms vs ${labelB}=${responseB.timing.total_ms}ms (Δ${Math.round(timingDiff)}ms)`,\n )\n }\n\n // Compare body\n const bodyA = JSON.stringify(responseA.body, null, 2)\n const bodyB = JSON.stringify(responseB.body, null, 2)\n\n if (bodyA !== bodyB) {\n diffs.push('Body: diferente')\n\n // Find specific key differences for objects\n if (\n typeof responseA.body === 'object' &&\n typeof responseB.body === 'object' &&\n responseA.body &&\n responseB.body\n ) {\n const keysA = new Set(Object.keys(responseA.body as Record<string, unknown>))\n const keysB = new Set(Object.keys(responseB.body as Record<string, unknown>))\n\n const onlyInA = [...keysA].filter((k) => !keysB.has(k))\n const onlyInB = [...keysB].filter((k) => !keysA.has(k))\n const common = [...keysA].filter((k) => keysB.has(k))\n\n if (onlyInA.length > 0) diffs.push(` Solo en ${labelA}: ${onlyInA.join(', ')}`)\n if (onlyInB.length > 0) diffs.push(` Solo en ${labelB}: ${onlyInB.join(', ')}`)\n\n for (const key of common) {\n const valA = JSON.stringify(\n (responseA.body as Record<string, unknown>)[key],\n )\n const valB = JSON.stringify(\n (responseB.body as Record<string, unknown>)[key],\n )\n if (valA !== valB) {\n const shortA = valA.length > 50 ? valA.substring(0, 50) + '...' : valA\n const shortB = valB.length > 50 ? valB.substring(0, 50) + '...' : valB\n diffs.push(` ${key}: ${labelA}=${shortA} vs ${labelB}=${shortB}`)\n }\n }\n }\n }\n\n // Compare size\n const sizeDiff = Math.abs(responseA.size_bytes - responseB.size_bytes)\n if (sizeDiff > 0) {\n diffs.push(\n `Size: ${labelA}=${responseA.size_bytes}B vs ${labelB}=${responseB.size_bytes}B`,\n )\n }\n\n const identical = diffs.length === 0\n\n const lines: string[] = [\n identical ? '✅ IDÉNTICAS' : `⚠️ ${diffs.length} DIFERENCIAS ENCONTRADAS`,\n '',\n `${labelA}: ${params.request_a.method} ${params.request_a.url} → ${responseA.status} (${responseA.timing.total_ms}ms)`,\n `${labelB}: ${params.request_b.method} ${params.request_b.url} → ${responseB.status} (${responseB.timing.total_ms}ms)`,\n ]\n\n if (!identical) {\n lines.push('')\n lines.push('Diferencias:')\n for (const diff of diffs) {\n lines.push(` ${diff}`)\n }\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n\n // ── bulk_test ──\n\n server.tool(\n 'bulk_test',\n 'Ejecuta todos los requests guardados en la colección y reporta resultados. Filtrable por tag.',\n {\n tag: z.string().optional().describe('Filtrar por tag'),\n expected_status: z\n .number()\n .optional()\n .describe('Status HTTP esperado para todos (default: cualquier 2xx)'),\n },\n async (params) => {\n try {\n const collections = await storage.listCollections(params.tag)\n if (collections.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: params.tag\n ? `No hay requests guardados con tag '${params.tag}'.`\n : 'No hay requests guardados en la colección.',\n },\n ],\n }\n }\n\n const variables = await storage.getActiveVariables()\n const results: Array<{\n name: string\n method: string\n url: string\n status: number\n timing: number\n pass: boolean\n error?: string\n }> = []\n\n for (const item of collections) {\n const saved = await storage.getCollection(item.name)\n if (!saved) continue\n\n try {\n let config = saved.request\n\n // Auto-prepend BASE_URL\n let resolvedUrl = config.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n config = { ...config, url: resolvedUrl }\n const interpolated = interpolateRequest(config, variables)\n const response = await executeRequest(interpolated)\n\n const pass = params.expected_status\n ? response.status === params.expected_status\n : response.status >= 200 && response.status < 300\n\n results.push({\n name: item.name,\n method: config.method,\n url: item.url,\n status: response.status,\n timing: response.timing.total_ms,\n pass,\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n results.push({\n name: item.name,\n method: item.method,\n url: item.url,\n status: 0,\n timing: 0,\n pass: false,\n error: message,\n })\n }\n }\n\n const passed = results.filter((r) => r.pass).length\n const failed = results.filter((r) => !r.pass).length\n const totalTime = Math.round(results.reduce((sum, r) => sum + r.timing, 0) * 100) / 100\n\n const lines: string[] = [\n `${failed === 0 ? '✅' : '❌'} BULK TEST — ${passed}/${results.length} passed | ${totalTime}ms total`,\n '',\n ]\n\n for (const r of results) {\n const icon = r.pass ? '✅' : '❌'\n if (r.error) {\n lines.push(`${icon} ${r.name} — ERROR: ${r.error}`)\n } else {\n lines.push(`${icon} ${r.name} — ${r.method} ${r.url} → ${r.status} (${r.timing}ms)`)\n }\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n isError: failed > 0,\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport type { ApiSpecSchema } from '../lib/types.js'\n\n/**\n * Genera datos fake basándose en un schema OpenAPI.\n */\nfunction generateMockData(schema: ApiSpecSchema, depth = 0): unknown {\n if (depth > 8) return null\n\n // If example exists, use it\n if (schema.example !== undefined) return schema.example\n\n // If enum, pick first value\n if (schema.enum && schema.enum.length > 0) {\n return schema.enum[Math.floor(Math.random() * schema.enum.length)]\n }\n\n switch (schema.type) {\n case 'object': {\n if (!schema.properties) return {}\n const obj: Record<string, unknown> = {}\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n obj[key] = generateMockData(propSchema, depth + 1)\n }\n return obj\n }\n\n case 'array': {\n if (!schema.items) return []\n const count = Math.floor(Math.random() * 3) + 1 // 1-3 items\n return Array.from({ length: count }, () =>\n generateMockData(schema.items!, depth + 1),\n )\n }\n\n case 'string': {\n switch (schema.format) {\n case 'date-time':\n return new Date().toISOString()\n case 'date':\n return new Date().toISOString().split('T')[0]\n case 'email':\n return `user${Math.floor(Math.random() * 1000)}@example.com`\n case 'uri':\n case 'url':\n return 'https://example.com/resource'\n case 'uuid':\n return crypto.randomUUID()\n case 'ipv4':\n return `192.168.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`\n default: {\n // Use description or key name for smarter generation\n const desc = (schema.description ?? '').toLowerCase()\n if (desc.includes('name') || desc.includes('nombre'))\n return `Test User ${Math.floor(Math.random() * 100)}`\n if (desc.includes('title') || desc.includes('título'))\n return `Test Title ${Math.floor(Math.random() * 100)}`\n if (desc.includes('description') || desc.includes('descripción'))\n return 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'\n if (desc.includes('password') || desc.includes('contraseña'))\n return 'TestPass123!'\n if (desc.includes('slug'))\n return `test-slug-${Math.floor(Math.random() * 1000)}`\n if (desc.includes('phone') || desc.includes('teléfono'))\n return '+34612345678'\n return `mock-string-${Math.floor(Math.random() * 10000)}`\n }\n }\n }\n\n case 'number':\n case 'integer':\n return Math.floor(Math.random() * 1000)\n\n case 'boolean':\n return Math.random() > 0.5\n\n default:\n return null\n }\n}\n\nexport function registerMockTool(server: McpServer, storage: Storage): void {\n server.tool(\n 'mock',\n 'Genera datos mock/fake para un endpoint basándose en su spec OpenAPI importada. Útil para frontend sin backend.',\n {\n name: z.string().describe('Nombre del API importada'),\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('Método HTTP del endpoint'),\n path: z.string().describe('Path del endpoint (ej: \"/users\", \"/blog\")'),\n target: z\n .enum(['request', 'response'])\n .optional()\n .describe('Generar mock del body de request o de la response (default: response)'),\n status: z\n .string()\n .optional()\n .describe('Status code de la respuesta a mockear (default: \"200\" o \"201\")'),\n count: z\n .number()\n .optional()\n .describe('Número de items mock a generar si el schema es un array (default: 3)'),\n },\n async (params) => {\n try {\n const spec = await storage.getSpec(params.name)\n if (!spec) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: API '${params.name}' no encontrada. Usa api_import para importarla primero.`,\n },\n ],\n isError: true,\n }\n }\n\n const endpoint = spec.endpoints.find(\n (ep) => ep.method === params.method && ep.path === params.path,\n )\n\n if (!endpoint) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: Endpoint ${params.method} ${params.path} no encontrado en '${params.name}'.`,\n },\n ],\n isError: true,\n }\n }\n\n const target = params.target ?? 'response'\n let schema: ApiSpecSchema | undefined\n\n if (target === 'request') {\n // Get request body schema\n const content = endpoint.requestBody?.content\n if (content) {\n const jsonContent = content['application/json']\n schema = jsonContent?.schema\n }\n\n if (!schema) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: El endpoint ${params.method} ${params.path} no tiene un body schema definido.`,\n },\n ],\n isError: true,\n }\n }\n } else {\n // Get response body schema\n const statusCode = params.status ?? (params.method === 'POST' ? '201' : '200')\n const response = endpoint.responses?.[statusCode]\n\n if (!response) {\n // Try to find any 2xx response\n const twoXX = Object.keys(endpoint.responses ?? {}).find((s) => s.startsWith('2'))\n if (twoXX && endpoint.responses) {\n const fallbackResp = endpoint.responses[twoXX]\n const content = fallbackResp?.content\n if (content) {\n const jsonContent = content['application/json']\n schema = jsonContent?.schema\n }\n }\n } else {\n const content = response.content\n if (content) {\n const jsonContent = content['application/json']\n schema = jsonContent?.schema\n }\n }\n\n if (!schema) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: No se encontró un schema de respuesta para ${params.method} ${params.path}.`,\n },\n ],\n isError: true,\n }\n }\n }\n\n // Generate mock data\n let mockData: unknown\n\n if (schema.type === 'array' && params.count) {\n // Generate specific number of items\n mockData = Array.from({ length: params.count }, () =>\n generateMockData(schema!.items ?? { type: 'object' }),\n )\n } else {\n mockData = generateMockData(schema)\n }\n\n const label = target === 'request' ? 'REQUEST BODY' : 'RESPONSE'\n\n return {\n content: [\n {\n type: 'text' as const,\n text: [\n `Mock ${label} para ${params.method} ${params.path}:`,\n '',\n '```json',\n JSON.stringify(mockData, null, 2),\n '```',\n '',\n 'Datos generados automáticamente desde el spec OpenAPI.',\n target === 'request'\n ? 'Puedes usar estos datos directamente en un request.'\n : 'Estos son datos de ejemplo que devolvería el endpoint.',\n ].join('\\n'),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n","import { z } from 'zod'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { Storage } from '../lib/storage.js'\nimport { executeRequest } from '../lib/http-client.js'\nimport { interpolateRequest } from '../lib/interpolation.js'\nimport type { RequestConfig } from '../lib/types.js'\n\nexport function registerLoadTestTool(server: McpServer, storage: Storage): void {\n server.tool(\n 'load_test',\n 'Lanza N requests concurrentes al mismo endpoint y mide tiempos promedio, percentiles y tasa de errores.',\n {\n method: z\n .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])\n .describe('HTTP method'),\n url: z.string().describe('URL del endpoint'),\n headers: z.record(z.string()).optional().describe('Headers HTTP'),\n body: z.any().optional().describe('Body del request'),\n query: z.record(z.string()).optional().describe('Query parameters'),\n auth: z\n .object({\n type: z.enum(['bearer', 'api-key', 'basic']),\n token: z.string().optional(),\n key: z.string().optional(),\n header: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n })\n .optional()\n .describe('Autenticación'),\n concurrent: z\n .number()\n .describe('Número de requests concurrentes a lanzar (max: 100)'),\n timeout: z\n .number()\n .optional()\n .describe('Timeout por request en ms (default: 30000)'),\n },\n async (params) => {\n try {\n const concurrentCount = Math.min(Math.max(params.concurrent, 1), 100)\n const variables = await storage.getActiveVariables()\n\n // Resolve URL\n let resolvedUrl = params.url\n if (resolvedUrl.startsWith('/') && variables.BASE_URL) {\n const baseUrl = variables.BASE_URL.replace(/\\/+$/, '')\n resolvedUrl = `${baseUrl}${resolvedUrl}`\n }\n\n const baseConfig: RequestConfig = {\n method: params.method,\n url: resolvedUrl,\n headers: params.headers,\n body: params.body,\n query: params.query,\n auth: params.auth,\n timeout: params.timeout,\n }\n\n const interpolated = interpolateRequest(baseConfig, variables)\n\n // Execute all requests concurrently\n const startTotal = performance.now()\n\n const promises = Array.from({ length: concurrentCount }, () =>\n executeRequest(interpolated)\n .then((response) => ({\n status: response.status,\n timing: response.timing.total_ms,\n error: undefined as string | undefined,\n }))\n .catch((error) => ({\n status: 0,\n timing: 0,\n error: error instanceof Error ? error.message : String(error),\n })),\n )\n\n const results = await Promise.all(promises)\n const endTotal = performance.now()\n const wallTime = Math.round((endTotal - startTotal) * 100) / 100\n\n // Calculate stats\n const successful = results.filter((r) => !r.error)\n const failed = results.filter((r) => r.error)\n const timings = successful.map((r) => r.timing).sort((a, b) => a - b)\n\n const statusCounts: Record<number, number> = {}\n for (const r of successful) {\n statusCounts[r.status] = (statusCounts[r.status] ?? 0) + 1\n }\n\n const avg = timings.length > 0\n ? Math.round((timings.reduce((s, t) => s + t, 0) / timings.length) * 100) / 100\n : 0\n const min = timings.length > 0 ? timings[0] : 0\n const max = timings.length > 0 ? timings[timings.length - 1] : 0\n const p50 = timings.length > 0 ? timings[Math.floor(timings.length * 0.5)] : 0\n const p95 = timings.length > 0 ? timings[Math.floor(timings.length * 0.95)] : 0\n const p99 = timings.length > 0 ? timings[Math.floor(timings.length * 0.99)] : 0\n\n const rps = wallTime > 0\n ? Math.round((successful.length / (wallTime / 1000)) * 100) / 100\n : 0\n\n const lines: string[] = [\n `📊 LOAD TEST — ${params.method} ${params.url}`,\n '',\n `Requests: ${concurrentCount} concurrentes`,\n `Exitosos: ${successful.length} | Fallidos: ${failed.length}`,\n `Tiempo total: ${wallTime}ms`,\n `Requests/segundo: ${rps}`,\n '',\n '⏱️ Tiempos de respuesta:',\n ` Min: ${min}ms`,\n ` Avg: ${avg}ms`,\n ` p50: ${p50}ms`,\n ` p95: ${p95}ms`,\n ` p99: ${p99}ms`,\n ` Max: ${max}ms`,\n ]\n\n if (Object.keys(statusCounts).length > 0) {\n lines.push('')\n lines.push('📋 Status codes:')\n for (const [status, count] of Object.entries(statusCounts)) {\n const pct = Math.round((count / concurrentCount) * 100)\n lines.push(` ${status}: ${count} (${pct}%)`)\n }\n }\n\n if (failed.length > 0) {\n lines.push('')\n lines.push('❌ Errores:')\n const errorCounts: Record<string, number> = {}\n for (const r of failed) {\n const errMsg = r.error ?? 'Unknown'\n errorCounts[errMsg] = (errorCounts[errMsg] ?? 0) + 1\n }\n for (const [err, count] of Object.entries(errorCounts)) {\n lines.push(` ${err}: ${count}x`)\n }\n }\n\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n isError: failed.length > successful.length, // More than 50% failed\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n }\n }\n },\n )\n}\n"],"mappings":"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","names":["z","AuthSchema","z","z","readFile","z","z","z","z","z","getByPath","z","z","z","z","z"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocaxcode/api-testing-mcp",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "MCP server for API testing. 20 tools: HTTP requests, assertions, flows, OpenAPI import, mock data, load testing. Zero cloud dependencies.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,12 +27,20 @@
27
27
  },
28
28
  "keywords": [
29
29
  "mcp",
30
+ "mcp-server",
30
31
  "api-testing",
31
32
  "http",
32
33
  "rest",
33
34
  "model-context-protocol",
34
35
  "claude",
35
- "ai-tools"
36
+ "claude-desktop",
37
+ "cursor",
38
+ "ai-tools",
39
+ "openapi",
40
+ "swagger",
41
+ "load-testing",
42
+ "mock-data",
43
+ "postman-alternative"
36
44
  ],
37
45
  "author": "cocaxcode",
38
46
  "license": "MIT",