mcp-openapi-schema-explorer 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 (133) hide show
  1. package/.devcontainer/devcontainer.json +24 -0
  2. package/.github/dependabot.yml +13 -0
  3. package/.github/workflows/ci.yml +111 -0
  4. package/.husky/pre-commit +6 -0
  5. package/.prettierignore +3 -0
  6. package/.prettierrc.json +12 -0
  7. package/.releaserc.json +23 -0
  8. package/CHANGELOG.md +32 -0
  9. package/CONTRIBUTING.md +67 -0
  10. package/Dockerfile +3 -0
  11. package/LICENSE +21 -0
  12. package/README.md +127 -0
  13. package/dist/src/config.d.ts +15 -0
  14. package/dist/src/config.js +19 -0
  15. package/dist/src/config.js.map +1 -0
  16. package/dist/src/handlers/component-detail-handler.d.ts +14 -0
  17. package/dist/src/handlers/component-detail-handler.js +87 -0
  18. package/dist/src/handlers/component-detail-handler.js.map +1 -0
  19. package/dist/src/handlers/component-map-handler.d.ts +14 -0
  20. package/dist/src/handlers/component-map-handler.js +63 -0
  21. package/dist/src/handlers/component-map-handler.js.map +1 -0
  22. package/dist/src/handlers/handler-utils.d.ts +69 -0
  23. package/dist/src/handlers/handler-utils.js +180 -0
  24. package/dist/src/handlers/handler-utils.js.map +1 -0
  25. package/dist/src/handlers/operation-handler.d.ts +14 -0
  26. package/dist/src/handlers/operation-handler.js +86 -0
  27. package/dist/src/handlers/operation-handler.js.map +1 -0
  28. package/dist/src/handlers/path-item-handler.d.ts +14 -0
  29. package/dist/src/handlers/path-item-handler.js +66 -0
  30. package/dist/src/handlers/path-item-handler.js.map +1 -0
  31. package/dist/src/handlers/top-level-field-handler.d.ts +14 -0
  32. package/dist/src/handlers/top-level-field-handler.js +72 -0
  33. package/dist/src/handlers/top-level-field-handler.js.map +1 -0
  34. package/dist/src/index.d.ts +2 -0
  35. package/dist/src/index.js +177 -0
  36. package/dist/src/index.js.map +1 -0
  37. package/dist/src/rendering/components.d.ts +67 -0
  38. package/dist/src/rendering/components.js +177 -0
  39. package/dist/src/rendering/components.js.map +1 -0
  40. package/dist/src/rendering/document.d.ts +36 -0
  41. package/dist/src/rendering/document.js +147 -0
  42. package/dist/src/rendering/document.js.map +1 -0
  43. package/dist/src/rendering/path-item.d.ts +45 -0
  44. package/dist/src/rendering/path-item.js +141 -0
  45. package/dist/src/rendering/path-item.js.map +1 -0
  46. package/dist/src/rendering/paths.d.ts +26 -0
  47. package/dist/src/rendering/paths.js +78 -0
  48. package/dist/src/rendering/paths.js.map +1 -0
  49. package/dist/src/rendering/types.d.ts +50 -0
  50. package/dist/src/rendering/types.js +12 -0
  51. package/dist/src/rendering/types.js.map +1 -0
  52. package/dist/src/rendering/utils.d.ts +31 -0
  53. package/dist/src/rendering/utils.js +79 -0
  54. package/dist/src/rendering/utils.js.map +1 -0
  55. package/dist/src/services/formatters.d.ts +36 -0
  56. package/dist/src/services/formatters.js +52 -0
  57. package/dist/src/services/formatters.js.map +1 -0
  58. package/dist/src/services/reference-transform.d.ts +27 -0
  59. package/dist/src/services/reference-transform.js +75 -0
  60. package/dist/src/services/reference-transform.js.map +1 -0
  61. package/dist/src/services/spec-loader.d.ts +27 -0
  62. package/dist/src/services/spec-loader.js +77 -0
  63. package/dist/src/services/spec-loader.js.map +1 -0
  64. package/dist/src/types.d.ts +11 -0
  65. package/dist/src/types.js +2 -0
  66. package/dist/src/types.js.map +1 -0
  67. package/dist/src/utils/uri-builder.d.ts +81 -0
  68. package/dist/src/utils/uri-builder.js +121 -0
  69. package/dist/src/utils/uri-builder.js.map +1 -0
  70. package/dist/src/version.d.ts +1 -0
  71. package/dist/src/version.js +4 -0
  72. package/dist/src/version.js.map +1 -0
  73. package/eslint.config.js +88 -0
  74. package/jest.config.js +32 -0
  75. package/justfile +66 -0
  76. package/memory-bank/activeContext.md +139 -0
  77. package/memory-bank/productContext.md +39 -0
  78. package/memory-bank/progress.md +141 -0
  79. package/memory-bank/projectbrief.md +50 -0
  80. package/memory-bank/systemPatterns.md +224 -0
  81. package/memory-bank/techContext.md +131 -0
  82. package/package.json +76 -0
  83. package/scripts/generate-version.js +49 -0
  84. package/src/config.ts +33 -0
  85. package/src/handlers/component-detail-handler.ts +121 -0
  86. package/src/handlers/component-map-handler.ts +92 -0
  87. package/src/handlers/handler-utils.ts +230 -0
  88. package/src/handlers/operation-handler.ts +114 -0
  89. package/src/handlers/path-item-handler.ts +88 -0
  90. package/src/handlers/top-level-field-handler.ts +92 -0
  91. package/src/index.ts +222 -0
  92. package/src/rendering/components.ts +228 -0
  93. package/src/rendering/document.ts +167 -0
  94. package/src/rendering/path-item.ts +157 -0
  95. package/src/rendering/paths.ts +87 -0
  96. package/src/rendering/types.ts +63 -0
  97. package/src/rendering/utils.ts +107 -0
  98. package/src/services/formatters.ts +71 -0
  99. package/src/services/reference-transform.ts +105 -0
  100. package/src/services/spec-loader.ts +88 -0
  101. package/src/types.ts +17 -0
  102. package/src/utils/uri-builder.ts +134 -0
  103. package/src/version.ts +4 -0
  104. package/test/__tests__/e2e/format.test.ts +224 -0
  105. package/test/__tests__/e2e/resources.test.ts +369 -0
  106. package/test/__tests__/e2e/spec-loading.test.ts +172 -0
  107. package/test/__tests__/unit/config.test.ts +39 -0
  108. package/test/__tests__/unit/handlers/component-detail-handler.test.ts +241 -0
  109. package/test/__tests__/unit/handlers/component-map-handler.test.ts +187 -0
  110. package/test/__tests__/unit/handlers/handler-utils.test.ts +255 -0
  111. package/test/__tests__/unit/handlers/operation-handler.test.ts +202 -0
  112. package/test/__tests__/unit/handlers/path-item-handler.test.ts +153 -0
  113. package/test/__tests__/unit/handlers/top-level-field-handler.test.ts +182 -0
  114. package/test/__tests__/unit/rendering/components.test.ts +269 -0
  115. package/test/__tests__/unit/rendering/document.test.ts +172 -0
  116. package/test/__tests__/unit/rendering/path-item.test.ts +197 -0
  117. package/test/__tests__/unit/rendering/paths.test.ts +115 -0
  118. package/test/__tests__/unit/services/formatters.test.ts +109 -0
  119. package/test/__tests__/unit/services/reference-transform.test.ts +320 -0
  120. package/test/__tests__/unit/services/spec-loader.test.ts +214 -0
  121. package/test/__tests__/unit/utils/uri-builder.test.ts +103 -0
  122. package/test/fixtures/complex-endpoint.json +146 -0
  123. package/test/fixtures/empty-api.json +8 -0
  124. package/test/fixtures/multi-component-types.json +55 -0
  125. package/test/fixtures/paths-test.json +61 -0
  126. package/test/fixtures/sample-api.json +68 -0
  127. package/test/fixtures/sample-v2-api.json +39 -0
  128. package/test/setup.ts +32 -0
  129. package/test/utils/console-helpers.ts +48 -0
  130. package/test/utils/mcp-test-helpers.ts +66 -0
  131. package/test/utils/test-types.ts +54 -0
  132. package/tsconfig.json +25 -0
  133. package/tsconfig.test.json +5 -0
