返回市场
python-mcp服务端

python-mcp服务端

作者:hesiod-au6 星标更新:2025-05-05

项目介绍

Python MCP Server for Code Graph Extraction

此MCP(模型上下文协议)服务器提供了用于提取和分析Python代码结构的工具,重点关注文件之间的导入/导出关系。这是一个轻量级实现,不需要代理系统,使其易于集成到任何Python应用程序中。

功能

  • 代码关系发现:分析Python文件之间的导入关系
  • 智能代码提取:仅提取最相关的代码部分以保持在令牌限制内
  • 目录上下文:包含同一目录中的文件以提供更好的上下文
  • 文档包含:始终包含README.md文件(或其变体)以提供项目文档
  • 适合语言模型的格式化:使用适当的元数据格式化代码
  • MCP协议支持:完全兼容模型上下文协议JSON-RPC标准

get_python_code 工具

该服务器公开了一个强大的代码提取工具,它:

  • 分析目标Python文件并发现所有导入的模块、类和函数
  • 返回目标文件的完整代码
  • 包含来自其他文件的所有引用对象的代码
  • 添加来自同一目录的额外上下文文件
  • 尊重令牌限制以避免压倒语言模型

安装

# 克隆仓库
git clone https://github.com/yourusername/python-mcp-new.git
cd python-mcp-new

# 创建虚拟环境
python -m venv venv
source venv/bin/activate  # 在Windows上使用:venv\Scripts\activate

# 安装依赖项
pip install -r requirements.txt

环境变量

基于提供的.env.example创建一个.env文件:

# 提取的令牌限制
TOKEN_LIMIT=8000

使用方法

配置MCP客户端

要为此MCP服务器配置MCP兼容客户端(如Codeium Windsurf),请向您的客户端MCP配置文件添加以下配置:

{
  "mcpServers": {
    "python-code-explorer": {
      "command": "python",
      "args": [
        "/path/to/python-mcp-new/server.py"
      ],
      "env": {
        "TOKEN_LIMIT": "8000"
      }
    }
  }
}

/path/to/python-mcp-new/server.py替换为您系统上server.py文件的实际绝对路径。

您还可以自定义环境变量:

  • TOKEN_LIMIT:代码提取的最大令牌限制(默认值:8000)

使用示例

直接函数调用

from agent import get_python_code

# 获取特定文件的Python代码结构
result = get_python_code(
    target_file="/home/user/project/main.py",
    root_repo_path="/home/user/project"  # 可选,默认为目标文件目录
)

# 处理结果
target_file = result["target_file"]
print(f"主文件:{target_file['file_path']}")
print(f"文档字符串:{target_file['docstring']}")

# 显示相关文件
for ref_file in result["referenced_files"]:
    print(f"相关文件:{ref_file['file_path']}")
    print(f"对象:{ref_file['object_name']}")
    print(f"类型:{ref_file['object_type']}")

# 查看是否接近令牌限制
print(f"令牌使用情况:{result['token_count']}/{result['token_limit']}")

示例响应(直接函数调用)

{
    "target_file": {
        "file_path": "main.py",
        "code": "import os\nimport sys\nfrom utils.helpers import format_output\n\ndef main():\n    args = sys.argv[1:]\n    if not args:\n        print('No arguments provided')\n        return\n    \n    result = format_output(args[0])\n    print(result)\n\nif __name__ == '__main__':\n    main()",
        "type": "target",
        "docstring": ""
    },
    "referenced_files": [
        {
            "file_path": "utils/helpers.py",
            "object_name": "format_output",
            "object_type": "function",
            "code": "def format_output(text):\n    \"\"\"Format the input text for display.\"\"\"\n    if not text:\n        return ''\n    return f'Output: {text.upper()}'\n",
            "docstring": "Format the input text for display.",
            "truncated": false
        }
    ],
    "additional_files": [
        {
            "file_path": "config.py",
            "code": "# Configuration settings\n\nDEBUG = True\nVERSION = '1.0.0'\nMAX_RETRIES = 3\n",
            "type": "related_by_directory",
            "docstring": "Configuration settings for the application."
        }
    ],
    "total_files": 3,
    "token_count": 450,
    "token_limit": 8000
}

使用MCP协议

列出可用工具

from agent import handle_mcp_request
import json

