Skip to main content

Universal converter between CLI (Typer), MCP (FastMCP), and API (FastAPI) interfaces

Project description

intpot

CI PyPI version Python versions License: MIT

Universal converter between CLI (Typer), MCP (FastMCP), and API (FastAPI) interfaces.

intpot bridges three popular Python frameworks:

  • Typer — CLI applications
  • FastMCP — Model Context Protocol servers
  • FastAPI — REST API applications

Given a source file written in any of these frameworks, intpot detects the framework, inspects its functions/tools/endpoints, and generates equivalent code in the target framework.

Features

  • 6 conversion directions — CLI to MCP, CLI to API, MCP to CLI, MCP to API, API to CLI, API to MCP
  • Auto-detection — automatically identifies the source framework by analyzing imports and patterns
  • Project scaffoldingintpot init creates new CLI, MCP, or API projects from templates
  • Jinja2 templates — clean, readable generated code with proper type hints
  • Fully typed — PEP 561 compatible with py.typed marker
  • Zero config — just point at a Python file and specify the target

Installation

pip install intpot            # core (CLI conversions only)
pip install intpot[mcp]       # + FastMCP support
pip install intpot[api]       # + FastAPI support
pip install intpot[all]       # everything

Quick Start

Scaffold a new project

intpot init my-server --type mcp
intpot init my-app --type cli
intpot init my-api --type api

Convert between frameworks

# MCP server -> Typer CLI
intpot to cli server.py

# CLI app -> FastMCP server
intpot to mcp app.py

# CLI app -> FastAPI app
intpot to api app.py

# Write output to a file
intpot to cli server.py --output cli_app.py

# Convert all apps in a directory
intpot to cli ./myproject/
intpot to mcp ./myproject/ --output ./converted/

Python API

Use intpot programmatically from Python:

import intpot

# From a file
app = intpot.load("mcp_server.py")
cli_code = app.to_cli()
api_code = app.to_api()

# From a live instance
from fastmcp import FastMCP

mcp = FastMCP("my-server")

@mcp.tool()
def greet(name: str) -> str:
    return f"Hello, {name}!"

app = intpot.load(mcp)
print(app.to_cli())

# Write directly to a file
app.write("output/cli_app.py", "cli")
app.write("output/api_app.py", "api")

The load() function accepts file paths (str or Path) and live app instances (FastMCP, Typer, FastAPI). The returned IntpotApp object provides:

  • .to_cli(), .to_mcp(), .to_api() — return generated code as strings
  • .write(path, target) — generate and write to a file in one step (target is "cli", "mcp", or "api")

Architecture

intpot uses a four-stage pipeline:

                    +-----------+
                    |  SOURCE   |
                    | (.py file)|
                    +-----+-----+
                          |
                    1. DETECT
                    (identify framework)
                          |
                    +-----v-----+
                    | SourceType|
                    | cli/mcp/api|
                    +-----+-----+
                          |
                    2. INSPECT
                    (extract functions)
                          |
                    +-----v-----+
                    | ToolDef[] |
                    | (normalized|
                    |  schema)  |
                    +-----+-----+
                          |
                    3. GENERATE
                    (render template)
                          |
                    +-----v-----+
                    |  OUTPUT   |
                    | (.py code)|
                    +-----------+
  1. DETECTcore/detector.py imports the source file and identifies whether it's a Typer app, FastMCP server, or FastAPI app
  2. INSPECT — Framework-specific inspectors (core/inspectors/) extract function signatures, parameters, types, defaults, and docstrings into a normalized ToolDef schema
  3. GENERATE — Framework-specific generators (core/generators/) render the normalized schema into target code using Jinja2 templates

Examples

MCP server to CLI app

Input (mcp_server.py):

from fastmcp import FastMCP

mcp = FastMCP("example-server")

@mcp.tool()
def greet(name: str, greeting: str = "Hello") -> str:
    """Greet someone by name."""
    return f"{greeting}, {name}!"

Command: intpot to cli mcp_server.py

