MCP工具开发完全指南:从零构建实时新闻工具

446 阅读7分钟

MCP工具开发完全指南:从零构建实时新闻工具

🎯 前言

MCP(Model Context Protocol)工具是现代AI应用开发中的重要组件,它允许我们为AI模型提供特定的功能和数据获取能力。本文将通过一个完整的实时新闻MCP工具项目,带你从零开始学习MCP工具的开发。

🔗 项目地址: GitHub - realtime-news

无论你是编程新手还是想了解MCP工具开发的开发者,这篇文章都会为你提供详细的指导和实践经验。

📚 什么是MCP工具?

MCP基础概念

MCP(Model Context Protocol)是一种标准化协议,用于AI模型与外部工具、数据源之间的通信。简单来说:

  • AI模型:类似大脑,负责理解和推理
  • MCP工具:类似工具箱,为AI提供特定能力
  • 协议:规定了AI和工具之间如何"对话"

MCP工具的作用

用户请求 → AI理解 → 调用MCP工具 → 获取数据/执行操作 → 返回结果给用户

例如:

  • 用户:"今天有什么重要新闻?"
  • AI调用新闻MCP工具获取最新新闻
  • 返回格式化的新闻列表给用户

🛠️ 项目概述:实时新闻MCP工具

我们要构建的实时新闻MCP工具具备以下功能:

核心功能

  • 📰 获取实时新闻:支持10种新闻分类
  • 🔍 关键词搜索:智能搜索相关新闻
  • 📋 分类管理:完整的新闻分类系统
  • 🛡️ 错误处理:完善的异常处理机制

技术特点

  • 基于Node.js开发
  • 使用聚合数据API
  • 支持环境变量配置
  • 完整的模块化设计

🏗️ 项目结构详解

让我们先了解整个项目的组织结构:

realtime-news-mcp/
├── realtime-news-mcp.js    # 主工具文件(核心逻辑)
├── package.json            # 项目配置文件
├── example.js             # 使用示例
├── interactive-demo.js    # 交互式演示
├── .env.local             # 环境变量配置
├── .gitignore             # Git忽略文件
├── README.md              # 项目说明文档
├── CHANGELOG.md           # 更新日志
├── CONTRIBUTING.md        # 贡献指南
└── LICENSE                # 开源许可证

文件职责分析

文件作用重要程度
realtime-news-mcp.js核心工具逻辑⭐⭐⭐⭐⭐
package.json项目配置和依赖管理⭐⭐⭐⭐⭐
example.js学习和测试示例⭐⭐⭐⭐
.env.local安全的配置管理⭐⭐⭐⭐

🔧 开发环境准备

1. 环境要求

# 检查Node.js版本(需要14.0.0以上)
node --version

# 检查npm版本(需要6.0.0以上)
npm --version

2. 项目初始化

# 创建项目目录
mkdir realtime-news-mcp
cd realtime-news-mcp

# 初始化npm项目
npm init -y

# 安装核心依赖
npm install axios dotenv

3. API密钥申请

  1. 访问聚合数据官网
  2. 注册账号并实名认证
  3. 申请"新闻头条"API服务
  4. 获取API密钥

📝 核心代码实现

1. 项目配置文件 (package.json)

{
  "name": "realtime-news-mcp",
  "version": "1.0.0",
  "description": "中国实时新闻MCP工具",
  "main": "realtime-news-mcp.js",
  "scripts": {
    "start": "node realtime-news-mcp.js",
    "test": "node -e "const tool = require('./realtime-news-mcp.js'); tool.mcpNewsTool('categories').then(console.log);"",
    "demo": "node example.js"
  },
  "dependencies": {
    "axios": "^1.6.0",
    "dotenv": "^16.6.1"
  },
  "engines": {
    "node": ">=14.0.0"
  }
}

2. 环境变量配置 (.env.local)

# 聚合数据API密钥
JUHE_API_KEY=你的API密钥

# 可选配置
API_TIMEOUT=10000
MAX_RESULTS=30

