Skip to main content
Glama
TatooCollado

Agent Lab MCP Server

by TatooCollado

Agent Lab

CI Production Smoke

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

Статус

Этапы 1–11 — Фундамент, MCP, Agent Runtime, Auth/RBAC, A2A, оценки, облако, CI/CD, детерминированные контракты, отказоустойчивость и семантическая устойчивость:

  • фронтенд React + Vite;

  • бэкенд Node.js + Express;

  • схема и миграции PostgreSQL;

  • пользователи приложения admin и viewer;

  • детерминированные календарные периоды;

  • технический контракт TraceEvent;

  • модульные тесты и визуальная оболочка Agent Lab;

  • официальный MCP-сервер поверх транспорта stdio;

  • семь MCP-инструментов только для чтения со структурированными ответами;

  • параметризованные PostgreSQL-запросы через роль с минимальными привилегиями.

  • Ollama с qwen3:8b для локального вывода и tool calling без затрат на токены;

  • OpenAI Responses API сохранён как опциональный провайдер;

  • локальный MCP Client с обнаружением и выполнением инструментов;

  • grounded-оркестратор и конечная точка POST /api/agent/query;

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

  • аутентификация с непрозрачными сессиями, хранящимися в PostgreSQL;

  • cookie HttpOnly, SameSite=Strict и настраиваемый срок действия;

  • авторизация RBAC с профилями admin и viewer;

  • аудируемое создание пользователей и транзакционное удаление данных HR;

  • два агента, публикующие Agent Cards A2A 1.0;

  • делегирование HR → Finance через JSON-RPC SendMessage;

  • финансовая задача с жизненным циклом и структурированным Artifact;

  • отчёт о потерях из-за отсутствий, полученный через MCP.

  • набор поведенческих оценок с детерминированными assertions;

  • эталонные случаи, пустой результат и свежесть PostgreSQL;

  • изолированная динамическая фикстура с гарантированной очисткой и проверкой остатков.

  • бюджетный timeout, ограниченный транзиентный retry и circuit breaker для горячего экземпляра;

  • безопасная деградация, сохраняющая grounded answerPayload, если падает только нарратив;

  • оценка отказоустойчивости с контролируемой инъекцией сбоев.

  • интерпретация нейтрального, неформального и риоплатского испанского через семантическое предложение LLM;

  • серверная валидация capability, схемы, периода, полярности и лимитов до MCP;

  • типизированные решения о уточнении и неподдерживаемом запросе без доступа к PostgreSQL;

  • версионированный лингвистический бенчмарк с baseline before/after и стабильностью между повторными запусками.

Приложение развёрнуто со статическим фронтендом на Render, serverless-бэкендом на Vercel и PostgreSQL на Neon. GitHub Actions применяет quality gates и smoke-тесты против продакшена.

Related MCP server: Employee Management MCP Server

Структура

frontend/   React, inspector técnico y system index
backend/    API, dominio, migraciones, acceso PostgreSQL y trazas

Требования

  • Node.js 22 или выше.

  • npm 10 или выше.

  • Ollama 0.32 или выше и локальная модель qwen3:8b.

  • Облачный PostgreSQL с тремя отдельными учётными данными, если провайдер это позволяет.

Установка

npm --prefix backend install
npm --prefix frontend install

Скопируйте backend/.env.example в backend/.env и заполните URL-адреса провайдера PostgreSQL. Никогда не используйте владельческие учётные данные в DATABASE_READONLY_URL или DATABASE_ADMIN_URL.

Провайдер по умолчанию — локальный Ollama:

LLM_PROVIDER=ollama
OLLAMA_HOST=http://127.0.0.1:11434
OLLAMA_MODEL=qwen3:8b

Установите Ollama и один раз загрузите модель командой ollama pull qwen3:8b. Вывод использует локальные CPU/GPU и хранилище, без затрат на платный API.