Output:

import typer

app = typer.Typer()

@app.command()
def greet(
    name: str = typer.Argument(..., help=""),
    greeting: str = typer.Option('Hello', help=""),
) -> None:
    """Greet someone by name."""
    # TODO: implement
    typer.echo("greet called")

CLI app to FastAPI

Input (cli_app.py):

import typer

app = typer.Typer()

@app.command()
def add(
    a: int = typer.Argument(..., help="First number"),
    b: int = typer.Argument(..., help="Second number"),
) -> None:
    """Add two numbers together."""
    typer.echo(a + b)

Command: intpot to api cli_app.py

Output:

from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()

class AddRequest(BaseModel):
    a: int = Field(..., description="First number")
    b: int = Field(..., description="Second number")

@app.post("/add")
def add(request: AddRequest) -> dict:
    """Add two numbers together."""
    # TODO: implement
    return {"result": "add called"}

API app to MCP server

Input (api_app.py):

from fastapi import FastAPI

app = FastAPI()

@app.post("/greet")
def greet(name: str, greeting: str = "Hello") -> dict:
    """Greet someone by name."""
    return {"message": f"{greeting}, {name}!"}

Command: intpot to mcp api_app.py

Output:

from fastmcp import FastMCP

mcp = FastMCP("generated-server")

@mcp.tool()
def greet(
    name: str,
    greeting: str = 'Hello',
) -> dict:
    """Greet someone by name."""
    # TODO: implement
    return "greet called"

See the examples/ directory for all 6 conversion outputs.

CLI Reference

intpot init

Scaffold a new project from a template.

intpot init <name> --type <mcp|cli|api>
Argument/Option Description
name Project name (creates a directory)
--type, -t Project type: mcp, cli, or api (required)

intpot to cli

Convert an MCP or API source file to a Typer CLI app.

intpot to cli <source> [--output <path>]

intpot to mcp

Convert a CLI or API source file to a FastMCP server.

intpot to mcp <source> [--output <path>]

intpot to api

Convert a CLI or MCP source file to a FastAPI app.

intpot to api <source> [--output <path>]
Argument/Option Description
source Path to a source Python file or directory
--output, -o Output file path (prints to stdout if omitted)

Development

Requires uv.

git clone https://github.com/tugrulguner/intpot.git
cd intpot
uv sync --all-extras
uv run pre-commit install

Run the full check suite:

make check   # lint + typecheck + test

Individual targets:

make lint        # ruff check + format check
make typecheck   # pyright
make test        # pytest
make format      # auto-format code

See CONTRIBUTING.md for more details.

License

MIT

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

intpot-0.2.0.tar.gz (112.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

intpot-0.2.0-py3-none-any.whl (21.7 kB view details)

Uploaded Python 3

File details

Details for the file intpot-0.2.0.tar.gz.

File metadata

  • Download URL: intpot-0.2.0.tar.gz
  • Upload date:
  • Size: 112.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for intpot-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5a79041b093ef1495a18b511bd44eec8418b7ba6382826ec8c2d4d1d3bd954e4
MD5 ca6ecb330bcd310f9787b80ddfa4218d
BLAKE2b-256 84a57054a20d03e9ec6543f53c03e2492546ee7faf31bd833103a8a6e1ed575f

See more details on using hashes here.

Provenance

The following attestation bundles were made for intpot-0.2.0.tar.gz:

Publisher: release.yml on tugrulguner/intpot

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file intpot-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: intpot-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 21.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for intpot-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 23b340ec666a47cf1e2d527d81094f8f5c4ed485777b461061d51e83f3221b1c
MD5 f92e127daf4fc3845823d0b3e7c288ee
BLAKE2b-256 5bb01023885a0f5243c6f3d68b135612d5e33c2c0008ec6edbff9e633c69fb5f

See more details on using hashes here.

Provenance

The following attestation bundles were made for intpot-0.2.0-py3-none-any.whl:

Publisher: release.yml on tugrulguner/intpot

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page