3. 主工具文件结构分析

让我们逐步分析核心文件realtime-news-mcp.js的实现:

A. 基础配置和依赖
#!/usr/bin/env node

// 加载环境变量
require('dotenv').config({ path: '.env.local' });

const axios = require('axios');

// 工具配置
const TOOL_NAME = "中国实时新闻MCP工具";
const API_KEY = process.env.JUHE_API_KEY || "请设置API密钥";
const BASE_URL = "http://v.juhe.cn/toutiao/index";

// 新闻分类映射
const NEWS_CATEGORIES = {
  'top': '头条',
  'shehui': '社会',
  'guonei': '国内',
  'guoji': '国际',
  'yule': '娱乐',
  'tiyu': '体育',
  'junshi': '军事',
  'keji': '科技',
  'caijing': '财经',
  'shishang': '时尚'
};

设计要点:

  • 使用环境变量保护API密钥
  • 清晰的配置集中管理
  • 中文分类映射提升用户体验
B. 核心功能函数

1. 获取最新新闻

async function getLatestNews(category = 'top', limit = 10) {
  try {
    // 1. 参数验证
    if (category && !NEWS_CATEGORIES[category]) {
      return `❌ 错误:不支持的新闻分类 "${category}"`;
    }

    // 2. 构建请求参数
    const params = {
      key: API_KEY,
      type: category
    };

    // 3. 发送API请求
    const response = await axios.get(BASE_URL, {
      params,
      timeout: 10000 // 10秒超时
    });

    // 4. 检查响应状态
    if (response.data.error_code !== 0) {
      return `❌ API错误:${response.data.reason}`;
    }

    // 5. 处理和格式化数据
    const newsData = response.data.result.data || [];
    const limitedNews = newsData.slice(0, limit);
    const formattedNews = formatNewsData(limitedNews, category);

    return `✅ 获取成功\n\n${formattedNews}`;

  } catch (error) {
    // 6. 错误处理
    return handleApiError(error);
  }
}

设计亮点:

  • 完整的错误处理流程
  • 参数验证确保安全性
  • 超时控制防止请求挂起
  • 数据限制避免信息过载

2. 关键词搜索功能

async function searchNews(keyword, limit = 5) {
  try {
    if (!keyword || keyword.trim() === '') {
      return "❌ 错误:搜索关键词不能为空";
    }

    // 并行搜索多个分类
    const categories = ['top', 'shehui', 'guonei', 'guoji', 'keji'];
    const searchResults = [];

    for (const category of categories) {
      try {
        const response = await axios.get(BASE_URL, {
          params: { key: API_KEY, type: category },
          timeout: 5000
        });

        if (response.data.error_code === 0) {
          const newsData = response.data.result.data;
          
          // 筛选包含关键词的新闻
          const filteredNews = newsData.filter(news =>
            news.title.includes(keyword) ||
            (news.content && news.content.includes(keyword))
          );

          searchResults.push(...filteredNews);
        }
      } catch (err) {
        console.log(`搜索 ${category} 分类时出错:`, err.message);
      }
    }

    // 排序和格式化结果
    const sortedResults = searchResults
      .sort((a, b) => new Date(b.date) - new Date(a.date))
      .slice(0, limit);

    return formatSearchResults(sortedResults, keyword);

  } catch (error) {
    return `❌ 搜索失败: ${error.message}`;
  }
}

实现特色:

  • 多分类并行搜索
  • 标题和内容双重匹配
  • 时间排序确保时效性
  • 容错机制保证稳定性
