# 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`](/Users/maria/Documents/GitHub/extra/mcp-templates/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 `.gitignore` in the copied wrapper
- keep the main MCP file visually obvious as `mcp_server.py`
- move secondary tooling into `support/`
- get a generated `.env.example` with the renamed runtime variables, and auto-load `.env` if present
- get a generated `START_HERE.md` with first-run steps for the copied wrapper
- validate setup with `doctor.py` before opening a client
- validate setup with `doctor.py` before opening a client, including machine-readable `--json` output for CI or setup tooling
- use a real `mcp-template` command from the repo root instead of calling an internal script path
- scaffold a repeatable `deploy/` folder for Docker packaging
- 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:

```bash
./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:

```bash
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:

```bash
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:

```bash
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
```

Safe first try on any CLI:

```bash
mcp-template generate /path/to/output \
  --server-name my-tool \
  --tool-name run_task \
  --binary-name my-cli \
  --bin-path /abs/path/to/my-cli \
  --dry-run
```

If you want a different env namespace than the server slug, add:

```bash
--env-prefix YOUR_TEAM_TOOL
```

If you want to preview the generated output first, add:

```bash
--dry-run
```

If you already know the real executable path, add:

```bash
--bin-path /abs/path/to/your-cli
```

If you want the generated client config to use a specific Python interpreter, add:

```bash
--python-path /abs/path/to/python
```

If you want to prefill allowed directories too, add:

```bash
--read-dirs /abs/path/to/data,/abs/path/to/profiles \
--write-dirs /abs/path/to/artifacts
```

Then:

1. replace the placeholder command mapping in `mcp_server.py`
2. replace the stub binary in `support/bin/`
3. fill in `.env.example`
4. read `START_HERE.md`
5. adapt one of the generated sample configs in `examples/`
6. run `support/doctor.py`
7. call `version` and `paths`
8. validate with `healthcheck`

If you want a container packaging path after the wrapper itself works locally:

```bash
mcp-template package docker /path/to/your-project/mcp
```

That creates a `deploy/` folder with:

- `docker-compose.yml`
- `docker.env.example`
- starter `runtime/` directories for data, profiles, and artifacts

If `deploy/` already exists, the command now refuses to overwrite it unless you pass `--force`.
If your wrapper ships more than one executable under `support/bin/`, pass `--binary-name your-cli` to choose which one the container should treat as the runtime binary.

## 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:

```bash
pipx install mcp-template
```

If `mcp-template` is not found right after install, run:

```bash
pipx ensurepath
```

Then restart your shell or reload `~/.zshrc`.

Then the command stays the same everywhere:

```bash
mcp-template generate /path/to/your-project/mcp --server-name your-project
```

## How It Fits Together

```mermaid
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 tool
- `python-cli-template/bin/project-cli`: stub binary used only for template smoke testing
- `python-cli-template/doctor.py`: preflight checker for Python, env vars, paths, and client config JSON
- `python-cli-template/Dockerfile`: minimal container target for packaging the Python template
- `mcp-template`: repo-local launcher for the public CLI
- `src/mcp_template_cli/`: installable `mcp-template` CLI package
- `scripts/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 build
- `examples/claude_desktop_config.sample.json`: local Claude Desktop config example
- `examples/claude_code_mcp.sample.json`: generic Claude Code-style config example
- `docs/QUICKSTART.md`: 10-minute setup flow
- `docs/MCP_PRIMER.md`: short explanation of what MCP is and why this repo exists
- `docs/EXAMPLE_ADAPTER.md`: concrete walkthrough for wrapping a real CLI command
- `docs/LAUNCH_CHECKLIST.md`: rollout checklist for validating a wrapper before production use

## How To Use

1. Run the repo-local generator with `./mcp-template generate`.
2. Generate a project-specific copy.
3. Replace the stub binary and adjust the command mapping.
4. Adapt one of the generated sample configs in `examples/` for your client.
5. Set env vars (`*_BIN`, allowed read/write dirs).
6. Run `support/doctor.py` to catch binary, Python, path, and config issues early.
7. Register server in your MCP client config.
8. Test with `version`, `paths`, and `healthcheck` first.

## 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`](/Users/maria/Documents/GitHub/extra/mcp-templates/docs/EXAMPLE_ADAPTER.md).
Before rollout, use [`docs/LAUNCH_CHECKLIST.md`](/Users/maria/Documents/GitHub/extra/mcp-templates/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, and `mcp-template package docker` scaffolds a `deploy/` folder around it for a repeatable container path.
- 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-template` can 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.py` passes in a normal runner environment
- the Docker image builds and can run `doctor.py` inside 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
