foro (Python)
The Python SDK and CLI for foro.sh — the fastest path from
"I want to build an MCP server" to a deployed https://<slug>.foro.sh URL.
Quickstart
uvx foro init my-server && cd my-server
uvx foro dev
foro init scaffolds a working FastMCP server plus
a foro.yaml; foro dev runs it exactly as foro.sh will and confirms it
would pass the platform's health check. Once it looks good:
git init && git add -A && git commit -m "init" && gh repo create --push
Then, on the foro.sh dashboard: sign in with GitHub, pick the repo, add any secrets your tools need, and deploy.
CLI
Install once with uv tool install foro, or run ad-hoc with
uvx foro ... — no need to add it to your project's own dependencies.
| Command | What it does |
|---|---|
foro init [name] |
Scaffold a new project, or add foro.yaml to an existing one (run with no argument) |
foro check [path] |
Validate a repo against foro.sh's deploy contract before you push |
foro dev [path] |
Run the server locally exactly as foro.sh will, and confirm it would pass the health check |
foro check mirrors the platform's own validation rule for rule, so a repo
it passes will deploy and one it flags will not — the same reason code,
surfaced locally instead of as a 60-second health-check timeout.
Runtime
One import, used from your server's entrypoint:
from fastmcp import FastMCP
import foro
mcp = FastMCP("my-server")
@mcp.tool
def add(a: int, b: int) -> int:
return a + b
if __name__ == "__main__":
foro.run(mcp) # streamable HTTP, host 0.0.0.0, port $MCP_PORT - identical locally and deployed
| Function | What it does |
|---|---|
foro.run(server, *, port=None) |
The one correct way to start a server for foro.sh. Accepts any FastMCP-shaped server (standalone fastmcp.FastMCP, mcp.server.fastmcp.FastMCP, or a low-level Server) — it's duck-typed, not tied to a specific class. |
foro.secret(name) |
Read a required secret from the environment, raising a dashboard-actionable error if it's missing. Set secrets in your project's Secrets tab on the dashboard; they arrive as env vars at deploy time. |
Bare foro (what a deployed container installs — no [cli] extra) stays
dependency-free, so a deployed container never pulls in CLI tooling it
doesn't use.
foro.yaml reference
Every deployable repo carries one, at its root:
name: my-server # required, ^[a-z0-9-]{3,48}$ - display name only, not the URL slug
entrypoint: server.py # required, relative path, run as `uv run <entrypoint>`
build_path: . # optional, default "." - dir holding pyproject.toml + uv.lock
python_version: "3.12" # optional, one of 3.11 / 3.12 / 3.13
port: 8000 # optional, default 8000 - the port your server must listen on
At runtime the container gets MCP_PORT (matching port above) and every
project secret as its own env var. Public traffic arrives at
https://<slug>.foro.sh, so your server must listen on 0.0.0.0:$MCP_PORT —
which is exactly what foro.run() does for you.
Example
foro-sh/todo-mcp is a small stateful
todo-list server built the way described above — every new foro.sh workspace
gets a deployed copy of it to poke at before deploying anything of your own.
Develop this package
uv sync
uv run pytest
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 foro-0.2.1.tar.gz.
File metadata
- Download URL: foro-0.2.1.tar.gz
- Upload date:
- Size: 318.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f1092e7af2cddc3ded418883ce39c28aa93675c6cdf3c020d52ff0405b9f59f
|
|
| MD5 |
9b7bc2c859ad8fc83287dc760d28da26
|
|
| BLAKE2b-256 |
4cd3ee5b91384dab6c9ba06fa61908588604e6700dcd34425f47a5ae5ea53a7c
|
Provenance
The following attestation bundles were made for foro-0.2.1.tar.gz:
Publisher:
semantic-release.yml on foro-sh/foro
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
foro-0.2.1.tar.gz -
Subject digest:
3f1092e7af2cddc3ded418883ce39c28aa93675c6cdf3c020d52ff0405b9f59f - Sigstore transparency entry: 2281118638
- Sigstore integration time:
-
Permalink:
foro-sh/foro@4cb45e1804c9860ff2643ad519c8b28b0f6a2608 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/foro-sh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
semantic-release.yml@4cb45e1804c9860ff2643ad519c8b28b0f6a2608 -
Trigger Event:
push
-
Statement type:
File details
Details for the file foro-0.2.1-py3-none-any.whl.
File metadata
- Download URL: foro-0.2.1-py3-none-any.whl
- Upload date:
- Size: 18.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7be924894e562ea8b3666f9447b8c9bb5812410b99186a121f3bf2b050d2137f
|
|
| MD5 |
d59072b7c46c63b28b5e161496f2076f
|
|
| BLAKE2b-256 |
453f223a9324b3615030a0501b8c7b4bf21d607e721b44be661bbd93ce448214
|
Provenance
The following attestation bundles were made for foro-0.2.1-py3-none-any.whl:
Publisher:
semantic-release.yml on foro-sh/foro
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
foro-0.2.1-py3-none-any.whl -
Subject digest:
7be924894e562ea8b3666f9447b8c9bb5812410b99186a121f3bf2b050d2137f - Sigstore transparency entry: 2281118654
- Sigstore integration time:
-
Permalink:
foro-sh/foro@4cb45e1804c9860ff2643ad519c8b28b0f6a2608 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/foro-sh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
semantic-release.yml@4cb45e1804c9860ff2643ad519c8b28b0f6a2608 -
Trigger Event:
push
-
Statement type: