fes-mcp
Sisense Meta-Management MCP Server
⚠️ Уведомление об экспериментальном проекте
Инструмент, созданный сообществом, от инженерного отдела Sisense Field Engineering
Этот проект — экспериментальный инструмент, разработанный инженерным отделом Sisense Field Engineering для облегчения изучения и исследования возможностей Sisense клиентами. Он не является частью основного жизненного цикла выпуска продукта Sisense и не проходит те же процессы валидации, поддержки или сертификации, что и общедоступные (GA) функции Sisense. Он предоставляется «как есть» — см. Поддержка и вклад.
Сервер MCP, соответствующий стандартам, который предоставляет операции с окружением Sisense как инструменты, готовые для ИИ, на основе SDK PySisense: управление, управление активами и пользователями/группами, задачи жизненного цикла и проверки работоспособности — не создание дашбордов или аналитические Q&A.
Он работает для любого пользователя Sisense: каждый вызов инструмента выполняется с собственными учетными данными вызывающего пользователя в Sisense, поэтому результаты и разрешения точно соответствуют тому, что этот пользователь может видеть и делать в самом Sisense, что обеспечивается нативно API Sisense.
Только инструменты, без агента. Claude Desktop, Claude Code, claude.ai, Cursor — любой MCP-клиент приносит своего собственного агента; этот проект предоставляет и выполняет ~100 подобранных инструментов (дашборды, модели данных, пользователи/группы, папки, плагины, проверки работоспособности, …).
Архитектура
Современная форма спецификации MCP — два взаимодействующих сервиса,
поставляемых как два Docker-образа (fes-auth, fes-mcp — собранные из
одного многоступенчатого Dockerfile с общими слоями):
fes-auth — сервер авторизации (AS). Владеет всем, что касается кто вызывает: OAuth 2.1 для MCP-клиентов (PKCE, динамическая регистрация клиентов, обнаружение), страница входа в браузере и хранилище учетных данных, сопоставляющее каждый выданный MCP-токен с токеном Sisense пользователя. Он проксирует каждый вызов инструмента на сервер ресурсов с внедренными учетными данными Sisense.
fes-mcp — сервер ресурсов (RS). Не имеет состояния, не знает об OAuth. Читает внедренные учетные данные из каждого запроса, проверяет их против Sisense (с кэшированием) и выполняет инструмент от имени этого пользователя против этого экземпляра Sisense.
flowchart LR
subgraph clients [MCP clients]
C1[Claude Desktop]
C2[Claude Code]
C3[claude.ai / Cursor]
end
subgraph box [one host - docker compose]
subgraph AS [fes-auth : authorization server]
O[OAuth 2.1\nPKCE + DCR + discovery]
L[/login page/]
V[(vault\nMCP token → Sisense credential)]
P[/mcp proxy\ninjects credential headers/]
end
subgraph RS [fes-mcp : resource server]
T[Tool layer\nregistry-driven, ~100 tools]
D[Dispatcher\nper-credential PySisense client]
end
end
R[(tool registry JSON\nauto-generated from SDK)] -.defines.-> T
C1 & C2 & C3 -- "MCP over HTTPS\nBearer <MCP token>" --> P
C1 & C2 & C3 -. "browser: sign in once" .-> L
P -- "Authorization: Bearer <Sisense token>\nX-Sisense-Url: <instance>\n(internal network only)" --> T
T --> D
D -- "REST, as the signed-in user" --> F[(Sisense Fusion Deployment)]Стык между двумя сервисами — это просто эти два заголовка плюс контракт 401, поэтому каждая половина может развиваться — или быть заменена — без ведома другой. Между ними намеренно нет общего секрета — доверие обеспечивается внутренней сетью (порт RS никогда не публикуется).
Процесс входа (что испытывает пользователь)
Каждый пользователь добавляет коннектор один раз в своем MCP-клиенте, указывая свой собственный экземпляр Sisense в URL:
https://your-host/mcp?target=https://acme.sisense.comsequenceDiagram
participant U as User (browser)
participant C as MCP client
participant A as fes-auth
participant S as Sisense
C->>A: POST /mcp?target=<sisense url> (no token)
A-->>C: 401 + resource metadata URL (carries target)
C->>A: discovery + client registration (RFC 7591)
C->>U: open browser at A's /login
Note over U,A: target present → instance fixed,<br/>only username/password asked<br/>(no target → domain field shown)
U->>A: username/password (or API token for SSO)
A->>S: POST /api/v1/authentication/login
S-->>A: user's Sisense token (kept server-side, in the vault)
A-->>C: authorization code → MCP access token (PKCE)
Note over C,A: from here, silent — token refresh is automaticКлиент никогда не видит учетные данные Sisense; сервер никогда не хранит пароли (используются один раз для выпуска токена пользователя, затем отбрасываются). Пользователи на экземплярах с SSO/MFA входят, вставляя вместо этого свой личный API-токен Sisense.
Вызов инструмента (установившийся режим)
sequenceDiagram
participant C as MCP client
participant A as fes-auth (proxy)
participant R as fes-mcp (tools)
participant S as Sisense (target)
C->>A: POST /mcp (Bearer <MCP token>)
A->>A: validate token → vault → Sisense credential
A->>R: same request + Authorization: Bearer <Sisense token><br/>+ X-Sisense-Url: <instance>
R->>S: verify credential (TTL-cached) · SDK call as that user
S-->>R: result (user's permissions, user in audit log)
R-->>A: MCP response (streamed)
A-->>C: MCP response (streamed)Жизненный цикл учетных данных и самовосстановление
Сервер ресурсов повторно проверяет каждую пару (экземпляр, токен) против Sisense через
FES_MCP_VERIFY_TTLсекунд (по умолчанию 300). Токен, отозванный в Sisense, превращается в HTTP 401 в течение максимум этого окна.fes-auth рассматривает 401 от RS как мертвые учетные данные: он удаляет запись из хранилища и повторно запрашивает MCP-клиента, чей следующий шаг — повторный запуск процесса входа. Таким образом, отзыв на стороне сервера распространяется без ручных действий.
Сеансы по замыслу хранятся в памяти (без базы данных): перезапуск fes-auth выводит всех пользователей — следующий вызов каждого пользователя снова открывает вход в браузере (с
?target=, это просто имя пользователя/ пароль). Перезапуск fes-mcp незаметен: он не хранит состояние.
Related MCP server: Dynamics 365 Business Central Admin MCP Server
Развертывание (docker compose)
docker compose up --buildЭто собирает два образа (docker build --target fes-auth|fes-mcp) и
публикует только fes-auth на :8200; fes-mcp остается внутренним. Завершите
TLS на фронте (ALB / nginx / Caddy) — MCP-клиенты требуют HTTPS для OAuth —
и установите FES_MCP_PUBLIC_URL на этот публичный URL:
FES_MCP_PUBLIC_URL=https://your-host.example.com docker compose up -d --buildЗатем пользователи добавляют https://your-host.example.com/mcp?target=https://their-instance.sisense.com
как пользовательский коннектор. Часть ?target= необязательна — без нее на
странице входа запрашивается URL Sisense как третье поле.
Конечные точки на fes-auth: /mcp (проксируемый MCP), /login,
/.well-known/* + /authorize + /token + /register (OAuth 2.1), /
(статус), /healthz. Включено усиление защиты: ограничение скорости входа по
IP, защищенная от CSRF форма входа, журналы доступа с идентификаторами запросов.
Быстрый старт (локальная разработка)
Требуется Python 3.11+ и uv. Локальная разработка
полностью пропускает AS: транспорт stdio по умолчанию использует аутентификацию
env — одни учетные данные из .env, все выполняется от вашего имени.
uv sync
cp .env.example .env # set SISENSE_DOMAIN / SISENSE_TOKEN
uv run fes-mcp # stdio transportКонфигурация MCP-клиента (например, claude_desktop_config.json):
{
"mcpServers": {
"sisense": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/fes_mcp", "fes-mcp"]
}
}
}Чтобы запустить полное разделение локально без Docker:
FES_MCP_TRANSPORT=http uv run fes-mcp & # RS on :8200 (upstream auth)
FES_MCP_PORT=8300 FES_MCP_RS_URL=http://127.0.0.1:8200 uv run fes-auth
# connector: http://127.0.0.1:8300/mcp?target=https://your.sisense.comСтруктура
src/fes_mcp/—settings(конфигурация env) ·registry(загрузка/ фильтрация) ·dispatcher(диспетчеризация SDK по учетным данным) ·upstream(проверка учетных данных RS) ·auth(OAuth-провайдер + страница входа) ·authserver(сервис fes-auth + прокси) ·middleware(журналы доступа) ·server(сборка FastMCP)config/tools.registry.with_examples.json— автоматически сгенерированный реестр инструментов. Никогда не пишется вручную; перегенерируйте с помощью./refresh_registry.shпри обновлении PySisense.config/allowlist.txt— подобранная поверхность инструментов, по одному инструменту на строку. Удалите/закомментируйте строку, чтобы удалить инструмент. Инструменты, не перечисленные в списке, никогда не предоставляются, поэтому обновления реестра не могут незаметно расширить поверхность. (Инструменты миграции намеренно не перечислены — им нужно двухэкземплярное соединение, которое этот сервер не моделирует.)Изменяющие инструменты ограничены
FES_MCP_ALLOW_MUTATIONS=true— см. Безопасность для полных мер защиты от изменений.
Технические и соображения безопасности
Обработка учетных данных
MCP-клиент никогда не видит учетные данные Sisense, и сервер никогда не хранит
пароли — пароль используется один раз против API входа Sisense для выпуска
собственного токена пользователя, затем отбрасывается. Токены Sisense хранятся
в хранилище в памяти fes-auth, привязанном к MCP-токену доступа, и переживают
ротацию обновления. В режиме разработки единственные учетные данные из env
(SISENSE_DOMAIN/SISENSE_TOKEN) остаются на вашей машине. Ничего не
сохраняется на диск: перезапуск fes-auth стирает хранилище (все входят заново)
— это осознанный компромисс ради отсутствия базы данных и поверхности
шифрования в состоянии покоя.
Усиление защиты на размещенной поверхности: ограничение скорости входа по IP, защищенная от CSRF форма входа, журналы доступа с идентификаторами запросов и поинструментальные журналы (инструмент / домен пользователя / результат / длительность).
Авторизация
Ничего кастомного: авторизация — это работа Sisense. Каждый вызов инструмента выполняется с собственным токеном Sisense вызывающего пользователя, поэтому Sisense применяет их реальные разрешения к каждому вызову API, и ошибки разрешений передаются клиенту дословно. Это также причина, почему сервер не только для администраторов — любой пользователь Sisense получает ровно свою собственную область.
Доверие между двумя сервисами
Доверие fes-auth ↔ fes-mcp — на уровне сети: без общего секрета. Порт RS
никогда не должен быть доступен извне внутренней сети (compose публикует
только fes-auth). Глубина защиты: FES_MCP_ALLOWED_SISENSE_ORIGINS закрепляет,
какие источники Sisense RS будет принимать в X-Sisense-Url.
Изменения
Изменяющие инструменты предоставляются только при
FES_MCP_ALLOW_MUTATIONS=true, всегда несут destructiveHint, блокируются на
стороне сервера как второй уровень при отключении и записываются в журнал
аудита изменений.
Кроме того, изменяющие инструменты запрашивают у человека одобрение перед
выполнением — через элиситацию MCP, на клиентах, объявляющих эту возможность
(Claude Code, Cursor, VS Code). Диалог «продолжить/прервать» открывается
посреди вызова, раскрывая точные аргументы; прерывание или отклонение ничего
не меняет. На клиентах без элиситации (Claude Desktop, claude.ai) вызов
выполняется обычным образом, и собственный процесс одобрения инструментов
клиента плюс аннотация destructiveHint являются защитой, как для любого
MCP-сервера.
Продолжение без диалога — осознанное решение (fail-open), а не упущение: элиситация — это необязательная возможность клиента, и ее может автоматически ответить неисправный клиент, поэтому она рассматривается строго как UX — граница авторизации всегда является собственными разрешениями пользователя в Sisense.
Поток данных к LLM-провайдеру
Этот сервер не имеет уровня суммаризации или редактирования данных: каждый
результат инструмента — полные строки, а не метаданные {ok, count} —
возвращается MCP-клиенту и попадает в контекст модели. Это сделано намеренно
и именно это обеспечивает работу многошаговых цепочек инструментов: модель
может рассуждать, фильтровать и передавать вывод одного инструмента в
следующий вызов, только если она действительно видит данные.
Следствие: тот, кто подключает этот сервер к MCP-клиенту, принимает, что данные Sisense (содержимое дашбордов, результаты запросов, списки пользователей, …) передаются LLM-провайдеру этого клиента — например, Anthropic для Claude — на их собственных условиях с этим провайдером. Сервер не может обеспечить или ограничить это; это осознанное принятие для каждого развертывания.
Рекомендуемые правила использования
Начните с режима только для чтения: держите
FES_MCP_ALLOW_MUTATIONS=false(по умолчанию), пока не обретете уверенность в непроизводственной среде.Сократите
config/allowlist.txtдо инструментов, которые действительно нужны вашему развертыванию — меньше инструментов означает меньше раскрытия данных и более понятную историю одобрений.Предпочитайте непроизводственные экземпляры Sisense при исследовании; инструменты настолько безопасны, насколько безопасны разрешения вошедшего пользователя.
Тестируйте разрушительные операции с MCP-клиентом, поддерживающим элиситацию (Claude Code, Cursor), чтобы видеть диалоги подтверждения.
Конфигурация
Переменная | По умолчанию | Используется | Назначение |
| — | fes-mcp | учетные данные режима разработки ( |
|
| оба | проверять TLS при вызове Sisense |
| по транспорту: http ⇒ | fes-mcp | источник учетных данных |
|
| fes-mcp |
|
|
| оба | привязка HTTP |
| — | fes-auth | публичный базовый URL (обнаружение/редиректы OAuth) |
| — | fes-auth | сервер ресурсов для проксирования вызовов инструментов |
|
| fes-mcp | секунды, в течение которых проверенная пара (экземпляр, токен) доверяется |
| — (принимать любые) | fes-mcp | точное совпадение allowlist для |
|
| fes-mcp | переопределение через запятую tool_ids / модулей |
|
| fes-mcp | предоставлять изменяющие инструменты |
| встроенный реестр | fes-mcp | альтернативный JSON реестра |
|
| оба | подробность журнала (только stderr) |
Тесты
uv run python -m pytest(python -m важен: он помещает корень репозитория в sys.path, на что
полагаются импорты from tests.conftest import … в тестовых модулях.)
49 тестов, без сети и без учетных данных (Sisense и SDK замоканы): выбор реестра, проверка/ошибки диспетчера, MCP-циклы, подтверждение мутаций (approve/abort/decline/no-capability), проверка вышестоящих учетных данных (внедренные заголовки, контракт 401, список разрешенных источников, отзыв TTL), и полное разделение AS+RS — OAuth-танец с ?target= и без, метаданные обнаружения, проксированные вызовы инструментов, ротация обновлений, самовосстановление при отзыве на стороне Sisense, плюс пути злоупотреблений (поддельный CSRF, ограничение скорости перебора, истекшие сессии).
Регенерация реестра
./refresh_registry.sh # rebuild config/ from the installed PySisense SDKНовые методы SDK попадают в реестр, но остаются скрытыми, пока не будут явно добавлены в config/allowlist.txt.
Поддержка и вклад
Это экспериментальный проект, созданный сообществом и поддерживаемый Sisense Field Engineering, предоставляемый «как есть».
Не открывайте тикет GSS — это не функция GA Sisense.
По вопросам использования или помощи в начале работы обращайтесь к вашему менеджеру по успеху клиентов (CSM), который направит отзывы команде Field Engineering.
Проблемы и вклад приветствуются через репозиторий.
Лицензия
Available Tools
36 toolsaccess_management_get_datamodel_columnsaccess_management.get_datamodel_columnsARead-only
Retrieve columns from a DataModel by collecting them from its datasets and tables. Resolves the DataModel ID by title, then walks its datasets and tables to gather every column.
Returns: list[dict[str, Any]] A list of dictionaries, each containing datamodel_id, datamodel_name, table, and column. An empty list is returned if the DataModel cannot be found or has no columns.
| Name | Required | Description | Default |
|---|---|---|---|
| datamodel_name | Yes | The name of the DataModel from which to extract columns. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, non-destructive operation. The description adds meaningful behavioral details beyond those annotations: it resolves the DataModel by title, walks datasets and tables, and returns an empty list if the DataModel is not found or has no columns. This gives the agent useful expectations about edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no wasted words: purpose, resolution/collection process, and return format/edge behavior. Each sentence contributes necessary information and the most important action is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple single-parameter input and the presence of read-only annotations, the description is complete. It explains the return value shape and the empty-list behavior, which is especially important because no output schema is provided.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds extra semantic value by clarifying that datamodel_name is resolved as a title to an ID, which is critical for correct invocation. It also reinforces that an unknown title yields an empty list rather than an error.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Retrieve columns') and resource ('DataModel'), and distinguishes itself by explaining it collects columns from datasets and tables after resolving the DataModel ID by title. This clearly differentiates it from sibling tools like datamodel_get_table_schema, which target a single table schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies when to use the tool: when you have a DataModel title and need all its columns aggregated from datasets and tables. However, it does not explicitly mention alternatives or state when not to use this tool, leaving some inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
access_management_get_groupsaccess_management.get_groupsARead-only
Retrieve groups — one named group, or all of them. Fetches the groups defined on the Sisense server. With name the API filters server-side to that group; without it, every group is returned. One row per group.
Returns: list[dict[str, Any]] | dict[str, Any] A list of raw group objects as returned by the API (each with _id, name, defaultRole, and related fields). Without name, an empty list means the server genuinely has …
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Group name to filter by. Omit for all groups. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and non-destructive, so the description correctly adds value beyond them: it discloses server-side filtering, one row per group, raw API objects with key fields, and the meaning of an empty list. This is exactly the behavioral detail an agent needs beyond the safety hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is focused and front-loaded, with each sentence serving a purpose: scope, filtering behavior, output shape, and empty-list semantics. No filler or redundant restatement of the tool name is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one optional parameter, no output schema, and supported by read/write annotations, the description covers the return type, key returned fields, filtering behavior, and edge-case meaning of an empty result. Nothing needed for correct invocation or interpretation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single optional parameter, so the baseline is 3. The description adds extra meaning by clarifying the server-side filter behavior and tying the parameter to the return shape ('one row per group'), going slightly beyond the schema's one-line description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the action ('Retrieve'), the resource ('groups defined on the Sisense server'), and the input-dependent scope ('one named group, or all of them'). It also distinguishes this tool from sibling group-related tools like use or role tools by specifying exactly what kind of group data it returns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: provide `name` for a server-side filtered lookup, omit it to fetch every group. It does not explicitly name sibling alternatives or say when not to use this tool, but the boundary between 'one group' and 'all groups' is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
access_management_get_my_useraccess_management.get_my_userARead-only
Retrieve the currently logged-in user for the API token. Sends GET /api/users/loggedin. Use this to resolve migration user identity (email, username, internal ID) for the authenticated admin token.
Returns: dict[str, Any] The logged-in user object from the API, or {"error": "..."} on failure.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false, covering the safety profile. The description adds value beyond this by disclosing the concrete HTTP endpoint, the return type (dict[str, Any]), and the failure shape ({"error": "..."}). It does not mention rate limits or other failure modes, but for a zero-parameter read call the disclosure is solid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: the primary action, the endpoint plus use case, and the return/error format. It is front-loaded with the most important information. Slightly dense with the 'Returns:' type annotation, but that detail justifies itself given the absence of an output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with no output schema, this description is complete. It covers what the tool does, the exact endpoint, the intended migration-user-identity scenario, the return object type, and the error case. An agent has everything needed to invoke it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters with 100% schema coverage, so there is nothing for the description to document. The baseline of 4 applies, and the description's mention of 'for the API token' correctly signals that the identity is derived from the token rather than passed in.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Retrieve the currently logged-in user for the API token') and names the exact endpoint (GET /api/users/loggedin). This clearly distinguishes it from siblings like access_management_get_user and access_management_get_users_all, which target specific users or all users rather than the token's own identity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit intended use case: 'Use this to resolve migration user identity (email, username, internal ID) for the authenticated admin token.' This is clear context an agent can act on. However, it does not name alternatives or state when NOT to use this tool versus the similarly named get_user/get_users_all siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
access_management_get_rolesaccess_management.get_rolesARead-only
Retrieve all Sisense roles. Sends GET /api/roles. Returns the raw role list used to build role name-to-ID maps (for example in multi-tenant migration workflows).
Returns: list[dict[str, Any]] | dict[str, Any] A list of role objects on success, or {"error": "..."} on failure.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint and destructiveHint=false, so the safety profile is clear. The description adds value by specifying the exact GET endpoint, stating it returns the raw role list, and documenting an `{"error": "..."}` failure shape. This is transparent beyond the structured fields, though it does not cover auth or rate-limit behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is generally tight and front-loaded, starting with the action and endpoint. There is minor redundancy between 'Returns the raw role list...' and the later 'Returns: list[dict[str, Any]]...' line, but it remains compact and readable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only list endpoint with no output schema, this description is complete. It includes the endpoint, success return type, failure format, and a representative use case, so an agent has enough information to invoke it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the schema already covers everything relevant. The description still adds useful return semantics with the list/error types, which is appropriate for a parameterless tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Retrieve', names the exact resource ('all Sisense roles'), and even spells out the HTTP endpoint `GET /api/roles`. This clearly distinguishes the tool from the many sibling getters that target users, groups, dashboards, or datamodel objects.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a concrete use case: building role name-to-ID maps for multi-tenant migration workflows. This helps an agent understand when this exact list is needed, though it does not explicitly discuss when not to use it or name alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
access_management_get_unused_columns_bulkaccess_management.get_unused_columns_bulkARead-only
Run unused-column analysis for one or more data models and return a combined per-model outcome.
Returns: dict[str, Any] Always a dict with "results" and "errors": - "results": flat list of column rows across all processed data models, each row shaped as get_datamodel_columns rows plus a "used" boolean. …
| Name | Required | Description | Default |
|---|---|---|---|
| datamodels | Yes | One or more data model references to analyze. **Required.** Each reference can be: - a data model ID, or - a data model title (name). At runtime this parameter is tolerant of a single string and will normalize it to a one-element list. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and non-destructive behavior. The description adds valuable behavioral detail: it always returns a dict with 'results' and 'errors', returns a flat list across models, and normalizes a single string input. This goes beyond the structured annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: it opens with the core action, then details the return contract in a readable list. It is informative without being bloated, though the trailing ellipsis suggests some content may be omitted and the opening sentence overlaps slightly with the return explanation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite lacking an output schema, the description provides enough return structure for an agent to consume the result. It explains the combined across-models behavior and error grouping. It relies on knowledge of get_datamodel_columns row shape, which is reasonable given the sibling tool exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% parameter coverage, including accepted reference types and tolerant string normalization. The description does not materially add parameter-level semantics beyond restating 'one or more', so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Run unused-column analysis') and the resource ('one or more data models'), and explicitly differentiates this as a bulk operation from the single-model sibling access_management_get_datamodel_columns. The output semantics are also described, making the tool's purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes it clear this tool is for analyzing multiple data models at once and returns combined results, which implies when to choose it over single-model tools. However, it does not explicitly name alternatives or state conditions for when not to use it, so it falls short of the highest bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
access_management_get_useraccess_management.get_userARead-only
Retrieve one named user by email address, in the canonical user row shape. Fetches users with expanded groups and role data and returns the record matching the provided email address. Changed in 2.0: ROLE_NAME held the display name in 1.x (that value is now ROLE_DISPLAY_NAME); GROUPS still holds the group names and is joined by the new GROUP_IDS. See docs/upgrading.md.
Returns: dict[str, Any] The canonical user row: USER_ID, USER_NAME, EMAIL, FIRST_NAME, LAST_NAME, IS_ACTIVE, ROLE_ID, ROLE_NAME (the raw Sisense value, e.g. "consumer"), ROLE_DISPLAY_NAME …
| Name | Required | Description | Default |
|---|---|---|---|
| user_email | Yes | Email address of the user to retrieve. **Required** — this method always answers "one named user"; use ``get_users_all`` for every user. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false, and the description goes further by disclosing expanded groups/role data, the canonical row shape, and the 2.0 field-name migration from ROLE_NAME to ROLE_DISPLAY_NAME. This adds meaningful behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well structured: core action first, then behavioral detail, then version-change context, then return shape. Every sentence adds distinctive value, and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even without an output schema, the description supplies the canonical return fields, expanded group/role semantics, and a note on version-specific field naming. This is sufficient for an agent to invoke the tool correctly and interpret the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, user_email, is already fully described in the schema with format and required status, giving 100% schema coverage. The description merely restates 'by email address' and 'matching record,' so it adds little beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Retrieve one named user by email address,' giving a specific verb, resource, and scope. It clearly differentiates from siblings like get_users_all and get_my_user by emphasizing the single-user, email-based lookup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies this tool is for retrieving exactly one named user by email rather than listing users. It does not explicitly name alternatives in the description itself, though the schema parameter does direct users to get_users_all for all users.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
access_management_get_users_allaccess_management.get_users_allARead-only
Retrieve every user, one canonical user row each. Reports exactly what Sisense stores: group memberships are unfiltered (Everyone is included — consumers that want to hide a universal group can drop it; a consumer that never received it cannot put it back), and ROLE_NAME carries the raw Sisense value with the UI-facing name in ROLE_DISPLAY_NAME. Changed in 2.0: ROLE_NAME held the display name in 1.x (that value is now ROLE_DISPLAY_NAME), GROUPS is joined by the new GROUP_IDS, and Everyone is no longer filtered out of GROUPS. See docs/upgrading.md.
Returns: list[dict[str, Any]] | dict[str, Any] One row per user, each with USER_ID, USER_NAME, EMAIL, FIRST_NAME, LAST_NAME, IS_ACTIVE, ROLE_ID, ROLE_NAME (raw, e.g. "consumer"), …
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavioral context beyond the annotations: group memberships are unfiltered, 'Everyone' is included, ROLE_NAME contains the raw Sisense value while ROLE_DISPLAY_NAME is UI-facing, and it documents version 2.0 changes affecting field semantics. This is exactly the kind of non-obvious behavior an agent needs to know.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then provides meaningful caveats and version-change context. It is longer than strictly necessary, and the upgrade-history detail could arguably live only in the referenced doc, but the structure is logical and each section earns its place for interpretation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema present, the description properly explains the return shape, lists the key fields, and clarifies important edge cases like the 'Everyone' group and raw ROLE_NAME values. An agent has enough context to invoke the tool correctly and interpret its results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema coverage is 100%, so there are no parameter semantics to clarify. The description focuses on return value semantics instead, which is appropriate here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Retrieve every user, one canonical user row each.' It clearly distinguishes this from single-user or group-related tools by emphasizing 'every user' and 'canonical user row.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use this tool by highlighting 'every user' and unfiltered data, but it does not explicitly name alternatives like access_management_get_user or access_management_get_my_user, nor does it state when not to use it. The usage context is present but left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
access_management_users_per_groupaccess_management.users_per_groupARead-only
Retrieve group memberships — one group's members, or every membership. Returns one flat row per (group, user) membership. With group_name the rows are that group's members; without it, every membership on the instance is returned (ask get_groups for the per-group view). Everyone and All users in system are omitted from the all-groups view: Sisense fills both with every user, so they restate get_users_all rather than describing group structure. Naming either one still returns its members. The rule across the SDK: **targeted questions give complete answers; only the …
Returns: list[dict[str, Any]] | dict[str, Any] One row per (group, user) membership, each with GROUP_ID, GROUP_NAME, USER_ID, USER_NAME, EMAIL, FIRST_NAME, LAST_NAME, IS_ACTIVE, ROLE_ID, …
| Name | Required | Description | Default |
|---|---|---|---|
| group_name | No | The name of the group whose members to list. Omit for all memberships. A name that matches no group returns ``{"error": "..."}`` naming it — never a silent empty list. Naming ``Everyone`` or ``All users in system`` returns their members — an explicit request is always honored, even though the all-groups view omits them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this read-only and non-destructive, and the description adds substantial behavioral detail beyond them: flat-row semantics, omission of synthetic groups in the all-groups view, honoring explicit requests for those groups, and a non-silent error for unmatched group names. It also discloses the return shape and fields despite no output schema, which is valuable context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and mode distinction, and most sentences earn their place by explaining edge cases. It loses a point because some content repeats the schema's group_name notes and the final sentence is truncated ('only the …'), leaving a dangling rule that does not contribute.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter read-only tool with no output schema, the description supplies the return format, field list, error behavior, and alternative tools, so an agent can call it correctly. The incomplete closing sentence and the absence of any mention of pagination or limits are minor gaps, so it is strong but not perfect.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents group_name with 100% coverage, including omit behavior, error behavior, and Everyone/All users handling. The description mostly reflects those same semantics rather than adding new parameter-level meaning beyond the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a specific verb and resource: 'Retrieve group memberships' and immediately clarifies the two modes (one group vs. every membership). It also distinguishes itself from the sibling get_groups by noting this tool returns 'one flat row per (group, user) membership' while get_groups gives the per-group view, so there is no ambiguity about what this tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to omit vs. provide group_name and points to the alternative get_groups for a per-group view. It also explains that the all-groups view omits Everyone and All users in system because those restate get_users_all, preventing misuse of this tool for all-user queries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dashboard_can_be_owneddashboard.can_be_ownedARead-only
Check whether a dashboard can be owned by the current user. Sends GET /api/v1/dashboards/{dashboard_id}/can_be_owned.
Returns: dict[str, Any] The API response on success, or {"error": "..."} on failure.
| Name | Required | Description | Default |
|---|---|---|---|
| dashboard_id | Yes | The dashboard ``oid`` to check. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds the HTTP method and a success/error return shape, but no deeper behavior such as auth requirements, failure modes, or side effects. This is useful but limited context, so a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise, purposeful sentences front-load the action, then give the endpoint and return contract. There is no filler or repetition of schema annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only tool with no output schema, the description covers purpose, endpoint, and return/error format. It is close to complete, though it omits any preconditions or ownership-transfer usage context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, meaning dashboard_id is already documented as 'The dashboard oid to check.' The description adds no parameter-level meaning beyond the endpoint path, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific predicate, 'Check whether a dashboard can be owned by the current user,' and names the exact API call. It is clearly distinguishable from sibling dashboard_get_* tools, which fetch dashboards or shares rather than check ownership eligibility.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides no explicit guidance about when to use this tool versus alternatives, such as 'before ownership transfer' or 'when confirming eligibility for the current user.' The only clue is 'current user,' which describes the tool's semantics rather than a usage condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dashboard_find_widgets_by_typedashboard.find_widgets_by_typeARead-only
Find all widgets matching a given type across one or more dashboards. Iterates over the specified dashboards (or all dashboards when dashboards is None) and returns every widget whose type field matches widget_type.
Returns: list[dict[str, Any]] A list of match records. Each record contains: - dashboard_id (str): The oid of the containing dashboard. - dashboard_title (str): The title of the containing dashboard. - widget_id …
| Name | Required | Description | Default |
|---|---|---|---|
| dashboards | No | One or more dashboard IDs or titles to search. A bare string is treated as a single-item list. When ``None`` (default), all dashboards on the instance are searched. | |
| max_results | No | Stop after collecting this many matching widgets. ``None`` (default) means no limit. | |
| widget_type | Yes | The widget type to match (for example ``"BloX"``, ``"chart"``, ``"pivot"``). Comparison is case-sensitive. | |
| admin_access | No | When ``True`` (default), enumerates all dashboards on the instance via the admin endpoint and fetches widgets using ``adminAccess=true``, so dashboards owned by other users are included. When ``False``, only dashboards visible to the API token user are scanned. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral details beyond the readOnly/destructive annotations: it describes iteration over dashboards, the effect of admin_access on including other users' dashboards, case-sensitive matching, and early stopping via max_results. These are not present in the annotations and help the agent understand side effects and scope. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and efficient: a one-sentence purpose, a brief iteration explanation, and a concise return-value breakdown. Every sentence contributes useful information and there is no filler. The most important scoping information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with four parameters and no output schema, the description covers the main behavioral context: what is searched, how admin access affects scope, how limits work, and the shape of returned records. The return record list is slightly truncated ('widget_id …'), which leaves minor ambiguity about the full record contents, so it is not a perfect 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all four parameters including defaults and behavior. The description reinforces some parameter semantics (e.g., dashboards=None means all dashboards, widget_type is case-sensitive) but does not add substantial new meaning beyond the schema. Baseline 3 is appropriate given the high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Find all widgets matching a given type across one or more dashboards.' This clearly distinguishes it from siblings like dashboard_get_widget_by_id (single widget lookup) and dashboard_get_dashboards (list dashboards). The scope and matching criterion are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context by explaining that it iterates over specified dashboards or all dashboards when none are given, and matches widgets by type. It does not explicitly name alternatives or state when not to use it, but the behavior is specific enough that an agent can infer appropriate usage. A small deduction because no explicit exclusion or alternative guidance is present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dashboard_get_all_dashboardsdashboard.get_all_dashboardsARead-only
Retrieve all dashboards from the Sisense server. Sends GET /api/v1/dashboards/admin?dashboardType=owner using the admin endpoint, which requires elevated access.
Returns: list[dict[str, Any]] | dict[str, Any] A list of dashboard objects on success, or {"error": "..."} on failure.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds value by specifying the exact HTTP endpoint, the required elevated access, and the failure return shape ({'error': '...'}), which goes beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core purpose. Every sentence adds useful information: what it does, which endpoint it calls, what access is required, and what the caller should expect on success or failure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read-only tool, the description is complete. It names the endpoint, auth requirement, success return type, and error format. No output schema exists, so the description's return-value note is especially valuable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema coverage is 100%, so there is nothing for the description to explain about parameters. The description instead clarifies the endpoint and return behavior, which is appropriate and sufficient.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Retrieve all dashboards from the Sisense server'), identifies the exact endpoint, and notes the elevated-access requirement. The word 'all' and the admin endpoint help distinguish it from sibling tools like dashboard_get_dashboards or dashboard_get_dashboard_by_id.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for use: retrieving all dashboards via the admin endpoint, and it warns that elevated access is required. It does not explicitly name alternatives or say when not to use it, but the scope and access requirement provide sufficient practical guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dashboard_get_dashboard_by_iddashboard.get_dashboard_by_idARead-only
Retrieve a specific dashboard by its ID. Sends GET /api/v1/dashboards/admin?dashboardType=owner&id={dashboard_id} against the admin endpoint.
Returns: list[dict[str, Any]] | dict[str, Any] The matching dashboard objects on success, or {"error": "..."} when the request fails or no dashboard is found.
| Name | Required | Description | Default |
|---|---|---|---|
| dashboard_id | Yes | The ``oid`` of the dashboard to retrieve. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/destructive annotations, the description discloses the exact HTTP request, the response shape, and the failure contract: it returns an error dict when the request fails or no dashboard is found. It does not cover authorization details or rate limits, but it adds meaningful behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two compact sentences with the primary purpose front-loaded, followed by the endpoint and return contract. There is no filler, redundancy, or unnecessary restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only GET with no output schema, the description is complete: it specifies the endpoint, the success return shape, and the error behavior. No critical call-time detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already says dashboard_id is 'The oid of the dashboard to retrieve.' The description's endpoint template confirms the parameter's role but adds no substantially new meaning beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a specific verb and resource: 'Retrieve a specific dashboard by its ID.' It also provides the exact GET endpoint, making its scope unambiguous and differentiating it from siblings like dashboard_get_all_dashboards and dashboard_get_dashboards.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the correct usage context: call this when you already have a dashboard ID and need one specific dashboard. It does not explicitly name sibling alternatives or give when-not-to-use guidance, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dashboard_get_dashboard_columnsdashboard.get_dashboard_columnsARead-only
Retrieve columns referenced by a dashboard, including widget and filter columns. Resolves the dashboard by title with get_dashboard_by_name, exports its full metadata, then extracts column references from both filters and widgets. The final list is deduplicated by table and column.
Returns: list[dict[str, Any]] | dict[str, Any] A list of distinct column entries. Each entry contains dashboard_name, source ("filter" or "widget"), widget_id, table, and column — an empty list means …
| Name | Required | Description | Default |
|---|---|---|---|
| dashboard_name | Yes | Title of the dashboard to retrieve columns from. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though readOnlyHint is already annotated, the description adds valuable behavioral detail: it resolves the dashboard by title, exports full metadata, extracts column references from both filters and widgets, and deduplicates by table and column. It also discloses the exact output fields, which is especially useful given the absence of an output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loads the main purpose before diving into implementation details. The Returns section is clearly structured and avoids filler. A small amount of internal implementation detail could have been trimmed, but it remains useful for transparency.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read-only tool, the description covers the operation, the return type, the fields included, the deduplication behavior, and the meaning of an empty list. It does not describe error behavior when a dashboard is not found, and the final 'empty list means …' sentence is cut off, leaving a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes dashboard_name as 'Title of the dashboard to retrieve columns from,' so coverage is high. The description adds extra meaning by explaining that the name is used to resolve the dashboard through get_dashboard_by_name, reinforcing that it is a human-readable title rather than an ID.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource pair: 'Retrieve columns referenced by a dashboard, including widget and filter columns.' It also clarifies the tool resolves by title via get_dashboard_by_name, which distinguishes it from sibling tools like dashboard_get_dashboard_by_id.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is implied through the phrase 'Retrieve columns referenced by a dashboard,' but there is no explicit statement of when to use this tool versus alternatives such as dashboard_get_dashboard_by_id or dashboard_find_widgets_by_type. The guidance is inferred rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dashboard_get_dashboardsdashboard.get_dashboardsARead-only
Retrieve dashboards visible to the authenticated user. Sends GET /api/v1/dashboards, which returns dashboards the current user owns or has been shared to — as opposed to get_all_dashboards, which uses the admin endpoint and requires elevated access.
Returns: list[dict[str, Any]] | dict[str, Any] List of dashboard objects on success, or {"error": "..."} on failure.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Subset of fields to include in the response (for example ``["oid", "title", "owner"]``). When omitted, all fields are returned. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and destructiveHint annotations, the description discloses the exact HTTP method and endpoint, the visibility semantics (owned or shared), and the return shape including the error format. This is strong behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The main action and endpoint are front-loaded, followed by a concise comparison to a sibling and a return-type note.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers what the tool does, its scope, its endpoint, its return type, and its error behavior. With only one optional parameter and no output schema, nothing essential is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter 'fields' is already fully documented in the schema with an example and behavior when omitted. With 100% schema description coverage, the tool description does not need to add more, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Retrieve dashboards visible to the authenticated user' via GET /api/v1/dashboards. It explicitly contrasts with get_all_dashboards, making the purpose and scope unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states when to use this tool versus dashboard_get_all_dashboards: the former uses the user-facing endpoint, while the latter uses the admin endpoint and requires elevated access. This gives an agent an explicit routing rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dashboard_get_dashboard_scriptdashboard.get_dashboard_scriptARead-only
Build a formatted dashboard script helper object. Retrieves a dashboard export payload and wraps its script content in a :class:SisenseScript helper that can render plain text, markdown, or file output.
Returns: SisenseScript | dict[str, str] A :class:SisenseScript instance when the dashboard is retrieved and has a script. {"error": "..."} when the export fails (including status_code for HTTP failures such as missing …
| Name | Required | Description | Default |
|---|---|---|---|
| dashboard_id | Yes | The dashboard identifier to export. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral detail beyond annotations: it specifies the return type (SisenseScript or error dict), the condition for success (dashboard retrieved and has a script), and error behavior (includes status_code for HTTP failures). This gives an agent a good sense of outcomes without making the description the sole source of safety information.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and mostly front-loaded: the first sentence states the primary purpose, and the second covers the return contract. The phrasing 'Build a formatted dashboard script helper object' is slightly abstract but immediately clarified. No redundant filler appears, though the return type sentence could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, read-only tool with annotations and no output schema, the description covers the essential behavioral contract: what it returns on success, what it returns on failure, and how errors are shaped. Minor gaps exist, such as not explicitly describing what happens when a dashboard exists but has no script, but overall it is sufficiently complete for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% coverage of the single parameter, dashboard_id, with a clear description. The tool description does not add additional meaning about the parameter beyond what is already in the schema. According to the rubric, baseline 3 is appropriate since schema_description_coverage is high and the parameter is simple.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action: building a formatted dashboard script helper object by retrieving a dashboard export and wrapping its script in a SisenseScript helper. This clearly distinguishes it from sibling tools like dashboard_get_dashboard_by_id (which retrieves the dashboard itself) and dashboard_get_widget_script (which targets widget scripts). The verb 'build' plus the resource 'dashboard script helper' makes the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is used when a formatted dashboard script helper is needed, but it does not explicitly state when to use it over alternatives or when not to use it. No sibling comparisons or exclusions are provided. The usage context is inferable from the clear resource focus, but explicit guidance is absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dashboard_get_widget_by_iddashboard.get_widget_by_idARead-only
Retrieve a single widget by its dashboard and widget IDs. Sends GET /api/v1/dashboards/{dashboard_id}/widgets/{widget_id}. Returns the full widget object as returned by the Sisense API.
Returns: dict[str, Any] The widget object returned by the API, or {"error": "..."} on failure.
| Name | Required | Description | Default |
|---|---|---|---|
| widget_id | Yes | The ``oid`` of the widget to retrieve. | |
| admin_access | No | When ``True`` (default), appends ``?adminAccess=true`` to the request, allowing access to dashboards the API token user does not own. Some Sisense versions reject the ``adminAccess`` query parameter with HTTP 422 (strict query-schema validation); the request is then retried automatically without it. | |
| dashboard_id | Yes | The ``oid`` of the dashboard that contains the widget. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral detail by specifying the exact HTTP GET endpoint and stating that failure returns an error dict rather than raising an unhandled exception.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core action and endpoint. There is slight redundancy between 'Returns the full widget object as returned by the Sisense API' and the following 'Returns: dict[str, Any]' line, which prevents a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only GET with no output schema and well-covered parameters, the description is complete: it provides the endpoint, the expected return value, the error behavior, and the needed IDs. Combined with the strong input schema coverage, an agent has everything required to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% parameter description coverage, including clear definitions for dashboard_id, widget_id, and the admin_access retry behavior. The description itself does not need to add parameter semantics, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Retrieve a single widget by its dashboard and widget IDs.' It names the exact REST endpoint, making the operation unambiguous and distinguishing it from sibling tools like dashboard_get_dashboard_by_id or dashboard_find_widgets_by_type.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives. It does not mention that dashboard_get_dashboard_by_id should be used for dashboards or that dashboard_find_widgets_by_type should be used when searching by widget type. The usage context is only implied by the endpoint and parameter names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dashboard_get_widget_scriptdashboard.get_widget_scriptARead-only
Build a formatted widget script helper object. Retrieves a dashboard export payload, selects a widget by index/key, and wraps its script content in a :class:SisenseScript helper for downstream rendering.
Returns: SisenseScript | dict[str, str] A :class:SisenseScript instance when the widget is found and has a script. {"error": "..."} when the export fails (including status_code for HTTP failures such as missing …
| Name | Required | Description | Default |
|---|---|---|---|
| widget_id | Yes | The widget identifier or lookup key used in the exported widget mapping. | |
| dashboard_id | Yes | The dashboard identifier to export. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds meaningful behavior: it retrieves an export payload, selects by index/key, wraps script content, and returns an error dict with status_code on export failure. This is useful context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the main purpose. The return behavior is appended clearly. Minor redundancy exists ('Build...helper' and later 'wraps...helper') but it is not bloated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with two fully documented parameters and annotations, the description covers the main operation, return type, and failure mode. It does not explain the case where the widget is found but has no script, but this is a minor gap given the overall clarity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters. The description adds minimal new meaning; it mentions selection by index/key but does not enrich the parameter definitions beyond what the schema already states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses specific verbs ('Retrieves', 'selects', 'wraps') and a clear resource (widget script for downstream rendering). It is clearly distinct from siblings like dashboard_get_dashboard_script and dashboard_get_widget_by_id, so an agent can tell what this tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly indicates the use case: get a widget's script wrapped in a SisenseScript helper for downstream rendering. It does not explicitly name alternatives or exclusion criteria, but the context is strong enough to guide selection among similar dashboard tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_describe_datamodeldatamodel.describe_datamodelARead-only
Retrieve data model structure in a flat, row-based format. Resolves the data model by name and flattens its datasets and tables into one row per table, suitable for DataFrame or CSV export. Returns: list[dict[str, Any]] List of row dicts, each representing a single table with model, dataset, connection, and table context. Returns an empty list if the data model is not found.
| Name | Required | Description | Default |
|---|---|---|---|
| datamodel_name | Yes | Name (title) of the data model to describe. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and destructiveHint annotations, the description discloses meaningful behavior: it resolves the data model by name, flattens datasets and tables, returns a list of row dicts, and returns an empty list when the model is not found. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the primary purpose, then immediately explains the return format and missing-model behavior. Every sentence earns its place, and the return type note compensates for the lack of an output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, read-only tool with no output schema, the description fully covers what an agent needs: what the tool returns, the row structure, the missing-model behavior, and the use case. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents the only parameter with 100% coverage ('Name (title) of the data model to describe'). The description lightly reinforces the meaning by saying it 'resolves the data model by name' but adds no new depth beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Retrieve') with a concrete resource ('data model structure') and clearly distinguishes its output format ('flat, row-based format', 'one row per table') from sibling tools like datamodel_get_model_schema. The mention of DataFrame/CSV suitability further clarifies its unique role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context about when to use this tool: when a flat, row-oriented representation of a data model is needed, especially for DataFrame or CSV export. It does not explicitly name alternatives or exclusions, but the format-oriented context is sufficient for most selection scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_generate_connections_payloaddatamodel.generate_connections_payloadARead-only
Generate a connection payload for a given data source type. Builds the provider-specific request body consumed by create_connections. The datasource_type is matched case-insensitively. Supported types are "Athena", "RedShift", "BigQuery", and "DataBricks".
Returns: dict[str, Any] The provider-specific connection payload.
| Name | Required | Description | Default |
|---|---|---|---|
| datasource_type | Yes | Type of data source (matched case-insensitively). | |
| connection_params | Yes | Connection details. Supported keys depend on ``datasource_type``: - Athena: ``name`` (required), ``region`` (required), ``s3_output_location`` (required), ``aws_access_key`` (required), ``aws_secret_key`` (required), ``description``, ``schema``, ``additional_parameters``. - DataBricks: ``name`` (required), ``connection_string`` (required), ``token`` (required), ``description``, ``use_dynamic_schema``, ``schema``. - BigQuery: ``name`` (required), ``service_account_key_path`` (required), ``description``, ``use_service_account``, ``use_proxy_server``, ``use_dynamic_schema``, ``record_field_flattening_level``, ``unnest_arrays``, ``allow_large_results``, ``use_storage_api``, ``additional_parameters``, ``database``. - RedShift: ``server`` (required), ``username`` (required), ``password`` (required), ``name``, ``description``, ``default_database``, ``additional_parameters``. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral detail: datasource_type matching is case-insensitive, the output is a dict payload, and the tool is a payload builder rather than a connector. This goes beyond what annotations alone provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core purpose, and every sentence contributes either to scope, supported types, or return type. There is no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich input schema and annotations, the description is nearly complete. It explains the output type and how the payload is intended to be used. A more explicit note about what happens with unsupported datasource types would improve it, but the supported list and schema enum already cover the main decision.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents datasource_type and connection_params, including per-type required and optional keys. The description adds little beyond what the schema already provides, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Generate a connection payload') and a clear resource ('for a given data source type'). It distinguishes itself from sibling datamodel tools by explicitly noting it builds the provider-specific request body for create_connections, not performing connection operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use this to produce a payload consumed by create_connections, with supported datasource types enumerated. It does not explicitly name alternatives or say when not to use it, but the intended use case is strongly implied by the 'consumed by create_connections' phrasing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_get_all_datamodeldatamodel.get_all_datamodelARead-only
Retrieve metadata for all data models using an internal API. Sends a POST /api/v2/ecm/ GraphQL query (elasticubesMetadata). This includes additional fields such as build status, size, and timestamps that may not be available through the standard public endpoints.
Returns: list[dict[str, Any]] | dict[str, Any] List of data model metadata objects (each with oid, title, type, status, sizeInMb) on success, or {"error": "..."} on failure.
Uses an internal Linux-only route; on Windows-based Sisense use get_elasticubes instead.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and non-destructive annotations, the description discloses the internal API route, the fact that it sends a POST request, the Linux-only platform constraint, and the exact success/error return shapes. This adds meaningful behavioral context that annotations alone do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then adds the API detail, return type, and platform caveat in a logical order. Every sentence provides useful information for selection and invocation, with no fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read-only metadata tool, the description is complete: it explains the API mechanism, the returned metadata fields, error behavior, and when to use an alternative. There is no output schema, so the explicit return format in the description fully covers what an agent needs to interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no parameters, so the description needs no parameter-level explanation. With zero parameters, baseline is 4, and the description appropriately focuses on output and platform behavior instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves metadata for all data models via an internal API, with a specific endpoint and GraphQL query. It also distinguishes itself from the related sibling get_elasticubes by noting the Linux-only route, so an agent can tell them apart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly explains when to use this tool versus the alternative: on Windows-based Sisense, use get_elasticubes instead. It also clarifies that this tool accesses internal metadata not available through standard public endpoints, giving clear selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_get_connectiondatamodel.get_connectionARead-only
Retrieve connections matching a name. Sends GET /api/v2/connections?name=<connection_name> and returns the matching connection list.
Returns: list[dict[str, Any]] | dict[str, Any] List of matching connection objects if found, or {"error": "..."} on failure or when no match is found.
| Name | Required | Description | Default |
|---|---|---|---|
| connection_name | Yes | Name of the connection to filter by. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the readOnlyHint=true and destructiveHint=false annotations by disclosing the HTTP method, endpoint, query parameter, return type, and the error shape on failure or no match. Minor operational details like authentication requirements are not mentioned, but for a read-only GET operation this is acceptable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with the action and endpoint front-loaded, followed only by the return behavior. There is no redundancy or filler, and every sentence contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, read-only tool with no output schema, the description is complete: it specifies what is retrieved, how the request is made, what the matching data looks like, and what happens on failure or no match. No critical information needed to use the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully describes connection_name with 100% coverage. The description adds that the parameter becomes the name query parameter in the request, but provides no additional constraints, formatting rules, or semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Retrieve connections matching a name' and gives the exact endpoint GET /api/v2/connections?name=<connection_name>. The name-based filter distinguishes this from the sibling datamodel_get_connections_all, so an agent can tell them apart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly indicates this tool is for retrieving connections by name, which provides clear context for invocation. It does not explicitly name the alternative for getting all connections or list when-not-to-use conditions, but the intended usage is explicit rather than merely implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_get_connections_alldatamodel.get_connections_allARead-only
Retrieve all connections. Sends GET /api/v2/connections and returns the full connection list.
Returns: list[dict[str, Any]] | dict[str, Any] List of connection objects on success, or {"error": "..."} on failure.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses the concrete HTTP method and path (GET /api/v2/connections) and the exact return shape (list of connection objects or error dict). This adds real behavioral context beyond readOnlyHint and destructiveHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two terse sentences deliver the core action, the endpoint, and the return contract without repetition or fluff. The most important information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless, read-only tool with annotations covering safety, the description fully specifies the side effect (network GET) and the success/failure return. No output schema exists, so the stated return types are necessary and sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the description has no parameter documentation burden. The input schema is vacously fully covered, meriting the baseline of 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the specific verb 'Retrieve' with the resource 'all connections' and states the exact endpoint and return type. The emphatic 'all' differentiates it from the sibling datamodel_get_connection, which targets a single connection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use or when-not-to-use guidance is provided. The word 'all' implicitly suggests usage when the full connection list is needed, but no alternatives or exclusions are mentioned, leaving the agent to infer selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_get_datadatamodel.get_dataARead-only
Retrieve data from a specific table in a data model. Runs a SQL query against the data model and returns the rows in a row-based format (a list of dicts) compatible with to_dataframe.
Returns: list[dict[str, Any]] | dict[str, Any] List of dictionaries where each dict represents a row — an empty list means the query genuinely returned no data. On failure, returns the standard ``{"ok": False, "error": "...", …
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Optional SQL query to filter the data. When omitted, all rows of the table are selected. | |
| table_name | Yes | Name of the table to retrieve data from. | |
| datamodel_name | Yes | Name of the data model. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only and non-destructive behavior, and the description adds meaningful context: success returns a list of dicts, an empty list means genuinely no data, and failure returns a standard error dict. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded and mostly efficient, but the failure-return sentence is truncated mid-structure with '...', making it incomplete. It reads as slightly malformed rather than fully polished.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by specifying the row format, empty-list semantics, and failure return behavior. It omits a full error-dict shape and SQL execution caveats, but for a simple read-only 3-param tool it is fairly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents datamodel_name, table_name, and query. The description adds no parameter-specific meaning beyond restating that a SQL query is executed, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action and resource: 'Retrieve data from a specific table in a data model' via a SQL query. It is distinct from schema/count siblings by emphasizing a row-based list-of-dicts result compatible with to_dataframe.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description conveys when to use the tool: when table row data is needed, optionally filtered by SQL. However, it never explicitly distinguishes it from alternatives like datamodel_get_row_count or datamodel_get_table_schema, so the routing is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_get_datasecurity_detaildatamodel.get_datasecurity_detailARead-only
Retrieve detailed datasecurity rules for a data model, including share-level visibility. Each row represents a unique column-level rule and is repeated per share for clarity. Special handling is applied to interpret member values: - If members is an empty list and exclusionary is missing/null, it is interpreted as "Nothing". - If members is empty and exclusionary is False, it is interpreted as "Everything". - If values exist and exclusionary is True, it is treated as a restricted subset.
Returns: list[dict[str, Any]] | dict[str, Any] List of dicts representing datasecurity rules in flat, share-resolved format, each with "datamodel_name", "table_name", "column_name", "data_type", "value", …
| Name | Required | Description | Default |
|---|---|---|---|
| datamodel_name | Yes | Name of the data model to retrieve datasecurity rules for. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the readOnly/destructive annotations by explaining that each row is a column-level rule repeated per share, and by documenting the special interpretation of members and exclusionary values. This gives the agent essential behavioral context that annotations alone do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: a clear purpose sentence, a row-semantics explanation, a bulleted list for special member-value handling, and a return-format note. Each part earns its place and the most critical information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the key behavioral nuances and return shape well, especially given there is no output schema. However, the union return type 'list[dict[str, Any]] | dict[str, Any]' is not fully clarified, and the trailing '…' leaves the complete set of returned fields slightly vague.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is only one parameter, datamodel_name, and the input schema already describes it fully at 100% coverage. The description mentions 'data model' again but adds no new semantic details about the parameter, so the baseline score of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and object: 'Retrieve detailed datasecurity rules for a data model', and adds distinguishing details like 'share-level visibility' and 'column-level rule'. This clearly separates it from sibling tools such as datamodel_get_datamodel_shares or datamodel_get_table_schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description establishes a clear context: use this when you need detailed datasecurity rules and their share-resolved interpretation for a data model. It does not explicitly mention alternatives or when-not-to-use conditions, so it stops short of a perfect score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_get_elasticubesdatamodel.get_elasticubesARead-only
List all ElastiCubes using the legacy v1 endpoint. Sends GET /api/v1/elasticubes/getElasticubes. This endpoint is supported on both Linux and Windows Sisense deployments and returns basic ElastiCube metadata including title, address, and fullname. Prefer get_all_datamodel for Linux deployments when richer metadata (build status, size, timestamps) is needed. Use get_elasticubes when targeting Windows environments or when a lightweight list suffices.
Returns: list[dict[str, Any]] | dict[str, Any] List of ElastiCube objects on success, or {"error": "..."} on failure.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as readOnly and non-destructive, and the description adds useful behavioral context: it calls the legacy v1 endpoint, works on both Linux and Windows, returns only basic metadata fields, and describes both success and error return shapes. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the primary purpose, followed by endpoint details, usage guidance, and return behavior. Every sentence contributes distinct information with no redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read-only listing tool, this description is complete: it specifies the endpoint, platform compatibility, metadata scope, alternative tool, and the return/error format. There is no output schema, so the explicit return type fills that gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema is empty, so there is nothing for the description to add. The description correctly avoids inventing parameter details, matching the baseline of 4 for a no-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List all ElastiCubes'. It also names the exact legacy v1 endpoint and explicitly distinguishes itself from the sibling tool datamodel_get_all_datamodel by platform support and metadata richness.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit selection criteria: prefer get_all_datamodel for Linux deployments when richer metadata is needed, and use get_elasticubes for Windows environments or when a lightweight list suffices. This directly tells an agent when to choose this tool over the alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_get_model_schemadatamodel.get_model_schemaARead-only
Retrieve the schema of a data model, including tables and columns. Resolves the data model by name and emits one row per column, mapping Sisense numeric column type codes to readable type names.
Returns: list[dict[str, Any]] | dict[str, Any] A list of dicts (one per column) with datamodel_name, datamodel_type, dataset_name, table_name, column_name, and column_type on success, or ``{"error": …
| Name | Required | Description | Default |
|---|---|---|---|
| datamodel_name | Yes | Name (title) of the data model to retrieve the schema for. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context beyond the annotations: it explains the row-per-column emission, type-code mapping, success/error return shape, and the returned field names. This gives the agent a clear picture of what to expect when calling the tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded with the core purpose, followed by output behavior and return fields. It is mostly efficient, though 'one row per column' appears twice (once in the first paragraph and again in the return description), which is a minor redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, read-only schema retrieval tool with no output schema, the description is complete: it covers the input, the resolution behavior, the output format, the returned fields, and the error return shape. An agent has enough information to invoke it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with datamodel_name documented as 'Name (title) of the data model to retrieve the schema for.' The description reinforces this by saying the model is 'resolved by name,' but adds no substantially new semantic detail beyond what the schema already provides. Baseline 3 is appropriate given the high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific action ('Retrieve the schema of a data model') and resource, and goes further by describing the output granularity ('one row per column') and the mapping of numeric type codes. However, it does not explicitly distinguish itself from the closely related sibling datamodel_get_table_schema, so it stops short of full differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The usage context is implied: use this when you need the full column-level schema of a named data model. The description does not explicitly state when not to use it or point to alternatives such as datamodel_get_table_schema or datamodel_get_all_datamodel, leaving the agent to infer the proper selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_get_row_countdatamodel.get_row_countARead-only
Retrieve the row count for each table in a specific data model. Resolves the data model's tables, counts rows per table, and returns the results in a flat row-based structure suitable for tabular representation.
Returns: list[dict[str, Any]] | dict[str, Any] List of dictionaries, each with "table_name" and "row_count", plus a final entry with the total row count. On failure, returns the standard ``{"ok": False, "error": "...", …
| Name | Required | Description | Default |
|---|---|---|---|
| datamodel_name | Yes | Name of the data model. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this read-only and non-destructive. The description adds meaningful behavioral detail: it resolves tables, counts rows per table, returns a flat list of dictionaries with table_name and row_count plus a total entry, and specifies the failure return shape. This goes beyond the annotations and is especially valuable because no output schema exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is mostly efficient and front-loaded, but the second sentence partly restates the first ('Resolves the data model's tables, counts rows per table') before adding the return shape. Still, the return details are necessary and well placed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one parameter, no output schema, and annotations covering safety, the description provides sufficient context: it states the operation, return structure, final total row entry, and failure format. No critical information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, datamodel_name, has 100% schema description coverage ('Name of the data model.'). The description adds no new parameter-level detail, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Retrieve the row count for each table in a specific data model.' It is clearly distinct from siblings like datamodel_get_data or datamodel_get_all_datamodel, but it does not explicitly differentiate itself from similar sibling tools, so it misses the top score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is implied: call this when you need per-table row counts for a named data model. However, there is no explicit when-not-to-use guidance or mention of alternatives such as datamodel_describe_datamodel or datamodel_get_table_schema for schema-level needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamodel_get_table_schemadatamodel.get_table_schemaARead-only
Retrieve the schema of a table within a connection's data source. Resolves the connection by name to obtain its oid and provider, then sends POST /api/v1/connection/{id}/table_schema_details.
Returns: dict[str, Any] Table schema details if found, or {"error": "..."} on failure or when no schema is found.
Note: This endpoint is undocumented and may change in future Sisense versions. Use with caution.
| Name | Required | Description | Default |
|---|---|---|---|
| table_name | Yes | Name of the table (sent as ``table``). | |
| schema_name | Yes | Name of the schema (sent as ``schema``). | |
| database_name | Yes | Name of the database (sent as ``Database``). | |
| connection_name | Yes | Name of the connection. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint, openWorldHint, and destructiveHint. The description goes well beyond that by disclosing the POST endpoint, the connection resolution process, the exact return contract (dict or error), and a caution that the endpoint is undocumented and may change. This is substantial behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences deliver purpose+mechanism, return value, and a risk warning with no filler. The key facts are front-loaded and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers what the tool does, how it executes (connection resolution + POST), what it returns on success and failure, and a stability warning. With readOnly and non-destructive annotations covering the safety profile, nothing essential is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents all four parameters with descriptions and wire-name mappings, so schema coverage is 100%. The description adds no additional parameter-level meaning beyond the schema's own documentation, making baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Retrieve the schema of a table within a connection's data source,' a specific verb+resource statement. It also names the exact API endpoint and scope, distinguishing it from sibling tools like datamodel_get_model_schema, which targets model-level schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: this is for retrieving table schema from a connection's data source, and it explains the resolution flow via connection_name. However, it does not explicitly state when to prefer this over datamodel_get_model_schema or datamodel_describe_datamodel, nor does it mention exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
folder_get_all_foldersfolder.get_all_foldersARead-only
Retrieve the full folder tree. Convenience wrapper for get_folders("tree"). Returns the nested folder hierarchy used by Sisense for organizing dashboards.
Returns: list[dict[str, Any]] | dict[str, Any] A list of root-level folder nodes (each may contain nested folders and dashboards keys), or {"error": "..."} on failure.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral detail about the return shape, including nested 'folders' and 'dashboards' keys and the error dict on failure, which is beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: one explanatory sentence, one wrapping-context sentence, and a compact return-type breakdown. Every sentence adds information, and the main purpose is front-loaded rather than buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only convenience tool with no output schema, the description is complete: it states what the tool returns, how the hierarchy is organized, and what the failure shape looks like. An agent has everything needed to decide whether to call it and to interpret its result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is no parameter semantics burden on the description. Per the baseline rule, a score of 4 applies because no parameter documentation is needed; the description appropriately focuses on the return value instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Retrieve the full folder tree.' It further clarifies the returned nested hierarchy and names the underlying convenience wrapper, making the tool's purpose unmistakable and distinct from sibling folder_get_folder_id, which targets a specific folder.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states this is the tool for retrieving the complete folder tree and identifies it as a convenience wrapper for get_folders("tree"), which implies the common use case. It does not explicitly state when not to use it or compare it to folder_get_folder_id, but the usage context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
folder_get_folder_idfolder.get_folder_idARead-only
Retrieve a single folder by OID. Sends GET /api/v1/folders/{folder_id} and returns the folder metadata object.
Returns: dict[str, Any] Folder metadata from the API, or {"error": "..."} if the request fails or no folder is found.
| Name | Required | Description | Default |
|---|---|---|---|
| folder_id | Yes | OID of the folder to retrieve. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds useful behavioral detail by naming the HTTP endpoint (`GET /api/v1/folders/{folder_id}`) and disclosing the exact return behavior, including the error shape when the request fails or no folder is found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: it states the core action, the endpoint, and the return format in three short sentences. There is no filler or redundant content beyond what is useful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read-only tool with no output schema, the description is complete. It provides the parameter, endpoint, return type, and failure behavior, giving an agent everything needed to invoke it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the description repeats the parameter's role ('by OID') without adding significant new meaning. It does place the parameter in the endpoint URL, which adds mild context, but the schema already fully documents folder_id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Retrieve'), a resource ('a single folder'), and the key identifier ('by OID'). It clearly distinguishes this tool from sibling folder_get_all_folders by emphasizing single-folder retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies when to use the tool: when you have a folder OID and need a single folder's metadata. It does not explicitly mention alternatives or exclusions, but the contrast with folder_get_all_folders is evident from the language and context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plugins_get_all_pluginsplugins.get_all_pluginsARead-only
Retrieve all plugins installed on the Sisense instance. Fetches the complete plugin list using paginated requests to GET /api/v1/plugins. All pages are collected and returned as a single flat list.
Returns: list[dict[str, Any]] A list of plugin objects, each containing at minimum: - name (str): API identifier for the plugin. - folderName (str): Filesystem folder name (e.g. "plugin-MyPlugin"). - isEnabled …
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly and destructive annotations, the description reveals meaningful behavior: paginated requests to GET /api/v1/plugins, collection of all pages, and return as a single flat list. It also documents minimum fields in the return objects, though it stops short of describing error or empty-list behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the purpose, followed by pagination behavior and a concise bulleted return contract. Every sentence carries useful information and the bullet list makes the return fields easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless, read-only list operation, the description sufficiently covers purpose, pagination, aggregation behavior, and return shape. The explicit Returns section compensates for the absence of an output schema, and the annotations already cover the safety profile.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema confirms an empty properties object, so the 0-parameter baseline of 4 applies. The description appropriately focuses on behavior and return shape rather than inventing parameter details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific operation: 'Retrieve all plugins installed on the Sisense instance.' It reinforces scope with 'complete plugin list' and the exact API endpoint, making it easy to distinguish from sibling tools focused on dashboards, datamodels, folders, and reports.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context by explicitly saying it retrieves all plugins and that all pages are collected, so an agent knows to call this when the full plugin list is needed. It does not name alternatives, but no plugin-specific sibling appears in the provided tool list, so explicit exclusions are less necessary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
report_manager_get_reportsreport_manager.get_reportsARead-only
Retrieve all reports configured in Report Manager. Sends paginated requests to GET /api/v1/report_manager/reports and collects every page into a single flat list. Filters are applied server-side.
Returns: list[dict[str, Any]] | dict[str, Any] A flat list of report objects, or {"error": "..."} on failure.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | No | One or more report ids to filter by. A bare string is treated as a single id. | |
| name | No | Search reports by name. | |
| sort | No | Field to sort results by. Ascending by default, descending if prefixed with ``-``. | |
| limit | No | Page size used for the underlying paginated requests. Default is ``100``. | |
| fields | No | Whitelist of fields to return for each report. Fields can also be excluded by prefixing their name with ``-``. | |
| enabled | No | When provided, filter to only enabled (``True``) or disabled (``False``) reports. | |
| priority | No | Filter reports by priority. One of ``"high"``, ``"normal"``. | |
| statuses | No | One or more running statuses to filter by. A bare string is treated as a single status. | |
| owner_ids | No | One or more owner user ids to filter by. A bare string is treated as a single id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only annotation, the description discloses pagination behavior ('sends paginated requests... collects every page'), server-side filtering, and the failure return shape ({'error': ...}). This tells the agent not to expect partial pages and how failures surface.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded: purpose first, then pagination/behavior, then return shape. No sentence is wasted; the endpoint URL and return line add practical detail without bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description fully specifies the return type ('list[dict[str, Any]] | dict[str, Any]') and the error shape. Combined with the read-only annotation and comprehensive schema, nothing essential is missing for an agent to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with every parameter documented in the input schema. The description adds only a general statement that filters are applied server-side, which is a behavioral note rather than parameter-level semantics, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a concrete verb and resource ('Retrieve all reports configured in Report Manager') and adds behavioral specificity (paginated requests, flat list). It clearly distinguishes this tool from the dashboard/datamodel/folder/plugin getters among the siblings by naming the Report Manager resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context for when to call it: any time all reports (optionally filtered) are needed, with filters applied server-side. It does not explicitly name alternative tools or list exclusions, but no overlapping report-management siblings exist, so the context is sufficient for an agent to select it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wellcheck_run_full_wellcheckwellcheck.run_full_wellcheckARead-only
Run a composite "full" wellcheck across dashboards and data models. This method is a convenience wrapper that orchestrates multiple dashboard-level and data-model-level checks and returns a structured report that groups their results. It additionally delegates unused-column analysis to AccessManagement.get_unused_columns_bulk when an AccessManagement instance is configured on this WellCheck (the default constructor configures one); otherwise the unused_columns section is an empty list and a warning is logged.
Returns: dict A dictionary with two top-level sections: - "dashboards": { "structure": [...], "widget_counts": [...], "pivot_widget_fields": [...], } - "datamodels": { "custom_tables": [...], "island_tables": [...], …
Can be slow: the m2m check runs real aggregate SQL. Scope it with the dashboards/datamodels parameters whenever the user named specific assets.
| Name | Required | Description | Default |
|---|---|---|---|
| dashboards | No | One or more dashboard references to analyze. Each reference can be: - a Sisense dashboard ID, or - a dashboard title (name). At runtime this parameter is tolerant of a single string and will normalize it to a one-element list. | |
| datamodels | No | One or more data model references to analyze. Each reference can be: - a data model ID, or - a data model title (name). At runtime this parameter is tolerant of a single string and will normalize it to a one-element list. | |
| max_pivot_fields | No | Threshold used by the pivot-fields check. Any pivot widget with more than this number of fields is flagged. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/destructiveHint annotations, the description discloses meaningful runtime behavior: the tool can be slow, the m2m check executes real SQL, unused-column analysis is conditionally delegated to AccessManagement.get_unused_columns_bulk, and the default constructor configures AccessManagement with a fallback empty list and warning. This is substantial behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is information-dense but well-organized: purpose first, then behavior, then return shape, then a practical performance caveat at the end. Every sentence adds value, especially given there is no output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a composite tool with no output schema, the description provides sufficient context: what it does, how it behaves conditionally, what the return structure looks like, and when scoping is needed. The schema covers the optional parameters, and annotations cover the read-only safety profile.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already fully documents the parameters' meaning, formats, and normalization behavior. The description only reinforces scoping via the dashboards/datamodels parameters without adding new semantic detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb ('Run a composite full wellcheck') and a resource ('across dashboards and data models'). It distinguishes itself from sibling getter tools by framing it as an orchestration wrapper that groups multiple checks into one structured report.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides concrete guidance on scoping: 'Scope it with the dashboards/datamodels parameters whenever the user named specific assets.' It also warns about slowness due to real aggregate SQL. It does not explicitly name alternative sibling tools, so it falls just short of full when-to-use versus alternatives guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
48 tool updates
v0.1.2- Removed
access_management_get_group - Added
access_management_get_groups - Removed
access_management_get_unused_columns - Changed
access_management_get_unused_columns_bulk2 fields changed- changed
Input schema / properties / datamodels / descriptionPrevious value: -"One or more data model references to analyze. Each reference can be: - a data model ID, or - a data model title (name). At least one data model reference is required. At runtime this parameter is tolerant of a single string and will normalize it to a one-element list."New value: +"One or more data model references to analyze. **Required.** Each reference can be: - a data model ID, or - a data model title (name). At runtime this parameter is tolerant of a single string and will normalize it to a one-element list." - changed
Input schema / requiredPrevious value: -[]New value: +[ + "datamodels" +]
- Changed
access_management_get_user1 field changed- changed
Input schema / properties / user_email / descriptionPrevious value: -"Email address of the user to retrieve."New value: +"Email address of the user to retrieve. **Required** — this method always answers \"one named user\"; use ``get_users_all`` for every user."
- Removed
access_management_get_user_with_role_and_group_names - Removed
access_management_get_users_with_role_names_and_group_names - Changed
access_management_users_per_group2 fields changed- changed
Input schema / properties / group_name / descriptionPrevious value: -"The name of the group whose members to list."New value: +"The name of the group whose members to list. Omit for all memberships. A name that matches no group returns ``{\"error\": \"...\"}`` naming it — never a silent empty list. Naming ``Everyone`` or ``All users in system`` returns their members — an explicit request is always honored, even though the all-groups view omits them." - changed
Input schema / requiredPrevious value: -[ - "group_name" -]New value: +[]
- Removed
access_management_users_per_group_all - Removed
blox_get_blox_actions - Removed
custom_code_export_notebook - Removed
custom_code_get_notebooks - Removed
custom_code_list_notebook_folder_contents - Removed
dashboard_export_dashboard - Added
dashboard_find_widgets_by_type - Removed
dashboard_get_dashboard_by_name - Removed
dashboard_get_dashboard_shares_v1 - Removed
dashboard_get_dashboard_widgets - Added
dashboard_get_widget_by_id - Removed
dashboard_resolve_dashboard_reference - Removed
datamodel_describe_datamodel_raw - Changed
datamodel_generate_connections_payload5 fields changed- added
Input schema / properties / connection_params / additionalPropertiesAdded value: +true - added
Input schema / properties / connection_params / propertiesAdded value: +{ + "additional_parameters": { + "type": "string" + }, + "allow_large_results": { + "type": "boolean" + }, + "aws_access_key": { + "type": "string" + }, + "aws_secret_key": { + "type": "string" + }, + "connection_string": { + "type": "string" + }, + "database": { + "type": "string" + }, + "default_database": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "password": { + "type": "string" + }, + "record_field_flattening_level": { + "type": "string" + }, + "region": { + "type": "string" + }, + "s3_output_location": { + "type": "string" + }, + "schema": { + "type": "string" + }, + "server": { + "type": "string" + }, + "service_account_key_path": { + "type": "string" + }, + "token": { + "type": "string" + }, + "unnest_arrays": { + "type": "boolean" + }, + "use_dynamic_schema": { + "type": "boolean" + }, + "use_proxy_server": { + "type": "boolean" + }, + "use_service_account": { + "type": "boolean" + }, + "use_storage_api": { + "type": "boolean" + }, + "username": { + "type": "string" + } +} - added
Input schema / properties / connection_params / requiredAdded value: +[] - changed
Input schema / properties / datasource_type / descriptionPrevious value: -"Type of data source. One of ``\"Athena\"``, ``\"RedShift\"``, ``\"BigQuery\"``, ``\"DataBricks\"`` (case-insensitive)."New value: +"Type of data source (matched case-insensitively)." - added
Input schema / properties / datasource_type / enumAdded value: +[ + "Athena", + "RedShift", + "BigQuery", + "DataBricks" +]
- Removed
datamodel_get_connections - Added
datamodel_get_connections_all - Removed
datamodel_get_datamodel - Removed
datamodel_get_datasecurity - Removed
datamodel_load_datamodel - Removed
datamodel_resolve_datamodel_reference - Removed
folder_get_folder_ancestors - Removed
folder_get_folders - Removed
folder_get_navver - Removed
metadata_get_datasource_dimensions - Removed
metadata_get_datasource_measures - Removed
metadata_get_datasources - Removed
plugins_get_plugin - Removed
plugins_save_snapshot - Removed
queries_elasticube_run_jaql_query - Removed
queries_elasticubes_run_jaql_csv - Added
report_manager_get_reports - Removed
wellcheck_check_dashboard_structure - Removed
wellcheck_check_dashboard_widget_counts - Removed
wellcheck_check_datamodel_custom_tables - Removed
wellcheck_check_datamodel_import_queries - Removed
wellcheck_check_datamodel_island_tables - Removed
wellcheck_check_datamodel_m2m_relationships - Removed
wellcheck_check_datamodel_rls_datatypes - Removed
wellcheck_check_pivot_widget_fields - Added
wellcheck_run_full_wellcheck
68 tool updates
v0.1.0- First observed
access_management_get_all_dashboard_shares - First observed
access_management_get_datamodel_columns - First observed
access_management_get_group - First observed
access_management_get_my_user - First observed
access_management_get_roles - First observed
access_management_get_unused_columns - First observed
access_management_get_unused_columns_bulk - First observed
access_management_get_user - First observed
access_management_get_user_with_role_and_group_names - First observed
access_management_get_users_all - First observed
access_management_get_users_with_role_names_and_group_names - First observed
access_management_users_per_group - First observed
access_management_users_per_group_all - First observed
blox_get_blox_actions - First observed
custom_code_export_notebook - First observed
custom_code_get_notebooks - First observed
custom_code_list_notebook_folder_contents - First observed
dashboard_can_be_owned - First observed
dashboard_export_dashboard - First observed
dashboard_get_all_dashboards - First observed
dashboard_get_dashboard_by_id - First observed
dashboard_get_dashboard_by_name - First observed
dashboard_get_dashboard_columns - First observed
dashboard_get_dashboard_script - First observed
dashboard_get_dashboard_share - First observed
dashboard_get_dashboard_shares_v1 - First observed
dashboard_get_dashboard_widgets - First observed
dashboard_get_dashboards - First observed
dashboard_get_widget_script - First observed
dashboard_resolve_dashboard_reference - First observed
datamodel_describe_datamodel - First observed
datamodel_describe_datamodel_raw - First observed
datamodel_generate_connections_payload - First observed
datamodel_get_all_datamodel - First observed
datamodel_get_connection - First observed
datamodel_get_connections - First observed
datamodel_get_data - First observed
datamodel_get_datamodel - First observed
datamodel_get_datamodel_shares - First observed
datamodel_get_datasecurity - First observed
datamodel_get_datasecurity_detail - First observed
datamodel_get_elasticubes - First observed
datamodel_get_model_schema - First observed
datamodel_get_row_count - First observed
datamodel_get_table_schema - First observed
datamodel_load_datamodel - First observed
datamodel_resolve_datamodel_reference - First observed
folder_get_all_folders - First observed
folder_get_folder_ancestors - First observed
folder_get_folder_id - First observed
folder_get_folders - First observed
folder_get_navver - First observed
metadata_get_datasource_dimensions - First observed
metadata_get_datasource_measures - First observed
metadata_get_datasources - First observed
plugins_get_all_plugins - First observed
plugins_get_plugin - First observed
plugins_save_snapshot - First observed
queries_elasticube_run_jaql_query - First observed
queries_elasticubes_run_jaql_csv - First observed
wellcheck_check_dashboard_structure - First observed
wellcheck_check_dashboard_widget_counts - First observed
wellcheck_check_datamodel_custom_tables - First observed
wellcheck_check_datamodel_import_queries - First observed
wellcheck_check_datamodel_island_tables - First observed
wellcheck_check_datamodel_m2m_relationships - First observed
wellcheck_check_datamodel_rls_datatypes - First observed
wellcheck_check_pivot_widget_fields
TDQS
Scored across 36 tools
The domain prefixes and resource nouns separate most tools, but several pairs overlap in obvious ways: get_all_dashboards vs get_dashboards, get_all_datamodel vs get_elasticubes, and get_connection vs get_connections_all require close reading of descriptions to disambiguate. The shared read-only 'get everything' pattern across access, dashboards, and datamodels adds selection risk, so the boundaries are not crisp enough for a higher score.
The dominant pattern is domain_prefix_get_resource, and snake_case is used throughout, which makes the set feel predictable. Deviations like access_management_users_per_group, dashboard_can_be_owned, datamodel_describe_datamodel, datamodel_generate_connections_payload, and wellcheck_run_full_wellcheck break the pattern, and singular/plural forms like get_connection vs get_connections_all are inconsistent.
With 36 tools, this server is well above the 25-tool threshold for a heavy surface. The broad read-only scope would feel more manageable if consolidated into fewer aggregate tools per domain, but as-is the agent will carry a large tool list for what is largely a retrieval/wellcheck server.
The tool surface is almost entirely read-only: nearly every tool is a getter plus a single wellcheck runner. There are no create, update, delete, or ownership-changing operations, and datamodel_generate_connections_payload mentions create_connections without actually exposing that tool, creating a clear dead end. Agents can inspect the Sisense instance but cannot act on it.
Maintenance
Related MCP Connectors
Access Oi Contexts, Workflows, Skills, Guardrails, Connections, and reporting tools.
Read AI-gateway analytics, configs, virtual keys, workspaces and users; log request feedback.
Manage API keys, identities, permissions, rate-limit overrides and verification analytics.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Related MCP Servers
FlicenseNot gradedqualityCmaintenanceEnables AI agents and users to interact with the Britive platform for dynamic access, query configurations, reporting, and access activity.1-- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Dynamics 365 Business Central environments through natural language commands, including environment, app, session, and extension management.20 npm11MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to interact with OSDU platform services including search, data management, and schema operations.8Apache 2.0
- AlicenseAqualityAmaintenanceEnables AI clients to check status, read non-secret settings, schedules, and subject rules, and—when explicitly allowed—update settings and existing subject rules. It also supports local diagnostic workflows while excluding passwords, credentials, arbitrary SQL, files, and shell commands.61MIT