Book API with GraphQL, REST, and MCP (fastapi-mcp) — Chapter 9 of Building Serverless Python Apps on AWS.
Based on sample-fastapi-graphql-book-api with REST routes annotated for MCP tools (operation_id, description).
MCP is mounted with streamable HTTP via mcp.mount_http() (recommended in fastapi-mcp 0.4+). The legacy mcp.mount() SSE transport is not used.
Part of the serverless-python-dev monorepo.
uv sync --all-groups
uv run uvicorn main:app --reloadStart MongoDB locally (API on the host uses localhost, not the Docker service name):
docker compose up mongoIn another terminal, launch the Inspector (no --url flag on current releases):
npx @modelcontextprotocol/inspectorOpen the browser UI (default http://127.0.0.1:6274). The npx command does not pass your API URL—you connect in the UI:
- Transport: Streamable HTTP (not legacy SSE).
- Server:
http://127.0.0.1:8000/mcp(or host127.0.0.1, port8000, path/mcp). - Connect, then open the Tools tab and run
fetch_books.
Do not use npx @modelcontextprotocol/inspector --url http://.../sse or transport SSE—those match Node/Java MCP samples, not this app. Use Streamable HTTP and path /mcp only. Current Inspector releases reject --url anyway.
REST/MCP tools return HTTP 200 with success: false and an errorMessage when the database is down (see src/api/rest_errors.py), instead of a bare 500.
Local .env example:
DB_URL=mongodb://localhost:27017
DB_NAME=bookapiUse your Atlas URI only if that cluster still exists; a bad SRV host shows up as a DNS error in errorMessage.
Optional auth (.env):
AUTH_ENABLED=true
ALLOWED_SUBJECTS=TEST_SERVICE1,TEST_SERVICE_2Claude/Cursor mcp.json example:
{
"mcpServers": {
"bookapi-local": {
"url": "http://127.0.0.1:8000/mcp"
}
}
}For local MongoDB only:
docker compose up mongoThe bookapi service in docker-compose.yaml expects a locally built bookapi image (docker build -t bookapi -f Dockerfile .). For day-to-day MCP work, run the API with uv run uvicorn on the host and Mongo in Docker as above.
To refresh the image on your local (for server devs), run the following:
docker build -t bookapi -f Dockerfile .You can run the one off image and container with the following:
docker run -d --name bookapi -p 8000:8000 bookapiInstall dependencies with uv:
uv sync --all-groupsYou'll need the following environment variables configured or in a .env file to run the server successfully:
# FastAPI Setup
export HOST="127.0.0.1"
export PORT=8000
# BookAPI DB Setup
export DB_URL='mongodb://localhost:27017'
export DB_NAME='bookapi'
# AWS and Infra Setup
AWS_ACCOUNT='YOUR_ACCOUNT'
AWS_REGION='AWS REGION (e.g. us-east-1)'
# Optional — chapter 5 "Prettify the URL"; omit for HTTP on the ALB DNS name
DOMAIN_NAME='example.com'
# Infra Setup
LOCAL_NETWORK_CIDR='YOUR_NETWORK_CIDR'The main entry point is main.py, so you can start that file from command line or use whatever execution method is available from your IDE. To install the IDE to interact with GraphQL, look in the SETUP.md for GraphQL Playground installation instructions then simply open the GraphQL Playground to interact with the local server and insert the base url http://127.0.0.1:8000/graph.
Changes under /app may be picked up by the auto-refresh (no need to restart server). To understand how to use the playground to run queries, please reference the following: GraphQL Queries Reference
All tests are located under the tests folder. To run them from terminal, execute the following:
uv run pytest testsTo run with coverage, run the following:
uv run coverage run -m pytest -v tests && uv run coverage report -mThe docs are autogenerated and are available after starting the server. Docs are available at {BASE_URL}/graphql/docs.
To update the doc url, update the get_graphql_docs() function in main.py.
Note that the Makefile included in this repo uses several environment variables. Be sure to have your .env setup to fully leverage all the shortcuts made available.