swagger-tools/CLAUDE.md
rimskij 7791adc288 docs: update README and CLAUDE.md with new features
- Document broken $ref fallback handling
- Document .NET-style name sanitization for TypeScript
- Add "Tested With" section showing enterprise API support
- Add example output from .NET API
- Update CLAUDE.md with key features section

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-12 15:15:34 +01:00

4.6 KiB

swagger-tools

MCP server for parsing, validating, and querying OpenAPI/Swagger specifications.

Quick Start

npm install
npm run build
npm start

MCP Configuration

Add to ~/.claude.json:

{
  "mcpServers": {
    "swagger-tools": {
      "command": "node",
      "args": ["/Users/rimskij/projects/swagger-tools/dist/index.js"]
    }
  }
}

Restart Claude Code after configuration.

Available Tools

Tool Purpose Key Parameters
parse-spec Parse spec, show metadata path
validate-spec Validate against schema path
query-endpoints Search/filter endpoints path, method?, pathPattern?, tag?
get-schema Get schema details path, schemaName
generate-types Generate TypeScript path, schemas?

Usage Examples

# Natural language - Claude calls the right tool
"Parse the API spec at ./api.yaml"
"Show me all POST endpoints in api.yaml"
"Generate TypeScript types from https://petstore.swagger.io/v2/swagger.json"
"Is api.yaml valid?"
"What does the User schema look like?"

Key Features

Broken $ref Fallback

When specs have broken $ref pointers, parser falls back to non-dereferenced mode:

// In lib/parser.ts
try {
  spec = await SwaggerParser.dereference(specPath);  // Try first
} catch {
  spec = await SwaggerParser.parse(specPath);        // Fallback
}

.NET Name Sanitization

Converts .NET-style schema names to valid TypeScript:

// In tools/generate.ts - sanitizeName()
"Namespace.Type"            "Type"
"Generic`1[Inner]"          "Generic_Inner"
"Company.Api.V5.ViewModel"  "ViewModel"

Project Structure

src/
├── index.ts              # Entry point - registers tools, starts stdio server
├── tools/                # Tool implementations
│   ├── parse.ts          # parseSpec() → metadata extraction
│   ├── validate.ts       # validateSpec() → error collection
│   ├── query.ts          # queryEndpoints() → filtering logic
│   ├── schema.ts         # getSchema() → schema lookup
│   └── generate.ts       # generateTypes() → TS code generation + sanitizeName()
├── lib/                  # Shared utilities
│   ├── parser.ts         # SwaggerParser wrapper (dereference with fallback)
│   ├── validator.ts      # SwaggerParser.validate() wrapper
│   └── types.ts          # TypeScript interfaces
└── utils/
    └── format.ts         # Human-readable output formatting

Code Patterns

Tool Structure

Each tool exports:

export const toolName = 'tool-name';
export const toolDescription = '...';
export const toolSchema = { param: z.string() };
export async function toolHandler({ param }) { ... }

Return Format

Tools return MCP-compatible responses:

return {
  content: [{ type: 'text', text: humanReadable }],
  structuredContent: { success: true, data: ... }
};

Error Handling

Wrap in try/catch, return error in both content and structuredContent:

catch (err) {
  return {
    content: [{ type: 'text', text: `Error: ${err.message}` }],
    structuredContent: { success: false, error: err.message }
  };
}

Development

npm run build      # Compile TypeScript
npm run typecheck  # Type check only
npm run dev        # Run with tsx (hot reload)

Testing

# List tools
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | node dist/index.js

# Local spec
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"parse-spec","arguments":{"path":"test/fixtures/petstore.yaml"}}}' | node dist/index.js

# Remote URL
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"parse-spec","arguments":{"path":"https://petstore.swagger.io/v2/swagger.json"}}}' | node dist/index.js

# Enterprise API with broken refs
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"parse-spec","arguments":{"path":"https://projects.moravia.com/api/swagger/v5/swagger.json"}}}' | node dist/index.js

Adding New Tools

  1. Create src/tools/newtool.ts following existing pattern
  2. Export name, description, schema, handler
  3. Import and register in src/index.ts:
    server.tool(name, description, schema, handler);
    
  4. Rebuild: npm run build

Dependencies

Package Version Purpose
@modelcontextprotocol/sdk ^1.0.0 MCP protocol
@apidevtools/swagger-parser ^10.1.0 OpenAPI parsing
zod ^3.23.0 Schema validation