Skip to main content
Glama

Портфолио MCP

Автономный сервер Model Context Protocol (MCP) для управления блогом на базе Supabase, используемым в портфолио Салмана Батта.

Публичное Next.js-портфолио остаётся доступным только для чтения. Этот сервис владеет привилегированной поверхностью управления блогом и хранит секретный ключ Supabase вне фронтенд-развёртывания.

Что он предоставляет

Инструменты для статей

  • list_blog_posts

  • get_blog_post

  • create_blog_post

  • update_blog_post

  • publish_blog_post

  • unpublish_blog_post

  • delete_blog_post

Инструменты для изображений

  • upload_blog_image

  • replace_blog_image

  • delete_blog_image

  • get_blog_image_url

Сервер не предоставляет произвольный SQL или неограниченный доступ к Supabase.

Related MCP server: Self-Hosted Supabase MCP Server

Архитектура

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

Требования

  • Node.js 22+

  • Проект Supabase, содержащий таблицу blogs портфолио

  • Серверный секретный ключ Supabase с доступом к таблице блога и корзине Storage

  • Для ChatGPT: доступное по HTTPS удалённое развёртывание этого MCP-сервера

Настройка

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

Настройте .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

Точки входа HTTP и stdio автоматически загружают локальный файл .env, если он присутствует. Переменные окружения, внедряемые вашей платформой развёртывания, продолжают работать как обычно.

Сгенерируйте MCP-токены

Выполните эту команду дважды:

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

Используйте два разных вывода:

  • PORTFOLIO_MCP_TOKEN — bearer-токен для клиентов, которые могут отправлять заголовки Authorization.

  • PORTFOLIO_MCP_URL_TOKEN — одноразовый токен для клиентов, где настройка статического пользовательского заголовка неудобна.

Оба токена должны быть не менее 32 символов и должны различаться.

Никогда не используйте секретный ключ Supabase в качестве MCP-токена. Никогда не помещайте SUPABASE_SECRET_KEY в URL коннектора ChatGPT.

Аутентификация Supabase

Предпочитайте современный серверный секретный ключ Supabase:

sb_secret_...

Сервис отправляет современные ключи sb_secret_* только в заголовке apikey Supabase. Эти ключи являются непрозрачными ключами API и не отправляются как JWT в Authorization: Bearer.

Устаревшие ключи service_role на основе JWT остаются поддерживаемыми для совместимости при миграции, но новые развёртывания должны использовать sb_secret_*.

Разработка

Удалённый режим HTTP:

npm run dev:http

Конечная точка MCP:

http://localhost:3000/mcp

Проверка работоспособности:

http://localhost:3000/healthz

Локальный режим stdio:

npm run dev:stdio

Режим stdio не использует HTTP MCP-токены, поскольку доступ контролируется локальным процессом, запускающим сервер.

Производственное развёртывание

Соберите и запустите напрямую:

npm run build
npm start

Или используйте Docker:

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

Контейнер устанавливает зависимости из package-lock.json, работает от непривилегированного пользователя node и предоставляет Docker health check /healthz.

Разверните этот сервис на платформе, поддерживающей долго работающий Node HTTP-процесс/контейнер, например Railway, Render, Fly.io, Kubernetes или VPS. Текущая реализация не является точкой входа для serverless-функций Vercel.

Для ChatGPT развёрнутая конечная точка MCP должна быть доступна по HTTPS, например:

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

HTTP-аутентификация

Клиенты, поддерживающие заголовки запросов, должны использовать:

Authorization: Bearer <PORTFOLIO_MCP_TOKEN>

Для клиента, где настройка статического bearer-заголовка неудобна, конечная точка также принимает:

https://YOUR_MCP_HOST/mcp?token=YOUR_PORTFOLIO_MCP_URL_TOKEN

Учётные данные в строке запроса могут появляться в журналах инфраструктуры/доступа. Относитесь к PORTFOLIO_MCP_URL_TOKEN как к одноразовому и ротируйте его при раскрытии. Предпочитайте bearer-аутентификацию, когда MCP-клиент её поддерживает.

Подключение к ChatGPT

ChatGPT подключается к удалённым MCP-серверам, а не к серверу, работающему только на localhost.

На момент обновления этого репозитория (август 2026) OpenAI документирует полную поддержку пользовательских MCP, включая действия записи/изменения для рабочих пространств ChatGPT Business, Enterprise и Edu в вебе. Доступность может меняться, поэтому проверяйте текущую документацию OpenAI по пользовательским приложениям/MCP, если ваш интерфейс отличается.

