Skip to main content
Glama
aliaksandr-liapin

FastMCP Production-Ready Server

README.md
# fast-mcp-server

# PRD: FastMCP Production-Ready Server

## 1. Purpose
Build a production-ready FastMCP server that is structured, configurable, testable, and ready for local, containerized, and Azure deployments. Include Neo4j connectivity as a tool and provide CI/CD scaffolding.

## 2. Goals
- Organize the project into a package-based structure.
- Provide environment-driven configuration (HOST/PORT, app name, Neo4j creds).
- Add structured logging (JSON).
- Add Neo4j tools: health check and query tool.
- Provide tests, Docker, Docker Compose, and Azure deployment templates.
- Provide CI workflow for tests and optional deployments.

## 3. Non-Goals
- Full production security hardening (secrets management, network policies).
- Domain-specific Neo4j schema or complex query library.
- Full monitoring/observability stack.

## 4. Target Environment
- Python 3.10.19
- FastMCP 2.14.5
- Neo4j 5.25.0
- Local dev on macOS, production on Azure (Container Apps or App Service)

## 5. Functional Requirements

### 5.1 Server
- Must start a FastMCP server with name from environment.
- Must bind to HOST and PORT from environment.
- MCP endpoint available at /mcp.

### 5.2 Tools
- greet(name: str) -> str returns "Hello, {name}!".
- neo4j_health() -> "ok" or "error" with exception string.
- neo4j_query(cypher: str, parameters: dict | None = None, limit: int = 50) -> list[dict]
  - Limit capped to 1..1000.
  - Return list of record dicts or [{"error": "..."}] on failure.

### 5.3 Configuration
- Read these variables:
  - APP_NAME
  - HOST
  - PORT
  - LOG_LEVEL
  - NEO4J_URI
  - NEO4J_USER
  - NEO4J_PASSWORD
- Provide .env.example template.

### 5.4 Logging
- Emit JSON logs to stdout.
- Include time (UTC ISO), level, logger, message, and exc_info when present.

### 5.5 Tests
- Basic unit test for greet tool.
- Run with pytest.

### 5.6 Docker and Compose
- Dockerfile for app container.
- docker-compose.yml with app and Neo4j services.
- App uses Neo4j container via bolt://neo4j:7687.

### 5.7 Azure Deployment
- Azure Container Apps template (containerapp.yaml).
- Script to deploy Container Apps.
- App Service startup script.
- App Service appsettings.json template.
- Script to deploy App Service.
- GitHub Actions workflow for CI and optional deploy.

### 5.8 GitHub Secrets (Deploy)
Required for CI deploy jobs:
- AZURE_CREDENTIALS (service principal JSON)
- AZURE_RG
- AZURE_LOCATION
- ACR_LOGIN_SERVER
- ACR_USERNAME
- ACR_PASSWORD

App Service only:
- APP_SERVICE_NAME

Container Apps only:
- ACA_ENV
- ACA_APP_NAME

## 6. Project Structure
.
├─ app/
│ ├─ __init__.py
│ ├─ config.py
│ ├─ logging.py
│ ├─ main.py
│ └─ tools/
│ ├─ __init__.py
│ ├─ greetings.py
│ └─ neo4j.py
├─ tests/
│ └─ test_greetings.py
├─ requirements/
│ ├─ base.txt
│ └─ dev.txt
├─ .env.example
├─ Dockerfile
├─ docker-compose.yml
├─ startup.sh
├─ requirements.txt
├─ server.py
├─ azure/
│ ├─ appsettings.json
│ └─ containerapp.yaml
├─ scripts/
│ ├─ deploy_aca.sh
│ └─ deploy_appservice.sh
└─ .github/
└─ workflows/
└─ ci-deploy.yml


## 6.1 Quick Start

Local:
1. Create a .env file from .env.example and adjust values as needed.
2. Install deps: pip install -r requirements/dev.txt
3. Run tests: pytest
4. Start server: python -m app.main
5. Open: http://127.0.0.1:8000/mcp

Docker:
1. Build and run: docker compose up --build
2. Open: http://127.0.0.1:8000/mcp
3. Neo4j browser: http://127.0.0.1:7474

Azure App Service (manual):
1. Set required environment variables and secrets for ACR.
2. Run: bash scripts/deploy_appservice.sh

Neo4j env vars (required for Neo4j tools):
- NEO4J_URI
- NEO4J_USER
- NEO4J_PASSWORD

MCP client headers (stateless streamable-http):
- Accept: application/json, text/event-stream
- Content-Type: application/json

