Generate MCP servers from plain-English skill descriptions
Project description
skill-to-mcp
Turn a plain-English skill description into a working MCP server in seconds.
skill-to-mcp is a CLI code generator that reads a SKILL.md file — a plain-English description of a tool — and scaffolds a complete, runnable MCP (Model Context Protocol) server with:
- ✅ Correct JSON-RPC schema (
tool_name,description,inputSchema,outputSchema) - ✅ Pydantic v2 models for type-safe input/output
- ✅ MCP server boilerplate (stdio or HTTP SSE transport)
- ✅
pyproject.tomlready forpip install - ✅ Auto-generated
README.mdwith usage instructions
Why?
Describing a tool in Markdown is more readable, versionable, and composable than hand-writing JSON-RPC schemas. skill-to-mcp bridges the gap between "I know what my tool does" and "I have a working MCP server."
Read the full motivation: SKILL.md might be a better abstraction than function calling
Apify Actor
Run skill-to-mcp on the Apify platform:
docker build -t skill-to-mcp .
docker run -e DEEPSEEK_API_KEY=sk-... skill-to-mcp
The Apify Actor accepts the same inputs as the CLI via a web form: Skill Description (required), LLM Model, MCP Transport, Generate Example Implementation, and API Key.
Output is pushed to the Apify Dataset and a ZIP archive of all generated files is saved to the key-value store.
The Actor builds directly from this git repository via
.actor/actor.json and the root
Dockerfile (entry point: python -m skill_to_mcp.actor).
Quick Start
1. Install
pip install skillmd-to-mcp
2. Set your API key
export DEEPSEEK_API_KEY="sk-your-key-here"
Get a key at platform.deepseek.com. Cost per generation: < $0.001 with DeepSeek.
OpenAI fallback: If you have an OpenAI key, set
OPENAI_API_KEYinstead. The CLI automatically tries both:DEEPSEEK_API_KEYfirst, thenOPENAI_API_KEY.
3. Create a SKILL.md
# webpage-reader
Fetches a web page given a URL and returns:
- title: the page title
- description: the meta description
- body_text: visible text stripped of HTML
- links: list of the first 10 internal links
## Input
- url: string, required
- max_links: integer, default 10
4. Generate the MCP server
skill-to-mcp generate SKILL.md
Output:
output/
└── webpage-reader/
├── server.py # MCP server, runnable immediately
├── models.py # Pydantic v2 input/output models
├── handler.py # Tool logic (stub — implement here)
├── pyproject.toml # Dependencies and metadata
└── README.md # Installation and usage guide
5. Implement & Run
cd output/webpage-reader
pip install -e .
# Edit handler.py to add your business logic
python server.py
CLI Reference
skill-to-mcp generate SKILL.md [OPTIONS]
Arguments
| Argument | Description |
|---|---|
SKILL.md |
Path to the skill description file |
Options
| Option | Short | Default | Description |
|---|---|---|---|
--output-dir |
-o |
./output |
Output directory for generated files |
--model |
-m |
deepseek-v4-flash |
LLM model for schema inference |
--api-key |
-k |
$DEEPSEEK_API_KEY or $OPENAI_API_KEY |
API key for the LLM provider. Falls back to OPENAI_API_KEY if DEEPSEEK_API_KEY is not set |
--transport |
-t |
stdio |
MCP transport: stdio or sse |
--dry-run |
false |
Show inferred schema without generating files | |
--prompt-file |
-p |
Custom system prompt for LLM inference | |
--with-example-impl |
false |
Generate a working handler implementation via LLM | |
--templates-dir |
Custom Jinja2 templates directory | ||
--verbose |
-v |
false |
Enable debug logging |
Batch Processing
Process multiple SKILL.md files at once:
skill-to-mcp generate tool1.md tool2.md tool3.md -o ./my-tools
skill-to-mcp generate *.md --with-example-impl
Examples
# Basic usage
skill-to-mcp generate SKILL.md
# Preview the inferred schema (no files written)
skill-to-mcp generate SKILL.md --dry-run
# Use SSE transport for HTTP-based MCP hosts
skill-to-mcp generate SKILL.md --transport sse
# Custom output directory
skill-to-mcp generate SKILL.md -o ./my-mcp-tools
# Use a specific model
skill-to-mcp generate SKILL.md -m deepseek-v4-flash
# Custom LLM prompt
skill-to-mcp generate SKILL.md --prompt-file my_prompt.txt
# Verbose output for debugging
skill-to-mcp generate SKILL.md -v
Architecture
flowchart LR
A[SKILL.md] --> B[parser.py]
B --> C[llm.py]
C --> D[DeepSeek API]
D --> E[validator.py]
E -->|valid| F[renderer.py]
E -->|invalid + retry| C
F --> G[templates/]
G --> H[output/]
Pipeline
parser.py— ReadsSKILL.md, extracts title and sectionsllm.py— Calls DeepSeek API (OpenAI-compatible) to infer JSON Schemavalidator.py— Validates schema (types, snake_case, required fields)renderer.py— Applies Jinja2 templates to generate Python codecli.py— Typer-based CLI with Rich output
LLM Prompt
The system prompt is transparent and overridable. View the default in config.py or customize with --prompt-file.
MCP Host Configuration
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"my-tool": {
"command": "python",
"args": ["path/to/output/my-tool/server.py"]
}
}
}
Cursor IDE
Add to .cursor/mcp.json:
{
"mcpServers": {
"my-tool": {
"command": "python",
"args": ["path/to/output/my-tool/server.py"]
}
}
}
SSE Transport
For HTTP-based MCP hosts:
skill-to-mcp generate SKILL.md --transport sse
cd output/my-tool && python server.py
# MCP endpoint: http://127.0.0.1:8000/sse
Development
Setup
git clone https://github.com/YOUR_USERNAME/skill-to-mcp
cd skill-to-mcp
pip install -e ".[dev]"
Run Tests
# All tests (99 total)
pytest tests/ -v
# End-to-end only
pytest tests/test_e2e.py -v
# With real API (requires DEEPSEEK_API_KEY)
DEEPSEEK_API_KEY="sk-..." skill-to-mcp generate tests/fixtures/simple_skill.md --dry-run
Code Quality
ruff check skill_to_mcp/ tests/
Tech Stack
| Component | Technology |
|---|---|
| CLI Framework | Typer |
| Templates | Jinja2 |
| LLM SDK | OpenAI Python (DeepSeek-compatible) |
| Validation | Pydantic v2 |
| MCP SDK | modelcontextprotocol/python-sdk |
| Output | Rich |
| Testing | pytest + pytest-mock |
| Linting | ruff |
FAQ
Do I need to understand MCP protocol internals?
No. The generated server handles JSON-RPC, tool discovery, and schema validation. You only need to implement handler.py.
What if the LLM produces a wrong schema?
The validator catches type errors, invalid names, and missing fields. Retry is automatic (up to 3 attempts). Use --dry-run to preview before generating.
Can I use OpenAI instead of DeepSeek?
Yes. The CLI automatically falls back to OPENAI_API_KEY if DEEPSEEK_API_KEY is not set.
export OPENAI_API_KEY="sk-..."
skill-to-mcp generate SKILL.md --model gpt-4o-mini
Any OpenAI-compatible endpoint works (OpenAI, DeepSeek, OpenRouter, Together AI, etc.).
What Python version do I need?
Python 3.10+ for the CLI. The generated MCP servers also require Python 3.10+.
Is this production-ready?
This is an MVP (v0.1.0). The generated code is correct and runnable, but you should review and test the generated handler before deploying.
How much does each generation cost?
~$0.001 per generation with DeepSeek V4 Flash. The prompt is ~300 tokens and the response is ~200 tokens.
Is the --with-example-impl handler production-ready?
The LLM-generated handler is a starting point. It may contain bugs (e.g., referencing local variables instead of input.field). Always review and test the generated code before deploying. The prompt has been tuned to minimize common LLM mistakes, but human review is recommended.
Roadmap
-
--with-example-implflag for LLM-generated handler implementations - TypeScript/Go output support
- Batch processing (multiple
SKILL.mdfiles) - Hosted registry at
registry.skill-to-mcp.dev -
skill-to-mcp publishcommand - Smithery integration
- Custom template directories (
--templates-dir)
Contributing
Pull requests are welcome! See project_state.md for current status and next steps.
- Fork the repo
- Create a feature branch (
git checkout -b feature/amazing-feature) - Run tests (
pytest tests/ -v) - Commit your changes
- Push and open a PR
License
MIT — see LICENSE.
Built with ❤️ for MCP developers. If this saved you time, ⭐ the repo!
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 skillmd_to_mcp-0.1.1.tar.gz.
File metadata
- Download URL: skillmd_to_mcp-0.1.1.tar.gz
- Upload date:
- Size: 350.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e80466703895d452585a3b5e4a992b31b79ee750cda074bbb140cc85089c04c
|
|
| MD5 |
ed5f76056c6512fa8af16848b6830d80
|
|
| BLAKE2b-256 |
f708d524de8c97040934eb3350759ea174fbe273885293858bb9b6ec0d6098c4
|
File details
Details for the file skillmd_to_mcp-0.1.1-py3-none-any.whl.
File metadata
- Download URL: skillmd_to_mcp-0.1.1-py3-none-any.whl
- Upload date:
- Size: 32.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
500e5f3b66b9e5fe14e94ec15c86fca9f98f0aa5129a5d0160e87b4ea157e73f
|
|
| MD5 |
223b06cd570e74780980e666cab42875
|
|
| BLAKE2b-256 |
77afde6250c076562522fe95afc3eb79090eb48e45e8b2936a36c01cb65f7f22
|