A reusable framework and scaffold for Python CLI applications with MCP, REST, and service-layer architecture
Project description
click-clop
A Python framework and project generator where every feature is simultaneously a CLI command (Click), MCP tool (FastMCP), and REST endpoint (FastAPI).
Write your business logic once as a service class — click-clop exposes it everywhere.
Service method ──► CLI command (Click)
──► MCP tool (FastMCP)
──► REST endpoint (FastAPI)
Quick Start
Install
pip install click-clop
Generate a new project
click-clop new my-app --description "My awesome CLI"
cd my-app
make install-dev
This scaffolds a complete project with a Makefile, Dockerfile, Helm charts, telemetry config, BDD tests, and documentation — with intelligent defaults based on your system.
Write a service
# src/my_app/services/greet.py
from click_clop import Service
class GreetService(Service):
"""Greeting service."""
name = "greet"
description = "Say hello"
def hello(self, name: str = "world") -> str:
"""Say hello to someone."""
return f"Hello, {name}!"
def farewell(self, name: str = "world") -> str:
"""Say goodbye to someone."""
return f"Goodbye, {name}!"
_service = GreetService() # auto-registers
Expose as CLI
import click
from click_clop import expose_cli
@click.group()
def main():
"""My CLI app."""
expose_cli(main) # all registered services become subcommands
$ my-app greet hello --name Claude
Hello, Claude!
Expose as REST
from click_clop import expose_rest
app = expose_rest() # creates /api/greet/hello, /api/greet/farewell
Expose as MCP tools
from fastmcp import FastMCP
from click_clop import expose_mcp
mcp = FastMCP("my-service")
expose_mcp(mcp) # registers greet_hello, greet_farewell tools
CLI
click-clop new <PROJECT_NAME> Create a new project from template
-d, --description TEXT Project description
-a, --author TEXT Author name (auto-detected from git)
-o, --output-dir PATH Parent directory (default: cwd)
click-clop detect Show detected system capabilities
Library API
from click_clop import (
Service, # Base class for services
ServiceRegistry, # Global registry of all services
load_config, # Load TOML config with env overrides
expose_cli, # Add services to a Click group
expose_mcp, # Add services as MCP tools
expose_rest, # Add services as FastAPI endpoints
)
Configuration
load_config() merges TOML files in order (later wins):
config.toml— base defaultsconfig.dev.toml— development overridesconfig.local.toml— local/gitignored overrides- Environment variables with prefix
from click_clop import load_config
config = load_config(prefix="APP")
Environment variables map with double-underscore nesting:
APP_SERVER__HOST=0.0.0.0 → config["server"]["host"]
APP_DATABASE__PORT=5432 → config["database"]["port"]
Secrets (1Password)
from click_clop.secrets import get_secret_field, ensure_secret
# Read a secret
api_key = get_secret_field("vault-name", "item-name", "api_key")
# Create or update a secret
ensure_secret("vault-name", "item-name", {"api_key": "sk-..."})
Requires the 1Password CLI (op) installed and authenticated.
Telemetry (OpenTelemetry)
from click_clop.telemetry import setup_telemetry, get_tracer
setup_telemetry(service_name="my-service", otlp_endpoint="http://localhost:4317")
tracer = get_tracer("my_module")
with tracer.start_as_current_span("operation"):
...
Logging (structlog)
from click_clop.logging import setup_logging, get_logger
setup_logging(level="INFO", json_output=True, service_name="my-service")
log = get_logger("my_module")
log.info("event", key="value")
System Detection
from click_clop.system_detect import detect_system
info = detect_system()
print(info.summary())
Detects Docker/Podman, Helm, 1Password CLI, Python, uv, Git, OS, and architecture.
Generated Project Structure
my_app/
├── src/my_app/
│ ├── __main__.py # Entry point
│ ├── cli.py # CLI main group
│ ├── server.py # MCP + REST server
│ └── services/
│ └── hello.py # Example service
├── tests/
│ └── unit/
│ └── test_hello.py
├── features/ # BDD/Gherkin tests
├── helm/my_app/ # Kubernetes Helm charts
├── alloy/config.alloy # Grafana Alloy telemetry config
├── docs/ # Sphinx documentation
├── config.toml # Application config
├── Makefile # Development tasks
├── Dockerfile
└── pyproject.toml
Generated project commands
make install-dev # Install with dev dependencies
make test # Run pytest
make test-bdd # Run BDD tests
make lint # Lint with ruff + mypy
make format # Format with ruff
make serve # Run REST + MCP server (Swagger at localhost:8000/docs)
make build-image # Build container image
make helm-install # Deploy via Helm
make docs # Build Sphinx docs
Development
git clone https://github.com/bpayne/click-clop.git
cd click-clop
make install-dev
make test
make lint
Type Mapping
Service method parameters are automatically mapped:
| Python type | CLI (Click) | REST (FastAPI) |
|---|---|---|
str |
STRING |
str |
int |
INT |
int |
float |
FLOAT |
float |
bool |
--flag/--no-flag |
bool |
Parameters without type annotations default to str.
License
MIT
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 click_clop-0.3.0.tar.gz.
File metadata
- Download URL: click_clop-0.3.0.tar.gz
- Upload date:
- Size: 92.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d933d04f8f343fe67fc354fa95f1bdfbbf6986654e6dd6e47c6b79f45816913c
|
|
| MD5 |
31c3bfc7e36eacd7a6e6fea0a963393c
|
|
| BLAKE2b-256 |
a0b58f9fe528653bf75efcfeb94ac963b90c53bd2bf7a60408a5454ae70387f4
|
File details
Details for the file click_clop-0.3.0-py3-none-any.whl.
File metadata
- Download URL: click_clop-0.3.0-py3-none-any.whl
- Upload date:
- Size: 39.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6573a30db974f1afdde3b30ae2dd4d8c8cbf56a4fcbdb9295a4242d7d854e74
|
|
| MD5 |
b3c6c830955b3489920707ef54d3f94c
|
|
| BLAKE2b-256 |
e5b4f1f5b95299013de9c8dd7df418fd3d4d6540973b82b20c912035a96ffb6d
|