C. 数据格式化和用户体验
function formatNewsData(newsData, category) {
  const categoryName = NEWS_CATEGORIES[category] || '搜索结果';
  let formatted = `📰 ${categoryName}新闻 (${newsData.length}条)\n`;
  formatted += "=".repeat(50) + "\n\n";

  newsData.forEach((news, index) => {
    formatted += `${index + 1}. 📢 ${news.title}\n`;
    
    if (news.author_name) {
      formatted += `   👤 来源:${news.author_name}\n`;
    }
    
    if (news.date) {
      formatted += `   🕒 时间:${news.date}\n`;
    }
    
    if (news.content) {
      const summary = news.content.length > 100
        ? news.content.substring(0, 100) + "..."
        : news.content;
      formatted += `   📝 摘要:${summary}\n`;
    }
    
    formatted += "\n" + "-".repeat(40) + "\n\n";
  });

  // 添加统计信息
  formatted += `📊 数据统计:\n`;
  formatted += `• 获取时间:${new Date().toLocaleString('zh-CN')}\n`;
  formatted += `• 新闻数量:${newsData.length}条\n`;

  return formatted;
}

用户体验设计:

  • 清晰的视觉分隔符
  • 丰富的emoji图标
  • 合理的信息层次
  • 实用的统计信息
D. MCP工具接口
async function mcpNewsTool(action = 'latest', param = 'top', limit = 10) {
  try {
    console.log(`🚀 执行操作: ${action}, 参数: ${param}, 限制: ${limit}`);

    switch (action.toLowerCase()) {
      case 'latest':
        return await getLatestNews(param, limit);

      case 'search':
        return await searchNews(param, limit);

      case 'categories':
        return getNewsCategories();

      default:
        return `❌ 不支持的操作: ${action}\n支持的操作: latest, search, categories`;
    }

  } catch (error) {
    return `❌ 工具执行失败: ${error.message}`;
  }
}

接口设计原则:

  • 统一的调用入口
  • 清晰的参数约定
  • 标准的错误响应
  • 完整的操作日志

🎯 使用示例和测试

1. 基础使用示例

创建example.js文件:

const { mcpNewsTool } = require('./realtime-news-mcp.js');

async function runExamples() {
  try {
    // 示例1: 获取头条新闻
    console.log('📰 获取头条新闻:');
    const headlines = await mcpNewsTool('latest', 'top', 3);
    console.log(headlines);

    // 示例2: 搜索科技新闻
    console.log('\n💻 获取科技新闻:');
    const techNews = await mcpNewsTool('latest', 'keji', 2);
    console.log(techNews);

    // 示例3: 关键词搜索
    console.log('\n🔍 搜索关键词:');
    const searchResults = await mcpNewsTool('search', 'AI', 2);
    console.log(searchResults);

    // 示例4: 查看分类
    console.log('\n📋 查看分类:');
    const categories = await mcpNewsTool('categories');
    console.log(categories);

  } catch (error) {
    console.error('示例执行失败:', error);
  }
}

runExamples();

2. 批量操作示例

// 批量获取多分类新闻
async function batchGetNews() {
  const categories = ['top', 'keji', 'caijing'];
  const results = {};

  for (const category of categories) {
    try {
      const news = await mcpNewsTool('latest', category, 2);
      results[category] = '✅ 获取成功';
    } catch (error) {
      results[category] = `❌ 获取失败: ${error.message}`;
    }
  }

  console.log('批量获取结果:', results);
}

3. 自定义应用场景

// 创建个性化新闻摘要
async function getMyDailyNews() {
  const results = {};
  
  // 获取各类新闻
  results.headlines = await mcpNewsTool('latest', 'top', 3);
  results.tech = await mcpNewsTool('latest', 'keji', 2);
  results.finance = await mcpNewsTool('latest', 'caijing', 2);
  
  // 搜索感兴趣的话题
  results.ai = await mcpNewsTool('search', '人工智能', 1);
  
  return results;
}

🛡️ 错误处理和最佳实践

1. 完善的错误处理

function handleApiError(error) {
  if (error.code === 'ECONNABORTED') {
    return "❌ 请求超时,请检查网络连接";
  } else if (error.response) {
    return `❌ API请求失败: HTTP ${error.response.status}`;
  } else if (error.code === 'ENOTFOUND') {
    return "❌ 网络连接失败,请检查网络设置";
  } else {
    return `❌ 网络错误: ${error.message}`;
  }
}

