Integración de FastMCP con el código Claude
Integración de FastMCP con Claude Code
Claude Code es la herramienta oficial de línea de comandos (CLI) de Anthropic que soporta servidores MCP, permitiéndote expandir las capacidades de Claude con tus servidores FastMCP personalizados. Esta integración facilita flujos de trabajo de desarrollo potentes donde Claude puede acceder a tus herramientas, recursos y funcionalidades específicas de tu dominio.
¿Por qué integrar con Claude Code?
La integración con Claude Code ofrece varios beneficios atractivos:
- Flujo de trabajo de desarrollo mejorado: Accede a tus herramientas personalizadas directamente desde Claude.
- Asistencia con conciencia de contexto: Claude puede leer los recursos y la configuración de tu proyecto.
- Tareas automatizadas: Ejecuta operaciones complejas a través de tus herramientas MCP.
- Soporte local y remoto: Conéctate tanto a servidores de desarrollo locales como a servicios desplegados.
- Interacción en tiempo real: Descubrimiento y ejecución dinámica de herramientas.
Configuración de tu servidor FastMCP
Creación de un servidor de desarrollo
Vamos a crear un servidor FastMCP completo diseñado para flujos de trabajo de desarrollo:
# dev_server.py
import os
import subprocess
import json
from pathlib import Path
from datetime import datetime
from fastmcp import FastMCP, Context
mcp = FastMCP(
name="Development Assistant",
instructions="""
Este servidor proporciona herramientas de desarrollo que incluyen:
- Análisis de proyectos y operaciones de archivos
- Operaciones Git y gestión de repositorios
- Comprobaciones de calidad de código y pruebas
- Gestión de entornos y dependencias
"""
)
@mcp.tool
def run_command(command: str, cwd: str = ".") -> dict:
"""Ejecuta un comando de shell y devuelve el resultado."""
try:
result = subprocess.run(
command.split(),
cwd=cwd,
capture_output=True,
text=True,
timeout=30
)
return {
"command": command,
"returncode": result.returncode,
"stdout": result.stdout,
"stderr": result.stderr,
"success": result.returncode == 0
}
except subprocess.TimeoutExpired:
return {"error": "El comando excedió el tiempo de espera (30 segundos)"}
except Exception as e:
return {"error": str(e)}
@mcp.tool
def analyze_project_structure(path: str = ".") -> dict:
"""Analiza la estructura de un directorio de proyecto."""
project_path = Path(path)
if not project_path.exists():
return {"error": f"La ruta {path} no existe"}
structure = {
"root": str(project_path.absolute()),
"files": [],
"directories": [],
"python_files": [],
"config_files": [],
"total_size": 0
}
config_extensions = {".json", ".yaml", ".yml", ".toml", ".ini", ".cfg"}
for item in project_path.rglob("*"):
if item.is_file():
size = item.stat().st_size
structure["total_size"] += size
file_info = {
"path": str(item.relative_to(project_path)),
"size": size,
"modified": datetime.fromtimestamp(item.stat().st_mtime).isoformat()
}
structure["files"].append(file_info)
if item.suffix == ".py":
structure["python_files"].append(file_info)
elif item.suffix in config_extensions:
structure["config_files"].append(file_info)
elif item.is_dir():
structure["directories"].append(str(item.relative_to(project_path)))
return structure
@mcp.tool
async def check_code_quality(file_path: str, ctx: Context) -> dict:
"""Verifica la calidad del código usando varias herramientas de linting."""
await ctx.info(f"Verificando la calidad del código para {file_path}...")
if not os.path.exists(file_path):
return {"error": f"Archivo {file_path} no encontrado"}
results = {"file": file_path, "checks": {}}
# Check with different tools
tools = {
"flake8": ["flake8", file_path],
"pylint": ["pylint", file_path, "--output-format=json"],
"mypy": ["mypy", file_path]
}
for tool, command in tools.items():
try:
result = subprocess.run(
command,
capture_output=True,
text=True,
timeout=15
)
results["checks"][tool] = {
"returncode": result.returncode,
"output": result.stdout,
"errors": result.stderr
}
except (subprocess.TimeoutExpired, FileNotFoundError):
results["checks"][tool] = {"error": f"{tool} no disponible o tiempo de espera excedido"}
return results
@mcp.resource("project://config")
def get_project_config() -> dict:
"""Obtiene la configuración del proyecto a partir de varios archivos de configuración."""
config = {"found_files": [], "configurations": {}}
config_files = [
"pyproject.toml", "setup.py", "requirements.txt",
"package.json", "Dockerfile", ".env", "config.yaml"
]
for config_file in config_files:
if os.path.exists(config_file):
config["found_files"].append(config_file)
try:
with open(config_file, 'r') as f:
content = f.read()
config["configurations"][config_file] = {
"content": content[:1000] + ("..." if len(content) > 1000 else ""),
"size": len(content)
}
except Exception as e:
config["configurations"][config_file] = {"error": str(e)}
return config
@mcp.resource("git://status")
def get_git_status() -> dict:
"""Obtiene el estado actual del repositorio Git."""
try:
# Check if we're in a git repository
subprocess.run(["git", "rev-parse", "--git-dir"],
check=True, capture_output=True)
# Get various git information
commands = {
"branch": ["git", "branch", "--show-current"],
"status": ["git", "status", "--porcelain"],
"last_commit": ["git", "log", "-1", "--pretty=format:%H|%an|%ad|%s"],
"remote": ["git", "remote", "-v"]
}
result = {}
for key, command in commands.items():
try:
output = subprocess.run(
command, capture_output=True, text=True, check=True
).stdout.strip()
result[key] = output
except subprocess.CalledProcessError:
result[key] = "no disponible"
return result
except subprocess.CalledProcessError:
return {"error": "No es un repositorio git"}
if __name__ == "__main__":
mcp.run(transport="http", host="127.0.0.1", port=8000)
Conexión a Claude Code
Ejecución de tu servidor
Primero, inicia tu servidor FastMCP:
# Inicia el servidor en modo HTTP
python dev_server.py
Tu servidor estará funcionando en http://127.0.0.1:8000/mcp/
Añadir el servidor a Claude Code
Usa los comandos de gestión de MCP de Claude Code para añadir tu servidor:
# Añade tu servidor FastMCP
claude mcp add dev-assistant --transport http http://localhost:8000/mcp/
# Verifica que el servidor esté conectado
claude mcp list
Alternativa: transporte STDIO
Para el desarrollo local, podrías preferir el transporte STDIO:
# dev_server_stdio.py
# ... (mismo código de servidor que el anterior)
if __name__ == "__main__":
mcp.run() # Usa STDIO por defecto
Añádelo a Claude Code:
claude mcp add dev-assistant --transport stdio "python dev_server_stdio.py"
Uso de tu servidor con Claude Code
Una vez conectado, puedes interactuar con tu servidor MCP a través de Claude Code:
Uso básico de herramientas
# Claude descubrirá y usará automáticamente tus herramientas
claude "Analiza la estructura de mi proyecto actual"
# Claude llamará a tu herramienta analyze_project_structure
# La respuesta incluirá el recuento de archivos, tamaños y organización
Acceso a recursos
Claude puede acceder a los recursos de tu servidor usando las menciones @
:
# Accede a la configuración del proyecto
claude "¿Qué archivos de configuración tiene este proyecto? Usa @dev-assistant:project://config"
# Verifica el estado de git
claude "¿Cuál es el estado actual de git? Usa @dev-assistant:git://status"
Flujos de trabajo complejos
Combina múltiples herramientas para operaciones sofisticadas:
claude "Por favor, verifica la calidad del código de todos los archivos Python en el directorio src/ y resume los problemas"
# Claude hará lo siguiente:
# 1. Usar analyze_project_structure para encontrar archivos Python
# 2. Usar check_code_quality en cada archivo
# 3. Resumir los resultados
Ejemplos de configuración avanzada
Servidor de desarrollo con herramientas de base de datos
# db_server.py
import sqlite3
from fastmcp import FastMCP
mcp = FastMCP("Database Tools")
@mcp.tool
def query_database(query: str, db_path: str = "app.db") -> dict:
"""Ejecuta una consulta SQL en la base de datos."""
try:
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute(query)
if query.strip().upper().startswith("SELECT"):
results = cursor.fetchall()
columns = [description[0] for description in cursor.description]
return {
"columns": columns,
"rows": results,
"count": len(results)
}
else:
conn.commit()
return {"affected_rows": cursor.rowcount}
except Exception as e:
return {"error": str(e)}
finally:
conn.close()
@mcp.resource("db://schema")
def get_database_schema() -> dict:
"""Obtiene la información del esquema de la base de datos."""
# Implementación para leer el esquema de la base de datos
pass
if __name__ == "__main__":
mcp.run(transport="http", port=8001)
Servidor de pruebas de API
# api_server.py
import requests
from fastmcp import FastMCP, Context
mcp = FastMCP("API Testing Tools")
@mcp.tool
async def test_api_endpoint(url: str, method: str = "GET",
headers: dict = None, data: dict = None,
ctx: Context = None) -> dict:
"""Prueba un endpoint de API y devuelve resultados detallados."""
await ctx.info(f"Probando {method} {url}...")
try:
response = requests.request(
method=method.upper(),
url=url,
headers=headers or {},
json=data,
timeout=10
)
return {
"url": url,
"method": method.upper(),
"status_code": response.status_code,
"headers": dict(response.headers),
"response_time": response.elapsed.total_seconds(),
"body": response.text[:1000] if response.text else None,
"success": 200 <= response.status_code < 300
}
except Exception as e:
return {
"url": url,
"method": method.upper(),
"error": str(e),
"success": False
}
if __name__ == "__main__":
mcp.run(transport="http", port=8002)
Configuración de múltiples servidores
Puedes conectar varios servidores FastMCP a Claude Code:
# Añade varios servidores
claude mcp add dev-tools --transport http http://localhost:8000/mcp/
claude mcp add db-tools --transport http http://localhost:8001/mcp/
claude mcp add api-tools --transport http http://localhost:8002/mcp/
# Claude ahora puede acceder a todos los servidores
claude "Revisa la estructura del proyecto y luego prueba los endpoints de la API definidos en la configuración"
Solución de problemas comunes
El servidor no responde
# Verifica si el servidor está en ejecución
curl http://localhost:8000/mcp/
# Elimina y vuelve a añadir el servidor
claude mcp remove dev-assistant
claude mcp add dev-assistant --transport http http://localhost:8000/mcp/
Herramienta no encontrada
Asegúrate de que tu servidor esté registrado correctamente y las herramientas estén decoradas:
# Asegúrate de que las herramientas estén bien decoradas
@mcp.tool # Este decorador es necesario
def my_tool():
pass
Problemas de acceso a recursos
Verifica el formato del URI del recurso:
# Formato correcto
claude "Usa @server-name:resource://uri"
# No @server-name/resource://uri
Mejores prácticas para la integración con Claude Code
- Nombres de herramientas claros: Usa nombres de herramientas descriptivos y autoexplicativos.
- Buena documentación: Incluye docstrings completos.
- Manejo de errores: Proporciona mensajes de error significativos.
- Organización de recursos: Usa esquemas de URI lógicos para los recursos.
- Rendimiento: Mantén tiempos de ejecución de herramientas razonables.
- Seguridad: Valida las entradas y restringe las operaciones peligrosas.
Próximos pasos
Con tu servidor FastMCP integrado en Claude Code, puedes:
- Crear asistentes de desarrollo específicos de tu dominio.
- Automatizar tareas complejas de gestión de proyectos.
- Desarrollar herramientas personalizadas de análisis y calidad de código.
- Crear flujos de trabajo especializados para pruebas y despliegues.
En la sección final, exploraremos patrones avanzados, despliegue en producción y estrategias de escalado para tus servidores FastMCP.