Introduction to Model Context Protocol — Resumen de estudio
Paths: Developer · Architect · FDE · 14 lecciones, 12 videos (hands-on con el SDK de Python y
uv)Construir servidores y clientes MCP desde cero y entender sus 3 primitives: tools, resources y prompts.
1. Qué es MCP y qué problema resuelve
- Una capa de comunicación que le da contexto y tools a Claude sin que tengas que escribir todo el código de integración: la definición y la ejecución de las tools pasan de tu servidor a servidores MCP especializados.
- Arquitectura: MCP Client (tu servidor) ↔ MCP Servers (exponen tools, prompts y resources; cada uno es la interfaz a un servicio externo).
- Ejemplo GitHub: sin MCP tendrías que escribir y mantener decenas de schemas y funciones (repos, PRs, issues…). Con el MCP server de GitHub, alguien más ya lo hizo.
- ¿Quién escribe los servidores? Cualquiera; a menudo el propio proveedor (p. ej. AWS).
- MCP ≠ tool use: son complementarios.
- MCP trae los schemas y funciones ya hechos.
- Tool use es cómo Claude llama a esas tools.
- La diferencia está en quién hizo el trabajo.
2. El cliente MCP
- Es el puente con los servidores; se encarga del intercambio de mensajes del protocolo.
- Transport-agnostic: stdio (lo más común, en la misma máquina), HTTP, WebSockets, etc.
- Mensajes clave:
ListToolsRequest/Result("¿qué tools tienes?") yCallToolRequest/Result(ejecutar una tool con argumentos). - Flujo completo:
- El usuario pregunta.
- Tu servidor pide al cliente la lista de tools (ListTools).
- Envías la consulta + las tools a Claude.
- Claude decide usar una tool.
- Tu servidor pide al cliente ejecutarla (CallTool); el servidor MCP llama a la API.
- El resultado vuelve a Claude, que responde.
3. Construir un servidor (Python SDK)
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("DocumentMCP", log_level="ERROR")
@mcp.tool(name="read_doc_contents",
description="Read the contents of a document and return it as a string.")
def read_document(doc_id: str = Field(description="Id of the document to read")):
if doc_id not in docs: raise ValueError(f"Doc with id {doc_id} not found")
return docs[doc_id]
- Decoradores + type hints +
Fieldde Pydantic → el SDK genera el JSON schema; los errores se manejan con excepciones de Python. - Ejemplo de edición:
edit_document(doc_id, old_str, new_str)hace un find & replace.
4. MCP Inspector
mcp dev mcp_server.py(ouv run mcp dev ...) abre un inspector en el navegador (≈http://127.0.0.1:6274).- Connect → Tools → List Tools → elige una tool, completa los inputs → Run Tool. Mantiene el estado entre llamadas (editas y luego lees).
- Sirve para iterar, probar edge cases y depurar sin una app completa.
5. Implementar el cliente
- Dos componentes: tu clase MCP Client (facilita el uso y limpia los recursos) + la Client Session del SDK (la conexión).
- Normalmente implementas o el cliente o el servidor; el curso hace ambos para ver cómo encajan.
async def list_tools(self): return (await self.session().list_tools()).tools
async def call_tool(self, name, inp): return await self.session().call_tool(name, inp)
- Se prueba con
uv run mcp_client.pyy luegouv run main.py("What is the contents of the report.pdf document?").
6. Resources (datos de solo lectura, como un GET)
- Para traer información, no para ejecutar acciones. Caso de uso: menciones
@documento(autocompletado + inyectar el contenido en el prompt sin que Claude tenga que llamar una tool). - Mensajes:
ReadResourceRequest(con URI) →ReadResourceResult. - Direct: URI fija.
``python @mcp.resource("docs://documents", mime_type="application/json") def list_docs(): return list(docs.keys()) ``
- Templated: parámetros en la URI, que el SDK pasa como kwargs.
``python @mcp.resource("docs://documents/{doc_id}", mime_type="text/plain") def fetch_doc(doc_id: str): ... ``
mime_typeorienta al cliente (application/json,text/plain,application/pdf). El SDK serializa automáticamente.- Cliente:
read_resource(uri)→result.contents[0]; si el MIME es JSON se hacejson.loads, si no se devuelve el texto. El Inspector separa "Resources" y "Resource Templates".
7. Prompts (plantillas de instrucciones probadas)
- El autor del servidor diseña, prueba y evalúa prompts mejores de lo que escribiría un usuario. Ventajas: consistencia, experiencia del dominio, reutilización y mantenimiento en un solo lugar.
@mcp.prompt(name="format", description="Rewrites the contents of the document in Markdown format.")
def format_document(doc_id: str = Field(...)) -> list[base.Message]:
return [base.UserMessage(f"...<document_id>{doc_id}</document_id>... use 'edit_document'...")]
- Devuelven una lista de mensajes (user/assistant). En el cliente aparecen como slash commands (
/format plan.md). - Cliente:
list_prompts()yget_prompt(name, args); los argumentos se interpolan como kwargs.
8. Cómo elegir el primitive (repaso)
| Primitive | Lo controla | Para qué | Ejemplo en Claude.ai |
|---|---|---|---|
| Tools | El modelo | Darle capacidades nuevas a Claude | Ejecutar código o hacer cálculos |
| Resources | La app | Datos para la UI o para dar contexto | "Add from Google Drive" |
| Prompts | El usuario | Workflows predefinidos que se disparan a demanda | Botones de workflow bajo el input |
"Las tools sirven al modelo, los resources a tu app y los prompts a tus usuarios."
Evaluación final (tus respuestas, 6 de 7)
- Componentes del cliente → la clase MCP Client + la Client Session.
- Descubrir tools →
ListToolsRequest. - Probar el servidor sin una app → MCP Inspector (
mcp dev mcp_server.py). - El problema sin MCP → escribir y mantener todo el código de las tools de GitHub tú mismo (la fallaste).
- Botón de "resumir documento" que dispara el usuario → Prompts.
- Definir una tool en Python → decorador
@mcp.tool(). - Recurso por ID (
docs://documents/report.pdf) → templated resource.