Saltar al contenido
K0lateral
Programación

Cómo construir un asistente de código MCP (Model Context Protocol) local con ...

· Foto: Pexels

Automatiza tu codigo con inteligencia artificial paso a paso.

Cómo construir un asistente de código MCP (Model Context Protocol) local con ...
Foto: Pexels

El ecosistema de asistentes de código ha evolucionado rápidamente, pero la dependencia de servicios cloud como GitHub Copilot o ChatGPT genera preocupaciones sobre privacidad, costos y latencia. Aquí entra el Model Context Protocol (MCP), un estándar abierto que permite a modelos de lenguaje interactuar directamente con herramientas y sistemas locales sin enviar datos a la nube.

MCP define una capa de comunicación entre el modelo y el entorno, similar a cómo HTTP estructura las peticiones web. Con MCP, puedes construir un asistente que lea archivos, ejecute comandos, analice código y devuelva respuestas contextualizadas, todo corriendo en tu máquina. Combinado con Ollama (gestor de modelos locales) y Python, tienes un stack completo para crear un asistente de código privado, rápido y personalizable.

En este artículo práctico, construirás desde cero un asistente MCP que entiende tu proyecto, sugiere refactors y ejecuta scripts, usando modelos como CodeLlama o Mistral.

Configuración del entorno: Ollama + Python

Paso 1: Instalar Ollama y descargar un modelo

Ollama simplifica la ejecución de modelos locales. Instálalo desde ollama.com y luego descarga un modelo optimizado para código:

PROMPT# Instalar en Linux/macOS (curl) curl -fsSL https://ollama.com/install.sh | sh Descargar CodeLlama (7B parámetros, ideal para código) ollama pull codellama:7b Alternativa: Mistral (buen balance general) ollama pull mistral Verifica que el modelo funciona:

PROMPTollama run codellama:7b "Escribe una función en Python que calcule factorial"

Paso 2: Configurar el proyecto Python

Crea un entorno virtual e instala las dependencias clave:

PROMPTmkdir asistente-mcp && cd asistente-mcp python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate pip install ollama-python mcp python-dotenv - ollama-python: Cliente oficial para interactuar con Ollama.

  • mcp: Librería para implementar el protocolo MCP.
  • python-dotenv: Para gestionar configuraciones sensibles.

Crea un archivo .env con:

PROMPTMODEL_NAME=codellama:7b WORKSPACE_PATH=./proyecto_ejemplo

Construcción del asistente MCP: Arquitectura y código

El corazón del asistente: servidor MCP

El asistente se compone de un servidor MCP que expone herramientas (leer archivos, ejecutar comandos) y un cliente que usa el modelo para decidir qué herramientas invocar.

Crea servidor_mcp.py:

PROMPTimport os import subprocess from mcp import Server, Tool, Resource from mcp.types import TextContent class AsistenteMCPServer: def __init__(self, workspace_path): self.workspace = workspace_path self.server = Server("asistente-codigo") Registrar herramientas self.server.add_tool( Tool( name="leer_archivo", description="Lee el contenido de un archivo en el workspace", input_schema={ "type": "object", "properties": { "ruta": {"type": "string", "description": "Ruta relativa al workspace"} }, "required": ["ruta"] }, handler=self.leer_archivo ) ) self.server.add_tool( Tool( name="ejecutar_comando", description="Ejecuta un comando shell (uso seguro)", input_schema={ "type": "object", "properties": { "comando": {"type": "string"}, "timeout": {"type": "integer", "default": 30} }, "required": ["comando"] }, handler=self.ejecutar_comando ) ) Recurso: lista de archivos del proyecto self.server.add_resource( Resource( uri="file://proyecto/estructura", name="Estructura del proyecto", description="Árbol de directorios del workspace", handler=self.obtener_estructura ) ) async def leer_archivo(self, ruta: str) -> TextContent: ruta_completa = os.path.join(self.workspace, ruta) if not os.path.exists(ruta_completa): return TextContent(type="text", text=C%F3mo%20construir%20un%20asistente%20de%20c%F3digo%20MCP%20%28Model%20Context%20Protocol%29%20local%20con%20..."Error: Archivo {ruta} no encontrado") with open(ruta_completa, 'r') as f: contenido = f.read() return TextContent(type="text", text=contenido) async def ejecutar_comando(self, comando: str, timeout: int = 30) -> TextContent: try: resultado = subprocess.run( comando, shell=True, capture_output=True, text=True, timeout=timeout, cwd=self.workspace ) salida = resultado.stdout + resultado.stderr return TextContent(type="text", text=salida[:2000]) # Limitar tamaño except subprocess.TimeoutExpired: return TextContent(type="text", text="Error: Comando excedió tiempo límite") async def obtener_estructura(self) -> TextContent: estructura = [] for root, dirs, files in os.walk(self.workspace): nivel = root.replace(self.workspace, '').count(os.sep) indent = ' ' 2 nivel estructura.append(f"{indent}{os.path.basename(root)}/") subindent = ' ' 2 (nivel + 1) for file in files: estructura.append(f"{subindent}{file}") return TextContent(type="text", text="\n".join(estructura)) async def iniciar(self): await self.server.start()

