Second Opinion MCP Server

Second Opinion MCP Server

利用谷歌 Gemini AI 提供 AI 驱动的编码问题协助,结合 Perplexity 的洞察和 Stack Overflow 的参考资料,促进上下文分析和自动响应存档,以改进故障排除。

远程shell执行
网络自动化与隐身
Git管理工具
数据与应用分析
访问服务器

README

Second Opinion MCP 服务器

一个 MCP 服务器,通过结合以下来源的见解,为编码问题提供 AI 驱动的辅助:

  • Google 的 Gemini AI
  • Stack Overflow 采纳的答案
  • Perplexity AI 分析

功能

  • 获取编码问题的详细解决方案,其中包含来自多个来源的上下文
  • 从文件扩展名自动检测语言
  • 代码片段提取和格式化
  • 为解决方案生成 Markdown 报告
  • Git 感知的文件上下文收集

设置

  1. 安装依赖项:
npm install
  1. 构建服务器:
npm run build
  1. 在 MCP 设置中配置环境变量:
{
  "mcpServers": {
    "second-opinion": {
      "command": "node",
      "args": ["/path/to/second-opinion-server/build/index.js"],
      "env": {
        "GEMINI_API_KEY": "your-gemini-api-key",
        "PERPLEXITY_API_KEY": "your-perplexity-api-key",
        "STACK_EXCHANGE_KEY": "your-stack-exchange-key"
      }
    }
  }
}

必需的环境变量:

  • GEMINI_API_KEY: Google 的 Gemini AI API 密钥
  • PERPLEXITY_API_KEY: Perplexity AI API 密钥
  • STACK_EXCHANGE_KEY: Stack Exchange API 密钥(可选,如果未提供,则使用匿名访问)

用法

该服务器提供一个工具:

get_second_opinion

获取 AI 驱动的编码问题见解和解决方案。

输入模式:

{
  "goal": "string (必需) - 您尝试完成的目标",
  "error": "string (可选) - 您看到的任何错误消息",
  "code": "string (可选) - 相关的代码上下文",
  "solutionsTried": "string (可选) - 您已经尝试过的解决方案",
  "filePath": "string (可选) - 出现问题的文件路径"
}

输入示例:

{
  "goal": "修复 React useEffect 清理错误",
  "error": "React Hook useEffect 缺少依赖项: 'socket'。 要么将其包含在依赖项数组中,要么删除依赖项数组 react-hooks/exhaustive-deps",
  "code": "useEffect(() => {\n  socket.on('message', handleMessage);\n  return () => socket.off('message');\n}, []);",
  "solutionsTried": "我尝试将 socket 添加到依赖项数组,但随后导致无限重新渲染"
}

响应示例:

理解问题

核心问题在于 React 的 useEffect hook 如何管理副作用及其依赖项。 当您提供一个空依赖项数组 ([]) 时,您是在告诉 React 该 effect 应该只在组件挂载时运行一次,并且清理函数应该在组件卸载时运行。

但是,在您的代码中,socket 对象在 effect 中使用。 这会创建一个闭包,其中 handleMessage 函数和清理函数 (socket.off('message')) 隐式地依赖于 socket 的当前值。 如果 socket 发生更改(例如,由于重新连接或重新初始化),您的 effect 将使用过时的 socket 实例。

常见问题

  • 过时的闭包: 事件处理程序 (handleMessage) 可能正在使用旧的 socket 对象
  • 不正确的清理: socket.off('message') 可能无法删除预期的事件侦听器
  • 内存泄漏: 清理失败可能导致内存泄漏和意外行为

解决方案

1. 使用 useRef 获取稳定的引用

import React, { useEffect, useRef } from 'react';

function MyComponent({ socket }) {
  const socketRef = useRef(socket);

  useEffect(() => {
    const currentSocket = socketRef.current;
    currentSocket.on('message', handleMessage);
    return () => {
      currentSocket.off('message');
    };
  }, []); // 空依赖项数组现在是安全的
}

为什么有效:

  • useRef 创建一个在渲染之间持久存在的 mutable 对象
  • ref 对象本身不会改变,从而防止 effect 重新运行
  • 您可以通过 ref 访问最新的 socket 值

2. 使用 useCallback 获取处理程序

import React, { useEffect, useRef, useCallback } from 'react';

