智能编码助手

@PoliTwit1984/second-opinion-mcp-server
0 Stars 679 次浏览 PoliTwit1984 更新于 2026-08-23

提供了使用谷歌的Gemini AI、结合Perplexity见解和Stack Overflow参考的编码问题人工智能辅助功能,有助于上下文分析和自动响应存档,以提高故障排除效率。

该服务暂未提供标准配置,请参考 README 手动接入

服务介绍

Second Opinion MCP 服务器

一个结合以下来源的见解,为编码问题提供AI支持的MCP服务器:

  • 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 (required) - What you're trying to accomplish",
  "error": "string (optional) - Any error messages you're seeing",
  "code": "string (optional) - Relevant code context",
  "solutionsTried": "string (optional) - What solutions you've already tried",
  "filePath": "string (optional) - Path to the file with the issue"
}

示例输入:

{
  "goal": "Fix React useEffect cleanup error",
  "error": "React Hook useEffect has a missing dependency: 'socket'. Either include it in the dependency array, or remove the dependency array  react-hooks/exhaustive-deps",
  "code": "useEffect(() => {\n  socket.on('message', handleMessage);\n  return () => socket.off('message');\n}, []);",
  "solutionsTried": "I tried adding socket to the dependency array but then it causes infinite re-renders"
}

示例响应:

理解问题

核心问题在于React的useEffect钩子如何管理副作用及其依赖项。当您提供一个空的依赖数组([])时,这意味着效果仅在组件挂载时运行一次,并且清理函数将在组件卸载时运行。

然而,在您的代码中,socket对象是在效果内使用的。这创建了一个闭包,其中handleMessage函数和清理函数(socket.off('message'))隐式地依赖于当前的socket值。如果socket发生了变化(例如由于重新连接或重新初始化),那么您的效果将使用过时的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');
    };
  }, []); // Empty dependency array is now safe
}

为什么有效:

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

2. 使用 useCallback 优化处理器

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

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

  const handleMessage = useCallback((message) => {
    // Do something with the message and potentially someProp
    console.log(message, someProp);
  }, [someProp]); // Include dependencies of handleMessage

  useEffect(() => {
    const currentSocket = socketRef.current;
    currentSocket.on('message', handleMessage);
    return () => {
      currentSocket.off('message', handleMessage);
    };
  }, [handleMessage]); // Depend on the memoized handler
}

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();
    };
  }, []); // Empty array is correct - socket lifecycle managed within
}

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 缓存处理函数
    • 考虑套接字生命周期管理
  2. 性能优化

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

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

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

项目结构

src/
├── config.ts        # Configuration and API settings
├── fileUtils.ts     # File operations and language detection
├── index.ts         # Entry point
├── perplexity.ts   # Perplexity AI integration
├── server.ts       # MCP server implementation
├── stackOverflow.ts # Stack Overflow API integration
└── types.ts        # TypeScript interfaces

已知问题

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

相关 MCP 服务