Python MCP Server for Code Graph Extraction
Extrae y analiza estructuras de código Python, centrándose en las relaciones de importación/exportación.
Documentación
Python MCP Server for Code Graph Extraction
Este servidor MCP (Model Context Protocol) proporciona herramientas para extraer y analizar estructuras de código Python, centrándose en las relaciones de importación/exportación entre archivos. Es una implementación ligera que no requiere un sistema de agentes, lo que facilita su integración en cualquier aplicación Python.
Características
- Descubrimiento de relaciones de código: Analiza las relaciones de importación entre archivos Python
- Extracción inteligente de código: Extrae solo las secciones de código más relevantes para mantenerse dentro de los límites de tokens
- Contexto de directorio: Incluye archivos del mismo directorio para proporcionar un mejor contexto
- Inclusión de documentación: Siempre incluye archivos README.md (o variantes) para proporcionar documentación del proyecto
- Formato amigable para LLM: Formatea el código con metadatos adecuados para modelos de lenguaje
- Soporte del protocolo MCP: Totalmente compatible con el estándar JSON-RPC del Model Context Protocol
La herramienta get_python_code
El servidor expone una potente herramienta de extracción de código que:
- Analiza un archivo Python objetivo y descubre todos los módulos, clases y funciones importados
- Devuelve el código completo del archivo objetivo
- Incluye el código de todos los objetos referenciados de otros archivos
- Añade archivos contextuales adicionales del mismo directorio
- Respeta los límites de tokens para no abrumar a los modelos de lenguaje
Instalación
# 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
Variables de entorno
Crea un archivo .env basado en el .env.example proporcionado:
# Token limit for extraction
TOKEN_LIMIT=8000
Uso
Configuración para clientes MCP
Para configurar este servidor MCP para su uso en clientes compatibles con MCP (como Codeium Windsurf), añade la siguiente configuración al archivo de configuración MCP de tu cliente:
{
"mcpServers": {
"python-code-explorer": {
"command": "python",
"args": [
"/path/to/python-mcp-new/server.py"
],
"env": {
"TOKEN_LIMIT": "8000"
}
}
}
}
Reemplaza /path/to/python-mcp-new/server.py con la ruta absoluta al archivo server.py en tu sistema.
También puedes personalizar las variables de entorno:
TOKEN_LIMIT: Límite máximo de tokens para la extracción de código (por defecto: 8000)
Ejemplos de uso
Llamada directa a la función
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']}")
Ejemplo de respuesta (llamada directa a la función)
{
"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
}
Uso del protocolo MCP
Listado de herramientas disponibles
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))
Ejemplo de respuesta (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"]
}
}
]
}
}
Llamada a la herramienta 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))
Ejemplo de respuesta (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
}
}
Manejo de errores
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))
Ejemplo de respuesta de error
{
"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
}
}
Pruebas
Ejecuta las pruebas para verificar la funcionalidad:
python -m unittest discover tests
Componentes clave
- agent.py: Contiene la función
get_python_codey los manejadores personalizados del protocolo MCP - code_grapher.py: Implementa la clase
CodeGrapherpara el análisis de código Python - server.py: Implementación completa del servidor MCP utilizando el SDK de MCP para Python
- run_server.py: Herramienta CLI para ejecutar el servidor MCP
- examples/: Scripts de ejemplo que muestran cómo usar el servidor y el cliente MCP
- tests/: Casos de prueba exhaustivos para toda la funcionalidad
Detalles del formato de respuesta
La herramienta get_python_code devuelve un objeto JSON estructurado con los siguientes campos:
| Campo | Tipo | Descripción |
|---|---|---|
target_file | Object | Información sobre el archivo Python objetivo |
referenced_files | Array | Lista de objetos importados por el archivo objetivo |
additional_files | Array | Archivos de contexto adicionales del mismo directorio |
total_files | Number | Número total de archivos incluidos en la respuesta |
token_count | Number | Recuento aproximado de tokens en todo el código incluido |
token_limit | Number | Límite máximo de tokens configurado para la extracción |
Objeto de archivo objetivo
| Campo | Tipo | Descripción |
|---|---|---|
file_path | String | Ruta relativa al archivo desde la raíz del repositorio |
code | String | Código fuente completo del archivo |
type | String | Siempre "target" |
docstring | String | Docstring a nivel de módulo si está disponible |
Objeto de archivo referenciado
| Campo | Tipo | Descripción |
|---|---|---|
file_path | String | Ruta relativa al archivo |
object_name | String | Nombre del objeto importado (clase, función, etc.) |
object_type | String | Tipo del objeto ("class", "function", etc.) |
code | String | Código fuente del objeto específico |
docstring | String | Docstring del objeto si está disponible |
truncated | Boolean | Indica si el código fue truncado debido a los límites de tokens |
Objeto de archivo adicional
| Campo | Tipo | Descripción |
|---|---|---|
file_path | String | Ruta relativa al archivo |
code | String | Código fuente completo del archivo |
type | String | Tipo de relación (por ejemplo, "related_by_directory") |
docstring | String | Docstring a nivel de módulo si está disponible |
Uso del servidor SDK de MCP
Este proyecto ahora incluye un servidor Model Context Protocol (MCP) completo, construido con el SDK oficial de MCP para Python. El servidor expone nuestra funcionalidad de extracción de código de forma estandarizada que puede utilizarse con cualquier cliente MCP, incluido Claude Desktop.
Inicio del 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
Uso del modo de desarrollo de MCP
Con el SDK de MCP instalado, puedes ejecutar el servidor en modo de desarrollo utilizando la CLI de MCP:
# Install the MCP CLI
pip install "mcp[cli]"
# Start the server in development mode with the Inspector UI
mcp dev server.py
Esto iniciará el MCP Inspector, una interfaz web para probar y depurar tu servidor.
Integración con Claude Desktop
Puedes instalar el servidor en Claude Desktop para acceder a tus herramientas de exploración de código directamente desde Claude:
# Install the server in Claude Desktop
mcp install server.py
# With custom configuration
mcp install server.py --name "Python Code Explorer" -f .env
Despliegue personalizado del servidor
Para despliegues personalizados, puedes usar el servidor MCP directamente:
from server import mcp
# Configure the server
mcp.name = "Custom Code Explorer"
# Run the server
mcp.run()
Uso del cliente MCP
Puedes usar el SDK de MCP para Python para conectarte al servidor programáticamente. Consulta el ejemplo proporcionado en 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()
Ejecuta el ejemplo:
python examples/mcp_client_example.py [optional_target_file.py]
Añadir herramientas adicionales
Puedes añadir herramientas adicionales al servidor MCP decorando funciones con el decorador @mcp.tool() en 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()]
También puedes añadir endpoints de recursos para proporcionar datos directamente:
@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
Integración con el Model Context Protocol
Este proyecto adopta plenamente el estándar Model Context Protocol (MCP), ofreciendo dos opciones de implementación:
-
Integración MCP nativa: La implementación original en
agent.pyproporciona una interfaz JSON-RPC directa compatible con MCP. -
Integración con el SDK de MCP: La nueva implementación en
server.pyutiliza el SDK oficial de MCP para Python para una experiencia más robusta y rica en funciones.
Beneficios de la integración con MCP
- Interfaz estandarizada: Hace que tus herramientas estén disponibles para cualquier cliente compatible con MCP
- Seguridad mejorada: Modelo de permisos integrado y controles de recursos
- Mejor integración con LLM: Integración perfecta con Claude Desktop y otras plataformas de LLM
- Experiencia de desarrollo mejorada: Herramientas integrales como el MCP Inspector
Versión del protocolo MCP
Esta implementación es compatible con la versión 0.7.0 del protocolo MCP.
Para obtener más información sobre MCP, consulta la documentación oficial.