Starter CLI for generating MCP wrappers around existing command-line tools.
Project description
MCP Templates
Production-style starter templates for turning existing CLIs into MCP servers quickly, safely, and with minimal deployment friction.
If you already have a useful command-line tool, script, or internal binary, this repo helps you expose it to MCP clients without rewriting the tool from scratch.
The path is intentionally simple:
existing CLI -> generated MCP wrapper -> validation -> client config -> working tool
Who This Is For
This repo is built for:
- platform teams exposing internal tools to MCP clients
- developers with a working CLI who want MCP support fast
- AI enablement teams that need safe, debuggable tool wrappers
- consultants or builders packaging an existing workflow for Claude Desktop, Claude Code, or similar clients
If MCP is new to you, start with docs/MCP_PRIMER.md.
Positioning
Most MCP examples prove that a server can run. This repo is aimed at the harder problem: getting a real internal tool wrapped, validated, and ready to ship without rebuilding it from scratch.
The core bet is simple:
- reuse the CLI you already have
- add safety guardrails by default
- keep the server transport/client agnostic
- make local setup and deployment boring
Why This Is Different
- Safer than toy examples: templates start with path allowlists, timeout handling, arg validation, and structured JSON output.
- Faster than framework-heavy rewrites: wrap an existing binary instead of reimplementing business logic in a new server stack.
- More portable than client-specific setups: the same server can be registered in Claude Desktop, Claude Code, and other MCP clients.
- Closer to production: examples are designed around real subprocess execution, explicit env configuration, and predictable failure modes.
Why This Beats Existing Options
For the right audience, this is better than most existing MCP starter options because it optimizes for migration, not greenfield demos.
- Most examples show how to build an MCP server from scratch. This helps you keep the CLI you already trust.
- Many wrappers stop at "it runs." This repo includes validation, generated configs, CI smoke tests, and packaging paths.
- Client-specific examples often trap you in one setup. This stays transport- and client-agnostic.
- Framework-heavy approaches can force a rewrite too early. This keeps the MCP layer thin until the workflow proves valuable.
If someone already has a working CLI, the comparison should not be "template versus template." It should be:
rewrite the tool vs wrap the tool safely and ship sooner
What You Get In Practice
With the current Python template, you can:
- generate a project-specific MCP wrapper with renamed placeholders
- point it at a real binary instead of a toy example
- get project-specific sample client config files during bootstrap, already pointed at the generated
mcp_server.py - get a starter
.gitignorein the copied wrapper - keep the main MCP file visually obvious as
mcp_server.py - move secondary tooling into
support/ - get a generated
.env.examplewith the renamed runtime variables, and auto-load.envif present - get a generated
START_HERE.mdwith first-run steps for the copied wrapper - validate setup with
doctor.pybefore opening a client - validate setup with
doctor.pybefore opening a client, including machine-readable--jsonoutput for CI or setup tooling - use a real
mcp-templatecommand from the repo root instead of calling an internal script path - package it with Docker
- verify the template itself in CI with bootstrap, syntax, and smoke checks
30-Second Quickstart
If you already have a CLI, the basic flow is:
./mcp-template generate /path/to/your-project/mcp \
--server-name your-project \
--tool-name run_profile \
--binary-name your-cli
Repeat --tool-name if your CLI needs more than one MCP tool stub:
mcp-template generate /path/to/your-project/mcp \
--server-name factorlens \
--tool-name analyze_csv \
--tool-name analyze_compare \
--tool-name explain_analyze
If a generated function name should map to a different CLI subcommand, opt in explicitly:
mcp-template generate /path/to/your-project/mcp \
--server-name factorlens \
--tool-name analyze_compare \
--tool-subcommand analyze_compare=analyze-compare
If the real CLI already has useful --help output, you can ask the generator to infer richer starter signatures from it:
mcp-template generate /path/to/your-project/mcp \
--server-name factorlens \
--tool-name explain_analyze \
--tool-subcommand explain_analyze=explain-analyze \
--binary-name factorlens \
--bin-path /abs/path/to/factorlens \
--infer-tools-from-help
If you want a different env namespace than the server slug, add:
--env-prefix YOUR_TEAM_TOOL
If you want to preview the generated output first, add:
--dry-run
If you already know the real executable path, add:
--bin-path /abs/path/to/your-cli
If you want the generated client config to use a specific Python interpreter, add:
--python-path /abs/path/to/python
If you want to prefill allowed directories too, add:
--read-dirs /abs/path/to/data,/abs/path/to/profiles \
--write-dirs /abs/path/to/artifacts
Then:
- replace the placeholder command mapping in
mcp_server.py - replace the stub binary in
support/bin/ - fill in
.env.example - read
START_HERE.md - adapt one of the generated sample configs in
examples/ - run
support/doctor.py - call
versionandpaths - validate with
healthcheck
Install Options
Use one of these depending on how you want to adopt the tool:
- From a clone right now:
./mcp-template generate ... - Local pip install from a clone:
python -m pip install . - Local isolated install from a clone:
pipx install .
After the package is published, the intended install command is:
pipx install mcp-template
Then the command stays the same everywhere:
mcp-template generate /path/to/your-project/mcp --server-name your-project
How It Fits Together
flowchart LR
A["Existing CLI or binary"] --> B["Generated MCP wrapper"]
B --> C["support/doctor.py validation"]
B --> D["Claude Desktop / Claude Code / other MCP client"]
D --> B
B --> E["Allowed read/write dirs"]
B --> F["Structured JSON results"]
Included
python-cli-template/: production-style Python MCP wrapper for any CLI toolpython-cli-template/bin/project-cli: stub binary used only for template smoke testingpython-cli-template/doctor.py: preflight checker for Python, env vars, paths, and client config JSONpython-cli-template/Dockerfile: minimal container target for packaging the Python templatemcp-template: repo-local launcher for the public CLIsrc/mcp_template_cli/: installablemcp-templateCLI packagescripts/init_python_cli_template.py: compatibility shim for the public CLI.github/workflows/python-template-smoke.yml: CI smoke test for syntax, preflight validation, and container buildexamples/claude_desktop_config.sample.json: local Claude Desktop config exampleexamples/claude_code_mcp.sample.json: generic Claude Code-style config exampledocs/QUICKSTART.md: 10-minute setup flowdocs/MCP_PRIMER.md: short explanation of what MCP is and why this repo existsdocs/EXAMPLE_ADAPTER.md: concrete walkthrough for wrapping a real CLI commanddocs/LAUNCH_CHECKLIST.md: rollout checklist for validating a wrapper before production use
How To Use
- Run the repo-local generator with
./mcp-template generate. - Generate a project-specific copy.
- Replace the stub binary and adjust the command mapping.
- Adapt one of the generated sample configs in
examples/for your client. - Set env vars (
*_BIN, allowed read/write dirs). - Run
support/doctor.pyto catch binary, Python, path, and config issues early. - Register server in your MCP client config.
- Test with
version,paths, andhealthcheckfirst.
Best Fit
This repo is a strong fit when you already have:
- a working CLI or script that solves the real problem
- a need to expose it to an MCP client without a full rewrite
- requirements around file access boundaries, predictable execution, and debuggable failures
It is less useful if you want a full hosted platform, a managed registry, or opinionated cloud infrastructure out of the box.
When Not To Use This
This repo is probably the wrong fit if:
- you need a hosted control plane, not a local or self-managed MCP server
- you do not already have a working CLI, script, or binary to wrap
- you want a full product UI before you have validated the tool workflow
- your use case requires broad unrestricted filesystem access with minimal guardrails
In those cases, a different architecture may be a better starting point than a thin wrapper around an existing command.
Quick Example
If you already have something like:
inventory-cli run --input profiles/acme.toml --out artifacts/report.json
you can use this repo to generate an MCP wrapper, map that command shape in mcp_server.py, lock access to the right directories, and expose it to an MCP client with a minimal config entry.
That is the core use case: keep the real tool, add a thin MCP layer, and make the setup repeatable.
For a more concrete walkthrough, see docs/EXAMPLE_ADAPTER.md.
Before rollout, use docs/LAUNCH_CHECKLIST.md.
Design Principles
- strict arg validation
- path allowlists
- no
shell=True - subprocess timeout
- structured JSON responses
Notes
- Template is transport/runner-agnostic: same server can be used by Claude Desktop, Claude Code, and other MCP clients.
- Each client still needs its own config entry pointing to the server command.
- The included Dockerfile is intentionally minimal: you still need to copy your real CLI into the image and set
PROJECT_BIN. - The smoke-test workflow uses a stub CLI so the template can be validated in CI without your real binary.
- The repo now includes package metadata and bundled template assets so
mcp-templatecan be distributed as a pip package, not only used from source.
FAQ
Do I need a desktop app for this?
No. The template is designed to stay headless and MCP-focused. A desktop app could be a future companion for setup or demos, but it is not required to use the template.
Can this wrap a compiled binary instead of a Python tool?
Yes. The template wraps a command-line executable through subprocess calls. Your real tool can be a Python CLI, shell-backed binary, Rust binary, Go binary, or another executable, as long as you map the command shape correctly.
Why not just build a custom MCP server from scratch?
If you already trust the CLI, a thin wrapper is usually faster to ship, easier to debug, and less likely to create a second implementation that drifts from the original tool.
CI Coverage
The starter workflow currently verifies the template in three layers:
- bootstrap generation rewrites the template as expected
- Python files compile cleanly
doctor.pypasses in a normal runner environment- the Docker image builds and can run
doctor.pyinside the container
Near-Term Roadmap
To make this easier to deploy than other MCP starter options, the next high-value additions are:
- example hosting configs for common runtimes
- more reference adapters for common CLI patterns so users copy less and customize less
Project details
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_template-0.2.0.tar.gz.
File metadata
- Download URL: mcp_template-0.2.0.tar.gz
- Upload date:
- Size: 21.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98b7c222b77ec8ef6facb676cece979d989bdb973d27c4f5e3adad7b15792208
|
|
| MD5 |
e63a4db6ba15909e5b5f4952686b8960
|
|
| BLAKE2b-256 |
82c3f665b79458b8365541c6515968ead829562bd086767920dff1fd1446893e
|
Provenance
The following attestation bundles were made for mcp_template-0.2.0.tar.gz:
Publisher:
release.yml on kraftaa/mcp-templates
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_template-0.2.0.tar.gz -
Subject digest:
98b7c222b77ec8ef6facb676cece979d989bdb973d27c4f5e3adad7b15792208 - Sigstore transparency entry: 1096829512
- Sigstore integration time:
-
Permalink:
kraftaa/mcp-templates@37c9ec87241571e03fed23f3dfeb4776567bd0a8 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/kraftaa
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@37c9ec87241571e03fed23f3dfeb4776567bd0a8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mcp_template-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mcp_template-0.2.0-py3-none-any.whl
- Upload date:
- Size: 20.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f074da5824d50bee73591009df08af92d13fad45901367909505df29d8fc7b32
|
|
| MD5 |
45eef8718df5c60cc05abbf31f195d8c
|
|
| BLAKE2b-256 |
87e3be92873bf9c95f89eb33a86f5d485f6e204770e36e57f77dc778fea02231
|
Provenance
The following attestation bundles were made for mcp_template-0.2.0-py3-none-any.whl:
Publisher:
release.yml on kraftaa/mcp-templates
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_template-0.2.0-py3-none-any.whl -
Subject digest:
f074da5824d50bee73591009df08af92d13fad45901367909505df29d8fc7b32 - Sigstore transparency entry: 1096829513
- Sigstore integration time:
-
Permalink:
kraftaa/mcp-templates@37c9ec87241571e03fed23f3dfeb4776567bd0a8 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/kraftaa
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@37c9ec87241571e03fed23f3dfeb4776567bd0a8 -
Trigger Event:
push
-
Statement type: