Skip to main content
Glama
Shrey-Parikh31

rbac-rag-assistant

rbac-rag-assistant

Связано: drivescore-cloud, сервис на Go в Kubernetes с Terraform и журналом инцидентов.

Внутренний知识 ассистент для университета: сотрудники и студенты задают вопросы на обычном языке и получают ответы, основанные на политиках, которые им разрешено читать. Retrieval-augmented, tool-calling, role-aware и доступен через MCP, так что любой клиент может использовать те же инструменты по тем же правилам.

Это Layer 0 пятиуровневой системы. Уровни выше добавляют конвейер доставки, reliability engineering, оценку, тестирование безопасности и наблюдаемость, каждый поверх этого приложения, а не рядом с ним.

Запуск

Python 3.13. Обратите внимание: python на этой машине указывает на сборку msys2, в которой нет ни одного из этих пакетов, поэтому вызывайте интерпретатор venv напрямую.

py -3.13 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe test_rag.py
.\.venv\Scripts\python.exe test_tools.py

Обе команды выводят ok и не требуют API-ключа. Поиск и правила доступа можно тестировать офлайн — в этом и смысл того, чтобы держать их вне модели.

Задайте вопрос (требуется GEMINI_API_KEY):

.\.venv\Scripts\python.exe agent.py student "I have a 1.8 GPA, what happens?"
.\.venv\Scripts\python.exe agent.py staff "the wifi is down in the east wing, log it"

Только поиск, без ключа:

.\.venv\Scripts\python.exe rag.py admin "adjunct pay per credit hour"

Related MCP server: mcp-business-bot

Как это устроено

Файл

Что в его ведении

rag.py

Разбор, разбиение на чанки, TF-IDF индекс и фильтр допуска

tools.py

Три инструмента, их правила доступа и валидация аргументов

agent.py

Цикл вызова инструментов и единственный файл, который знает вендора модели

mcp_server.py

Те же инструменты через MCP. Никакой собственной реализации

docs/

Корпус. Во front matter у каждого документа указан его role

Три решения, которые стоит защищать

Роль вызывающего — не параметр инструмента. Она привязывается вне канала до начала хода. Если бы существовал search_docs(query, role), модель сама держала бы свой допуск, и предложение, спрятанное в найденном документе и говорящее «используй role=admin», стало бы путём эскалации. Передавать нечего — значит, нечего и выпросить.

Фильтр допуска работает на множестве кандидатов, а не на результатах. Чанк, который вызывающий не может видеть, никогда не попадает в ранжирование, поэтому о его существовании нельзя узнать ни по пробелу в результатах, ни по изменившейся оценке.

TF-IDF, а не эмбеддинги. Это базовый уровень, который Layer 3 существует, чтобы побить. Замена на семантический ретривер до появления golden set была бы гаданием; замена после него даёт число, оправдывающее изменение. Точка замены — Index.

MCP

mcp_server.py регистрирует функции из tools.py и больше ничего не добавляет — в этом и состоит аргумент в пользу MCP в одном файле: одна реализация, один набор правил доступа, много клиентов. Добавьте в конфиг клиента:

{
  "mcpServers": {
    "rbac-rag-assistant": {
      "command": "C:\\Users\\Shrey\\Documents\\CLAUDE CODE\\rbac-rag-assistant\\.venv\\Scripts\\python.exe",
      "args": ["C:\\Users\\Shrey\\Documents\\CLAUDE CODE\\rbac-rag-assistant\\mcp_server.py"],
      "env": { "KB_ROLE": "staff" }
    }
  }
}

У MCP-клиента нет понятия университетской роли, поэтому KB_ROLE читается один раз при запуске и применяется ко всему соединению. Роль принадлежит процессу сервера, а не диалогу — именно это не даёт модели выбирать её.

Поведение при отказе в доступе

Студенту, спрашивающему о материалах только для сотрудников, сообщается, что материал существует, но ему нужен допуск, а не что ничего нет (ADR-7). Проверено вживую:

Инструкции о том, что делать, если вы подозреваете, что ваш аккаунт взломан, есть в документации университета, но для доступа к ним требуется допуск сотрудника. Пожалуйста, обратитесь в офис, которому принадлежит эта политика.

Через границу проходит только классификационная метка и ничего больше. Ни фрагмента, ни заголовка, ни имени файла. На вопрос, который не покрывает ни один документ, даётся другой ответ — в этом весь смысл различия.

Что меня удивило

Первое. faculty compensation bands ничего не вернул администратору, а professor salary вернул тот же документ с оценкой 0.29. Эти три слова есть только в заголовке документа, а parse() выносит заголовок из тела в метаданные ещё до индексации. Пользователи ищут по заголовку документа гораздо чаще, чем по его формулировкам, поэтому самый естественный запрос к самому чувствительному документу был обречён на провал. Одна строка для исправления: индексировать title + text, хранить text.

Стоит записать из-за того, где это было найдено. Тесты контроля доступа проходили всё время, включая тест, утверждающий, что студент никогда не видит конфиденциальный контент, — и он был тривиально истинным, когда никому вообще не удавалось найти документ. Тест, проходящий потому, что ничего не вернулось, выглядит так же, как тест, проходящий потому, что правило работает.

Второе, найдено при реализации ADR-7. Уведомление «материал с ограниченным доступом существует» срабатывает на невинных вопросах. «Кто здесь полный профессор» набирает 0.28 по компенсационным диапазонам — это выше легитимного совпадения для сотрудника с 0.19. Никакой порог их не разделяет, так что это не настраивается; это лексическое сопоставление не умеет отличать общее слово от общего смысла. Ничего не утекает, но ответ всё равно неверный. Первое, что должен измерять Layer 3.

Третье. Модель заполняет небольшие пробелы, которые документы не покрывают. На вопрос о взломанном аккаунте она предложила обратиться «в IT Service Desk или в команду IT Security», хотя инструмент сказал только «в офис, которому принадлежит эта политика». Правдоподобно, здесь безвредно и не основано ни на чём из найденного. Это ровно то поведение, для поимки которого существует скоринг обоснованности, и оно появилось уже в первых пяти живых вопросах.

Окружение

Переменная

По умолчанию

GEMINI_API_KEY

Требуется только agent.py

KB_MODEL

gemini-3.6-flash

Закреплён, не алиас. ADR-8

KB_ROLE

student

Только MCP-сервер

KB_DOCS

docs

Каталог корпуса

KB_TICKETS

tickets.jsonl

Журнал тикетов

F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

0Releases (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 Connectors

Related MCP Servers

View all related MCP servers

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/Shrey-Parikh31/rbac-rag-assistant'

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