# 列出可用工具
list_request = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list"
}

response = handle_mcp_request(list_request)
print(json.dumps(response, indent=2))

示例响应(tools/list)

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "get_python_code",
        "description": "根据导入/导出关系返回目标Python文件及其相关文件的代码。",
        "inputSchema": {
          "type": "object",
          "properties": {
            "target_file": {
              "type": "string",
              "description": "要分析的Python文件的路径。"
            },
            "root_repo_path": {
              "type": "string",
              "description": "仓库的根目录。如果未提供,则使用目标文件的目录。"
            }
          },
          "required": ["target_file"]
        }
      }
    ]
  }
}

调用get_python_code工具

from agent import handle_mcp_request
import json

# 调用get_python_code工具
tool_request = {
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
        "name": "get_python_code",
        "arguments": {
            "target_file": "/home/user/project/main.py",
            "root_repo_path": "/home/user/project"  # 可选
        }
    }
}

response = handle_mcp_request(tool_request)
print(json.dumps(response, indent=2))

示例响应(tools/call)

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "对/home/user/project/main.py的Python代码分析"
      },
      {
        "type": "resource",
        "resource": {
          "uri": "resource://python-code/main.py",
          "mimeType": "application/json",
          "data": {
            "target_file": {
              "file_path": "main.py",
              "code": "import os\nimport sys\nfrom utils.helpers import format_output\n\ndef main():\n    args = sys.argv[1:]\n    if not args:\n        print('No arguments provided')\n        return\n    \n    result = format_output(args[0])\n    print(result)\n\nif __name__ == '__main__':\n    main()",
              "type": "target",
              "docstring": ""
            },
            "referenced_files": [
              {
                "file_path": "utils/helpers.py",
                "object_name": "format_output",
                "object_type": "function",
                "code": "def format_output(text):\n    \"\"\"Format the input text for display.\"\"\"\n    if not text:\n        return ''\n    return f'Output: {text.upper()}'\n",
                "docstring": "Format the input text for display.",
                "truncated": false
              }
            ],
            "additional_files": [
              {
                "file_path": "config.py",
                "code": "# Configuration settings\n\nDEBUG = True\nVERSION = '1.0.0'\nMAX_RETRIES = 3\n",
                "type": "related_by_directory",
                "docstring": "Configuration settings for the application."
              }
            ],
            "total_files": 3,
            "token_count": 450,
            "token_limit": 8000
          }
        }
      }
    ],
    "isError": false
  }
}

处理错误

from agent import handle_mcp_request

# 使用无效文件路径调用
faulty_request = {
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
        "name": "get_python_code",
        "arguments": {
            "target_file": "/path/to/nonexistent.py"
        }
    }
}

response = handle_mcp_request(faulty_request)
print(json.dumps(response, indent=2))

示例错误响应

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "处理Python代码时出错:没有这样的文件或目录:'/path/to/nonexistent.py'"
      }
    ],
    "isError": true
  }
}

测试

运行测试以验证功能:

python -m unittest discover tests

关键组件

  • agent.py:包含get_python_code函数和自定义MCP协议处理器
  • code_grapher.py:实现CodeGrapher类用于Python代码分析
  • server.py:使用MCP Python SDK实现的完整MCP服务器
  • run_server.py:用于运行MCP服务器的CLI工具
  • examples/:展示如何使用MCP服务器和客户端的示例脚本
  • tests/:涵盖所有功能的全面测试用例

响应格式详情

get_python_code工具返回一个结构化的JSON对象,包含以下字段:

字段类型描述
target_file对象关于目标Python文件的信息
referenced_files数组目标文件导入的对象列表
additional_files数组来自同一目录的额外上下文文件
total_files数字响应中包含的文件总数
token_count数字所有包含代码的大致令牌计数
token_limit数字提取配置的最大令牌限制

目标文件对象

字段类型描述
file_path字符串文件相对于仓库根目录的相对路径
code字符串文件的完整源代码
type字符串总是“target”
docstring字符串如果存在,模块级别的文档字符串

引用文件对象

字段类型描述
file_path字符串文件的相对路径
object_name字符串导入对象的名称(类、函数等)
object_type字符串对象的类型(“类”、“函数”等)
code字符串特定对象的源代码
docstring字符串如果存在,对象的文档字符串
truncated布尔值由于令牌限制,代码是否被截断

