Generate MCP (Model Context Protocol) tools from YAML configuration files. Turn any REST API into callable MCP tools without writing code.
Project description
MCP YAML Server
Generate MCP (Model Context Protocol) tools from YAML configuration files. Turn any REST API into callable MCP tools without writing code.
Perfect for teams who want to expose internal APIs to AI assistants like Claude Desktop, GitHub Copilot, or any MCP-compatible client.
✨ Features
- 🎯 Zero-Code Integration - Define API endpoints in YAML, get working MCP tools
- 🔐 Multiple Auth Methods - API key, Bearer token, Basic auth, custom headers
- 📁 File Upload Support - Handle multipart/form-data with type/size validation
- 🔄 All HTTP Methods - GET, POST, PUT, PATCH, DELETE
- 🌐 Remote & Local - Works with both local and remote MCP servers
- ⚡ High Performance - Async HTTP with connection pooling and HTTP/2
- 🛡️ Type Safe - Pydantic validation for configuration and parameters
- 🐳 Docker Ready - Deploy as containerized HTTP/SSE server
- 🔧 Environment Variables - Secure credential management with
${VAR}syntax
📦 Installation
pip install mcp-yaml-server
Requirements: Python 3.10+
🚀 Quick Start
1. Create a YAML Configuration
Create my-api.yaml:
server:
name: "my_api_tools"
version: "1.0.0"
description: "My API integration"
global:
base_url: "https://jsonplaceholder.typicode.com"
timeout: 30
endpoints:
- name: "get_user"
description: "Retrieve user information by their unique ID"
method: "GET"
path: "/users/{id}"
parameters:
- name: "id"
type: "integer"
description: "The unique identifier of the user"
required: true
location: "path"
- name: "create_post"
description: "Create a new blog post for a user"
method: "POST"
path: "/posts"
parameters:
- name: "title"
type: "string"
description: "The title of the blog post"
required: true
location: "body"
- name: "body"
type: "string"
description: "The content body of the post"
required: true
location: "body"
- name: "userId"
type: "integer"
description: "The ID of the user creating the post"
required: true
location: "body"
2. Start the MCP Server
# Standard MCP server (stdio transport for Claude Desktop)
mcp-yaml-server my-api.yaml
# HTTP server for remote access
mcp-yaml-server --transport http --host 0.0.0.0 --port 8000 my-api.yaml
# SSE/Streaming HTTP server (for GitHub Copilot, etc.)
mcp-yaml-server --transport streamable-http --host 0.0.0.0 --port 8000 my-api.yaml
# Validate configuration without starting
mcp-yaml-server --dry-run my-api.yaml
# Debug mode with verbose logging
mcp-yaml-server --debug my-api.yaml
3. Connect from Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"my_api_tools": {
"command": "mcp-yaml-server",
"args": ["/absolute/path/to/my-api.yaml"]
}
}
}
Restart Claude Desktop - your tools are now available!
4. Connect from GitHub Copilot
Add to your MCP settings:
{
"servers": {
"my_api_tools": {
"type": "sse",
"url": "http://localhost:8000/mcp"
}
}
}
📖 Configuration Reference
Server Configuration
server:
name: "my_server" # Required: Server identifier (alphanumeric + underscore)
version: "1.0.0" # Required: Semantic version
description: "Description" # Optional: Human-readable description
Global Settings
global:
base_url: "https://api.example.com" # Required: Base URL for all endpoints
timeout: 30 # Optional: Default timeout in seconds (default: 30)
headers: # Optional: Headers added to all requests
X-Custom-Header: "value"
auth: # Optional: Authentication configuration
type: "bearer" # Options: bearer, api_key, basic, custom
bearer:
token: "${API_TOKEN}"
Authentication Types
Bearer Token
auth:
type: "bearer"
bearer:
token: "${AUTH_TOKEN}"
API Key
auth:
type: "api_key"
api_key:
header_name: "X-API-Key"
token: "${API_KEY}"
Basic Auth
auth:
type: "basic"
basic:
username: "${API_USER}"
password: "${API_PASS}"
Custom Headers
auth:
type: "custom"
custom:
headers:
Authorization: "Custom ${TOKEN}"
X-Auth-Provider: "my-provider"
Endpoint Configuration
endpoints:
- name: "endpoint_name" # Required: Tool name (alphanumeric + underscore)
description: "What this does" # Required: Min 20 characters
method: "GET" # Required: GET, POST, PUT, PATCH, DELETE
path: "/resource/{id}" # Required: URL path with optional {placeholders}
parameters: [...] # Optional: List of parameters
request_config: {...} # Optional: Request customization
response_config: {...} # Optional: Response handling
Parameter Configuration
parameters:
- name: "param_name" # Required: Parameter name
type: "string" # Required: string, integer, number, boolean, array, object
description: "What this param is" # Required: Min 20 characters
required: true # Required: true or false
location: "path" # Required: path, query, header, body, file
default: "value" # Optional: Default value if not provided
Parameter Locations:
path- URL path parameter (e.g.,/users/{id})query- URL query parameter (e.g.,?limit=10)header- HTTP headerbody- JSON request body fieldfile- File upload (multipart/form-data)
Request Configuration
request_config:
body_type: "json" # Options: json, form, multipart (default: json)
timeout: 60 # Override global timeout for this endpoint
headers: # Additional headers for this endpoint
X-Custom: "value"
files: # File upload configuration
max_size_mb: 50
allowed_types:
- "application/pdf"
- "image/jpeg"
- "image/png"
field_name: "file" # Form field name for file
multiple: false # Allow multiple files
Response Configuration
response_config:
success_codes: [200, 201] # Expected success status codes
extract_path: "$.data.items" # JSONPath to extract from response
error_handling:
extract_message_path: "$.error.msg" # JSONPath to extract error message
default_message: "Request failed" # Fallback error message
include_status_code: true # Include HTTP status in error
include_response_body: false # Include response body in error
📁 File Uploads
The server supports file uploads from both local and remote MCP clients:
endpoints:
- name: "upload_document"
description: "Upload and process a document file"
method: "POST"
path: "/documents/upload"
parameters:
- name: "file"
type: "string"
description: "Path to the document file to upload"
required: true
location: "file"
- name: "title"
type: "string"
description: "Title for the uploaded document"
required: true
location: "body"
request_config:
body_type: "multipart"
files:
max_size_mb: 50
allowed_types:
- "application/pdf"
- "image/jpeg"
- "image/png"
Usage:
- Local paths:
/Users/me/document.pdf- File is read automatically - Base64 content: Raw base64-encoded string for programmatic uploads
- Data URI:
data:application/pdf;base64,JVBERi0xLjQ...
🔐 Environment Variables
Use ${VAR_NAME} syntax for secure credential management:
global:
base_url: "${API_BASE_URL}"
auth:
type: "bearer"
bearer:
token: "${API_TOKEN}"
With defaults:
base_url: "${API_BASE_URL:https://api.example.com}"
timeout: "${TIMEOUT:30}"
Set variables before running:
export API_BASE_URL="https://api.example.com"
export API_TOKEN="your-secret-token"
mcp-yaml-server my-api.yaml
🐳 Docker Deployment
Using the Dockerfile
FROM python:3.11-slim
WORKDIR /app
RUN pip install mcp-yaml-server
COPY my-api.yaml /app/config.yaml
ENV MCP_CONFIG=/app/config.yaml
ENV HOST=0.0.0.0
ENV PORT=8000
CMD ["mcp-yaml-server", "--transport", "streamable-http", "--host", "0.0.0.0", "--port", "8000", "/app/config.yaml"]
Build and Run
docker build -t my-mcp-server .
docker run -p 8000:8000 -e API_TOKEN=secret my-mcp-server
Docker Compose
version: '3.8'
services:
mcp-server:
build: .
ports:
- "8000:8000"
environment:
- API_TOKEN=${API_TOKEN}
- API_BASE_URL=https://api.example.com
volumes:
- ./configs:/app/configs
command: >
mcp-yaml-server
--transport streamable-http
--host 0.0.0.0
--port 8000
/app/configs/my-api.yaml
🛠️ CLI Reference
# Start MCP server (stdio transport - default)
mcp-yaml-server config.yaml
# Start HTTP server
mcp-yaml-server --transport http --port 8000 config.yaml
# Start SSE/streaming server
mcp-yaml-server --transport streamable-http --port 8000 config.yaml
# Validate configuration
mcp-yaml-server --dry-run config.yaml
mcp-yaml-validate config.yaml
# Debug mode
mcp-yaml-server --debug config.yaml
# Multiple configurations
mcp-yaml-server api1.yaml api2.yaml
# Full options
mcp-yaml-server \
--transport streamable-http \
--host 0.0.0.0 \
--port 8000 \
--debug \
config.yaml
🔧 Troubleshooting
Common Issues
"Configuration file not found"
# Use absolute paths
mcp-yaml-server /absolute/path/to/config.yaml
"bearer field required when type is 'bearer'"
# Correct nested structure:
auth:
type: "bearer"
bearer:
token: "${TOKEN}"
"String should have at least 20 characters"
# Descriptions must be at least 20 characters
description: "This is a detailed description of the endpoint"
"Environment variable 'X' is not set"
# Set required variables
export API_TOKEN="your-token"
mcp-yaml-server config.yaml
File upload "File not found" on remote server
- Ensure you're running the latest version with client-side file reading
- For remote servers, files are read locally and uploaded automatically
Debug Mode
# Enable verbose logging
mcp-yaml-server --debug config.yaml
# Validate without starting
mcp-yaml-server --dry-run config.yaml
📚 Examples
See the examples/ directory for complete configuration examples:
sample-config.yaml- Basic GET endpointssample-github-api.yaml- GitHub API with authenticationsample-file-upload.yaml- File upload endpointsdpr-mock-server-config.yaml- Complex multi-endpoint configuration
🏗️ Architecture
- Language: Python 3.10+
- MCP Framework: FastMCP 2.x
- HTTP Client: httpx (async, HTTP/2)
- Validation: Pydantic 2.x
- YAML Parser: PyYAML 6.0+
⚡ Performance
- YAML parse/load: <1s for 50+ endpoints
- Tool metadata generation: <100ms per tool
- HTTP request overhead: <50ms beyond API latency
- Supports 100+ concurrent tool invocations
- Connection pooling and HTTP/2 for efficiency
🤝 Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
# Clone and install dev dependencies
git clone https://github.com/labtessi/mcp-yaml-server.git
cd mcp-yaml-server
pip install -e ".[dev]"
# Run tests
pytest
# Run linter
ruff check src/ tests/
# Format code
black src/ tests/
📄 License
MIT License - see LICENSE file for details.
🔗 Related Projects
📞 Support
- Issues: GitHub Issues
- Documentation: GitHub README
- MCP Docs: Model Context Protocol
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_yaml_server-1.1.0.tar.gz.
File metadata
- Download URL: mcp_yaml_server-1.1.0.tar.gz
- Upload date:
- Size: 37.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67d9b552c217755beb169310126fe037b186ed2208c469c849a1f9750462154e
|
|
| MD5 |
8e88122a671405e6905f365f4200d0ad
|
|
| BLAKE2b-256 |
d9cea3368478ea8c395aca0a2e176db3c06bfb7c10a0fd0040d8609792315b63
|
File details
Details for the file mcp_yaml_server-1.1.0-py3-none-any.whl.
File metadata
- Download URL: mcp_yaml_server-1.1.0-py3-none-any.whl
- Upload date:
- Size: 30.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
384fc2d6d84b8553532afacf347121cc2b7d848746ef4a6bd45ea761691ed511
|
|
| MD5 |
8b7d2cb0439b4ec3c0280e0f2dd0e5d5
|
|
| BLAKE2b-256 |
275ae290dc9a4e135f8597f391a728a3c4edebb031a221316c854995af10bf6b
|