Я дал своему портфолио MCP-сервер

Почему и как я построил MCP-сервер поверх своего личного сайта — чтобы AI-ассистенты могли напрямую запрашивать мои проекты, опыт и техническую работу.

Диаграмма: AI-ассистент подключается к портфолио через MCP

Я стал чаще экспериментировать с AI-агентами и MCP, и в какой-то момент у меня возникла простая мысль:

А что если дать моему личному сайту MCP-сервер?

Я не решаю здесь какую-то огромную проблему. Мой сайт не такой уж большой, у меня нет тысяч статей или масштабной базы знаний, которой отчаянно нужен AI-поиск.

Мне просто показалось, что это будет интересно собирать.

А поскольку у меня уже был сайт с проектами, статьями и прочим контентом — это казалось хорошим местом для экспериментов с MCP.

Суть идеи

Сайт — это Astro-проект, и бо́льшая часть контента хранится как Markdown/MDX в Git-репозитории.

Я хотел сохранить это как источник правды и построить поверх небольшой MCP-сервер.

Основная идея:

Архитектура: Git-репозиторий подаёт MDX-файлы в antlis-mcp, который предоставляет их AI-агентам через MCP

Ничего особенно сложного.

MCP-сервер читает контент из репозитория и предоставляет AI-клиентам полезные операции.

Инструменты

Я начал с пяти инструментов:

about_me
search_projects
get_project
search_blog
get_article

Поиск проектов находит по технологиям, темам, описаниям и другой информации о проектах.

Поиск по блогу работает аналогично, а get_project и get_article возвращают полные данные по конкретному элементу.

Например, AI-агент может вызвать:

search_projects("React")

и получить структурированную информацию о проектах.

Или:

get_article("ai-harness-setup")

чтобы получить всю статью целиком.

Это, по сути, вся первая версия.

Почему GitHub?

Потому что контент уже там живёт.

Я не хотел вводить базу данных только ради этого проекта и не хотел поддерживать вторую копию контента сайта где-то ещё.

В репозитории уже есть Markdown/MDX-файлы, и MCP-сервер может их просто читать.

Для проектов я получаю дерево репозитория, нахожу MDX-файлы проектов, паршу их frontmatter и выдаю полезные поля.

Блог работает так же.

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

Простота

Поскольку это в основном эксперимент, я намеренно избегал нагромождения AI-инфраструктуры.

Никакой векторной базы.

Никаких эмбеддингов.

Никакого RAG-пайплайна.

Никакого LLM внутри MCP-сервера.

Объём контента достаточно мал, чтобы обычный поиск прекрасно справлялся.

Реализация по сути:

Пайплайн: GitHub → MDX → парсинг → поиск → MCP-инструменты

Можно всегда сделать сложнее, если реально появится необходимость.

Пока что мне больше нравится небольшой проект, который легко понять.

Деплой на Vercel

Я задеплоил MCP-сервер как Vercel-функцию.

Эндпоинт:

https://antlis-mcp.vercel.app/api/mcp

Сервер написан на TypeScript и использует экосистему MCP SDK вместе с mcp-handler.

Репозиторий тоже подключен к Vercel, поэтому процесс деплоя теперь выглядит так:

Деплой: git push → Vercel → развёрнутый MCP-сервер

Приятно и скучно.

Подключение к Telegram AI-боту

Следующее, что я хотел попробовать — подключить MCP-сервер к AI-агенту, которым я уже пользуюсь.

У меня есть Telegram AI-бот на Hermes, и Hermes поддерживает MCP-серверы.

Я добавил удалённый MCP-эндпоинт к боту.

Архитектура теперь выглядит так:

Интеграция с Telegram: Telegram → AI-бот → antlis-mcp → Git-репозиторий

После подключения бот обнаружил все пять инструментов.

Это уже было хорошим подтверждением того, что сервер работает как надо.

Но, очевидно, просто видеть инструменты — не так уж интересно.

Я хотел, чтобы бот реально их использовал.

Первый реальный тест

Я спросил бота:

Какие проекты демонстрируют опыт с React?

Агент решил, что ему нужна информация с моего сайта, и вызвал MCP-инструмент поиска с запросом React.

MCP-сервер нашёл проекты и вернул подходящий.

Бот использовал результат, чтобы сформировать ответ.

Реальный флоу:

Полный флоу запроса: Telegram-сообщение → AI-модель → MCP-вызов → antlis-mcp → GitHub → данные → ответ

