以「asset-price-mcp」为例,从 0 开发 MCP Server

简介

关于 MCP 的介绍之前已经写过,可以参考 《Model Context Protocol (MCP) 快速开始》。

今天从 0 开始开发一个 MCP Server,实现一个资产价格查询的 MCP Server。


实现步骤

1. 设置 MCP 服务器

首先,使用 @modelcontextprotocol/sdk 提供的 McpServer 类创建一个 MCP 服务器实例:

javascript 复制代码
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'

const server = new McpServer({
  name: 'asset-price',
  version: '1.0.0',
})

这里,我们将服务器命名为 "asset-price",版本号为 "1.0.0"。

2. 定义数据结构

使用 zod 库定义资产符号和资产价格的数据结构,以确保从 API 获取的数据符合预期格式:

javascript 复制代码
import { z } from 'zod'

const AssetSymbolSchema = z.object({
  name: z.string(),
  symbol: z.string(),
})

const AssetPriceSchema = z.object({
  name: z.string(),
  price: z.number(),
  symbol: z.string(),
  updatedAt: z.string(),
  updatedAtReadable: z.string(),
})

这些模式用于验证从外部 API 获取的数据的结构和类型。

3. 实现缓存机制

为了提高性能并减少对外部 API 的请求次数,实现了一个简单的内存缓存:

javascript 复制代码
class SimpleCache {
  private cache: Map<string, CacheEntry<any>> = new Map();

  get<T>(key: string): T | null {
    const entry = this.cache.get(key);
    if (!entry) return null;

    if (Date.now() - entry.timestamp > CACHE_TTL) {
      this.cache.delete(key);
      return null;
    }

    return entry.data as T;
  }

  set<T>(key: string, data: T): void {
    this.cache.set(key, {
      data,
      timestamp: Date.now()
    });
  }

  clear(): void {
    this.cache.clear();
  }
}

const apiCache = new SimpleCache();

该缓存会在设定的时间间隔后自动清除过期的数据。

4. 获取资产符号和价格数据

定义一个通用的函数 fetchApiData,用于从外部 API 获取数据并进行验证:

javascript 复制代码
async function fetchApiData<T>(url: string, schema: z.ZodSchema<T>, useCache = true): Promise<T | null> {
  if (useCache) {
    const cachedData = apiCache.get<T>(url);
    if (cachedData) {
      return cachedData;
    }
  }

  const headers = {
    "User-Agent": USER_AGENT,
    "Accept": "application/json",
  };

  try {
    const response = await fetchWithTimeout(url, { headers });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}, url: ${url}`);
    }

    const data = await response.json();
    const parsedData = schema.parse(data);

    if (useCache && parsedData) {
      apiCache.set(url, parsedData);
    }

    return parsedData;
  } catch (error: any) {
    if (error instanceof z.ZodError) {
      console.error(`Schema validation failed for ${url}:`, error.errors);
    } else if (error.name === 'AbortError') {
      console.error(`Request timeout for ${url}`);
    } else {
      console.error(`API request failed for ${url}:`, error);
    }
    return null;
  }
}

该函数首先检查缓存,如果缓存中没有数据,则从 API 获取数据,并使用 zod 模式进行验证。

5. 定义 MCP 工具

在 MCP 服务器上注册一个工具 get_asset_price,用于检索当前的资产价格信息:

javascript 复制代码
server.tool(
  "get_asset_price",
  "Retrieves current pricing information for various assets including precious metals and cryptocurrencies",
  {
    random_string: z.string().optional().describe("Dummy parameter for no-parameter tools")
  },
  async () => {
    try {
      const symbols = await fetchApiData(
        `${GOLD_API_BASE}/symbols`,
        z.array(AssetSymbolSchema)
      );

      if (!symbols?.length) {
        return {
          content: [{
            type: "text",
            text: "No available asset symbols found. Service might be temporarily unavailable.",
          }]
        };
      }

      const prices: AssetPrice[] = [];
      for (const { symbol } of symbols) {
        const priceData = await fetchApiData(`${GOLD_API_BASE}/price/${symbol}`, AssetPriceSchema);
        if (priceData) {
          prices.push(priceData);
        }
      }

      return {
        content: [{
          type: "text",
          text: prices.map(price => `${price.name}: ${price.price}`).join("\n"),
        }]
      };
    } catch (error) {
      console.error("Tool execution failed:", error);
      return {
        content: [{
          type: "text",
          text: "An error occurred while processing your request. Please try again later.",
        }]
      };
    }
  }
);

此工具允许 LLM 通过 MCP 服务器请求资产价格数据,并以文本形式返回结果。

相关推荐
阿里云大数据AI技术10 小时前
OpenSearch 视频 RAG 实践
数据库·人工智能·llm
大模型开发11 小时前
零基础打造AI智能体实战教学(10)----零基础用Coze打造短视频自动洗稿工作流
llm·agent·coze
商汤万象开发者12 小时前
懒懒笔记 | 课代表带你梳理【RAG课程 19:基于知识图谱的RAG】
llm
字节跳动视频云技术团队14 小时前
ICME 2025 | 火山引擎在国际音频编码能力挑战赛中夺得冠军
llm·aigc·音视频开发
AI大模型15 小时前
COZE实战部署(二)—— 创建Coze应用
程序员·llm·coze
聚客AI15 小时前
大模型学习进阶路线图:从Prompt到预训练的四阶段全景解析
人工智能·llm·掘金·日新计划
大模型开发15 小时前
零基础打造AI智能体实战教学(9)----把Coze AI助手部署到Discord频道教程
llm·agent·coze
ansurfen17 小时前
我的第一个AI项目:从零搭建RAG知识库的踩坑之旅
python·llm
五更琉璃018 小时前
十分钟完全理解MCP
mcp
围巾哥萧尘18 小时前
「MCP系列」轻松上手:三步快速完成 MCP 运行环境搭建指南🧣
mcp