A FastAPI service for CaseRover with MariaDB backend, exposing both REST API and MCP (Model Context Protocol) functionality.
- REST API with OpenAPI documentation
- MCP Server for AI assistant integration
- Multi-tenant isolation with law-firm scoping
- API key authentication with SHA-256 hashing
- SSH tunnel support for secure remote database connections (dev environments)
- Structured logging with JSON output
- Auto-calculated transaction totals
- API keys hashed with SHA-256 before database lookup
- Law-firm scoping on all queries (multi-tenant isolation)
- Automatic owner_id and law_firm_id attribution
- Whitelisted editable fields on case updates
- Never logs API keys
REST API (FastAPI) ──┐
├──> Service Layer ──> Database (MariaDB)
MCP Server (SSE) ──┘
Both REST and MCP use the same service layer, ensuring consistent law-firm scoping and business logic.
# Using the virtual environment
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -e .Or install dev dependencies:
pip install -e ".[dev]"Copy .env and configure your database:
cp .env .env.localEdit .env:
DATABASE_URL=mysql+pymysql://username:password@localhost:3306/cr
API_V1_PREFIX=/api/v1
API_KEY_HEADER=X-API-Key
MCP_PATH=/mcp
LOG_LEVEL=INFOSSH Tunnel Support: If you need to connect to a remote database through an SSH tunnel (common in dev environments), see SSH Tunnel Setup Guide for detailed configuration instructions.
python -c "from app.database import engine; engine.connect(); print('Database connected!')"uvicorn app.main:app --reload --port 8000The service will be available at:
- REST API:
http://localhost:8000/api/v1 - MCP Server:
http://localhost:8000/mcp - API Docs:
http://localhost:8000/docs - Health Check:
http://localhost:8000/health
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4All requests require an API key in the header:
curl -H "X-API-Key: YOUR_API_KEY" http://localhost:8000/api/v1/cases/TEST-001curl -H "X-API-Key: YOUR_KEY" \
http://localhost:8000/api/v1/cases/TEST-001curl -X PATCH \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"injured_first_name": "John",
"injured_last_name": "Doe",
"accident_date": "2024-01-15T10:30:00"
}' \
http://localhost:8000/api/v1/cases/TEST-001curl -X POST \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"principal_amount": 1000.00,
"interest_amount": 50.00,
"cost": 25.00
}' \
http://localhost:8000/api/v1/cases/TEST-001/transactionsThe total field is auto-calculated: 1000 + 50 + 25 = 1075.00
curl -X POST \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"note": "Client called regarding settlement offer",
"important": true
}' \
http://localhost:8000/api/v1/cases/TEST-001/notesThe MCP (Model Context Protocol) server provides AI assistant integration with the same security and business logic as the REST API.
Endpoint: http://localhost:8000/mcp
Transport: SSE (Server-Sent Events)
Authentication: Required via X-API-Key header
All MCP requests must include the API key in the header:
X-API-Key: your_api_key_here
The server authenticates the user and enforces law-firm scoping on all operations, just like the REST API.
MCP clients that require OAuth (like ChatGPT) can authenticate via OAuth 2.1 Authorization Code + PKCE. See docs/MCP_EXAMPLES.md for setup instructions.
Get case details by case_id.
Parameters:
case_id(string, required): The case ID to look up
Returns: Formatted case details including injured/insured parties, dates, and AAA arbitration information.
Example response:
Case ABC-123 found:
- Injured: John Doe
- Insured: Jane Smith
- Accident Date: 2024-01-15
- Policy #: POL-12345
- AAA Case #: AAA-789
- AAA URL: https://adr.org/cases/789
Update case fields.
Parameters:
case_id(string, required): The case ID to update- Optional fields:
injured_first_name,injured_last_name,insured_first_name,insured_last_name,accident_date,policy_number,claim_number,carrier_counsel_file_number,aaa_case_number,aaa_case_url,aaa_filing_date,aaa_conciliation_date,aaa_hearing_date,aaa_award_date
Returns: Confirmation with list of updated fields.
Add a financial transaction to a case.
Parameters:
case_id(string, required): The case IDsource(string, required): Transaction source type. One of:deposited_provider- Deposited in Provider Accountdeposited_attorney- Deposited in Attorney Accountforwarded_provider- Forwarded to Providercost_paid_attorney- Cost/Other: Paid by Attorneycost_paid_provider- Cost/Other: Paid by Provider
- Optional:
date,principal_amount,interest_amount,attorney_fee_amount,cost,other_cost
Returns: Transaction confirmation with ID, total, source, and date.
Note: provider_id is automatically retrieved from the case. Total is auto-calculated from component amounts.
Add a note to a case.
Parameters:
case_id(string, required): The case IDnote(string, required): The note contentimportant(boolean, optional, default: false): Mark as importantmute(boolean, optional, default: false): Mute the note
Returns: Note confirmation with ID and timestamp.
Note: Date is automatically set to current time.
All tools return error messages if:
- Case not found or not accessible (law-firm scoping)
- Invalid transaction source
- Authentication failure
- Validation errors
The service uses an existing MariaDB schema (schema/caserover_schema.sql).
Key tables:
api_keys- API key authentication (hashed)user- Users with law_firm_idorg- Law firms (organizations)matter- Cases with law_firm_id scopingfin_transaction- Transactions with law_firm_id scopingnote- Notesmatter_note- Case-note relationships
All data access is automatically scoped by law_firm_id:
- User authenticates with API key
- API key lookup returns user with
law_firm_id - All service methods filter by
WHERE law_firm_id = current_user.law_firm_id - Users can only access data from their own law firm
- API keys are hashed with SHA-256 before database lookup
- Only the hash is stored in the database
- API keys are NEVER logged
- Keys can have expiration dates
last_used_atis updated on each request
Case updates only allow specific fields:
- Injured/insured names and dates
- Case identifiers (policy_number, claim_number, etc.)
- AAA arbitration fields
All other fields are protected from modification.
app/
├── api/
│ ├── deps.py # Authentication dependencies
│ └── v1/endpoints/ # REST endpoints
├── core/
│ ├── security.py # API key hashing
│ ├── logging.py # Structured logging
│ └── exceptions.py # Custom exceptions
├── mcp/
│ ├── server.py # MCP server
│ └── tools.py # Tool definitions
├── models/ # SQLAlchemy ORM
├── schemas/ # Pydantic request/response
├── services/ # Business logic with law-firm scoping
│ ├── base.py # BaseService (CRITICAL SECURITY)
│ ├── case_service.py
│ ├── transaction_service.py
│ └── note_service.py
├── config.py # Settings
├── database.py # Database connection
└── main.py # FastAPI app
pytestIf the database schema changes, regenerate models:
python scripts/generate_models.pyAll logs are output as JSON for easy parsing:
{
"timestamp": "2024-01-15T10:30:00Z",
"level": "info",
"user_id": 123,
"law_firm_id": 5,
"message": "Case retrieved",
"case_id": "TEST-001"
}IMPORTANT: API keys are NEVER logged.
| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
MariaDB connection string | Required |
API_V1_PREFIX |
REST API path prefix | /api/v1 |
API_KEY_HEADER |
Header name for API key | X-API-Key |
MCP_PATH |
MCP server path | /mcp |
LOG_LEVEL |
Logging level | INFO |
The CaseRover API uses Docker and GitHub Actions for automated CI/CD deployment to AWS EC2 instances.
- Staging: https://api.stage.caserover.com (auto-deploys on push to
main) - Production: https://api.caserover.com (manual deployment via GitHub releases)
Deploy to Staging (automatic on merge to main):
git push origin mainDeploy to Production (create a release):
git tag v1.0.0
git push origin v1.0.0
gh release create v1.0.0 --title "v1.0.0" --notes "Release notes"- Deployment Guide: Complete setup and deployment documentation
- Quick Start: Fast reference for common deployment tasks
- Docker multi-stage builds for optimized images
- GitHub Container Registry (ghcr.io) for image storage
- Zero-downtime deployments with health checks
- Nginx reverse proxy with SSL/TLS termination
- Automated rollback capability
- Host networking for direct database access
Proprietary - CaseRover