OpenAI по-прежнему доступен как альтернатива: настройте LLM_PROVIDER=openai, OPENAI_API_KEY и OPENAI_MODEL. Ключ принадлежит только backend/.env, который игнорируется Git. Его никогда нельзя отправлять на фронтенд или включать в трассы.

База данных

  1. Создайте базу PostgreSQL у облачного провайдера.

  2. Создайте или настройте роли по backend/ops/database-roles.example.sql.

  3. Настройте переменные окружения.

  4. Выполните:

npm --prefix backend run db:migrate
npm --prefix backend run db:seed
npm --prefix backend run db:smoke
npm --prefix backend run db:verify-permissions

db:smoke использует исключительно DATABASE_READONLY_URL и запрашивает представление hr_late_arrivals с параметрами дат.

Seed требует SEED_ADMIN_PASSWORD и SEED_VIEWER_PASSWORD, обе — не менее 12 символов. В репозитории нет паролей по умолчанию.

Разработка

В двух терминалах:

npm run dev:backend
npm run dev:frontend
  • Фронтенд: http://localhost:5173

  • Бэкенд: http://localhost:3000

Проверка без облачной базы

npm test
npm run typecheck
npm run build

Тесты календаря проверяют:

  • текущий месяц с 1-го числа по сегодняшний день включительно;

  • полный предыдущий календарный месяц;

  • февраль високосного года;

  • последние 30 календарных дней.

Временные интервалы

Интерфейс говорит об инклюзивных датах, но внутри используются полуоткрытые интервалы:

startInclusive <= timestamp < endExclusive

Это позволяет не зависеть от 23:59:59 и корректно сохраняет точность PostgreSQL.

Трассируемость

Фронтенд показывает технические события с:

  • названием события;

  • технологией;

  • компонентом;

  • категорией;

  • концепциями;

  • санитизированными входом и выходом;

  • длительностью и статусом.

Учётные данные, токены сессий и внутренние рассуждения модели не отображаются.

MCP Server

Сервер использует официальный SDK Model Context Protocol для предоставления:

  • count_employees: подсчитывает общее количество сотрудников, активных и неактивных;

  • list_employees: выводит полный справочник с табельным номером, именем, отделом и статусом;

  • find_employee: ищет по имени или номеру сотрудника;

  • summarize_employee_delays: агрегирует исторические опоздания человека по имени или табельному номеру;

  • list_late_arrivals: выводит опоздания за период и по опциональному сотруднику;

  • list_employees_without_late_arrivals: вычисляет в PostgreSQL, какие активные сотрудники не имели опозданий за период;

  • list_absences: выводит отсутствия за период и по опциональному сотруднику.

Инструменты объявляют readOnlyHint, валидируют вход и выход с помощью Zod и возвращают как текстовое содержимое, так и structuredContent. Результаты включают источник, дату запроса, применённый период, общее количество и признак усечения. Каждый вызов заново обращается к PostgreSQL; на этом этапе кэша нет.

Для запуска локального MCP-сервера:

npm run mcp:server

Для проверки обнаружения, реальных вызовов, посеянных данных и пустого результата:

npm run mcp:smoke

stdout зарезервирован под протокол MCP; операционные ошибки отправляются в stderr, а ответ клиенту санитизируется.

Agent Runtime

Реализованный поток:

React → POST /api/agent/query → HrAgentOrchestrator
      → Ollama local + qwen3:8b (tool calling)
      → MCP Client → MCP Server → PostgreSQL
      → tool result → Ollama → respuesta + TraceEvent[]

MCP Client обнаруживает доступные инструменты, но роутер передаёт модели единственное определение allowlist, управляемой исполнением. Схемы function calling строгие, а параллельные вызовы отключены, чтобы каждое выполнение было легко инспектировать.

grounded: true означает, что оркестратор проверил вызов одобренного инструмента и получил structuredContent перед запросом финального ответа. Это не означает математической гарантии по каждому токену, произведённому моделью; это качество должно измеряться оценками.

