RunR v0.5.7

Documentation

MCP server starter — Python

server.py is a Model Context Protocol server on the official MCP Python SDK (FastMCP): Streamable HTTP at /mcp on $PORT, stateless, behind the RunR MCP gateway (docs/mcp.md).

File
runtime.yaml the mcp-python runtime: image ghcr.io/brf-tech/runr/reqs/python:3.13-slim, dependencies from requirements.txt into /app/vendor, run.command python -u /app/code/server.py (http mode), starter template server.py
server.py tools hello, add, whoami, resource starter://about, prompt greet; GatewaySignature checks X-RunR-Signature
requirements.txt mcp, uvicorn
Dockerfile the same server as an image for a CaaS project

Deploy on RunR#

Projects → New MCP server → Python. RunR creates a FaaS project on mcp-python with these files; the first save builds the dependencies into the version's image. Deploy it, then connect:

claude mcp add --transport http my-server https://runr.example.com/mcp/servers/<project slug>

Keep requirements.txt in the project: without the dependency file the version is not built and the image has no MCP SDK.

Add a tool#

@mcp.tool()
def forecast(city: str, days: int = 3) -> dict:
    """Weather forecast for a city."""
    return {"city": city, "days": days, "summary": "sunny"}

Save (a new version), deploy, and the tool shows up in tools/list. Tools that need the caller take ctx: Context and read identity_of(ctx):

@mcp.tool()
def my_projects(ctx: Context) -> str:
    identity = identity_of(ctx) or {}
    user = (identity.get("user") or {}).get("name", "anonymous")
    return f"Hello {user}, authenticated by {identity.get('auth')}"

Run locally#

python -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
PORT=8080 python server.py
npx @modelcontextprotocol/inspector   # connect to http://localhost:8080/mcp (Streamable HTTP)

Without RUNR_MCP_GATEWAY_KEY the server accepts unsigned requests. To try the check locally, set a key and sign a request the way the gateway does:

export RUNR_MCP_GATEWAY_KEY=local-test-key
PORT=8080 python server.py &
python - <<'EOF'
import base64, hashlib, hmac, json, os, time, urllib.request
key = os.environ["RUNR_MCP_GATEWAY_KEY"]
body = json.dumps({"jsonrpc": "2.0", "id": 1, "method": "tools/list"}).encode()
identity = base64.urlsafe_b64encode(json.dumps({"auth": "token", "user": {"id": "1", "name": "Ada"}}).encode()).decode().rstrip("=")
t = int(time.time())
signed = f"{t}.POST\n/mcp\n{hashlib.sha256(body).hexdigest()}\n{identity}".encode()
sig = hmac.new(key.encode(), signed, hashlib.sha256).hexdigest()
req = urllib.request.Request("http://localhost:8080/mcp", data=body, method="POST", headers={
    "Content-Type": "application/json", "Accept": "application/json, text/event-stream",
    "X-RunR-Identity": identity, "X-RunR-Signature": f"t={t},v1={sig}"})
print(urllib.request.urlopen(req).read().decode())
EOF

As your own image#

docker build -t registry.example.com/acme/mcp-python:1.0 .
docker push registry.example.com/acme/mcp-python:1.0

Then Projects → New MCP server → Container image with that image and port 8080.

RunR v0.5.7 · MIT License