Skip to main content
Glama

Portfolio MCP

Servidor independiente del Model Context Protocol (MCP) para gestionar el blog de ingeniería respaldado por Supabase que utiliza el portafolio de Salman Butt.

El portafolio público de Next.js permanece de solo lectura. Este servicio posee la superficie privilegiada de gestión del blog y mantiene la clave secreta de Supabase fuera del despliegue del frontend.

Lo que expone

Herramientas de artículos

  • list_blog_posts

  • get_blog_post

  • create_blog_post

  • update_blog_post

  • publish_blog_post

  • unpublish_blog_post

  • delete_blog_post

Herramientas de imágenes

  • upload_blog_image

  • replace_blog_image

  • delete_blog_image

  • get_blog_image_url

El servidor no expone SQL arbitrario ni acceso sin restricciones a Supabase.

Related MCP server: Self-Hosted Supabase MCP Server

Arquitectura

ChatGPT / remote MCP host / local MCP client
             |
             | Streamable HTTP or stdio
             v
      portfolio-mcp service
             |
             +--> MCP token authentication (HTTP)
             |
             +--> MCP SDK v2 tool layer
             |
             +--> Supabase REST: public.blogs
             |
             +--> Supabase Storage: blog-images

Public visitors
      |
      v
Next.js portfolio --> Supabase anon read-only access

Requisitos

  • Node.js 22+

  • Un proyecto de Supabase que contenga la tabla blogs del portafolio

  • Una clave secreta de Supabase del lado del servidor con acceso a la tabla de blogs y al bucket de Storage

  • Para ChatGPT: un despliegue remoto de este servidor MCP accesible por HTTPS

Configuración

git clone https://github.com/salman0butt/portfolio-mcp.git
cd portfolio-mcp
npm ci
cp .env.example .env

Configura .env:

SUPABASE_URL=https://YOUR_PROJECT.supabase.co
SUPABASE_SECRET_KEY=sb_secret_REPLACE_ME
SUPABASE_BLOG_BUCKET=blog-images

PORTFOLIO_MCP_TOKEN=replace-with-long-random-bearer-token
PORTFOLIO_MCP_URL_TOKEN=replace-with-different-long-random-url-token

PORT=3000
HOST=0.0.0.0
MCP_ALLOWED_ORIGINS=*
MCP_MAX_REQUEST_BYTES=5242880

Los puntos de entrada HTTP y stdio cargan automáticamente un archivo .env local cuando está presente. Las variables de entorno inyectadas por tu plataforma de despliegue siguen funcionando normalmente.

Generar los tokens MCP

Ejecuta este comando dos veces:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Usa dos salidas diferentes:

  • PORTFOLIO_MCP_TOKEN — token de portador para clientes que pueden enviar cabeceras Authorization.

  • PORTFOLIO_MCP_URL_TOKEN — token desechable para clientes donde una cabecera estática personalizada es inconveniente.

Ambos tokens deben tener al menos 32 caracteres y deben ser diferentes.

Nunca uses la clave secreta de Supabase como token MCP. Nunca pongas SUPABASE_SECRET_KEY en una URL de conector de ChatGPT.

Autenticación de Supabase

Prefiere la clave secreta moderna del lado del servidor de Supabase:

sb_secret_...

El servicio envía claves modernas sb_secret_* solo en la cabecera apikey de Supabase. Estas claves son claves API opacas y no se envían como JWTs Authorization: Bearer.

Las claves service_role basadas en JWT heredadas siguen siendo compatibles para la migración, pero los nuevos despliegues deben usar sb_secret_*.

Desarrollo

Modo HTTP remoto:

npm run dev:http

Punto final MCP:

http://localhost:3000/mcp

Comprobación de salud:

http://localhost:3000/healthz

Modo stdio local:

npm run dev:stdio

El modo stdio no usa tokens MCP HTTP porque el acceso está controlado por el proceso local que lanza el servidor.

Despliegue en producción

Compila y ejecuta directamente:

npm run build
npm start

O usa Docker:

docker build -t portfolio-mcp .
docker run --rm -p 3000:3000 --env-file .env portfolio-mcp

El contenedor instala las dependencias desde package-lock.json, se ejecuta como el usuario node no root y expone una comprobación de salud Docker /healthz.

