这是一个全面的 Model Context Protocol (MCP) 服务器实现,提供来自 CoinGecko API 的实时加密货币价格数据。该项目展示了传统的 MCP 标准 I/O 传输和现代 HTTP 端点,以增强测试和集成能力。
此项目实现了一个 Model Context Protocol (MCP) 服务器,作为 AI 代理与实时加密货币市场数据之间的桥梁。它提供了:
Model Context Protocol (MCP) 是一个标准化协议,使 AI 代理能够以安全一致的方式访问外部数据源和工具。此服务器通过 MCP 工具暴露加密货币市场数据,这些工具可以被 AI 代理调用。
graph TB
A[AI Agent/Client] --> B[MCP Server - stdio]
C[Web Browser] --> D[Express HTTP Server]
B --> E[CoinGecko API]
D --> E
E --> F[Real-time Price Data]
subgraph "MCP Tools"
G[getCryptoPrice]
H[listTopCryptos]
end
B --> G
B --> H
D --> G
D --> H
# 克隆仓库
git clone https://github.com/AdI-70/realtime-cryptoprice-MCP.git
cd realtime-cryptoprice-MCP
# 安装依赖
npm install
# 启动 Web 服务器
npm run web
在浏览器中打开 http://localhost:3000 查看仪表板!
# 在单独的终端中测试 MCP 客户端
npm run client
创建项目目录
mkdir crypto-mcp-server
cd crypto-mcp-server
初始化 Node.js 项目
npm init -y
配置 ES 模块
// 添加到 package.json
{
"type": "module",
"scripts": {
"start": "node server.js",
"client": "node client.js",
"web": "node web-server.js"
}
}
# 核心 MCP 依赖
npm install @modelcontextprotocol/sdk zod node-fetch
# Web 服务器依赖
npm install express
server.js)import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import fetch from "node-fetch";
// 创建 MCP 服务器实例
const server = new McpServer({
name: "CryptoPrice",
version: "1.0.0"
});
// 定义 getCryptoPrice 工具
server.tool("getCryptoPrice", {
id: z.string().describe("加密货币 ID(例如,bitcoin, ethereum)"),
currency: z.string().default("usd").describe("货币(usd, eur 等)")
}, async ({ id, currency }) => {
try {
const response = await fetch(
`https://api.coingecko.com/api/v3/simple/price?ids=${id}&vs_currencies=${currency}`
);
const data = await response.json();
if (!data[id]) {
return { content: [{ type: "text", text: `加密货币 '${id}' 未找到。` }] };
}
const price = data[id][currency];
return {
content: [{ type: "text", text: `${id}: ${price} ${currency.toUpperCase()}` }]
};
} catch (error) {
return {
content: [{ type: "text", text: `错误: ${error.message}` }]
};
}
});
// 定义 listTopCryptos 工具
server.tool("listTopCryptos", {
limit: z.number().default(10).describe("顶级加密货币的数量")
}, async ({ limit }) => {
try {
const response = await fetch(
`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=${limit}&page=1`
);
const data = await response.json();
const cryptoList = data.map(crypto =>
`${crypto.name} (${crypto.symbol}): $${crypto.current_price}`
).join('\n');
return { content: [{ type: "text", text: cryptoList }] };
} catch (error) {
return {
content: [{ type: "text", text: `错误: ${error.message}` }]
};
}
});
// 使用标准 I/O 传输启动服务器
const transport = new StdioServerTransport();
console.log("正在启动 CryptoPrice MCP 服务器...");
await server.connect(transport);
console.log("CryptoPrice MCP 服务器运行中");
client.js)import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
async function main() {
// 创建连接到服务器的传输
const transport = new StdioClientTransport({
command: "node",
args: ["server.js"]
});
// 创建客户端
const client = new Client({
name: "crypto-price-client",
version: "1.0.0"
});
// 连接并测试
await client.connect(transport);
try {
console.log("已连接到 CryptoPrice MCP 服务器\n");
// 测试比特币价格
const bitcoinPrice = await client.callTool({
name: "getCryptoPrice",
arguments: { id: "bitcoin", currency: "usd" }
});
console.log("比特币价格:", bitcoinPrice.content[0].text);
// 测试顶级加密货币
const topCryptos = await client.callTool({
name: "listTopCryptos",
arguments: { limit: 5 }
});
console.log("\n顶级 5 种加密货币:");
console.log(topCryptos.content[0].text);
} catch (error) {
console.error("错误:", error.message);
}
}
main().catch(console.error);
web-server.js)import express from 'express';
import path from 'path';
import { fileURLToPath } from 'url';
import fetch from 'node-fetch';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const PORT = 3000;
// 中间件
app.use(express.json());
app.use(express.static('public'));
// API 路由
app.get('/api/crypto/:id', async (req, res) => {
try {
const { id } = req.params;
const { currency = 'usd' } = req.query;
const response = await fetch(
`https://api.coingecko.com/api/v3/simple/price?ids=${id}&vs_currencies=${currency}`
);
const data = await response.json();
if (!data[id]) {
return res.status(404).json({ error: `加密货币 '${id}' 未找到` });
}
res.json({
id,
currency: currency.toUpperCase(),
price: data[id][currency],
formatted: `${id}: ${data[id][currency]} ${currency.toUpperCase()}`
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.get('/api/top-cryptos', async (req, res) => {
try {
const { limit = 10 } = req.query;
const response = await fetch(
`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=${limit}&page=1`
);
const data = await response.json();
const cryptoList = data.map(crypto => ({
id: crypto.id,
name: crypto.name,
symbol: crypto.symbol.toUpperCase(),
price: crypto.current_price,
change_24h: crypto.price_change_percentage_24h
}));
res.json({ cryptos: cryptoList, count: cryptoList.length });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// 健康检查
app.get('/api/health', (req, res) => {
res.json({
status: 'healthy',
server: 'CryptoPrice MCP Web Server',
timestamp: new Date().toISOString()
});
});
app.listen(PORT, () => {
console.log(`🚀 服务器正在运行于 http://localhost:${PORT}`);
});
创建 public 目录
mkdir public
创建 public/index.html(美观且响应式的仪表板)
创建 .gitignore
node_modules/
*.log
.env
.DS_Store
初始化 Git 仓库
git init
git add .
git commit -m "初始提交:CryptoPrice MCP 服务器"
创建 mcpserver.json
{
"servers": [{
"name": "CryptoPrice",
"command": "node",
"args": ["server.js"],
"description": "来自 CoinGecko 的加密货币价格数据",
"metadata": {
"version": "1.0.0",
"tools": [
{
"name": "getCryptoPrice",
"description": "获取特定加密货币的当前价格"
},
{
"name": "listTopCryptos",
"description": "按市值列出顶级加密货币"
}
]
}
}]
}
# 启动 MCP 服务器
npm start
# 使用客户端测试
npm run client
# 启动 Web 服务器
npm run web
# 打开浏览器
open http://localhost:3000
// 获取比特币价格
fetch('http://localhost:3000/api/crypto/bitcoin')
.then(response => response.json())
.then(data => console.log(data));
// 获取顶级 5 种加密货币
fetch('http://localhost:3000/api/top-cryptos?limit=5')
.then(response => response.json())
.then(data => console.log(data));
| 端点 | 方法 | 描述 | 参数 |
|---|---|---|---|
/api/crypto/:id | GET | 获取特定加密货币的价格 | currency(可选) |
/api/top-cryptos | GET | 获取顶级加密货币 | limit(可选) |
/api/health | GET | 服务器健康检查 | 无 |
GET /api/crypto/bitcoin
{
"id": "bitcoin",
"currency": "USD",
"price": 43250.50,
"formatted": "bitcoin: 43250.50 USD"
}
GET /api/top-cryptos?limit=3
{
"cryptos": [
{
"id": "bitcoin",
"name": "Bitcoin",
"symbol": "BTC",
"price": 43250.50,
"change_24h": 2.5
}
],
"count": 3
}
crypto-mcp-server/
├── server.js # MCP 服务器(标准 I/O 传输)
├── client.js # MCP 客户端用于测试
├── web-server.js # 带有 API 端点的 HTTP 服务器
├── package.json # 依赖项和脚本
├── mcpserver.json # MCP 服务器配置
├── .gitignore # Git 忽略规则
├── public/
│ └── index.html # Web 仪表板
└── README.md # 此文件
添加新的 MCP 工具
server.tool("newTool", {
param: z.string().describe("参数描述")
}, async ({ param }) => {
// 实现
return { content: [{ type: "text", text: "结果" }] };
});
添加新的 API 端点
app.get('/api/new-endpoint', async (req, res) => {
// 实现
res.json({ result: "数据" });
});
创建 .env 文件进行配置:
PORT=3000
API_BASE_URL=https://api.coingecko.com/api/v3
CACHE_DURATION=60000
# 测试 MCP 服务器
npm run client
# 测试 Web 服务器
curl http://localhost:3000/api/crypto/bitcoin
curl http://localhost:3000/api/top-cryptos?limit=5
# 安装测试依赖
npm install --save-dev jest supertest
# 运行测试
npm test
# 安装 PM2 进程管理器
npm install -g pm2
# 使用 PM2 启动
pm2 start web-server.js --name "crypto-mcp-web"
pm2 start server.js --name "crypto-mcp-server"
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "run", "web"]
Procfile,内容为 web: node web-server.js