Когда ваше рабочее пространство ChatGPT предоставляет пользовательские MCP-приложения/коннекторы:

  1. Разверните этот репозиторий на HTTPS-конечной точке.

  2. Настройте все переменные окружения сервера на платформе развёртывания.

  3. В ChatGPT включите режим разработчика / пользовательские приложения в соответствии с правами вашего рабочего пространства.

  4. Создайте пользовательское MCP-приложение.

  5. Если форма ChatGPT не предоставляет статическое поле для пользовательского bearer-заголовка, используйте конечную точку с URL-токеном:

    https://YOUR_MCP_HOST/mcp?token=YOUR_PORTFOLIO_MCP_URL_TOKEN
  6. Выберите No Auth в ChatGPT для этого коннектора. Аутентификация по-прежнему обеспечивается этим сервером через URL-токен.

  7. Выберите Scan Tools. Сервер должен предоставить перечисленные выше инструменты для статей и изображений.

  8. Добавьте/включите приложение в новом чате и протестируйте действие чтения, например list_blog_posts, перед тестированием действия записи.

  9. ChatGPT может запрашивать подтверждение для действий записи/уничтожения в зависимости от прав рабочего пространства/приложения и аннотаций инструментов.

Не вводите SUPABASE_SECRET_KEY в ChatGPT. ChatGPT нуждается только в удалённой конечной точке MCP (и, при такой настройке с URL-токеном, в одноразовом MCP URL-токене).

Рекомендуемая последовательность тестирования ChatGPT

После успешного сканирования коннектора:

List my portfolio blog posts.

Затем:

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

Потом проверьте это:

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

Наконец, удалите тестовый черновик только тогда, когда вы явно намерены его удалить.

CORS / источники

MCP_ALLOWED_ORIGINS принимает список, разделённый запятыми:

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

HTTP-сервер поддерживает современные заголовки MCP-запросов, включая Mcp-Protocol-Version, Mcp-Method, Mcp-Name и Mcp-Session-Id в CORS-предварительных запросах браузера.

Значение по умолчанию * максимизирует совместимость, при этом токен-аутентификация остаётся обязательной. Ужесточите список, когда вы знаете точные источники браузера, которые должны вызывать сервис.

Лимиты запросов и изображений

Максимальный размер HTTP MCP-запроса по умолчанию — 5 МиБ:

MCP_MAX_REQUEST_BYTES=5242880

Это намеренно больше, чем лимит декодированного изображения в 3 МиБ, потому что base64 добавляет примерно одну треть накладных расходов плюс JSON-обрамление.

Принимаемые типы содержимого изображений:

  • PNG

  • JPEG

  • WebP

  • GIF

  • AVIF

Пути хранения нормализуются и отклоняют обход каталогов, например ../. Полезные нагрузки изображений должны содержать корректный base64.

Рекомендуемые пути объектов:

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

Удаление статьи блога не удаляет автоматически её изображения. Это предотвращает случайное удаление медиафайлов, которые могут быть общими или повторно используемыми.

Рабочий процесс блога

Рекомендуемый поток публикации:

  1. Создайте статью как черновик.

  2. Загрузите обложку/диаграммы, если необходимо.

  3. Обновите черновик, указав возвращённые публичные URL изображений.

  4. Проверьте заголовок, выдержку, Markdown, категорию, теги и дату публикации.

  5. Опубликуйте с помощью publish_blog_post.

  6. Обновляйте или снимайте с публикации позже при необходимости.

  7. Удаляйте статью или изображения только тогда, когда это явно задумано.

published_at принимает дату или дату-время в формате ISO 8601, например:

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

Модель безопасности

  • Секретные учётные данные Supabase хранятся только на стороне сервера.

  • Современные ключи sb_secret_* отправляются как ключи API Supabase, а не как JWT bearer-токены.

  • Next.js-портфолио сохраняет свою публичную модель доступа к Supabase только для чтения.

  • HTTP MCP-запросы требуют bearer-токен или URL-токен.

  • MCP-токены должны быть надёжными и различаться.

  • Сравнение токенов использует устойчивое к времени равенство.

  • Не предоставляется общий исполнитель SQL/запросов.

  • Проверяются слаги, даты публикации, пути изображений, типы изображений, полезные нагрузки base64, размеры изображений и размеры HTTP-запросов.

  • Инструменты перезаписи, снятия с публикации, замены и удаления используют аннотации MCP, соответствующие уровню риска.

  • Завершение работы прекращает приём нового трафика и даёт активным запросам ограниченный период дренажа перед закрытием ресурсов MCP.

  • Секреты никогда не должны попадать в GitHub.

Протокол MCP

HTTP-сервер использует стабильный MCP TypeScript SDK v2 и предоставляет Streamable HTTP на /mcp. Включена точка входа stdio для локальных MCP-хостов.

Удалённая HTTP-обёртка поддерживает как современный MCP-трафик, так и устаревший без сохранения состояния fallback SDK для максимальной совместимости с клиентами.

Проверка

Запустите ту же проверку, что используется в CI:

npm run check

Это выполняет:

  • строгую проверку типов TypeScript

  • регрессионные тесты времени выполнения

  • производственную сборку TypeScript

Тесты времени выполнения охватывают обработку секретных ключей Supabase, HTTP-аутентификацию, CORS, лимиты запросов, загрузку окружения, проверку токенов и реальный запрос tools/list MCP через удалённый HTTP-адаптер.

GitHub Actions устанавливает точный граф зависимостей с помощью npm ci из зафиксированного lockfile.

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