Despliega este servicio en una plataforma que admita un proceso/contenedor HTTP de Node de larga duración, como Railway, Render, Fly.io, Kubernetes o un VPS. La implementación actual no es un punto de entrada de función serverless de Vercel.

Para ChatGPT, el punto final MCP desplegado debe ser accesible por HTTPS, por ejemplo:

https://portfolio-mcp.example.com/mcp

Autenticación HTTP

Los clientes que admiten cabeceras de solicitud deben usar:

Authorization: Bearer <PORTFOLIO_MCP_TOKEN>

Para un cliente donde configurar una cabecera de portador estática es inconveniente, el punto final también acepta:

https://YOUR_MCP_HOST/mcp?token=YOUR_PORTFOLIO_MCP_URL_TOKEN

Las credenciales en la cadena de consulta pueden aparecer en los registros de infraestructura/acceso. Trata PORTFOLIO_MCP_URL_TOKEN como desechable y rótalo si se expone. Prefiere la autenticación de portador cuando el cliente MCP lo admita.

Conectar a ChatGPT

ChatGPT se conecta a servidores MCP remotos, no a un servidor que se ejecuta solo en localhost.

En el momento de esta actualización del repositorio (agosto de 2026), OpenAI documenta soporte completo de MCP personalizado, incluidas acciones de escritura/modificación para espacios de trabajo de ChatGPT Business, Enterprise y Edu en la web. La disponibilidad puede cambiar, así que consulta la documentación actual de aplicaciones/MCP personalizadas de OpenAI ChatGPT si tu interfaz difiere.

Cuando tu espacio de trabajo de ChatGPT exponga aplicaciones/conectores MCP personalizados:

  1. Despliega este repositorio en un punto final HTTPS.

  2. Configura todas las variables de entorno del servidor en la plataforma de despliegue.

  3. En ChatGPT, activa el Modo Desarrollador / aplicaciones personalizadas según los permisos de tu espacio de trabajo.

  4. Crea una aplicación MCP personalizada.

  5. Si el formulario de ChatGPT no proporciona un campo de cabecera de portador estática personalizada, usa el punto final de token de URL:

    https://YOUR_MCP_HOST/mcp?token=YOUR_PORTFOLIO_MCP_URL_TOKEN
  6. Selecciona Sin autenticación en ChatGPT para ese conector. La autenticación aún la aplica este servidor mediante el token de URL.

  7. Elige Escanear herramientas. El servidor debe exponer las herramientas de artículos e imágenes listadas anteriormente.

  8. Añade/habilita la aplicación en un nuevo chat y prueba una acción de lectura como list_blog_posts antes de probar una acción de escritura.

  9. ChatGPT puede solicitar confirmación para acciones de escritura/destructivas según los permisos del espacio de trabajo/aplicación y las anotaciones de herramientas.

No introduzcas SUPABASE_SECRET_KEY en ChatGPT. ChatGPT solo necesita el punto final MCP remoto (y, con esta configuración de token de URL, el token MCP de URL desechable).

Secuencia de prueba recomendada para ChatGPT

Después de que el conector escanee correctamente:

List my portfolio blog posts.

Luego:

Create a draft blog post titled "MCP Connection Test". Do not publish it.

Después verifícalo:

Get the MCP Connection Test draft and show me its metadata.

Finalmente, elimina el borrador de prueba solo cuando tengas la intención explícita de eliminarlo.

CORS / orígenes

MCP_ALLOWED_ORIGINS acepta una lista separada por comas:

MCP_ALLOWED_ORIGINS=https://example.com,https://another-client.example

El servidor HTTP admite las cabeceras MCP actuales, incluidas Mcp-Protocol-Version, Mcp-Method, Mcp-Name y Mcp-Session-Id en los preflight CORS del navegador.

El valor predeterminado * maximiza la compatibilidad mientras la autenticación por token sigue siendo obligatoria. Ajusta la lista cuando conozcas los orígenes exactos del navegador que deben llamar al servicio.

Límites de solicitudes e imágenes

El límite predeterminado de solicitudes HTTP MCP es 5 MiB:

MCP_MAX_REQUEST_BYTES=5242880

Esto es intencionalmente mayor que el límite de imagen decodificada de 3 MiB porque base64 añade aproximadamente un tercio de sobrecarga más el marco JSON.

