#!/usr/bin/env node
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import fetch from "node-fetch";
const COINGECKO_API_BASE = "https://api.coingecko.com/api/v3";
class CoinGeckoServer {
constructor() {
this.server = new Server(
{
name: "coingecko-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
this.setupHandlers();
this.setupErrorHandling();
}
setupErrorHandling() {
this.server.onerror = (error) => {
console.error("[MCP Error]", error);
};
process.on("SIGINT", async () => {
await this.server.close();
process.exit(0);
});
}
setupHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "get_price",
description: "Get current price of cryptocurrencies in specified currencies",
inputSchema: {
type: "object",
properties: {
ids: {
type: "string",
description: "Comma-separated cryptocurrency IDs (e.g., 'bitcoin,ethereum')",
},
vs_currencies: {
type: "string",
description: "Comma-separated target currencies (e.g., 'usd,eur')",
default: "usd",
},
},
required: ["ids"],
},
},
{
name: "get_coin_details",
description: "Get detailed information about a specific cryptocurrency",
inputSchema: {
type: "object",
properties: {
id: {
type: "string",
description: "Cryptocurrency ID (e.g., 'bitcoin')",
},
},
required: ["id"],
},
},
{
name: "get_market_data",
description: "Get market data for cryptocurrencies with pagination",
inputSchema: {
type: "object",
properties: {
vs_currency: {
type: "string",
description: "Target currency (e.g., 'usd')",
default: "usd",
},
per_page: {
type: "number",
description: "Number of results per page (1-250)",
default: 10,
},
page: {
type: "number",
description: "Page number",
default: 1,
},
},
},
},
{
name: "search_coins",
description: "Search for cryptocurrencies by name or symbol",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "Search query",
},
},
required: ["query"],
},
},
{
name: "get_trending",
description: "Get trending cryptocurrencies",
inputSchema: {
type: "object",
properties: {},
},
},
],
}));
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
switch (request.params.name) {
case "get_price":
return await this.getPrice(request.params.arguments);
case "get_coin_details":
return await this.getCoinDetails(request.params.arguments);
case "get_market_data":
return await this.getMarketData(request.params.arguments);
case "search_coins":
return await this.searchCoins(request.params.arguments);
case "get_trending":
return await this.getTrending();
default:
throw new Error(`Unknown tool: ${request.params.name}`);
}
} catch (error) {
return {
content: [
{
type: "text",
text: `Error: ${error.message}`,
},
],
};
}
});
}
async getPrice(args) {
const { ids, vs_currencies = "usd" } = args;
const url = `${COINGECKO_API_BASE}/simple/price?ids=${ids}&vs_currencies=${vs_currencies}&include_24hr_change=true&include_market_cap=true`;
const response = await fetch(url);
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
}
async getCoinDetails(args) {
const { id } = args;
const url = `${COINGECKO_API_BASE}/coins/${id}?localization=false&tickers=false&community_data=true&developer_data=false`;
const response = await fetch(url);
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
}
async getMarketData(args) {
const { vs_currency = "usd", per_page = 10, page = 1 } = args;
const url = `${COINGECKO_API_BASE}/coins/markets?vs_currency=${vs_currency}&per_page=${per_page}&page=${page}&order=market_cap_desc`;
const response = await fetch(url);
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
}
async searchCoins(args) {
const { query } = args;
const url = `${COINGECKO_API_BASE}/search?query=${encodeURIComponent(query)}`;
const response = await fetch(url);
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
}
async getTrending() {
const url = `${COINGECKO_API_BASE}/search/trending`;
const response = await fetch(url);
const data = await response.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error("CoinGecko MCP Server running on stdio");
}
}
const server = new CoinGeckoServer();
server.run().catch(console.error);