Documentación del conector MCP
Resumen
Qué es el servidor MCP, dónde está, cómo se autentica y todo lo que puede hacer.
Qué es MCP
El Model Context Protocol permite que un asistente de IA llame a herramientas reales en lugar de adivinar. Apunta un cliente al servidor MCP de Static.app y tu asistente podrá listar tus sitios, editar archivos y publicar un ZIP en lenguaje natural, con tu propia clave de API.
Todo lo que hace el servidor pasa por la API REST de Static.app, así que una acción MCP y una llamada a la API tienen exactamente los mismos efectos y permisos.
Endpoint
Un servidor alojado, transporte Streamable HTTP, JSON-RPC 2.0, según la especificación de MCP (2025-03-26).
| Endpoint | Método | Finalidad |
|---|---|---|
/mcp | POST / GET / DELETE | Streamable HTTP. POST envía JSON-RPC, GET abre un flujo de eventos opcional y DELETE cierra la sesión. |
/upload | POST / PUT | Prepara un ZIP fuera de banda. Consulta Subida de archivos. |
/sse + /message | GET / POST | Transporte SSE antiguo (2024-11-05), que se mantiene para los clientes configurados antes de que existiera /mcp. Solo con clave de API. |
Autenticación
El servidor es multiusuario: no guarda credenciales propias, así que cada cliente trae las suyas. En /mcp hay dos formas de entrar:
- Inicio de sesión OAuth. Los clientes que lo admiten (Claude, Claude Code, Codex, Cursor, VS Code, Gemini CLI) siguen el
401del servidor hasta un inicio de sesión de Static.app, y tú haces clic en Authorize. No hay clave que copiar. Revoca el acceso cuando quieras en Cuenta → API / MCP. - Clave de API. Para los clientes que no pueden iniciar sesión y para el endpoint antiguo
/sse. Crea una en Cuenta → API / MCP. Las claves empiezan porsk_.
Pasa la clave en una de estas dos cabeceras:
| Método | Valor | Notas |
|---|---|---|
| Cabecera Authorization | Authorization: Bearer sk_xxxx | Recomendada. |
| Cabecera personalizada | X-API-Key: sk_xxxx | Para clientes que no pueden establecer Authorization. |
Todas las herramientas
Las herramientas se dividen en cuatro grupos. Todas se ejecutan en nuestros servidores y ninguna puede ver archivos de tu ordenador, así que el contenido viaja como argumentos o a través del endpoint de subida.
| Herramienta | Grupo | Qué hace |
|---|---|---|
list_sites | Sitios | Lista todos los sitios de la cuenta. |
get_site | Sitios | Obtiene un sitio por su PID. |
get_site_files | Sitios | Lista los archivos de un sitio. |
create_site_from_archive | Sitios | Crea un sitio a partir de un ZIP. |
update_site_from_archive | Sitios | Sustituye el contenido de un sitio con un ZIP. |
download_site_archive | Sitios | Obtiene un enlace de descarga de todo el sitio. |
download_site_files | Sitios | Obtiene un enlace de descarga de archivos seleccionados. |
delete_site | Sitios | Elimina un sitio. |
write_site_files | Archivos | Crea o sustituye archivos a partir de contenido enviado en la propia llamada. |
read_site_file | Archivos | Lee un archivo. |
delete_site_files | Archivos | Elimina archivos o directorios. |
create_upload | Subida de archivos | Reserva una URL de subida de un solo uso para un ZIP o un archivo suelto. |
list_forms | Formularios | Lista los formularios de un sitio. |
get_form | Formularios | Obtiene un formulario. |
get_form_entries | Formularios | Lista los envíos. |
delete_form_entry | Formularios | Elimina un envío. |
Identificador de sitio (pid)
Toda herramienta que toca un sitio recibe su identificador público de 10 caracteres, p. ej. 0aw4jtby1z, nunca el ID numérico de la base de datos. Ejecuta list_sites para ver los PID de tu cuenta.
Configuración
Conecta un cliente en un par de minutos. Todas las configuraciones de abajo apuntan al mismo endpoint, https://mcp.static.app/mcp, y solo cambian en cómo quiere escribirlo cada cliente. Los clientes que admiten OAuth abren un inicio de sesión de Static.app y no necesitan clave; el resto envía una clave de API en una cabecera.
Claude Code
Un solo comando añade el servidor para todos tus proyectos. Después ejecuta /mcp en Claude Code, elige static-app e inicia sesión en Static.app en tu navegador:
claude mcp add --transport http --scope user static-app https://mcp.static.app/mcp
Para usar una clave de API en lugar de iniciar sesión, guárdala en una variable de entorno y pásala como cabecera:
export STATIC_API_KEY=sk_xxxx
claude mcp add --transport http --scope user static-app https://mcp.static.app/mcp \
--header "Authorization: Bearer $STATIC_API_KEY"
O añade al repositorio del proyecto un archivo .mcp.json. Con la cabecera, la clave se lee del entorno de cada persona, así que nunca llega al repositorio; sin la cabecera, cada persona inicia sesión:
{
"mcpServers": {
"static-app": {
"type": "http",
"url": "https://mcp.static.app/mcp",
"headers": { "Authorization": "Bearer ${STATIC_API_KEY}" }
}
}
}
Claude Desktop
Claude Desktop añade el servidor como conector personalizado, sin archivo de configuración y sin clave. Abre Settings → Connectors, haz clic en Add custom connector, pega la URL y deja vacía la configuración avanzada (Advanced settings):
https://mcp.static.app/mcp
Claude abre un inicio de sesión de Static.app; haz clic en Authorize y ya estás conectado. El mismo conector funciona después en claude.ai y en la app móvil de Claude. En los planes Team y Enterprise, primero un Owner lo añade para la organización y luego cada persona se conecta.
Codex
Añade esto a ~/.codex/config.toml y luego inicia sesión desde la terminal con codex mcp login static-app:
[mcp_servers.static-app]
url = "https://mcp.static.app/mcp"
Para usar una clave de API en su lugar, léela de tu entorno:
[mcp_servers.static-app]
url = "https://mcp.static.app/mcp"
bearer_token_env_var = "STATIC_API_KEY"
Cursor
Añade esto a ~/.cursor/mcp.json para todos los proyectos, o a .cursor/mcp.json en un solo proyecto. Sin headers, Cursor abre un inicio de sesión de Static.app; con ellas, la clave se lee de tu entorno:
{
"mcpServers": {
"static-app": {
"url": "https://mcp.static.app/mcp",
"headers": { "Authorization": "Bearer ${env:STATIC_API_KEY}" }
}
}
}
Devin Desktop (antes Windsurf)
Añade esto a ~/.config/devin/mcp_config.json (en Windows, %APPDATA%\devin\mcp_config.json) y reinicia Devin Desktop. La primera vez que se conecta abre un inicio de sesión de Static.app:
{
"mcpServers": {
"static-app": {
"url": "https://mcp.static.app/mcp",
"transport": "http"
}
}
}
n8n y clientes personalizados
En n8n, añade un nodo MCP Client Tool a tu AI Agent, define Endpoint como https://mcp.static.app/mcp, deja Server Transport en HTTP Streamable y elige Bearer Auth con tu clave de API.
Cualquier otro cliente que hable MCP sobre Streamable HTTP funciona con la misma URL. Si admite OAuth, inicia sesión con Static.app; si no, envía la cabecera Authorization en cada petición, y listará las herramientas del índice de herramientas al conectarse.
¿Vas a crear el tuyo? Cada llamada es un POST de JSON-RPC a /mcp. initialize responde con una cabecera Mcp-Session-Id; devuélvela en cada petición posterior.
curl -i https://mcp.static.app/mcp \
-H "Authorization: Bearer sk_xxxx" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": { "name": "curl", "version": "1.0" }
}
}'
# HTTP/2 200
# mcp-session-id: mcp-session-f5df9141-...
https://mcp.static.app/sse con una clave de API (ahí no hay OAuth). Si tu cliente no puede usar ninguno de los dos, usa directamente la API REST . Ofrece las mismas funciones sin sesión.Comprobar la conexión
Pide al asistente que liste tus sitios. Si las herramientas están bien conectadas, llamará a list_sites y responderá con dominios reales. Para comprobarlo a mano, confirma la sesión de antes y luego llama a una herramienta en ella:
curl https://mcp.static.app/mcp \
-H "Authorization: Bearer sk_xxxx" \
-H "Mcp-Session-Id: YOUR_SESSION_ID" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{ "jsonrpc": "2.0", "method": "notifications/initialized" }'
curl https://mcp.static.app/mcp \
-H "Authorization: Bearer sk_xxxx" \
-H "Mcp-Session-Id: YOUR_SESSION_ID" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": { "name": "list_sites", "arguments": {} }
}'
El resultado llega en la respuesta a ese POST.
Herramientas de sitios
Lista, inspecciona, publica y elimina sitios. Todas reciben el pid del sitio, no su ID numérico.
list_sites
Devuelve todos los sitios del espacio de trabajo activo.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| Sin argumentos. | |||
Resultado de ejemplo
[
{
"pid": "xxxxxxxxxx",
"slug": "example-site",
"name": "Example Site",
"domain": "example.staticdomains.app",
"status": true,
"full_url": "https://example.staticdomains.app",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-02-01T12:30:00Z"
}
]
Pregunta a tu asistente
"Show me all my Static.app sites."
get_site
Devuelve un sitio.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Identificador público, p. ej. 0aw4jtby1z. |
get_site_files
Lista los archivos y directorios de un sitio, de forma recursiva desde la raíz.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Identificador público del sitio. |
Resultado de ejemplo
{
"status": "success",
"current_path": "",
"files": [
{ "name": "index.html", "path": "index.html", "is_dir": false, "size": 1234, "type": "html", "hash": "0123456789abcdef0123456789abcdef" },
{ "name": "images", "path": "images", "is_dir": true, "size": null, "type": "directory", "hash": null }
]
}
create_site_from_archive
Crea un sitio nuevo a partir de un archivo ZIP. Indica exactamente una fuente de archivo. Se prueban en el orden de abajo. El servidor no puede leer archivos de tu ordenador, así que el archivo llega a través de create_upload o desde una URL pública.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
upload_id | string | opcional | Preferida. ID de create_upload una vez que el ZIP se ha enviado con PUT a su URL. |
archive_url | string | opcional | URL desde la que descargar el ZIP. |
archive_base64 | string | opcional | Alternativa heredada. Consulta Base64 (heredado). |
name | string | opcional | Subdominio deseado, p. ej. my-site. Si no, se genera uno aleatorio. |
Resultado de ejemplo
{
"status": "success",
"pid": "xxxxxxxxxx",
"slug": "my-site",
"url": "https://my-site.staticdomains.app"
}
update_site_from_archive
Sustituye el contenido de un sitio con un ZIP nuevo. Para cambiar unos pocos archivos en lugar de todo el sitio, usa write_site_files.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Sitio que actualizar. |
upload_id | string | opcional | Preferida. ID de create_upload. |
archive_url | string | opcional | URL desde la que descargar el ZIP. |
archive_base64 | string | opcional | Alternativa heredada. |
download_site_archive
Empaqueta todo el sitio y devuelve un enlace de descarga.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Sitio que descargar. |
Resultado de ejemplo
{
"status": "success",
"url": "https://static.app/storage/zip/abcdef0123456789_download.zip"
}
download_site_files
Empaqueta los archivos seleccionados y devuelve un enlace de descarga.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Sitio del que descargar. |
files | string | obligatorio | Matriz JSON de rutas, p. ej. ["index.html", "css/style.css"]. |
delete_site
Elimina un sitio y todo lo que contiene. No se puede deshacer.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Sitio que eliminar. |
Herramientas de archivos
Lee, escribe y elimina archivos individuales sin volver a publicar todo el sitio.
write_site_files
Crea o reemplaza archivos concretos y deja intacto el resto del sitio. Envía el texto en la propia llamada; para imágenes y otros binarios, prepara el archivo con create_upload y pasa su upload_id. Los archivos que todavía no existen se crean, y las carpetas que faltan se crean por el camino.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Sitio en el que escribir. |
files | string | obligatorio | Matriz JSON de {path, content, encoding} o {path, upload_id}. Hasta 200 entradas, como máximo 20 con upload_id. |
create_only | boolean | opcional | Falla con 409 en lugar de sobrescribir un archivo existente. Por defecto es false. No se puede combinar con upload_id. |
Campos de la entrada de archivo
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
path | string | obligatorio | Relativa a la raíz del sitio, p. ej. css/style.css. Se rechazan las rutas que salen del sitio. |
content | string | uno de los dos | El contenido del archivo. Máx. 200 MB. |
upload_id | string | uno de los dos | ID de create_upload, una vez que el archivo se ha enviado con PUT a su URL. No cuesta tokens, sea cual sea su tamaño. |
encoding | string | opcional | Para content. "text" (por defecto) lo envía tal cual; "base64" es para binarios muy pequeños, ya que cada byte cuesta tokens. |
Argumentos de ejemplo
{
"pid": "xxxxxxxxxx",
"files": "[{\"path\": \"index.html\", \"content\": \"<!doctype html><h1>Hello</h1>\"}, {\"path\": \"img/logo.png\", \"upload_id\": \"0e9837a760c5062279ea57107d8f0a1c\"}]"
}
Resultado de ejemplo
{
"status": "success",
"written": 2,
"files": [
{ "name": "index.html", "path": "index.html", "size": 34, "hash": "0123456789abcdef0123456789abcdef" },
{ "name": "logo.png", "path": "img/logo.png", "size": 2048, "hash": "89abcdef0123456789abcdef01234567" }
],
"errors": []
}
upload_id; si se rechaza parte de un lote, los archivos preparados se quedan donde están para que puedas reintentarlo.Errores
| Código | Cuándo |
|---|---|
| 409 | Se indicó create_only y todos los archivos ya existen. |
| 422 | No se pudo escribir nada: extensión no admitida, ruta no válida o base64 incorrecto. |
Pregunta a tu asistente
"Add a privacy.html page to site xxxxxxxxxx with a short placeholder policy."
"Change the heading colour in css/style.css on site xxxxxxxxxx to #6551E0."
read_site_file
Devuelve el contenido de un archivo. El texto llega tal cual; los binarios llegan codificados en base64 con encoding ajustado en consecuencia.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Sitio del que leer. |
path | string | obligatorio | Relativa a la raíz del sitio, p. ej. css/style.css. |
Resultado de ejemplo
{
"status": "success",
"path": "css/style.css",
"encoding": "text",
"size": 14,
"hash": "fedcba9876543210fedcba9876543210",
"content": "body{margin:0}"
}
Errores
| Código | Cuándo |
|---|---|
| 400 | Falta path o apunta fuera del sitio. |
| 404 | No se encuentra el sitio o el archivo. |
| 413 | El archivo pesa más de 1 MB, así que usa en su lugar download_site_files. |
delete_site_files
Elimina archivos o directorios. Los directorios se eliminan de forma recursiva.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Sitio del que eliminar. |
paths | string | obligatorio | Matriz JSON de rutas, p. ej. ["old.html", "assets/legacy"]. |
Una nota sobre rutas locales
El servidor alojado se ejecuta en nuestra infraestructura y no comparte sistema de archivos contigo, así que no hay ninguna herramienta que reciba una ruta de tu ordenador. Todo lo que tenga que viajar lo hace como contenido o por HTTP:
| Qué quieres hacer | Usa |
|---|---|
| Cambiar o añadir un archivo de texto | write_site_files, enviando el contenido |
| Añadir una imagen, una fuente o un vídeo | create_upload, y luego write_site_files con upload_id |
| Publicar un ZIP que tienes en local | create_upload, y luego upload_id |
| Publicar un ZIP que ya está online | archive_url |
¿Alojas el servidor tú mismo? Define LOCAL_FILE_ACCESS=true y además expone upload_site_files y un argumento archive_path, que leen de la máquina en la que se ejecuta el servidor.
Subida de archivos
Cómo meter contenido en un sitio sin pagarlo dos veces: una en ancho de banda y otra en tokens.
Qué método usar
El servidor se ejecuta en remoto, así que nada se lee de tu disco. Dos preguntas deciden el resto: ¿cambias unos pocos archivos o sustituyes todo el sitio? ¿Tiene tu cliente una terminal?
| Situación | Usa | Coste en tokens |
|---|---|---|
| Editar páginas y estilos, añadir un archivo | write_site_files | Solo el texto del propio archivo. |
| Añadir una imagen, una fuente o un vídeo a un sitio | create_upload + write_site_files | Ninguno. El archivo nunca entra en la conversación. |
| Sustituir todo un sitio con un ZIP | create_upload + upload_id | Ninguno. El archivo nunca entra en la conversación. |
| El ZIP ya está alojado en algún sitio | archive_url | Ninguno. |
| El cliente no tiene terminal ni hosting | archive_base64 | Aproximadamente 1,4 tokens por byte de ZIP. |
create_upload
Reserva un espacio de un solo uso y devuelve una URL a la que enviar un archivo con PUT, más un comando curl listo para ejecutar. La URL no necesita clave de API. El archivo va directo de tu disco al servidor, así que su tamaño no cuesta nada de contexto. Publica un ZIP con él, o coloca un archivo suelto con write_site_files.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
file_name | string | opcional | Nombre del archivo. Por defecto es archive.zip. |
Resultado de ejemplo
{
"upload_id": "0e9837a760c5062279ea57107d8f0a1c",
"upload_url": "https://mcp.static.app/upload/0e9837a760c5062279ea57107d8f0a1c",
"file_name": "site.zip",
"expires_at": "2026-08-25T12:57:32Z",
"max_size": 204800000,
"single_use": true
}
Después envía el archivo con PUT
curl -fsS -T site.zip https://mcp.static.app/upload/0e9837a760c5062279ea57107d8f0a1c
Después publícalo
{
"pid": "xxxxxxxxxx",
"upload_id": "0e9837a760c5062279ea57107d8f0a1c"
}
write_site_files.Endpoint de subida
La herramienta es una comodidad, y cualquier cliente HTTP puede usar el endpoint directamente. POST recibe tu clave de API, prepara un archivo y devuelve un ID nuevo en un solo paso; PUT rellena un ID que entregó create_upload y no necesita clave.
Ejemplo de solicitud
curl -X POST --data-binary @site.zip \
-H "Authorization: Bearer sk_xxxx" \
"https://mcp.static.app/upload?file_name=site.zip"
Ejemplo de respuesta
{
"status": "success",
"upload_id": "0e9837a760c5062279ea57107d8f0a1c",
"file_name": "site.zip",
"size": 5000000,
"sha256": "1df9cfae4840f7c4eef12dbd4691c043ce4e247130817053c55f1aa04eddd971",
"expires_at": "2026-08-25T12:57:32Z"
}
Errores
| Código | Cuándo |
|---|---|
| 401 | POST sin clave de API. |
| 404 | ID desconocido o caducado. |
| 409 | Ya se subió contenido para este ID. |
| 413 | El cuerpo supera el límite de 200 MB. |
| 503 | El almacenamiento temporal está desactivado en el servidor. Usa archive_url en su lugar. |
Base64 (heredado)
archive_base64 sigue funcionando y se comprueba en último lugar. Existe para clientes que no pueden hacer una petición HTTP por su cuenta, pero base64 añade un tercio sobre los bytes originales, y todos pasan por el modelo, así que un archivo de 2 MB cuesta unos 700.000 tokens. Se rechaza todo lo que pase de 1.048.576 caracteres (unos 750 KB de ZIP). Da preferencia a upload_id siempre que haya una terminal disponible.
# macOS
base64 -i site.zip | tr -d '\n'
# Linux
base64 -w 0 site.zip
Herramientas de formularios
Lee los formularios de un sitio y trabaja con sus envíos.
list_forms
Devuelve todos los formularios de un sitio.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Identificador público del sitio. |
get_form
Devuelve un formulario con sus campos.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Identificador público del sitio. |
form_id | string | obligatorio | ID del formulario. |
get_form_entries
Devuelve los envíos de un formulario, los más recientes primero.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Identificador público del sitio. |
form_id | string | obligatorio | ID del formulario. |
limit | number | opcional | Cuántos envíos devolver. |
offset | number | opcional | Desplazamiento para la paginación. |
Pregunta a tu asistente
"Summarise the last 20 contact form submissions on site xxxxxxxxxx."
delete_form_entry
Elimina un envío.
Argumentos
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
pid | string | obligatorio | Identificador público del sitio. |
form_id | string | obligatorio | ID del formulario. |
entry_id | string | obligatorio | ID del envío que eliminar. |
Solución de problemas
Los fallos que se dan de verdad y qué significa cada uno.
401 Unauthorized
- Comprueba que la clave está vigente y no se ha revocado en Cuenta → API / MCP.
- La cabecera necesita el prefijo
Bearer:Authorization: Bearer sk_xxxx. - En un archivo de configuración, confirma que la variable de entorno se ha resuelto de verdad: un
${STATIC_API_KEY}literal que llega al servidor se interpreta como una clave incorrecta. - Has iniciado sesión con OAuth y ahora recibes
401: la conexión se desconectó en Cuenta → API / MCP. Vuelve a iniciar sesión desde el cliente (/mcpen Claude Code,codex mcp login static-appen Codex).
"Site not found"
- Pasa el PID (el ID público de 10 caracteres, como
0aw4jtby1z), no el ID numérico de la base de datos. - El sitio tiene que pertenecer a la cuenta de la clave. Ejecuta
list_sitespara ver cuáles pertenecen. - Cambiar de espacio de trabajo cambia qué sitios se ven.
Pasar una ruta de tu ordenador
El servidor alojado no comparte sistema de archivos contigo, así que una ruta como /Users/me/site.zip no significa nada para él. Un cliente antiguo que aún envíe archive_path recibe un error que explica qué usar en su lugar; uno que llame a upload_site_files recibe tool not found, porque esa herramienta no está registrada aquí en absoluto.
- Cambiar archivos →
write_site_files, con el texto en la propia llamada y los binarios porupload_id. - Publicar un archivo comprimido →
create_upload, envía el ZIP con PUT y luegoupload_id. - Archivo ya alojado →
archive_url. - Si ejecutas el servidor tú mismo →
LOCAL_FILE_ACCESS=truerecupera las herramientas de rutas locales.
Las herramientas no aparecen
- Reinicia el cliente después de editar su configuración MCP. La mayoría solo la lee al arrancar.
- Claude Desktop registra el handshake:
~/Library/Logs/Claude/mcp*.logen macOS. Cannot find module 'mcp-remote': usanpx -y mcp-remote, que lo instala al momento.- Una conexión sana lista las herramientas del índice de herramientas. Si salen menos, el cliente guardó en caché una sesión anterior.
Errores de conexión
- La URL es exactamente
https://mcp.static.app/mcp, y el cliente está configurado con Streamable HTTP (--transport http,"type": "http"), no con SSE. - Prueba el endpoint por separado:
curl -i -X POST https://mcp.static.app/mcp. Sin credenciales responde401con una cabeceraWWW-Authenticateque apunta a los metadatos de inicio de sesión, lo que demuestra que el servidor es accesible. 404en una petición que llevaMcp-Session-Id: la sesión ha caducado o el servidor se ha reiniciado. Los clientes se reconectan solos; uno hecho a mano tiene que volver a enviarinitialize.- ¿Sigues en el endpoint antiguo
/sse? Mantiene una conexión abierta de larga duración, así que los proxies que almacenan las respuestas en búfer o cortan las conexiones inactivas la rompen. Cambia a/mcp.
Subida rechazada
| Código | Significado | Solución |
|---|---|---|
| 403 | Se intenta publicar un ID que pertenece a otra clave. | Usa la misma clave que llamó a create_upload. |
| 404 | ID desconocido o caducado. | Los espacios vacíos duran 15 minutos y los llenos 30, y se eliminan una vez publicados. Reserva uno nuevo. |
| 409 | Ya se subió contenido para este ID. | Un espacio admite un solo archivo. Reserva otro para volver a subir. |
| 413 | Supera el límite de 200 MB. | Divide la publicación, o deja fuera los recursos grandes y añádelos con write_site_files. |
| 503 | El almacenamiento temporal está desactivado en el servidor. | Publica con archive_url, o pídenos que apuntemos UPLOAD_DIR a una ruta con permiso de escritura. |
| 422 | No se pudo escribir nada. | Revisa la matriz errors. Suele ser una extensión no admitida o una ruta que sale de la raíz del sitio. |
Sigue sin funcionar
Las mismas operaciones están disponibles por HTTP, y reproducir un fallo con la API REST te dice si el problema es del cliente o de la cuenta. Si no es ninguno de los dos, contacta con soporte.