Tipos de contenido de imagen aceptados:

  • PNG

  • JPEG

  • WebP

  • GIF

  • AVIF

Las rutas de almacenamiento se normalizan y rechazan el traversal como ../. Las cargas útiles de imagen deben contener base64 válido.

Rutas de objetos recomendadas:

senior-software-engineer/cover.webp
production-rag-systems/architecture.webp
nextjs-at-scale/performance.webp

Eliminar un artículo de blog no elimina automáticamente sus imágenes. Esto evita la eliminación accidental de medios que pueden compartirse o reutilizarse.

Flujo de trabajo del blog

Flujo de publicación recomendado:

  1. Crea el artículo como borrador.

  2. Sube imágenes de portada/diagramas si es necesario.

  3. Actualiza el borrador con las URLs públicas de imagen devueltas.

  4. Revisa el título, el extracto, el Markdown, la categoría, las etiquetas y la fecha de publicación.

  5. Publica usando publish_blog_post.

  6. Actualiza o despublica más tarde cuando sea necesario.

  7. Solo elimina el artículo o las imágenes cuando sea explícitamente intencional.

published_at acepta una fecha o fecha-hora ISO 8601, por ejemplo:

2026-08-25
2026-08-25T12:00:00+05:00

Modelo de seguridad

  • Las credenciales secretas de Supabase son solo del lado del servidor.

  • Las claves modernas sb_secret_* se envían como claves API de Supabase, no como tokens de portador JWT.

  • El portafolio de Next.js mantiene su modelo de acceso público de solo lectura a Supabase.

  • Las solicitudes HTTP MCP requieren un token de portador o token de URL.

  • Los tokens MCP deben ser fuertes y distintos.

  • La comparación de tokens usa igualdad segura en tiempo.

  • No se expone ningún ejecutor SQL/consulta genérico.

  • Se validan slugs, fechas de publicación, rutas de imagen, tipos de imagen, cargas útiles base64, tamaños de imagen y tamaños de solicitud HTTP.

  • Las herramientas de sobrescritura, despublicación, reemplazo y eliminación usan anotaciones MCP apropiadas al riesgo.

  • El apagado deja de aceptar nuevo tráfico y da a las solicitudes activas un período de drenaje limitado antes de cerrar los recursos MCP.

  • Los secretos nunca deben comprometerse en GitHub.

Protocolo MCP

El servidor HTTP usa el SDK de TypeScript MCP estable v2 y expone HTTP Streamable en /mcp. Se incluye un punto de entrada stdio para hosts MCP locales.

El envoltorio HTTP remoto admite tanto el tráfico MCP moderno como el fallback heredado sin estado del SDK para maximizar la compatibilidad con los clientes.

Validación

Ejecuta la misma validación que usa CI:

npm run check

Esto ejecuta:

  • verificación estricta de tipos de TypeScript

  • pruebas de regresión en tiempo de ejecución

  • compilación de TypeScript de producción

Las pruebas en tiempo de ejecución cubren el manejo de claves secretas de Supabase, autenticación HTTP, CORS, límites de solicitudes, carga de entorno, validación de tokens y una solicitud real de tools/list MCP a través del adaptador HTTP remoto.

GitHub Actions instala el grafo de dependencias exacto con npm ci desde el lockfile comprometido.

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Manage your Ghost blog content directly from Claude, Cursor, or any MCP-compatible client, allowing you to create, edit, search, and delete posts with support for tag management and analytics.
    14
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables developers to interact with self-hosted Supabase instances, providing database introspection, migration management, auth user operations, storage management, and TypeScript type generation directly from MCP-compatible development environments.
  • A
    license
    A
    quality
    F
    maintenance
    Enables AI tools to programmatically manage Substack content, including creating drafts, publishing posts, and posting to Substack Notes. It supports image uploads, live blogging, and document formatting compatible with Substack's ProseMirror editor.
    11
    8
    MIT

View all related MCP servers

Related MCP Connectors

  • Publish and manage articles, series, comments, reactions, newsletters and blog analytics.

  • Manage Supabase projects end to end across database, auth, storage, realtime, and migrations. Moni…

  • Manage Appwrite projects, databases, auth, storage, functions, and messaging; search Appwrite docs

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/salman0butt/portfolio-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server