Skip to content

feat: Automate OpenAPI generation from JSON Schema #178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions docs/server-registry-api/README.md

This file was deleted.

33 changes: 33 additions & 0 deletions docs/server-registry-api/generation/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Makefile for generating OpenAPI documentation

.PHONY: all generate bundle clean

# Default target
all: generate bundle

# Generate OpenAPI components from JSON Schema
generate:
@echo "Generating OpenAPI components from JSON Schema..."
@cd ../../../tools/server-json-to-openapi-sync && go run . \
-s ../../docs/server-json/schema.json \
-o ../../docs/server-registry-api/generation/openapi-components-generated.yaml

# Bundle the manual and generated files into final openapi.yaml
bundle: generate
@echo "Bundling OpenAPI files..."
@npx @redocly/cli bundle openapi-manual.yaml -o ../openapi.yaml

# Clean generated files
clean:
@echo "Cleaning generated files..."
@rm -f openapi-components-generated.yaml ../openapi.yaml

# Install required tools
install-tools:
@echo "Installing required tools..."
@npm install -g @redocly/cli

# Validate the final OpenAPI spec
validate: bundle
@echo "Validating OpenAPI spec..."
@npx @redocly/cli lint ../openapi.yaml
65 changes: 65 additions & 0 deletions docs/server-registry-api/generation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Server Registry API Generation

This directory contains the source files and tools for generating the OpenAPI specification for the MCP Server Registry API.

## Files

- **`openapi-manual.yaml`** - Hand-written API endpoints and registry-specific extensions
- **`openapi-components-generated.yaml`** - Auto-generated from `../../server-json/schema.json` (DO NOT EDIT)
- **`Makefile`** - Build commands for generating and bundling the specifications

The generated `openapi.yaml` is output to the parent directory (`../openapi.yaml`).

## Architecture

The OpenAPI specification is split into two parts to maintain DRY principles:

1. **Generated Components**: Common schemas are automatically generated from the canonical `server-json/schema.json` file
2. **Manual Definitions**: API-specific endpoints, extensions, and registry-specific fields are maintained manually

This approach ensures that:
- Core data models stay in sync with the JSON Schema source of truth
- API-specific concerns remain separate and maintainable
- The final specification is a complete, self-contained OpenAPI document

## Workflow

### Regenerating the OpenAPI Specification

```bash
# From this directory
make all

# Or from the project root
go generate ./...
```

This will:
1. Generate `openapi-components-generated.yaml` from `../../server-json/schema.json`
2. Bundle `openapi-manual.yaml` with the generated components into `../openapi.yaml`

### Making Changes

- **To modify core data models**: Edit `../../server-json/schema.json` and run `make all`
- **To modify API endpoints or registry-specific fields**: Edit `openapi-manual.yaml` and run `make bundle`
- **Never edit** `openapi-components-generated.yaml` or `openapi.yaml` directly

### Validating Changes

```bash
make validate
```

## Dependencies

- Go 1.22+ (for the schema converter)
- Node.js and npm (for the OpenAPI bundler)
- `@redocly/cli` (installed automatically when running make commands)

## Schema Extensions

The manual file extends generated schemas with registry-specific fields:

- `Server` adds an `id` field for registry identification
- `VersionDetail` adds `release_date` and `is_latest` fields
- `ServerList` is a registry-specific schema for pagination
240 changes: 240 additions & 0 deletions docs/server-registry-api/generation/openapi-components-generated.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
# THIS FILE IS AUTO-GENERATED. DO NOT EDIT.
# Generated from ../../docs/server-json/schema.json
# Run 'go generate' to regenerate this file.

components:
schemas:
Argument:
anyOf:
- $ref: '#/components/schemas/PositionalArgument'
- $ref: '#/components/schemas/NamedArgument'
Input:
properties:
choices:
description: A list of possible values for the input. If provided, the user must select one of these values.
example: []
items:
type: string
type: array
default:
description: The default value for the input.
type: string
description:
description: A description of the input, which clients can use to provide context to the user.
type: string
format:
default: string
description: |-
Specifies the input format. Supported values include `filepath`, which should be interpreted as a file on the user's filesystem.

When the input is converted to a string, booleans should be represented by the strings "true" and "false", and numbers should be represented as decimal values.
enum:
- string
- number
- boolean
- filepath
type: string
is_required:
default: false
type: boolean
is_secret:
default: false
description: Indicates whether the input is a secret value (e.g., password, token). If true, clients should handle the value securely.
type: boolean
value:
description: |
The default value for the input. If this is not set, the user may be prompted to provide a value. If a value is set, it should not be configurable by end users.

