Asynchronous Financial Modeling Prep API Client with MCP Server
Project description
aiofmp
aiofmp is a comprehensive Python SDK that provides seamless access to the Financial Modeling Prep API through an intuitive, category-based interface. Built with asyncio for high-performance concurrent operations, it offers:
- Complete FMP API Coverage: Access to 22+ API categories including financial statements, market data, news, technical indicators, and more
- Async-First Design: Built with asyncio for high-performance concurrent operations and non-blocking I/O
- MCP Server Integration: Built-in Model Context Protocol server that exposes all FMP APIs as AI-friendly tools
- Type Safety: Full type hints throughout the codebase for better IDE support and error prevention
- Clean Architecture: Category-based organization that mirrors the FMP API structure
- Comprehensive Error Handling: Robust error handling with custom exceptions and retry logic
- Rate Limiting: Built-in rate limiting and retry logic to respect API limits
- AI-Ready: MCP tools designed specifically for AI assistants with natural language prompts
- CachedClient: Intelligent caching wrapper that stores time-series data locally and only fetches missing date ranges from the API
Key Features
- 22 API Categories: Complete coverage of all FMP API endpoints
- Flexible Configuration: Environment-based configuration for easy deployment
- 160+ MCP Tools: Every FMP API function exposed as an MCP tool for AI assistants
- Dual Transport Support: Both STDIO and HTTP transport modes for MCP server
- Comprehensive Testing: Full test coverage with 500+ unit tests
- Production Ready: Built for reliability and performance in production environments
Installation
Prerequisites
- Python 3.10 or higher
- Financial Modeling Prep API key (Get one here)
Install from Source
# Clone the repository
git clone https://github.com/your-username/aiofmp.git
cd aiofmp
# Install dependencies using uv (recommended)
uv sync
# Install the package in development mode
uv pip install -e .
# Or using pip
pip install -e .
# Activate virtual environment (if using uv)
source .venv/bin/activate # On Windows: .venv\Scripts\activate
Usage
Basic Client Usage
import asyncio
from aiofmp import FmpClient
async def main():
# Initialize client with your API key
client = FmpClient(api_key="your_api_key_here")
# Use async context manager for automatic session management
async with client:
# Search for symbols
symbols = await client.search.symbols("AAPL", limit=10)
print(f"Found {len(symbols)} symbols")
# Get company profile
profile = await client.company.profile("AAPL")
print(f"Company: {profile['companyName']}")
# Get financial statements
income_statement = await client.statements.income_statement("AAPL", limit=5)
print(f"Retrieved {len(income_statement)} periods of income statement data")
# Run the example
asyncio.run(main())
CachedClient Usage
The CachedClient wraps FmpClient with an intelligent caching layer. It intercepts time-series API calls, stores data locally in Parquet files, and only fetches missing date ranges from the FMP API on subsequent calls. This dramatically reduces API usage when working with historical data.
By default, data is cached under ~/.aiofmp/cache. Override the location with the AIOFMP_CACHE_FILE_PATH environment variable.
import asyncio
from aiofmp import FmpClient
from aiofmp.cachedclient import CachedClient
async def main():
fmp = FmpClient(api_key="your_api_key_here")
cached = CachedClient(fmp) # caches to ~/.aiofmp/cache by default
async with cached:
# First call: fetches from FMP API, stores locally in Parquet
data = await cached.chart.historical_price_full("AAPL", "2020-01-01", "2023-12-31")
print(f"Fetched {len(data)} records")
# Second call: extends the range — only fetches the 2024 gap from the API
data = await cached.chart.historical_price_full("AAPL", "2020-01-01", "2025-01-01")
print(f"Got {len(data)} records (2020-2023 from cache, 2024+ from API)")
# Repeated call with same range: fully served from cache, zero API calls
data = await cached.chart.historical_price_full("AAPL", "2020-01-01", "2025-01-01")
# Financial statements: merges fresh data with stored history
stmts = await cached.statements.income_statement("AAPL", limit=5, period="annual")
# Non-cacheable endpoints pass through unchanged
profile = await cached.company.profile("AAPL")
asyncio.run(main())
Supported caching patterns:
- Date-range endpoints (chart, economics, calendar, news, technical indicators, etc.): gap detection fetches only the missing date ranges
- Period-based endpoints (income statements, balance sheets, ratios, etc.): fetches fresh data and merges with stored historical records
- Non-cacheable endpoints (profiles, quotes, search, etc.): pass through directly to the FMP API
Storage is pluggable — ParquetStorage is the built-in default, but you can pass any StorageBackend subclass to CachedClient(fmp, storage=my_storage).
MCP Server Usage
The aiofmp package includes a built-in MCP server that exposes all FMP APIs as AI-friendly tools.
Configuration
Set up environment variables for MCP server configuration:
# Required: FMP API Key
export FMP_API_KEY="your_api_key_here"
# Optional: MCP Server Configuration
export MCP_TRANSPORT="stdio" # or "http"
export MCP_HOST="localhost" # for HTTP transport
export MCP_PORT="3000" # for HTTP transport
export MCP_LOG_LEVEL="INFO" # DEBUG, INFO, WARNING, ERROR
Running the MCP Server
STDIO Transport (for MCP clients like Claude Desktop):
aiofmp-mcp-server
HTTP Transport (for web-based MCP clients):
aiofmp-mcp-server --transport http
Custom Configuration:
aiofmp-mcp-server --transport http --host 0.0.0.0 --port 8080
With API Key:
aiofmp-mcp-server --api-key your_api_key_here
With Debug Logging:
aiofmp-mcp-server --log-level DEBUG
Include text content alongside structured content:
aiofmp-mcp-server --text-content
Enable local caching of time-series data:
aiofmp-mcp-server --cached
When --cached is enabled, the MCP server uses CachedClient under the hood. Time-series API calls are cached locally in Parquet files so repeated queries for the same historical data don't consume API quota. Cache directory defaults to ~/.aiofmp/cache (override with AIOFMP_CACHE_FILE_PATH).
Claude Desktop Integration
Add to your Claude Desktop configuration (claude_desktop_config.json):
{
"mcpServers": {
"aiofmp": {
"command": "aiofmp-mcp-server",
"args": ["--api-key", "your_api_key_here"]
}
}
}
Alternative with environment variable:
{
"mcpServers": {
"aiofmp": {
"command": "aiofmp-mcp-server",
"env": {
"FMP_API_KEY": "your_api_key_here"
}
}
}
}
CLI Reference
The aiofmp-mcp-server command provides a user-friendly interface for running the MCP server:
# Basic usage
aiofmp-mcp-server
# Show help
aiofmp-mcp-server --help
# HTTP transport
aiofmp-mcp-server --transport http --host 0.0.0.0 --port 8080
# With API key
aiofmp-mcp-server --api-key your_api_key_here
# Debug logging
aiofmp-mcp-server --log-level DEBUG
# Include text content alongside structured content
aiofmp-mcp-server --text-content
# Enable local caching
aiofmp-mcp-server --cached
# All options
aiofmp-mcp-server --transport http --host localhost --port 3000 --log-level INFO --api-key your_key --text-content --cached
Command Options:
--transport: Transport mode (stdioorhttp, default:stdio)--host: Host for HTTP transport (default:localhost)--port: Port for HTTP transport (default:3000)--log-level: Logging level (DEBUG,INFO,WARNING,ERROR, default:INFO)--api-key: FMP API key (can also be set viaFMP_API_KEYenvironment variable)--text-content: Include text content alongside structured content in MCP tool responses (default: text content is empty when structured content is present)--cached: Enable CachedClient to cache time-series data locally in Parquet files, minimizing API calls (default: off). Cache dir:~/.aiofmp/cache(override withAIOFMP_CACHE_FILE_PATH)
Available API Categories
The aiofmp client provides access to 22+ FMP API categories:
- Analyst: Financial estimates, ratings, price targets, and analyst recommendations
- Calendar: Earnings, dividends, IPOs, and economic events
- Chart: Historical price data and technical analysis
- Company: Company profiles, key metrics, and corporate information
- Commodity: Commodity prices, quotes, and historical data
- COT: Commitment of Traders reports for commodities
- Crypto: Cryptocurrency prices, quotes, and market data
- DCF: Discounted Cash Flow valuations and analysis
- Directory: Symbol lists, exchanges, sectors, and reference data
- Economics: Economic indicators, treasury rates, and macro data
- ETF: ETF holdings, performance, and analysis
- Forex: Foreign exchange rates and currency data
- Form 13F: Institutional holdings and filings
- Indexes: Stock market indices and performance
- Insider Trades: Insider trading activity and statistics
- Market Performance: Sector performance, market movers, and P/E ratios
- News: Financial news, press releases, and market updates
- Quote: Real-time quotes, price changes, and market data
- Search: Symbol search, company search, and stock screening
- Senate: Congressional trading disclosures and activity
- Statements: Financial statements, ratios, and metrics
- Technical Indicators: Moving averages, RSI, and technical analysis tools
Examples
Client Examples
The examples/ directory contains comprehensive examples for each API category:
# Run specific examples
python examples/fmp_search_example.py
python examples/fmp_company_example.py
python examples/fmp_statements_example.py
python examples/fmp_cachedclient_example.py
MCP Server Examples
Example 1: Basic MCP Tool Usage
# These are example prompts that would be sent to an AI assistant using the MCP server
"What is the current stock quote for Apple (AAPL)?"
"Show me the 20-day Simple Moving Average for Microsoft (MSFT)"
"Get the latest financial statements for Tesla (TSLA)"
Example 2: Advanced Financial Analysis
# Complex analysis prompts
"Compare the P/E ratios of Apple, Microsoft, and Google over the past year"
"Find all technology stocks with market cap over $100 billion"
"Show me the insider trading activity for Tesla in the last 3 months"
Example 3: Market Research
# Market research prompts
"What are the biggest gainers in the market today?"
"Show me the sector performance for the technology sector"
"Get the latest earnings calendar for next week"
Example Files
fmp_cachedclient_example.py- CachedClient caching wrapperfmp_analyst_example.py- Analyst estimates and ratingsfmp_calendar_example.py- Earnings and dividend calendarsfmp_chart_example.py- Historical price datafmp_company_example.py- Company profiles and metricsfmp_commodity_example.py- Commodity prices and datafmp_cot_example.py- Commitment of Traders reportsfmp_crypto_example.py- Cryptocurrency datafmp_dcf_example.py- DCF valuationsfmp_directory_example.py- Symbol lists and reference datafmp_economics_example.py- Economic indicatorsfmp_etf_example.py- ETF analysisfmp_forex_example.py- Foreign exchange datafmp_form13f_example.py- Institutional holdingsfmp_indexes_example.py- Market indicesfmp_insider_trades_example.py- Insider tradingfmp_search_example.py- Symbol and company searchfmp_statements_example.py- Financial statements
MCP Server Testing
Test the MCP server functionality:
# Run all MCP tests
uv run pytest tests/test_mcp_tools.py tests/test_mcp_server.py -v
# Run specific category tests
uv run pytest tests/test_mcp_tools.py::TestSearchTools -v
uv run pytest tests/test_mcp_server.py::TestMCPServer -v
# Test with debug logging
aiofmp-mcp-server --log-level DEBUG
Harvester
aiofmp harvest is a long-running CLI that proactively warms the local Parquet cache. It runs one async task per enabled category, each on its own configurable interval, and uses category-specific strategies to minimise redundant fetches (target: stay under 20 GB/month on FMP starter plan).
Quick start:
cp examples/harvester.example.yaml ~/harvester.yaml
export FMP_API_KEY=your_key_here
# Print the plan, fetch nothing
aiofmp harvest --config ~/harvester.yaml --dry-run
# One cycle per enabled category, then exit
aiofmp harvest --config ~/harvester.yaml --once
# Run a single category once
aiofmp harvest --config ~/harvester.yaml --once --category statements
# Run forever (Ctrl-C to stop cleanly)
aiofmp harvest --config ~/harvester.yaml
# Inspect state
aiofmp harvest-status --config ~/harvester.yaml
State: SQLite at <state_dir>/harvester.sqlite (checkpoints, bandwidth ledger, symbol catalogs). Parquet under <state_dir>/cachedclient_data/.
See docs/superpowers/specs/2026-05-15-harvester-v2-design.md for the full design.
Configuration
Environment Variables
| Variable | Description | Default | Required |
|---|---|---|---|
FMP_API_KEY |
Financial Modeling Prep API key | None | Yes |
MCP_TRANSPORT |
MCP server transport mode | stdio |
No |
MCP_HOST |
MCP server host (HTTP mode) | localhost |
No |
MCP_PORT |
MCP server port (HTTP mode) | 3000 |
No |
MCP_LOG_LEVEL |
Logging level | INFO |
No |
AIOFMP_CACHED |
Enable CachedClient (true/false) |
false |
No |
AIOFMP_CACHE_FILE_PATH |
Cache directory for Parquet files | ~/.aiofmp/cache |
No |
MCP Server Modes
STDIO Mode (Default):
- Used by MCP clients like Claude Desktop
- Communicates via standard input/output
- No network configuration required
HTTP Mode:
- Used by web-based MCP clients
- Requires host and port configuration
- Supports multiple concurrent connections
API Reference
Client Categories
Each API category provides methods that mirror the FMP API structure:
# Search and discovery
await client.search.symbols("AAPL")
await client.search.companies("Apple")
await client.search.screener(sector="Technology")
# Company information
await client.company.profile("AAPL")
await client.company.key_metrics("AAPL")
# Financial statements
await client.statements.income_statement("AAPL")
await client.statements.balance_sheet("AAPL")
await client.statements.cash_flow_statement("AAPL")
# Market data
await client.quote.stock_quote("AAPL")
await client.chart.historical_price_full("AAPL")
# Technical analysis
await client.technical_indicators.simple_moving_average("AAPL", 20, "1day")
await client.technical_indicators.relative_strength_index("AAPL", 14, "1day")
MCP Tools
The MCP server exposes 160+ tools across all categories. Each tool includes:
- Detailed descriptions and parameter documentation
- Natural language examples for AI assistants
- Comprehensive error handling
- Type validation and parameter checking
Error Handling
The client includes comprehensive error handling:
from aiofmp.exceptions import FmpError, FmpRateLimitError, FmpAPIError
try:
data = await client.search.symbols("INVALID")
except FmpAPIError as e:
print(f"API Error: {e}")
except FmpRateLimitError as e:
print(f"Rate limit exceeded: {e}")
except FmpError as e:
print(f"General error: {e}")
Testing
Run the comprehensive test suite:
# Run all tests
uv run pytest
# Run specific test categories
uv run pytest tests/test_search.py -v
uv run pytest tests/test_mcp_tools.py -v
# Run with coverage
uv run pytest --cov=aiofmp --cov-report=html
Performance
- Async Operations: All API calls are non-blocking
- Connection Pooling: Efficient HTTP connection management
- Rate Limiting: Built-in rate limiting to respect API limits
- CachedClient: Intelligent time-series caching with gap detection — only fetches missing data from the API
- Concurrent Requests: Support for multiple simultaneous API calls
Security
- API Key Management: Secure handling of API keys
- Environment Variables: Support for environment-based configuration
- No Hardcoded Secrets: All sensitive data via configuration
- HTTPS Only: All API communications over secure connections
Release Process
This project uses Semantic Release for automated versioning and publishing. The release process is fully automated through GitHub Actions.
How It Works
- Conventional Commits: All commits must follow the Conventional Commits specification
- Automatic Versioning: Semantic Release analyzes commit messages to determine the next version
- Automatic Publishing: When a new version is detected, it automatically:
- Creates a git tag
- Updates the CHANGELOG.md
- Publishes to PyPI
- Creates a GitHub release
Commit Message Format
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featuresfix: Bug fixesdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoringperf: Performance improvementstest: Test additions or changeschore: Build process or auxiliary tool changes
Examples:
feat(mcp): add new search tools for financial data
fix(api): resolve authentication error in client
docs: update installation instructions
test: add unit tests for MCP server
chore: update dependencies
Setting Up Releases
-
Configure Git (run once):
./scripts/setup-git.sh
-
Set up PyPI Token:
- Go to PyPI Account Settings
- Create an API token
- Add it to GitHub Secrets as
PYPI_API_TOKEN
-
Update Repository URLs:
- Update URLs in
pyproject.toml - Update author information
- Make Changes and Commit:
git add . git commit -m "feat: add new feature" git push origin main
The GitHub Action will automatically:
- Run quick tests and linting
- Check code quality
- Determine if a release is needed
- Create a new version and publish to PyPI
Manual Testing
For comprehensive testing, you can manually trigger the test workflow:
- Go to the "Actions" tab in your GitHub repository
- Select the "Test" workflow
- Click "Run workflow"
- Choose:
- Python version: 3.10, 3.11, 3.12, or 3.13
- Test type: all, unit, mcp, or integration
- Click "Run workflow"
This allows you to run tests on specific Python versions or test categories without using your free tier minutes unnecessarily.
Contributing
Contributions are welcome! We appreciate any help in improving aiofmp.
Development Setup
# Clone and setup development environment
git clone https://github.com/your-username/aiofmp.git
cd aiofmp
uv sync --dev
# Install pre-commit hooks
pre-commit install
# Run tests
uv run pytest
# Run linting
uv run ruff check .
uv run ruff format .
Contribution Guidelines
- Fork the repository and create a feature branch
- Follow the coding standards (type hints, docstrings, error handling)
- Add comprehensive tests for new functionality
- Update documentation for any API changes
- Ensure all tests pass before submitting a PR
- Use conventional commits for commit messages
Areas for Contribution
- New API Endpoints: Add support for new FMP API endpoints
- Performance Improvements: Optimize existing functionality
- Documentation: Improve examples and documentation
- Testing: Add more comprehensive test coverage
- MCP Tools: Enhance MCP tool descriptions and examples
- Error Handling: Improve error messages and handling
Reporting Issues
Please report bugs and request features through GitHub Issues. Include:
- Python version and operating system
- Steps to reproduce the issue
- Expected vs actual behavior
- Relevant error messages and logs
License
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
Acknowledgments
- Financial Modeling Prep for providing the comprehensive financial data API
- FastMCP for the MCP server framework
- The Python asyncio community for excellent async programming tools
Support
- Documentation: Check the examples directory and inline docstrings
- Issues: Report bugs and request features via GitHub Issues
- Discussions: Use GitHub Discussions for questions and community support
- API Reference: Full API documentation available in the code
Built with ❤️ for the financial data community
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aiofmp-1.2.0.tar.gz.
File metadata
- Download URL: aiofmp-1.2.0.tar.gz
- Upload date:
- Size: 488.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fa25e4082281f8885a5cc4f34951294fae1834cc4a6a2dbfb293c46430fe19a
|
|
| MD5 |
f8a6c204e282edf2f2a2c9520fea6860
|
|
| BLAKE2b-256 |
f423a70b7f956d1d08906d84c1a99fbdd60b6732106e27da2fc36f4ab361dbab
|
File details
Details for the file aiofmp-1.2.0-py3-none-any.whl.
File metadata
- Download URL: aiofmp-1.2.0-py3-none-any.whl
- Upload date:
- Size: 164.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
905e68e5f207eb1718157794e3dd8d84eda26e2aec72541e0d59d92829d0360b
|
|
| MD5 |
98733906879fb44c323a12ad59a6d777
|
|
| BLAKE2b-256 |
cb23b65be5eb179cffc606af7ea3b4712149205aab411816e3bad1f78b7262b4
|