额外文件对象

字段类型描述
file_path字符串文件的相对路径
code字符串文件的完整源代码
type字符串关系类型(例如,“related_by_directory”)
docstring字符串如果存在,模块级别的文档字符串

使用MCP SDK服务器

该项目现在包括一个使用官方Python MCP SDK构建的全功能模型上下文协议(MCP)服务器。该服务器以标准化方式公开我们的代码提取功能,可以与任何MCP客户端一起使用,包括Claude Desktop。

启动服务器

# 使用默认设置启动服务器
python run_server.py

# 指定自定义名称
python run_server.py --name "我的代码探索器"

# 使用特定的.env文件
python run_server.py --env-file .env.production

使用MCP开发模式

安装了MCP SDK后,您可以使用MCP CLI以开发模式运行服务器:

# 安装MCP CLI
pip install "mcp[cli]"

# 使用Inspector UI以开发模式启动服务器
mcp dev server.py

这将启动MCP Inspector,这是一个用于测试和调试服务器的Web界面。

Claude Desktop集成

您可以在Claude Desktop中安装服务器,以便直接从Claude访问代码探索工具:

# 在Claude Desktop中安装服务器
mcp install server.py

# 使用自定义配置
mcp install server.py --name "Python代码探索器" -f .env

自定义服务器部署

对于自定义部署,您可以直接使用MCP服务器:

from server import mcp

# 配置服务器
mcp.name = "自定义代码探索器"

# 运行服务器
mcp.run()

使用MCP客户端

您可以使用MCP Python SDK以编程方式连接到服务器。请参阅提供的示例examples/mcp_client_example.py

from mcp.client import Client, Transport

# 连接到服务器
client = Client(Transport.subprocess(["python", "server.py"]))
client.initialize()

# 列出可用工具
for tool in client.tools:
    print(f"工具:{tool.name}")

# 使用get_code工具
result = client.tools.get_code(target_file="path/to/your/file.py")
print(f"找到{len(result['referenced_files'])}个引用文件")

# 清理
client.shutdown()

运行示例:

python examples/mcp_client_example.py [可选的目标文件.py]

添加额外工具

您可以通过在server.py中使用@mcp.tool()装饰器来添加额外的工具:

@mcp.tool()
def analyze_imports(target_file: str) -> Dict[str, Any]:
    """分析Python文件中的所有导入。"""
    # 实现代码
    return {
        "file": target_file,
        "imports": [],  # 找到的导入列表
        "analysis": ""  # 导入的分析
    }
    
@mcp.tool()
def find_python_files(directory: str, pattern: str = "*.py") -> list[str]:
    """查找目录中匹配模式的Python文件。"""
    from pathlib import Path
    return [str(p) for p in Path(directory).glob(pattern) if p.is_file()]

您还可以添加资源端点以直接提供数据:

@mcp.resource("python_stats://{directory}")
def get_stats(directory: str) -> Dict[str, Any]:
    """获取目录中Python文件的统计信息。"""
    from pathlib import Path
    stats = {
        "directory": directory,
        "file_count": 0,
        "total_lines": 0,
        "average_lines": 0
    }
    
    files = list(Path(directory).glob("**/*.py"))
    stats["file_count"] = len(files)
    
    if files:
        total_lines = 0
        for file in files:
            with open(file, "r") as f:
                total_lines += len(f.readlines())
        stats["total_lines"] = total_lines
        stats["average_lines"] = total_lines / len(files)
    
    return stats

模型上下文协议集成

该项目完全采用了模型上下文协议(MCP)标准,提供了两种实现选项:

  1. 原生MCP集成agent.py中的原始实现提供了与MCP兼容的直接JSON-RPC接口。
  2. MCP SDK集成server.py中的新实现利用了官方MCP Python SDK,提供了更强大和丰富的体验。

MCP集成的好处

  • 标准化接口:使您的工具可用于任何MCP兼容客户端
  • 增强的安全性:内置权限模型和资源控制
  • 更好的LLM集成:与Claude Desktop和其他LLM平台无缝集成
  • 改进的开发者体验:全面的工具,如MCP Inspector

MCP协议版本

此实现支持MCP协议版本0.7.0。

有关MCP的更多信息,请参阅官方文档