function MyComponent({ socket, someProp }) {
  const socketRef = useRef(socket);

  const handleMessage = useCallback((message) => {
    // 使用消息和潜在的 someProp 做一些事情
    console.log(message, someProp);
  }, [someProp]); // 包括 handleMessage 的依赖项

  useEffect(() => {
    const currentSocket = socketRef.current;
    currentSocket.on('message', handleMessage);
    return () => {
      currentSocket.off('message', handleMessage);
    };
  }, [handleMessage]); // 依赖于 memoized 处理程序
}

3. 在 useEffect 内部管理 Socket 生命周期

import React, { useEffect, useState } from 'react';

function MyComponent() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const socket = new WebSocket('your_websocket_url');

    const handleMessage = (message) => {
      setMessages((prevMessages) => [...prevMessages, message]);
    };

    socket.on('message', handleMessage);

    return () => {
      socket.off('message', handleMessage);
      socket.close();
    };
  }, []); // 空数组是正确的 - socket 生命周期在内部管理
}

4. 自定义 Hook 解决方案

function useSocket(url) {
  const [messages, setMessages] = useState([]);
  const socketRef = useRef(null);

  useEffect(() => {
    const socket = new WebSocket(url);
    socketRef.current = socket;

    const handleMessage = (message) => {
      setMessages((prevMessages) => [...prevMessages, message]);
    };

    socket.on('message', handleMessage);

    return () => {
      socket.off('message', handleMessage);
      socket.close();
    };
  }, [url]);

  const sendMessage = useCallback((message) => {
    if (socketRef.current?.readyState === WebSocket.OPEN) {
      socketRef.current.send(message);
    }
  }, []);

  return { messages, sendMessage };
}

最佳实践

  1. 依赖管理

    • 使用 useRef 获取稳定的引用
    • 使用 useCallback 记忆处理程序
    • 考虑 socket 生命周期管理
  2. 性能优化

    • 尽量减少不必要的重新渲染
    • 有效处理大量消息
    • 使用适当的清理模式
  3. 错误处理

    • 优雅地处理连接错误
    • 如果需要,实现重新连接逻辑
    • 正确清理资源
  4. 测试注意事项

    • 在测试中模拟 WebSocket 连接
    • 验证事件侦听器清理
    • 测试错误场景

项目结构

src/
├── config.ts        # 配置和 API 设置
├── fileUtils.ts     # 文件操作和语言检测
├── index.ts         # 入口点
├── perplexity.ts   # Perplexity AI 集成
├── server.ts       # MCP 服务器实现
├── stackOverflow.ts # Stack Overflow API 集成
└── types.ts        # TypeScript 接口

已知问题

请参阅 errors.md 了解当前问题和解决方法。

推荐服务器

Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
mult-fetch-mcp-server

mult-fetch-mcp-server

一个多功能的、符合 MCP 规范的网页内容抓取工具,支持多种模式(浏览器/Node)、格式(HTML/JSON/Markdown/文本)和智能代理检测,并提供双语界面(英语/中文)。

精选
本地
AIO-MCP Server

AIO-MCP Server

🚀 集成了 AI 搜索、RAG 和多服务(GitLab/Jira/Confluence/YouTube)的一体化 MCP 服务器,旨在增强 AI 驱动的开发工作流程。来自 Folk。

精选
本地
Hyperbrowser

Hyperbrowser

欢迎来到 Hyperbrowser,人工智能的互联网。Hyperbrowser 是下一代平台,旨在增强人工智能代理的能力,并实现轻松、可扩展的浏览器自动化。它专为人工智能开发者打造,消除了本地基础设施和性能瓶颈带来的麻烦,让您能够:

精选
本地
https://github.com/Streen9/react-mcp

https://github.com/Streen9/react-mcp

react-mcp 与 Claude Desktop 集成,能够根据用户提示创建和修改 React 应用程序。

精选
本地
any-chat-completions-mcp

any-chat-completions-mcp

将 Claude 与任何 OpenAI SDK 兼容的聊天完成 API 集成 - OpenAI、Perplexity、Groq、xAI、PyroPrompts 等。

精选
Exa MCP Server

Exa MCP Server

一个模型上下文协议服务器,它使像 Claude 这样的人工智能助手能够以安全和受控的方式,使用 Exa AI 搜索 API 执行实时网络搜索。

精选
BigQuery MCP Server

BigQuery MCP Server

这是一个服务器,可以让你的大型语言模型(LLM,比如Claude)直接与你的BigQuery数据对话!可以把它想象成一个友好的翻译器,它位于你的AI助手和数据库之间,确保它们可以安全高效地进行交流。

精选