System prompt требует, чтобы корпоративные данные поступали исключительно из инструментов, чтобы пустые результаты сообщались явно, а полученное содержимое трактовалось как данные, а не как инструкции.

Детерминированный интеграционный тест без потребления API:

npm run agent:smoke

Реальный тест с локальным Ollama, MCP и Neon:

npm run agent:smoke:ollama

Реальный тест с Groq, MCP и Neon:

npm run agent:smoke:groq

Опциональный тест с OpenAI, MCP и Neon:

npm run agent:smoke:openai

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

POST /api/agent/query
Content-Type: application/json

{"question":"¿Qué empleados llegaron tarde durante el último mes?"}

Ответ содержит answer, model, grounded, toolsUsed и последовательность санитизированных технических событий. Он не включает токены, учётные данные или внутренние рассуждения.

Семантическая устойчивость, валидированная маршрутизация и детерминированное представление

LLM получает семь управляемых capabilities и предлагает ровно одно решение. Бэкенд не доверяет этому предложению: он валидирует allowlist, схему Zod, выраженный пользователем период, полярность и бизнес-лимиты перед разрешением MCP-вызова:

LLM propone → backend valida → MCP ejecuta → PostgreSQL → payload determinista

Capability

Инструмент

подсчёт сотрудников

count_employees

вывод справочника

list_employees

поиск человека

find_employee

сводка исторических опозданий

summarize_employee_delays

запрос опозданий за период

list_late_arrivals

запрос тех, у кого не было опозданий

list_employees_without_late_arrivals

запрос отсутствий за период

list_absences

Помимо семи MCP-инструментов, планировщик имеет два внутренних решения, которые никогда не доходят до MCP: request_clarification и reject_unsupported_query. Первое возвращает agent_clarification_required, когда отсутствует период или есть неоднозначность; второе возвращает unsupported_agent_query, когда запрос требует несуществующей capability, ранжирования, частоты или фильтра. Публичный каталог доступен через GET /api/agent/capabilities и также присутствует в System index.

Неформальные выражения интерпретируются по смыслу. Например, llegar, entrar, caer, fichar или marcar tarde могут относиться к late_arrivals; «sin tardanzas» и «siempre puntual» интерпретируются как ноль событий только в пределах явного периода. Выражения вроде «banda», «una bocha», «siempre» или «seguido» никогда не превращаются в выдуманные количества.

После выполнения MCP AnswerPresentation валидирует structuredContent через дискриминируемое объединение Zod. API возвращает две отдельные поверхности:

  • presentation: типизированный, детерминированный answerPayload, отображаемый конкретным React-компонентом;

  • answer: grounded-нарратив, сгенерированный LLM, видимый на вторичной панели, помеченной как недетерминированный.

Количества, таблицы, даты, пустые состояния и метаданные источника отображаются из presentation; они не извлекаются из текста модели. Этап 11 не изменяет этот контракт Этапа 9. Трасса включает llm.semantic_proposal.completed, agent.semantic_decision.validated и presentation.payload.validated для разделения предложения, валидации и детерминированного представления.

Отрицательный запрос реализуется как разность множеств: активные сотрудники минус сотрудники хотя бы с одним опозданием в пределах периода. PostgreSQL выполняет эту семантику через NOT EXISTS; LLM не вычисляет дополнение. Если Groq возвращает пустой финальный ответ или пытается выполнить второй tool call во время завершения, адаптер выполняет единственный текстовый повтор с теми же grounded-данными. Событие llm.grounded_response.completed сообщает recovery=not_required, тип применённого retry или откат к детерминированному представлению.

Отказоустойчивость LLM-провайдера

Этап 10 обрабатывает внешние сбои с помощью четырёх явных механизмов:

Техника

Политика демонстрации

Результат

timeout budget

12 секунд на попытку

прерывает вызов, превышающий бюджет

bounded retry

1 транзиентный повтор

повторяет 429, таймаут, сеть или 5xx; не повторяет функциональные ошибки

