mcp-openapi-schema-explorer
Version:
MCP OpenAPI schema explorer
147 lines • 6.15 kB
JavaScript
// No longer need ResourceContents here
// Placeholder for other renderable objects we'll create
// import { RenderablePaths } from './paths.js'; // Add .js
// import { RenderableComponents } from './components.js'; // Add .js
/**
* Wraps an OpenAPIV3.Document to make it renderable.
* Handles rendering for top-level fields like 'info', 'servers', etc.
* Delegates list rendering for 'paths' and 'components' to respective objects.
*/
export class RenderableDocument {
// TODO: Add RenderablePaths and RenderableComponents instances
// private renderablePaths: RenderablePaths;
// private renderableComponents: RenderableComponents;
constructor(document) {
this.document = document;
// Initialize renderable wrappers for paths and components here
// this.renderablePaths = new RenderablePaths(document.paths);
// this.renderableComponents = new RenderableComponents(document.components);
}
/**
* Renders a list view. For the document level, this is intended
* to be called only when the requested field is 'paths' or 'components'.
* The actual routing/delegation will happen in the handler based on the field.
*/
renderList(_context) {
// Prefix context with _
// This method should ideally not be called directly on the document
// without specifying 'paths' or 'components' as the field.
// The handler for openapi://{field} will delegate to the appropriate
// sub-object's renderList.
// Returning an error result item.
return [
{
uriSuffix: 'error',
data: null, // No specific data for this error
isError: true,
errorText: 'Error: List rendering is only supported for specific fields like "paths" or "components" at the top level.',
renderAsList: true, // Errors often shown as plain text
},
];
}
/**
* Renders the detail view. For the document level, this should not be called
* directly without specifying a field. The handler should call
* `renderTopLevelFieldDetail` instead.
*/
renderDetail(_context) {
// Prefix context with _
// This method implementation fulfills the interface requirement,
// but direct detail rendering of the whole document isn't meaningful here.
return [
{
uriSuffix: 'error',
data: null,
isError: true,
errorText: 'Error: Detail rendering requires specifying a top-level field (e.g., "info", "servers").',
renderAsList: true, // Errors often shown as plain text
},
];
}
/**
* Renders the detail view for a *specific* top-level field (e.g., 'info', 'servers').
* This is called by the handler after identifying the field.
*
* @param context - The rendering context.
* @param fieldObject - The actual top-level field object to render (e.g., document.info).
* @param fieldName - The name of the field being rendered (e.g., 'info').
* @returns An array of RenderResultItem representing the detail view.
*/
renderTopLevelFieldDetail(context, fieldObject, fieldName) {
// Ensure fieldObject is provided (handler should validate fieldName exists)
if (fieldObject === undefined || fieldObject === null) {
return [
{
uriSuffix: fieldName,
data: null,
isError: true,
errorText: `Error: Field "${fieldName}" not found in the OpenAPI document.`,
renderAsList: true,
},
];
}
// Avoid rendering structural fields that have dedicated list views
if (fieldName === 'paths' || fieldName === 'components') {
return [
{
uriSuffix: fieldName,
data: null,
isError: true,
errorText: `Error: Field "${fieldName}" should be accessed via its list view (${context.baseUri}${fieldName}). Use the list view first.`,
renderAsList: true,
},
];
}
try {
// For successful detail rendering, return the data object itself.
// The handler will format it using the context.formatter.
return [
{
uriSuffix: fieldName,
data: fieldObject, // Pass the raw data
// isError defaults to false
// renderAsList defaults to false (meaning use detail formatter)
},
];
}
catch (error) {
// Handle potential errors during data access or initial checks
// Formatting errors will be caught by the handler later
return [
{
uriSuffix: fieldName,
data: null,
isError: true,
errorText: `Error preparing field "${fieldName}" for rendering: ${error instanceof Error ? error.message : String(error)}`,
renderAsList: true,
},
];
}
} // End of renderTopLevelFieldDetail
// --- Helper methods to access specific parts ---
getPathsObject() {
return this.document.paths;
}
getComponentsObject() {
return this.document.components;
}
getTopLevelField(fieldName) {
// Define allowed top-level OpenAPI document properties
const allowedFields = [
'openapi',
'info',
'servers',
'paths',
'components',
'security',
'tags',
'externalDocs',
];
// Only allow access to documented OpenAPI properties
if (allowedFields.includes(fieldName)) {
return this.document[fieldName];
}
return undefined;
}
} // End of RenderableDocument class
//# sourceMappingURL=document.js.map