truss-api-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +89 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/code-generator.d.ts +6 -0
  8. package/dist/lib/code-generator.d.ts.map +1 -0
  9. package/dist/lib/code-generator.js +890 -0
  10. package/dist/lib/code-generator.js.map +1 -0
  11. package/dist/lib/http-client.d.ts +6 -0
  12. package/dist/lib/http-client.d.ts.map +1 -0
  13. package/dist/lib/http-client.js +76 -0
  14. package/dist/lib/http-client.js.map +1 -0
  15. package/dist/lib/license.d.ts +4 -0
  16. package/dist/lib/license.d.ts.map +1 -0
  17. package/dist/lib/license.js +97 -0
  18. package/dist/lib/license.js.map +1 -0
  19. package/dist/lib/openapi-parser.d.ts +11 -0
  20. package/dist/lib/openapi-parser.d.ts.map +1 -0
  21. package/dist/lib/openapi-parser.js +390 -0
  22. package/dist/lib/openapi-parser.js.map +1 -0
  23. package/dist/lib/schema-validator.d.ts +15 -0
  24. package/dist/lib/schema-validator.d.ts.map +1 -0
  25. package/dist/lib/schema-validator.js +206 -0
  26. package/dist/lib/schema-validator.js.map +1 -0
  27. package/dist/tools/compare-specs.d.ts +3 -0
  28. package/dist/tools/compare-specs.d.ts.map +1 -0
  29. package/dist/tools/compare-specs.js +59 -0
  30. package/dist/tools/compare-specs.js.map +1 -0
  31. package/dist/tools/generate-client.d.ts +3 -0
  32. package/dist/tools/generate-client.d.ts.map +1 -0
  33. package/dist/tools/generate-client.js +65 -0
  34. package/dist/tools/generate-client.js.map +1 -0
  35. package/dist/tools/generate-openapi.d.ts +3 -0
  36. package/dist/tools/generate-openapi.d.ts.map +1 -0
  37. package/dist/tools/generate-openapi.js +57 -0
  38. package/dist/tools/generate-openapi.js.map +1 -0
  39. package/dist/tools/generate-tests.d.ts +3 -0
  40. package/dist/tools/generate-tests.d.ts.map +1 -0
  41. package/dist/tools/generate-tests.js +59 -0
  42. package/dist/tools/generate-tests.js.map +1 -0
  43. package/dist/tools/mock-server.d.ts +3 -0
  44. package/dist/tools/mock-server.d.ts.map +1 -0
  45. package/dist/tools/mock-server.js +60 -0
  46. package/dist/tools/mock-server.js.map +1 -0
  47. package/dist/tools/parse-openapi.d.ts +3 -0
  48. package/dist/tools/parse-openapi.d.ts.map +1 -0
  49. package/dist/tools/parse-openapi.js +48 -0
  50. package/dist/tools/parse-openapi.js.map +1 -0
  51. package/dist/tools/test-endpoint.d.ts +3 -0
  52. package/dist/tools/test-endpoint.d.ts.map +1 -0
  53. package/dist/tools/test-endpoint.js +66 -0
  54. package/dist/tools/test-endpoint.js.map +1 -0
  55. package/dist/tools/validate-response.d.ts +3 -0
  56. package/dist/tools/validate-response.d.ts.map +1 -0
  57. package/dist/tools/validate-response.js +44 -0
  58. package/dist/tools/validate-response.js.map +1 -0
  59. package/dist/types.d.ts +121 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +3 -0
  62. package/dist/types.js.map +1 -0
  63. package/evals/eval-http.ts +163 -0
  64. package/evals/eval-openapi.ts +506 -0
  65. package/evals/run-evals.ts +29 -0
  66. package/glama.json +4 -0
  67. package/package.json +37 -0
  68. package/smithery.yaml +9 -0
  69. package/src/index.ts +110 -0
  70. package/src/lib/code-generator.ts +1045 -0
  71. package/src/lib/http-client.ts +87 -0
  72. package/src/lib/license.ts +121 -0
  73. package/src/lib/openapi-parser.ts +456 -0
  74. package/src/lib/schema-validator.ts +234 -0
  75. package/src/tools/compare-specs.ts +67 -0
  76. package/src/tools/generate-client.ts +75 -0
  77. package/src/tools/generate-openapi.ts +67 -0
  78. package/src/tools/generate-tests.ts +69 -0
  79. package/src/tools/mock-server.ts +68 -0
  80. package/src/tools/parse-openapi.ts +54 -0
  81. package/src/tools/test-endpoint.ts +71 -0
  82. package/src/tools/validate-response.ts +54 -0
  83. package/src/types.ts +156 -0
  84. package/tsconfig.json +19 -0
