Skip to main content
Glama

Investment Statement MCP Server

PROJECT_SUMMARY.md7.84 kB
# Investment Statement MCP Server - Project Summary ## Overview A production-ready MCP (Model Context Protocol) server for parsing and querying investment statements using natural language and structured queries. ## ✅ Completed Features ### Core Infrastructure - ✅ FastMCP 2.0 server with Python - ✅ Dual-database architecture (SQLite + LanceDB) - ✅ Hybrid archival system (PDFs + JSON) - ✅ Sentence-transformers embeddings for semantic search ### Questrade Parser - ✅ Account summary extraction (balances, FX rates, TFSA info) - ✅ Holdings/positions parsing (symbols, quantities, P/L, returns) - ✅ Transaction history extraction (trades, dividends, deposits) - ✅ Multi-currency support (CAD/USD) ### MCP Resources (Read-Only Data) - ✅ `statements://catalog` - List all statements - ✅ `statements://{id}` - Get specific statement - ✅ `statements://{id}/summary` - Get account summary ### MCP Tools (Active Operations) - ✅ `index_statement(file_path)` - Index new PDF - ✅ `reindex_statement(statement_id)` - Reindex existing - ✅ `get_indexing_stats()` - Get statistics - ✅ `search_statements(query, limit)` - Natural language search - ✅ `get_holdings_by_symbol(symbol)` - Query by symbol - ✅ `get_transactions_by_date_range(start, end)` - Query by date - ✅ `get_account_balance(account, date)` - Get balance at date ### Storage - ✅ SQLite for structured data (statements, holdings, transactions) - ✅ LanceDB for vector search - ✅ Automatic PDF archiving - ✅ JSON export for each statement ### Documentation - ✅ README with installation and features - ✅ USAGE guide with examples - ✅ Example scripts - ✅ Test files ## Project Structure ``` investing-mcp/ ├── src/ │ ├── server.py # Main MCP server (FastMCP) │ ├── database/ │ │ ├── schemas.py # Pydantic models │ │ ├── sqlite_client.py # SQLite async client │ │ └── lancedb_client.py # Vector database client │ ├── embeddings/ │ │ └── generator.py # Sentence-transformers │ ├── parsers/ │ │ └── questrade_parser.py # Questrade PDF parser │ ├── tools/ │ │ ├── indexing.py # Indexing tools │ │ ├── search.py # Semantic search │ │ └── query.py # Structured queries │ └── resources/ │ └── catalog.py # MCP resources ├── tests/ │ └── test_questrade_parser.py # Parser tests ├── examples/ │ └── index_and_query.py # Example usage ├── data/ # Created on first run │ ├── pdfs/ # PDF archive │ ├── json/ # JSON archive │ ├── statements.db # SQLite database │ └── lancedb/ # Vector database ├── pyproject.toml # Dependencies ├── .mcp.json # MCP configuration ├── README.md # Main documentation └── USAGE.md # Usage guide ``` ## Technology Stack | Component | Technology | Purpose | |-----------|------------|---------| | MCP Framework | FastMCP 2.0 | Server implementation | | PDF Parsing | pymupdf4llm | Extract text from PDFs | | Vector DB | LanceDB | Semantic search | | Structured DB | SQLite (aiosqlite) | Metadata & queries | | Embeddings | sentence-transformers | Text → vectors | | Validation | Pydantic | Data models | | Testing | pytest | Unit tests | ## Key Design Decisions ### 1. Hybrid Storage - **SQLite**: Fast structured queries (by date, symbol, account) - **LanceDB**: Semantic search with natural language - **Archives**: Original PDFs + parsed JSON for auditing ### 2. Extensible Parser Architecture - Base parser interface - Institution-specific implementations - Easy to add Interactive Brokers, Scotia, etc. ### 3. Both Natural Language & Structured Queries - Natural language for exploratory queries - Structured queries for precise data retrieval - Best of both worlds ### 4. Async-First Design - All database operations are async - Scalable for large statement collections - Concurrent processing support ## Sample Usage ### Indexing ```python # Via MCP tool result = await index_statement("/path/to/statement.pdf") # → {status: "success", statement_id: "questrade_abc123", ...} ``` ### Natural Language Search ``` "What were my dividends in Q3 2025?" "Show me all SPY holdings" "When did I deposit money?" ``` ### Structured Queries ```python # Track position over time holdings = await get_holdings_by_symbol("SPY") # Get transactions in date range txns = await get_transactions_by_date_range("2025-01-01", "2025-12-31") # Get balance at specific date balance = await get_account_balance("51516162", "2025-09-30") ``` ## Testing Run the example script: ```bash python examples/index_and_query.py ``` Run pytest: ```bash pytest tests/ -v ``` ## Integration with Claude Desktop Add to `~/Library/Application Support/Claude/claude_desktop_config.json`: ```json { "mcpServers": { "investment-statements": { "command": "python", "args": ["-m", "src.server"], "cwd": "/Users/jasonlo/Repos/AI/investing-mcp", "env": { "LANCEDB_PATH": "./data/lancedb", "SQLITE_PATH": "./data/statements.db", "PDF_ARCHIVE_PATH": "./data/pdfs", "JSON_ARCHIVE_PATH": "./data/json", "MODEL_NAME": "all-MiniLM-L6-v2" } } } } ``` ## Future Enhancements ### Near-Term (High Priority) 1. **Interactive Brokers Parser** - Most requested institution 2. **Scotia Parser** - Common Canadian institution 3. **Better Table Extraction** - Use pdfplumber for complex tables 4. **Performance Metrics** - Track portfolio performance over time ### Medium-Term 5. **Tax Reporting** - Generate tax summaries 6. **Export Features** - Export to CSV/Excel 7. **Multi-Account Aggregation** - Cross-account views 8. **Chart Generation** - Visualize holdings and performance ### Long-Term 9. **Web UI** - Browse statements in browser 10. **API Server** - REST API for external integrations 11. **Real-time Updates** - Auto-import from brokers 12. **Mobile App** - iOS/Android support ## Notes for Future Developers ### Adding a New Institution 1. Create parser in `src/parsers/{institution}_parser.py` 2. Inherit from base parser pattern 3. Implement `parse()` method returning `Statement` 4. Add institution detection in `indexing.py` 5. Add tests in `tests/test_{institution}_parser.py` ### Improving PDF Extraction Current parser uses pymupdf4llm + regex. Consider: - **pdfplumber** for tables - **camelot** for complex layouts - **tabula-py** for statement tables - **LLM-based extraction** for unstructured text ### Scaling Considerations - SQLite supports ~1M transactions easily - LanceDB scales to billions of vectors - For >10K statements, consider PostgreSQL - For production, add connection pooling ## Installation & Deployment ### Development ```bash git clone <repo> cd investing-mcp pip install -e ".[dev]" python examples/index_and_query.py ``` ### Production ```bash pip install -e . python -m src.server ``` ### Docker (Future) ```bash docker build -t investing-mcp . docker run -v ./data:/app/data investing-mcp ``` ## Performance Benchmarks Based on sample Questrade statement: - **PDF Parsing**: ~0.5-1.0s per statement - **Embedding Generation**: ~0.1-0.2s per chunk - **SQLite Insert**: ~10ms per statement - **LanceDB Insert**: ~50ms for all chunks - **Semantic Search**: ~50-100ms per query - **Structured Query**: ~1-10ms per query Total indexing time: **~1-2 seconds per statement** ## License MIT ## Author Jason Lo ## Last Updated 2025-11-16

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/VinnyCarter05/investing-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server