Вот это мне и было интересно.

Я не говорил боту явно, как искать информацию.

Он сам обнаружил, что у него есть инструмент, и решил его использовать.

Более сложный тест

Потом я спросил:

Какие проекты были бы самыми сильными для позиции Senior React/Next.js? Объясни рассуждения и используй данные портфолио, а не свои предыдущие знания.

Снова запрос к MCP-серверу, снова получение данных о проектах.

Ответ был разумным, но тест также выявил нечто важное при построении подобных систем.

Модель начала делать предположения, которых на самом деле нет в моих исходных данных.

Например, она вывела некоторые архитектурные детали из того факта, что проект использует Next.js.

Это хорошее напоминание о том, что MCP магически не предотвращает галлюцинации.

MCP-сервер может предоставить точную информацию, но модель всё равно может слишком агрессивно интерпретировать эти данные.

Думаю, хороший принцип проектирования здесь:

MCP → факты и доказательства
LLM → интерпретация и объяснение

Если в данных проекта сказано, что использовался React и Next.js, MCP-сервер должен вернуть ровно это.

Он не должен превращать это в утверждение о SSR, SSG, управлении состоянием или какой-то другой архитектуре, если этой информации фактически нет.

Модель сама может сделать вывод, но должно быть понятно, когда она делает предположение.

Что дальше

Есть несколько направлений, которые я хочу попробовать.

Очевидное — инструмент более высокого уровня:

recommend_for_role

Вместо простого поиска React-проектов я могу попросить MCP-сервер найти проекты, релевантные:

Senior React / Next.js Developer

Сервер мог бы ранжировать проекты на основе их метаданных и возвращать обоснование каждого совпадения.

Также хочется поэкспериментировать с MCP-ресурсами и промптами.

Например, ресурсы могли бы выглядеть так:

portfolio://projects/topforex
portfolio://projects/tg-mpv-bot
portfolio://articles/ai-harness-setup

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

Но я не хочу превращать это в большой проект только ради добавления фич.

Маленькая версия уже достаточно полезна как эксперимент.

Почему я это сделал

Честно говоря, основная причина в том, что MCP — это интересно.

Я часто использую AI-агентов и экспериментирую с разными способами дать им доступ к информации и инструментам.

Построить MCP-сервер для того, что у тебя уже есть — казалось гораздо лучшим способом изучить это, чем делать очередную игрушку.

Вместо:

"Hello world" MCP-сервер

у меня есть нечто, что реально подключено к моим данным.

И теперь один и тот же контент может иметь два совершенно разных интерфейса:

Два интерфейса: контент сайта разделяется на Astro для людей и MCP для AI-агентов

Сайту не нужно знать ничего об AI-агенте.

AI-агенту не нужно знать, как реализован сайт.

MCP-сервер стоит между ними и предоставляет те части, которые агенту имеет смысл использовать.

Это довольно элегантный паттерн.

Текущее состояние

Реализация намеренно маленькая:

antlis-mcp
├── about_me
├── search_projects
├── get_project
├── search_blog
└── get_article

Она развёрнута на Vercel, работает из того же Git-репозитория, что и сайт, и я успешно подключил её к своему Telegram AI-боту.

Исходный код доступен на GitHub: antlis/antlis-mcp

Теперь я могу спросить бота о своих проектах, и вместо того чтобы полагаться только на уже имеющийся контекст, он может обратиться к реальному источнику.

Попробуйте сами

Вместо того чтобы просто объяснять, что делает MCP, я встроил сюда небольшой клиент для него. Спросите что-нибудь о сайте.

Спросите об этом сайте

Спросите об этом сайте

Виджет отправляет ваш вопрос в LLM, который решает, какие MCP-инструменты вызвать, получает данные с сервера и отвечает на основе найденной информации. Можно развернуть карточки вызовов инструментов, чтобы увидеть, что именно было запрошено и что вернулось.

Позже я расписал, как этот виджет устроен от начала до конца — фронтенд, подключение к OpenRouter и как заставить его стримить ответ, как ChatGPT: Как я заставил чат-виджет портфолио стримить, как ChatGPT.

Текущее состояние

Пока этого достаточно.

Скорее всего, буду расширять по мере того, как будут появляться интересные идеи для MCP.

В этом и есть суть проекта — я хотел узнать, как работает MCP, дав чему-то, что у меня уже есть, AI-интерфейс.

Оказалось, что это довольно весело.