Python MCP Server

local-only server

The server can only run on the client’s local machine because it depends on local resources.

Integrations

  • Provides configuration for use with Codeium Windsurf as an MCP-compatible client

用于代码图提取的 Python MCP 服务器

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

特征

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

get_python_code工具

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

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

安装

# Clone the repository git clone https://github.com/yourusername/python-mcp-new.git cd python-mcp-new # Create a virtual environment python -m venv venv source venv/bin/activate # On Windows, use: venv\Scripts\activate # Install dependencies pip install -r requirements.txt

环境变量

根据提供的.env.example创建一个.env文件:

# Token limit for extraction 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 # Get Python code structure for a specific file result = get_python_code( target_file="/home/user/project/main.py", root_repo_path="/home/user/project" # Optional, defaults to target file directory ) # Process the result target_file = result["target_file"] print(f"Main file: {target_file['file_path']}") print(f"Docstring: {target_file['docstring']}") # Display related files for ref_file in result["referenced_files"]: print(f"Related file: {ref_file['file_path']}") print(f"Object: {ref_file['object_name']}") print(f"Type: {ref_file['object_type']}") # See if we're close to the token limit print(f"Token usage: {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 available tools list_request = { "jsonrpc": "2.0", "id": 1, "method": "tools/list" } response = handle_mcp_request(list_request) print(json.dumps(response, indent=2))

响应示例(工具/列表)

{ "jsonrpc": "2.0", "id": 1, "result": { "tools": [ { "name": "get_python_code", "description": "Return the code of a target Python file and related files based on import/export proximity.", "inputSchema": { "type": "object", "properties": { "target_file": { "type": "string", "description": "Path to the Python file to analyze." }, "root_repo_path": { "type": "string", "description": "Root directory of the repository. If not provided, the directory of the target file will be used." } }, "required": ["target_file"] } } ] } }

调用 get_python_code 工具

from agent import handle_mcp_request import json # Call the get_python_code tool 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" # Optional } } } response = handle_mcp_request(tool_request) print(json.dumps(response, indent=2))

响应示例(工具/呼叫)

{ "jsonrpc": "2.0", "id": 2, "result": { "content": [ { "type": "text", "text": "Python code analysis for /home/user/project/main.py" }, { "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 # Call with invalid file path 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": "Error processing Python code: No such file or directory: '/path/to/nonexistent.py'" } ], "isError": true } }

测试

运行测试来验证功能:

python -m unittest discover tests

关键组件

  • agent.py :包含get_python_code函数和自定义 MCP 协议处理程序
  • code_grapher.py :实现用于 Python 代码分析的CodeGrapher
  • 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细绳始终“瞄准”
docstring细绳模块级文档字符串(如果可用)

引用的文件对象

场地类型描述
file_path细绳文件的相对路径
object_name细绳导入对象的名称(类、函数等)
object_type细绳对象的类型(“类”、“函数”等)
code细绳具体对象的源代码
docstring细绳对象的文档字符串(如果可用)
truncated布尔值代码是否因令牌限制而被截断

附加文件对象

场地类型描述
file_path细绳文件的相对路径
code细绳文件的完整源代码
type细绳关系类型(例如“related_by_directory”)
docstring细绳模块级文档字符串(如果可用)

使用 MCP SDK 服务器

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

启动服务器

# Start the server with default settings python run_server.py # Specify a custom name python run_server.py --name "My Code Explorer" # Use a specific .env file python run_server.py --env-file .env.production

使用 MCP 开发模式

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

# Install the MCP CLI pip install "mcp[cli]" # Start the server in development mode with the Inspector UI mcp dev server.py

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

Claude 桌面集成

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

# Install the server in Claude Desktop mcp install server.py # With custom configuration mcp install server.py --name "Python Code Explorer" -f .env

自定义服务器部署

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

from server import mcp # Configure the server mcp.name = "Custom Code Explorer" # Run the server mcp.run()

使用 MCP 客户端

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

from mcp.client import Client, Transport # Connect to the server client = Client(Transport.subprocess(["python", "server.py"])) client.initialize() # List available tools for tool in client.tools: print(f"Tool: {tool.name}") # Use the get_code tool result = client.tools.get_code(target_file="path/to/your/file.py") print(f"Found {len(result['referenced_files'])} referenced files") # Clean up client.shutdown()

运行示例:

python examples/mcp_client_example.py [optional_target_file.py]

添加其他工具

您可以通过在server.py中使用@mcp.tool()装饰器来装饰函数,从而向 MCP 服务器添加其他工具:

@mcp.tool() def analyze_imports(target_file: str) -> Dict[str, Any]: """Analyze all imports in a Python file.""" # Implementation code here return { "file": target_file, "imports": [], # List of imports found "analysis": "" # Analysis of the imports } @mcp.tool() def find_python_files(directory: str, pattern: str = "*.py") -> list[str]: """Find Python files matching a pattern in a directory.""" 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]: """Get statistics about Python files in a directory.""" 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 的更多信息,请参阅官方文档

ID: 4zt7hpbt5k