alpha-ventage-mcp
Version:
A Model Context Protocol (MCP) server for Alpha Vantage financial data API
357 lines (339 loc) • 9.54 kB
text/typescript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ErrorCode,
McpError,
} from '@modelcontextprotocol/sdk/types.js';
import axios, { AxiosInstance } from 'axios';
interface AlphaVantageConfig {
apiKey: string;
}
class AlphaVantageServer {
private server: Server;
private axiosInstance: AxiosInstance;
constructor(config: AlphaVantageConfig) {
this.server = new Server(
{
name: 'alpha-ventage-mcp',
version: '0.1.0',
},
{
capabilities: {
tools: {},
},
}
);
this.axiosInstance = axios.create({
baseURL: 'https://www.alphavantage.co/query',
params: {
apikey: config.apiKey,
},
});
this.setupToolHandlers();
this.server.onerror = (error) => console.error('[MCP Error]', error);
process.on('SIGINT', async () => {
await this.server.close();
process.exit(0);
});
}
private setupToolHandlers() {
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
switch (request.params.name) {
case 'get_stock_price':
return await this.getStockPrice(request.params.arguments);
case 'get_company_overview':
return await this.getCompanyOverview(request.params.arguments);
case 'get_daily_time_series':
return await this.getDailyTimeSeries(request.params.arguments);
case 'get_weekly_time_series':
return await this.getWeeklyTimeSeries(request.params.arguments);
case 'get_forex_rate':
return await this.getForexRate(request.params.arguments);
case 'get_crypto_price':
return await this.getCryptoPrice(request.params.arguments);
case 'get_technical_indicator':
return await this.getTechnicalIndicator(request.params.arguments);
default:
throw new McpError(
ErrorCode.MethodNotFound,
`Unknown tool: ${request.params.name}`
);
}
} catch (error) {
if (axios.isAxiosError(error)) {
return {
content: [
{
type: 'text',
text: `Alpha Vantage API error: ${
error.response?.data.message ?? error.message
}`,
},
],
isError: true,
};
}
throw error;
}
});
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'get_stock_price',
description: 'Get real-time stock price information',
inputSchema: {
type: 'object',
properties: {
symbol: {
type: 'string',
description: 'The stock symbol (e.g., AAPL)',
},
},
required: ['symbol'],
},
},
{
name: 'get_company_overview',
description: 'Get company information and key metrics',
inputSchema: {
type: 'object',
properties: {
symbol: {
type: 'string',
description: 'The stock symbol (e.g., AAPL)',
},
},
required: ['symbol'],
},
},
{
name: 'get_daily_time_series',
description: 'Get daily time series data for a stock',
inputSchema: {
type: 'object',
properties: {
symbol: {
type: 'string',
description: 'The stock symbol (e.g., AAPL)',
},
outputsize: {
type: 'string',
description: 'Amount of data to return (compact/full)',
enum: ['compact', 'full'],
default: 'compact',
},
},
required: ['symbol'],
},
},
{
name: 'get_weekly_time_series',
description: 'Get weekly time series data for a stock',
inputSchema: {
type: 'object',
properties: {
symbol: {
type: 'string',
description: 'The stock symbol (e.g., AAPL)',
},
},
required: ['symbol'],
},
},
{
name: 'get_forex_rate',
description: 'Get exchange rate for currency pairs',
inputSchema: {
type: 'object',
properties: {
from_currency: {
type: 'string',
description: 'From currency (e.g., USD)',
},
to_currency: {
type: 'string',
description: 'To currency (e.g., EUR)',
},
},
required: ['from_currency', 'to_currency'],
},
},
{
name: 'get_crypto_price',
description: 'Get cryptocurrency prices',
inputSchema: {
type: 'object',
properties: {
symbol: {
type: 'string',
description: 'The crypto symbol (e.g., BTC)',
},
market: {
type: 'string',
description: 'Market currency (e.g., USD)',
},
},
required: ['symbol', 'market'],
},
},
{
name: 'get_technical_indicator',
description: 'Get technical indicators for a stock',
inputSchema: {
type: 'object',
properties: {
symbol: {
type: 'string',
description: 'The stock symbol (e.g., AAPL)',
},
indicator: {
type: 'string',
description: 'Technical indicator (e.g., SMA, EMA, RSI)',
},
interval: {
type: 'string',
description: 'Time interval',
enum: ['1min', '5min', '15min', '30min', '60min', 'daily', 'weekly', 'monthly'],
default: 'daily',
},
},
required: ['symbol', 'indicator'],
},
},
],
}));
}
private async getStockPrice(args: any) {
const response = await this.axiosInstance.get('', {
params: {
function: 'GLOBAL_QUOTE',
symbol: args.symbol,
},
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2),
},
],
};
}
private async getCompanyOverview(args: any) {
const response = await this.axiosInstance.get('', {
params: {
function: 'OVERVIEW',
symbol: args.symbol,
},
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2),
},
],
};
}
private async getDailyTimeSeries(args: any) {
const response = await this.axiosInstance.get('', {
params: {
function: 'TIME_SERIES_DAILY',
symbol: args.symbol,
outputsize: args.outputsize || 'compact',
},
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2),
},
],
};
}
private async getWeeklyTimeSeries(args: any) {
const response = await this.axiosInstance.get('', {
params: {
function: 'TIME_SERIES_WEEKLY',
symbol: args.symbol,
},
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2),
},
],
};
}
private async getForexRate(args: any) {
const response = await this.axiosInstance.get('', {
params: {
function: 'CURRENCY_EXCHANGE_RATE',
from_currency: args.from_currency,
to_currency: args.to_currency,
},
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2),
},
],
};
}
private async getCryptoPrice(args: any) {
const response = await this.axiosInstance.get('', {
params: {
function: 'CRYPTO_INTRADAY',
symbol: args.symbol,
market: args.market,
},
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2),
},
],
};
}
private async getTechnicalIndicator(args: any) {
const response = await this.axiosInstance.get('', {
params: {
function: args.indicator,
symbol: args.symbol,
interval: args.interval || 'daily',
},
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data, null, 2),
},
],
};
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('Alpha Vantage MCP server running on stdio');
}
}
const API_KEY = process.env.ALPHA_VANTAGE_API_KEY;
if (!API_KEY) {
throw new Error('ALPHA_VANTAGE_API_KEY environment variable is required');
}
const server = new AlphaVantageServer({
apiKey: API_KEY,
});
server.run().catch(console.error);