Agent skill
fastapi-sweetener
Add FastAPI server capabilities to an existing Python project with uvicorn, OpenAPI docs, and configuration management
Install this agent skill to your Project
npx add-skill https://github.com/pborenstein/plinth/tree/main/skills/fastapi-sweetener
SKILL.md
FastAPI Sweetener Skill
Add FastAPI server capabilities to an existing Python project, integrating as a CLI subcommand alongside existing functionality.
Prerequisites
This skill assumes you already have a Python project (typically created with /plinth:python-project-init) with:
- Existing
pyproject.toml - Package directory with
__init__.py - Existing CLI (typically
cli.py)
What This Skill Adds
Adds FastAPI server capabilities to your existing project:
- FastAPI server with OpenAPI docs (/docs, /redoc)
- CLI subcommand -
{package} serverto start the API - Configuration management (JSON/YAML config files)
- CORS middleware for web clients
- Lifespan management for startup/shutdown
- Dependencies - adds fastapi, uvicorn, click to pyproject.toml
Files Added/Modified
New files:
{package}/server.py- FastAPI application{package}/config.py- Configuration managementconfig.example.json- Example configuration.env.example- Environment variable template
Modified files:
{package}/cli.py- Addsserversubcommand (converts to Click if needed)pyproject.toml- Adds dependencies (fastapi, uvicorn, click, pyyaml)
Implementation Steps
Step 1: Detect Project Structure
Use Glob and Read to discover:
- Find
pyproject.tomlin current directory - Extract
project.nameand package name from pyproject.toml - Locate package directory (usually
{package}/orsrc/{package}/) - Find existing CLI file (usually
cli.py) - Read
__init__.pyor__version__.pyto get description
If unable to detect structure, ask user for:
- PACKAGE_NAME
- PROJECT_NAME
Step 2: Check for Existing Server
Check if server already exists:
ls {package}/server.py
If it exists, ask user if they want to overwrite it.
Step 3: Gather Configuration
Ask user for (use AskUserQuestion if needed):
Optional parameters (with defaults):
-
SERVER_HOST (string) - Default: "0.0.0.0"
- Host to bind server to
-
SERVER_PORT (integer) - Default: 8000
- Port to bind server to
Step 4: Add Server Files
Create the following files from templates in skills/fastapi-sweetener/assets/:
{package}/server.py - FastAPI application:
- Read
assets/server.py.template - Replace template variables
- Write to
{package}/server.py
{package}/config.py - Configuration management:
- Read
assets/config.py.template - Replace template variables
- Write to
{package}/config.py
config.example.json - Example config:
- Read
assets/config.example.json.template - Replace SERVER_HOST and SERVER_PORT
- Write to project root
config.example.json
.env.example - Environment template:
- Read
assets/.env.example.template - Write to project root
.env.example
Step 5: Update CLI to Add Server Subcommand
This is the most critical step. The CLI needs to support subcommands.
If cli.py uses Click:
Add a new @main.command() for the server:
@main.command()
@click.option('--host', default=None, help='Server host (default: from config)')
@click.option('--port', default=None, type=int, help='Server port (default: from config)')
@click.option('--reload', is_flag=True, help='Enable auto-reload for development')
@click.option('--log-level', default='info',
type=click.Choice(['critical', 'error', 'warning', 'info', 'debug']),
help='Logging level')
def server(host, port, reload, log_level):
"""Start the FastAPI server.
This starts the HTTP server that provides the API.
The server will be accessible via http://HOST:PORT
"""
import uvicorn
from .config import Config
config = Config()
# Override config with CLI options if provided
server_host = host or config.server_host
server_port = port or config.server_port
print(f"Starting server at http://{server_host}:{server_port}")
print(f"OpenAPI docs: http://{server_host}:{server_port}/docs")
uvicorn.run(
"{{PACKAGE_NAME}}.server:app",
host=server_host,
port=server_port,
reload=reload,
log_level=log_level
)
If cli.py uses argparse:
Convert to Click. This is a significant change but necessary for subcommands:
- Read existing
cli.py - Identify the main() function
- Rewrite to use Click groups:
- Convert
ArgumentParser()to@click.group() - Convert existing logic to
@main.command()named appropriately - Add the
serversubcommand as shown above
- Convert
- Use Edit tool to update the file
Step 6: Update pyproject.toml Dependencies
Add required dependencies to pyproject.toml:
Use Edit tool to add to the dependencies array:
dependencies = [
# ... existing deps ...
"fastapi>=0.104.0",
"uvicorn[standard]>=0.24.0",
"click>=8.0",
"pyyaml>=6.0",
]
Step 7: Install Dependencies
Run uv sync to install new dependencies:
uv sync
Step 8: Create Config File
Guide user to create config from example:
cp config.example.json config.json
Step 9: Verification & Next Steps
Provide verification commands:
# Verify CLI still works
uv run {package} --version
# Start development server
uv run {package} server --reload
# Open in browser
open http://localhost:{port}/docs
Tell user:
- Server added as
{package} serversubcommand - Configure via
config.json(copy from config.example.json) - Add API endpoints to
{package}/server.py - OpenAPI docs available at
/docsand/redoc - Use
/plinth:macos-launchd-serviceto set up auto-start
Template Variable Reference
| Variable | Example | Source |
|---|---|---|
{{PROJECT_NAME}} |
"Temoa" | From pyproject.toml or user input |
{{PACKAGE_NAME}} |
"temoa" | Detected from directory structure |
{{PACKAGE_NAME_UPPER}} |
"TEMOA" | Derived from PACKAGE_NAME |
{{DESCRIPTION}} |
"Semantic search" | From init.py or user input |
{{SERVER_HOST}} |
"0.0.0.0" | User input or default |
{{SERVER_PORT}} |
"8000" | User input or default |
Example Execution
User request: "Add FastAPI to my CLI project"
Detected:
- PROJECT_NAME: "MyProject" (from pyproject.toml)
- PACKAGE_NAME: "myproject" (from directory structure)
- Existing cli.py with Click
User provides:
- SERVER_PORT: 8080 (default: 8000)
Result:
Files added:
myproject/server.pymyproject/config.pyconfig.example.json.env.example
Files modified:
myproject/cli.py(addedservercommand)pyproject.toml(added fastapi, uvicorn, etc.)
Usage:
myproject --help # Shows all subcommands
myproject server # Starts FastAPI on port 8080
myproject server --reload # Development mode with auto-reload
Idempotency
The skill should be safe to run multiple times:
- Check if
server.pyexists before creating - Ask user before overwriting existing files
- Only add dependencies if not already present
- Don't duplicate CLI commands
Common Issues
CLI Not Using Click
If the existing CLI uses argparse, the skill will convert it to Click. This is necessary for subcommands. The conversion:
- Preserves existing CLI functionality
- Moves it to a default command or appropriately named subcommand
- Adds the
serversubcommand
Warn the user about this change.
Port Already in Use
If the default port is occupied, user can override:
myproject server --port 8001
Missing Config File
Server requires config.json. If missing:
cp config.example.json config.json
Edit values as needed.
What NOT to Do
- Don't create this from scratch - requires existing project
- Don't skip the CLI conversion if needed - subcommands require Click
- Don't overwrite server.py without asking
- Don't add emojis to any files
- Don't run python directly - always use
uv run - Don't modify README.md or documentation files (user does this)
Post-Addition Customization
After adding FastAPI, users typically:
- Edit
config.jsonwith their specific configuration - Add API endpoints to
server.py - Update tests to include API endpoint tests
- Set up launchd service using
/plinth:macos-launchd-service - Document API endpoints in README.md
Integration with Other Skills
Works well with:
/plinth:python-project-init- Creates the base project first/plinth:macos-launchd-service- Auto-start the server/plinth:session-wrapup- Document the addition
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
python-project-init
Initialize complete Python project with comprehensive documentation, development environment, and tooling. Use when creating a new Python project from scratch.
macos-launchd-service
Set up macOS launchd service for auto-starting Python applications
releaserator
Generate semantic versioned releases with changelog and GitHub releases
git-workflow-hooks
Install git hooks to prevent common workflow mistakes
edit-article
Edit and improve articles by restructuring sections, improving clarity, and tightening prose. Use when user wants to edit, revise, or improve an article draft.
handoff
Compact the current conversation into a handoff document for another agent to pick up.
Didn't find tool you were looking for?