Python MCP Server for Code Graph Extraction
Extrai e analisa estruturas de código Python, com foco em relações de importação/exportação.
Documentação
Python MCP Server for Code Graph Extraction
Este servidor MCP (Model Context Protocol) fornece ferramentas para extrair e analisar estruturas de código Python, com foco nas relações de importação/exportação entre arquivos. Esta é uma implementação leve que não requer um sistema de agente, facilitando a integração em qualquer aplicação Python.
Recursos
- Descoberta de Relações de Código: Analisa relações de importação entre arquivos Python
- Extração Inteligente de Código: Extrai apenas as seções de código mais relevantes para permanecer dentro dos limites de tokens
- Contexto de Diretório: Inclui arquivos do mesmo diretório para fornecer melhor contexto
- Inclusão de Documentação: Sempre inclui arquivos README.md (ou variantes) para fornecer documentação do projeto
- Formatação Amigável para LLM: Formata código com metadados adequados para modelos de linguagem
- Suporte ao Protocolo MCP: Totalmente compatível com o padrão JSON-RPC do Model Context Protocol
A Ferramenta get_python_code
O servidor expõe uma ferramenta poderosa de extração de código que:
- Analisa um arquivo Python alvo e descobre todos os módulos, classes e funções importados
- Retorna o código completo do arquivo alvo
- Inclui código para todos os objetos referenciados de outros arquivos
- Adiciona arquivos contextuais adicionais do mesmo diretório
- Respeita os limites de tokens para evitar sobrecarregar modelos de linguagem
Instalação
# 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
Variáveis de Ambiente
Crie um arquivo .env com base no .env.example fornecido:
# Token limit for extraction
TOKEN_LIMIT=8000
Uso
Configurando para Clientes MCP
Para configurar este servidor MCP para uso em clientes compatíveis com MCP (como Codeium Windsurf), adicione a seguinte configuração ao arquivo de configuração MCP do seu cliente:
{
"mcpServers": {
"python-code-explorer": {
"command": "python",
"args": [
"/path/to/python-mcp-new/server.py"
],
"env": {
"TOKEN_LIMIT": "8000"
}
}
}
}
Substitua /path/to/python-mcp-new/server.py pelo caminho absoluto para o arquivo server.py no seu sistema.
Você também pode personalizar as variáveis de ambiente:
TOKEN_LIMIT: Limite máximo de tokens para extração de código (padrão: 8000)
Exemplos de Uso
Chamada Direta de Função
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']}")
Exemplo de Resposta (Chamada Direta de Função)
{
"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
}
Usando o Protocolo MCP
Listando Ferramentas Disponíveis
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))
Exemplo de Resposta (tools/list)
{
"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"]
}
}
]
}
}
Chamando a Ferramenta 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))
Exemplo de Resposta (tools/call)
{
"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
}
}
Tratamento de Erros
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))
Exemplo de Resposta de Erro
{
"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
}
}
Testes
Execute os testes para verificar a funcionalidade:
python -m unittest discover tests
Componentes Principais
- agent.py: Contém a função
get_python_codee manipuladores personalizados do protocolo MCP - code_grapher.py: Implementa a classe
CodeGrapherpara análise de código Python - server.py: Implementação completa do servidor MCP usando o SDK Python MCP
- run_server.py: Ferramenta CLI para executar o servidor MCP
- examples/: Scripts de exemplo mostrando como usar o servidor e o cliente MCP
- tests/: Casos de teste abrangentes para toda a funcionalidade
Detalhes do Formato de Resposta
A ferramenta get_python_code retorna um objeto JSON estruturado com os seguintes campos:
| Campo | Tipo | Descrição |
|---|---|---|
target_file | Objeto | Informações sobre o arquivo Python alvo |
referenced_files | Array | Lista de objetos importados pelo arquivo alvo |
additional_files | Array | Arquivos de contexto adicionais do mesmo diretório |
total_files | Número | Número total de arquivos incluídos na resposta |
token_count | Número | Contagem aproximada de tokens em todo o código incluído |
token_limit | Número | Limite máximo de tokens configurado para extração |
Objeto de Arquivo Alvo
| Campo | Tipo | Descrição |
|---|---|---|
file_path | String | Caminho relativo para o arquivo a partir da raiz do repositório |
code | String | Código-fonte completo do arquivo |
type | String | Sempre "target" |
docstring | String | Docstring de nível de módulo, se disponível |
Objeto de Arquivo Referenciado
| Campo | Tipo | Descrição |
|---|---|---|
file_path | String | Caminho relativo para o arquivo |
object_name | String | Nome do objeto importado (classe, função, etc.) |
object_type | String | Tipo do objeto ("class", "function", etc.) |
code | String | Código-fonte do objeto específico |
docstring | String | Docstring do objeto, se disponível |
truncated | Booleano | Se o código foi truncado devido aos limites de tokens |
Objeto de Arquivo Adicional
| Campo | Tipo | Descrição |
|---|---|---|
file_path | String | Caminho relativo para o arquivo |
code | String | Código-fonte completo do arquivo |
type | String | Tipo de relação (ex.: "related_by_directory") |
docstring | String | Docstring de nível de módulo, se disponível |
Usando o Servidor com SDK MCP
Este projeto agora inclui um servidor Model Context Protocol (MCP) completo, construído com o Python MCP SDK oficial. O servidor expõe nossa funcionalidade de extração de código de forma padronizada, que pode ser usada com qualquer cliente MCP, incluindo o Claude Desktop.
Iniciando o Servidor
# 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
Usando o Modo de Desenvolvimento MCP
Com o SDK MCP instalado, você pode executar o servidor em modo de desenvolvimento usando a CLI MCP:
# Install the MCP CLI
pip install "mcp[cli]"
# Start the server in development mode with the Inspector UI
mcp dev server.py
Isso iniciará o MCP Inspector, uma interface web para testar e depurar seu servidor.
Integração com Claude Desktop
Você pode instalar o servidor no Claude Desktop para acessar suas ferramentas de exploração de código diretamente do Claude:
# Install the server in Claude Desktop
mcp install server.py
# With custom configuration
mcp install server.py --name "Python Code Explorer" -f .env
Implantação Personalizada do Servidor
Para implantações personalizadas, você pode usar o servidor MCP diretamente:
from server import mcp
# Configure the server
mcp.name = "Custom Code Explorer"
# Run the server
mcp.run()
Usando o Cliente MCP
Você pode usar o SDK Python MCP para conectar-se ao servidor programaticamente. Veja o exemplo fornecido em 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()
Execute o exemplo:
python examples/mcp_client_example.py [optional_target_file.py]
Adicionando Ferramentas Adicionais
Você pode adicionar ferramentas adicionais ao servidor MCP decorando funções com o decorador @mcp.tool() em server.py:
@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()]
Você também pode adicionar endpoints de recursos para fornecer dados diretamente:
@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
Integração com Model Context Protocol
Este projeto adota totalmente o padrão Model Context Protocol (MCP), oferecendo duas opções de implementação:
-
Integração MCP Nativa: A implementação original em
agent.pyfornece uma interface JSON-RPC direta compatível com MCP. -
Integração com SDK MCP: A nova implementação em
server.pyutiliza o SDK Python MCP oficial para uma experiência mais robusta e rica em recursos.
Benefícios da Integração MCP
- Interface Padronizada: Disponibiliza suas ferramentas para qualquer cliente compatível com MCP
- Segurança Aprimorada: Modelo de permissões e controles de recursos integrados
- Melhor Integração com LLM: Integração perfeita com Claude Desktop e outras plataformas de LLM
- Experiência de Desenvolvimento Aprimorada: Ferramentas abrangentes como o MCP Inspector
Versão do Protocolo MCP
Esta implementação suporta a versão 0.7.0 do Protocolo MCP.
Para mais informações sobre MCP, consulte a documentação oficial.