FastAPI
Mount pyRPC on a FastAPI application using mount_fastapi.
The FastAPI adapter mounts pyRPC onto a FastAPI app. Every registered procedure becomes callable at POST /rpc. Queries map to useQuery and mutations to useMutation on the frontend, no extra config needed.
1. Install
uv add pyrpc-core[fastapi]
# or
pip install "pyrpc-core[fastapi]"2. Write the server
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pyrpc_core import rpc
from pyrpc_fastapi import mount_fastapi
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"], # your frontend origin
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@rpc.query
def read_root():
return {"Hello": "World"}
@rpc.query
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
@rpc.mutation
def create_item(name: str, description: str = None):
return {"name": name, "description": description, "created": True}
mount_fastapi(app)3. Start the dev server
From the directory containing main.py:
pyrpc devFirst run launches a short wizard - backend framework (FastAPI is preselected when detected) and entry point, then client root and frontend framework - and writes pyrpc.json. Every subsequent run reads that file, no prompts. To skip the wizard entirely:
# auto-detect everything
pyrpc dev --yes
# fully explicit: good for CI
pyrpc dev --yes --framework fastapi --module main --client ../clientpyrpc dev starts uvicorn with your module[:app] entry point, generates __pyrpc.ts at the client project root, and re-generates it on every .py save. If a server is already running on that port, it skips starting uvicorn and only runs the type watcher.
4. Connect the frontend
Install the adapter for your frontend framework:
# React
npm install @pyrpc/react @tanstack/react-query
# Next.js
npm install @pyrpc/next @tanstack/react-query
# Vue
npm install @pyrpc/vue @tanstack/vue-query
# Svelte
npm install @pyrpc/svelte @tanstack/svelte-queryThen create the typed client, the import from @pyrpc/types resolves to the generated __pyrpc.ts in your client project:
import { createReactClient, httpBatchLink } from "@pyrpc/react"
import type { Types } from "@pyrpc/types"
export const api = createReactClient<Types>({
links: [
httpBatchLink({
url: "http://localhost:8000",
}),
],
})See the React, Next.js, Vue, or Svelte docs for complete setup per framework.
How it works
@rpc.query/@rpc.mutationregister the function in a global procedure registry and tag it with a kind.mount_fastapi(app)adds two routes:POST /rpc: procedure dispatchGET /rpc: schema introspection (used bypyrpc devto generate types)
- The kind tag (
queryvsmutation) flows through codegen into the generated__pyrpc.tsfile, which is how the frontend adapter knows which TanStack hook to expose on each procedure.
CORS origins by frontend
| Frontend | Default dev origin |
|---|---|
| React (CRA) | http://localhost:3000 |
| React (Vite) | http://localhost:5173 |
| Next.js | http://localhost:3000 |
| Vue (Vite) | http://localhost:5173 |
| Svelte (Vite) | http://localhost:5173 |
Routers
For larger projects, organize procedures into separate routers:
from pyrpc_core import Router
from pyrpc_fastapi import mount_fastapi
users = Router()
items = Router()
@users.query
def get_user(user_id: int): ...
@items.mutation
def create_item(name: str): ...
# Merge into the default router before mounting
from pyrpc_core import default_router
default_router.include(users, prefix="users")
default_router.include(items, prefix="items")
mount_fastapi(app)Full working examples
| Example | Frontend | Source |
|---|---|---|
| FastAPI + React | React + TanStack Query | examples/fastapi-react |
| FastAPI + Next.js | Next.js App Router + RSC | examples/fastapi-nextjs |
| FastAPI + Vue | Vue 3 + TanStack Vue Query | examples/fastapi-vue |
| FastAPI + Svelte | Svelte + TanStack Svelte Query | examples/fastapi-svelte |

pyRPC