Ross MCP
by Ross-C
README.md
# Ross MCP
Personal life admin system — manage Apple Reminders, Outlook email/calendar, Apple Notes, voice memos, and documents from Claude, ChatGPT, or any MCP/API client.
**Architecture:** Client (Claude/ChatGPT/API) → Cloud Relay (Fly.io) → Local Mac Agent → Apple APIs / Microsoft Graph
## Features
| Category | Tools |
|----------|-------|
| **Apple Reminders** | Create, list, complete reminders |
| **Outlook Email** | Search, read threads, draft, send, schedule, archive, attachments |
| **Outlook Calendar** | List events, create/update/cancel events, find free slots |
| **Apple Notes** | Search, read, create notes, list folders |
| **Voice Memos** | List recordings, transcribe with speaker diarization (Deepgram) |
| **Documents** | Convert Markdown to PDF or DOCX |
| **Agent Management** | Check agent status, trigger remote self-update |
**29 tools** accessible from:
- **Claude Web/Desktop** via remote MCP (streamable-http)
- **Claude Code** via remote MCP (same endpoint)
- **ChatGPT** via Custom GPT Actions (OpenAPI)
- **Any HTTP client** via REST API
## Quick Start
### 1. Clone and set up Python
```bash
cd ross-mcp
arch -arm64 python3 -m venv .venv # Use arch -arm64 on Apple Silicon
source .venv/bin/activate
pip install -r agent/requirements.txt
pip install mcp httpx python-dotenv
```
### 2. Configure environment
```bash
cp .env.example .env
# Edit .env — set RELAY_API_KEY (must match the Fly.io secret)
```
### 3. Set up Outlook (one-time per Mac)
```bash
brew install azure-cli
az login
./agent/setup_azure.sh
python3 -c "
import asyncio
from dotenv import load_dotenv
load_dotenv()
from agent.services.outlook_auth import OutlookAuth
auth = OutlookAuth()
asyncio.run(auth.authorize())
print('Success!' if auth.is_authenticated else 'Failed')
"
```
The refresh token auto-renews every 3 days.
### 4. Run the agent
```bash
source .venv/bin/activate
python -m agent.agent
```
The agent will:
- Connect to the cloud relay via WebSocket
- Start a local web UI at http://127.0.0.1:8001
- Listen for commands from any client
### 5. Install as auto-start service
```bash
./agent/install.sh
```
Creates a launchd service that starts on boot and stays running.
## Connecting Clients
All clients connect to the **same remote endpoint** on the relay. No local MCP server needed.
### Claude Web / Desktop (MCP)
| Setting | Value |
|---------|-------|
| URL | `https://ross-mcp-relay.fly.dev/mcp/mcp` |
| Transport | Streamable HTTP |
| Auth | Bearer token (your `RELAY_API_KEY`) |
### Claude Code (CLI)
Add to `~/.claude/settings.json`:
```json
{
"mcpServers": {
"ross-life-admin": {
"type": "http",
"url": "https://ross-mcp-relay.fly.dev/mcp/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
```
### ChatGPT (Custom GPT)
1. Create a Custom GPT at chat.openai.com
2. Add an **Action** → Import from URL: `https://ross-mcp-relay.fly.dev/openapi.json`
3. Set auth to **Bearer** with your `RELAY_API_KEY`
### Direct REST API
```bash
curl -X POST https://ross-mcp-relay.fly.dev/api/command \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type": "create_reminder", "payload": {"title": "Buy milk"}}'
```
## MyPurchases (invoices) — connected MCP
[MyPurchases](https://mypurchases.fly.dev) is a separate private app that tracks bank transactions and whether each purchase's receipt/invoice is stored. It's connected to Claude Code as its **own MCP server** (not routed through this relay), because invoice finding is driven from local Claude Code — so it's **Claude-only** and doesn't need the relay's local-agent plumbing. (If voice/ChatGPT ever need it, add a thin relay proxy then.)
Add it on a machine:
```bash
claude mcp add --transport http mypurchases https://mypurchases.fly.dev/api/mcp \
--header "Authorization: Bearer <api-key>" -s user
```
(key from MyPurchases → Settings → Integrations). Already added on both agents.
**Tools:** `missing_invoices { from?, to?, supplier_id? }`, `push_invoice { transaction_id, filename, content_base64, modified_at? }`, `list_suppliers`, `classify_transaction`.
**To add invoices:** `missing_invoices` for the date range → match each file to a transaction by supplier + amount + date → `push_invoice` (one per file). See `CLAUDE.md` for the full workflow.
## Deployment & Updates
### Deploy workflow (from any machine)
The `deploy.sh` script handles the full deployment pipeline:
```bash
# 1. Commit your changes
git add . && git commit -m "your changes"
# 2. Deploy everything
./deploy.sh
```
This will:
1. Push code to git
2. Deploy the relay to Fly.io
3. Tell all connected agents to pull updates and restart
### Manual steps
**Deploy relay only:**
```bash
fly deploy --app ross-mcp-relay
```
**Update agents only (via any client):**
Tell Claude/ChatGPT: "update the agents" — this triggers a git pull + restart on all connected agents.
Or via API:
```bash
curl -X POST https://ross-mcp-relay.fly.dev/api/command \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type": "update_agent", "payload": {}}'
```
**View relay logs:**
```bash
fly logs --app ross-mcp-relay
```
### Setting up a second Mac
1. Clone the repo
2. Set up venv: `arch -arm64 python3 -m venv .venv && pip install -r agent/requirements.txt`
3. Copy `.env` and change `AGENT_NAME` to identify the machine (e.g. `mac-mini`)
4. Run `./agent/setup_azure.sh` then the OAuth login (one-time)
5. Run `./agent/install.sh`
Both agents connect to the same relay. Commands route to whichever is online. Use `agent_status` to see connected agents.
### Launchd service commands
| Action | Command |
|--------|---------|
| Install | `./agent/install.sh` |
| Stop | `launchctl unload ~/Library/LaunchAgents/com.ross.mcp-agent.plist` |
| Start | `launchctl load ~/Library/LaunchAgents/com.ross.mcp-agent.plist` |
| Restart | Unload then load |
| Logs | `tail -f ~/Library/Logs/mcp-agent/mcp-agent.log` |
| Errors | `tail -f ~/Library/Logs/mcp-agent/mcp-agent.err` |
## Voice Memo Transcription
Record meetings on iPad using Voice Memos, share to iCloud Drive, then transcribe via Claude or ChatGPT.
### Setup
1. Create a "Meeting Recordings" folder in iCloud Drive (done automatically by the agent)
2. Create an iOS Shortcut called "Save Meeting Recording" on your iPad:
- Action: **Save File** → iCloud Drive / Meeting Recordings (Ask Where to Save: off)
- Enable **Show in Share Sheet**, set receives to **Audio**
3. Add your `DEEPGRAM_API_KEY` to `.env`
### After a meeting
1. Open Voice Memos on iPad → tap **...** → **Share** → **Save Meeting Recording**
2. Tell Claude: *"Transcribe my meeting with [name] from this morning"*
3. Claude finds the recording, transcribes with speaker diarization, enriches with summary and action points, and saves as an Apple Note
## Dashboard
The relay includes a secure web dashboard at `https://ross-mcp-relay.fly.dev/`.
**Features:**
- Password-protected login (session cookie, httponly + secure)
- Agent status with capabilities and uptime
- Command stats with counters (emails drafted, reminders created, etc.)
- Charts: commands by day (configurable range), breakdown by category
- Filterable activity log
- Client setup instructions (Claude Desktop, Claude Web, Claude Code, ChatGPT)
**Set the dashboard password:**
```bash
fly secrets set DASHBOARD_PASSWORD=your-password --app ross-mcp-relay
```
## Remote Endpoints
| Endpoint | URL | Auth |
|----------|-----|------|
| Dashboard | `https://ross-mcp-relay.fly.dev/` | Dashboard password |
| MCP (Claude) | `POST https://ross-mcp-relay.fly.dev/mcp/mcp` | Bearer token |
| REST API | `POST https://ross-mcp-relay.fly.dev/api/command` | Bearer token |
| Tool endpoints (ChatGPT) | `POST https://ross-mcp-relay.fly.dev/api/tools/*` | Bearer token |
| Swagger UI | `https://ross-mcp-relay.fly.dev/docs` | None (read-only) |
| Status | `GET https://ross-mcp-relay.fly.dev/api/status` | Bearer token |
| Agent WebSocket | `wss://ross-mcp-relay.fly.dev/ws/agent` | Bearer token |
## Secrets
| Secret | Location | Notes |
|--------|----------|-------|
| `RELAY_API_KEY` | `.env` (local) + Fly.io secrets | Shared by agent, relay, and clients |
| `DASHBOARD_PASSWORD` | Fly.io secrets | Web dashboard login |
| `MS_CLIENT_ID` / `MS_CLIENT_SECRET` | `.env` (local) | Azure AD app credentials |
| `.outlook_tokens.json` | Project root (gitignored) | OAuth tokens, auto-refreshed |
| `DEEPGRAM_API_KEY` | `.env` (local) | For voice memo transcription |
**Regenerate API key:**
```bash
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
# Update: .env, fly secrets set, Claude settings.json, and ChatGPT action auth
```
## Project Structure
```
ross-mcp/
├── agent/ # Local Mac agent
│ ├── agent.py # Main agent (WebSocket client + command dispatch)
│ ├── web.py # Local web UI (port 8001)
│ ├── setup_azure.sh # Azure AD app registration script
│ ├── install.sh # Launchd auto-start installer
│ └── services/
│ ├── reminders.py # Apple Reminders via EventKit
│ ├── notes.py # Apple Notes via AppleScript
│ ├── outlook_auth.py # OAuth2 for Microsoft Graph
│ ├── outlook_mail.py # Outlook email operations
│ ├── outlook_calendar.py # Outlook calendar operations
│ ├── voice_memos.py # Voice memo transcription (Deepgram)
│ └── documents.py # Markdown to PDF/DOCX conversion
├── relay/ # Cloud relay (Fly.io)
│ ├── relay.py # FastAPI hub (WebSocket + HTTP + dashboard)
│ ├── mcp_endpoint.py # Remote MCP server (streamable-http)
│ ├── openai_endpoints.py # REST endpoints for ChatGPT Actions
│ ├── Dockerfile
│ └── requirements.txt
├── shared/
│ └── messages.py # Command/Response schemas (all command types)
├── mcp_server.py # Local MCP server (stdio, legacy — use remote instead)
├── deploy.sh # Full deploy: git push + relay deploy + agent update
├── fly.toml # Fly.io config
└── .env.example # Environment template
```
## Links
- [Fly.io Dashboard](https://fly.io/apps/ross-mcp-relay) — Deployment management
- [Swagger UI](https://ross-mcp-relay.fly.dev/docs) — API documentation
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing