diff --git a/CLAUDE.md b/CLAUDE.md index 7e39e2a..356f4f1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,92 +5,134 @@ MCP server for parsing, validating, and querying OpenAPI/Swagger specifications. ## Quick Start ```bash -# Install dependencies npm install - -# Build npm run build - -# Run (for testing) npm start ``` -## MCP Server Configuration +## MCP Configuration -Add to `~/.claude.json` (or project `.mcp.json`): +Add to `~/.claude.json`: ```json { "mcpServers": { "swagger-tools": { "command": "node", - "args": ["/absolute/path/to/swagger-tools/dist/index.js"] + "args": ["/Users/rimskij/projects/swagger-tools/dist/index.js"] } } } ``` -After configuring, restart Claude Code. The tools will be available as: -- `mcp__swagger-tools__parse-spec` -- `mcp__swagger-tools__validate-spec` -- `mcp__swagger-tools__query-endpoints` -- `mcp__swagger-tools__get-schema` -- `mcp__swagger-tools__generate-types` +Restart Claude Code after configuration. -## Claude Code Slash Command +## Available Tools -Use `/openapi` for convenient access: +| 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?` | -```bash -/openapi parse api.yaml # Parse and show overview -/openapi validate api.yaml # Validate spec -/openapi endpoints api.yaml # List all endpoints -/openapi schema api.yaml User # Get schema details -/openapi types api.yaml # Generate TypeScript types +## 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?" ``` ## Project Structure ``` src/ -├── index.ts # MCP server entry point (stdio) -├── tools/ # MCP tool implementations -│ ├── parse.ts # parse-spec tool -│ ├── validate.ts # validate-spec tool -│ ├── query.ts # query-endpoints tool -│ ├── schema.ts # get-schema tool -│ └── generate.ts # generate-types tool -├── lib/ # Core library -│ ├── parser.ts # OpenAPI parsing wrapper -│ ├── validator.ts # Validation logic -│ └── types.ts # TypeScript types +├── 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 +├── lib/ # Shared utilities +│ ├── parser.ts # SwaggerParser.dereference() wrapper +│ ├── validator.ts # SwaggerParser.validate() wrapper +│ └── types.ts # TypeScript interfaces └── utils/ - └── format.ts # Output formatting + └── format.ts # Human-readable output formatting +``` -.claude/ -└── commands/ - └── openapi.md # Slash command definition +## Code Patterns + +### Tool Structure + +Each tool exports: +```typescript +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: +```typescript +return { + content: [{ type: 'text', text: humanReadable }], + structuredContent: { success: true, data: ... } +}; +``` + +### Error Handling + +Wrap in try/catch, return error in both content and structuredContent: +```typescript +catch (err) { + return { + content: [{ type: 'text', text: `Error: ${err.message}` }], + structuredContent: { success: false, error: err.message } + }; +} ``` ## Development ```bash -# Type check without building -npm run typecheck - -# Run with tsx (development) -npm run dev +npm run build # Compile TypeScript +npm run typecheck # Type check only +npm run dev # Run with tsx (hot reload) ``` -## Supported Formats +## Testing -- OpenAPI 3.0.x -- OpenAPI 3.1.x -- Swagger 2.0 -- YAML and JSON files +```bash +# List tools +echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | node dist/index.js + +# Call a tool +echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"parse-spec","arguments":{"path":"test/fixtures/petstore.yaml"}}}' | 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`: + ```typescript + server.tool(name, description, schema, handler); + ``` +4. Rebuild: `npm run build` ## Dependencies -- `@modelcontextprotocol/sdk` - MCP server framework -- `@apidevtools/swagger-parser` - OpenAPI parsing and validation -- `zod` - Schema validation for tool inputs +| Package | Version | Purpose | +|---------|---------|---------| +| `@modelcontextprotocol/sdk` | ^1.0.0 | MCP protocol | +| `@apidevtools/swagger-parser` | ^10.1.0 | OpenAPI parsing | +| `zod` | ^3.23.0 | Schema validation | diff --git a/README.md b/README.md new file mode 100644 index 0000000..ce82045 --- /dev/null +++ b/README.md @@ -0,0 +1,291 @@ +# swagger-tools + +MCP (Model Context Protocol) server for parsing, validating, and querying OpenAPI/Swagger specifications. + +## Features + +- **Parse** OpenAPI 3.x and Swagger 2.0 specifications +- **Validate** specs against official schemas with detailed error reporting +- **Query** endpoints by method, path pattern, tag, or operation ID +- **Inspect** component schemas with resolved references +- **Generate** TypeScript interfaces from schemas +- **Support** both local files and remote URLs + +## Installation + +```bash +git clone https://git.hyperlocalplatform.com/rimskij/swagger-tools.git +cd swagger-tools +npm install +npm run build +``` + +## Configuration + +### Claude Code + +Add to `~/.claude.json`: + +```json +{ + "mcpServers": { + "swagger-tools": { + "command": "node", + "args": ["/path/to/swagger-tools/dist/index.js"] + } + } +} +``` + +Restart Claude Code after configuration. + +### Other MCP Clients + +The server uses stdio transport. Run with: + +```bash +node /path/to/swagger-tools/dist/index.js +``` + +Communicate via JSON-RPC 2.0 over stdin/stdout. + +## Tools + +### parse-spec + +Parse an OpenAPI/Swagger spec and return metadata. + +**Input:** +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `path` | string | Yes | Path to spec file or URL | + +**Output:** +- Version (OpenAPI 3.x or Swagger 2.0) +- Title and description +- Server URLs +- Path count, operation count, schema count +- Tags + +**Example:** +``` +Parse the OpenAPI spec at ./api.yaml +``` + +--- + +### validate-spec + +Validate a spec against the OpenAPI schema. + +**Input:** +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `path` | string | Yes | Path to spec file or URL | + +**Output:** +- Validation status (pass/fail) +- Errors with JSON path locations +- Warnings (missing operationId, missing descriptions) + +**Example:** +``` +Validate https://petstore.swagger.io/v2/swagger.json +``` + +--- + +### query-endpoints + +Search and filter API endpoints. + +**Input:** +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `path` | string | Yes | Path to spec file or URL | +| `method` | string | No | Filter by HTTP method (GET, POST, etc.) | +| `pathPattern` | string | No | Regex pattern to match paths | +| `tag` | string | No | Filter by tag name | +| `operationId` | string | No | Filter by exact operation ID | + +**Output:** +- Matching endpoints with: + - Method and path + - Operation ID and summary + - Tags + - Parameters (name, location, required, schema) + - Request body info + - Response status codes and content types + +**Examples:** +``` +Show all GET endpoints in api.yaml +List endpoints with path matching /users in api.yaml +Find endpoints tagged "authentication" in api.yaml +``` + +--- + +### get-schema + +Get details of a component schema. + +**Input:** +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `path` | string | Yes | Path to spec file or URL | +| `schemaName` | string | Yes | Schema name in components/schemas | + +**Output:** +- Schema name and type +- Description +- Full JSON schema with resolved $refs + +**Example:** +``` +Show the User schema from api.yaml +``` + +--- + +### generate-types + +Generate TypeScript interfaces from schemas. + +**Input:** +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `path` | string | Yes | Path to spec file or URL | +| `schemas` | string[] | No | Specific schemas (all if omitted) | + +**Output:** +- TypeScript interface/type definitions +- JSDoc comments from descriptions +- Proper handling of: + - Required vs optional properties + - Enums as union types + - Arrays and nested objects + - allOf (intersection), oneOf/anyOf (union) + - additionalProperties as Record + +**Examples:** +``` +Generate TypeScript types from api.yaml +Generate only User and Order types from api.yaml +``` + +## Supported Formats + +| Format | Version | File Types | +|--------|---------|------------| +| OpenAPI | 3.0.x | .yaml, .yml, .json | +| OpenAPI | 3.1.x | .yaml, .yml, .json | +| Swagger | 2.0 | .yaml, .yml, .json | + +## Input Sources + +| Source | Example | +|--------|---------| +| Local file (relative) | `./api.yaml` | +| Local file (absolute) | `/path/to/api.yaml` | +| Remote URL (HTTPS) | `https://example.com/openapi.json` | +| Remote URL (HTTP) | `http://localhost:3000/api-docs` | + +## Architecture + +``` +src/ +├── index.ts # MCP server entry (stdio transport) +├── tools/ +│ ├── parse.ts # parse-spec implementation +│ ├── validate.ts # validate-spec implementation +│ ├── query.ts # query-endpoints implementation +│ ├── schema.ts # get-schema implementation +│ └── generate.ts # generate-types implementation +├── lib/ +│ ├── parser.ts # SwaggerParser wrapper +│ ├── validator.ts # Validation logic +│ └── types.ts # TypeScript type definitions +└── utils/ + └── format.ts # Output formatting +``` + +## Dependencies + +| Package | Purpose | +|---------|---------| +| `@modelcontextprotocol/sdk` | MCP server framework | +| `@apidevtools/swagger-parser` | Parse, validate, dereference specs | +| `zod` | Input schema validation | + +## Development + +```bash +# Install dependencies +npm install + +# Build TypeScript +npm run build + +# Type check without emit +npm run typecheck + +# Run in development (with tsx) +npm run dev +``` + +## Testing + +Manual test with JSON-RPC: + +```bash +# List available tools +echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | node dist/index.js + +# Parse a spec +echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"parse-spec","arguments":{"path":"test/fixtures/petstore.yaml"}}}' | node dist/index.js +``` + +## Example Output + +### parse-spec + +``` +# Pet Store API +Version: OpenAPI 3.0.3 +Description: A sample Pet Store API + +## Statistics +- Paths: 3 +- Operations: 5 +- Schemas: 5 + +## Servers +- https://api.petstore.example.com/v1 + +## Tags +- pets +- store +``` + +### generate-types + +```typescript +/** A pet in the store */ +export interface Pet { + /** Unique identifier */ + id: number; + /** Pet name */ + name: string; + /** Pet availability status */ + status?: 'available' | 'pending' | 'sold'; + tags?: Tag[]; +} + +/** Pet availability status */ +export type PetStatus = 'available' | 'pending' | 'sold'; +``` + +## License + +MIT