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,75 @@
1
+ import { buildComponentDetailUri } from '../utils/uri-builder.js'; // Added .js extension
2
+ export class ReferenceTransformService {
3
+ constructor() {
4
+ this.transformers = new Map();
5
+ }
6
+ registerTransformer(format, transformer) {
7
+ this.transformers.set(format, transformer);
8
+ }
9
+ transformDocument(document, context) {
10
+ const transformer = this.transformers.get(context.format);
11
+ if (!transformer) {
12
+ throw new Error(`No transformer registered for format: ${context.format}`);
13
+ }
14
+ return transformer.transformRefs(document, context);
15
+ }
16
+ }
17
+ export class OpenAPITransformer {
18
+ // Handle nested objects recursively
19
+ transformObject(obj, _context) {
20
+ if (!obj || typeof obj !== 'object') {
21
+ return obj;
22
+ }
23
+ // Handle arrays
24
+ if (Array.isArray(obj)) {
25
+ return obj.map(item => this.transformObject(item, _context));
26
+ }
27
+ // Handle references
28
+ if (this.isReferenceObject(obj)) {
29
+ return this.transformReference(obj.$ref);
30
+ }
31
+ // Recursively transform object properties
32
+ const result = {};
33
+ if (typeof obj === 'object') {
34
+ for (const [key, value] of Object.entries(obj)) {
35
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
36
+ Object.defineProperty(result, key, {
37
+ value: this.transformObject(value, _context),
38
+ enumerable: true,
39
+ writable: true,
40
+ configurable: true,
41
+ });
42
+ }
43
+ }
44
+ }
45
+ return result;
46
+ }
47
+ isReferenceObject(obj) {
48
+ return typeof obj === 'object' && obj !== null && '$ref' in obj;
49
+ }
50
+ transformReference(ref) {
51
+ // Handle only internal references for now
52
+ if (!ref.startsWith('#/')) {
53
+ return { $ref: ref }; // Keep external refs as-is
54
+ }
55
+ // Example ref: #/components/schemas/MySchema
56
+ const parts = ref.split('/');
57
+ // Check if it's an internal component reference
58
+ if (parts[0] === '#' && parts[1] === 'components' && parts.length === 4) {
59
+ const componentType = parts[2];
60
+ const componentName = parts[3];
61
+ // Use the centralized builder to create the correct URI
62
+ const newUri = buildComponentDetailUri(componentType, componentName);
63
+ return {
64
+ $ref: newUri,
65
+ };
66
+ }
67
+ // Keep other internal references (#/paths/...) and external references as-is
68
+ return { $ref: ref };
69
+ }
70
+ transformRefs(document, context) {
71
+ const transformed = this.transformObject(document, context);
72
+ return transformed;
73
+ }
74
+ }
75
+ //# sourceMappingURL=reference-transform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reference-transform.js","sourceRoot":"","sources":["../../../src/services/reference-transform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { OpenAPI } from 'openapi-types';
2
+ import { ReferenceTransformService, TransformContext } from './reference-transform.js';
3
+ /**
4
+ * Service for loading and transforming OpenAPI specifications
5
+ */
6
+ export declare class SpecLoaderService {
7
+ private specPath;
8
+ private referenceTransform;
9
+ private specData;
10
+ constructor(specPath: string, referenceTransform: ReferenceTransformService);
11
+ /**
12
+ * Load, potentially convert (from v2), and parse the OpenAPI specification.
13
+ */
14
+ loadSpec(): Promise<OpenAPI.Document>;
15
+ /**
16
+ * Get the loaded specification
17
+ */
18
+ getSpec(): Promise<OpenAPI.Document>;
19
+ /**
20
+ * Get transformed specification with MCP resource references
21
+ */
22
+ getTransformedSpec(context: TransformContext): Promise<OpenAPI.Document>;
23
+ }
24
+ /**
25
+ * Create and initialize a new SpecLoaderService instance
26
+ */
27
+ export declare function createSpecLoader(specPath: string, referenceTransform: ReferenceTransformService): Promise<SpecLoaderService>;
@@ -0,0 +1,77 @@
1
+ import * as swagger2openapi from 'swagger2openapi';
2
+ /**
3
+ * Service for loading and transforming OpenAPI specifications
4
+ */
5
+ export class SpecLoaderService {
6
+ constructor(specPath, referenceTransform) {
7
+ this.specPath = specPath;
8
+ this.referenceTransform = referenceTransform;
9
+ this.specData = null;
10
+ }
11
+ /**
12
+ * Load, potentially convert (from v2), and parse the OpenAPI specification.
13
+ */
14
+ async loadSpec() {
15
+ const options = {
16
+ patch: true, // Fix minor errors in the spec
17
+ warnOnly: true, // Add warnings for non-patchable errors instead of throwing
18
+ origin: this.specPath, // Helps with resolving relative references if needed
19
+ source: this.specPath,
20
+ };
21
+ try {
22
+ let result;
23
+ // Check if specPath is a URL
24
+ if (this.specPath.startsWith('http://') || this.specPath.startsWith('https://')) {
25
+ result = await swagger2openapi.convertUrl(this.specPath, options);
26
+ }
27
+ else {
28
+ result = await swagger2openapi.convertFile(this.specPath, options);
29
+ }
30
+ // swagger2openapi returns the result in result.openapi
31
+ if (!result || !result.openapi) {
32
+ throw new Error('Conversion or parsing failed to produce an OpenAPI document.');
33
+ }
34
+ // TODO: Check result.options?.warnings for potential issues?
35
+ this.specData = result.openapi; // Assuming result.openapi is compatible
36
+ return this.specData;
37
+ }
38
+ catch (error) {
39
+ // Improve error message clarity
40
+ let message = `Failed to load/convert OpenAPI spec from ${this.specPath}: `;
41
+ if (error instanceof Error) {
42
+ message += error.message;
43
+ // Include stack trace if available and helpful?
44
+ // console.error(error.stack);
45
+ }
46
+ else {
47
+ message += String(error);
48
+ }
49
+ throw new Error(message);
50
+ }
51
+ }
52
+ /**
53
+ * Get the loaded specification
54
+ */
55
+ async getSpec() {
56
+ if (!this.specData) {
57
+ await this.loadSpec();
58
+ }
59
+ return this.specData;
60
+ }
61
+ /**
62
+ * Get transformed specification with MCP resource references
63
+ */
64
+ async getTransformedSpec(context) {
65
+ const spec = await this.getSpec();
66
+ return this.referenceTransform.transformDocument(spec, context);
67
+ }
68
+ }
69
+ /**
70
+ * Create and initialize a new SpecLoaderService instance
71
+ */
72
+ export async function createSpecLoader(specPath, referenceTransform) {
73
+ const loader = new SpecLoaderService(specPath, referenceTransform);
74
+ await loader.loadSpec();
75
+ return loader;
76
+ }
77
+ //# sourceMappingURL=spec-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-loader.js","sourceRoot":"","sources":["../../../src/services/spec-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,eAAe,MAAM,iBAAiB,CAAC;AAInD;;GAEG;AACH,MAAM,OAAO,iBAAiB;IAG5B,YACU,QAAgB,EAChB,kBAA6C;QAD7C,aAAQ,GAAR,QAAQ,CAAQ;QAChB,uBAAkB,GAAlB,kBAAkB,CAA2B;QAJ/C,aAAQ,GAA4B,IAAI,CAAC;IAK9C,CAAC;IAEJ;;OAEG;IACH,KAAK,CAAC,QAAQ;QACZ,MAAM,OAAO,GAAG;YACd,KAAK,EAAE,IAAI,EAAE,+BAA+B;YAC5C,QAAQ,EAAE,IAAI,EAAE,4DAA4D;YAC5E,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,qDAAqD;YAC5E,MAAM,EAAE,IAAI,CAAC,QAAQ;SACtB,CAAC;QAEF,IAAI,CAAC;YACH,IAAI,MAAM,CAAC;YACX,6BAA6B;YAC7B,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAChF,MAAM,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACpE,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,MAAM,eAAe,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACrE,CAAC;YAED,uDAAuD;YACvD,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;YAClF,CAAC;YAED,6DAA6D;YAE7D,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAA2B,CAAC,CAAC,wCAAwC;YAC5F,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gCAAgC;YAChC,IAAI,OAAO,GAAG,4CAA4C,IAAI,CAAC,QAAQ,IAAI,CAAC;YAC5E,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC;gBACzB,gDAAgD;gBAChD,8BAA8B;YAChC,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACxB,CAAC;QACD,OAAO,IAAI,CAAC,QAAS,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CAAC,OAAyB;QAChD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClE,CAAC;CACF;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAgB,EAChB,kBAA6C;IAE7C,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IACnE,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;IACxB,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { OpenAPI } from 'openapi-types';
2
+ import type { TransformContext } from './services/reference-transform.js';
3
+ /** Common HTTP methods used in OpenAPI specs */
4
+ export type HttpMethod = 'get' | 'put' | 'post' | 'delete' | 'patch';
5
+ /** Interface for spec loader */
6
+ export interface SpecLoaderService {
7
+ getSpec(): Promise<OpenAPI.Document>;
8
+ getTransformedSpec(context: TransformContext): Promise<OpenAPI.Document>;
9
+ }
10
+ export type { TransformContext };
11
+ export type { OpenAPI };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Utility functions for building standardized MCP URIs for this server.
3
+ */
4
+ /**
5
+ * Encodes a string component for safe inclusion in a URI path segment.
6
+ * Uses standard encodeURIComponent.
7
+ * Encodes a path string for safe inclusion in a URI.
8
+ * This specifically targets path strings which might contain characters
9
+ * like '{', '}', etc., that need encoding when forming the URI path part.
10
+ * Uses standard encodeURIComponent.
11
+ * Encodes a path string for safe inclusion in a URI path segment.
12
+ * This is necessary because the path segment comes from the user potentially
13
+ * containing characters that need encoding (like '{', '}').
14
+ * Uses standard encodeURIComponent.
15
+ * @param path The path string to encode.
16
+ * @returns The encoded path string, with leading slashes removed before encoding.
17
+ */
18
+ export declare function encodeUriPathComponent(path: string): string;
19
+ /**
20
+ * Builds the URI for accessing a specific component's details.
21
+ * Example: openapi://components/schemas/MySchema
22
+ * @param type The component type (e.g., 'schemas', 'responses').
23
+ * @param name The component name.
24
+ * @returns The full component detail URI.
25
+ */
26
+ export declare function buildComponentDetailUri(type: string, name: string): string;
27
+ /**
28
+ * Builds the URI for listing components of a specific type.
29
+ * Example: openapi://components/schemas
30
+ * @param type The component type (e.g., 'schemas', 'responses').
31
+ * @returns The full component map URI.
32
+ */
33
+ export declare function buildComponentMapUri(type: string): string;
34
+ /**
35
+ * Builds the URI for accessing a specific operation's details.
36
+ * Example: openapi://paths/users/{userId}/GET
37
+ * @param path The API path (e.g., '/users/{userId}').
38
+ * @param method The HTTP method (e.g., 'GET', 'POST').
39
+ * @returns The full operation detail URI.
40
+ */
41
+ export declare function buildOperationUri(path: string, method: string): string;
42
+ /**
43
+ * Builds the URI for listing methods available at a specific path.
44
+ * Example: openapi://paths/users/{userId}
45
+ * @param path The API path (e.g., '/users/{userId}').
46
+ * @returns The full path item URI.
47
+ */
48
+ export declare function buildPathItemUri(path: string): string;
49
+ /**
50
+ * Builds the URI for accessing a top-level field (like 'info' or 'servers')
51
+ * or triggering a list view ('paths', 'components').
52
+ * Example: openapi://info, openapi://paths
53
+ * @param field The top-level field name.
54
+ * @returns The full top-level field URI.
55
+ */
56
+ export declare function buildTopLevelFieldUri(field: string): string;
57
+ /**
58
+ * Builds the URI suffix for a specific component's details.
59
+ * Example: components/schemas/MySchema
60
+ */
61
+ export declare function buildComponentDetailUriSuffix(type: string, name: string): string;
62
+ /**
63
+ * Builds the URI suffix for listing components of a specific type.
64
+ * Example: components/schemas
65
+ */
66
+ export declare function buildComponentMapUriSuffix(type: string): string;
67
+ /**
68
+ * Builds the URI suffix for a specific operation's details.
69
+ * Example: paths/users/{userId}/get
70
+ */
71
+ export declare function buildOperationUriSuffix(path: string, method: string): string;
72
+ /**
73
+ * Builds the URI suffix for listing methods available at a specific path.
74
+ * Example: paths/users/{userId}
75
+ */
76
+ export declare function buildPathItemUriSuffix(path: string): string;
77
+ /**
78
+ * Builds the URI suffix for a top-level field.
79
+ * Example: info, paths
80
+ */
81
+ export declare function buildTopLevelFieldUriSuffix(field: string): string;
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Utility functions for building standardized MCP URIs for this server.
3
+ */
4
+ const BASE_URI_SCHEME = 'openapi://';
5
+ /**
6
+ * Encodes a string component for safe inclusion in a URI path segment.
7
+ * Uses standard encodeURIComponent.
8
+ * Encodes a path string for safe inclusion in a URI.
9
+ * This specifically targets path strings which might contain characters
10
+ * like '{', '}', etc., that need encoding when forming the URI path part.
11
+ * Uses standard encodeURIComponent.
12
+ * Encodes a path string for safe inclusion in a URI path segment.
13
+ * This is necessary because the path segment comes from the user potentially
14
+ * containing characters that need encoding (like '{', '}').
15
+ * Uses standard encodeURIComponent.
16
+ * @param path The path string to encode.
17
+ * @returns The encoded path string, with leading slashes removed before encoding.
18
+ */
19
+ export function encodeUriPathComponent(path) {
20
+ // Added export
21
+ // Remove leading slashes before encoding
22
+ const pathWithoutLeadingSlash = path.replace(/^\/+/, '');
23
+ return encodeURIComponent(pathWithoutLeadingSlash);
24
+ }
25
+ // --- Full URI Builders ---
26
+ /**
27
+ * Builds the URI for accessing a specific component's details.
28
+ * Example: openapi://components/schemas/MySchema
29
+ * @param type The component type (e.g., 'schemas', 'responses').
30
+ * @param name The component name.
31
+ * @returns The full component detail URI.
32
+ */
33
+ export function buildComponentDetailUri(type, name) {
34
+ // Per user instruction, do not encode type or name here.
35
+ return `${BASE_URI_SCHEME}components/${type}/${name}`;
36
+ }
37
+ /**
38
+ * Builds the URI for listing components of a specific type.
39
+ * Example: openapi://components/schemas
40
+ * @param type The component type (e.g., 'schemas', 'responses').
41
+ * @returns The full component map URI.
42
+ */
43
+ export function buildComponentMapUri(type) {
44
+ // Per user instruction, do not encode type here.
45
+ return `${BASE_URI_SCHEME}components/${type}`;
46
+ }
47
+ /**
48
+ * Builds the URI for accessing a specific operation's details.
49
+ * Example: openapi://paths/users/{userId}/GET
50
+ * @param path The API path (e.g., '/users/{userId}').
51
+ * @param method The HTTP method (e.g., 'GET', 'POST').
52
+ * @returns The full operation detail URI.
53
+ */
54
+ export function buildOperationUri(path, method) {
55
+ // Encode only the path component. Assume 'path' is raw/decoded.
56
+ // Method is assumed to be safe or handled by SDK/client.
57
+ return `${BASE_URI_SCHEME}paths/${encodeUriPathComponent(path)}/${method.toLowerCase()}`; // Standardize method to lowercase
58
+ }
59
+ /**
60
+ * Builds the URI for listing methods available at a specific path.
61
+ * Example: openapi://paths/users/{userId}
62
+ * @param path The API path (e.g., '/users/{userId}').
63
+ * @returns The full path item URI.
64
+ */
65
+ export function buildPathItemUri(path) {
66
+ // Encode only the path component. Assume 'path' is raw/decoded.
67
+ return `${BASE_URI_SCHEME}paths/${encodeUriPathComponent(path)}`;
68
+ }
69
+ /**
70
+ * Builds the URI for accessing a top-level field (like 'info' or 'servers')
71
+ * or triggering a list view ('paths', 'components').
72
+ * Example: openapi://info, openapi://paths
73
+ * @param field The top-level field name.
74
+ * @returns The full top-level field URI.
75
+ */
76
+ export function buildTopLevelFieldUri(field) {
77
+ // Per user instruction, do not encode field here.
78
+ return `${BASE_URI_SCHEME}${field}`;
79
+ }
80
+ // --- URI Suffix Builders (for RenderResultItem) ---
81
+ /**
82
+ * Builds the URI suffix for a specific component's details.
83
+ * Example: components/schemas/MySchema
84
+ */
85
+ export function buildComponentDetailUriSuffix(type, name) {
86
+ // Per user instruction, do not encode type or name here.
87
+ return `components/${type}/${name}`;
88
+ }
89
+ /**
90
+ * Builds the URI suffix for listing components of a specific type.
91
+ * Example: components/schemas
92
+ */
93
+ export function buildComponentMapUriSuffix(type) {
94
+ // Per user instruction, do not encode type here.
95
+ return `components/${type}`;
96
+ }
97
+ /**
98
+ * Builds the URI suffix for a specific operation's details.
99
+ * Example: paths/users/{userId}/get
100
+ */
101
+ export function buildOperationUriSuffix(path, method) {
102
+ // Encode only the path component for the suffix. Assume 'path' is raw/decoded.
103
+ return `paths/${encodeUriPathComponent(path)}/${method.toLowerCase()}`;
104
+ }
105
+ /**
106
+ * Builds the URI suffix for listing methods available at a specific path.
107
+ * Example: paths/users/{userId}
108
+ */
109
+ export function buildPathItemUriSuffix(path) {
110
+ // Encode only the path component for the suffix. Assume 'path' is raw/decoded.
111
+ return `paths/${encodeUriPathComponent(path)}`;
112
+ }
113
+ /**
114
+ * Builds the URI suffix for a top-level field.
115
+ * Example: info, paths
116
+ */
117
+ export function buildTopLevelFieldUriSuffix(field) {
118
+ // Per user instruction, do not encode field here.
119
+ return field;
120
+ }
121
+ //# sourceMappingURL=uri-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uri-builder.js","sourceRoot":"","sources":["../../../src/utils/uri-builder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,eAAe,GAAG,YAAY,CAAC;AAErC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,eAAe;IACf,yCAAyC;IACzC,MAAM,uBAAuB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzD,OAAO,kBAAkB,CAAC,uBAAuB,CAAC,CAAC;AACrD,CAAC;AAED,4BAA4B;AAE5B;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY,EAAE,IAAY;IAChE,yDAAyD;IACzD,OAAO,GAAG,eAAe,cAAc,IAAI,IAAI,IAAI,EAAE,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,iDAAiD;IACjD,OAAO,GAAG,eAAe,cAAc,IAAI,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,MAAc;IAC5D,gEAAgE;IAChE,yDAAyD;IACzD,OAAO,GAAG,eAAe,SAAS,sBAAsB,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,kCAAkC;AAC9H,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,gEAAgE;IAChE,OAAO,GAAG,eAAe,SAAS,sBAAsB,CAAC,IAAI,CAAC,EAAE,CAAC;AACnE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,kDAAkD;IAClD,OAAO,GAAG,eAAe,GAAG,KAAK,EAAE,CAAC;AACtC,CAAC;AAED,qDAAqD;AAErD;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAAC,IAAY,EAAE,IAAY;IACtE,yDAAyD;IACzD,OAAO,cAAc,IAAI,IAAI,IAAI,EAAE,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAAY;IACrD,iDAAiD;IACjD,OAAO,cAAc,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY,EAAE,MAAc;IAClE,+EAA+E;IAC/E,OAAO,SAAS,sBAAsB,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;AACzE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,+EAA+E;IAC/E,OAAO,SAAS,sBAAsB,CAAC,IAAI,CAAC,EAAE,CAAC;AACjD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAAa;IACvD,kDAAkD;IAClD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const VERSION = "1.0.0";
@@ -0,0 +1,4 @@
1
+ // Auto-generated by scripts/generate-version.js during semantic-release prepare step
2
+ // Do not edit this file manually.
3
+ export const VERSION = '1.0.0';
4
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,kCAAkC;AAElC,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,88 @@
1
+ import tseslint from '@typescript-eslint/eslint-plugin';
2
+ import tsparser from '@typescript-eslint/parser';
3
+ import eslintJs from '@eslint/js';
4
+ import globals from 'globals';
5
+ import security from 'eslint-plugin-security';
6
+
7
+ export default [
8
+ {
9
+ ignores: ['dist/**', 'node_modules/**', 'local-docs/**'],
10
+ },
11
+ eslintJs.configs.recommended,
12
+ {
13
+ files: ['src/**/*.ts'],
14
+ languageOptions: {
15
+ parser: tsparser,
16
+ parserOptions: {
17
+ project: './tsconfig.json',
18
+ ecmaVersion: 2020,
19
+ sourceType: 'module',
20
+ },
21
+ globals: {
22
+ ...globals.node,
23
+ },
24
+ },
25
+ plugins: {
26
+ '@typescript-eslint': tseslint,
27
+ security: security,
28
+ },
29
+ rules: {
30
+ ...tseslint.configs['recommended'].rules,
31
+ ...tseslint.configs['recommended-requiring-type-checking'].rules,
32
+ '@typescript-eslint/explicit-function-return-type': 'error',
33
+ '@typescript-eslint/no-explicit-any': 'error',
34
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
35
+ '@typescript-eslint/naming-convention': [
36
+ 'error',
37
+ {
38
+ selector: 'interface',
39
+ format: ['PascalCase'],
40
+ },
41
+ ],
42
+ 'no-console': ['error', { allow: ['warn', 'error'] }],
43
+ ...security.configs.recommended.rules,
44
+ },
45
+ },
46
+ {
47
+ files: ['test/**/*.ts'],
48
+ languageOptions: {
49
+ parser: tsparser,
50
+ parserOptions: {
51
+ project: './tsconfig.test.json',
52
+ ecmaVersion: 2020,
53
+ sourceType: 'module',
54
+ },
55
+ globals: {
56
+ ...globals.node,
57
+ ...globals.jest,
58
+ },
59
+ },
60
+ plugins: {
61
+ '@typescript-eslint': tseslint,
62
+ security: security,
63
+ },
64
+ rules: {
65
+ ...tseslint.configs['recommended'].rules,
66
+ ...tseslint.configs['recommended-requiring-type-checking'].rules,
67
+ '@typescript-eslint/explicit-function-return-type': 'error',
68
+ '@typescript-eslint/no-explicit-any': 'error',
69
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
70
+ 'no-console': 'off', // Allow console in tests
71
+ },
72
+ },
73
+ // Configuration for scripts (like generate-version.js)
74
+ {
75
+ files: ['scripts/**/*.js'],
76
+ languageOptions: {
77
+ globals: {
78
+ ...globals.node, // Enable Node.js global variables
79
+ },
80
+ ecmaVersion: 2022, // Use a recent version supporting top-level await etc.
81
+ sourceType: 'module', // Treat .js files in scripts/ as ES Modules
82
+ },
83
+ rules: {
84
+ // Add any specific rules for scripts if needed, e.g., allow console
85
+ 'no-console': 'off',
86
+ },
87
+ },
88
+ ];
package/jest.config.js ADDED
@@ -0,0 +1,32 @@
1
+ /** @type {import('jest').Config} */
2
+ export default {
3
+ testPathIgnorePatterns: ['/node_modules/', '/local-docs/', '/dist/'],
4
+ preset: 'ts-jest',
5
+ testEnvironment: 'node',
6
+ extensionsToTreatAsEsm: ['.ts'],
7
+ moduleNameMapper: {
8
+ '^(\\.{1,2}/.*)\\.js$': '$1',
9
+ },
10
+ transform: {
11
+ '^.+\\.tsx?$': [
12
+ 'ts-jest',
13
+ {
14
+ useESM: true,
15
+ tsconfig: 'tsconfig.test.json',
16
+ },
17
+ ],
18
+ },
19
+ setupFilesAfterEnv: ['./test/setup.ts'],
20
+ reporters: [
21
+ [
22
+ 'jest-silent-reporter',
23
+ {
24
+ useDots: true,
25
+ showPaths: true,
26
+ showInlineStatus: true,
27
+ showWarnings: true,
28
+ },
29
+ ],
30
+ ],
31
+ verbose: true,
32
+ };
package/justfile ADDED
@@ -0,0 +1,66 @@
1
+ default:
2
+ @just --list
3
+
4
+ # Install dependencies
5
+ install:
6
+ npm install
7
+
8
+ # Run tests
9
+ test *ARGS='':
10
+ npm run test {{ARGS}}
11
+ @echo "All tests passed successfully!"
12
+
13
+ # Run tests with coverage
14
+ test-coverage *ARGS='':
15
+ npm run test:coverage {{ARGS}}
16
+
17
+ # Lint code
18
+ lint:
19
+ npm run lint
20
+ @echo "Linting completed successfully!"
21
+
22
+ # Format code
23
+ format:
24
+ npm run format
25
+
26
+ # Type check
27
+ type-check:
28
+ npm run type-check
29
+ @echo "Type checking completed successfully!"
30
+
31
+ # Security scan dependencies for vulnerabilities
32
+ audit:
33
+ npm audit
34
+
35
+ # Check license compliance
36
+ check-licenses:
37
+ npx license-checker --production \
38
+ --onlyAllow "MIT;ISC;BSD-2-Clause;BSD-3-Clause;Apache-2.0;Python-2.0" \
39
+ --excludePrivatePackages \
40
+ --summary
41
+
42
+ # Run all security checks
43
+ security:
44
+ @just audit
45
+ @just check-licenses
46
+
47
+ # Build the project
48
+ build:
49
+ npm run build
50
+
51
+ # Launch MCP inspector server
52
+ inspect:
53
+ #!/usr/bin/env sh
54
+ just build
55
+ npx @modelcontextprotocol/inspector \
56
+ node dist/src/index.js \
57
+ test/fixtures/complex-endpoint.json \
58
+ --output-format yaml
59
+
60
+ # Run all checks including security
61
+ all:
62
+ @just format
63
+ @just lint
64
+ @just build
65
+ @just test-coverage
66
+ @just security