CrewAI y MCP: cómo construir equipos de agentes IA y conectarlos con cualquier herramienta

Qué es CrewAI
CrewAI es un framework de Python para orquestar equipos de agentes de IA autónomos. La idea es simple: en lugar de pedirle a un solo modelo que haga todo, creás un crew (equipo) de agentes especializados, cada uno con un rol, objetivo y backstory propios, que trabajan juntos como un equipo humano.
Con más de 100,000 desarrolladores certificados, CrewAI se ha posicionado como el framework líder para workflows enterprise donde los agentes tienen responsabilidades claras y trabajan en secuencia o jerarquía.
CrewAI vs otros frameworks
| Necesitás | Elegí |
|---|---|
| Workflows estructurados, role-based | CrewAI |
| State machines con branching condicional | LangGraph |
| Coordinación conversacional, chat-driven | AG2 / AutoGen |
| Autonomía total, planificación independiente | AutoGPT |
CrewAI brilla en workflows donde los agentes tienen responsabilidades claras y trabajan en una secuencia predecible. Si necesitás state management con branching, LangGraph da más control. Si tus agentes necesitan back-and-forth conversacional, AG2 (el fork comunitario de AutoGen) es mejor.
Instalación
Requisitos
- Python >=3.10 y <3.14 (verificar con
python --version) - API key de un LLM provider (OpenAI, Anthropic, Google Gemini, etc.)
uvpackage manager (recomendado por CrewAI)
Paso 1: Instalar uv
curl -LsSf https://astral.sh/uv/install.sh | sh
Paso 2: Instalar CrewAI CLI
uv tool install crewai
Alternativa con pip
pip install 'crewai[tools]'
Paso 3: Verificar instalación
crewai --version
Crear tu primer crew
1. Scaffold del proyecto
crewai create crew research_crew
cd research_crew
Esto genera la estructura completa:
research_crew/
├── .gitignore
├── pyproject.toml
├── README.md
├── .env # API keys
└── src/
└── research_crew/
├── __init__.py
├── main.py # Entry point
├── crew.py # Orquestación
├── tools/
│ ├── custom_tool.py
│ └── __init__.py
└── config/
├── agents.yaml # Definir agentes
└── tasks.yaml # Definir tareas
2. Configurar API key
Editar .env:
OPENAI_API_KEY=sk-...
# o
GEMINI_API_KEY=...
# o
ANTHROPIC_API_KEY=sk-ant-...
3. Definir agentes (agents.yaml)
# src/research_crew/config/agents.yaml
researcher:
role: >
Senior Research Analyst for {topic}
goal: >
Find accurate, up-to-date information on {topic}
backstory: >
You are a meticulous researcher with 10 years of experience.
You cross-reference multiple sources before reporting findings.
tools:
- SerperDevTool
- ScrapeWebsiteTool
verbose: true
writer:
role: >
Technical Content Writer
goal: >
Turn raw research into a clear, structured report
backstory: >
You write for a technical audience that values precision
over filler. Every claim must cite its source.
verbose: true
allow_delegation: false
4. Definir tareas (tasks.yaml)
# src/research_crew/config/tasks.yaml
research_task:
description: >
Search for the latest developments on {topic}.
Focus on announcements from the past 30 days.
Include source URLs for every claim.
expected_output: >
A structured list of 5-10 findings, each with a
one-sentence summary and source URL.
agent: researcher
report_task:
description: >
Using the research findings, write a 500-word technical
briefing on {topic}. Cite all sources inline.
expected_output: >
A markdown-formatted report with sections for key findings,
analysis, and source list.
agent: writer
output_file: "output/report.md"
5. Ejecutar
crewai install
crewai run
Programa equivalente en Python
from crewai import LLM, Agent, Crew, Task, Process
# Configurar LLM (Gemini free via Google AI Studio)
llm = LLM(model="gemini/gemini-2.5-flash")
# Agente 1: Investigador
researcher = Agent(
role="Researcher",
goal="Find accurate information on renewable energy",
backstory="You are a meticulous researcher with 10 years of experience.",
llm=llm,
verbose=True,
)
# Agente 2: Escritor
writer = Agent(
role="Writer",
goal="Turn raw research into a clear, structured report",
backstory="You write for a technical audience that values precision.",
llm=llm,
verbose=True,
)
# Tareas
research_task = Task(
description="Research the latest trends in renewable energy",
expected_output="A detailed list of the top 5 trends with explanations",
agent=researcher,
)
writing_task = Task(
description="Write a 300-word article based on the research",
expected_output="A well-structured article on renewable energy trends",
agent=writer,
)
# Crew (ejecución secuencial)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential,
verbose=True,
)
result = crew.kickoff()
print(result.raw)
Cuando llamás crew.kickoff(), el investigador completa su tarea primero y su output fluye automáticamente al escritor como contexto.
Tools: dándole capacidades a los agentes
Sin tools, los agentes solo pueden generar texto basado en su entrenamiento. Las tools son funciones que los agentes pueden llamar:
| Tool | Qué hace |
|---|---|
SerperDevTool | Búsqueda web via Serper API |
ScrapeWebsiteTool | Scrapea contenido de una URL |
FileReadTool | Lee archivos locales |
DirectoryReadTool | Lista contenido de directorios |
| Custom tools | Tus propias funciones Python |
Crear una tool custom
from crewai.tools import tool
@tool("Calculate Revenue")
def calculate_revenue(price: float, units: int) -> str:
"""Calculate total revenue from price and units sold."""
revenue = price * units
return f"Total revenue: ${revenue:,.2f}"
Flows: orquestación event-driven
Los Flows son la característica de CrewAI para workflows event-driven donde el orden de ejecución está garantizado por lógica determinística. Dentro de cada step, un agente puede aplicar judgment.
Crear un Flow
crewai create flow guide_creator_flow
cd guide_creator_flow
Estructura de un Flow
from crewai.flow.flow import Flow, listen, start
from pydantic import BaseModel, Field
class GuideState(BaseModel):
topic: str = ""
audience_level: str = ""
outline: list = Field(default_factory=list)
class GuideCreatorFlow(Flow[GuideState]):
@start()
def get_user_input(self):
self.state.topic = input("Topic? ")
self.state.audience_level = input("Audience? ")
return self.state
@listen(get_user_input)
def create_outline(self, state):
# LLM call directo para crear outline
self.state.outline = ["intro", "core", "conclusion"]
return self.state
@listen(create_outline)
def generate_sections(self, state):
# Llamar a un crew para cada sección
for section in self.state.outline:
kickoff_content_crew({"section": section})
Los Flows soportan: branching condicional (router nodes), crews embebidas en un step, HITL (Human-in-the-Loop), y export a código fuente real.
Crew Studio: el Automated Agent Builder
Crew Studio (julio 2026) es el builder visual de agentes de CrewAI. Describís el workflow en lenguaje natural y Studio lo diseña, construye, conecta y deploya:
"When a new support ticket arrives, classify it,
pull the account history, draft a response,
and post a summary to the team channel."
Studio diseña la arquitectura del flow, crea los steps, configura el agente en cada uno y wirea las integraciones. Usa best practices extraídas de 700K+ patrones de uso de la comunidad open source.
Características de Crew Studio
- 1,000+ conectores: CRM, support, messaging, productivity, marketing, dev tools
- Single-agent nodes: tareas focalizadas con su propio task definition y model selection
- Crew nodes: un multi-agent team entero embebido en un step
- Router nodes: branching condicional
- Agent repository: agentes reutilizables org-wide
- Export a código: cualquier flow es código real, versionable
- Test, trace, ship: Run function, Output y Traces tabs, deploy desde el mismo lugar
Modelos soportados
CrewAI es model-agnostic. No estás lock-in a un proveedor:
- OpenAI (GPT-5.x)
- Anthropic (Claude Opus/Sonnet/Haiku)
- Google (Gemini 2.5 Flash/Pro — gratis via Google AI Studio)
- Mistral
- Groq
- Ollama (modelos locales)
Comparación con AutoGen y LangGraph
| Feature | CrewAI | AutoGen (AG2) | LangGraph |
|---|---|---|---|
| Arquitectura | Role-based, jerárquica | Event-driven, conversacional | State machines |
| Multi-agent | ✅ Built-in | ✅ Built-in | Requiere setup |
| Memoria | Compartida entre agentes | Thread-based | State management |
| Curva de aprendizaje | Media | Media | Alta |
| Ideal para | Enterprise automation | Research, dev | Complex state logic |
| Observabilidad | AMP Suite | Enhanced | LangSmith |
| GUI visual | Crew Studio | AutoGen Studio | LangGraph Studio |
Mejores prácticas
- Un rol por agente: no mezcles responsabilidades
- Backstory importa: el LLM usa el backstory para calibrar respuestas
- expected_output detallado: cuanto más específico, mejor el resultado
- Usá context explícito:
context=[research_task]para dependencias - allow_delegation: false para agentes que no deben delegar
- Verbose en desarrollo: apagalo en producción
- Tools expanden capacidades: sin tools, los agentes solo generan texto
Model Context Protocol (MCP): la guía completa
Qué es MCP
El Model Context Protocol es un estándar open-source que permite a las aplicaciones de IA conectarse con sistemas externos de forma estructurada y consistente. Es como USB-C para la IA: un conector universal entre modelos y herramientas.
Con MCP, aplicaciones como Claude, Cursor, Replit o ChatGPT pueden acceder a archivos locales, consultar databases, correr tools, interactuar con APIs —todo a través del mismo protocolo estandarizado.
Arquitectura cliente-servidor
MCP usa un modelo cliente-servidor:
- Host: la aplicación de IA (Claude Desktop, Cursor, VS Code)
- Client: conexión persistente dentro del host
- Server: programa que expone capabilities al host
Un host puede conectar múltiples servers simultáneamente, cada uno con su client dedicado.
Capas del protocolo
| Capa | Función |
|---|---|
| Transport | Mecánica de comunicación: stdio (local) o Streamable HTTP (remoto) |
| Data | JSON-RPC 2.0 para intercambio de mensajes |
Los 3 primitivos de un MCP server
| Primitivo | Qué es | Quién lo controla | Ejemplos |
|---|---|---|---|
| Tools | Funciones que el LLM puede llamar activamente | Modelo (IA decide) | Buscar vuelos, enviar mensajes, crear events |
| Resources | Datos read-only para contexto | Aplicación | Contenido de archivos, schemas de DB, docs de API |
| Prompts | Templates pre-built para guiar al modelo | Usuario | Planear vacaciones, resumir meetings, redactar email |
Construir un MCP server en Python
Instalar el SDK
uv add "mcp[cli]"
# o
pip install "mcp[cli]"
Server en 15 líneas
from mcp.server import MCPServer
mcp = MCPServer("Demo")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
"""Greet someone by name."""
return f"Hello, {name}!"
Sin JSON Schema manual (los type hints son el schema), sin request parsing, sin validation code, sin protocol handling. Dos funciones Python con type hints y docstrings.
Probar con MCP Inspector
uv run mcp dev server.py
Llamá add con a=1, b=2 y obtenés 3.
Instalar en Claude Desktop
mcp install server.py
Construir un MCP client
import asyncio
from mcp import Client
from server import mcp
async def main() -> None:
async with Client(mcp) as client:
result = await client.call_tool("add", {"a": 1, "b": 2})
print(result.structured_content) # {'result': 3}
asyncio.run(main())
Cambiá mcp por "http://localhost:8000/mcp" y el mismo código habla con un server remoto.
Ejemplo práctico: server de clima
from mcp.server import MCPServer
import httpx2
mcp = MCPServer("weather")
NWS_API_BASE = "https://api.weather.gov"
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
async with httpx2.AsyncClient() as client:
response = await client.get(url, headers={"User-Agent": "weather-app/1.0"})
data = response.json()
if not data.get("features"):
return "No active alerts"
alerts = [format_alert(f) for f in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location."""
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
# ... fetch and return forecast
MCP en las herramientas principales
| Herramienta | Soporte MCP | Cómo |
|---|---|---|
| Claude Code | ✅ Nativo (reference impl) | claude mcp add o .mcp.json |
| Cursor | ✅ Nativo first-class | Settings → MCP |
| VS Code | ✅ Via extensión | Extension marketplace |
| Replit | ✅ Integrado | Agent configura automáticamente |
| GitHub Copilot | ⚠️ Limitado | Via extensions |
| Windsurf | ⚠️ Parcial | Workspace settings |
Scopes de configuración en Claude Code
- User scope (
--scope user): disponible en todos los proyectos. Ideal para tools personales (Linear, Notion) - Project scope (
--scope project): commiteado a.mcp.json, compartido con el team. Ideal para tools específicos del proyecto (Supabase, GitHub repo) - Local scope (default): solo esta máquina, este proyecto
Servers MCP populares
| Server | Qué expone |
|---|---|
@modelcontextprotocol/server-filesystem | Read/write archivos locales |
@modelcontextprotocol/server-github | Repos, issues, PRs de GitHub |
@modelcontextprotocol/server-postgres | Queries a PostgreSQL |
@modelcontextprotocol/server-slack | Mensajes y canales de Slack |
@modelcontextprotocol/server-google-drive | Documentos de Google Drive |
| Supabase MCP | Database, auth, storage de Supabase |
Conclusión
CrewAI y MCP resuelven problemas complementarios: CrewAI te deja orquestar equipos de agentes especializados con roles claros y workflows estructurados, mientras MCP estandariza cómo esos agentes se conectan con el mundo exterior.
La combinación es poderosa: un crew de CrewAI donde cada agente tiene acceso a tools MCP puede investigar en la web, consultar tu database, leer archivos de Google Drive y enviar mensajes a Slack —todo coordinado en un workflow determinístico. Para equipos que necesitan automatización enterprise con control y observabilidad, esta combinación es el camino.