Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Use generic, obviously-fake examples instead: "Main Credit Card", "Corner Deli",
- `MONARCH_FORCE_LOGIN=true uv run python server.py` - Force fresh login (if session expires)

### Debugging Startup Issues (Updated July 2025)
- **Session expired**: Delete `.mm/session.pickle` or set `MONARCH_FORCE_LOGIN=true`
- **Session expired**: Delete `~/.monarch-mcp/session.pickle` or set `MONARCH_FORCE_LOGIN=true`
- **JSON parse errors**: Fixed - all stdout output suppressed with `contextlib.redirect_stdout()`
- **MCP protocol compliance**: All logging/warnings redirected to stderr, third-party lib output suppressed
- **AsyncIO errors**: Fixed - uses `run_stdio_async()` in async context
Expand Down Expand Up @@ -166,7 +166,7 @@ refactor: split server.py into modular components (auth, tools, models)
- Automatic capability negotiation and tool discovery

**Secure Authentication & Session Management**
- Sessions stored in `.mm/` directory with 0700 permissions
- Sessions stored in `~/.monarch-mcp/` directory (override via `MONARCH_SESSION_DIR`) with 0700 permissions
- Proper `RequireMFAException` handling
- Structured logging with `structlog` for debugging
- Environment variables: `MONARCH_EMAIL`, `MONARCH_PASSWORD`, `MONARCH_MFA_SECRET`
Expand Down Expand Up @@ -237,7 +237,7 @@ Published to PyPI as `monarch-mcp-jamiew` and to the MCP Registry as `io.github.

### Session Management

- Session files stored in `.mm/` directory (created automatically)
- Session files stored in `~/.monarch-mcp/` directory (created automatically; override via `MONARCH_SESSION_DIR`)
- Session invalidation handled gracefully with automatic re-authentication
- Use `MONARCH_FORCE_LOGIN=true` to bypass session cache for debugging
- Sessions follow Monarch Money API session management patterns
Expand All @@ -249,7 +249,7 @@ Published to PyPI as `monarch-mcp-jamiew` and to the MCP Registry as `io.github.
#### Phase 1 Critical Fixes (All Complete)
- **✅ Type Safety**: Eliminated `Any` types, added Pydantic models, strict typing
- **✅ FastMCP Migration**: Modern MCP protocol with `@mcp.tool()` decorators
- **✅ Authentication Security**: `.mm/` directory, 0600 permissions, `RequireMFAException` handling
- **✅ Authentication Security**: `~/.monarch-mcp/` directory, 0600 permissions, `RequireMFAException` handling
- **✅ Structured Logging**: Context-rich logs with `structlog`
- **✅ Complete API Coverage**: All 14 Monarch Money API methods as tools

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ By default, transactions return a compact format with the fields that matter:

## Session management

Sessions are cached in a `.mm` directory for faster subsequent logins. If you hit auth issues:
Sessions are cached in `~/.monarch-mcp/` for faster subsequent logins (override the location with the `MONARCH_SESSION_DIR` env var). If you hit auth issues:

- Delete `.mm/session.pickle` to clear the cached session
- Delete `~/.monarch-mcp/session.pickle` to clear the cached session
- Set `MONARCH_FORCE_LOGIN=true` in your env config to force a fresh login
- Make sure your system clock is accurate (required for TOTP)

Expand Down Expand Up @@ -281,7 +281,7 @@ uv run scripts/eval_session.py analyze # analyze new entries
- The server runs locally on your machine — your credentials live in your MCP client config and **never pass through the LLM**. Only the financial data you actually query is returned to the assistant.
- Your credentials have full account access — treat them like passwords
- The MFA secret (TOTP key) provides ongoing access
- Session files in `.mm/` contain auth tokens — keep them secure
- Session files in `~/.monarch-mcp/` contain auth tokens — keep them secure
- Never commit `.env` or `.mcp.json` files to version control
- This is an unofficial API — Monarch Money could change or restrict access at any time

Expand Down
11 changes: 8 additions & 3 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,9 +921,14 @@ class AuthState(Enum):
auth_failed_at: float | None = None # Timestamp of last auth failure for cooldown
AUTH_RETRY_COOLDOWN_SECONDS = 60 # Wait 60 seconds before retrying after FAILED state

# Secure session directory with proper permissions
session_dir = Path(".mm")
session_dir.mkdir(mode=0o700, exist_ok=True)
# Secure session directory with proper permissions.
# Resolve to an absolute, writable path: many MCP clients (e.g. Claude Desktop)
# launch the server with a read-only working directory like "/", so a relative
# ".mm" would fail with "Read-only file system". Honor MONARCH_SESSION_DIR if set,
# otherwise default to ~/.monarch-mcp which is always writable.
_session_dir_env = os.getenv("MONARCH_SESSION_DIR")
session_dir = Path(_session_dir_env).expanduser() if _session_dir_env else Path.home() / ".monarch-mcp"
session_dir.mkdir(mode=0o700, parents=True, exist_ok=True)
session_file = session_dir / "session.pickle"


Expand Down
Loading