[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-construye-primer-servidor-mcp-guia-practica-desarrolladores":3},{"article":4,"author":50},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":7,"meta_description":16,"focus_keyword":17,"og_image":18,"canonical_url":18,"robots_meta":19,"created_at":15,"updated_at":15,"tags":20,"category_name":30,"related_articles":31},"d0000000-0000-0000-0000-000000000519","a0000000-0000-0000-0000-000000000086","Construye tu primer servidor MCP: guia practica para desarrolladores","construye-primer-servidor-mcp-guia-practica-desarrolladores","Un tutorial practico paso a paso para construir un servidor Model Context Protocol (MCP) en TypeScript y Python, conectarlo a Claude Desktop o Cursor y desplegarlo en produccion.","## Que es el Model Context Protocol (MCP)?\n\nEl **Model Context Protocol (MCP)** es un estandar abierto creado por Anthropic que define como las aplicaciones de AI se comunican con fuentes de datos y herramientas externas. Piensa en MCP como el **USB-C para la integracion de AI**: asi como USB-C proporciona un unico conector universal para carga, transferencia de datos y salida de pantalla, MCP proporciona un unico protocolo universal para conectar modelos de AI a bases de datos, APIs, sistemas de archivos y cualquier otro servicio. MCP elimina la necesidad de integraciones personalizadas entre cada aplicacion de AI y cada herramienta.\n\nEn 2026, MCP se ha convertido en el estandar dominante para la comunicacion AI-herramientas. Gartner predice que **el 40 % de las aplicaciones empresariales incluiran agentes de AI para finales de 2026**, y MCP es el protocolo que hace esto practico a gran escala. Antes de MCP, conectar un modelo de AI a N herramientas requeria N integraciones personalizadas. Con M aplicaciones de AI y N herramientas, se necesitaban M x N adaptadores de integracion. MCP reduce esto a M + N: cada aplicacion de AI implementa un MCP client, cada herramienta implementa un MCP server.\n\n## Arquitectura MCP: Host, Client, Server y Transport\n\nComprender la arquitectura MCP es esencial antes de escribir codigo. El protocolo define cuatro roles clave:\n\n| Componente | Rol | Ejemplo |\n|------------|-----|---------|\n| **Host** | La aplicacion de AI con la que interactua el usuario final | Claude Desktop, Cursor, VS Code Copilot |\n| **Client** | El manejador del protocolo MCP dentro del host | Integrado en la aplicacion host |\n| **Server** | Expone tools, resources y prompts a traves de MCP | Tu servidor personalizado (lo que vamos a construir) |\n| **Transport** | La capa de comunicacion entre client y server | stdio, HTTP+SSE, Streamable HTTP |\n\nEl flujo de comunicacion funciona asi:\n\n1. El **Host** arranca e inicializa un MCP **Client** para cada servidor configurado.\n2. El **Client** se conecta al **Server** a traves de un **Transport** (stdio para local, HTTP para remoto).\n3. El **Client** envia una solicitud `initialize`, negociando la version del protocolo y las capacidades.\n4. El **Server** responde con sus **tools**, **resources** y **prompts** disponibles.\n5. Cuando el modelo de AI necesita datos o acciones externas, el **Client** llama al metodo del servidor apropiado.\n6. El **Server** ejecuta la operacion y devuelve los resultados a traves de mensajes JSON-RPC 2.0.\n\n### Tools vs Resources vs Prompts\n\nLos MCP servers pueden exponer tres tipos de capacidades:\n\n- **Tools** son funciones que el modelo de AI puede llamar. Aceptan entrada estructurada y devuelven salida estructurada. Ejemplo: `query_database(sql: string)` o `send_email(to: string, subject: string, body: string)`.\n- **Resources** son datos que el modelo de AI puede leer. Se identifican por URIs y devuelven contenido. Ejemplo: `file:\u002F\u002F\u002Fpath\u002Fto\u002Fdocument.md` o `postgres:\u002F\u002Flocalhost\u002Fmydb\u002Fusers`.\n- **Prompts** son plantillas de prompts reutilizables proporcionadas por el servidor. Ayudan a estandarizar como la AI interactua con el dominio del servidor. Ejemplo: una plantilla `summarize_ticket` para un Jira MCP server.\n\n## Paso a paso: construir un servidor MCP en TypeScript\n\nConstruyamos un servidor MCP practico que proporcione una herramienta para consultar una base de datos SQLite. Este es un caso de uso comun: dar a un modelo de AI acceso seguro de solo lectura a los datos de tu aplicacion.\n\n### Paso 1: Inicializar el proyecto\n\n```bash\nmkdir mcp-sqlite-server && cd mcp-sqlite-server\nnpm init -y\nnpm install @modelcontextprotocol\u002Fsdk better-sqlite3\nnpm install -D typescript @types\u002Fnode @types\u002Fbetter-sqlite3\nnpx tsc --init\n```\n\nConfigurar `tsconfig.json`:\n\n```json\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"Node16\",\n    \"moduleResolution\": \"Node16\",\n    \"outDir\": \".\u002Fdist\",\n    \"rootDir\": \".\u002Fsrc\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"declaration\": true\n  },\n  \"include\": [\"src\u002F**\u002F*\"]\n}\n```\n\n### Paso 2: Implementar el servidor\n\nCrear `src\u002Findex.ts`:\n\n```typescript\nimport { McpServer } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fmcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fstdio.js\";\nimport Database from \"better-sqlite3\";\nimport { z } from \"zod\";\n\nconst db = new Database(process.env.DB_PATH || \".\u002Fdata.db\", {\n  readonly: true,\n});\n\nconst server = new McpServer({\n  name: \"sqlite-query\",\n  version: \"1.0.0\",\n});\n\nserver.tool(\n  \"query\",\n  \"Ejecutar una consulta SQL de solo lectura en la base de datos SQLite\",\n  {\n    sql: z.string().describe(\"La consulta SQL SELECT a ejecutar\"),\n  },\n  async ({ sql }) => {\n    const normalized = sql.trim().toUpperCase();\n    if (!normalized.startsWith(\"SELECT\")) {\n      return {\n        content: [{ type: \"text\", text: \"Error: solo se permiten consultas SELECT.\" }],\n        isError: true,\n      };\n    }\n    try {\n      const rows = db.prepare(sql).all();\n      return {\n        content: [{ type: \"text\", text: JSON.stringify(rows, null, 2) }],\n      };\n    } catch (error) {\n      return {\n        content: [{ type: \"text\", text: `Error de consulta: ${(error as Error).message}` }],\n        isError: true,\n      };\n    }\n  }\n);\n\nserver.tool(\n  \"list_tables\",\n  \"Listar todas las tablas de la base de datos con sus esquemas\",\n  {},\n  async () => {\n    const tables = db\n      .prepare(\n        `SELECT name, sql FROM sqlite_master\n         WHERE type='table' AND name NOT LIKE 'sqlite_%'\n         ORDER BY name`\n      )\n      .all();\n    return {\n      content: [{ type: \"text\", text: JSON.stringify(tables, null, 2) }],\n    };\n  }\n);\n```\n\n### Paso 3: Compilar y probar localmente\n\n```bash\nnpx tsc\necho '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-03-26\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0\"}}}' | node dist\u002Findex.js\n```\n\nDeberas ver una respuesta JSON-RPC con las capacidades del servidor.\n\n### Paso 4: Construir el mismo servidor en Python\n\nPara desarrolladores Python, aqui esta la implementacion equivalente usando el SDK oficial de Python para MCP:\n\n```python\nimport sqlite3\nimport json\nfrom mcp.server.fastmcp import FastMCP\n\nmcp = FastMCP(\"sqlite-query\")\nDB_PATH = \"data.db\"\n\n@mcp.tool()\ndef query(sql: str) -> str:\n    \"\"\"Ejecutar una consulta SQL de solo lectura en la base de datos SQLite.\"\"\"\n    normalized = sql.strip().upper()\n    if not normalized.startswith(\"SELECT\"):\n        raise ValueError(\"Solo se permiten consultas SELECT.\")\n    conn = sqlite3.connect(DB_PATH)\n    conn.row_factory = sqlite3.Row\n    try:\n        cursor = conn.execute(sql)\n        rows = [dict(row) for row in cursor.fetchall()]\n        return json.dumps(rows, indent=2, default=str)\n    finally:\n        conn.close()\n\n@mcp.tool()\ndef list_tables() -> str:\n    \"\"\"Listar todas las tablas de la base de datos con sus esquemas.\"\"\"\n    conn = sqlite3.connect(DB_PATH)\n    conn.row_factory = sqlite3.Row\n    try:\n        cursor = conn.execute(\n            \"SELECT name, sql FROM sqlite_master \"\n            \"WHERE type='table' AND name NOT LIKE 'sqlite_%'\"\n        )\n        tables = [dict(row) for row in cursor.fetchall()]\n        return json.dumps(tables, indent=2)\n    finally:\n        conn.close()\n\nif __name__ == \"__main__\":\n    mcp.run(transport=\"stdio\")\n```\n\n## Conexion a Claude Desktop\n\nClaude Desktop soporta servidores MCP de forma nativa. Para conectar tu servidor, edita el archivo de configuracion de Claude Desktop:\n\n**macOS:** `~\u002FLibrary\u002FApplication Support\u002FClaude\u002Fclaude_desktop_config.json`\n**Windows:** `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-query\": {\n      \"command\": \"node\",\n      \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"DB_PATH\": \"\u002Fabsolute\u002Fpath\u002Fto\u002Fyour\u002Fdata.db\"\n      }\n    }\n  }\n}\n```\n\nReinicia Claude Desktop. Veras un icono de martillo en la interfaz de chat indicando las herramientas MCP disponibles. Ahora puedes hacer preguntas a Claude como \"Que tablas hay en la base de datos?\" o \"Muestra los 10 principales usuarios por fecha de registro\" y Claude usara tu servidor MCP para consultar la base de datos directamente.\n\n## Conexion a Cursor\n\nCursor tambien soporta servidores MCP. Agrega la configuracion a `.cursor\u002Fmcp.json` en la raiz de tu proyecto:\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-query\": {\n      \"command\": \"node\",\n      \"args\": [\".\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"DB_PATH\": \".\u002Fdata.db\"\n      }\n    }\n  }\n}\n```\n\nDespues de guardar, reinicia Cursor. Las herramientas MCP aparecen en el panel del asistente de AI y pueden invocarse durante las sesiones de generacion de codigo y depuracion.\n\n## Pruebas y depuracion de tu servidor MCP\n\n### Uso del MCP Inspector\n\nEl MCP Inspector es la herramienta oficial de depuracion. Proporciona una interfaz web para interactuar con tu servidor:\n\n```bash\nnpx @modelcontextprotocol\u002Finspector node dist\u002Findex.js\n```\n\nEsto abre una interfaz de navegador en `http:\u002F\u002Flocalhost:5173` donde puedes:\n\n- Ver todos los tools, resources y prompts registrados\n- Llamar a tools con entradas personalizadas e inspeccionar las respuestas\n- Monitorear el flujo de mensajes JSON-RPC en tiempo real\n- Probar el manejo de errores enviando solicitudes malformadas\n\n### Problemas comunes de depuracion\n\n| Problema | Causa | Solucion |\n|----------|-------|----------|\n| El servidor no aparece en Claude Desktop | Ruta de configuracion o error de sintaxis JSON | Validar JSON, verificar rutas absolutas |\n| Error \"Tool not found\" | Los tools no estan registrados antes de conectar | Registrar tools antes de llamar a `server.connect()` |\n| Timeout en llamadas a tools | Operacion de larga duracion sin progreso | Agregar notificaciones de progreso via `server.sendProgress()` |\n| La salida stderr corrompe el protocolo | console.log escribe en stdout (transporte stdio) | Usar `console.error()` para logging con stdio |\n| Desconexion despues de inactividad | Timeout del transporte | Implementar heartbeat o usar transporte HTTP |\n\n## Mejores practicas para produccion\n\n1. **Validacion de entradas**: Siempre valida y sanea las entradas de los tools. Usa esquemas Zod (TypeScript) o modelos Pydantic (Python) para verificacion de tipos estricta.\n\n2. **Solo lectura por defecto**: Comienza con acceso de solo lectura. Solo agrega capacidades de escritura cuando sea realmente necesario, y siempre solicita confirmacion para operaciones destructivas.\n\n3. **Manejo de errores**: Devuelve mensajes de error estructurados con `isError: true`. Nunca expongas stack traces internos o cadenas de conexion a la base de datos.\n\n4. **Registro**: Registra todas las llamadas a tools con marca de tiempo, entradas y duracion de ejecucion. Usa stderr para logging (no stdout) con el transporte stdio.\n\n5. **Limitacion de velocidad**: Implementa limites de velocidad por tool para evitar que bucles de AI no controlados sobrecarguen tus servicios backend.\n\n6. **Timeout**: Establece timeouts de ejecucion en todos los handlers de tools. Los modelos de AI pueden llamar a tools que disparen consultas costosas — protege tu infraestructura.\n\n7. **Separacion de entornos**: Usa variables de entorno para toda la configuracion. Nunca codifiques en duro URLs de bases de datos, claves API o rutas de archivos.\n\n8. **Versionado**: Usa versionado semantico para tu servidor MCP. El handshake `initialize` incluye negociacion de versiones — los cambios incompatibles requieren un bump de version mayor.\n\n## FAQ\n\n**P: Cual es la diferencia entre MCP y function calling?**\nR: El function calling (usado por OpenAI, Anthropic y otros) define tools en linea en cada solicitud API. MCP externaliza las definiciones de tools a servidores independientes que pueden ser descubiertos y usados por hosts compatibles con MCP. El function calling es por solicitud; MCP es un protocolo persistente con sesiones stateful.\n\n**P: Puedo usar MCP con modelos que no sean Claude?**\nR: Si. MCP es un protocolo abierto. OpenAI, Google DeepMind y Microsoft han adoptado soporte MCP en sus plataformas desde principios de 2026. Cualquier aplicacion de AI que implemente un MCP client puede conectarse a cualquier MCP server.\n\n**P: MCP es solo para herramientas locales?**\nR: No. Aunque el transporte stdio esta disenado para servidores locales, los transportes HTTP+SSE y Streamable HTTP soportan servidores MCP remotos. Puedes desplegar un servidor MCP como servicio en la nube accesible a traves de la red.\n\n**P: Como maneja MCP la autenticacion?**\nR: El protocolo soporta OAuth 2.0 para servidores remotos. Los servidores stdio locales heredan el contexto de seguridad del proceso host. Para despliegues empresariales, un MCP gateway puede centralizar la autenticacion y autorizacion.\n\n**P: Que lenguajes se pueden usar para construir un servidor MCP?**\nR: Los SDKs oficiales estan disponibles para TypeScript, Python, Java, Kotlin, C# y Swift. Los SDKs de la comunidad incluyen Rust, Go, Ruby y PHP. El protocolo es agnostico en cuanto al lenguaje — cualquier lenguaje que pueda leer\u002Fescribir JSON-RPC a traves de stdio o HTTP puede implementar un servidor MCP.\n\n**P: Como actualizar un servidor MCP sin reiniciar el host?**\nR: MCP soporta notificaciones de cambio de capacidades. Cuando los tools de tu servidor cambian, el servidor puede enviar un mensaje `notifications\u002Ftools\u002Flist_changed`, que indica al client que vuelva a obtener la lista de tools. Para servidores stdio, el host normalmente necesita reiniciarse. Los servidores HTTP pueden actualizarse sin reiniciar el host.","\u003Ch2 id=\"que-es-el-model-context-protocol-mcp\">Que es el Model Context Protocol (MCP)?\u003C\u002Fh2>\n\u003Cp>El \u003Cstrong>Model Context Protocol (MCP)\u003C\u002Fstrong> es un estandar abierto creado por Anthropic que define como las aplicaciones de AI se comunican con fuentes de datos y herramientas externas. Piensa en MCP como el \u003Cstrong>USB-C para la integracion de AI\u003C\u002Fstrong>: asi como USB-C proporciona un unico conector universal para carga, transferencia de datos y salida de pantalla, MCP proporciona un unico protocolo universal para conectar modelos de AI a bases de datos, APIs, sistemas de archivos y cualquier otro servicio. MCP elimina la necesidad de integraciones personalizadas entre cada aplicacion de AI y cada herramienta.\u003C\u002Fp>\n\u003Cp>En 2026, MCP se ha convertido en el estandar dominante para la comunicacion AI-herramientas. Gartner predice que \u003Cstrong>el 40 % de las aplicaciones empresariales incluiran agentes de AI para finales de 2026\u003C\u002Fstrong>, y MCP es el protocolo que hace esto practico a gran escala. Antes de MCP, conectar un modelo de AI a N herramientas requeria N integraciones personalizadas. Con M aplicaciones de AI y N herramientas, se necesitaban M x N adaptadores de integracion. MCP reduce esto a M + N: cada aplicacion de AI implementa un MCP client, cada herramienta implementa un MCP server.\u003C\u002Fp>\n\u003Ch2 id=\"arquitectura-mcp-host-client-server-y-transport\">Arquitectura MCP: Host, Client, Server y Transport\u003C\u002Fh2>\n\u003Cp>Comprender la arquitectura MCP es esencial antes de escribir codigo. El protocolo define cuatro roles clave:\u003C\u002Fp>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Componente\u003C\u002Fth>\u003Cth>Rol\u003C\u002Fth>\u003Cth>Ejemplo\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>\u003Cstrong>Host\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>La aplicacion de AI con la que interactua el usuario final\u003C\u002Ftd>\u003Ctd>Claude Desktop, Cursor, VS Code Copilot\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Cstrong>Client\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>El manejador del protocolo MCP dentro del host\u003C\u002Ftd>\u003Ctd>Integrado en la aplicacion host\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Cstrong>Server\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>Expone tools, resources y prompts a traves de MCP\u003C\u002Ftd>\u003Ctd>Tu servidor personalizado (lo que vamos a construir)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Cstrong>Transport\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>La capa de comunicacion entre client y server\u003C\u002Ftd>\u003Ctd>stdio, HTTP+SSE, Streamable HTTP\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>El flujo de comunicacion funciona asi:\u003C\u002Fp>\n\u003Col>\n\u003Cli>El \u003Cstrong>Host\u003C\u002Fstrong> arranca e inicializa un MCP \u003Cstrong>Client\u003C\u002Fstrong> para cada servidor configurado.\u003C\u002Fli>\n\u003Cli>El \u003Cstrong>Client\u003C\u002Fstrong> se conecta al \u003Cstrong>Server\u003C\u002Fstrong> a traves de un \u003Cstrong>Transport\u003C\u002Fstrong> (stdio para local, HTTP para remoto).\u003C\u002Fli>\n\u003Cli>El \u003Cstrong>Client\u003C\u002Fstrong> envia una solicitud \u003Ccode>initialize\u003C\u002Fcode>, negociando la version del protocolo y las capacidades.\u003C\u002Fli>\n\u003Cli>El \u003Cstrong>Server\u003C\u002Fstrong> responde con sus \u003Cstrong>tools\u003C\u002Fstrong>, \u003Cstrong>resources\u003C\u002Fstrong> y \u003Cstrong>prompts\u003C\u002Fstrong> disponibles.\u003C\u002Fli>\n\u003Cli>Cuando el modelo de AI necesita datos o acciones externas, el \u003Cstrong>Client\u003C\u002Fstrong> llama al metodo del servidor apropiado.\u003C\u002Fli>\n\u003Cli>El \u003Cstrong>Server\u003C\u002Fstrong> ejecuta la operacion y devuelve los resultados a traves de mensajes JSON-RPC 2.0.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3>Tools vs Resources vs Prompts\u003C\u002Fh3>\n\u003Cp>Los MCP servers pueden exponer tres tipos de capacidades:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Tools\u003C\u002Fstrong> son funciones que el modelo de AI puede llamar. Aceptan entrada estructurada y devuelven salida estructurada. Ejemplo: \u003Ccode>query_database(sql: string)\u003C\u002Fcode> o \u003Ccode>send_email(to: string, subject: string, body: string)\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Resources\u003C\u002Fstrong> son datos que el modelo de AI puede leer. Se identifican por URIs y devuelven contenido. Ejemplo: \u003Ccode>file:\u002F\u002F\u002Fpath\u002Fto\u002Fdocument.md\u003C\u002Fcode> o \u003Ccode>postgres:\u002F\u002Flocalhost\u002Fmydb\u002Fusers\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Prompts\u003C\u002Fstrong> son plantillas de prompts reutilizables proporcionadas por el servidor. Ayudan a estandarizar como la AI interactua con el dominio del servidor. Ejemplo: una plantilla \u003Ccode>summarize_ticket\u003C\u002Fcode> para un Jira MCP server.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"paso-a-paso-construir-un-servidor-mcp-en-typescript\">Paso a paso: construir un servidor MCP en TypeScript\u003C\u002Fh2>\n\u003Cp>Construyamos un servidor MCP practico que proporcione una herramienta para consultar una base de datos SQLite. Este es un caso de uso comun: dar a un modelo de AI acceso seguro de solo lectura a los datos de tu aplicacion.\u003C\u002Fp>\n\u003Ch3>Paso 1: Inicializar el proyecto\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-bash\">mkdir mcp-sqlite-server &amp;&amp; cd mcp-sqlite-server\nnpm init -y\nnpm install @modelcontextprotocol\u002Fsdk better-sqlite3\nnpm install -D typescript @types\u002Fnode @types\u002Fbetter-sqlite3\nnpx tsc --init\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Configurar \u003Ccode>tsconfig.json\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"Node16\",\n    \"moduleResolution\": \"Node16\",\n    \"outDir\": \".\u002Fdist\",\n    \"rootDir\": \".\u002Fsrc\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"declaration\": true\n  },\n  \"include\": [\"src\u002F**\u002F*\"]\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Paso 2: Implementar el servidor\u003C\u002Fh3>\n\u003Cp>Crear \u003Ccode>src\u002Findex.ts\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-typescript\">import { McpServer } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fmcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fstdio.js\";\nimport Database from \"better-sqlite3\";\nimport { z } from \"zod\";\n\nconst db = new Database(process.env.DB_PATH || \".\u002Fdata.db\", {\n  readonly: true,\n});\n\nconst server = new McpServer({\n  name: \"sqlite-query\",\n  version: \"1.0.0\",\n});\n\nserver.tool(\n  \"query\",\n  \"Ejecutar una consulta SQL de solo lectura en la base de datos SQLite\",\n  {\n    sql: z.string().describe(\"La consulta SQL SELECT a ejecutar\"),\n  },\n  async ({ sql }) =&gt; {\n    const normalized = sql.trim().toUpperCase();\n    if (!normalized.startsWith(\"SELECT\")) {\n      return {\n        content: [{ type: \"text\", text: \"Error: solo se permiten consultas SELECT.\" }],\n        isError: true,\n      };\n    }\n    try {\n      const rows = db.prepare(sql).all();\n      return {\n        content: [{ type: \"text\", text: JSON.stringify(rows, null, 2) }],\n      };\n    } catch (error) {\n      return {\n        content: [{ type: \"text\", text: `Error de consulta: ${(error as Error).message}` }],\n        isError: true,\n      };\n    }\n  }\n);\n\nserver.tool(\n  \"list_tables\",\n  \"Listar todas las tablas de la base de datos con sus esquemas\",\n  {},\n  async () =&gt; {\n    const tables = db\n      .prepare(\n        `SELECT name, sql FROM sqlite_master\n         WHERE type='table' AND name NOT LIKE 'sqlite_%'\n         ORDER BY name`\n      )\n      .all();\n    return {\n      content: [{ type: \"text\", text: JSON.stringify(tables, null, 2) }],\n    };\n  }\n);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Paso 3: Compilar y probar localmente\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-bash\">npx tsc\necho '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-03-26\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0\"}}}' | node dist\u002Findex.js\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Deberas ver una respuesta JSON-RPC con las capacidades del servidor.\u003C\u002Fp>\n\u003Ch3>Paso 4: Construir el mismo servidor en Python\u003C\u002Fh3>\n\u003Cp>Para desarrolladores Python, aqui esta la implementacion equivalente usando el SDK oficial de Python para MCP:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-python\">import sqlite3\nimport json\nfrom mcp.server.fastmcp import FastMCP\n\nmcp = FastMCP(\"sqlite-query\")\nDB_PATH = \"data.db\"\n\n@mcp.tool()\ndef query(sql: str) -&gt; str:\n    \"\"\"Ejecutar una consulta SQL de solo lectura en la base de datos SQLite.\"\"\"\n    normalized = sql.strip().upper()\n    if not normalized.startswith(\"SELECT\"):\n        raise ValueError(\"Solo se permiten consultas SELECT.\")\n    conn = sqlite3.connect(DB_PATH)\n    conn.row_factory = sqlite3.Row\n    try:\n        cursor = conn.execute(sql)\n        rows = [dict(row) for row in cursor.fetchall()]\n        return json.dumps(rows, indent=2, default=str)\n    finally:\n        conn.close()\n\n@mcp.tool()\ndef list_tables() -&gt; str:\n    \"\"\"Listar todas las tablas de la base de datos con sus esquemas.\"\"\"\n    conn = sqlite3.connect(DB_PATH)\n    conn.row_factory = sqlite3.Row\n    try:\n        cursor = conn.execute(\n            \"SELECT name, sql FROM sqlite_master \"\n            \"WHERE type='table' AND name NOT LIKE 'sqlite_%'\"\n        )\n        tables = [dict(row) for row in cursor.fetchall()]\n        return json.dumps(tables, indent=2)\n    finally:\n        conn.close()\n\nif __name__ == \"__main__\":\n    mcp.run(transport=\"stdio\")\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"conexion-a-claude-desktop\">Conexion a Claude Desktop\u003C\u002Fh2>\n\u003Cp>Claude Desktop soporta servidores MCP de forma nativa. Para conectar tu servidor, edita el archivo de configuracion de Claude Desktop:\u003C\u002Fp>\n\u003Cp>\u003Cstrong>macOS:\u003C\u002Fstrong> \u003Ccode>~\u002FLibrary\u002FApplication Support\u002FClaude\u002Fclaude_desktop_config.json\u003C\u002Fcode>\n\u003Cstrong>Windows:\u003C\u002Fstrong> \u003Ccode>%APPDATA%\\Claude\\claude_desktop_config.json\u003C\u002Fcode>\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  \"mcpServers\": {\n    \"sqlite-query\": {\n      \"command\": \"node\",\n      \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"DB_PATH\": \"\u002Fabsolute\u002Fpath\u002Fto\u002Fyour\u002Fdata.db\"\n      }\n    }\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Reinicia Claude Desktop. Veras un icono de martillo en la interfaz de chat indicando las herramientas MCP disponibles. Ahora puedes hacer preguntas a Claude como “Que tablas hay en la base de datos?” o “Muestra los 10 principales usuarios por fecha de registro” y Claude usara tu servidor MCP para consultar la base de datos directamente.\u003C\u002Fp>\n\u003Ch2 id=\"conexion-a-cursor\">Conexion a Cursor\u003C\u002Fh2>\n\u003Cp>Cursor tambien soporta servidores MCP. Agrega la configuracion a \u003Ccode>.cursor\u002Fmcp.json\u003C\u002Fcode> en la raiz de tu proyecto:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  \"mcpServers\": {\n    \"sqlite-query\": {\n      \"command\": \"node\",\n      \"args\": [\".\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"DB_PATH\": \".\u002Fdata.db\"\n      }\n    }\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Despues de guardar, reinicia Cursor. Las herramientas MCP aparecen en el panel del asistente de AI y pueden invocarse durante las sesiones de generacion de codigo y depuracion.\u003C\u002Fp>\n\u003Ch2 id=\"pruebas-y-depuracion-de-tu-servidor-mcp\">Pruebas y depuracion de tu servidor MCP\u003C\u002Fh2>\n\u003Ch3>Uso del MCP Inspector\u003C\u002Fh3>\n\u003Cp>El MCP Inspector es la herramienta oficial de depuracion. Proporciona una interfaz web para interactuar con tu servidor:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">npx @modelcontextprotocol\u002Finspector node dist\u002Findex.js\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Esto abre una interfaz de navegador en \u003Ccode>http:\u002F\u002Flocalhost:5173\u003C\u002Fcode> donde puedes:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Ver todos los tools, resources y prompts registrados\u003C\u002Fli>\n\u003Cli>Llamar a tools con entradas personalizadas e inspeccionar las respuestas\u003C\u002Fli>\n\u003Cli>Monitorear el flujo de mensajes JSON-RPC en tiempo real\u003C\u002Fli>\n\u003Cli>Probar el manejo de errores enviando solicitudes malformadas\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Problemas comunes de depuracion\u003C\u002Fh3>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Problema\u003C\u002Fth>\u003Cth>Causa\u003C\u002Fth>\u003Cth>Solucion\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>El servidor no aparece en Claude Desktop\u003C\u002Ftd>\u003Ctd>Ruta de configuracion o error de sintaxis JSON\u003C\u002Ftd>\u003Ctd>Validar JSON, verificar rutas absolutas\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Error “Tool not found”\u003C\u002Ftd>\u003Ctd>Los tools no estan registrados antes de conectar\u003C\u002Ftd>\u003Ctd>Registrar tools antes de llamar a \u003Ccode>server.connect()\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Timeout en llamadas a tools\u003C\u002Ftd>\u003Ctd>Operacion de larga duracion sin progreso\u003C\u002Ftd>\u003Ctd>Agregar notificaciones de progreso via \u003Ccode>server.sendProgress()\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>La salida stderr corrompe el protocolo\u003C\u002Ftd>\u003Ctd>console.log escribe en stdout (transporte stdio)\u003C\u002Ftd>\u003Ctd>Usar \u003Ccode>console.error()\u003C\u002Fcode> para logging con stdio\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Desconexion despues de inactividad\u003C\u002Ftd>\u003Ctd>Timeout del transporte\u003C\u002Ftd>\u003Ctd>Implementar heartbeat o usar transporte HTTP\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Ch2 id=\"mejores-practicas-para-produccion\">Mejores practicas para produccion\u003C\u002Fh2>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Validacion de entradas\u003C\u002Fstrong>: Siempre valida y sanea las entradas de los tools. Usa esquemas Zod (TypeScript) o modelos Pydantic (Python) para verificacion de tipos estricta.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Solo lectura por defecto\u003C\u002Fstrong>: Comienza con acceso de solo lectura. Solo agrega capacidades de escritura cuando sea realmente necesario, y siempre solicita confirmacion para operaciones destructivas.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Manejo de errores\u003C\u002Fstrong>: Devuelve mensajes de error estructurados con \u003Ccode>isError: true\u003C\u002Fcode>. Nunca expongas stack traces internos o cadenas de conexion a la base de datos.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Registro\u003C\u002Fstrong>: Registra todas las llamadas a tools con marca de tiempo, entradas y duracion de ejecucion. Usa stderr para logging (no stdout) con el transporte stdio.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Limitacion de velocidad\u003C\u002Fstrong>: Implementa limites de velocidad por tool para evitar que bucles de AI no controlados sobrecarguen tus servicios backend.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Timeout\u003C\u002Fstrong>: Establece timeouts de ejecucion en todos los handlers de tools. Los modelos de AI pueden llamar a tools que disparen consultas costosas — protege tu infraestructura.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Separacion de entornos\u003C\u002Fstrong>: Usa variables de entorno para toda la configuracion. Nunca codifiques en duro URLs de bases de datos, claves API o rutas de archivos.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Versionado\u003C\u002Fstrong>: Usa versionado semantico para tu servidor MCP. El handshake \u003Ccode>initialize\u003C\u002Fcode> incluye negociacion de versiones — los cambios incompatibles requieren un bump de version mayor.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"faq\">FAQ\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>P: Cual es la diferencia entre MCP y function calling?\u003C\u002Fstrong>\nR: El function calling (usado por OpenAI, Anthropic y otros) define tools en linea en cada solicitud API. MCP externaliza las definiciones de tools a servidores independientes que pueden ser descubiertos y usados por hosts compatibles con MCP. El function calling es por solicitud; MCP es un protocolo persistente con sesiones stateful.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>P: Puedo usar MCP con modelos que no sean Claude?\u003C\u002Fstrong>\nR: Si. MCP es un protocolo abierto. OpenAI, Google DeepMind y Microsoft han adoptado soporte MCP en sus plataformas desde principios de 2026. Cualquier aplicacion de AI que implemente un MCP client puede conectarse a cualquier MCP server.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>P: MCP es solo para herramientas locales?\u003C\u002Fstrong>\nR: No. Aunque el transporte stdio esta disenado para servidores locales, los transportes HTTP+SSE y Streamable HTTP soportan servidores MCP remotos. Puedes desplegar un servidor MCP como servicio en la nube accesible a traves de la red.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>P: Como maneja MCP la autenticacion?\u003C\u002Fstrong>\nR: El protocolo soporta OAuth 2.0 para servidores remotos. Los servidores stdio locales heredan el contexto de seguridad del proceso host. Para despliegues empresariales, un MCP gateway puede centralizar la autenticacion y autorizacion.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>P: Que lenguajes se pueden usar para construir un servidor MCP?\u003C\u002Fstrong>\nR: Los SDKs oficiales estan disponibles para TypeScript, Python, Java, Kotlin, C# y Swift. Los SDKs de la comunidad incluyen Rust, Go, Ruby y PHP. El protocolo es agnostico en cuanto al lenguaje — cualquier lenguaje que pueda leer\u002Fescribir JSON-RPC a traves de stdio o HTTP puede implementar un servidor MCP.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>P: Como actualizar un servidor MCP sin reiniciar el host?\u003C\u002Fstrong>\nR: MCP soporta notificaciones de cambio de capacidades. Cuando los tools de tu servidor cambian, el servidor puede enviar un mensaje \u003Ccode>notifications\u002Ftools\u002Flist_changed\u003C\u002Fcode>, que indica al client que vuelva a obtener la lista de tools. Para servidores stdio, el host normalmente necesita reiniciarse. Los servidores HTTP pueden actualizarse sin reiniciar el host.\u003C\u002Fp>\n","es","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:39.516601Z","Tutorial paso a paso para construir un servidor MCP en TypeScript y Python. Conectalo a Claude Desktop o Cursor, prueba con MCP Inspector y despliega en produccion.","tutorial servidor mcp",null,"index, follow",[21,26],{"id":22,"name":23,"slug":24,"created_at":25},"c0000000-0000-0000-0000-000000000008","AI","ai","2026-03-28T10:44:21.513630Z",{"id":27,"name":28,"slug":29,"created_at":25},"c0000000-0000-0000-0000-000000000002","TypeScript","typescript","Ingeniería",[32,38,44],{"id":33,"title":34,"slug":35,"excerpt":36,"locale":12,"category_name":30,"published_at":37},"d0000000-0000-0000-0000-000000000683","Por qué Bali se está convirtiendo en el hub de impact-tech del Sudeste Asiático en 2026","por-que-bali-hub-impact-tech-sudeste-asiatico-2026","Bali ocupa el puesto 16 entre los ecosistemas startup del Sudeste Asiático. Con una concentración creciente de constructores Web3, startups de AI sostenible y empresas de eco-travel tech, la isla se consolida como capital de impact-tech de la región.","2026-03-28T10:44:49.926489Z",{"id":39,"title":40,"slug":41,"excerpt":42,"locale":12,"category_name":30,"published_at":43},"d0000000-0000-0000-0000-000000000682","El mosaico de protección de datos de ASEAN: checklist de cumplimiento para desarrolladores","mosaico-proteccion-datos-asean-checklist-cumplimiento-desarrolladores","Siete países de ASEAN tienen ahora leyes integrales de protección de datos, cada una con diferentes modelos de consentimiento, requisitos de localización y estructuras de sanciones. Un checklist práctico de cumplimiento para desarrolladores.","2026-03-28T10:44:49.919345Z",{"id":45,"title":46,"slug":47,"excerpt":48,"locale":12,"category_name":30,"published_at":49},"d0000000-0000-0000-0000-000000000681","La transformación digital de 29 mil millones de dólares de Indonesia: oportunidades para empresas de software","transformacion-digital-29-mil-millones-dolares-indonesia-oportunidades-empresas-software","El mercado de servicios IT de Indonesia alcanzará los 29.030 millones de dólares en 2026, frente a los 24.370 millones de 2025. La infraestructura cloud, la AI, el comercio electrónico y los centros de datos impulsan el crecimiento más rápido del Sudeste Asiático.","2026-03-28T10:44:49.897658Z",{"id":13,"name":51,"slug":52,"bio":53,"photo_url":18,"linkedin":18,"role":54,"created_at":55,"updated_at":55},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]