circuit breaker

размыкается при 3 сбоях; пробный half-open через 30 секунд

позволяет не давить на провайдера, который остаётся недоступным

graceful degradation

только после успешного MCP-запроса

сохраняет presentation grounded, даже если LLM-нарратив отсутствует

Публичный эндпоинт GET /api/resilience раскрывает политику и санитизированное состояние контура, но никогда — учётные данные. Агент переиспользуется внутри каждого горячего инстанса, чтобы circuit breaker сохранял состояние между запросами. В Vercel каждый инстанс имеет собственный контур; глобальная координация потребовала бы распределённого хранилища и не оправдана для этой лаборатории.

Если падает начальное планирование, MCP-вызова и grounded-данных ещё нет, и API возвращает типизированную ошибку (llm_timeout, llm_rate_limited, llm_provider_unavailable или llm_circuit_open). Если падает только финальная формулировка, API отвечает успешно с детерминированной таблицей и выдаёт llm.grounded_response.degraded.

Аутентификация и авторизация

Учётные данные проверяются по bcrypt-хешам в app_users. При аутентификации бэкенд создаёт случайный токен, сохраняет только его SHA-256-хеш в app_sessions и передаёт токен через cookie HttpOnly. Фронтенд никогда не обращается к токену.

Длительность настраивается через SESSION_TTL_HOURS=8.

Права приложения:

  • viewer: может обращаться к агенту и просматривать технический индекс;

  • admin: включает возможности запросов, создание пользователей и контролируемое удаление операционных данных.

Административное удаление не выполняет DROP DATABASE. Оно удаляет attendance_records, employees и departments в рамках одной транзакции; сохраняет схему, пользователей, сессии и audit_events. Требуется буквальное подтверждение DELETE HR DATA, результат фиксируется в аудите.

Роль PostgreSQL app_admin не имеет DROP, CREATE DATABASE, суперпользователя или членства neon_superuser. Это разделение демонстрирует, что RBAC приложения и привилегии базы данных — разные слои.

Реальный тест обоих пользователей и полного цикла сессии:

npm run auth:smoke

Агенты и A2A

Проект реализует A2A Protocol 1.0 с официальным SDK @a2a-js/sdk:

  • HR Grounding Agent: запросы сотрудников и посещаемости, grounded через MCP;

  • Absence Finance Agent: детерминированный экономический анализ отсутствий.

Agent Cards:

/.well-known/agent-card.json
/.well-known/hr-agent-card.json
/.well-known/finance-agent-card.json

Финансовый поток:

Usuario → HR Agent / A2A Client
        → descubre Finance Agent Card
        → JSON-RPC SendMessage
        → Finance Agent Task: submitted → working
        → MCP list_absences → PostgreSQL
        → calculadora determinista
        → A2A Artifact application/json
        → Task completed → reporte + TraceEvent[]

Эндпоинты A2A используют внутренний случайный bearer-токен. Agent Card описывает схему безопасности, но никогда не содержит учётных данных.

В базе нет зарплат. Поэтому отчёт требует явных параметров: валюта, дневная стоимость, премия за замену и влияние на производительность. Формула:

días × costo diario × (1 + prima de reemplazo + impacto de productividad)

LLM не выполняет арифметику. Детерминированная TypeScript-функция вычисляет суммы с округлением до двух знаков. Если MCP сообщает, что результат был усечён, агент отклоняет расчёт, чтобы не выдать неполный отчёт.

Реализация использует A2A-задачи в памяти, потому что поток короткий и синхронный. Для нескольких инстансов или длинных задач TaskStore придётся перенести в постоянное хранилище.

Реальный тест Agent Card, A2A, MCP и Neon:

npm run a2a:smoke

Оценки агента

Юнит-тесты проверяют функции и контракты с контролируемыми зависимостями. Набор оценок измеряет полное поведение реального агента с настроенной моделью, MCP и PostgreSQL.

