Files
gh-jezweb-claude-skills-ski…/references/cloud-deployment.md
2025-11-30 08:24:49 +08:00

310 lines
6.3 KiB
Markdown

# FastMCP Cloud Deployment Guide
Complete guide for deploying FastMCP servers to FastMCP Cloud.
## Critical Requirements
**❗️ MUST HAVE** for FastMCP Cloud:
1. **Module-level server object** named `mcp`, `server`, or `app`
2. **PyPI dependencies only** in `requirements.txt`
3. **Public GitHub repository** (or accessible to FastMCP Cloud)
4. **Environment variables** for configuration (no hardcoded secrets)
## Cloud-Ready Server Pattern
```python
# server.py
from fastmcp import FastMCP
import os
# ✅ CORRECT: Module-level export
mcp = FastMCP("production-server")
# ✅ Use environment variables
API_KEY = os.getenv("API_KEY")
DATABASE_URL = os.getenv("DATABASE_URL")
@mcp.tool()
async def production_tool(data: str) -> dict:
if not API_KEY:
return {"error": "API_KEY not configured"}
return {"status": "success", "data": data}
if __name__ == "__main__":
mcp.run()
```
## Common Anti-Patterns
### ❌ WRONG: Function-Wrapped Server
```python
def create_server():
mcp = FastMCP("server")
return mcp
if __name__ == "__main__":
server = create_server() # Too late for cloud!
server.run()
```
### ✅ CORRECT: Factory with Module Export
```python
def create_server() -> FastMCP:
mcp = FastMCP("server")
# Complex setup logic here
return mcp
# Export at module level
mcp = create_server()
if __name__ == "__main__":
mcp.run()
```
## Deployment Steps
### 1. Prepare Repository
```bash
# Initialize git
git init
# Add files
git add .
# Commit
git commit -m "Initial MCP server"
# Create GitHub repo
gh repo create my-mcp-server --public
# Push
git push -u origin main
```
### 2. Deploy to FastMCP Cloud
1. Visit https://fastmcp.cloud
2. Sign in with GitHub
3. Click "Create Project"
4. Select your repository
5. Configure:
- **Server Name**: Your project name
- **Entrypoint**: `server.py`
- **Environment Variables**: Add all needed variables
### 3. Configure Environment Variables
In FastMCP Cloud dashboard, add:
- `API_KEY`
- `DATABASE_URL`
- `CACHE_TTL`
- Any custom variables
### 4. Access Your Server
- **URL**: `https://your-project.fastmcp.app/mcp`
- **Auto-deploy**: Pushes to main branch auto-deploy
- **PR Previews**: Pull requests get preview deployments
## Project Structure Requirements
### Minimal Structure
```
my-mcp-server/
├── server.py # Main entry point (required)
├── requirements.txt # PyPI dependencies (required)
├── .env # Local dev only (git-ignored)
├── .gitignore # Must ignore .env
└── README.md # Documentation (recommended)
```
### Production Structure
```
my-mcp-server/
├── src/
│ ├── server.py # Main entry point
│ ├── utils.py # Self-contained utilities
│ └── tools/ # Tool modules
│ ├── __init__.py
│ └── api_tools.py
├── requirements.txt
├── .env.example # Template for .env
├── .gitignore
└── README.md
```
## Requirements.txt Rules
### ✅ ALLOWED: PyPI Packages
```txt
fastmcp>=2.12.0
httpx>=0.27.0
python-dotenv>=1.0.0
pydantic>=2.0.0
```
### ❌ NOT ALLOWED: Non-PyPI Dependencies
```txt
# Don't use these in cloud:
git+https://github.com/user/repo.git
-e ./local-package
./wheels/package.whl
```
## Environment Variables Best Practices
### ✅ GOOD: Environment-based Configuration
```python
import os
class Config:
API_KEY = os.getenv("API_KEY", "")
BASE_URL = os.getenv("BASE_URL", "https://api.example.com")
DEBUG = os.getenv("DEBUG", "false").lower() == "true"
@classmethod
def validate(cls):
if not cls.API_KEY:
raise ValueError("API_KEY is required")
```
### ❌ BAD: Hardcoded Values
```python
# Never do this in cloud:
API_KEY = "sk-1234567890" # Exposed in repository!
DATABASE_URL = "postgresql://user:pass@host/db" # Insecure!
```
## Avoiding Circular Imports
**Critical for cloud deployment!**
### ❌ WRONG: Factory Function in `__init__.py`
```python
# shared/__init__.py
def get_api_client():
from .api_client import APIClient # Circular import risk
return APIClient()
# shared/monitoring.py
from . import get_api_client # Creates circle!
```
### ✅ CORRECT: Direct Imports
```python
# shared/__init__.py
from .api_client import APIClient
from .cache import CacheManager
# shared/monitoring.py
from .api_client import APIClient
client = APIClient() # Create directly
```
## Testing Before Deployment
### Local Testing
```bash
# Test with stdio (default)
fastmcp dev server.py
# Test with HTTP
python server.py --transport http --port 8000
```
### Pre-Deployment Checklist
- [ ] Server object exported at module level
- [ ] Only PyPI dependencies in requirements.txt
- [ ] No hardcoded secrets (all in environment variables)
- [ ] `.env` file in `.gitignore`
- [ ] No circular imports
- [ ] No import-time async execution
- [ ] Works with `fastmcp dev server.py`
- [ ] Git repository committed and pushed
- [ ] All required environment variables documented
## Monitoring Deployment
### Check Deployment Logs
FastMCP Cloud provides:
- Build logs
- Runtime logs
- Error logs
### Health Check Endpoint
Add a health check resource:
```python
@mcp.resource("health://status")
async def health_check() -> dict:
return {
"status": "healthy",
"timestamp": datetime.now().isoformat(),
"version": "1.0.0"
}
```
### Common Deployment Errors
1. **"No server object found"**
- Fix: Export server at module level
2. **"Module not found"**
- Fix: Use only PyPI packages
3. **"Import error: circular dependency"**
- Fix: Avoid factory functions in `__init__.py`
4. **"Environment variable not set"**
- Fix: Add variables in FastMCP Cloud dashboard
## Continuous Deployment
FastMCP Cloud automatically deploys when you push to main:
```bash
# Make changes
git add .
git commit -m "Add new feature"
git push
# Deployment happens automatically!
# Check status at fastmcp.cloud
```
## Rollback Strategy
If deployment fails:
```bash
# Revert to previous commit
git revert HEAD
git push
# Or reset to specific commit
git reset --hard <commit-hash>
git push --force # Use with caution!
```
## Resources
- **FastMCP Cloud**: https://fastmcp.cloud
- **FastMCP GitHub**: https://github.com/jlowin/fastmcp
- **Deployment Docs**: Check FastMCP Cloud documentation