2. API密钥验证

async function validateApiKey() {
  if (!process.env.JUHE_API_KEY) {
    console.error("❌ 请先设置JUHE_API_KEY环境变量");
    return false;
  }

  try {
    const response = await axios.get(BASE_URL, {
      params: { key: API_KEY, type: 'top' },
      timeout: 5000
    });
    return response.data.error_code === 0;
  } catch (error) {
    return false;
  }
}

3. 安全最佳实践

  • 环境变量管理:敏感信息不直接写在代码中
  • 输入验证:所有用户输入都进行验证
  • 超时控制:防止请求无限等待
  • 错误日志:记录详细的错误信息

🚀 部署和分发

1. 项目打包

# 创建发布版本
npm version patch

# 生成package-lock.json
npm install

# 检查文件完整性
npm pack --dry-run

2. 依赖管理

{
  "dependencies": {
    "axios": "^1.6.0",
    "dotenv": "^16.6.1"
  },
  "engines": {
    "node": ">=14.0.0",
    "npm": ">=6.0.0"
  }
}

3. 文档完善

重要文档包括:

  • README.md:详细的使用说明
  • CHANGELOG.md:版本更新记录
  • CONTRIBUTING.md:贡献指南
  • LICENSE:开源许可证

🔄 持续改进

1. 功能扩展思路

  • 缓存机制:减少API调用次数
  • 数据持久化:保存历史新闻记录
  • 多语言支持:支持英文等其他语言
  • 推送通知:重要新闻实时推送

2. 性能优化

// 实现简单缓存
const newsCache = new Map();

async function getCachedNews(category, limit) {
  const cacheKey = `${category}-${limit}`;
  
  if (newsCache.has(cacheKey)) {
    const { data, timestamp } = newsCache.get(cacheKey);
    
    // 缓存有效期5分钟
    if (Date.now() - timestamp < 5 * 60 * 1000) {
      return data;
    }
  }
  
  const news = await getLatestNews(category, limit);
  newsCache.set(cacheKey, {
    data: news,
    timestamp: Date.now()
  });
  
  return news;
}

3. 监控和调试

// 添加性能监控
function measurePerformance(func) {
  return async function(...args) {
    const start = Date.now();
    const result = await func.apply(this, args);
    const duration = Date.now() - start;
    
    console.log(`函数 ${func.name} 执行耗时: ${duration}ms`);
    return result;
  };
}

// 使用示例
const monitoredGetNews = measurePerformance(getLatestNews);

📖 学习总结

通过这个实时新闻MCP工具项目,我们学习了:

核心技能

  1. MCP工具架构设计:理解工具的基本结构和接口设计
  2. API集成开发:学会与第三方API安全交互
  3. 错误处理机制:构建健壮的异常处理系统
  4. 用户体验设计:创建友好的数据展示格式

开发流程

  1. 需求分析 → 确定工具功能和接口
  2. 架构设计 → 规划模块结构和数据流
  3. 核心实现 → 编写主要功能代码
  4. 测试验证 → 确保功能正确性和稳定性
  5. 文档完善 → 提供完整的使用指南

最佳实践

  • 模块化设计,职责分离
  • 环境变量管理敏感信息
  • 完善的错误处理和日志记录
  • 用户友好的接口和反馈
  • 详细的文档和示例

🎯 下一步计划

基于这个基础项目,你可以继续扩展:

  1. 集成更多新闻源:增加其他新闻API支持
  2. 开发Web界面:创建可视化的管理界面
  3. 构建微服务:将工具部署为独立服务
  4. 机器学习集成:添加新闻分类和情感分析
  5. 移动应用开发:创建配套的移动端应用

这个项目为你提供了MCP工具开发的完整框架,希望能帮助你在AI工具开发的道路上更进一步!


💡 提示: 如果你在学习过程中遇到问题,欢迎查看项目的Issues页面或提交新问题。记住,最好的学习方法就是实践和分享!