Реализованные случаи:

  • employee-count: проверяет, что вопрос о количестве направляется исключительно в count_employees;

  • employee-directory: проверяет, что запрос имён направляется в list_employees и получает справочник;

  • employee-delay-summary: проверяет детерминированную агрегацию задержек Bruno Silva через summarize_employee_delays;

  • employees-without-late-arrivals: проверяет маршрутизацию отрицания, разность множеств и ожидаемый результат EMP-003;

  • known-late-arrivals: сравнивает инструмент, grounding и количество с посеянным набором данных;

  • unknown-employee: требует пустого результата PostgreSQL и явного ответа без выдуманных данных;

  • source-of-truth-freshness: вставляет временного уникального сотрудника и опоздание, запрашивает только что созданную запись и проверяет, что агент видит обновление.

  • finalization-failure-degradation: внедряет контролируемый сбой после MCP и проверяет, что PostgreSQL-полезная нагрузка остаётся доступной.

  • semantic-robustness-v1: выполняет 80 нейтральных, формальных, неформальных, риоплатенских и пограничных формулировок; измеряет намерение, решение, аргументы, темпоральность, неоднозначность и стабильность.

Динамическая фикстура использует административную роль только во время подготовки и очистки. Запрос агента продолжает использовать роль только для чтения. Блок finally удаляет по UUID и точному номеру сотрудника; в конце дополнительный запрос требует, чтобы не осталось сотрудников EVAL-% или посещений с источником agent-evaluation.

Реальный запуск с настроенным LLM-провайдером, MCP и Neon:

npm run evals:run
npm run resilience:eval
npm run semantic:eval
npm run semantic:stability

semantic:eval один раз проходит 80 случаев, а semantic:stability повторяет критический набор пять раз. Оба сообщают validDecisionRate, intentRecognitionRate, toolSelectionRate, argumentExtractionRate, temporalInterpretationRate, exactOutcomeRate, stabilityRate, ambiguityPassRate и unsupportedPassRate. По умолчанию они ждут 30 секунд между вызовами, чтобы уважать бесплатный бюджет токенов Groq и отделять лимиты провайдера от семантической нестабильности. Базовый уровень Stage 10 сохраняется в backend/evals/baselines/, а результаты Stage 11 — в backend/evals/results/.

Остальные команды возвращают воспроизводимый JSON с passRate, длительностью, ожидаемыми/фактическими проверками и grounded-доказательствами по каждому случаю. Они завершаются ненулевым кодом, если оценка не удалась или осталась временная фикстура. Эталонный случай предполагает наличие демонстрационного сида.

Облачное развёртывание

Репозиторий хранит frontend/ и backend/ отдельно, с двумя поверхностями развёртывания:

  • agent-lab-ignac: фронтенд Vite как Render Static Site;

  • agent-lab-api-ignac: бэкенд Express как Vercel Function с Fluid Compute.

Продакшн-URL:

  • приложение: https://agent-lab-ignac.onrender.com;

  • API: https://agent-lab-api-ignac.vercel.app;

  • прямой health check: https://agent-lab-api-ignac.vercel.app/api/health.

