omni-app-mcp
An MCP server that puts the whole Omni REST API in front of an LLM client over stdio — users, groups and permissions, connections and dbt, models and model YAML, git branches and pull requests, content validation, documents (v1 and v2), folders and labels, queries returning decoded Apache Arrow results, dashboards, schedules, AI jobs, routines, evals and credit governance — as typed, self-documenting tools that return markdown or JSON. Every tool maps to one documented API operation, carries a docstring written for a model choosing what to call, and never raises.
Why this exists
Omni ships its own MCP server, and it is good at what it is built for: a remote, OAuth-authenticated, query-focused server that turns natural language into scoped queries against a model and topic. It is deliberately narrow — analysis, not administration.
This project covers the other half. It runs locally over stdio against the REST API, so an agent can administer, model, validate and publish: branch a model, edit its YAML with checksum conflict detection, validate it, open the pull request, merge the branch, sync git; find every document still pointing at a renamed field and fix them; provision users, groups and model roles; wire dbt; publish document drafts; run and pause schedules; audit AI credit limits.
The two are complementary and can be installed side by side — see docs/comparison.md for an honest side-by-side.
Quick start
Once published on PyPI:
uvx omni-app-mcp
Until then, run it straight from the repository:
uvx --from git+https://github.com/trustxai/omni-mcp omni-app-mcp
The PyPI distribution and console script are both omni-app-mcp (the bare omni-mcp name is not
available on PyPI); the repository keeps its name.
The server speaks stdio only and needs two environment variables: your instance URL and an API key.
This is an independent open-source project. It is not affiliated with, endorsed by, or supported by Omni.
| Variable | Required | Default | Description |
|---|---|---|---|
OMNI_BASE_URL |
yes | — | Your instance URL, e.g. https://your-instance.omniapp.co. A trailing /api is accepted and normalised. |
OMNI_API_KEY |
yes | — | Organization API key or Personal Access Token, sent as Authorization: Bearer. |
OMNI_REQUEST_TIMEOUT_SECONDS |
no | 60 |
Per-request timeout in seconds. |
OMNI_MAX_RETRIES |
no | 3 |
Extra attempts on 429 (honouring Retry-After) and 502/503/504. |
OMNI_MAX_RESULT_CHARS |
no | 900000 |
Result-size budget in UTF-8 bytes; longer results are truncated with a visible marker, keeping them under the MCP 1 MB limit. |
Getting an API key
Two kinds of credential work, and which one you pick decides what the tools can reach (see the API authentication docs):
- An Organization API key — Settings → API access → Organization keys. Organization Admin only, and it is what unlocks the whole surface.
- A Personal Access Token — generate it under Profile → Manage account → Generate token; once created it is listed under Settings → API access → Personal tokens. A PAT acts as a single user and carries that user's permissions.
A PAT covers the large majority of tools, but the API bars it from a documented set of endpoints,
which answer 403:
- SCIM-backed user and group management —
omni_list_users,omni_create_user,omni_create_user_group,omni_update_user_groupand their siblings. - Any tool that takes a
user_idto act on another user's behalf (several AI tools do). - Document export and import —
omni_export_dashboard,omni_import_dashboard. - Email-only user management —
omni_manage_email_only_user,omni_bulk_manage_email_only_users.
Use an Organization API key for those. The API is rate limited to 60 requests per minute per
key, and instances can ask Omni to raise it (up to 500 requests/minute is documented); the client
honours Retry-After either way. Start a session with omni_health_check to confirm the key works
and omni_whoami to see exactly what it can reach.
Client configuration
Claude Code
claude mcp add omni \
--env OMNI_BASE_URL=https://your-instance.omniapp.co \
--env OMNI_API_KEY=your-key \
-- uvx omni-app-mcp
Claude Desktop
claude_desktop_config.json:
{
"mcpServers": {
"omni": {
"command": "uvx",
"args": ["omni-app-mcp"],
"env": {
"OMNI_BASE_URL": "https://your-instance.omniapp.co",
"OMNI_API_KEY": "your-key"
}
}
}
}
Cursor
.cursor/mcp.json:
{
"mcpServers": {
"omni": {
"command": "uvx",
"args": ["omni-app-mcp"],
"env": {
"OMNI_BASE_URL": "https://your-instance.omniapp.co",
"OMNI_API_KEY": "your-key"
}
}
}
}
Any stdio MCP client
The generic shape — a command, its arguments, and the two environment variables:
{
"command": "uvx",
"args": ["--from", "git+https://github.com/trustxai/omni-mcp", "omni-app-mcp"],
"env": {
"OMNI_BASE_URL": "https://your-instance.omniapp.co",
"OMNI_API_KEY": "your-key"
}
}
Docker
No image is published yet; build one locally. The container talks MCP over stdin/stdout, so -i
is required and -t must be omitted.
docker build -t omni-app-mcp .
docker run -i --rm --env-file .env omni-app-mcp
Copy .env.example to .env first. In a client config, the command becomes
docker with args: ["run", "-i", "--rm", "--env-file", "/absolute/path/to/.env", "omni-app-mcp"].
Tools
198 tools across 20 modules. The full generated reference — every tool, its access mode and its one-line description — is in docs/TOOLS.md.
| Module | Tools | Covers | Highlights |
|---|---|---|---|
ai |
11 | AI jobs, conversations, query generation, topic picking, docs search | omni_ask_ai, omni_generate_query, omni_search_omni_docs |
ai_governance |
17 | AI credit controls and usage, model suggestions | omni_get_ai_credit_controls, omni_set_user_ai_credit_limits, omni_list_model_suggestions |
ai_routines_evals |
18 | Scheduled AI routines, eval prompt sets and runs | omni_create_ai_routine, omni_trigger_ai_routine, omni_start_eval_run |
connections |
13 | Database connections, environments, schema refresh schedules | omni_list_connections, omni_update_connection, omni_create_schema_refresh_schedule |
content |
6 | Content search, the content validator, dashboard export/import | omni_validate_content, omni_find_and_replace_content, omni_export_dashboard |
dashboards |
6 | Dashboard downloads (PDF/CSV/…) and dashboard filters | omni_export_dashboard_file, omni_get_dashboard_filters, omni_update_dashboard_filters |
dbt |
9 | dbt configuration, environments, exposures | omni_get_dbt_configuration, omni_create_dbt_environment, omni_get_dbt_exposures |
document_access |
12 | Document permissions, favorites, labels | omni_list_document_access, omni_grant_document_permissions, omni_bulk_update_document_labels |
documents |
13 | Documents v1 — list, read, queries, drafts, move, duplicate, ownership | omni_list_documents, omni_get_document_queries, omni_transfer_document_ownership |
documents_v2 |
7 | Documents v2 — create, draft, patch, publish, read state | omni_create_document_v2, omni_patch_document_draft, omni_publish_document_draft |
folders |
14 | Folders, folder permissions, folder labels, labels | omni_list_folders, omni_create_folder, omni_grant_folder_permissions |
health |
2 | Local diagnostics — configuration and connectivity | omni_health_check, omni_get_api_info |
identity |
6 | Who am I, API tokens, user attribute definitions | omni_whoami, omni_list_api_tokens, omni_list_user_attributes |
model_git |
7 | Git configuration, sync, branch pull requests, merges | omni_sync_model_with_git, omni_create_or_update_model_branch_pull_request, omni_merge_model_branch |
models |
16 | Models, model YAML, validation, schemas, cache, topics | omni_get_model_yaml, omni_update_model_yaml, omni_validate_model |
queries |
3 | Running queries and reading their results | omni_run_query, omni_wait_for_query_results, omni_get_job_status |
schedules |
14 | Scheduled deliveries, alerts, recipients, email-only users | omni_list_schedules, omni_create_schedule, omni_trigger_schedule |
uploads |
4 | CSV uploads (data input tables) | omni_upload_csv, omni_replace_upload_data, omni_list_uploads |
user_groups |
10 | User groups and user/group model roles | omni_create_user_group, omni_assign_user_model_role, omni_get_user_group_model_roles |
users |
10 | Standard, embed and email-only users (SCIM) | omni_list_users, omni_create_user, omni_list_embed_users |
Start with omni_health_check to confirm the key works, and omni_get_api_info to see how the
server is configured.
Workflows
Short, real sequences an agent can run end to end. Tool names are exactly as registered.
Modelling on a branch, then promoting it
omni_list_modelswithinclude: "activeBranches"to see each shared model together with its active branches — ormodel_kind: "BRANCH"plusbase_model_id: <shared model id>to list one model's branches directly.omni_get_model_yamlon the branch — it returns each file with a checksum (this server defaultsinclude_checksumsto true precisely so the write-back is safe).- Edit the YAML, then
omni_update_model_yamlwithfiles(file name → new content) andchecksums(the same file name → the checksumomni_get_model_yamlreturned for it). A checksum mismatch means someone else wrote first; re-fetch rather than overwrite. omni_validate_modelon the branch and fix what it groups by file.omni_create_or_update_model_branch_pull_requestto push the branch and open (or update) the PR, thenomni_merge_model_branchonce it is approved.omni_sync_model_with_gitto bring the shared model back in line with the repository.
Running a query and reading the rows
omni_run_querywith the query definition (model, topic/fields, filters, limit). Results come back as base64 Apache Arrow and are decoded into a markdown table — or raw records withresponse_format: json.- If the query outlives its request, the API returns
408with the job ids still running. Feed them toomni_wait_for_query_results, which polls and returns the rows when they land. omni_get_job_statuscovers the other asynchronous jobs (schema refreshes, for example).
Content governance: rename a field without breaking dashboards
omni_validate_contenton the model — it walks every document and reports broken view, field and topic references, grouped by document.omni_find_and_replace_contentwith the old reference and the new one. It rewrites every document on the model, so read the dry summary before confirming: the tool is marked destructive, and clients that surfacedestructiveHintwill ask.omni_validate_contentagain to confirm the list is empty.omni_search_dashboardsto spot-check the dashboards that referenced the field.
Documents v2 lifecycle
omni_create_document_v2creates and publishes a document in one call.omni_create_draft_and_patch_documentopens a draft on a published document and applies the first patch;omni_patch_document_draftapplies further ones.omni_get_document_draft_statereads back what the draft currently holds — the unpublished counterpart ofomni_get_document_state.omni_publish_document_draftmakes it live. This one is effectively irreversible; publish only after reading the draft state.
Administration: people, roles and deliveries
omni_whoamifirst — it reports the key's scope, org role and per-model permissions, which tells you immediately whether SCIM tools will work.omni_list_users/omni_create_userandomni_create_user_group/omni_replace_user_groupto provision people and groups (Organization API key required).omni_assign_user_model_roleandomni_assign_user_group_model_roleto grant model access,omni_get_user_model_rolesto audit it.omni_list_schedulesto review deliveries,omni_create_scheduleto add one,omni_pause_schedule/omni_resume_scheduleto hold it, andomni_trigger_scheduleonly when you mean it — that sends a real delivery to real recipients.
Safety notes
- Destructive tools say so. Every tool ships MCP
ToolAnnotations; deletes, merges, publishes and anything irreversible carrydestructiveHint, reads carryreadOnlyHint. Clients that prompt on destructive tools will prompt on these. - Secrets are never echoed. Connection passwords, deploy private keys, SFTP passwords, webhook secrets and CSV payloads never appear in a tool result. Tools report whether a credential is configured, never its value.
- Rate limits are handled. 60 requests/minute per key (raisable on request, up to a documented
500); the client honours
Retry-Afteron429and backs off on502/503/504automatically. - Results stay under the 1 MB MCP limit. Everything goes through a byte-budgeted truncator that
leaves a visible marker rather than silently cutting; tune it with
OMNI_MAX_RESULT_CHARS. - Binary downloads go to disk. Dashboard PDFs, CSVs and other binaries are written to the
output_pathyou supply and never inlined into the result; the tools refuse to overwrite an existing file unless you ask. - The key is the boundary. This server adds no permissions. Row-level security, model roles and content permissions apply exactly as they do in the app.
Development
uv sync --group dev
uv run pre-commit install
uv run pytest -m "not live"
uv run ruff check src/ tests/ scripts/
uv run ruff format --check src/ tests/ scripts/
uv run mypy src/
uv run python scripts/tool_table.py
Live tests (-m live) run against a real instance and are skipped unless OMNI_API_KEY is set;
copy .env.example to .env to enable them. CONTRIBUTING.md is the contract
every tool module follows — naming, annotations, docstring sections, pagination, error handling —
and reading it once makes review short.
Roadmap
- An embed URL signing helper, so embed sessions can be produced without leaving the agent.
- More convenience workflows layered over the existing tools (a modelling promote-and-validate
loop, a content-migration wrapper), in the shape of
omni_ask_aiandomni_export_dashboard_file.
License
Apache-2.0 — see LICENSE.
Metadata
Release files for omni-app-mcp 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| omni_app_mcp-0.2.1.tar.gz | 402.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| omni_app_mcp-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 644.9 kB
Release files / omni_app_mcp-0.2.1.tar.gz
| Download URL | omni_app_mcp-0.2.1.tar.gz |
|---|---|
| Size | 402.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a1a85dcb46cf876df8f22148fcb811246d82134a850631ee80a94d1f6985f54c
|
|
BLAKE2b-256 checksum How to use checksums |
d201b329c8c1e75d947aa0cbff38c0a45eb285c5ea3bbce6218fc5196a85e223
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / omni_app_mcp-0.2.1-py3-none-any.whl
| Download URL | omni_app_mcp-0.2.1-py3-none-any.whl |
|---|---|
| Size | 242.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9970a0866beca500ad4623fa1a6fbeca11fda83047a28510ae9f03141ada88b4
|
|
BLAKE2b-256 checksum How to use checksums |
450c9c3d5dbf4b2822c0e65f176ca06ac8fa0f4a8170117a985af3e821f96a2a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|