apic
apic
Компилятор из приложения в API. Укажите ему веб-приложение, у которого нет API для агентов. Агент, работающий с компьютером, исследует UI, проверяет найденное, выполняя это, и выдаёт типизированный MCP-сервер для приложения.
Playwright MCP интерпретирует приложение при каждом вызове. apic компилирует его один раз.
Создано в одиночку за один день на {Tech: Europe} × VEED Hackathon, Лондон, 22 августа 2026.
→ apic-ui.vercel.app — там демо-видео, решения каждой модели-партнёра и результаты замеров компилятора.
Публичные потребительские сайты
apic --read https://example.com компилирует публичную, доступную только для чтения поверхность любого потребительского сайта в MCP-инструменты. Он начинает с этого сайта (плюс необязательные стартовые URL того же сайта), находит поисковые поля, фильтры и повторяющиеся карточки результатов, а затем выдаёт только те инструменты, чьи «строки» переживают чистый перезапуск. Он не исходит из предположения о маршрутах Deliveroo, ресторанной лексике, аккаунте, корзине или оформлении заказа.
Для известной страницы коллекции/товара передайте её явно как прямой стартовый URL того же сайта: APIC_READ_DIRECT_URL=https://example.com/catalog/item apic --read https://example.com. URL, предоставляемые агентом, ограничены тем origin, который был скомпилирован в рецепт.
Один запрос без целевого URL
Когда APIC подключён к MCP-серверу, для обычного пользовательского вопроса используйте fulfill_request вместо compile_app:
{ "request": "Find me the cheapest pizza near 17 & 18 Clere Street" }Сервер использует Tavily для поиска публичных кандидатных сервисов, OpenAI — для выбора и выполнения скомпилированного сценария, h — для приоритизации неоднозначных контролов чтения, Pioneer — для классификации того, дали ли пробные проверки осмысленные результаты, а fal — только там, где этой классификации нужна визуальная арбитражная проверка. Он пробует небольшой резервный набор из других origins, если кандидат защищён вызовом или не имеет воспроизводимого публичного сценария. Он никогда не входит в систему, не делает заказ, не завершает покупку и не обходит вызов. Выжившие инструменты чистым способом проверяются, возвращаются в качестве подтверждения и регистрируются на том же MCP-сервере для последующих вызовов.
Related MCP server: mcp-apps-demo-engine
Демонстрация
Смотрите на сайте: apic-ui.vercel.app — две минуты, без монтажа: компиляция, появление сгенерированных инструментов, в живую сессию и watcher, который сам замечает изменение UI.
На том же сайте — цифры, о которых говорится в этом README, разбивка по партнёрам и фрагмент для установки для каждого MCP-клиента.
Проблема
Агенты, работающие с компьютером, экономически не масштабируются. Каждый запуск заново извлекает из пикселей одни и те же знания: модель совершает круг за шагом, снимок страницы за шагом заполняет контекстное окно, а надёжность падает с каждым звеном цепочки. Именно поэтому их беспрерывно показывают в демо, но редко внедряют.
Программное обеспечение, которым агентам нужно управлять сильнее всего, — это как раз ПО, которое с наименьшей вероятностью когда-либо получит API: внутренние инструменты, legacy-системы, всё, от чего исчез вендор. Нельзя прочесть сетевую вкладку, в которой ничего нет, и нельзя попросить корпоративное приложение 2011 года внедрить новый протокол.
apic использует дорогого агента один раз, чтобы написать интерфейс. После этого — это просто вызов функции.
Как это работает
Этап | Задача | Технология |
Ground | Читает документацию целевого сайта и усваивает существительные этого приложения, чтобы словарь не был захардкожен под Vikunja | Tavily + OpenAI, кэш по хосту — только CLI-путь |
Explore | Управляет приложением, ранжирует возможности так, чтобы действия создания шли первыми, открывает формы и отправляет их | Playwright + h (уровень эскалации для контролов, которые словарь не может назвать) |
Perceive | Определяет, изменилось ли что-то значимое | DOM-сравнение, обостряет эскалацией до fal на CLI-пути |
Synthesise | Превращает траекторию в типизированную схему инструмента | детерминированно — без обращения к модели |
Verify | Холодно повторяет инструмент с аргументами, которых приложение никогда не видел | нижняя граница — diff без ключей, затем дообученный судья Pioneer, с OpenAI в резерве |
Emit | Создаёт запускаемый MCP-сервер, его схемы и доказательства | — |
Watch | Повторно прогоняет тесты через интервал | — |
Heal | Красный («упавший») инструмент повторно входит в discovery на собственном фиде | — |
Путь восстановления — тот же путь, что и путь построения. «Лечение» не патчит селектор — оно заново про googles discovery, которое первоначально создало инструмент, и сопоставляет по имени, которое выдаёт синтез. Переименованная кнопка по-прежнему даёт createProject.
Инструмент существует только тогда, когда приложение подтвердило запись
Подсчёт узлов DOM даёт правдоподобный инструмент для каждой кнопки на странице. apic выпускает инструмент только тогда, когда само приложение подтверждает, что состояние изменилось, — через три сигнала, отражающих три разных типа поведения приложения:
Поведение | Пример | Сигнал |
announce-and-stay | создание метки | баннер успеха в области статуса |
announce-and-navigate | создание проекта | баннер переживает смену URL |
silent-append | быстрое добавление в канбан | введённое значение появляется как отрисованный контент |
relocation | перетаскивание карточки между колонками | карточка сменила контейнер |
Перемещение важно, потому что у сервер no banner and no echo — the card already existed. The change of container is the proof; no decorative re-render can produce it.
Рецепты привязаны к идентификации, а не к местоположению
Vikunja на каждой загрузке страницы заново генерирует DOM-идентификаторы, поэтому сохранённый селектор мёртв с самого начала. Рецепт фиксирует, чем поле является — его подпись, placeholder, name — и при воспроизведении повторно резолвит его вживую, в числу it: стабильную селекторную «цепочку» (name → стабильный id → placeholder → and last the generated id).
Результаты
Скомпилировано из интерфейса. Спецификация OpenAPI, предоставленная сайтом, никогда не читается во время компиляции — она используется только как истина-эталон для оценки, поэтому число полноты, которое здесь называется, «до».
День знаменатель, before the unexam: 18 — это все операции записи (POST/PUT/DELETE) по /projects, /tasks and /labels в спецификации OpenAPI самого Vikunja, за минусом того, что не является жестом доски: teams, project-level permissions, sharing by link, attachments, task relationships, duplication, bulk endpoints and read receipts. Vikunja publishes a total of 105 write operations; 18 — this is a subset that a person can perform on a Kanban board, and each emitted tool may pretend to hold at most one of them, so the accuracy cannot be inflated by vague matching.
RECALL 8/18 of the board write-ops in the target's own API
PRECISION 9/9 emitted tools that map to a real operation
VERIFIED 9/9 survived a cold replay with arguments never seen beforeДевять инструменты нашли, девять были показаны. Отклонённые инструменты не удаляются — они остаются в tools.json с verified: false, потому что отброшенный инструмент — это evidence about the compiler, not garbage.
markTask is flavky, and that's more valuable than the 9/9. Two consecutive verifying runs over same build, with no changes in between, gave 8/9 and then 9/9: it failed with "observed mutation but nothing confirmed a write", and then passed with "Success — the task was saved successfully." The probable cause is the state of the seed: if the agent starts from an already completed task, the control reads as MARK THE UNDONE and confirms it differently. It takes no parameters, so it cannot disambiguate by an argument either.
Это — живое проявление проблемы flake-vs-drift, которая ниже перечислена как нерешённая: watch посчитал бы этот сбой дрейфом и вызвал было бы heal, хотя дрейф ничем не.
Непрекращающаяся проверка в течение живого дня:
327 checks · 118 breaks · 3 automatic repairs · MTTR 20s(out/watch-stats.json, 38head from 11:33, still running when playing — counters keep moving.)
Смотрите на этот счётчик числа просто провалов. stats.breaks++ срабатывает на каждый красный повтор в каждомы цикле, поэтому три инструмента с, остававшихся красными все 38 циклов, читаются как ~114 провалов — это счётчик «красный инструмент × цикл», а не 118 отдельных событий дрейфа. А этот watcher был запущен в 11:12, до того как поправить heal(), который возвращал восстановленный рецепт без свежисего provenance, по которому реально кликает гарантия replay(); поэтому базовый инструмент, у которого переименовали контрл, причём действовал с большинством циклов and didn't get green in none. Именно это даёт большую часть 6/9. It was fixed in the code, and was not re-run on an equivalent window.
Партнёрские технологии
У каждой есть свой этап, и каждая деградирует, а не блокирует: весь pipeline пашет вообще без API-ключ, с reduced accuracy. Именно поэтому компилятор был in the assembled before any account appeared arrived — and it is also why an integration can be disconnected without the compile noticing; it is the status column and notes it.
Технология | Этап | Почему она заслуживает своего места | Статус |
OpenAI | Verify | Независимый вердикт о том, произошёл ли прогнозируемый эффект, поверх бесключевого diff-уровня. Может подтвердить отклонение, но никогда не отменить его | в использовании — она вынесла решение по единственному инструменту, который |
fal | Perceive | Быстрая VLM для оценки «значимое против косметического», подключается только когда DOM-diff неоднозначен | в использовании — 4/4 эскалированных шагов оценены при последней компиляции, 2 из них признаны косметическими. Только через CLI; |
Pioneer | Verify, Distil | Энкодер GLiNER2, дообученный на собственных verify-данных apic, заменяет судью GPT-4.1-mini — и превосходит его на отложенных инструментах (ниже). Также классификатор diff-текста в | в использовании — |
h | Explore | Читает страницу и называет действия записи, которые бесключевой словарь отказался распознавать | в использовании — запускается один раз на сид по остаткам; называет 0 из 3 на Vikunja, корректно |
Tavily | Ground | Документация приложения → доменный словарь, поэтому инструменты называются | в использовании — |
Двухуровневое разделение — это тезис самого продукта, применённый к нему же: fal — это дешёвый высокочастотный слой восприятия, OpenAI — дорогой низкочастотный слой рассуждений. Эскалируй при сбое, а не при каждом вызове.
Как каждая из них реально вызывается
h — holo3-1-35b-a3b, api.hcompany.ai/v1 (совместим с OpenAI).
gesture() сопоставляет видимый текст элемента управления с парой <глагол, ресурс>
через регулярные выражения и возвращает null для всего остального. Этот null — ворота точности,
и именно здесь теряется полнота: кнопка только с иконкой, элемент управления без ведущего
глагола или приложение, чью формулировку словарь не предвидел, отбрасывается, как бы явно
она ни была написана. h — это уровень эскалации именно для такого набора —
discover.js classify() отправляет JPEG страницы и
отклонённые элементы управления, один раз на сид, и спрашивает, какие из них выполняют запись.
Три вещи не дают этому стоить точности. Ответы проверяются по закрытому
словарю — шесть глаголов, четыре ресурса — через plan.gestureFrom(), поэтому
выдуманный глагол не может назвать инструмент. Элементы вне среза не предлагаются,
а удерживаются, потому что исключение ADD TO FAVORITES — это решение о границах,
а не пробел, который должна заполнять модель. И классифицированный элемент управления всё равно
должен заставить приложение подтвердить запись, как и любой другой кандидат.
Измерено на компиляции, о которой сообщает этот README: h читает три элемента управления, которые словарь оставляет нерешёнными на странице задач Vikunja, и называет один из них — элемент только с иконкой, который регулярные выражения отбрасывают полностью:
! h read 3 unresolved controls, named 1
! h: "Kanban bucket: To-Do" -> move task (Pencil icon allows changing task status)Это уровень эскалации, выполняющий свою работу: элемент управления без ведущего глагола и без полезного текста, восстановленный по иконке и сопоставленный с закрытым словарём.
Он не добавил инструмент, и мы не утверждаем, что добавил. move task
к тому моменту уже был найден дважды — один раз перетаскиванием на доске (Move card between columns), один раз выпадающим списком корзины на странице задачи (Kanban bucket: Doing) —
поэтому ответ h дедуплицировался в moveTask, который дало перетаскивание. На этой
цели h — это подтверждение, а не полнота: третий независимый путь к действию,
которого уже достигли два других пути. Более ранняя редакция этого файла утверждала, что h
никогда не срабатывал и ничего не называл; оба утверждения были неверны.
Добавляет ли h полноту — здесь не проверено, потому что записи Vikunja необычно хорошо подписаны. Случай, для которого он создан — приложение с кнопками-иконками — это ровно тот случай, которого эта цель не представляет. Без ключа компиляция теряет это подтверждение и ничего больше.
fal — google/gemini-2.5-flash-lite через fal-ai/any-llm/vision.
DOM-differ говорит, изменилась ли страница. Он не может оценить изменение,
которое текст не описывает — карточку, переместившуюся между колонками, элемент управления,
который просто подсветился. perceive.js adjudicate() эскалирует
эти шаги, и только их, к пикселям.
Измерено на последней полной компиляции: vision: 4/4 эскалированных шагов оценены fal, 1 перетаскивание подтверждено, 2 признаны косметическими. Два косметических вердикта —
самая интересная половина — fal удаляет кандидатов, которые иначе были бы
проверены как записи. Он запускается из cli.js; компиляция через compile_app
на MCP-сервере не эскалирует.
OpenAI — gpt-4.1-mini, структурированный вывод.
verify.js воспроизводит каждый выпущенный инструмент на холодную с аргументами,
которых приложение никогда не видело, и оценивает результат дважды: сначала детерминированный
diff-уровень, затем модель. Модель может подтвердить отклонение и никогда не отменить его —
инструмент, который diff не смог подтвердить, остаётся отклонённым, как бы уверен
ни был судья.
Измерено: на прогоне, где markTask не сработал, его запись гласит
openai/gpt-4.1-mini disagreed but cannot overturn a rejection. Эта асимметрия
намеренная: судья, который может продвигать собственные догадки, — это утечка точности.
Pioneer — GLiNER2 (fastino/gliner2-base-v1), один POST /inference на шаг.
distill.js отправляет diff-текст каждого шага отдельным
запросом и получает класс изменения состояния, флаг деструктивности и доменные
существительные при пороге уверенности выше 0.6. Раньше он отправлял всю траекторию пакетом,
и именно о пакетной обработке третий тяжёлый урок ниже: один и тот же текст получил
creation 0.777 в одиночку, creation 1.000 на позиции 0 и DELETION 0.600 на
позиции 2 перевёрнутого пакета — неверная метка, прошедшая порог. Идентификатор завершённого
тренировочного задания в PIONEER_MODEL заменяет базовый энкодер на чекпоинт, дообученный
на собственных метках apic — система, компилирующая собственный слой восприятия —
и больше ничего не меняется.
Pioneer — дообученный verify-судья. Это запись в побочном испытании Pioneer:
дообучить модель, которая превосходит или заменяет вызов универсального LLM API.
Вызов, который она заменяет, — это judgeModel() в
verify.js — GPT-4.1-mini, системный промпт на 200 слов,
структурированный вывод, один вопрос на каждый воспроизведённый инструмент: учитывая этот
DOM-diff, произошло ли прогнозируемое действие записи наглядно? Это двухклассовая
текстовая классификация, замаскированная под чат-завершение.
pioneer-train.js строит замену из собственных
выхлопов продукта, без ручной разметки:
collect — воспроизвести каждый скомпилированный инструмент шесть раз со свежими аргументами через
verifyAll(), записывая доказательства и вердикт, который дал штатный судья (diff-уровень + GPT). 54 реальных строки.dataset — получить негативы, удалив доказательства, на которые опирается уровень (баннер исчез, эхо переместилось в поле ввода, которое его набрало, аргумент не заполнен, воспроизведение выбросило ошибку, ничего не изменилось), и позитивы, сохраняющие метку (порядок узлов перевёрнут, добавлены несвязанные узлы, аргументы переименованы в значения, которые ввёл бы человек). Каждая производная строка переразмечается тем же детерминированным уровнем. 788 строк; отложены по инструментам, поэтому бенчмарк измеряет инструменты, которых энкодер никогда не видел.
upload / train —
POST /felix/datasets/upload/url→ presigned PUT →POST /felix/training-jobs,fastino/gliner2-base-v1, LoRA, 12 эпох. Обучается примерно за четыре минуты.bench — отложенные строки через обоих судей. LLM вызывается через неизменённый
judgeModel(), поэтому видит ровно то же, что и в продакшене.
судья | точность | precision | recall | ложные срабатывания | ложные пропуски | мс/строка |
Pioneer GLiNER2 fine-tune (задание | 94.4% | 100% | 87.6% | 0 | 12 | 150 |
OpenAI GPT-4.1-mini | 89.3% | 84.3% | 93.8% | 17 | 6 | 890 |
215 отложенных строк, два инструмента (createTask, assignLabel) отсутствуют в обучении.
Энкодер жертвует частью полноты ради нуля ложных срабатываний — правильный обмен
для этого судьи, который по замыслу может подтвердить отклонение, но никогда не продвинуть
догадку. Установите PIONEER_JUDGE_MODEL на идентификатор задания, и verify будет использовать его;
OpenAI остаётся в резерве как запасной вариант, а без ключей вовсе уровень всё равно работает.
Три урока, усвоенных на горьком опыте, все проверены вживую и записаны в коде:
multi_label/top_k внутри спецификации классификации заставляют единый
путь /inference возвращать categories: [] для любого текста (именно это, а не
кредиты, было причиной молчания этапа distil всё утро); GLiNER2 обучается только как LoRA —
training_type: "full" принимается и падает внутри Modal без единой строки в логе;
и пакетный вывод (text: [...]) на дообученной модели возвращает метки,
не совпадающие с входами, поэтому судья отправляет один текст на запрос.
Tavily — api.tavily.com/search, пять результатов, с ответом.
ground.js запускается перед первым сидом. plan.js поставляется
с существительными Vikunja — bucket, task, label, project — и при обращении к чему-либо
ещё gesture() получает вопросы о задачах и репозиториях от таблицы, которая
о них никогда не слышала, возвращает null, и элемент управления отбрасывается. Tavily получает
документацию самой цели; OpenAI структурирует этот текст в закрытый набор существительных
по строгой схеме; каждый термин проверяется на /^[a-z][a-z-]{1,18}$/,
ограничен 12 элементами и сливается во встроенную таблицу, а не заменяет её,
поэтому grounding может добавить словарь и никогда не может отнять словарь Vikunja. Кэшируется
по хосту в .apic/, так что повторная компиляция ничего не тратит, а демо не зависит
от wi-fi площадки.
Он деградирует в три шага — нет ключа Tavily, нет доказательств; нет ключа OpenAI,
доказательства нельзя структурировать; ничего не проходит валидацию — и каждый шаг
логируется и оставляет встроенную таблицу на месте. Как и fal, он запускается из cli.js:
compile_app на MCP-сервере использует встроенный словарь.
Таким образом, показатели полноты выше получены без ключей, с fal на эскалированных шагах восприятия и судьёй OpenAI на проходе verify. Это не демонстрация полного стека партнёров, и этот README не будет притворяться иначе.
Настройка
git clone https://github.com/brwbo/apic && cd apic
npm install && npx playwright install chromium
cp .env.example .env # fill in keys; .env is gitignored
npm run setup # starts the target app, checks every credentialЦелевое приложение (самохостимое, одноразовое — никогда не направляйте это на продукт третьей стороны):
docker volume create vikunja-files
docker run --rm -v vikunja-files:/data alpine sh -c "chown -R 1000:0 /data"
docker run -d --name vikunja -p 3456:3456 -v vikunja-files:/app/vikunja/files \
-e VIKUNJA_SERVICE_PUBLICURL=http://localhost:3456 \
-e VIKUNJA_DATABASE_PATH=/app/vikunja/files/vikunja.db \
-e VIKUNJA_RATELIMIT_ENABLED=false \
vikunja/vikunja:latestКоманда | Что делает |
| Какие учётные данные работают, какие цели доступны |
| Исследовать → синтезировать → выдать |
| Воспроизвести каждый инструмент на холодную; обслуживаются только выжившие |
| Непрерывная проверка с автоматическим восстановлением |
| Полнота и точность относительно реального API цели |
| Запустить сам apic как MCP-сервер — см. ниже |
Каждая команда читает одни и те же две переменные, поэтому весь запуск можно направить на альтернативный пакет, не трогая рабочий:
APIC_OUT_DIR=out/rescue APIC_APP=vikunja npm run verifyПеременная | По умолчанию | Значение |
|
| Где хранятся скомпилированные пакеты. |
|
| Какой пакет внутри него |
|
| Приложение, которое компилируется |
|
| Учётные данные для цели |
| обнаружен | Нужно только если форма входа не находится по пути в стиле |
|
| Страницы, с которых начинается исследование |
Семена и цель управляются окружением — ничто в компиляторе не знает маршрутов Vikunja:
APIC_APP=gitea TARGET_URL=http://localhost:3001 APIC_SEEDS=/repo/create,/issues npm run compileСгенерированный вывод
generated/vikunja/ — сервер, схемы и доказательства для каждого инструмента. Ничто в этом каталоге не было написано человеком.
Использование в качестве MCP-сервера
claude mcp add apic -- node /path/to/apic/src/server.jssrc/server.js начинается с одного инструмента, compile_app. Укажите ему URL, и он запустит конвейер в процессе, выдаст generated/<app>/, зарегистрирует скомпилированные инструменты на себе и отправит notifications/tools/list_changed — так что они вызываются по тому же соединению без перезапуска. С холодного старта:
[apic] ready - 0 compiled tools + compile_app
BEFORE compile, tools/list = [ 'compile_app' ]
compile_app returned in 22.1s
list_changed notification: YES
AFTER compile = [compile_app, createProject, createLabel, updateLabel, createTask]
createLabel -> {"ok":true,"effect":"creation","expected":"creation"}Компилятор, который требует перезапуска того, что он только что расширил, — это этап сборки. Тот, который не требует, — это живой компилятор. Заметки о совместимости с клиентами и полные стенограммы: docs/mcp-client.md.
Оба тупика получают ответ, а не сообщение
Клиент встречается с apic только в тот момент, когда чего-то не хватает, и оба этих момента раньше заканчивали разговор.
Несуществующий инструмент возвращает компиляцию, которая его создаст:
unknown tool: createIssue
No compiled tool exposes that action (compiled so far: vikunja). If the app has no API for it, make one:
compile_app { "url": "http://localhost:3456", "goal": "createIssue" }Инструмент, который приложение вытащило из-под ног, восстанавливается на пути вызова — watch лечит по таймеру, сервер лечит по требованию, через тот же heal(). Инструмент становится красным, компилятор заново исследует это одно действие, исправление записывается обратно в tools.json, и вызов повторяется до того, как вызывающий увидит сбой:
[apic] createLabel is red (no control matched "ADD LABEL (RENAMED)") - re-exploring to heal it
[apic] createLabel healed in 13.6s (click "…" -> "create label"; selectors re-resolved); retry passed
{ "ok": true, "effect": "creation", "healed": { "ms": 13589, "persisted": true } }Здоровый инструмент не затрагивается ничем из этого: тот же вызов, 4,4 с, без повторного исследования.
Связанные работы и чем это отличается
Проект | Что делает | Разница |
Автоматизация браузера как типизированные MCP-инструменты | Общие глаголы ( | |
Автоматически генерирует типизированные инструменты из входных схем Actor | Акторы написаны людьми — он генерирует обёртку из контракта, написанного человеком | |
URL + простой английский → структурированные данные | Возвращает данные, а не интерфейс, и перезапускает LLM при каждом вызове | |
URL/HAR/OpenAPI → CLI + MCP-сервер, с проверочными шлюзами | Перехватывает сетевой трафик — у приложения уже должен быть API. apic управляет интерфейсом | |
Спецификация OpenAPI → MCP-инструменты | Требует, чтобы API уже существовал | |
Агент генерирует и переиспользует MCP для каждой задачи | Генерирует инструменты, ища в интернете. apic выводит их, управляя программным обеспечением | |
Страницы объявляют свои собственные инструменты на JavaScript | Требует, чтобы разработчики приложения приняли его | |
Напишите навык, проверьте его, сохраните, переиспользуйте | Предок цикла «проверь, затем сохрани» |
Цикл не нов — ново то, откуда берётся возможность. Alita читает интернет, чтобы создавать инструменты; cli-printing-press читает сеть; Easy MCP читает спецификацию. apic читает приложение.
Что пока не работает
Сказано прямо, потому что компилятор, скрывающий свои режимы отказа, — не компилятор.
h находится в пути и ничего не даёт для этой цели. Он читает элементы управления, которые отказался обрабатывать словарь, и правильно не называет ни один из них, потому что срез доски Vikunja уже покрыт регулярными выражениями. Эскалация реальна и измерена; выигрыш здесь нулевой, и цель, чьи элементы управления являются иконками, а не глагольными фразами, — это случай, который это покажет.
compile_appвыполняет сокращённый конвейер.compile.js— это внутрипроцессная компиляция, которую вызывает MCP-сервер, и этоcli.jsминус пять вещей: обоснование (Tavily/OpenAI), обнаружение семян, специальный зонд страницы формы, семя деталей задачи и перетаскивание Kanban, а также уровень зрения fal —adjudicate()запускается только изcli.js. Он сохраняет обнаружение, персистентность, дистилляцию Pioneer, синтез и выдачу. Вот почему в приведённой выше стенограмме показано четыре инструмента, тогда какnpm run compileдаёт девять: демо живого компилятора и пакет из 9 инструментов — это два разных пути, и только CLI-путь описывается цифрами полноты.Pioneer выглядел недоступным всё утро — сначала
403 payment_method_required, а после нового ключаcategories: []при каждом вызове, что код воспринимал как «нет мнения» и переходил к эвристике. Второе было ошибкой формы запроса (multi_label/top_k), а не API. Каждая интеграция была написана так, чтобы деградировать молча, и каждая так и делала — деградация является предполагаемым поведением; не замечать её целое утро — нет.Тонко настроенный судья видел одно приложение. Его 788 обучающих строк — все из Vikunja. Отложенный сплит сделан по инструментам, а не по приложениям; стенд Gitea или ParaBank — следующий честный тест, и
collectпо второй цели — способ его получить.Вторая цель компилируется тонко. Gitea теперь компилируется от начала до конца —
createRepositoryиcreateIssue, оба проверены, 2/13 по срезу задач противswagger.v1.json. Для обнаружения не потребовалось изменений: два исправления были классом подтверждения (Gitea подтверждает запись, обслуживая результат по новому URL, несущему отправленное значение, а шлюз искал только баннеры и эхо тела) и переносом шаблонов URL контейнера/элемента изcli.jsв конфигурацию, где уже жилAPIC_SEEDS. Действия с метками и комментариями всё ещё пропускаются: они находятся за элементами управления, которые словарь не называет, иhне назвал ни одного из 14 переданных ему.8/18 полноты на Vikunja. Отсутствуют: создание корзин, комментарии, связи и вложения.
markTaskвыходит из строя примерно в одном запуске из двух (см. Результаты). Эффект реален и наблюдаем; подтверждает ли его что-либо, зависит от текущего состояния задачи. Любой живойnpm run verifyдолжен ожидаемо выводить 8/9 или 9/9.Параллельные запуски конфликтуют. Каждая команда использует одну сохранённую сессию в
.apic/session.json, поэтому компиляция и проверка, запущенные вместе, могут уничтожить контекст браузера друг друга в середине выполнения (Error setting storage state: Execution context was destroyed). Передайте отдельныйAPIC_SESSIONдля каждого запуска в качестве обходного пути; настоящее исправление — файл сессии для каждого запуска по умолчанию.Watch рассматривает каждый сбой как дрейф. Настоящей классификации «флейк против дрейфа» не существует. Три класса ложных срабатываний были исправлены вручную — ограничение скорости, истечение токена и упавшая страница — но общая проблема остаётся.
Семантическое изменение не обнаруживается и опасно. Если
deleteProjectначнёт архивировать вместо удаления, исцеление селектора — неправильный ответ. Проверка проверяет, что эффект произошёл, а не то, что это тот же эффект.Нет обратных действий, поэтому набор загрязняет собственный фикстур. Повторные запуски ухудшают цель, пока она не будет сброшена.
Аутентификация обходится стороной. Один вход, один пользователь, без областей разрешений — а это самая сложная часть проблемы в реальном корпоративном ПО.
Декларация о предыдущей работе
Написано с нуля на хакатоне. Никакого готового кода не приносилось; репозиторий был создан пустым утром мероприятия. Playwright, MCP SDK и клиенты OpenAI и fal — единственные зависимости.
Лицензия
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
- AlicenseCqualityAmaintenanceA production-grade MCP server that turns natural language intent into fully-architected, accessible, production-ready UI code through a 7-step agentic pipeline.201Apache 2.0
- FlicenseNot gradedqualityBmaintenanceAn extensible MCP server and generative UI engine for hosting interactive B2B enterprise workflows with dynamic styling and stateful simulators.
- FlicenseNot gradedqualityBmaintenanceThis MCP server renders UI design artifacts headlessly, runs deterministic linters, and manages stateful design review loops with an independent vision critic.
- FlicenseNot gradedqualityCmaintenanceA universal MCP server for registering internal, external, and OpenAPI-based APIs as MCP tools. It exposes them to MCP clients via Streamable HTTP and provides admin portal, RBAC/session auth, credential injection, and audit logging.
Related MCP Connectors
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Read-only MCP server for the WebAssembly spec: instructions, types, sections, search, proposals.
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/brwbo/apic'
If you have feedback or need assistance with the MCP directory API, please join our Discord server