Knowi exposes a Model Context Protocol (MCP) server that lets external AI tools - Claude, Cursor, Copilot, or any MCP-compatible client - operate Knowi programmatically. Instead of navigating the UI, your AI assistant creates dashboards, queries data, exports results, and manages reports through natural language.
The MCP server runs within Knowi's application server. No additional services to deploy.
For connecting AI tools, see the setup guides: Claude Code | Cursor | VS Code | ChatGPT | Codex CLI
Authentication
The MCP server supports three authentication methods.
Option 1: OAuth Browser Auth (Recommended)
MCP clients that support OAuth 2.1 (Claude Code, Cursor, VS Code, Codex CLI) can connect with a one-click browser flow - no manual token copy/paste needed.
- Add Knowi as an MCP server in your AI tool using just the URL (no token required).
- When you first use the connection, the AI tool opens your browser to Knowi's login page.
- Log in (if not already signed in) and click Allow on the consent page.
- Done. The AI tool receives a long-lived token automatically and stores it - no repeated auth until the token expires (1 year).
Under the hood, this uses OAuth 2.1 with PKCE:
- The AI tool discovers Knowi's OAuth endpoints via
GET /.well-known/oauth-authorization-server - Authorization uses
response_type=codewithcode_challenge_method=S256 - The token endpoint exchanges the code + PKCE verifier for a 1-year MCP bearer token
- No client secret needed - security comes from PKCE
Knowi App development is available when Apps is enabled for the account and the signed-in user's role permits it. The consent page discloses that App changes may write commits to a repository already authorized by the customer in Knowi.
See each client's setup guide for the exact configuration.
Option 2: MCP Token (Manual)
If your MCP client doesn't support OAuth, or you prefer manual token management, generate a long-lived MCP token from the Knowi UI.
- Log into Knowi.
- Navigate to Settings > AI Settings.
- Under MCP Token, select an expiry period and click Generate Token.
- Copy the token and paste it into your AI tool's configuration.
Use the token as a Bearer token in all MCP requests:
Authorization: Bearer YOUR_MCP_TOKEN
Security: The MCP token is a separate, revocable credential scoped to MCP endpoints only - it cannot access the broader Management API. Generating a new token automatically revokes any previous one. Revoke at any time from AI Settings.
Manual MCP tokens use the same account, role, and App permissions as OAuth tokens.
Option 3: Standard Bearer Token
For short-lived programmatic access, use the standard Management API login:
POST /api/2.0/login
curl -X POST https://www.knowi.com/api/2.0/login \
-H "Content-Type: application/json" \
-d '{"clientId":"YOUR_CLIENT_ID","clientSecret":"YOUR_CLIENT_SECRET"}'
This returns a bearer token that expires after 1 hour. Request a new token when you receive a 401 response.
Standard bearer tokens use the same account, role, and App permissions when calling MCP tools.
Instance URL: While the examples here use https://www.knowi.com, use the URL that matches your Knowi deployment:
-
Knowi Cloud (default):
https://www.knowi.com -
EU Cloud:
https://eu.knowi.com -
On-Premise: Your on-premise Knowi URL (e.g.
https://knowi.yourcompany.com)
Endpoints
All MCP endpoints are at /api/2.0/mcp/.
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/2.0/mcp/health | Health check | No |
| POST | /api/2.0/mcp | Streamable HTTP - all JSON-RPC methods (initialize, tools/list, tools/call) | Yes |
| DELETE | /api/2.0/mcp | Terminate a Streamable HTTP session | Yes |
| GET | /api/2.0/mcp/tools | List all available tools (REST) | Yes |
| GET | /api/2.0/mcp/tools/{toolName} | Get schema for a specific tool (REST) | Yes |
| POST | /api/2.0/mcp/tools/call | Execute a tool (REST) | Yes |
Health Check
curl https://www.knowi.com/api/2.0/mcp/health
Response:
{
"status": "healthy",
"toolCount": 31,
"tools": ["do", "ask", "search", ...],
"activeSessions": 0
}
List Tools
curl -H "Authorization: Bearer YOUR_TOKEN" \ https://www.knowi.com/api/2.0/mcp/tools
Returns an array of tool definitions with name, description, and input schema for each tool.
Call a Tool
Request
POST /api/2.0/mcp/tools/call
curl -X POST https://www.knowi.com/api/2.0/mcp/tools/call \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "list_dashboards",
"arguments": {}
}'
Response
{
"content": [
{"type": "text", "text": "Found 3 dashboards"}
],
"isError": false,
"_meta": {
"executionTimeMs": 245
}
}
Available Tools
The MCP server exposes both AI-powered and deterministic tools.
Knowi App development
knowi_app is one context-efficient tool for Knowi Apps. Its explicit name and schema keep it separate from unrelated software projects in Claude, Codex, or another MCP client.
MCP is the recommended way to build Knowi Apps. For a complete conversation from setup to a published App, follow Build through MCP. The Apps MCP action reference covers tool fields and permissions.
| Action | Required fields | Result |
|---|---|---|
| setup | None | Lists authorized repositories, available source options, and remaining setup requirements. |
| create | name, slug; source or repository option | Creates an App shell. Select an authorized source, omit it when exactly one writable repository is available, or use repository: knowi_managed when setup allows creation. Follow with read and change to save and build the first version. |
| read | appId | Returns current source, parentCommit, the App contract, and recent shared change summaries and notes. |
| change | appId, parentCommit, files, message | Commits the calling assistant's file changes and queues a build. Optional intent and handoff notes are shared with App collaborators. Read again after a source conflict. |
| status | appId; optional jobId | Returns not_built, running, ready, failed, or cancelled and the ready versionId. Checking status never starts a preview. |
| build | appId | Builds the current repository commit without generation. Poll status for the Ready versionId. |
| preview | appId, versionId | Starts a preview of the named Ready version and returns a short-lived URL. Call only when the user requests a preview. |
| publish | appId, versionId, confirm: true | Publishes a Ready version when the user explicitly requests publishing. Returns the App ID and published live URL and status. |
| secret | appId, secret: {name, value} | Saves a secret for App server code to use after the next publish. Removal uses secret: {name, remove: true} with confirm: true. Previews do not receive secrets. |
Builds are asynchronous: call read, write the code in your assistant, submit change, then poll status when done is false. MCP does not invoke Knowi's AI generator. Call preview separately when requested. Call setup first to discover authorized repositories and whether you can create one. Set optional source to an exact repository label returned by setup, or omit it when only one writable repository is available. If none is available, use the repository creation options below when permitted, or ask a Knowi administrator to make one available.
App history records observed commits, builds, and publishes across Claude, Codex, and other MCP clients. Open the App in Knowi and use Commits > Refresh to load changes made by another client. The commit list shows repository commit messages and Git authors; Versions brings together each build and its publication details. Recorded authenticated requesters and publishers are identified separately from Git authors. Refresh preserves your unsent Builder request, selected data, and running preview.
Optional intent and handoff notes are limited to 2,000 characters each, shared with App collaborators, and attached to the resulting commit. They appear in version details, and read identifies notes from earlier commits as stale. Keep private chats and secrets out of these shared notes. Client names, when available, are advisory attribution; the authenticated Knowi user determines permissions. Private conversations in Knowi are separate, and external chat transcripts are not automatically imported.
An App uses the dashboards and datasets selected for it. Describe the data you want so the assistant can find authorized assets and declare their bindings in the app.json file submitted with change. Knowi checks the editor's access for preview and the publisher's access at publication. Live Knowi sign-in Apps apply each viewer's data permissions. Public and App-managed Apps can expose selected dataset results through a grant checked against the publisher's current access and content filters; individual visitors have no Knowi identity. See App access and security.
create can also use repository: "knowi_managed" or repository: "ssh" with remoteUrl; SSH setup returns a deploy key to authorize before retrying with the source. create and change support access and managed-database settings. Publishing requires apps:publish; editing requires apps:edit and the App ACL. Knowi verifies the active connection, account, repository authorization, and action permissions on every call. The tool cannot delete an App, upload built output, or expose repository credentials. A Git host outage blocks new changes and builds but does not stop an already published App version.
After publish, use the returned App ID and declared page paths with create_report or create_alert. For example, an agent can build and publish an operations review, then create a Monday email report for its Overview page. Core owns schedules, recipients, and delivery; the App does not need a scheduler. Calling these MCP tools while building an App is separate from the App's runtime report.send and report.schedule capabilities.
AI-Powered Tools
These tools use the AI orchestrator to interpret natural language and chain multiple operations together.
do
Execute a Knowi operation using natural language. Knowi routes the instruction to the appropriate capability.
| Parameter | Type | Required | Description |
|---|---|---|---|
| instruction | string | Yes | Natural language instruction describing what to do |
| dashboardId | integer | No | Target dashboard ID for dashboard-level operations |
| widgetId | integer | No | Target widget ID for widget-level operations |
Example:
{
"name": "do",
"arguments": {
"instruction": "Create a sales dashboard with revenue trends and top products"
}
}
Note: do blocks destructive operations (delete, remove, drop). Use delete for those.
ask
Ask a data question in natural language. The AI finds the relevant dataset, generates a query, executes it, and returns results.
| Parameter | Type | Required | Description |
|---|---|---|---|
| question | string | Yes | Natural language question about your data |
| datasetIds | array of integers | No | Specific dataset IDs to query. If omitted, the AI searches all accessible datasets. |
Example:
{
"name": "ask",
"arguments": {
"question": "What were total sales last quarter?",
"datasetIds": [456]
}
}
Response includes the executed query, result fields, data rows, and the datasets that were searched.
search
Search across all Knowi assets using keyword or semantic search.
| Parameter | Type | Required | Description |
|---|---|---|---|
| query | string | Yes | Search query |
| assetType | string | No | Filter by type: dashboard, widget, dataset, query, report, alert |
| limit | integer | No | Maximum number of results to return |
Example:
{
"name": "search",
"arguments": {
"query": "customer retention",
"assetType": "dashboard"
}
}
Deterministic Tools
These tools execute specific operations directly without AI interpretation. They are fast and predictable.
list_dashboards
List all dashboards accessible to the authenticated user. No required parameters.
{
"name": "list_dashboards",
"arguments": {}
}
Returns dashboard IDs, names, and widget counts.
get_data
Retrieve data from a widget or dataset.
| Parameter | Type | Required | Description |
|---|---|---|---|
| widgetId | integer | No* | Widget ID to get data from |
| datasetId | integer | No* | Dataset ID to get data from |
| limit | integer | No | Maximum number of rows to return (default 100) |
*One of widgetId or datasetId is required.
get_details
Get full details for any asset.
| Parameter | Type | Required | Description |
|---|---|---|---|
| assetType | string | Yes | Type of asset: dashboard, widget, dataset, query, report, alert, datasource |
| assetId | integer | Yes | ID of the asset |
Returns full metadata including schema (for datasets), widget counts (for dashboards), and configuration details.
find_widget
Find widgets by name, optionally scoped to a dashboard.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Widget name to search for (substring match) |
| dashboardId | integer | No | Limit search to a specific dashboard |
Returns matching widget IDs, names, chart types, and dataset information.
push_data
Push data rows to a dataset. Creates the dataset if it does not exist.
| Parameter | Type | Required | Description |
|---|---|---|---|
| datasetName | string | Yes | Name of the dataset to push data to |
| rows | array of objects | Yes | Data rows to push |
import_file
Import file data (CSV, JSON, XML, or Excel) into a Knowi dataset. Pass inline text for CSV/JSON/XML, or base64-encoded content for Excel. Creates or updates a dataset.
| Parameter | Type | Required | Description |
|---|---|---|---|
| datasetName | string | Yes | Name for the dataset to create or update |
| content | string | No* | Inline file content. Raw text for CSV/JSON/XML; base64-encoded binary for Excel. |
| fileUrl | string | No* | URL to download file from (http/https). Prefer for large files. |
| fileType | string | No | File format: csv, json, xml, or excel. Auto-detected if omitted. |
*One of content or fileUrl is required.
export_pdf
Export a dashboard or widget as a PDF. Returns base64-encoded PDF content.
| Parameter | Type | Required | Description |
|---|---|---|---|
| dashboardId | integer | No* | Dashboard to export |
| widgetId | integer | No* | Widget to export |
*One of dashboardId or widgetId is required.
export_csv
Export a dashboard or widget as CSV. For dashboards, exports all widgets as separate CSV files. Returns base64-encoded content.
| Parameter | Type | Required | Description |
|---|---|---|---|
| dashboardId | integer | No* | Dashboard to export - each widget becomes a separate CSV |
| widgetId | integer | No* | Single widget to export as CSV |
| limit | integer | No | Max rows per widget (default 10000, max 200000) |
*One of dashboardId or widgetId is required.
get_embed_url
Generate an embeddable share URL for a dashboard or widget.
| Parameter | Type | Required | Description |
|---|---|---|---|
| dashboardId | integer | No* | Dashboard to share |
| widgetId | integer | No* | Widget to share |
*One of dashboardId or widgetId is required.
create_widget
Create a visualization on a dataset. Use get_data with a small limit first to inspect field names - the widget will show no data if field names are wrong.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Widget name |
| datasetId | integer | Yes | Dataset to visualize |
| chartType | string | No | Chart type: column, line, bar, pie, donut, area, scatter, heatmap, funnel, treemap, gauge, singletext, datagrid2, recommendation. Default: column |
| xAxis | string | No* | Field name for x-axis (exact field name from dataset). Required for chart types. |
| yAxis | string | No* | Field name for y-axis/value (exact field name from dataset). Required for chart types. |
| groupBy | string | No | Field name for grouping/legend (creates multiple series) |
| series | string | No | Comma-separated metric field names for multiple y-axis series |
| dashboardId | integer | No | Dashboard to add the widget to. If omitted, widget is created standalone. |
update_widget
Update an existing widget's data transformations (filters, aggregations, sorting) and/or display settings (chart type, name). Changes are saved server-side immediately.
| Parameter | Type | Required | Description |
|---|---|---|---|
| widgetId | integer | Yes | ID of the widget to update |
| filters | array of objects | No | Filters to apply. Each: {field, operator (=, !=, >, <, >=, <=, like, in, between), value}. Replaces existing filters. |
| c9ql | string | No | Raw C9QL query to set as data transformation. Replaces the entire transformation if provided. |
| chartType | string | No | New chart type: column, line, bar, pie, donut, area, scatter, heatmap, funnel, treemap, gauge, singletext, datagrid2 |
| widgetName | string | No | New name for the widget |
| xAxis | string | No | New x-axis field (exact field name from dataset) |
| yAxis | string | No | New y-axis field (exact field name from dataset) |
| groupBy | string | No | New group-by/legend field |
create_dashboard
Create a new dashboard, optionally with existing widgets on it. To build a dashboard from scratch, create it here, then call create_widget with the returned dashboardId. If the name is already taken, a number is appended.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Dashboard name |
| widgetIds | array of integers | No | Existing widgets to add, in display order. Placed two per row at the default size. |
layout_dashboard
Set widget positions and sizes on a dashboard. Grid is 24 columns wide.
| Parameter | Type | Required | Description |
|---|---|---|---|
| dashboardId | integer | Yes | Dashboard ID |
| widgets | array of objects | Yes | Widget positions. Each: {widgetId, col (1-24), row (1+), sizeX (1-24), sizeY (1-16)} |
update_dashboard
Rename a dashboard, change its description, or change settings from its Settings panel. An unknown setting name is rejected with the list of valid ones. Custom CSS/JS, header and footer code can't be changed through MCP.
| Parameter | Type | Required | Description |
|---|---|---|---|
| dashboardId | integer | Yes | Dashboard to update |
| name | string | No | New name. Must not match another of your dashboards. |
| description | string | No | New description |
| settings | object | No | Settings as {settingName: value}, e.g. {"locked": true, "enablePdfExport": false}. On/off settings take true or false. |
update_dashboard_filters
Set dashboard-level filters, which apply to every widget on the dashboard that has the field. Each filter replaces the existing dashboard filter on the same field; other filters are kept unless replaceAll is true. Locked filters can't be changed.
| Parameter | Type | Required | Description |
|---|---|---|---|
| dashboardId | integer | Yes | Dashboard to filter |
| filters | array of objects | Yes | Each: {field, operator (=, !=, >, >=, <, <=, in, not in, like, not like, range, is null, is not null; default =), values}. '=' with several values matches any of them; 'range' takes [from, to]. |
| replaceAll | boolean | No | Remove editable filters not listed. With an empty filters array, removes them all. Default: false |
create_datasource
Create a new datasource connection.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Name for the datasource |
| datasourceType | string | Yes | Type: mysql, postgresql, mongo, restapi, csv, snowflake, bigquery, redshift, elasticsearch, etc. |
| host | string | No | Database host |
| port | integer | No | Database port |
| dbName | string | No | Database name |
| dbUser | string | No | Database username |
| dbPassword | string | No | Database password |
create_query
Create a query against a datasource and run it to populate a dataset. Each run replaces the dataset (replace_all) unless overwriteStrategy says otherwise. The query runs once unless frequency and frequencyType schedule it.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Name for the query |
| datasourceId | integer | No* | Datasource to query against |
| datasourceName | string | No* | Datasource name, used when datasourceId is not given |
| queryStr | string | Yes | The query to execute (SQL, Mongo JSON, or the endpoint path for REST / third-party connectors) |
| overwriteStrategy | string | No | How each run writes to the dataset: replace_all (default), replace_all_force, upsert, upsert_by_time, append
|
| overwriteKeys | string | No | Comma-separated key field(s) for upsert / upsert_by_time; the time field carries a retention window, e.g. CustomerID,DateField-3m
|
| frequency | integer | No | Run every N frequencyType units. For weekdays, the digits of the days to run (1=Sunday..7=Saturday, 23456 = Mon-Fri) |
| frequencyType | string | No | Schedule unit: minutes, hours, days, weekdays, weeks, months
|
| startTime | string | No | Schedule anchor: HH:mm (today) or MM/dd/yyyy HH:mm. Default: now |
| timezone | string | No | IANA timezone for startTime. Default: the user's timezone |
| cronConfig | string | No | 5-field cron expression that overrides the frequency timing (frequency and frequencyType still required) |
| runNow | boolean | No | Execute the query immediately (default: true). false saves a draft |
*One of datasourceId or datasourceName is required.
update_query
Update an existing query: rename it, change its query text, set its overwrite strategy or schedule, or run it now. Only the fields passed change. Requires write access to the query.
| Parameter | Type | Required | Description |
|---|---|---|---|
| queryId | integer | Yes | ID of the query to update |
| name | string | No | New query name (also renames its dataset) |
| queryStr | string | No | New query text |
| overwriteStrategy | string | No |
replace_all, replace_all_force, upsert, upsert_by_time, append
|
| overwriteKeys | string | No | Key field(s) for upsert / upsert_by_time
|
| frequency | integer | No | Run every N frequencyType units |
| frequencyType | string | No |
minutes, hours, days, weekdays, weeks, months
|
| startTime | string | No |
HH:mm or MM/dd/yyyy HH:mm
|
| timezone | string | No | IANA timezone for startTime |
| cronConfig | string | No | 5-field cron expression overriding the frequency timing |
| scheduled | boolean | No |
false removes the schedule. Omit to keep it |
| runNow | boolean | No | Run right after saving (default: false). A draft becomes a live query with a new queryId |
get_details with assetType='query' returns the current overwriteStrategy, overwriteKeys, scheduled and schedule so you can confirm what was set.
cloud9ql_assist
Generate, fix, explain, convert, validate, or preview Cloud9QL using your dataset's actual schema and sample rows. Every query the tool returns has been executed against the dataset to confirm it parses and produces output - the response includes a validity flag and a small preview so you know the query works before applying it. Repairs broken Cloud9QL automatically (up to 2 retries) using validator hints. See the Cloud9QL Assistant docs for the in-product equivalent.
| Parameter | Type | Required | Description |
|---|---|---|---|
| mode | string | Yes | One of: `generate`, `fix`, `explain`, `convert`, `validate`, `preview` |
| user_request | string | No | Natural-language prompt (required for `generate`, optional for `fix`) |
| dataset_id | integer | No* | Knowi dataset ID for schema, validation, and preview |
| dataset_hint | string | No* | Dataset name when ID is unknown - the tool will resolve it |
| cloud9ql | string | No | Existing Cloud9QL (required for `fix`, `explain`, `validate`, `preview`) |
| sql | string | No | SQL input for `convert` mode |
| error | string | No | Error message to repair in `fix` mode |
| target_output_shape | string | No | Optional description of expected columns/shape |
| max_preview_rows | integer | No | Maximum preview rows (capped server-side) |
| include_preview_rows | boolean | No | Return the actual preview row data (default false; row count is always returned) |
*One of dataset_id or dataset_hint is required.
Requires the AI_USE_AGENT_ASSISTANT_QUERIES, QUERY_EDIT, and QUERY_CREATE permissions on the calling user's role.
run
Trigger execution of a query or report.
| Parameter | Type | Required | Description |
|---|---|---|---|
| queryId | integer | No* | Query to execute |
| reportId | integer | No* | Report to trigger |
*One of queryId or reportId is required.
create_report
Create a scheduled report that sends a dashboard or widgets via Email, Slack, or Teams. An App schedules reports for its own pages through the report.send and report.schedule capabilities, not through this tool.
| Parameter | Type | Required | Description |
|---|---|---|---|
| dashboardId | integer | No* | Dashboard to include in the report |
| widgetIds | array of integers | No* | Widget IDs to include (for widget-level reports) |
| recipients | string | No | Comma-separated email recipients. At least one delivery channel required. |
| slackName | string | No | Slack channel or config name (e.g. "#general", "sales-team") |
| teamsActionIds | array of integers | No | Teams integration IDs configured in Settings > Notifications |
| frequencyType | string | No | Frequency unit: minutes, hours, days, weeks, months. Default: days |
| frequency | integer | No | Frequency count (default: 1) |
| startTime | string | No | Time of day in HH:mm (24-hour). Default: 08:00 |
| timezone | string | No | IANA timezone. Default: user's timezone |
| dayOfWeek | string | No | Day for weekly reports: MONDAY-SUNDAY. Default: MONDAY |
| dayOfMonth | integer | No | Day of month for monthly reports (1-28). Default: 1 |
| format | string | No | Report format: pdf or image. Default: pdf |
| reportName | string | No | Display name for the report |
| subject | string | No | Email subject line |
| emailBody | string | No | Email body text |
| sendNow | boolean | No | If true, send immediately after creating. Default: false |
| exportCSV | boolean | No | Include CSV data export (widget-level reports only). Default: false |
| includeRecommendations | boolean | No | Include AI recommendations in the report. Default: false |
*One of dashboardId or widgetIds is required.
Example weekly report:
{
"name": "create_report",
"arguments": {
"dashboardId": 42,
"recipients": "leads@example.com",
"reportName": "Weekly operations review",
"frequencyType": "weeks",
"frequency": 1,
"dayOfWeek": "MONDAY",
"startTime": "08:00",
"timezone": "America/Los_Angeles"
}
}
update_report
Update an existing scheduled report's configuration, or pause or resume it. Only specified fields are changed.
| Parameter | Type | Required | Description |
|---|---|---|---|
| reportId | integer | Yes | ID of the report to update |
| frequencyType | string | No | New frequency unit: minutes, hours, days, weeks, months |
| frequency | integer | No | New frequency count |
| startTime | string | No | New time of day in HH:mm (24-hour) |
| timezone | string | No | New timezone (IANA format) |
| recipients | string | No | New comma-separated email recipients (replaces existing) |
| subject | string | No | New email subject line |
| emailBody | string | No | New email body text |
| reportName | string | No | New report name |
| sendNow | boolean | No | Send immediately after updating. Default: false |
| paused | boolean | No | true pauses scheduled sends, false resumes them. Editing other fields leaves a paused report paused. |
create_alert
Create an alert on a dataset. Supports conditional alerts (trigger when a C9QL condition matches), data-not-updated alerts, and query error alerts. Anomaly alert creation is not exposed by this tool.
| Parameter | Type | Required | Description |
|---|---|---|---|
| datasetId | integer | Yes | Dataset to create the alert on |
| alertName | string | Yes | Name for the alert |
| alertType | string | Yes | Type of alert: conditional, data_not_updated, query_error |
| alertCondition | string | No* | Condition that triggers the alert (natural language or C9QL). Required for conditional alerts. |
| recipients | string | No | Comma-separated email addresses for notifications |
| subject | string | No | Email subject for alert notification |
| frequencyType | string | No | Check frequency: minutes, hours, days, months. Default: days |
| startTime | string | No | Time of day to check in HH:mm. Default: 08:00 |
| timezone | string | No | Schedule timezone. Default: user's timezone |
| realtime | boolean | No | If true, evaluates every time the dataset updates. Default: false |
Current result comparison does not provide per-incident delivery tracking, and data attachments remain CSV.
list_alerts
List alerts accessible to the current user. Optionally filter by dataset or widget.
| Parameter | Type | Required | Description |
|---|---|---|---|
| datasetId | integer | No | Filter alerts for a specific dataset |
| widgetId | integer | No | Filter alerts for a specific widget |
test_alert
Test an alert by triggering it immediately. Sends notifications if the condition matches. Results are not recorded in the alert's history.
| Parameter | Type | Required | Description |
|---|---|---|---|
| alertId | integer | Yes | ID of the alert to test |
update_alert
Update an existing alert. Only specified fields are changed.
| Parameter | Type | Required | Description |
|---|---|---|---|
| alertId | integer | Yes | ID of the alert to update |
| alertName | string | No | New name for the alert |
| alertCondition | string | No | New condition (natural language or C9QL) |
| recipients | string | No | New comma-separated email recipients (replaces existing) |
| subject | string | No | New email subject |
| frequencyType | string | No | New check frequency: minutes, hours, days, months |
| startTime | string | No | New time of day in HH:mm |
| timezone | string | No | New timezone (IANA format) |
| realtime | boolean | No | Toggle real-time evaluation on/off |
| paused | boolean | No | true to pause the alert, false to resume |
ingest_document
Ingest a document (PDF, Word, CSV, Excel, images, or text) into Knowi for Q&A and data extraction. Documents are chunked, embedded, and stored for semantic search.
| Parameter | Type | Required | Description |
|---|---|---|---|
| fileUrl | string | No* | URL to download the document from (http/https) |
| content | string | No* | Inline content. Raw text for text/CSV/Markdown; base64-encoded for binary formats (PDF, DOCX, Excel, images). |
| fileName | string | No | File name with extension (e.g. "report.pdf"). Required when using inline content; auto-detected from URL otherwise. |
*One of fileUrl or content is required.
ask_document
Ask a natural language question against ingested documents. Returns an AI-generated answer with source citations.
| Parameter | Type | Required | Description |
|---|---|---|---|
| question | string | Yes | Natural language question to ask |
| documentIds | array of strings | No | Specific document IDs to search. If omitted, searches all documents. Use list_documents to find IDs. |
extract_document_data
Extract structured data from documents into a Knowi dataset. Define the fields to extract - Knowi parses each document and returns structured rows that can be queried and visualized.
| Parameter | Type | Required | Description |
|---|---|---|---|
| fields | string | Yes | Comma-separated field names to extract (e.g. "company_name, contract_value, start_date") |
| extractionPrompt | string | No | Custom prompt guiding extraction (e.g. "Parse dates as YYYY-MM-DD. Contract value should be numeric.") |
| documentIds | array of strings | No | Specific document IDs to extract from. If omitted, uses all documents. |
| detailsDepth | integer | No | Extraction thoroughness 1-20. Higher values examine more content but take longer. Default: 5 |
| datasetName | string | No | Name for the resulting dataset. Auto-generated if omitted. |
list_documents
List documents ingested into the document store. Returns document names and IDs for use with ask/extract/delete tools.
| Parameter | Type | Required | Description |
|---|---|---|---|
| datasourceId | integer | No | Filter by document datasource ID. If omitted, lists all documents. |
| query | string | No | Filter documents by name (partial match) |
delete_document
Delete an ingested document from the vector store. Requires confirmation.
| Parameter | Type | Required | Description |
|---|---|---|---|
| documentId | string | Yes | Document identifier. Use list_documents to find IDs. |
| confirm | boolean | Yes | Must be true to confirm deletion |
get_insights
Generate AI-powered insights and recommendations for a widget or dashboard. Returns observations, trends, anomalies, and actionable recommendations.
| Parameter | Type | Required | Description |
|---|---|---|---|
| widgetId | integer | No* | Widget ID to analyze |
| dashboardId | integer | No* | Dashboard ID to analyze (all widgets) |
| context | string | No | Optional guidance for analysis, e.g. "focus on revenue trends" |
*One of widgetId or dashboardId is required.
explain_lineage
Explain how a Knowi widget, dataset, query, or dashboard is built and what depends on it. Returns the same lineage recipe surfaced in the Data Lineage drawer: upstream sources, transformations, field traces, downstream impact, and any permission redactions.
| Parameter | Type | Required | Description |
|---|---|---|---|
| assetType | string | No* | Type of asset: widget, dataset, query, or dashboard |
| assetId | integer | No* | ID of the asset named by assetType |
| widgetId | integer | No* | Shortcut for assetType=widget |
| datasetId | integer | No* | Shortcut for assetType=dataset |
| queryId | integer | No* | Shortcut for assetType=query |
| dashboardId | integer | No* | Shortcut for assetType=dashboard, or widget context when explaining a widget |
| mode | string | No |
build, impact, or both. Defaults to both. |
| includeFields | boolean | No | Include field-level lineage traces. Defaults to false. |
| includeAi | boolean | No | Generate the AI narrative summary. Defaults to false to avoid extra model cost. |
| fieldName | string | No | Focus the field trace on one column. |
| question | string | No | The original business question that produced the answer being explained. |
*Either assetType + assetId, or one of the shortcut ID params (widgetId/datasetId/queryId/dashboardId), is required.
Example:
{
"name": "explain_lineage",
"arguments": {
"widgetId": 12345,
"mode": "build",
"includeFields": true
}
}
delete
Delete a Knowi asset. This is the only tool that performs destructive operations.
| Parameter | Type | Required | Description |
|---|---|---|---|
| assetType | string | Yes | Type of asset: dashboard, widget, dataset, report, alert |
| assetId | integer | Yes | ID of the asset to delete |
| confirm | boolean | Yes | Must be true to confirm deletion |
All three parameters are required. The confirm parameter must be explicitly set to true.
Semantic Layer Tools
These tools read and manage the Semantic Layer - the business glossary, dataset-level semantics, and how questions resolve against them - programmatically. Editing is subject to the same permissions as the Semantic workspace: Admin for glossary terms, Semantic edit access for dataset semantics.
list_glossary_terms
List the business glossary terms defined for the account. Each term includes its name, definition, aliases, status (Draft or Published), and how many datasets/fields it is mapped to.
| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | No | Filter by term status (Draft or Published) |
| query | string | No | Search terms by name |
| limit | integer | No | Maximum terms to return (default 100, max 500) |
get_glossary_term
Get one business glossary term: its full definition, aliases, and dataset/field mappings.
| Parameter | Type | Required | Description |
|---|---|---|---|
| termId | integer | Yes | ID of the glossary term (from list_glossary_terms) |
define_term
Create or update a business glossary term. The term is saved as a Draft - use publish_term to publish it.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Business term name, e.g. "Customer" or "Net Revenue" |
| definition | string | No | What this term means to the organization |
| aliases | array of strings | No | Other phrases people use for the same meaning. Replaces the term's aliases when provided; omit to leave unchanged. |
| termId | integer | No | ID of an existing term to update (e.g. to rename it) |
Example:
{
"name": "define_term",
"arguments": {
"name": "Customer",
"definition": "A company or individual with at least one paid order.",
"aliases": ["Client", "Buyer"]
}
}
map_term
Map a business glossary term to a dataset, optionally narrowing to specific fields. Existing mappings are preserved; the new mapping is added.
| Parameter | Type | Required | Description |
|---|---|---|---|
| termId | integer | Yes | ID of the glossary term to map |
| datasetId | integer | Yes | ID of the dataset to map the term to |
| fields | array of strings | No | Dataset field names to narrow the mapping to. Omit to map the term to the dataset as a whole. |
publish_term
Publish a Draft business glossary term so it participates in semantic resolution. Publishing is an explicit decision - terms are never published automatically.
| Parameter | Type | Required | Description |
|---|---|---|---|
| termId | integer | Yes | ID of the glossary term to publish |
update_dataset_semantics
Set dataset-level semantics: field synonyms, the primary date field used for date questions, and dataset AI instructions. Omitted settings are left unchanged; pass an empty value to clear a setting.
| Parameter | Type | Required | Description |
|---|---|---|---|
| datasetId | integer | Yes | ID of the dataset to update |
| synonyms | array | No | Field synonyms, e.g. [{"field": "revenue", "synonyms": ["sales", "income"]}]. Replaces all synonyms when provided; an empty array clears them. |
| primaryTimeField | string | No | Date/time field to use for date questions. Must be one of the dataset's date-typed fields; an empty string clears it. |
| aiInstructions | string | No | Dataset-specific AI instructions. An empty string clears them. |
get_semantic_context
Resolve a natural-language question against the semantic layer without running any query. Returns matched business terms, the resolved assets (primary and alternatives) with certification state, the resolution decision (REUSE, ADAPT, or CREATE), the execution disposition (continue, clarify, or block), and any blockers. Use ask to actually execute.
| Parameter | Type | Required | Description |
|---|---|---|---|
| question | string | Yes | Data question to resolve, e.g. "What was net revenue by region last quarter?" |
explain_semantic_resolution
Explain how the semantic layer would resolve a question, without running any query: the candidates considered with relevance scores, why the primary asset was selected, and why alternatives were not (lower relevance, not certified, and so on).
| Parameter | Type | Required | Description |
|---|---|---|---|
| question | string | Yes | Data question to explain resolution for |
Streamable HTTP Transport
MCP-compatible clients (Claude Code, Claude Desktop, Cursor, etc.) connect using the Streamable HTTP transport. This uses a single POST endpoint for all operations - no persistent connection required.
How It Works
Every MCP operation is a standard HTTP request/response. The client sends a JSON-RPC message via POST, and the server returns the result immediately. If the server restarts (e.g., during an update), the client simply retries the next request - no reconnection needed.
Initialize
curl -X POST https://www.knowi.com/api/2.0/mcp \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}}'
Response includes a Mcp-Session-Id header. Send this header on subsequent requests.
Mcp-Session-Id: sh-1
{"jsonrpc": "2.0", "id": 1, "result": {
"protocolVersion": "2024-11-05",
"capabilities": {"tools": {}},
"serverInfo": {"name": "knowi-mcp-server", "version": "1.0.0"}
}}
Call a Tool
curl -X POST https://www.knowi.com/api/2.0/mcp \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: sh-1" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "list_dashboards",
"arguments": {}
}
}'
JSON-RPC Methods
| Method | Description |
|---|---|
| initialize | Client handshake - returns server capabilities and protocol version |
| notifications/initialized | Client confirms initialization (no response, returns 204) |
| tools/list | List all available tools with schemas |
| tools/call | Execute a tool |
Session Management
- The server returns a
Mcp-Session-Idheader on every response - The client sends this header on subsequent requests for session continuity
- Sessions auto-expire after 30 minutes of inactivity
- The client can explicitly terminate a session with
DELETE /api/2.0/mcp(include theMcp-Session-Idheader) - If the server restarts, old sessions expire - the client automatically gets a new session on the next request
Security
Authentication Flow
MCP Token (recommended for MCP clients):
- The user generates an MCP token from Settings > AI Settings > MCP Token in the Knowi UI.
- Knowi revokes any existing MCP token for the user and creates a new long-lived token (configurable: 30 days to 1 year).
- The user copies the token into their MCP client configuration (e.g., Claude Code, Claude Desktop) as a
Bearertoken. - Knowi validates the token, confirms that it is scoped to MCP endpoints, and establishes the associated user and permissions for the request.
- If the token is compromised, the user revokes it from AI Settings and generates a new one. No other credentials are affected.
Standard Bearer Token (for programmatic use):
- The client sends a login request with
clientIdandclientSecrettoPOST /api/2.0/login. - Knowi returns a bearer token valid for 1 hour.
- When the token expires, the client must obtain a new one.
All tokens are tied to a specific user and inherit that user's full permission set. Tokens grant the same access as the user logging in through the UI.
Authorization
Every tool applies the authenticated user's current account and resource permissions. Requests for another organization or an unauthorized asset are denied. Resources created through MCP belong to the authenticated user's organization.
Data Flow and AI Provider Implications
Understanding what data is sent where is critical for security evaluation. When using the MCP server, there are two separate data flows:
Flow 1: Tool responses to the MCP client. Every tool - deterministic and AI-powered - returns results to the calling MCP client (e.g., Claude Code, Claude Desktop, Cursor). These results may contain actual data rows, dashboard metadata, field names, and generated insights. The client's LLM sees this data. For example, if you ask Claude Code to get data from a widget, the data rows are returned to Claude, which runs on Anthropic's infrastructure. This is inherent to MCP - the client must receive the results to act on them.
Flow 2: Knowi AI processing. AI-powered tools (do, ask, search) additionally send data to Knowi's configured AI model for reasoning (SQL generation, chart type selection, etc.). Where this data goes depends on the configured provider:
- Knowi In-House AI: Data stays within Knowi's infrastructure for AI processing.
- OpenAI / Anthropic: Data is also sent to the external provider's API.
See AI Model Providers to configure the provider Knowi uses.
Deterministic tools (list_dashboards, get_data, push_data, etc.) do not invoke any AI model on Knowi's side - they execute directly against Knowi's services. However, their results are still returned to the MCP client.
What the AI model on Knowi's side receives (Flow 2 only):
| Sent to Knowi's AI Model | NOT Sent to Knowi's AI Model |
|---|---|
| Dataset schema (field names and types) | Database credentials or connection strings |
| Sample data rows (truncated to fit context window) | User authentication tokens or passwords |
| The user's natural language instruction | Data from other organizations |
| Widget metadata (chart type, settings) | System configuration or server internals |
Security implication: Using the MCP server means data flows to the MCP client's infrastructure. Evaluate whether the data accessible through your MCP token is appropriate for transmission to the client platform you are using. For maximum data isolation, use Knowi's in-product agents (Dashboard and Widget AI Assistants) instead of MCP.
Input Validation and Prompt Injection
Only registered tools are accepted. AI-powered inputs are length-limited, normalized, and screened before model execution. These checks do not replace authorization; Knowi applies the user's permissions independently on every request.
Destructive Operation Safeguards
The do tool scans instructions for destructive intent (delete, remove, drop, destroy, purge, wipe). If detected, the request is blocked and the user is directed to use the explicit delete tool instead.
The delete tool requires three explicit parameters - assetType, assetId, and confirm: true - preventing accidental or AI-hallucinated deletions. All three parameters must be provided; omitting any one causes the request to fail.
Session Security
Streamable HTTP sessions are bound to the authenticated user. Each session receives a unique Mcp-Session-Id and validates that subsequent requests come from the same user who created the session. A valid bearer token is required for every request - session IDs alone do not grant access.
Sessions auto-expire after 30 minutes of inactivity and can be explicitly terminated by the client.
Audit Logging
All agent executions are logged with:
- The user's input prompt
- Success or failure status
- Agent response
- Execution time in milliseconds
- Associated resource IDs (dashboard, widget, dataset)
MCP tool calls are logged with the tool name, success status, and execution time. Logs are available to account administrators.
Data Exposure Controls
Data returned by tools is truncated by default:
-
get_datareturns a maximum of 100 rows by default (configurable via thelimitparameter). -
askreturns a maximum of 100 rows. - AI-powered recommendations truncate data to fit the AI model's context window, iteratively reducing rows until the prompt fits.
The response includes totalRows and returnedRows counts so the caller knows if data was truncated.
Known Limitations
- Usage limits: Usage and capacity limits may apply. Contact your Knowi administrator or account representative for your account's limits.
- Token permissions: Every tool inherits the authenticated user's current account, role, and asset permissions.
- One MCP token per user: Registering a new MCP token revokes the previous one. A user cannot have multiple active MCP tokens simultaneously.
Error Handling
Errors are returned in the MCP response format:
{
"content": [
{"type": "text", "text": "Access denied: you do not have permission to access dashboard 12345"}
],
"isError": true
}
Common error scenarios:
| Error | Cause | Resolution |
|---|---|---|
| 401 Unauthorized | Token expired or invalid | Generate a new MCP token from Settings > AI Settings |
| Access denied | User lacks permission for the requested resource | Check user permissions in Knowi settings |
| Tool not found | Invalid tool name in request | Use /api/2.0/mcp/tools to list valid tool names |
| Validation error | Missing required parameters | Check tool schema for required fields |
| Instruction blocked | Destructive instruction sent to do | Use delete for delete operations |
Rate Limits
AI-powered tools (do, ask, search) consume agent calls, which are metered based on your plan. Deterministic tools are unlimited.
See your account settings for current usage and limits.