Understanding how the Windmill MCP Server is generated from OpenAPI specifications.
The generator system automatically creates an MCP server from Windmill's OpenAPI specification. This enables:
- Automatic updates when Windmill API changes
- Preservation of custom modifications
- Consistent tool naming and organization
- Comprehensive API coverage
┌─────────────────┐
│ Windmill OpenAPI│
│ Specification │
└────────┬────────┘
│ fetch-spec.js
▼
┌────────┐
│ Cache │
└───┬────┘
│ generate.js
▼
┌──────────────────┐
│ openapi-mcp- │
│ generator │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Generated TS │
│ build/src/ │
└────────┬─────────┘
│ add-tool-namespaces.js
▼
┌──────────────────┐
│ Namespaced Tools │
└────────┬─────────┘
│ apply-overrides.js
▼
┌──────────────────┐
│ Custom Overrides │
│ Applied │
└────────┬─────────┘
│ npm build
▼
┌──────────────────┐
│ Compiled JS │
│ build/dist/ │
└──────────────────┘
Fetches the OpenAPI specification from Windmill.
Usage:
npm run fetch-specWhat it does:
- Downloads OpenAPI spec from configured URL
- Validates the spec is valid JSON
- Saves to
cache/openapi-spec-{version}.json - Extracts Windmill version from spec
Configuration (in src/generator/config.json):
{
"openapiSpecUrl": "https://app.windmill.dev/api/openapi.json",
"cacheDir": "cache"
}Caching:
- Specs are cached by version
- Reduces network calls during development
- Can be manually cleared:
rm -rf cache/
Orchestrates the generation process using openapi-mcp-generator.
Usage:
npm run generateWhat it does:
- Reads cached OpenAPI spec
- Configures openapi-mcp-generator
- Generates TypeScript MCP server in
build/ - Triggers post-generation hooks
Configuration (in src/generator/config.json):
{
"outputDir": "build",
"serverName": "windmill-mcp-server",
"generatorOptions": {
"includeOptionalParams": true,
"validateRequiredParams": true
}
}Generator Options:
includeOptionalParams: Include optional parameters in tool definitionsvalidateRequiredParams: Validate required parameters at runtimegroupByTag: Group tools by OpenAPI tags (auto-enabled)
Organizes the 500+ generated tools into logical categories.
Usage:
npm run add-tool-namespacesWhat it does:
- Parses generated tools
- Groups by OpenAPI tags (e.g.,
job,script,workflow) - Adds namespace prefixes (e.g.,
job:listJobs) - Creates 59 organized categories
Example Transformation:
// Before
tools.push({
name: "listJobs",
description: "list all available jobs"
});
// After
tools.push({
name: "job:listJobs",
description: "list all available jobs"
});Benefits:
- Easier discovery of related tools
- Prevents name collisions
- Better organization in MCP clients
- Matches Windmill API structure
Applies custom modifications that persist across regenerations.
Usage:
npm run apply-overridesWhat it does:
- Scans
src/overrides/for override files - Matches override structure to
build/structure - Copies override files, replacing generated versions
- Preserves custom modifications
Override Structure:
src/overrides/
└── src/
└── index.ts # Overrides build/src/index.ts
Use Cases:
- Fix bugs in generated code
- Add custom error handling
- Implement missing features
- Optimize performance
Creating Overrides:
- Identify file to override in
build/src/ - Create matching path in
src/overrides/ - Copy and modify the file
- Run
npm run generateto apply
Validation:
npm run validate-overridesChecks:
- Override paths match generated structure
- TypeScript syntax is valid
- No conflicting overrides
Compiles TypeScript to JavaScript.
What it does:
- Changes to
build/directory - Installs dependencies (if needed)
- Runs TypeScript compiler
- Outputs to
build/dist/index.js
Configuration (in build/tsconfig.json, auto-generated):
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"outDir": "./dist",
"strict": true
}
}Creates documentation of all available tools.
Usage:
npm run generate-tool-listWhat it does:
- Parses generated MCP server
- Extracts all tool definitions
- Groups by namespace/category
- Generates
docs/reference/generated-tools.md
Output Format:
## category:name
### `tool:name`
Description of the tool
### `tool:anotherName`
Description of another toolThe npm run generate command runs all steps in order:
# 1. Pre-generation hook
npm run fetch-spec
# 2. Main generation
node src/generator/generate.js
# 3. Post-generation hooks
npm run add-tool-namespaces
npm run apply-overrides
npm run build:generated
npm run generate-tool-listnpm script definition:
{
"scripts": {
"pregenerate": "npm run fetch-spec",
"generate": "node src/generator/generate.js",
"postgenerate": "npm run add-tool-namespaces && npm run apply-overrides && npm run build:generated && npm run generate-tool-list"
}
}Edit src/generator/config.json:
{
"openapiSpecUrl": "https://your-windmill.com/api/openapi.json"
}Edit src/generator/config.json:
{
"generatorOptions": {
"includeOptionalParams": false,
"validateRequiredParams": true,
"customOption": "value"
}
}Add to postgenerate script in package.json:
{
"postgenerate": "npm run add-tool-namespaces && npm run apply-overrides && npm run build:generated && npm run generate-tool-list && npm run your-custom-step"
}# TypeScript source
less build/src/index.ts
# Compiled JavaScript
less build/dist/index.js# Test spec fetching
npm run fetch-spec
ls -la cache/
# Test generation only
node src/generator/generate.js
ls -la build/src/
# Test overrides only
npm run apply-overrides
git diff build/src/Generation fails:
- Check internet connectivity
- Verify OpenAPI spec URL is accessible
- Check disk space for cache and build
- Review error messages in console
Overrides not applied:
- Check override file paths match generated structure
- Run
npm run validate-overrides - Ensure generation completed successfully
- Check file permissions
Build fails:
- Check TypeScript syntax in generated code
- Review compilation errors
- Try cleaning:
rm -rf build/ && npm run generate - Check Node.js version compatibility
The generator tracks versions at multiple levels:
- OpenAPI Spec Version: Extracted from spec
info.version - Windmill Version: From spec or environment
- Package Version: From
package.json - Generator Version: From openapi-mcp-generator
Versions are embedded in generated code and used by the runtime loader.
To use a different generator:
-
Install alternative generator:
npm install your-generator
-
Modify
src/generator/generate.js:const generator = require('your-generator');
-
Update configuration accordingly
Generate for multiple versions:
# Generate for specific version
WINDMILL_VERSION=1.520.1 npm run generate
mv build build-1.520.1
# Generate for another version
WINDMILL_VERSION=1.519.0 npm run generate
mv build build-1.519.0See .github/workflows/update-mcp-server.yml for automated generation in GitHub Actions.
- Override System - Detailed override documentation
- Testing Generated Code - Test the generated server
- Architecture - Overall system architecture
- openapi-mcp-generator - Generator tool
- Windmill OpenAPI - Windmill API docs