Skip to main content
Glama

get-api-spec

Convert Swagger API specifications to minified markdown or JSON format for documentation purposes.

Instructions

Get and convert Swagger specification for an API group to a minified markdown format

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
apigroup_idYesID of the API group to get specification for
formatNoOutput format: 'markdown' for concise documentation or 'json' for full specificationmarkdown

Implementation Reference

  • Main execution logic for the get-api-spec tool: fetches API group, retrieves Swagger spec via link, processes to markdown or JSON.
    async ({ apigroup_id, format }) => {
      console.error(`[Tool] Executing get-api-spec for API group ID: ${apigroup_id} with format: ${format}`);
      try {
        // Step 1: Get the API group details to find the Swagger spec link
        const apiGroup = await makeXanoRequest<XanoApiGroup>(`/workspace/${XANO_WORKSPACE}/apigroup/${apigroup_id}`);
        
        if (!apiGroup.swagger || !apiGroup.documentation || !apiGroup.documentation.link) {
          return {
            content: [
              {
                type: "text",
                text: `API group (ID: ${apigroup_id}) does not have Swagger documentation available.`
              }
            ],
            isError: true
          };
        }
        
        console.error(`[Tool] Found Swagger spec link: ${apiGroup.documentation.link}`);
        
        // Step 2: Fetch the Swagger JSON specification
        const swaggerResponse = await fetch(apiGroup.documentation.link);
        if (!swaggerResponse.ok) {
          throw new Error(`Failed to fetch Swagger spec: ${swaggerResponse.statusText}`);
        }
        
        const swaggerSpec = await swaggerResponse.json();
        console.error(`[Tool] Successfully retrieved Swagger specification`);
        
        // Step 3: Process the spec based on format
        if (format === "json") {
          // Return the full JSON specification
          return {
            content: [
              {
                type: "text",
                text: `# ${apiGroup.name} API Specification (Full JSON)\n\n\`\`\`json\n${JSON.stringify(swaggerSpec, null, 2)}\n\`\`\``
              }
            ]
          };
        } else {
          // Process the Swagger spec into a minified markdown format
          const markdown = processSwaggerToMarkdown(swaggerSpec, apiGroup.name);
          
          return {
            content: [
              {
                type: "text",
                text: markdown
              }
            ]
          };
        }
      } catch (error) {
        console.error(`[Error] Failed to get API spec: ${error instanceof Error ? error.message : String(error)}`);
        return {
          content: [
            {
              type: "text",
              text: `Error getting API specification: ${error instanceof Error ? error.message : String(error)}`
            }
          ],
          isError: true
        };
      }
    }
  • Zod input schema defining parameters: apigroup_id (string) and format (markdown/json, default markdown).
    {
      apigroup_id: z.string().describe("ID of the API group to get specification for"),
      format: z.enum(["markdown", "json"]).default("markdown").describe("Output format: 'markdown' for concise documentation or 'json' for full specification")
    },
  • src/index.ts:565-638 (registration)
    MCP server.tool registration for the get-api-spec tool, including name, description, input schema, and handler function.
    server.tool(
      "get-api-spec",
      "Get and convert Swagger specification for an API group to a minified markdown format",
      {
        apigroup_id: z.string().describe("ID of the API group to get specification for"),
        format: z.enum(["markdown", "json"]).default("markdown").describe("Output format: 'markdown' for concise documentation or 'json' for full specification")
      },
      async ({ apigroup_id, format }) => {
        console.error(`[Tool] Executing get-api-spec for API group ID: ${apigroup_id} with format: ${format}`);
        try {
          // Step 1: Get the API group details to find the Swagger spec link
          const apiGroup = await makeXanoRequest<XanoApiGroup>(`/workspace/${XANO_WORKSPACE}/apigroup/${apigroup_id}`);
          
          if (!apiGroup.swagger || !apiGroup.documentation || !apiGroup.documentation.link) {
            return {
              content: [
                {
                  type: "text",
                  text: `API group (ID: ${apigroup_id}) does not have Swagger documentation available.`
                }
              ],
              isError: true
            };
          }
          
          console.error(`[Tool] Found Swagger spec link: ${apiGroup.documentation.link}`);
          
          // Step 2: Fetch the Swagger JSON specification
          const swaggerResponse = await fetch(apiGroup.documentation.link);
          if (!swaggerResponse.ok) {
            throw new Error(`Failed to fetch Swagger spec: ${swaggerResponse.statusText}`);
          }
          
          const swaggerSpec = await swaggerResponse.json();
          console.error(`[Tool] Successfully retrieved Swagger specification`);
          
          // Step 3: Process the spec based on format
          if (format === "json") {
            // Return the full JSON specification
            return {
              content: [
                {
                  type: "text",
                  text: `# ${apiGroup.name} API Specification (Full JSON)\n\n\`\`\`json\n${JSON.stringify(swaggerSpec, null, 2)}\n\`\`\``
                }
              ]
            };
          } else {
            // Process the Swagger spec into a minified markdown format
            const markdown = processSwaggerToMarkdown(swaggerSpec, apiGroup.name);
            
            return {
              content: [
                {
                  type: "text",
                  text: markdown
                }
              ]
            };
          }
        } catch (error) {
          console.error(`[Error] Failed to get API spec: ${error instanceof Error ? error.message : String(error)}`);
          return {
            content: [
              {
                type: "text",
                text: `Error getting API specification: ${error instanceof Error ? error.message : String(error)}`
              }
            ],
            isError: true
          };
        }
      }
    );
  • Supporting function that converts raw Swagger/OpenAPI JSON specification into a concise, minified markdown documentation format for the tool's markdown output.
    // Helper function to process Swagger spec into concise markdown
    function processSwaggerToMarkdown(swaggerSpec: any, apiGroupName: string): string {
      try {
        console.error(`[Process] Converting Swagger spec to markdown for: ${apiGroupName}`);
        
        // Extract basic API information
        const info = swaggerSpec.info || {};
        const server = swaggerSpec.servers?.[0]?.url || 'https://';
        const baseUrl = server;
        
        // Build the markdown content
        let markdown = `# ${apiGroupName} API\n\n`;
        markdown += `## API Info\n`;
        markdown += `- Title: ${info.title || apiGroupName}\n`;
        markdown += `- Version: ${info.version || 'N/A'}\n`;
        markdown += `- Base URL: ${baseUrl}\n\n`;
        
        // Common responses
        markdown += `## Responses\n`;
        markdown += `| Code | Description |\n`;
        markdown += `|------|-------------|\n`;
        markdown += `| 200  | Success!    |\n`;
        markdown += `| 400  | Input Error |\n`;
        markdown += `| 401  | Unauthorized|\n`;
        markdown += `| 403  | Access Denied|\n`;
        markdown += `| 404  | Not Found  |\n`;
        markdown += `| 429  | Rate Limited|\n`;
        markdown += `| 500  | Server Error|\n\n`;
        
        // Process endpoints
        markdown += `## Endpoints\n\n`;
        const paths = swaggerSpec.paths || {};
        const pathKeys = Object.keys(paths).sort();
        
        for (const path of pathKeys) {
          const pathInfo = paths[path];
          const methods = Object.keys(pathInfo).filter(m => ['get', 'post', 'put', 'delete', 'patch'].includes(m.toLowerCase()));
          
          for (const method of methods) {
            const operation = pathInfo[method];
            markdown += `### ${method.toUpperCase()} ${path}\n`;
            markdown += `${operation.summary || 'No summary'}\n`;
            
            // Parameters
            const parameters = operation.parameters || [];
            if (parameters.length > 0) {
              markdown += `| Param | In | Req | Type |\n`;
              markdown += `|-------|----|-----|------|\n`;
              for (const param of parameters) {
                markdown += `| ${param.name} | ${param.in} | ${param.required ? 'Y' : 'N'} | ${param.schema?.type || 'unknown'} |\n`;
              }
            }
            markdown += '\n';
          }
        }
        
        // Authentication
        const securitySchemes = swaggerSpec.components?.securitySchemes || {};
        if (Object.keys(securitySchemes).length > 0) {
          markdown += `## Auth\n`;
          for (const name in securitySchemes) {
            const scheme = securitySchemes[name];
            markdown += `- ${name}: ${scheme.type}`;
            if (scheme.scheme) markdown += ` (${scheme.scheme})`;
            markdown += '\n';
          }
        }
        
        console.error(`[Process] Successfully converted Swagger spec to markdown`);
        return markdown;
        
      } catch (error) {
        console.error(`[Error] Error processing Swagger to Markdown: ${error instanceof Error ? error.message : String(error)}`);
        return `# Error\n\n${error instanceof Error ? error.message : String(error)}`;
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions the conversion to 'minified markdown format', which adds some context about output behavior, but fails to address critical aspects like whether this is a read-only operation, potential rate limits, authentication needs, or error handling. This leaves significant gaps for a tool that fetches and processes data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core action ('get and convert') without unnecessary words. Every part earns its place by specifying the resource and output format, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (fetching and converting API specs), no annotations, and no output schema, the description is adequate but incomplete. It covers the basic purpose and output format but lacks details on behavioral traits, error cases, or return structure, which are needed for full contextual understanding in this scenario.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents both parameters (apigroup_id and format). The description adds minimal value by implying the format parameter's purpose ('convert... to a minified markdown format'), but doesn't provide additional semantics beyond what the schema already states (e.g., details on 'minified' or conversion process). This meets the baseline for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('get and convert') and resource ('Swagger specification for an API group'), distinguishing it from siblings like 'list-api-groups' or 'browse-apis'. However, it doesn't explicitly differentiate from potential similar tools like 'get-table-schema' in terms of resource type, keeping it at 4 instead of 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites (e.g., needing an existing API group), exclusions, or comparisons to siblings like 'browse-apis' or 'list-api-groups', leaving the agent with minimal context for selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lowcodelocky2/xano-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server