此MCP(模型上下文协议)服务器提供了用于提取和分析Python代码结构的工具,重点关注文件之间的导入/导出关系。这是一个轻量级实现,不需要代理系统,使其易于集成到任何Python应用程序中。
get_python_code 工具该服务器公开了一个强大的代码提取工具,它:
# 克隆仓库
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兼容客户端(如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
}
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))
{
"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"]
}
}
]
}
}
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))
{
"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
get_python_code函数和自定义MCP协议处理器CodeGrapher类用于Python代码分析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 | 字符串 | 如果存在,模块级别的文档字符串 |
该项目现在包括一个使用官方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 SDK后,您可以使用MCP CLI以开发模式运行服务器:
# 安装MCP CLI
pip install "mcp[cli]"
# 使用Inspector UI以开发模式启动服务器
mcp dev server.py
这将启动MCP Inspector,这是一个用于测试和调试服务器的Web界面。
您可以在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 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)标准,提供了两种实现选项:
agent.py中的原始实现提供了与MCP兼容的直接JSON-RPC接口。server.py中的新实现利用了官方MCP Python SDK,提供了更强大和丰富的体验。此实现支持MCP协议版本0.7.0。
有关MCP的更多信息,请参阅官方文档。