Cliente inteligente que usa el modelo

Ahora crea cliente_mcp.py, el orquestador que recibe preguntas del usuario y usa el modelo para decidir acciones:

PROMPTimport ollama from servidor_mcp import AsistenteMCPServer import asyncio import os from dotenv import load_dotenv load_dotenv() class ClienteAsistente: def __init__(self, modelo: str, servidor: AsistenteMCPServer): self.modelo = modelo self.servidor = servidor self.historial = [] async def procesar_consulta(self, consulta: str) -> str: Construir contexto con herramientas disponibles herramientas = self.servidor.server.tools recursos = self.servidor.server.resources prompt_sistema = f"""Eres un asistente de código experto. Tienes acceso a estas herramientas: {', '.join([f"{t.name}: {t.description}" for t in herramientas])} Recursos disponibles: {', '.join([r.name for r in recursos])} Reglas: 1. Si necesitas información del proyecto, usa las herramientas disponibles. 2. Responde en español, salvo que el código esté en otro idioma. 3. Proporciona explicaciones claras de cada acción. 4. Si ejecutas comandos, explica qué harán. Consulta del usuario: {consulta}

Obtener respuesta del modelo

respuesta = ollama.chat(

model=self.modelo,

messages=[

{"role": "system", "content": prompt_sistema},

{"role": "user", "content": consulta}

],

stream=False

)

texto_respuesta = respuesta['message']['content']

Detectar si el modelo quiere usar herramientas (formato: TOOL:nombre|parametros)

if "TOOL:" in texto_respuesta:

partes = texto_respuesta.split("TOOL:")

for parte in partes[1:]:

nombre_herramienta, params = parte.split("|", 1)

nombre_herramienta = nombre_herramienta.strip()

if nombre_herramienta == "leer_archivo":

resultado = await self.servidor.leer_archivo(params.strip())

texto_respuesta += f"\n\nResultado de {nombre_herramienta}:\n{resultado.text}"

elif nombre_herramienta == "ejecutar_comando":

resultado = await self.servidor.ejecutar_comando(params.strip())

texto_respuesta += f"\n\nResultado de {nombre_herramienta}:\n{resultado.text}"

self.historial.append({"consulta": consulta, "respuesta": texto_respuesta})

return texto_respuesta

async def main():

Configurar

workspace = os.getenv("WORKSPACE_PATH", "./proyecto_ejemplo")

modelo = os.getenv("MODEL_NAME", "codellama:7b")

Crear proyecto de ejemplo si no existe

os.makedirs(workspace, exist_ok=True)

with open(os.path.join(workspace, "main.py"), "w") as f:

f.write("""def factorial(n):

if n == 0:

return 1

return n * factorial(n-1)

def fibonacci(n):

if n

Más sobre Programación

Ver todo →