Identifiers wrapped in `{curly_braces}` will be replaced with the corresponding properties from the input `variables` map. If an identifier in braces is not found in `variables`, or if `variables` is not provided, the `{curly_braces}` substring should remain unchanged.
type: string
type: object
InputWithVariables:
allOf:
- $ref: '#/components/schemas/Input'
- properties:
variables:
additionalProperties:
$ref: '#/components/schemas/Input'
description: A map of variable names to their values. Keys in the input `value` that are wrapped in `{curly_braces}` will be replaced with the corresponding variable values.
type: object
type: object
KeyValueInput:
allOf:
- $ref: '#/components/schemas/InputWithVariables'
- properties:
name:
description: Name of the header or environment variable.
example: SOME_VARIABLE
type: string
required:
- name
type: object
NamedArgument:
allOf:
- $ref: '#/components/schemas/InputWithVariables'
- properties:
is_repeated:
default: false
description: Whether the argument can be repeated multiple times.
type: boolean
name:
description: The flag name, including any leading dashes.
example: --port
type: string
type:
enum:
- named
example: named
type: string
required:
- type
- name
type: object
description: A command-line `--flag={value}`.
Package:
properties:
environment_variables:
description: A mapping of environment variables to be set when running the package.
items:
$ref: '#/components/schemas/KeyValueInput'
type: array
name:
description: Package name in the registry
example: io.modelcontextprotocol/filesystem
type: string
package_arguments:
description: A list of arguments to be passed to the package's binary.
items:
$ref: '#/components/schemas/Argument'
type: array
registry_name:
description: Package registry type
example: npm
type: string
runtime_arguments:
description: A list of arguments to be passed to the package's runtime command (such as docker or npx). The `runtime_hint` field should be provided when `runtime_arguments` are present.
items:
$ref: '#/components/schemas/Argument'
type: array
runtime_hint:
description: A hint to help clients determine the appropriate runtime for the package. This field should be provided when `runtime_arguments` are present.
examples:
- npx
- uvx
- dnx
type: string
version:
description: Package version
example: 1.0.2
type: string
required:
- registry_name
- name
- version
type: object
PositionalArgument:
allOf:
- $ref: '#/components/schemas/InputWithVariables'
- properties:
is_repeated:
default: false
description: Whether the argument can be repeated multiple times in the command line.
type: boolean
type:
enum:
- positional
example: positional
type: string
value_hint:
description: An identifier-like hint for the value. This is not part of the command line, but can be used by client configuration and to provide hints to users.
example: file_path
type: string
required:
- type
- value_hint
type: object
description: A positional input is a value inserted verbatim into the command line.
Remote:
properties:
headers:
description: HTTP headers to include
items:
$ref: '#/components/schemas/KeyValueInput'
type: array
transport_type:
description: Transport protocol type
enum:
- streamable
- sse
example: sse
type: string
url:
description: Remote server URL
example: https://mcp-fs.example.com/sse
format: uri
type: string
required:
- transport_type
- url
type: object
Repository:
properties:
id:
example: b94b5f7e-c7c6-d760-2c78-a5e9b8a5b8c9
type: string
source:
description: Repository hosting service
example: github
type: string
url:
example: https://github.com/modelcontextprotocol/servers
format: uri
type: string
required:
- url
- source
- id
type: object
Server:
properties:
description:
description: Human-readable description of the server's functionality
example: Node.js server implementing Model Context Protocol (MCP) for filesystem operations.
type: string
name:
description: Server name/identifier
example: io.modelcontextprotocol/filesystem
type: string
repository:
$ref: '#/components/schemas/Repository'
version_detail:
$ref: '#/components/schemas/VersionDetail'
required:
- name
- description
- version_detail
type: object
ServerDetail:
allOf:
- $ref: '#/components/schemas/Server'
- properties:
packages:
items:
$ref: '#/components/schemas/Package'
type: array
remotes:
items:
$ref: '#/components/schemas/Remote'
type: array
type: object
description: Schema for a static representation of an MCP server. Used in various contexts related to discovery, installation, and configuration.
VersionDetail:
description: Version information for this server. Defined as an object to allow for downstream extensibility (e.g. release_date)
properties:
version:
description: Equivalent of Implementation.version in MCP specification.
example: 1.0.2
type: string
required:
- version
type: object
Loading
Loading