mcp-a2ui-vega
mcp-a2ui-vega
MCP-приложение с интерфейсом A2UI и графиками Vega-Lite.
Попросите Claude показать дашборд продаж билетов — и он появится в разговоре: метрики, графики, таблица последних заказов, место для загрузки CSV. Затем попросите изменить что-то — превратите график продаж в линейный и покажите сегодняшние продажи зелёным, добавьте тепловую карту, когда люди покупают — и дашборд будет отредактирован на месте, а не перерисован с нуля. Перетащите в него CSV или добавьте строки из скрипта — и каждый график обновится сам по себе.
Дашборд — это не картинка, созданная моделью. Это дерево компонентов, которое
агент собрал из типизированного каталога, отрисованное собственным рендерером
A2UI от Google (@a2ui/react),
привязанное к набору данных, который отправляет ему изменения.
Из чего он состоит
Компонент | Что делает |
Каталог A2UI — API компонентов, функции и JSON-Schema-документ, сгенерированный из них. Контракт между агентом и рендерером. | |
Представление MCP-приложения: React + | |
Cloudflare Worker: MCP-сервер, хранилище наборов данных, библиотека сохранённых виджетов и ресурс | |
Набор данных, основанный на реальных еженедельных сборах Бродвея. | |
Навык, который учит агента хорошо собирать и пересобирать такие дашборды. | |
Сборщик набора данных, канал живого добавления, тестовый хост, сквозной тест. |
Никаких API-ключей. В этом репозитории нет модели. Агент — это любой MCP-хост, который подключается; сервер хранит строки и собирает JSON; рендерер детерминирован. Единственные учётные данные — это Cloudflare-ключи, которые нужны для развёртывания Worker.
Related MCP server: vegalite-viewer
Что это такое в терминах самого A2UI
В статье Google A2UI and MCP Apps названы три способа совместной работы двух протоколов. Этот репозиторий — Паттерн 3: A2UI внутри MCP Apps — пакет MCP-приложения несёт собственный рендерер A2UI, что позволяет хосту, который никогда не слышал об A2UI (сегодня это Claude), показывать UI, собранный агентом.
Это настоящий A2UI, а не его имитация. Рендерер — это
@a2ui/react, управляющий
MessageProcessor из @a2ui/web_core —
пакеты Google, без изменений. Формат передачи — сообщения A2UI v0.9:
createSurface, updateComponents, updateDataModel. Каталог расширяет
собственный базовый каталог A2UI, а не заменяет его, поэтому Column, Card
и ChoicePicker — их, а VegaChart — наш, под одним идентификатором каталога.
Здесь также реализован Паттерн 1: A2UI поверх MCP как второй путь — тот же
дашборд отдаётся как application/a2ui+json по адресу
a2ui://dashboard/ticket_sales, так что хост с собственным рендерером A2UI
(Flutter, Angular, нативный клиент) может отрисовать его вообще без iframe.
Этот payload — переносимый артефакт; MCP-приложение — способ увидеть его всем
остальным.
Как дашборд остаётся живым
agent ──render_dashboard──▶ server ──A2UI messages in _meta──▶ view
┌──────── change stream (SSE) ────────┐
server ──────────────┘ "ticket_sales moved" ▼
▲ view
└── get_dataset_rows, through the host's tool proxy ──── │
│
updateDataModel ──┘ every chart,
tile and table
re-rendersОсновную работу делают четыре решения:
Строки никогда не проходят через модель. render_dashboard возвращает
раскладку и количество строк. Представление само получает строки через
get_dataset_rows — инструмент, у которого _meta.ui.visibility равно
["app"], поэтому он никогда не появляется в списке инструментов агента.
Двенадцать тысяч заказов должны быть в графике, а не в контекстном окне.
Дашборд — это компоненты, а не изображение. Изменение одного графика — это
один вызов update_dashboard с указанием одного id. Фильтры пользователя,
порядок сортировки и позиция прокрутки сохраняются, потому что больше ничего
не затрагивается.
Обновление должно отображаться в представлении, которое никогда не видело
дашборд. Хост может открывать новое представление для каждого результата
инструмента, а не направлять его в текущее, и payload из чистых
updateComponents нечего обновлять там — A2UI отклоняет его с ошибкой
surface not found, и пользователь получает пустую панель там, где просил
изменение. Поэтому сервер запоминает собранное дерево, и каждое обновление
передаётся в двух формах: _meta['a2ui/messages'] пересобирает всю поверхность
с нуля, _meta['a2ui/patch'] несёт только дельту. Представление применяет ту,
которая подходит к тому, что у него уже есть, так что серверу не нужно
угадывать, с каким представлением он разговаривает.
Сервер говорит когда, хост по-прежнему несёт что. В MCP нет канала
сервер→представление, поэтому представление держит открытым поток изменений
напрямую к Worker — единственное, что ресурс приложения разрешает в
csp.connectDomains. По нему приходит уведомление, а не данные: строки
по-прежнему загружаются через прокси инструментов хоста, так что каждый байт
данных остаётся проверяемым. Простаивающий дашборд не делает никаких запросов,
а изменение доходит до него примерно за секунду.
Любой график, включая те, которых нет в каталоге
VegaChart принимает целую спецификацию Vega-Lite как свойство. Тепловая карта,
ящик с усами, фасетные малые множества — ни одного из них нет в каталоге, и все
они работают, потому что граница каталога — это типы компонентов, а не типы
графиков.
Когда пользователю нравится какой-то график, save_widget сохраняет его по
имени, а render_dashboard({widgets: ["sales_by_hour_heatmap"]}) возвращает его
в более позднем разговоре — всё ещё привязанным к живому набору данных, так что
он обновляется, как и всё остальное.
Данные
data/ticket_sales.csv — это по одной строке на каждый заказ билетов по
двенадцати бродвейским шоу. Шоу, их театры, размеры залов, недельная заполняемость
и уровни цен — реальные, из набора данных Broadway weekly grosses
dataset
(Playbill, через TidyTuesday). Отдельные заказы смоделированы на основе этих
цифр, потому что источник — недельный и агрегированный. В
data/README.md точно сказано, какие части какие.
npm run data:build # rebuild, 90 days ending now
npm run data:append -- --watch 10 # a live feed: new orders every 10sУкажите это для развёртывания с --url https://your-worker.workers.dev и
наблюдайте, как дашборд движется, пока вы на него смотрите — в течение секунды
после каждого добавления, потому что сервер сообщает ему об этом.
Запуск
npm install
npm run data:build # build the dataset (downloads the source CSV once)
npm run build # catalog → renderer → single-file app → worker
npm run dev -w @mcp-a2ui-vega/serverЗатем откройте http://localhost:8788/app.html для дашборда отдельно или http://localhost:8788/ для инструкций по подключению.
Установка в Claude
Сначала разверните (ниже) — до пользовательского коннектора обращаются из
облака Anthropic, а не с вашей машины, так что localhost не подойдёт.
Claude Code, прямо из этого репозитория:
/plugin marketplace add vpm238/mcp-a2ui-vega
/plugin install a2ui-vega-dashboards@mcp-a2ui-vegaЭто устанавливает MCP-сервер и навык вместе. URL сервера указан в
.claude-plugin/plugin.json — если вы развернёте собственный Worker, измените
эту одну строку и выполните /plugin marketplace update mcp-a2ui-vega.
Claude web или desktop: Настройки → Коннекторы → Добавить пользовательский
коннектор и вставьте https://your-worker.workers.dev/mcp. Никакого OAuth и
ключей нет. Затем добавьте навык: заархивируйте папку skills/a2ui-dashboards —
сама папка должна быть в корне архива — и загрузите её в Настройки →
Возможности → Навыки.
Навык в любом случае необязателен: сервер отправляет инструкции по использованию в своём MCP-рукопожатии. Именно он делает последующие запросы хорошими — редактирование одного компонента вместо перерисовки всего и запоминание понравившихся графиков.
Затем попросите дашборд продаж билетов.
Развёртывание
Worker — единственное, что нужно хостить. GitHub Pages получает автономное демо.
npx wrangler login
npm run deploy -w @mcp-a2ui-vega/serverЭто создаёт пространство имён KV, если его ещё нет, записывает его id в
wrangler.toml, собирает приложение и начальные данные и развёртывает.
Или добавьте два секрета репозитория и отправьте в main —
рабочий процесс делает всё это, включая создание
пространства имён, и пропускает развёртывание с предупреждением, а не с ошибкой,
пока секреты отсутствуют:
Секрет | Что это такое |
| Токен из шаблона Edit Cloudflare Workers |
| Ваш id аккаунта, из панели Workers |
Тот же рабочий процесс публикует автономное демо на GitHub Pages, как только Pages включён в Настройки → Pages с источником GitHub Actions. Пока этого не произошло, рабочий процесс сообщает об этом в предупреждении и остаётся зелёным.
Тестирование
npm test # dataset and catalog checks
npm run dev -w @mcp-a2ui-vega/server # terminal 1
python3 -m http.server 8479 # terminal 2, at the repo root
node tools/e2e.mjs # a real browser, the real protocolЧтобы запустить тот же набор тестов против развёртывания, а не локального worker:
node tools/relay.mjs https://your-worker.workers.dev # terminal 3
SERVER_URL=http://localhost:8790 node tools/e2e.mjsРетранслятор существует потому, что браузер за строгим прокси может не достать до Cloudflare, в то время как Node может; каждый байт по-прежнему приходит из реального развёртывания. Он буферизует ответы, поэтому не переносит поток изменений — представление за ним переходит на опрос, что тоже стоит проверить.
tools/e2e.mjs управляет tools/harness.html — самодельным
MCP Apps-хостом, ~120 строк, намеренно не разделяющим код с приложением, чтобы
ошибка протокола не могла незаметно пройти в обоих. Он проверяет то, что
проверка типов не может: что дашборд рисуется, что пересборка перекрашивает одну
плитку, не затрагивая остальные, что добавленные строки приходят без запроса,
что фильтр двигает метрики и таблицу вместе, и что сохранённый виджет
возвращается.
tools/push-latency.mjs измеряет то, что заявляет архитектура: простаивающий
дашборд делает ноль запросов, а изменение доходит до него примерно за
полсекунды ровно с одним fetch.
node tools/push-latency.mjs https://your-worker.workers.devЛицензия
MIT.
This server cannot be installed
Maintenance
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
- AlicenseNot gradedqualityDmaintenanceEnables business intelligence chart creation and visualization using Vega-Lite, with data loading and processing capabilities.13Apache 2.0
- AlicenseAqualityCmaintenanceMCP server for creating interactive Vega-Lite data visualizations that render inline in chat via MCP Apps.21MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to compose and edit dashboards through MCP tools, allowing them to manage tabs, widgets, layout, and data bindings via a unified control plane.9MIT
- FlicenseAqualityBmaintenanceMCP server that lets agents create, display, and export rich UI widgets (cards, dashboards, charts, forms) inline in conversations, with interactive iframe support in MCP Apps hosts and PNG image fallback for other clients.3
Related MCP Connectors
Create, browse, remix, collaborate on, and run durable AI workflow nodes from MCP hosts.
Build, deploy, and operate hosted web apps on VibeKit (vibekit.bot) from any MCP client.
MCP Hub: AI service discovery, per-user OAuth, and multi-service workflow orchestration
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/vpm238/mcp-a2ui-vega'
If you have feedback or need assistance with the MCP directory API, please join our Discord server