Skip to main content
Glama
jrolstad
by jrolstad
README.md
# becu-mcp

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that provides read-only access to your [BECU](https://www.becu.org) accounts via browser automation. Use it with Claude Code or any MCP-compatible client to query account balances and transaction history conversationally.

## What it does

Exposes three tools:

| Tool | Description |
|------|-------------|
| `get_accounts` | Returns all accounts with current balance, available balance, and YTD interest |
| `get_balance` | Returns balance details for a single account by index |
| `get_transactions` | Returns transaction history for an account (date, description, amount, balance) |

Authentication is handled automatically using Playwright to drive a Chromium browser. Sessions are persisted to `session.json` so subsequent calls run headlessly. If the session expires or MFA is required, a visible browser window opens for you to complete login.

## Installation

### Prerequisites

- Python 3.11+
- [uv](https://docs.astral.sh/uv/) or pip

### Steps

1. Clone the repository:
   ```bash
   git clone https://github.com/jrolstad/becu-mcp.git
   cd becu-mcp
   ```

2. Install dependencies:
   ```bash
   pip install -r requirements.txt
   ```

3. Install Playwright's Chromium browser:
   ```bash
   playwright install chromium
   ```

4. Set your BECU credentials using one of the two options below.

### Configure with Claude Code

Add the server to your Claude Code MCP settings (`~/.claude.json` under `mcpServers`). Credentials can be provided in the MCP config directly (recommended) or via a `.env` file.

**Option A — credentials in MCP config (recommended)**

Pass credentials as environment variables in the MCP server entry. This keeps everything in one place and avoids needing a `.env` file on disk.

```json
{
  "mcpServers": {
    "becu": {
      "type": "stdio",
      "command": "python",
      "args": ["/path/to/becu-mcp/server.py"],
      "env": {
        "BECU_USERNAME": "your_username_here",
        "BECU_PASSWORD": "your_password_here"
      }
    }
  }
}
```

**Option B — `.env` file**

Create a `.env` file in the repo directory:
```bash
cp .env.example .env
```
Then edit `.env`:
```
BECU_USERNAME=your_username_here
BECU_PASSWORD=your_password_here
```

The server loads this automatically via `python-dotenv` on startup. The `.env` file is gitignored.

## Usage

Once connected, you can ask Claude things like:

- "List my BECU accounts with their balances"
- "What are the last 20 transactions from My Checking?"
- "What's the balance on my savings account?"
- "How much YTD interest has the Annual Payments savings account earned?"

## Authentication and sessions

- On first run, a Chromium browser window opens and logs in with your credentials.
- If MFA is required, you have 60 seconds to complete it in the browser window.
- After a successful login, cookies are saved to `session.json` for future headless runs.
- If a session expires, the browser window opens again automatically.
- `session.json` is gitignored — do not commit it.

## Development

### Project structure

```
becu_client.py   # Playwright scraping and HTML parsing logic
server.py        # MCP server (FastMCP) — exposes tools to MCP clients
requirements.txt # Python dependencies
.env.example     # Credential template
session.json     # Persisted browser session cookies (gitignored)
```

### How scraping works

`becu_client.py` uses Playwright to load pages from `onlinebanking.becu.org`, then parses the HTML with BeautifulSoup. The BECU pages use a [Tablesaw](https://github.com/filamentgroup/tablesaw) responsive table library that embeds column labels inside each `<td>` as `<b class="tablesaw-cell-label">` elements. The parser extracts these labels to identify each cell's field regardless of column order, making it resilient to layout changes.

Key functions:

- `_get_page_html()` — fetches a page, handles auth/session management
- `_cell_label_and_value()` — extracts the field label and value from a tablesaw `<td>`
- `_parse_currency()` — converts `"$1,234.56"` to `1234.56`
- `get_accounts()` — scrapes the Summary page, deduplicates by account number
- `get_transactions()` — scrapes the Activity page, filters out summary/non-transaction rows

### Running locally

```bash
python server.py
```

Or via the MCP CLI:

```bash
mcp dev server.py
```

### Adding new tools

1. Add a new async function to `becu_client.py` that fetches and parses the relevant BECU page.
2. Register it as a tool in `server.py` using the `@mcp.tool()` decorator.
3. Reconnect your MCP client to pick up the new tool.

### Dependencies

| Package | Purpose |
|---------|---------|
| `mcp` | MCP server framework (FastMCP) |
| `playwright` | Headless browser automation for scraping |
| `beautifulsoup4` | HTML parsing |
| `python-dotenv` | Loading credentials from `.env` |

Maintenance

ActivityInactive
ResponsivenessNo issues