@@ -0,0 +1,59 @@
1
+ import { z } from 'zod';
2
+ import { requirePro } from '../lib/license.js';
3
+ import { parseOpenApiSpec } from '../lib/openapi-parser.js';
4
+ import { compareSpecs } from '../lib/code-generator.js';
5
+ export function registerCompareSpecs(server) {
6
+ server.tool('compare_specs', '[Pro] Diff two OpenAPI specs and find breaking changes, non-breaking changes, new endpoints, and removed endpoints. Essential for API versioning.', {
7
+ old_spec: z.string().describe('The old/previous OpenAPI spec as JSON or YAML'),
8
+ new_spec: z.string().describe('The new/updated OpenAPI spec as JSON or YAML'),
9
+ }, async ({ old_spec, new_spec }) => {
10
+ try {
11
+ await requirePro();
12
+ const oldParsed = parseOpenApiSpec(old_spec);
13
+ const newParsed = parseOpenApiSpec(new_spec);
14
+ const comparison = compareSpecs(oldParsed, newParsed);
15
+ return {
16
+ content: [
17
+ {
18
+ type: 'text',
19
+ text: JSON.stringify({
20
+ summary: {
21
+ breaking_changes: comparison.breaking_changes.length,
22
+ non_breaking_changes: comparison.non_breaking.length,
23
+ new_endpoints: comparison.new_endpoints.length,
24
+ removed_endpoints: comparison.removed_endpoints.length,
25
+ is_backwards_compatible: comparison.breaking_changes.length === 0,
26
+ },
27
+ breaking_changes: comparison.breaking_changes,
28
+ non_breaking_changes: comparison.non_breaking,
29
+ new_endpoints: comparison.new_endpoints,
30
+ removed_endpoints: comparison.removed_endpoints,
31
+ }, null, 2),
32
+ },
33
+ ],
34
+ };
35
+ }
36
+ catch (err) {
37
+ const message = err instanceof Error ? err.message : String(err);
38
+ const isLicense = message.includes('TRUSS Pro license');
39
+ return {
40
+ content: [
41
+ {
42
+ type: 'text',
43
+ text: JSON.stringify({
44
+ error: message,
45
+ ...(isLicense
46
+ ? {
47
+ upgrade_url: 'https://truss.dev/pricing',
48
+ price: '$25/mo',
49
+ }
50
+ : {}),
51
+ }, null, 2),
52
+ },
53
+ ],
54
+ isError: true,
55
+ };
56
+ }
57
+ });
58
+ }
59
+ //# sourceMappingURL=compare-specs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare-specs.js","sourceRoot":"","sources":["../../src/tools/compare-specs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,IAAI,CACT,eAAe,EACf,mJAAmJ,EACnJ;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QAC9E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;KAC9E,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC/B,IAAI,CAAC;YACH,MAAM,UAAU,EAAE,CAAC;YAEnB,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAC7C,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAC7C,MAAM,UAAU,GAAG,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAEtD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,OAAO,EAAE;gCACP,gBAAgB,EAAE,UAAU,CAAC,gBAAgB,CAAC,MAAM;gCACpD,oBAAoB,EAAE,UAAU,CAAC,YAAY,CAAC,MAAM;gCACpD,aAAa,EAAE,UAAU,CAAC,aAAa,CAAC,MAAM;gCAC9C,iBAAiB,EAAE,UAAU,CAAC,iBAAiB,CAAC,MAAM;gCACtD,uBAAuB,EAAE,UAAU,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC;6BAClE;4BACD,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;4BAC7C,oBAAoB,EAAE,UAAU,CAAC,YAAY;4BAC7C,aAAa,EAAE,UAAU,CAAC,aAAa;4BACvC,iBAAiB,EAAE,UAAU,CAAC,iBAAiB;yBAChD,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;YAExD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,OAAO;4BACd,GAAG,CAAC,SAAS;gCACX,CAAC,CAAC;oCACE,WAAW,EAAE,2BAA2B;oCACxC,KAAK,EAAE,QAAQ;iCAChB;gCACH,CAAC,CAAC,EAAE,CAAC;yBACR,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerGenerateClient(server: McpServer): void;
3
+ //# sourceMappingURL=generate-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-client.d.ts","sourceRoot":"","sources":["../../src/tools/generate-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoE9D"}
@@ -0,0 +1,65 @@
1
+ import { z } from 'zod';
2
+ import { requirePro } from '../lib/license.js';
3
+ import { parseOpenApiSpec } from '../lib/openapi-parser.js';
4
+ import { generateClient } from '../lib/code-generator.js';
5
+ export function registerGenerateClient(server) {
6
+ server.tool('generate_client', '[Pro] Generate a typed API client from an OpenAPI spec. Supports TypeScript (fetch/axios), Python (requests), and Go (net/http). Produces ready-to-use code with type definitions.', {
7
+ spec: z.string().describe('OpenAPI/Swagger spec as JSON or YAML string'),
8
+ language: z
9
+ .enum(['typescript', 'python', 'go'])
10
+ .describe('Target language for the client'),
11
+ style: z
12
+ .enum(['fetch', 'axios'])
13
+ .optional()
14
+ .default('fetch')
15
+ .describe('HTTP library style (TypeScript only, default: fetch)'),
16
+ }, async ({ spec, language, style }) => {
17
+ try {
18
+ await requirePro();
19
+ const parsed = parseOpenApiSpec(spec);
20
+ const code = generateClient(parsed, language, style);
21
+ const extensions = {
22
+ typescript: '.ts',
23
+ python: '.py',
24
+ go: '.go',
25
+ };
26
+ const filename = `api_client${extensions[language]}`;
27
+ return {
28
+ content: [
29
+ {
30
+ type: 'text',
31
+ text: JSON.stringify({
32
+ filename,
33
+ language,
34
+ style: language === 'typescript' ? style : undefined,
35
+ endpoint_count: parsed.endpoints.length,
36
+ code,
37
+ }, null, 2),
38
+ },
39
+ ],
40
+ };
41
+ }
42
+ catch (err) {
43
+ const message = err instanceof Error ? err.message : String(err);
44
+ const isLicense = message.includes('TRUSS Pro license');
45
+ return {
46
+ content: [
47
+ {
48
+ type: 'text',
49
+ text: JSON.stringify({
50
+ error: message,
51
+ ...(isLicense
52
+ ? {
53
+ upgrade_url: 'https://truss.dev/pricing',
54
+ price: '$25/mo',
55
+ }
56
+ : {}),
57
+ }, null, 2),
58
+ },
59
+ ],
60
+ isError: true,
61
+ };
62
+ }
63
+ });
64
+ }
65
+ //# sourceMappingURL=generate-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-client.js","sourceRoot":"","sources":["../../src/tools/generate-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,UAAU,sBAAsB,CAAC,MAAiB;IACtD,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,oLAAoL,EACpL;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;QACxE,QAAQ,EAAE,CAAC;aACR,IAAI,CAAC,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;aACpC,QAAQ,CAAC,gCAAgC,CAAC;QAC7C,KAAK,EAAE,CAAC;aACL,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;aACxB,QAAQ,EAAE;aACV,OAAO,CAAC,OAAO,CAAC;aAChB,QAAQ,CAAC,sDAAsD,CAAC;KACpE,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;QAClC,IAAI,CAAC;YACH,MAAM,UAAU,EAAE,CAAC;YAEnB,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;YAErD,MAAM,UAAU,GAA2B;gBACzC,UAAU,EAAE,KAAK;gBACjB,MAAM,EAAE,KAAK;gBACb,EAAE,EAAE,KAAK;aACV,CAAC;YAEF,MAAM,QAAQ,GAAG,aAAa,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAErD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,QAAQ;4BACR,QAAQ;4BACR,KAAK,EAAE,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;4BACpD,cAAc,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM;4BACvC,IAAI;yBACL,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;YAExD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,OAAO;4BACd,GAAG,CAAC,SAAS;gCACX,CAAC,CAAC;oCACE,WAAW,EAAE,2BAA2B;oCACxC,KAAK,EAAE,QAAQ;iCAChB;gCACH,CAAC,CAAC,EAAE,CAAC;yBACR,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerGenerateOpenApi(server: McpServer): void;
3
+ //# sourceMappingURL=generate-openapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-openapi.d.ts","sourceRoot":"","sources":["../../src/tools/generate-openapi.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6D/D"}
@@ -0,0 +1,57 @@
1
+ import { z } from 'zod';
2
+ import { requirePro } from '../lib/license.js';
3
+ import { generateOpenApiFromExamples } from '../lib/openapi-parser.js';
4
+ export function registerGenerateOpenApi(server) {
5
+ server.tool('generate_openapi', '[Pro] Auto-generate an OpenAPI 3.0 spec from example requests and responses. Infers schemas, path parameters, query parameters, and response types.', {
6
+ examples: z.array(z.object({
7
+ method: z.string().describe('HTTP method (GET, POST, etc.)'),
8
+ url: z.string().describe('Full URL of the request'),
9
+ request_body: z.unknown().optional().describe('Request body sent'),
10
+ response_body: z.unknown().describe('Response body received'),
11
+ status: z.number().describe('HTTP status code'),
12
+ headers: z.record(z.string(), z.string()).optional().describe('Request headers'),
13
+ })).min(1).describe('Array of example request/response pairs'),
14
+ }, async ({ examples }) => {
15
+ try {
16
+ await requirePro();
17
+ const yamlSpec = generateOpenApiFromExamples(examples);
18
+ return {
19
+ content: [
20
+ {
21
+ type: 'text',
22
+ text: yamlSpec,
23
+ },
24
+ ],
25
+ };
26
+ }
27
+ catch (err) {
28
+ const message = err instanceof Error ? err.message : String(err);
29
+ const isLicense = message.includes('TRUSS Pro license');
30
+ return {
31
+ content: [
32
+ {
33
+ type: 'text',
34
+ text: JSON.stringify({
35
+ error: message,
36
+ ...(isLicense
37
+ ? {
38
+ upgrade_url: 'https://truss.dev/pricing',
39
+ price: '$25/mo',
40
+ features: [
41
+ 'Generate OpenAPI specs from examples',
42
+ 'Generate API test suites',
43
+ 'Mock server generation',
44
+ 'Spec comparison & breaking change detection',
45
+ 'Multi-language client code generation',
46
+ ],
47
+ }
48
+ : {}),
49
+ }, null, 2),
50
+ },
51
+ ],
52
+ isError: true,
53
+ };
54
+ }
55
+ });
56
+ }
57
+ //# sourceMappingURL=generate-openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-openapi.js","sourceRoot":"","sources":["../../src/tools/generate-openapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAEvE,MAAM,UAAU,uBAAuB,CAAC,MAAiB;IACvD,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,qJAAqJ,EACrJ;QACE,QAAQ,EAAE,CAAC,CAAC,KAAK,CACf,CAAC,CAAC,MAAM,CAAC;YACP,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAC5D,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;YACnD,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YAClE,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;YAC7D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YAC/C,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;SACjF,CAAC,CACH,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,yCAAyC,CAAC;KAC7D,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,MAAM,UAAU,EAAE,CAAC;YAEnB,MAAM,QAAQ,GAAG,2BAA2B,CAAC,QAAkD,CAAC,CAAC;YAEjG,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,QAAQ;qBACf;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;YAExD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,OAAO;4BACd,GAAG,CAAC,SAAS;gCACX,CAAC,CAAC;oCACE,WAAW,EAAE,2BAA2B;oCACxC,KAAK,EAAE,QAAQ;oCACf,QAAQ,EAAE;wCACR,sCAAsC;wCACtC,0BAA0B;wCAC1B,wBAAwB;wCACxB,6CAA6C;wCAC7C,uCAAuC;qCACxC;iCACF;gCACH,CAAC,CAAC,EAAE,CAAC;yBACR,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerGenerateTests(server: McpServer): void;
3
+ //# sourceMappingURL=generate-tests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-tests.d.ts","sourceRoot":"","sources":["../../src/tools/generate-tests.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8D7D"}
@@ -0,0 +1,59 @@
1
+ import { z } from 'zod';
2
+ import { requirePro } from '../lib/license.js';
3
+ import { parseOpenApiSpec } from '../lib/openapi-parser.js';
4
+ import { generateTests } from '../lib/code-generator.js';
5
+ export function registerGenerateTests(server) {
6
+ server.tool('generate_tests', '[Pro] Generate a complete API test suite from an OpenAPI spec. Supports Jest, Vitest, and Pytest frameworks. Generates happy-path and error-case tests.', {
7
+ spec: z.string().describe('OpenAPI/Swagger spec as JSON or YAML string'),
8
+ base_url: z.string().describe('Base URL of the API to test (e.g., http://localhost:3000)'),
9
+ framework: z
10
+ .enum(['jest', 'vitest', 'pytest'])
11
+ .optional()
12
+ .default('vitest')
13
+ .describe('Test framework to generate for (default: vitest)'),
14
+ }, async ({ spec, base_url, framework }) => {
15
+ try {
16
+ await requirePro();
17
+ const parsed = parseOpenApiSpec(spec);
18
+ const testCode = generateTests(parsed, base_url, framework);
19
+ const filename = framework === 'pytest'
20
+ ? 'test_api.py'
21
+ : `api.test.${framework === 'jest' ? 'js' : 'ts'}`;
22
+ return {
23
+ content: [
24
+ {
25
+ type: 'text',
26
+ text: JSON.stringify({
27
+ filename,
28
+ framework,
29
+ endpoint_count: parsed.endpoints.length,
30
+ code: testCode,
31
+ }, null, 2),
32
+ },
33
+ ],
34
+ };
35
+ }
36
+ catch (err) {
37
+ const message = err instanceof Error ? err.message : String(err);
38
+ const isLicense = message.includes('TRUSS Pro license');
39
+ return {
40
+ content: [
41
+ {
42
+ type: 'text',
43
+ text: JSON.stringify({
44
+ error: message,
45
+ ...(isLicense
46
+ ? {
47
+ upgrade_url: 'https://truss.dev/pricing',
48
+ price: '$25/mo',
49
+ }
50
+ : {}),
51
+ }, null, 2),
52
+ },
53
+ ],
54
+ isError: true,
55
+ };
56
+ }
57
+ });
58
+ }
59
+ //# sourceMappingURL=generate-tests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-tests.js","sourceRoot":"","sources":["../../src/tools/generate-tests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,yJAAyJ,EACzJ;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;QACxE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC;QAC1F,SAAS,EAAE,CAAC;aACT,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;aAClC,QAAQ,EAAE;aACV,OAAO,CAAC,QAAQ,CAAC;aACjB,QAAQ,CAAC,kDAAkD,CAAC;KAChE,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE;QACtC,IAAI,CAAC;YACH,MAAM,UAAU,EAAE,CAAC;YAEnB,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;YAE5D,MAAM,QAAQ,GACZ,SAAS,KAAK,QAAQ;gBACpB,CAAC,CAAC,aAAa;gBACf,CAAC,CAAC,YAAY,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAEvD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,QAAQ;4BACR,SAAS;4BACT,cAAc,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM;4BACvC,IAAI,EAAE,QAAQ;yBACf,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;YAExD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,OAAO;4BACd,GAAG,CAAC,SAAS;gCACX,CAAC,CAAC;oCACE,WAAW,EAAE,2BAA2B;oCACxC,KAAK,EAAE,QAAQ;iCAChB;gCACH,CAAC,CAAC,EAAE,CAAC;yBACR,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerMockServer(server: McpServer): void;
3
+ //# sourceMappingURL=mock-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-server.d.ts","sourceRoot":"","sources":["../../src/tools/mock-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6D1D"}
@@ -0,0 +1,60 @@
1
+ import { z } from 'zod';
2
+ import { requirePro } from '../lib/license.js';
3
+ import { parseOpenApiSpec } from '../lib/openapi-parser.js';
4
+ import { generateMockServer } from '../lib/code-generator.js';
5
+ export function registerMockServer(server) {
6
+ server.tool('mock_server', '[Pro] Generate a mock server configuration from an OpenAPI spec. Produces routes with sample responses and a db.json file ready for json-server or similar.', {
7
+ spec: z.string().describe('OpenAPI/Swagger spec as JSON or YAML string'),
8
+ }, async ({ spec }) => {
9
+ try {
10
+ await requirePro();
11
+ const parsed = parseOpenApiSpec(spec);
12
+ const mockConfig = generateMockServer(parsed);
13
+ return {
14
+ content: [
15
+ {
16
+ type: 'text',
17
+ text: JSON.stringify({
18
+ route_count: mockConfig.routes.length,
19
+ routes: mockConfig.routes,
20
+ mock_data: mockConfig.mock_data,
21
+ usage_instructions: {
22
+ json_server: [
23
+ '1. Save mock_data to db.json',
24
+ '2. npx json-server db.json --port 3001',
25
+ '3. Access endpoints at http://localhost:3001',
26
+ ],
27
+ custom: [
28
+ 'Use the routes array to configure any mock server.',
29
+ 'Each route has: method, path, status, response, headers.',
30
+ ],
31
+ },
32
+ }, null, 2),
33
+ },
34
+ ],
35
+ };
36
+ }
37
+ catch (err) {
38
+ const message = err instanceof Error ? err.message : String(err);
39
+ const isLicense = message.includes('TRUSS Pro license');
40
+ return {
41
+ content: [
42
+ {
43
+ type: 'text',
44
+ text: JSON.stringify({
45
+ error: message,
46
+ ...(isLicense
47
+ ? {
48
+ upgrade_url: 'https://truss.dev/pricing',
49
+ price: '$25/mo',
50
+ }
51
+ : {}),
52
+ }, null, 2),
53
+ },
54
+ ],
55
+ isError: true,
56
+ };
57
+ }
58
+ });
59
+ }
60
+ //# sourceMappingURL=mock-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-server.js","sourceRoot":"","sources":["../../src/tools/mock-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,IAAI,CACT,aAAa,EACb,6JAA6J,EAC7J;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;KACzE,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,UAAU,EAAE,CAAC;YAEnB,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAE9C,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,WAAW,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM;4BACrC,MAAM,EAAE,UAAU,CAAC,MAAM;4BACzB,SAAS,EAAE,UAAU,CAAC,SAAS;4BAC/B,kBAAkB,EAAE;gCAClB,WAAW,EAAE;oCACX,8BAA8B;oCAC9B,wCAAwC;oCACxC,8CAA8C;iCAC/C;gCACD,MAAM,EAAE;oCACN,oDAAoD;oCACpD,0DAA0D;iCAC3D;6BACF;yBACF,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;YAExD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,OAAO;4BACd,GAAG,CAAC,SAAS;gCACX,CAAC,CAAC;oCACE,WAAW,EAAE,2BAA2B;oCACxC,KAAK,EAAE,QAAQ;iCAChB;gCACH,CAAC,CAAC,EAAE,CAAC;yBACR,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerParseOpenApi(server: McpServer): void;
3
+ //# sourceMappingURL=parse-openapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-openapi.d.ts","sourceRoot":"","sources":["../../src/tools/parse-openapi.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiD5D"}
@@ -0,0 +1,48 @@
1
+ import { z } from 'zod';
2
+ import { parseOpenApiSpec } from '../lib/openapi-parser.js';
3
+ export function registerParseOpenApi(server) {
4
+ server.tool('parse_openapi', 'Parse an OpenAPI 3.x or Swagger 2.0 spec (JSON or YAML) and list all endpoints with their parameters, request bodies, and response schemas.', {
5
+ spec: z.string().describe('OpenAPI/Swagger spec content as JSON or YAML string'),
6
+ }, async ({ spec }) => {
7
+ try {
8
+ const parsed = parseOpenApiSpec(spec);
9
+ return {
10
+ content: [
11
+ {
12
+ type: 'text',
13
+ text: JSON.stringify({
14
+ info: parsed.info,
15
+ servers: parsed.servers,
16
+ endpoint_count: parsed.endpoints.length,
17
+ endpoints: parsed.endpoints.map((ep) => ({
18
+ method: ep.method,
19
+ path: ep.path,
20
+ summary: ep.summary,
21
+ operationId: ep.operationId,
22
+ tags: ep.tags,
23
+ parameters: ep.parameters,
24
+ request_body: ep.requestBody,
25
+ responses: ep.responses,
26
+ })),
27
+ }, null, 2),
28
+ },
29
+ ],
30
+ };
31
+ }
32
+ catch (err) {
33
+ return {
34
+ content: [
35
+ {
36
+ type: 'text',
37
+ text: JSON.stringify({
38
+ error: err instanceof Error ? err.message : String(err),
39
+ hint: 'Provide a valid OpenAPI 3.x or Swagger 2.0 spec as JSON or YAML string.',
40
+ }, null, 2),
41
+ },
42
+ ],
43
+ isError: true,
44
+ };
45
+ }
46
+ });
47
+ }
48
+ //# sourceMappingURL=parse-openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-openapi.js","sourceRoot":"","sources":["../../src/tools/parse-openapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,IAAI,CACT,eAAe,EACf,6IAA6I,EAC7I;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;KACjF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAEtC,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,IAAI,EAAE,MAAM,CAAC,IAAI;4BACjB,OAAO,EAAE,MAAM,CAAC,OAAO;4BACvB,cAAc,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM;4BACvC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gCACvC,MAAM,EAAE,EAAE,CAAC,MAAM;gCACjB,IAAI,EAAE,EAAE,CAAC,IAAI;gCACb,OAAO,EAAE,EAAE,CAAC,OAAO;gCACnB,WAAW,EAAE,EAAE,CAAC,WAAW;gCAC3B,IAAI,EAAE,EAAE,CAAC,IAAI;gCACb,UAAU,EAAE,EAAE,CAAC,UAAU;gCACzB,YAAY,EAAE,EAAE,CAAC,WAAW;gCAC5B,SAAS,EAAE,EAAE,CAAC,SAAS;6BACxB,CAAC,CAAC;yBACJ,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;4BACvD,IAAI,EAAE,yEAAyE;yBAChF,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerTestEndpoint(server: McpServer): void;
3
+ //# sourceMappingURL=test-endpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-endpoint.d.ts","sourceRoot":"","sources":["../../src/tools/test-endpoint.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkE5D"}
@@ -0,0 +1,66 @@
1
+ import { z } from 'zod';
2
+ import { executeRequest } from '../lib/http-client.js';
3
+ export function registerTestEndpoint(server) {
4
+ server.tool('test_endpoint', 'Send an HTTP request and get a structured response with status, headers, body, timing, and size. Supports GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS.', {
5
+ method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']).describe('HTTP method'),
6
+ url: z.string().url().describe('Full URL to send the request to'),
7
+ headers: z.record(z.string(), z.string()).optional().describe('Request headers as key-value pairs'),
8
+ body: z.unknown().optional().describe('Request body (auto-serialized to JSON for objects)'),
9
+ timeout: z.number().min(100).max(120000).optional().describe('Request timeout in milliseconds (default: 30000, max: 120000)'),
10
+ }, async ({ method, url, headers, body, timeout }) => {
11
+ try {
12
+ const response = await executeRequest({
13
+ method,
14
+ url,
15
+ headers: headers,
16
+ body,
17
+ timeout,
18
+ });
19
+ return {
20
+ content: [
21
+ {
22
+ type: 'text',
23
+ text: JSON.stringify({
24
+ status: response.status,
25
+ statusText: response.statusText,
26
+ headers: response.headers,
27
+ body: response.body,
28
+ timing_ms: response.timing_ms,
29
+ size_bytes: response.size_bytes,
30
+ }, null, 2),
31
+ },
32
+ ],
33
+ };
34
+ }
35
+ catch (err) {
36
+ const message = err instanceof Error ? err.message : String(err);
37
+ // Provide helpful error context
38
+ let hint = '';
39
+ if (message.includes('ECONNREFUSED')) {
40
+ hint = 'The server is not running or not accepting connections.';
41
+ }
42
+ else if (message.includes('ENOTFOUND')) {
43
+ hint = 'DNS lookup failed. Check the URL hostname.';
44
+ }
45
+ else if (message.includes('timeout') || message.includes('abort')) {
46
+ hint = 'Request timed out. Try increasing the timeout parameter.';
47
+ }
48
+ else if (message.includes('certificate')) {
49
+ hint = 'SSL/TLS certificate error. The server may have an invalid certificate.';
50
+ }
51
+ return {
52
+ content: [
53
+ {
54
+ type: 'text',
55
+ text: JSON.stringify({
56
+ error: message,
57
+ hint: hint || undefined,
58
+ }, null, 2),
59
+ },
60
+ ],
61
+ isError: true,
62
+ };
63
+ }
64
+ });
65
+ }
66
+ //# sourceMappingURL=test-endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-endpoint.js","sourceRoot":"","sources":["../../src/tools/test-endpoint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerValidateResponse(server: McpServer): void;
3
+ //# sourceMappingURL=validate-response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-response.d.ts","sourceRoot":"","sources":["../../src/tools/validate-response.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiDhE"}
@@ -0,0 +1,44 @@
1
+ import { z } from 'zod';
2
+ import { validateResponse } from '../lib/schema-validator.js';
3
+ export function registerValidateResponse(server) {
4
+ server.tool('validate_response', 'Validate an API response against an expected HTTP status code and optional JSON Schema. Returns validation result with detailed error messages.', {
5
+ response: z.object({
6
+ status: z.number().describe('HTTP status code from the response'),
7
+ body: z.unknown().describe('Response body to validate'),
8
+ }).describe('The API response to validate'),
9
+ expected_status: z.number().describe('Expected HTTP status code'),
10
+ expected_schema: z.unknown().optional().describe('Expected JSON Schema (draft-07) for the response body'),
11
+ }, async ({ response, expected_status, expected_schema }) => {
12
+ try {
13
+ const result = validateResponse(response, expected_status, expected_schema ?? undefined);
14
+ return {
15
+ content: [
16
+ {
17
+ type: 'text',
18
+ text: JSON.stringify({
19
+ valid: result.valid,
20
+ errors: result.errors,
21
+ ...(result.valid
22
+ ? { message: 'Response matches expected status and schema.' }
23
+ : { message: `Validation failed with ${result.errors.length} error(s).` }),
24
+ }, null, 2),
25
+ },
26
+ ],
27
+ };
28
+ }
29
+ catch (err) {
30
+ return {
31
+ content: [
32
+ {
33
+ type: 'text',
34
+ text: JSON.stringify({
35
+ error: err instanceof Error ? err.message : String(err),
36
+ }, null, 2),
37
+ },
38
+ ],
39
+ isError: true,
40
+ };
41
+ }
42
+ });
43
+ }
44
+ //# sourceMappingURL=validate-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-response.js","sourceRoot":"","sources":["../../src/tools/validate-response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAE9D,MAAM,UAAU,wBAAwB,CAAC,MAAiB;IACxD,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,iJAAiJ,EACjJ;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC;YACjB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;YACjE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;SACxD,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QAC3C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QACjE,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;KAC1G,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,eAAe,EAAE,eAAe,EAAE,EAAE,EAAE;QACvD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,gBAAgB,CAC7B,QAA6C,EAC7C,eAAe,EACd,eAAoD,IAAI,SAAS,CACnE,CAAC;YAEF,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,MAAM,CAAC,KAAK;4BACnB,MAAM,EAAE,MAAM,CAAC,MAAM;4BACrB,GAAG,CAAC,MAAM,CAAC,KAAK;gCACd,CAAC,CAAC,EAAE,OAAO,EAAE,8CAA8C,EAAE;gCAC7D,CAAC,CAAC,EAAE,OAAO,EAAE,0BAA0B,MAAM,CAAC,MAAM,CAAC,MAAM,YAAY,EAAE,CAAC;yBAC7E,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBACxD,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}