Postman import (stateless collection):
```json
{
  "info": {
    "name": "FastMCP Neo4j (Stateless)",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [
    {
      "name": "neo4j_health",
      "request": {
        "method": "POST",
        "header": [
          { "key": "Accept", "value": "application/json, text/event-stream" },
          { "key": "Content-Type", "value": "application/json" }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"jsonrpc\": \"2.0\",\n  \"id\": \"h1\",\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"neo4j_health\",\n    \"arguments\": {}\n  }\n}"
        },
        "url": {
          "raw": "http://{{host}}:{{port}}/mcp",
          "protocol": "http",
          "host": ["{{host}}"],
          "port": "{{port}}",
          "path": ["mcp"]
        }
      }
    },
    {
      "name": "neo4j_query",
      "request": {
        "method": "POST",
        "header": [
          { "key": "Accept", "value": "application/json, text/event-stream" },
          { "key": "Content-Type", "value": "application/json" }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"jsonrpc\": \"2.0\",\n  \"id\": \"q1\",\n  \"method\": \"tools/call\",\n  \"params\": {\n    \"name\": \"neo4j_query\",\n    \"arguments\": {\n      \"cypher\": \"MATCH (n) RETURN n LIMIT 5\",\n      \"parameters\": {}\n    }\n  }\n}"
        },
        "url": {
          "raw": "http://{{host}}:{{port}}/mcp",
          "protocol": "http",
          "host": ["{{host}}"],
          "port": "{{port}}",
          "path": ["mcp"]
        }
      }
    }
  ],
  "variable": [
    { "key": "host", "value": "127.0.0.1" },
    { "key": "port", "value": "8000" }
  ]
}
```

## 7. Architecture

### 7.1 Component Diagram (ASCII)

flowchart TB
  App["FastMCP App<br/>app/main.py<br/>tools/*.py<br/>config.py<br/>logging.py"]
  Neo4j["Neo4j DB<br/>bolt://host:7687"]
  MCP["/mcp endpoint"]

  App <---> Neo4j
  App --> MCP

### 7.2 Runtime Flow (ASCII)
Start 
    -> load Settings 
    -> configure JSON logging 
    -> create FastMCP
    -> register tools 
    -> run(host, port)


### 7.3 Deployment Diagram (ASCII)
Local:
Developer -> Python -> FastMCP -> /mcp

Docker:
Developer -> Docker -> Container (FastMCP) -> Neo4j container

Azure Container Apps:
GitHub Actions -> ACA -> Container (FastMCP)

Azure App Service:
GitHub Actions -> App Service -> startup.sh -> FastMCP


## 8. Detailed Implementation Requirements

### 8.1 app/config.py
- Dataclass Settings with env defaults.
- get_settings() returns Settings.

### 8.2 app/logging.py
- JsonFormatter with ensure_ascii=True.
- configure_logging(level) sets root handler and level.

### 8.3 app/main.py
- create_app(settings) returns FastMCP with tools registered.
- main() loads settings and runs with host/port.

### 8.4 app/tools/neo4j.py
- Use neo4j.GraphDatabase.driver with cached driver.
- Health check uses "RETURN 1 AS ok".
- Query returns list of dicts, handles errors.

### 8.5 server.py
- Calls app.main.main for compatibility.

## 9. Security and Config
- No secrets stored in repo.
- .env.example is safe default.
- Azure app settings used to provide secrets in production.

## 10. Operational Considerations
- Logging is JSON for ingestion into Azure logging.
- Neo4j connectivity errors should not crash server on startup.
- Neo4j query tool is minimal and should be restricted in production.

## 11. Risks and Mitigations
- Unbounded queries: enforce limit cap.
- Credentials leakage: avoid committing .env, use Azure settings.
- Availability: allow container restarts via Azure.

## 12. Testing Plan
- Unit test for greet tool.
- Optional: add integration tests for Neo4j in docker-compose.

## 13. Acceptance Criteria
- Server runs with env HOST/PORT.
- /mcp endpoint responds.
- greet tool returns correct string.
- neo4j_health returns "ok" when DB reachable.
- neo4j_query returns rows for valid queries.
- docker-compose brings up app + neo4j.
- CI runs pytest.
- Azure templates and scripts are present.

## 14. Milestones
1. Restructure project and add config/logging/tools.
2. Add tests and split requirements.
3. Add Docker and Compose.
4. Add Azure templates and scripts.
5. Add CI workflow.

## 15. Open Questions
- Final Neo4j schema and query patterns.
- Azure target: Container Apps vs App Service primary.
- Secrets management strategy (Key Vault, etc.).