render.yaml управляет только фронтендом и переписывает /api/* на https://agent-lab-api-ignac.vercel.app. Для браузера аутентификация и cookie остаются под origin фронтенда; токен сессии остаётся HttpOnly и не передаётся в React.

backend/vercel.json объявляет Express, максимум 300 секунд и регион gru1 (Сан-Паулу), близкий к базе Neon. Vercel обнаруживает ленивый handler, экспортируемый из src/app.ts; приложение и его пулы инициализируются при первом запросе к инстансу. src/server.ts сохраняет app.listen() для локальной разработки.

Транспорт MCP выбирается через MCP_TRANSPORT:

  • stdio: локальная разработка; клиент запускает отдельный MCP-процесс;

  • in_process: Vercel; клиент и сервер MCP соединяются парой транспортов в памяти, не теряя протокол, контракты, валидацию или обнаружение инструментов.

В локальной разработке LLM_PROVIDER=ollama сохраняет qwen3:8b. В Vercel LLM_PROVIDER=groq использует openai/gpt-oss-20b, поддерживающий function calling. Адаптер Groq принудительно включает хотя бы один инструмент и возвращает его результат модели для создания grounded-ответа.

Требуемые переменные продакшена в проекте Vercel:

NODE_ENV=production
FRONTEND_ORIGIN=https://agent-lab-ignac.onrender.com
APP_TIMEZONE=America/Argentina/Buenos_Aires
SESSION_TTL_HOURS=8
PUBLIC_BASE_URL=https://agent-lab-api-ignac.vercel.app
MCP_TRANSPORT=in_process
LLM_PROVIDER=groq
GROQ_MODEL=openai/gpt-oss-20b
GROQ_API_KEY=<secret>
LLM_TIMEOUT_MS=12000
LLM_TRANSIENT_RETRIES=1
LLM_CIRCUIT_FAILURE_THRESHOLD=3
LLM_CIRCUIT_RESET_MS=30000
DATABASE_READONLY_URL=<secret>
DATABASE_ADMIN_URL=<secret>
A2A_INTERNAL_TOKEN=<secret-aleatorio-de-32-o-mas-caracteres>

Публичный бэкенд добавляет заголовки через Helmet, rate limits, явную обработку ошибок и GET /api/health. Лимиты в памяти демонстрационные и работают на горячий инстанс; распределённое продакшн-приложение использовало бы общее хранилище. PostgreSQL сохраняет пользователей, сессии и данные, поэтому serverless-файловая система остаётся одноразовой.

CI/CD и quality gates

Каждый push в main и каждый pull request запускают .github/workflows/ci.yml. Бэкенд и фронтенд проверяются в независимых и воспроизводимых jobs на Node.js 22:

checkout → npm ci → typecheck → build → tests → audit de dependencias productivas

npm ci устанавливает ровно дерево, зафиксированное каждым package-lock.json. Jobs имеют только права на чтение репозитория, имеют таймаут и отменяют предыдущие запуски той же ветки. Никакие продакшен-учётные данные не передаются в CI workflow.

Vercel подключён к репозиторию с backend/ как Root Directory; принятый коммит в main запускает serverless-развёртывание. Render поддерживает статический фронтенд из frontend/. Это разделение различает два контроля:

  • quality gate до рантайма: типы, компиляция, тесты и аудит;

  • smoke test после развёртывания: публичный HTTP-контракт, реально развёрнутый.

.github/workflows/production-smoke.yml слушает успешные статусы развёртывания и также позволяет ручной запуск. scripts/production-smoke.mjs проверяет:

  • прямой health бэкенда Vercel;

  • контракт /api/system и текущий этап;

  • публичный контракт /api/resilience;

  • прокси /api/*, обслуживаемый под origin Render;

  • доступность HTML-документа фронтенда.

Локальный запуск того же продакшен-контракта:

node scripts/production-smoke.mjs
F
license - not found
Not graded
quality - not tested
B
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

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with a PostgreSQL database through MCP tools for employee management. Supports listing and adding employees via natural language chat interface with LLM integration.
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables managing employee records by providing tools to list directories, retrieve detailed profiles, and search for staff by department. It integrates with Claude Desktop to allow users to interact with employee data through natural language commands.
    MIT
  • A
    license
    B
    quality
    C
    maintenance
    Enables Claude, Cursor, and other MCP clients to query PeopleForce HRIS data (employees, time-off, recruitment) via 27 read-only tools.
    28
    3
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to query a PostgreSQL database through a small set of controlled, read-only tools for schema inspection, row lookup, and aggregate statistics.
    1
    MIT

View all related MCP servers

Related MCP Connectors

  • Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.

  • Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.

  • See, price, and control every tool call your AI agents make: policy checks, cost, and audit tools.

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/TatooCollado/agent-lab'

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