Skip to content
Draft
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
7 changes: 7 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ uv run tally explain -c monthly /path/to/config # Explain all monthly merchan
uv run tally diag /path/to/config # Debug config issues
uv run tally discover /path/to/config # Find unknown merchants
uv run tally inspect file.csv # Analyze CSV structure
uv run tally mcp # Start MCP server (stdio)
uv run tally mcp init # Auto-configure MCP client
uv run tally mcp init --client claude-code # Configure for Claude Code
uv run tally mcp init --json # Output JSON config
uv run pytest tests/ # Run all tests
uv run pytest tests/test_analyzer.py -v # Run analyzer tests
```
Expand Down Expand Up @@ -47,7 +51,10 @@ Netflix → Monthly
- `src/tally/config_loader.py` - Settings loading, migration logic
- `src/tally/format_parser.py` - CSV format string parsing
- `src/tally/merchant_utils.py` - Merchant normalization, rule matching
- `src/tally/mcp_server.py` - MCP server with 8 tools for AI integration
- `src/tally/mcp_init.py` - MCP client setup for various AI tools
- `tests/test_analyzer.py` - Main test file for new features
- `tests/test_mcp.py` - Tests for MCP server tools
- `docs/` - Marketing website (GitHub Pages)
- `config/` - Example configuration files

Expand Down
58 changes: 57 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**A local rule engine for transaction classification.** Pair it with an LLM to eliminate the manual work.

Works with Claude Code, Codex, Copilot, Cursor, or a local model.
Works with Claude Code, Codex, Copilot, Cursor, or a local model. Also available as an [MCP server](#mcp-server) for Claude Desktop, VS Code, and other AI tools.

👉 **[Website](https://tallyai.money)** · **[Releases](https://github.com/davidfowl/tally/releases)**

Expand Down Expand Up @@ -42,6 +42,8 @@ tally run # Generate spending report
| `tally diag` | Debug config issues |
| `tally version` | Show version and check for updates |
| `tally update` | Update to latest version |
| `tally mcp` | Start MCP server for AI tool integration |
| `tally mcp init` | Configure MCP client (Claude Desktop, VS Code, etc.) |

### Output Formats

Expand All @@ -66,6 +68,60 @@ tally explain --classification monthly # Explain all monthly merchant
tally explain --category Subscriptions # Explain all subscriptions
```

## MCP Server

Tally includes an MCP (Model Context Protocol) server for direct integration with AI tools like Claude Desktop, VS Code, Cursor, and more.

### Quick Setup

```bash
tally mcp init # Auto-detect and configure your AI tool
tally mcp init --client claude-desktop # Or specify a client
tally mcp init --json # Output config JSON for manual setup
```

### Supported Clients

| Client | Setup Command |
|--------|--------------|
| Claude Desktop | `tally mcp init --client claude-desktop` |
| VS Code | `tally mcp init --client vscode` |
| Cursor | `tally mcp init --client cursor` |
| Claude Code | `tally mcp init --client claude-code` |
| OpenCode | `tally mcp init --client opencode` |
| Gemini CLI | `tally mcp init --client gemini` |

### Available Tools

Once configured, your AI assistant can use these tools:

| Tool | Description |
|------|-------------|
| `run_analysis` | Analyze spending and generate reports (JSON/markdown) |
| `explain_merchant` | Explain why a merchant is classified a certain way |
| `explain_summary` | Get classification summary for all merchants |
| `discover_unknown` | Find uncategorized merchants with suggested rules |
| `inspect_csv` | Analyze CSV structure for format string creation |
| `diagnose_config` | Debug configuration issues |
| `list_rules` | List all merchant categorization rules |
| `add_rule` | Add a new merchant categorization rule |
| `get_version` | Get tally version information |

### Manual Configuration

If auto-setup doesn't work, add this to your MCP config:

```json
{
"mcpServers": {
"tally": {
"command": "tally",
"args": ["mcp"]
}
}
}
```

## Configuration

### settings.yaml
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ classifiers = [
]
dependencies = [
"pyyaml>=6.0",
"mcp>=1.2.0",
]

[project.scripts]
Expand All @@ -30,6 +31,7 @@ tally = "tally.cli:main"
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"pytest-asyncio>=0.23.0",
]
build = [
"pyinstaller>=6.0",
Expand Down
33 changes: 33 additions & 0 deletions src/tally/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2438,6 +2438,31 @@ def main():
help='Skip confirmation prompts for asset updates'
)

# mcp subcommand
mcp_parser = subparsers.add_parser(
'mcp',
help='Start MCP server or configure MCP clients',
description='Run tally as an MCP (Model Context Protocol) server for integration with Claude Desktop, VS Code, and other AI tools.'
)
mcp_subparsers = mcp_parser.add_subparsers(dest='mcp_command')

# mcp init subcommand
mcp_init_parser = mcp_subparsers.add_parser(
'init',
help='Configure MCP client to use tally',
description='Set up tally MCP server on Claude Desktop, VS Code, Cursor, or other clients.'
)
mcp_init_parser.add_argument(
'--client',
choices=['claude-desktop', 'vscode', 'cursor', 'claude-code', 'opencode', 'gemini'],
help='Specific client to configure (default: auto-detect)'
)
mcp_init_parser.add_argument(
'--json',
action='store_true',
help='Output JSON config for manual setup'
)

args = parser.parse_args()

# If no command specified, show help with banner
Expand Down Expand Up @@ -2480,6 +2505,14 @@ def main():
print(f" Run 'tally update' to install")
elif args.command == 'update':
cmd_update(args)
elif args.command == 'mcp':
if args.mcp_command == 'init':
from .mcp_init import run_mcp_init
run_mcp_init(client=args.client, output_json=args.json)
else:
# No subcommand - run MCP server
from .mcp_server import run_server
run_server()


if __name__ == '__main__':
Expand Down
Loading