@@ -0,0 +1,39 @@
1
+ {
2
+ "swagger": "2.0",
3
+ "info": {
4
+ "title": "Simple Swagger 2.0 API",
5
+ "version": "1.0.0",
6
+ "description": "A simple API definition in Swagger 2.0 format for testing conversion."
7
+ },
8
+ "host": "localhost:3000",
9
+ "basePath": "/v2",
10
+ "schemes": ["http"],
11
+ "paths": {
12
+ "/ping": {
13
+ "get": {
14
+ "summary": "Check service health",
15
+ "description": "Returns a simple pong message.",
16
+ "produces": ["application/json"],
17
+ "responses": {
18
+ "200": {
19
+ "description": "Successful response",
20
+ "schema": {
21
+ "$ref": "#/definitions/Pong"
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }
27
+ },
28
+ "definitions": {
29
+ "Pong": {
30
+ "type": "object",
31
+ "properties": {
32
+ "message": {
33
+ "type": "string",
34
+ "example": "pong"
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
package/test/setup.ts ADDED
@@ -0,0 +1,32 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'path';
3
+
4
+ // Extend timeout for E2E tests
5
+ jest.setTimeout(30000);
6
+
7
+ // Clean up any previous test artifacts
8
+ beforeAll(async () => {
9
+ // Create required directories if they don't exist
10
+ const dirs = ['dist', 'dist/src', 'test/fixtures'];
11
+
12
+ for (const dir of dirs) {
13
+ try {
14
+ await fs.mkdir(dir, { recursive: true });
15
+ } catch (error) {
16
+ // Ignore if directory already exists
17
+ if ((error as { code?: string }).code !== 'EEXIST') {
18
+ throw error;
19
+ }
20
+ }
21
+ }
22
+
23
+ // Verify sample OpenAPI spec exists
24
+ const specPath = path.resolve(process.cwd(), 'test/fixtures/sample-api.json');
25
+ try {
26
+ await fs.access(specPath);
27
+ } catch {
28
+ throw new Error(`Sample OpenAPI spec not found at ${specPath}`);
29
+ }
30
+ });
31
+
32
+ // Custom matchers could be added here if needed
@@ -0,0 +1,48 @@
1
+ import { jest } from '@jest/globals';
2
+
3
+ // Define a type for the console.error function signature using unknown
4
+ type ConsoleErrorType = (message?: unknown, ...optionalParams: unknown[]) => void;
5
+
6
+ /**
7
+ * Temporarily suppresses console.error messages that match the expected pattern
8
+ * during the execution of a provided function (typically an async test operation).
9
+ * Unexpected console.error messages will still be logged.
10
+ *
11
+ * @param expectedMessage The exact string or a RegExp to match against the console.error message.
12
+ * @param fnToRun The async function to execute while suppression is active.
13
+ * @returns The result of the fnToRun function.
14
+ */
15
+ export async function suppressExpectedConsoleError<T>(
16
+ expectedMessage: string | RegExp,
17
+ fnToRun: () => T | Promise<T>
18
+ ): Promise<T> {
19
+ // Use the defined type for the original function
20
+ const originalConsoleError: ConsoleErrorType = console.error;
21
+
22
+ // Use unknown in the mock implementation signature
23
+ const consoleErrorSpy = jest
24
+ .spyOn(console, 'error')
25
+ .mockImplementation((message?: unknown, ...args: unknown[]) => {
26
+ const messageStr = String(message); // String conversion handles unknown
27
+ const shouldSuppress =
28
+ expectedMessage instanceof RegExp
29
+ ? expectedMessage.test(messageStr)
30
+ : messageStr === expectedMessage;
31
+
32
+ if (!shouldSuppress) {
33
+ // Call the original implementation for unexpected errors
34
+ // We still need to handle the potential type mismatch for the spread
35
+ // Using Function.prototype.apply is a safer way to call with dynamic args
36
+ Function.prototype.apply.call(originalConsoleError, console, [message, ...args]);
37
+ }
38
+ // If it matches, do nothing (suppress)
39
+ });
40
+
41
+ try {
42
+ // Execute the function that is expected to trigger the error log
43
+ return await fnToRun();
44
+ } finally {
45
+ // Restore the original console.error
46
+ consoleErrorSpy.mockRestore();
47
+ }
48
+ }
@@ -0,0 +1,66 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
3
+ // import path from 'path';
4
+
5
+ // Export the interface
6
+ export interface McpTestContext {
7
+ client: Client;
8
+ transport: StdioClientTransport;
9
+ cleanup: () => Promise<void>;
10
+ }
11
+
12
+ interface StartServerOptions {
13
+ outputFormat?: 'json' | 'yaml' | 'json-minified';
14
+ }
15
+
16
+ /**
17
+ * Start MCP server with test configuration
18
+ */
19
+ export async function startMcpServer(
20
+ specPath: string,
21
+ options: StartServerOptions = {}
22
+ ): Promise<McpTestContext> {
23
+ let transport: StdioClientTransport | undefined;
24
+ let client: Client | undefined;
25
+
26
+ try {
27
+ // Initialize transport with spec path as argument
28
+ transport = new StdioClientTransport({
29
+ command: 'node',
30
+ args: [
31
+ 'dist/src/index.js',
32
+ // path.resolve(specPath),
33
+ specPath,
34
+ ...(options.outputFormat ? ['--output-format', options.outputFormat] : []),
35
+ ],
36
+ stderr: 'inherit', // Pass through server errors normally - they're part of E2E testing
37
+ });
38
+
39
+ // Initialize client
40
+ client = new Client({
41
+ name: 'test-client',
42
+ version: '1.0.0',
43
+ });
44
+
45
+ await client.connect(transport);
46
+
47
+ // Create cleanup function
48
+ const cleanup = async (): Promise<void> => {
49
+ if (transport) {
50
+ await transport.close();
51
+ }
52
+ };
53
+
54
+ return {
55
+ client,
56
+ transport,
57
+ cleanup,
58
+ };
59
+ } catch (error) {
60
+ // Clean up on error
61
+ if (transport) {
62
+ await transport.close();
63
+ }
64
+ throw error;
65
+ }
66
+ }
@@ -0,0 +1,54 @@
1
+ import { OpenAPIV3 } from 'openapi-types';
2
+
3
+ export interface EndpointSuccessResponse {
4
+ method: string;
5
+ path: string;
6
+ parameters?: OpenAPIV3.ParameterObject[];
7
+ requestBody?: OpenAPIV3.RequestBodyObject;
8
+ responses: { [key: string]: OpenAPIV3.ResponseObject };
9
+ }
10
+
11
+ export interface EndpointErrorResponse {
12
+ method: string;
13
+ path: string;
14
+ error: string;
15
+ }
16
+
17
+ export type EndpointResponse = EndpointSuccessResponse | EndpointErrorResponse;
18
+
19
+ export function isEndpointErrorResponse(obj: unknown): obj is EndpointErrorResponse {
20
+ return (
21
+ typeof obj === 'object' &&
22
+ obj !== null &&
23
+ typeof (obj as EndpointErrorResponse).error === 'string'
24
+ );
25
+ }
26
+
27
+ export interface ResourceContent {
28
+ uri: string;
29
+ mimeType: string;
30
+ text: string;
31
+ }
32
+
33
+ export interface ResourceResponse {
34
+ contents: ResourceContent[];
35
+ }
36
+
37
+ // Types for Schema Resource E2E tests
38
+ export type SchemaSuccessResponse = OpenAPIV3.SchemaObject; // Use type alias
39
+
40
+ export interface SchemaErrorResponse {
41
+ name: string;
42
+ error: string;
43
+ }
44
+
45
+ export type SchemaResponse = SchemaSuccessResponse | SchemaErrorResponse;
46
+
47
+ export function isSchemaErrorResponse(obj: unknown): obj is SchemaErrorResponse {
48
+ return (
49
+ typeof obj === 'object' &&
50
+ obj !== null &&
51
+ typeof (obj as SchemaErrorResponse).name === 'string' && // Check for name property
52
+ typeof (obj as SchemaErrorResponse).error === 'string'
53
+ );
54
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "outDir": "dist",
11
+ "declaration": true,
12
+ "sourceMap": true,
13
+ "rootDir": ".",
14
+ "lib": ["ES2020"],
15
+ "noImplicitAny": true,
16
+ "noImplicitThis": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noImplicitReturns": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "types": ["jest", "node"]
22
+ },
23
+ "include": ["src/**/*"],
24
+ "exclude": ["node_modules", "dist", "local-docs", "test"]
25
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": ["src/**/*", "test/**/*"],
4
+ "exclude": ["node_modules", "dist", "local-docs"]
5
+ }