# Financial MCP Server - Complete Project Specification
## Project Overview
A production-ready Model Context Protocol (MCP) server that enables AI assistants (Claude Desktop, ChatGPT Desktop) to query financial data from three different sources. This demonstrates enterprise-grade AI integration patterns while maintaining data sovereignty.
**Repository**: https://github.com/Mindfreak00/financial-mcp-server
**Language**: TypeScript
**Framework**: MCP TypeScript SDK v1.0.4
**Transport**: stdio (standard input/output)
## Architecture Overview
### Three Data Integration Patterns
1. **Public API (Exchange Rates)** - No authentication required
- API: exchangerate-api.com
- Pattern: HTTP REST calls to public endpoint
- Use case: Any public data source
2. **Local Database (Transactions)** - CSV-based storage
- Database: In-memory loading from CSV files
- Pattern: Read-only data loaded at startup
- Use case: Simple, portable, human-readable data storage
3. **Authenticated API (Stock Market)** - Alpha Vantage with API key
- API: Alpha Vantage free tier
- Pattern: HTTP REST with API key authentication
- Use case: SaaS APIs, internal authenticated services
## Project Structure
```
financial-mcp-server/
├── package.json # Dependencies and npm scripts
├── tsconfig.json # TypeScript compiler configuration
├── .gitignore # Git ignore patterns
├── README.md # Complete user documentation
├── GITHUB_SETUP.md # GitHub setup instructions
├── setup-github.sh # Automated setup script
├── data/
│ ├── transactions.csv // Transaction data
│ └── budgets.csv // Budget data
└── src/
├── index.ts # Main MCP server entry point
├── types.ts # TypeScript type definitions
├── services/ # Data access layer
│ ├── exchangeRate.ts # Exchange rate API client
│ ├── stockData.ts # Stock market API client
│ └── database.ts # SQLite database service with sample data
└── tools/ # MCP tool implementations
├── exchangeRate.ts # 3 exchange rate tools
├── stockData.ts # 2 stock market tools
└── transactions.ts # 5 transaction query tools
```
## Dependencies
### Production Dependencies
```json
{
"@modelcontextprotocol/sdk": "^1.0.4", // MCP framework
"csv-parse": "^5.5.0", // CSV Parsing (if used) or native split
"zod": "^3.24.1" // Schema validation
}
```
### Dev Dependencies
```json
{
"@types/better-sqlite3": "^7.6.12",
"@types/node": "^22.10.1",
"typescript": "^5.7.2"
}
```
## Type Definitions (src/types.ts)
```typescript
export interface ExchangeRate {
base: string; // Source currency code (e.g., "EUR")
target: string; // Target currency code (e.g., "USD")
rate: number; // Exchange rate
timestamp: string; // ISO date string
}
export interface StockQuote {
symbol: string; // Stock ticker symbol
price: number; // Current price
change: number; // Price change
changePercent: number; // Percentage change
timestamp: string; // Trading day
}
export interface Transaction {
id: number;
date: string; // ISO date (YYYY-MM-DD)
description: string;
category: string; // Software, Hardware, Travel, Marketing
amount: number;
currency: string; // EUR, USD, GBP
vendor: string;
department: string; // Engineering, Sales, Marketing
}
export interface Budget {
id: number;
department: string;
category: string;
monthly_budget: number;
currency: string;
}
export interface SpendingSummary {
category: string;
total: number;
count: number;
currency: string;
}
```
## Service Layer
### 1. Exchange Rate Service (src/services/exchangeRate.ts)
**API Endpoint**: `https://api.exchangerate-api.com/v4/latest/{currency}`
**Methods**:
- `getRate(from: string, to: string)` - Get single exchange rate
- `convert(amount: number, from: string, to: string)` - Convert currency amount
- `getMultipleRates(base: string, targets: string[])` - Batch currency rates
**Error Handling**:
- Invalid currency codes
- API unavailability
- Network errors
**Example Response**:
```json
{
"base": "EUR",
"target": "USD",
"rate": 1.0847,
"timestamp": "2024-12-09"
}
```
### 2. Stock Data Service (src/services/stockData.ts)
**API Endpoint**: `https://www.alphavantage.co/query`
**Configuration**:
- Requires `ALPHA_VANTAGE_API_KEY` environment variable
- Free tier: 5 API calls per minute, 500 per day
- Function: `GLOBAL_QUOTE`
**Methods**:
- `isConfigured()` - Check if API key is set
- `getQuote(symbol: string)` - Get single stock quote
- `compareStocks(symbols: string[])` - Get multiple quotes (sequential with delays)
**Rate Limiting**:
- Sequential requests with 13-second delays between calls
- Graceful degradation if rate limit hit
**Error Handling**:
- Missing API key (helpful error message with setup instructions)
- Invalid stock symbols
- API rate limits
- Network errors
**Example Response**:
```json
{
"symbol": "AAPL",
"price": 195.71,
"change": 2.45,
"changePercent": 1.27,
"timestamp": "2024-12-09"
}
```
### 3. Transaction Database Service (src/services/database.ts)
**Database**: SQLite (better-sqlite3)
**Location**: `data/transactions.db` (auto-created)
**Schema**:
```sql
-- Transactions table
CREATE TABLE transactions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT NOT NULL,
description TEXT NOT NULL,
category TEXT NOT NULL,
amount REAL NOT NULL,
currency TEXT NOT NULL,
vendor TEXT NOT NULL,
department TEXT NOT NULL
);
-- Budgets table
CREATE TABLE budgets (
id INTEGER PRIMARY KEY AUTOINCREMENT,
department TEXT NOT NULL,
category TEXT NOT NULL,
monthly_budget REAL NOT NULL,
currency TEXT NOT NULL,
UNIQUE(department, category)
);
```
**Sample Data**:
- 23 transactions across Q4 2024 and Q1 2025
- 3 departments: Engineering, Sales, Marketing
- 4 categories: Software, Hardware, Travel, Marketing
- 6 budget entries
**Methods**:
- `queryTransactions(filters)` - Search with multiple filters
- `getSpendingByCategory(department?, startDate?, endDate?)` - Aggregate by category
- `getSpendingByDepartment(startDate?, endDate?)` - Aggregate by department
- `compareToBudget(department?)` - Compare actual vs budget
- `getTopVendors(limit, department?)` - Top vendors by spending
**Query Filters**:
```typescript
{
category?: string;
department?: string;
minAmount?: number;
maxAmount?: number;
startDate?: string; // YYYY-MM-DD
endDate?: string; // YYYY-MM-DD
vendor?: string; // Partial match
}
```
## MCP Tools Implementation
### Exchange Rate Tools (src/tools/exchangeRate.ts)
#### Tool 1: get_exchange_rate
```typescript
Input: {
from: string (3 chars, e.g., "EUR")
to: string (3 chars, e.g., "USD")
}
Output: {
base: "EUR",
target: "USD",
rate: 1.0847,
timestamp: "2024-12-09",
message: "1 EUR = 1.0847 USD"
}
```
#### Tool 2: convert_currency
```typescript
Input: {
amount: number (positive)
from: string (3 chars)
to: string (3 chars)
}
Output: {
original: { amount: 10000, currency: "EUR" },
converted: { amount: 10847, currency: "USD" },
rate: 1.0847,
message: "10000.00 EUR = 10847.00 USD"
}
```
#### Tool 3: get_multiple_rates
```typescript
Input: {
base: string (3 chars)
targets: string[] (1-10 items, 3 chars each)
}
Output: {
base: "EUR",
rates: [
{ currency: "USD", rate: 1.0847, conversion: "1 EUR = 1.0847 USD" },
{ currency: "GBP", rate: 0.8321, conversion: "1 EUR = 0.8321 GBP" }
],
timestamp: "2024-12-09"
}
```
### Stock Data Tools (src/tools/stockData.ts)
#### Tool 4: get_stock_quote
```typescript
Input: {
symbol: string (1-5 chars, e.g., "AAPL")
}
Output (with API key): {
symbol: "AAPL",
price: 195.71,
change: 2.45,
changePercent: 1.27,
timestamp: "2024-12-09",
summary: "AAPL: $195.71 (+1.27%)"
}
Output (without API key): {
error: "API key not configured",
message: "Alpha Vantage API key is required for stock data.",
instructions: [
"1. Get a free API key at: https://www.alphavantage.co/support/#api-key",
"2. Set the ALPHA_VANTAGE_API_KEY environment variable",
"3. Restart the MCP server"
]
}
```
#### Tool 5: compare_stocks
```typescript
Input: {
symbols: string[] (2-5 items)
}
Output: {
comparison: [
{
symbol: "AAPL",
price: 195.71,
change: 2.45,
changePercent: 1.27,
summary: "AAPL: $195.71 (+1.27%)"
},
{
symbol: "MSFT",
price: 378.91,
change: -1.23,
changePercent: -0.32,
summary: "MSFT: $378.91 (-0.32%)"
}
],
note?: "Some symbols failed to load due to API limits or invalid symbols"
}
```
### Transaction Tools (src/tools/transactions.ts)
#### Tool 6: query_transactions
```typescript
Input: {
category?: string;
department?: string;
minAmount?: number;
maxAmount?: number;
startDate?: string;
endDate?: string;
vendor?: string;
}
Output: {
count: 5,
totalAmount: "15890.00",
currency: "EUR",
transactions: Transaction[], // Max 50 results
note?: "Showing first 50 of 100 transactions"
}
```
#### Tool 7: get_spending_by_category
```typescript
Input: {
department?: string;
startDate?: string;
endDate?: string;
}
Output: {
totalSpending: "45230.00",
currency: "EUR",
breakdown: [
{
category: "Software",
total: "25890.00",
count: 12,
averageTransaction: "2157.50"
}
]
}
```
#### Tool 8: get_spending_by_department
```typescript
Input: {
startDate?: string;
endDate?: string;
}
Output: {
totalSpending: "68950.00",
currency: "EUR",
breakdown: [
{
department: "Engineering",
total: "32450.00",
count: 15,
averageTransaction: "2163.33"
}
]
}
```
#### Tool 9: compare_to_budget
```typescript
Input: {
department?: string;
}
Output: {
budgetAnalysis: [
{
department: "Engineering",
category: "Software",
budget: "8000.00",
actual: "8950.00",
remaining: "-950.00",
percentUsed: "111.9",
status: "OVER BUDGET" // or "WARNING" or "OK"
}
],
summary: {
overBudget: 2,
warning: 1,
ok: 3
}
}
```
#### Tool 10: get_top_vendors
```typescript
Input: {
limit?: number (1-20, default 10);
department?: string;
}
Output: {
totalSpending: "45230.00",
topVendors: [
{
rank: 1,
vendor: "Amazon Web Services",
total: "12450.00",
transactionCount: 5,
averageTransaction: "2490.00"
}
]
}
```
## Main Server (src/index.ts)
```typescript
#!/usr/bin/env node
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
// Initialize server
const server = new McpServer({
name: 'financial-mcp-server',
version: '1.0.0'
});
// Register all tools
registerExchangeRateTools(server);
registerStockDataTools(server);
registerTransactionTools(server);
// Start with stdio transport
const transport = new StdioServerTransport();
await server.connect(transport);
```
**Server Configuration**:
- Transport: stdio (standard input/output)
- Protocol: MCP (Model Context Protocol)
- Communication: JSON-RPC over stdio
**Tool Registration Pattern**:
```typescript
server.registerTool(
'tool_name',
{
title: 'Human-Readable Title',
description: 'Clear description of what the tool does',
inputSchema: {
param1: z.string().describe('Parameter description'),
param2: z.number().optional().describe('Optional parameter')
}
},
async (params) => {
// Implementation
const result = await service.method(params);
return {
content: [
{ type: 'text', text: JSON.stringify(result, null, 2) }
],
structuredContent: result // Modern MCP pattern
};
}
);
```
## Configuration Files
### package.json
```json
{
"name": "financial-mcp-server",
"version": "1.0.0",
"description": "MCP server for financial data",
"type": "module",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"watch": "tsc --watch",
"prepare": "npm run build"
},
"dependencies": { /* ... */ },
"devDependencies": { /* ... */ }
}
```
### tsconfig.json
```json
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
```
## Claude Desktop Configuration
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"financial-data": {
"command": "node",
"args": [
"/absolute/path/to/financial-mcp-server/dist/index.js"
],
"env": {
"ALPHA_VANTAGE_API_KEY": "optional_api_key_here"
}
}
}
}
```
## ChatGPT Desktop Configuration
**macOS**: `~/Library/Application Support/ChatGPT/config.json`
**Windows**: `%APPDATA%\ChatGPT\config.json`
Same format as Claude Desktop configuration.
## Error Handling
### Exchange Rate Service
- Network failures → "Failed to fetch exchange rates: [error]"
- Invalid currency → "Currency XXX not found"
- API errors → Pass through API error message
### Stock Data Service
- Missing API key → Friendly message with setup instructions
- Invalid symbol → "Invalid stock symbol: XXX"
- Rate limit → "API rate limit reached. Please try again in a minute."
- API errors → "No data available for symbol: XXX"
### Database Service
- All queries wrapped in try-catch
- SQL errors → "Failed to query transactions: [error]"
- Empty results → Return empty arrays with count: 0
- Database lock → Error message with suggestion to close other connections
### Tool-Level Error Handling
```typescript
try {
const result = await service.method(params);
return {
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
structuredContent: result
};
} catch (error) {
const errorMsg = error instanceof Error ? error.message : 'Unknown error';
throw new Error(`Failed to [action]: ${errorMsg}`);
}
```
## Sample Data
### Transactions (23 entries)
```
Q4 2024:
- Engineering: AWS ($2,450), GitHub ($950), JetBrains ($1,200), MacBook ($3,500), Azure ($1,800)
- Sales: Salesforce ($3,200), Flights ($280), Hotel ($450), LinkedIn ($890)
- Marketing: Adobe ($540), Google Ads ($5,000), Trade Show ($12,000), Hootsuite ($250)
Q1 2025:
- Engineering: AWS ($2,650), Datadog ($890), Monitors ($2,100), PagerDuty ($450)
- Sales: Salesforce ($3,200), Flight ($195), ZoomInfo ($750)
- Marketing: Mailchimp ($680), Facebook Ads ($4,500), Conference ($8,000)
```
### Budgets (6 entries)
```
Engineering:
- Software: €8,000/month
- Hardware: €5,000/month
Sales:
- Software: €5,000/month
- Travel: €2,000/month
Marketing:
- Software: €2,000/month
- Marketing: €15,000/month
```
## Build Process
```bash
# Install dependencies
npm install
# Build TypeScript to JavaScript
npm run build
# Output: dist/ folder with:
# - index.js (main entry)
# - types.js + types.d.ts
# - services/*.js + *.d.ts
# - tools/*.js + *.d.ts
```
## Testing
### Manual Testing Queries
**Exchange Rates (Instant):**
- "What's the EUR to USD exchange rate?"
- "Convert 10,000 EUR to USD and GBP"
- "Show me rates from EUR to USD, GBP, JPY, CHF"
**Transactions (Instant):**
- "What were our total expenses in Q4 2024?"
- "Show me all software purchases over €1,000"
- "Which department spent the most on travel?"
- "Are we over budget in any category?"
- "Who are our top 5 vendors by spending?"
**Stocks (Requires API key):**
- "What's Apple's current stock price?"
- "Compare Microsoft, Google, and Apple stock prices"
**Combined:**
- "Show our cloud expenses and convert them to USD"
- "What did we spend on software, and what's Microsoft's stock price?"
## Security Considerations
1. **Data Sovereignty**: All data stays on user's infrastructure
2. **API Keys**: Environment variables, never hardcoded
3. **Database**: Local SQLite, no external connections
4. **Read-Only**: All tools are read-only (no destructive operations)
5. **Input Validation**: Zod schemas validate all inputs
6. **Error Messages**: Never expose sensitive information
## Performance
- **Exchange Rates**: <1 second (network latency)
- **Database Queries**: <100ms (SQLite is very fast)
- **Stock Quotes**: 1-2 seconds per symbol (API latency)
- **Memory**: ~50MB (includes Node.js runtime)
- **Startup**: <1 second
## Extensibility
### Adding New Data Sources
1. Create service in `src/services/`
2. Create tool implementations in `src/tools/`
3. Register tools in `src/index.ts`
4. Update README with new tools
### Replacing SQLite with PostgreSQL
1. Replace `better-sqlite3` with `pg`
2. Update `src/services/database.ts` with connection pool
3. Adjust SQL queries for PostgreSQL syntax
4. Add connection string to environment variables
### Adding Authentication
1. Create auth service in `src/services/`
2. Add auth check middleware to tool handlers
3. Store credentials securely (not in code)
4. Add user context to database queries
## Git Repository Status
- Repository initialized
- All files committed (14 files, 1,651 lines)
- Branch: main
- Remote: https://github.com/Mindfreak00/financial-mcp-server.git
- Status: Ready to push
## Key Files Line Counts
```
src/index.ts 26 lines
src/types.ts 39 lines
src/services/exchangeRate.ts 73 lines
src/services/stockData.ts 98 lines
src/services/database.ts 266 lines
src/tools/exchangeRate.ts 138 lines
src/tools/stockData.ts 114 lines
src/tools/transactions.ts 214 lines
README.md 400+ lines
Total: 1,651 lines
```
## Success Criteria
✅ Builds without errors
✅ All 10 tools register correctly
✅ Exchange rate tools work instantly
✅ Transaction database queries work instantly
✅ Stock tools show helpful message if no API key
✅ Stock tools work correctly with API key
✅ Works identically in Claude and ChatGPT Desktop
✅ Documentation is complete and accurate
✅ Sample queries all work as expected
✅ Error messages are helpful and actionable
## Future Enhancements (Not Implemented)
- Web-based UI for testing tools
- Additional data sources (crypto, forex, commodities)
- Historical data analysis tools
- Data visualization capabilities
- Multi-user support with authentication
- Webhook notifications for price alerts
- Integration with accounting software
- Export capabilities (CSV, PDF, Excel)
---
## Implementation Notes for Claude Code
When implementing this project:
1. **Start with types.ts** - Foundation for type safety
2. **Build services layer** - Data access before tools
3. **Implement tools** - One data source at a time
4. **Test incrementally** - Verify each service works before moving on
5. **Follow MCP patterns** - Use `registerTool()` consistently
6. **Handle errors properly** - User-friendly messages at every layer
7. **Document as you go** - Clear comments for complex logic
The project follows a clean architecture:
- **Types**: Shared interfaces
- **Services**: Data access logic
- **Tools**: MCP tool implementations
- **Index**: Server initialization and tool registration
Each layer is independent and testable.