Skip to main content
Glama
billy-yoyo

React MCP SPA

by billy-yoyo

React MCP SPA

Минималистичное одностраничное приложение (SPA) на React, упакованное в один HTML-файл и обслуживаемое сервером MCP Apps. SPA не использует маршрутизацию по URL-путям — оно выбирает, какую страницу отобразить, считывая имя текущего инструмента из контекста хоста MCP.

Структура

  • packages/ui/ — SPA на React + Vite, собираемое в единый HTML-файл с помощью vite-plugin-singlefile.

  • packages/mcp/ — MCP-сервер, использующий @modelcontextprotocol/ext-apps/server. Регистрирует инструменты (show-home, show-counter, show-profile), которые указывают на один и тот же ресурс ui://.

  • packages/playground/ — инструмент для разработки, который отображает SPA внутри имитации чата с JSON-вводами для hostContext и toolResult, чтобы страницы можно было тестировать без MCP-хоста.

Установка

Требуется Node.js версии ≥ 20 и pnpm версии ≥ 9.

pnpm install

Разработка UI в изоляции

pnpm run dev:ui

Откройте указанный URL (например, http://localhost:5173). SPA обнаружит отсутствие MCP-хоста и покажет выбор маршрута, чтобы вы могли просмотреть каждую страницу.

Playground — тестирование рендеринга без MCP

pnpm run dev:playground

Открывается по адресу http://localhost:5174. Playground повторно использует реальный рендерер маршрутов SPA (RouteRenderer из packages/ui/src/Router.tsx) и оборачивает его в имитацию чата. В заголовке есть два текстовых поля JSON — одно для hostContext (определяет, какая страница отображается через toolInfo.tool.name), и другое для toolResult, передаваемого на страницу. Кнопки пресетов загружают готовые пары контекст+результат для каждого зарегистрированного инструмента; изменения в любом из текстовых полей обновляют вывод инструмента помощника в реальном времени.

Сборка и запуск MCP-сервера

pnpm run build       # builds packages/ui → dist/index.html, then packages/mcp
pnpm run serve:mcp   # starts Streamable HTTP server on http://localhost:3001/mcp

Для транспорта stdio:

pnpm --filter @react-mcp-spa/mcp run serve:stdio

Публикация сервера через cloudflared

Некоторые MCP-клиенты (включая облачные) не могут получить доступ к localhost. Используйте cloudflared, чтобы открыть быстрый туннель, который присваивает публичный HTTPS URL.

Установите cloudflared через менеджер пакетов вашей ОС:

# macOS (Homebrew)
brew install cloudflared

# Linux (Debian/Ubuntu)
# See https://pkg.cloudflare.com/ for the apt repo, or grab the .deb from
# https://github.com/cloudflare/cloudflared/releases

# Windows (winget)
winget install --id Cloudflare.cloudflared

Запустите сервер локально:

pnpm run serve:mcp

В другом терминале выполните:

cloudflared tunnel --url http://localhost:3001
# or: pnpm run tunnel

cloudflared выведет URL вида https://<random>.trycloudflare.com. Добавьте /mcp и используйте его как URL вашего MCP-сервера:

https://<random>.trycloudflare.com/mcp

Туннель остается активным, пока вы не завершите работу cloudflared. Для получения стабильного имени хоста настройте именованный туннель Cloudflare вместо быстрого туннеля.

Упаковка в качестве расширения Claude Desktop (.mcpb)

В репозитории есть упаковщик, который создает устанавливаемый MCP Bundle для Claude Desktop. Расширение запускает сервер через stdio — туннель не требуется.

pnpm run pack:mcpb

Эта команда собирает оба пакета, подготавливает скомпилированный сервер + UI HTML + рабочие node_modules в папке build/mcpb-staging/ и вызывает mcpb pack для создания:

build/react-mcp-spa.mcpb

Чтобы установить его, дважды щелкните файл .mcpb в Finder/Explorer (или перетащите его в Claude Desktop). Claude проверит манифест и зарегистрирует сервер; после установки три инструмента (show-home, show-counter, show-profile) станут доступны, и каждый из них будет отображать свою страницу как встроенный React UI.

Манифест пакета находится в mcpb/manifest.json — обновляйте там version (а также в packages/mcp/package.json) при выпуске новой версии расширения.

Как работает маршрутизация

SPA никогда не считывает window.location. Вместо этого packages/ui/src/App.tsx использует useApp() из @modelcontextprotocol/ext-apps/react и:

  1. Считывает app.getHostContext().toolInfo.tool.name, чтобы узнать, какой инструмент вызвал хост — это и есть "маршрут".

  2. Подписывается на app.ontoolresult, чтобы получить CallToolResult от сервера и передать его на страницу в качестве данных.

  3. Отслеживает app.onhostcontextchanged, чтобы обновления темы, безопасных областей (safe-area) или локали корректно перерисовывались.

Добавление новой страницы — это двухэтапный процесс:

  1. Зарегистрируйте инструмент в packages/mcp/src/server.ts с _meta.ui.resourceUri, указывающим на общий ресурс ui://react-mcp-spa/app.html.

  2. Добавьте case для имени инструмента в renderRoute() внутри packages/ui/src/App.tsx.

-
security - not tested
F
license - not found
-
quality - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

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/billy-yoyo/McpReactSpa'

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