Help · section 24 of 44

Admin Control Plane (MCP)

Mirrors the in-app Help. The live copy in your console and `dlake guide help` are always current.

A second, separate MCP connection for administering a tenant’s data lake from an AI client — it configures the lake (setup, not data transactions) and never reads or writes table data (that’s the data plane). Connect it exactly like the data-plane MCP — same two auth options (an X-API-Key header for any client that supports one, OAuth only for hosted connector UIs), same tenant host — but on the /admin path: https://datalake-ms-dab.commercient.com/auth/<tenant>/admin (vs the data plane’s /auth/<tenant>/mcp). A generic tenant-less URL https://datalake-ms-dab.commercient.com/admin also works — it resolves the tenant from the credential (OAuth JWT, a composite tenant:dlk_... API key, or an X-Tenant header) exactly like the generic data connector described under DAB & API Keys. Same guidance applies: use the generic URL to share one admin connector definition, or distinct per-tenant /auth/<tenant>/admin URLs to administer several tenants at once from one client (clients dedupe by URL). It is stateless JSON-RPC 2.0 (no session id), unlike the session-based data plane.

Access is strict: the API key must be full-scope and belong to an Admin user. A per-entity-scoped key, a non-admin full-scope key, and an interactive (non-key) login are all rejected with HTTP 403 + JSON-RPC error -32001 naming the requirement. Issue a dedicated full-scope key on an admin user for this.

The setup groups go further — they need the Admin role. Every registration_* wizard tool and every crmpro_* tool checks the caller’s roles as well: the key must belong to a tenant user who holds the Admin role, and anyone else is refused with a 403 naming that role. Permissions can’t express this on their own, because a key inherits all of its owning user’s rights — the named role is what tells a tenant Admin from any other user. Keys inherit the roles of the user who minted them, so a 403 here means the key was minted from the wrong account: generate it from an Admin user. Widening the key’s scope won’t help, and Owner / DBO Admin don’t bypass it.

Two orderings that catch everyone. (1) A new table/view/procedure is a database object only — the data plane and REST/GraphQL return EntityNotFound for it until set_entity_exposure {"entity":"…","expose":true} and restart_dab {"confirm":true}. (2) A key created with a non-empty scope returns 403 AuthorizationCheckFailed on every call until a restart_dab teaches DAB its key_<id> role — so a scoped-key handover is create key → restart (and the restart must come from a full-scope admin key, since a scoped key is locked out of this plane). Batch schema edits into one restart; the scoped key then needs its own.

Manage your schema end-to-end from Claude (or the CLI). The control plane now covers the full schema lifecycle — creating and dropping tables, adding/altering/dropping columns, indexes, full-text catalogs and indexes, functions, stored procedures, triggers, and schemas — plus the read-backs that let an agent check its own work (describe_table, get_view, get_function, get_procedure, list_change_tracking) — the same operations the Schema Builder UI offers, enforced with the same permissions and audit trail (every write is logged as mcp-admin:<tool>, and destructive tools refuse without confirm:true). So you can ask Claude to design a table, add a column, or build an index and it happens against your lake exactly as if you’d done it in the UI; the change reaches the live Data API on the next Restart DAB.

Its setup tools — dlake admin list prints every tool your key can use:

  • Entity exposure / DABlist_exposed_entities, set_entity_exposure, get_entity_settings, set_entity_settings (per-entity settings incl. column meanings and keyFields, the addressable key that makes a view writeable/by-key addressable — the same field as the UI gear’s Addressable Key), restart_dab, dab_status. Views without an inheritable base-table key must declare keyFields when they’re exposed; a keyless one is refused by name rather than taking the Data API down.
  • NL definitionsget_nl_definitions, put_nl_definitions, export_nl_definitions, import_nl_definitions (export/import round-trips a schema skeleton an external AI can fill). The import document is simply export_nl_definitions’ output fed back: terms:[{term,definition,sqlHint?}] and entities:[{entity,description?,columns:[{name,type?,meaning}]}]. columns is a list, not the name→meaning map set_entity_settings takes; entityName works as an alias for entity; a malformed document comes back with a plain-English shape message, not a parser error.
  • Import connections (lifecycle)create_import_connection (create a source connection without the portal: hubspot, stripe, salesforce, servicetitan, mssql, commercient, odbc, webhook; credentials are encrypted at rest and write-only — never echoed in a result, an error or the audit row; fields that don’t apply to the provider are refused by name, not ignored — secret for the keyless connectors, region outside HubSpot, baseUrl outside Salesforce/ServiceTitan, the agent trio outside odbc; Salesforce/ServiceTitan credentials may be sent as structured fields the tool assembles the way the portal does). An odbc connection is only the agent’s mailbox (the agent still has to be installed and its handoff link minted in the portal/REST) and a webhook connection needs an endpoint added in the portal before anything arrives — the create result states both. Plus update_import_connection (partial; supplying secret rotates it; writeMode: editor seeds sync anchors), test_import_connection (read-only credential probe) and delete_import_connection (destructive → confirm:true; use pause_connection to stop a connector without deleting it).
  • Import / sync setuplist_connections (secrets never returned; reports which providers can be created over MCP and what each still needs afterwards), list_source_entities (live source re-discovery — the answer always carries provider, enumerable, errored and a reason, so “reachable and empty” is never confused with “can’t be listed” or “the probe failed”; an inbound webhook is enumerable:false and lists the targets its endpoint mappings declare), get_entity_sync_config, save_entity_sync_config (validates CT-mode preconditions, and is all-or-nothing — every entity name is checked against the source’s entity list before anything is written, so one bad name rejects the whole batch and the message lists the valid set), run_entity_sync (preconditions are checked up front: the entity must be configured and enabled; an on-prem agent connection returns status: "requested" because the run is queued for the agent’s next poll; an inbound webhook has nothing to trigger and is refused; full:true needs a source that can be enumerated. full:true also works on tables with no rowversion — a full re-pull, flagged as fullResync in the run history), get_run_history (runs incl. destination row counts + notes), verify_entity_integrity (read-only full-snapshot source-vs-Lake diff for one connector-pull entity — no writes).
  • Operabilitypause_connection (pause/resume one connector without unconfiguring it: no scheduled runs claimed, no streaming drained, agent claims refused benignly; anything already running finishes; resuming restores the prior behaviour exactly), get_maintenance / set_maintenance (tenant-wide maintenance mode for a SQL host reboot or patch window — active:true pauses ALL import/sync activity, in-flight runs still finish and queued work resumes when cleared; the optional note shows in the UI banner with who set it).
  • Embeddings (semantic document search)get_embeddings_settings (is a provider configured, a masked last-4 key hint — never the key — and the resolved endpoint/model/dimensions), set_embeddings_settings (OpenAI or a local Ollama; the apiKey is write-only and kept when omitted; changing model/dimensions invalidates stored embeddings), test_embeddings (one live probe — connectivity plus a dimensions-match check).
  • Statusget_schema_status (this tenant), get_data_quality_summary.
  • Data-quality ruleslist_dq_rules, set_dq_rule (upsert), delete_dq_rule. Rule types: min_row_count ({"minRows":N}), not_null ({"columns":["a","b"]}), freshness_max_age_hours ({"timestampColumn":"ModifiedUtc","maxAgeHours":24}), null_rate ({"column":"email","thresholdPct":5}), row_count_drift ({"thresholdPct":20}), and row_count_parity ({"tolerancePct":1} and/or {"toleranceRows":10}). row_count_parity tunes the full-mirror source-vs-destination check that runs during a sync: set enabled:false to silence its warning for the entity, or a tolerance to allow small drift; with no rule row present, parity uses its default behaviour. Config keys are validated against the rule type — a missing required key (minRows, columns, column, timestampColumn), a wrong JSON type, or an unknown key is rejected by name with the accepted list and nothing is saved. All other types are also evaluated on the platform’s data-quality schedule.
  • GraphQL relationshipslist_relationships, set_relationship (upsert; validates both entities and both columns exist in the tenant schema — a bad name is rejected so it can’t crash-loop DAB), delete_relationship. A declared parent/child link nests the child under the parent (cardinality many by default) and the parent under the child (one) in the Data API’s GraphQL. Changes are not auto-applied — they take effect on the next Regenerate / Restart DAB.
  • Events (row-change capture)list_event_captures, enable_event_capture (installs the capture trigger + column map; idempotent; returns restartNeeded:true — until you Restart DAB, every Data API write to that table fails, see Triggers and the Data API), disable_event_capture (drops the trigger — no restart needed, and it un-breaks a table whose writes were failing), refresh_event_capture (rebuild the column map/trigger after raw-SQL column changes — rebuilds in place, so it does not repair failing writes).
  • Webhookslist_webhook_subscriptions (tenant-wide; secrets never returned), create_webhook_subscription (URL is SSRF-checked before storage; returns the signing secret exactly once — store it, it can never be retrieved again), update_webhook_subscription (URL re-checked; enabled:false pauses delivery), delete_webhook_subscription, get_webhook_delivery_status (cursor, failure streak, dead-letters).
  • Change loggingenable_change_logging also returns restartNeeded:true for the same reason as event capture: it arms a trigger on the source table.
  • Time Travel / change tracking / change loggingget_table_history_status (one-call posture for all three), enable_time_travel (needs a PK; mutually exclusive with Concurrency Protection — but it works alongside event capture, and installs no trigger, so it needs no DAB restart), disable_time_travel (dropHistory:true also drops the history table), query_row_history (one row’s full version timeline by PK, RLS-scoped, capped at 200 versions, default 50), list_change_tracking (the whole schema’s change-tracking posture in one read: the database’s enabled/retentionDays/autoCleanup plus every table’s enabled, trackColumnsUpdated, minValidVersion and currentVersion — capture this before you disable anything), enable_change_tracking / disable_change_tracking (omit table for the database level; the disable takes a scoped confirm — see below), enable_change_logging / disable_change_logging (shadow table + trigger; dropShadow:true also drops the shadow data).
  • RLS / permissions / roleslist_rls_policies (read-only — creating/dropping policies stays in UI/REST), get_permission_matrix, grant_permission / revoke_permission (target a role or one user as an override), list_roles.
  • Docsget_help_docs (optional section), get_api_guide — return this Help / the API guide as markdown (mirror of the data plane’s getHelpDocs/getAPIGuide).
  • Agent skillslist_skills returns the skills this platform publishes (name plus what each one is for), and get_skill (name) returns one of them in full. These are the same skills the dlake CLI ships, served live, so an AI client always reads the current version without upgrading anything.
  • API keyslist_api_keys (metadata only, no hashes; each row includes its project, and an optional project arg filters to one project), revoke_api_key, create_api_key (mints for the calling admin by default, or pass targetUserId to own it by another user — admin-only, same escalation guard as the UI; pass project to file the key under a project — get-or-create by name, case-insensitive, grouping only; expirationDays must be 7/30/90/180; returns the raw key exactly once — only its hash is stored), extend_api_key (push a key’s expiry out by 7/30/90/180 days — max(now, current) + days; refuses a revoked key), unrevoke_api_key (restore a revoked key; leaves the expiry untouched, so a still-expired key must then be extended), get_key_rights, set_key_rights (denylist model — removals only, applied at each exchange/refresh), set_key_entity_scopes (empty scope = full access; a non-empty scope also locks the key out of this admin plane).
  • Registration wizard (22) — finish a new Data Lake’s onboarding from here instead of the browser, using the tenant’s own API key: registration_status, registration_state (call this first — CurrentStep tells the agent which step it is on); registration_capture_server_ip for step 3 (the CRM step is guarded on it); step 4’s CRM group registration_crm_catalog, registration_crm_select, registration_crm_connect, registration_crm_finalize plus registration_crm_oauth_start / _status / _complete / _confirm_pin for OAuth CRMs (two callback legs — see Connecting an OAuth CRM); and step 5’s registration_connector_catalog, registration_connector_submit (optional erpName changes the registration’s ERP — omit it to keep the current one), registration_connector_provision, registration_provisioning_status. Five more cover the SYNC-AGENT PRODUCTS the customer’s on-prem agent should run — registration_products_list (which also reports syncAgentAllowed, the current state of the customer’s portal and installer access), registration_products_add, registration_products_remove, registration_products_request_install (which also grants the customer’s installer access and returns syncAgentAllowed plus a messages sentence when that grant did not land) and registration_products_allow_sync_agent (allow, required — grants or revokes that access on its own, and needs the wizard to have reached step 5); the accepted product names come from the list tool and are used verbatim (several are estate misspellings the installer matches literally). Two more carry the HOSTING CHOICE — where the tenant’s gateway database lives: registration_hosting_get (hosting express, source default or explicit, defaultRule default while the value is the resolved default and null once it is explicit, locked, and an express tenant’s containerState / containerHost / containerPort) and registration_hosting_set (hosting, required — refused with hosting_invalid, hosting_locked once the tenant is seeded, or hosting_unavailable where container hosting is not enabled); see Hosting — where your gateway database lives. Credential values are passed through but never logged and never audited — the audit row keeps the CRM/connector name and the field names only. Reads need dab.view, changes dab.manage. Signing up in the first place stays outside MCP by design (there is no key yet) — see Registering a New Data Lake.
  • CRMPro (26) — operate the forward ERP → CRM sync from an AI client or the CLI instead of the portal: crmpro_list_processes (the grid — the id it returns is the recordId every other process tool takes), crmpro_get_process, crmpro_get_process_sql, crmpro_field_mapping, crmpro_sync_status, crmpro_sync_history / crmpro_sync_history_options, crmpro_errors, crmpro_agent_info, crmpro_sync_log_export and crmpro_sync_log_text (the sync agent’s OWN log — filtered and windowed, never returned whole), crmpro_flags, crmpro_user_flags, crmpro_connections, crmpro_crm_objects, crmpro_crm_object_fields, crmpro_tables_views, crmpro_table_columns, crmpro_templates, crmpro_selected_templates — and six changes: crmpro_set_sync_enabled (the customer-wide switch, made idempotent — it reads the flag first and reports before/after/changed, so a retry can’t flip a customer’s sync the wrong way), crmpro_update_process_field (one checkbox, e.g. Is_Active), crmpro_update_process (send only the fields you’re changing — the merge happens server-side and everything omitted is preserved), crmpro_create_process, crmpro_delete_process (destructive → confirm:true) and crmpro_apply_template (destructive → confirm:true; replace-all — the list you send must be the complete desired selection). Reads need dab.view, changes dab.manage, and the whole group needs the Admin role (above). See CRMPro (forward sync) below.
  • Userslist_users (read-only, no hashes), activate_user, deactivate_user (the tenant owner and your own account are refused).
  • On-prem agentget_agent_status (last seen, version, streaming diagnostics), trigger_agent_update (cancel:true withdraws a pending push).
  • Export jobslist_export_jobs, cancel_export_job (this tenant’s running jobs only).
  • Auditquery_audit_log (every DDL/admin op incl. mcp-admin:*; filter by operation/target/user; capped at 200 rows, default 50).
  • Notificationslist_notifications (the calling user’s in-app notifications + unread count; newest first, max 1-200 (default 50) and unreadOnly to skip the read ones — the response reports the max it applied, the total that matched and whether it was truncated, while unreadCount stays your full unread total).
  • Schema sweeprun_schema_sweep (runs the internal schema-migration self-heal against this tenant’s own database only; includeManual:true also applies operator-gated migrations).
  • Object storage (S3 outlet)list_s3_connections, create_s3_connection (secret write-only, redacted in the result), test_s3_connection, delete_s3_connection; s3_list_objects (continuation-token paging), s3_upload / s3_download (base64, hard 8 MB cap — larger files go through dlake s3 put/get or the UI), s3_discover_schema (read a parquet footer / CSV head and return ready-to-attach columns — the object itself is never downloaded), s3_delete_object; and export_to_s3 — export a whole table/view straight into a connection’s bucket, reusing the scoped export-table pipeline (per-key scope, RLS, impersonation, 50M-row cap) and waiting up to an administrator-configured window (5 minutes by default) for completion. On SQL Server 2022+ tenants the attach tools mirror the REST attach endpoints: s3_list_attached (attached external tables + the capability probe), s3_attach_table (attach a parquet/CSV object or folder prefix as a queryable external table in the connection’s [s3_<id>] schema; omit columns to auto-discover the schema, same as the UI), and s3_detach_table (drop the external table; the S3 object is untouched). Reads use the data.ingest.* view tier; writes (create/delete/upload/delete-object/export/attach/detach) require data.ingest.manage.
  • Views (DDL)list_views, get_view (definition + round-trippable selectStatement), create_view / alter_view (send ONLY the inner SELECT — the server wraps it as CREATE/ALTER VIEW [schema].[name] AS …, identifier-validated; the body itself is checked before anything runs — it must be a single SELECT (or WITH CTE), no second statement, no blocked keyword such as OPENROWSET/OPENQUERY/OPENDATASOURCE, and a body that includes its own CREATE VIEW/ALTER VIEW header is refused by name. A get_viewalter_view round-trip of an unchanged body is always accepted), drop_view (destructive → confirm:true). Same permissions as the REST endpoints (views.view / views.create / views.edit / views.delete), audited as CREATE_VIEW/ALTER_VIEW/DROP_VIEW exactly like the UI path; view changes reach the live Data API on the next Regenerate / Restart DAB.
  • Tables (DDL)create_table (explicit column design: columns:[{name,type,size?,precision?,scale?,nullable?,default?,identity?,unique?,primaryKey?}] + a top-level primaryKey:[...] — the explicit alternative to ingest_table type-inference), drop_table (destructive), add_column / alter_column / drop_column (single-column ALTER TABLE; drop_column destructive), describe_table (read one table back column by column: the declarable typeTokenNVARCHAR(400), DECIMAL(18,2) — that you can paste straight back into create_table/alter_column, plus dataType/maxLength/precision/scale, nullable, isPrimaryKey, isIdentity, isUnique, defaultValue, and the table’s primaryKey list and foreignKeys. This is how an agent verifies what it just built). Primary-key and identity columns are implicitly NOT NULL — leave nullable off them; sending nullable:true on a PK or identity column is an error rather than being quietly ignored. Same validation and DLO system/shadow-table protection as POST/PUT/DELETE /api/ddl/tables; permissions tables.view / tables.create / tables.delete / tables.edit; live after restart_dab.
  • Indexes (DDL)create_index (ordered columns, unique?), drop_index (destructive; a PRIMARY KEY index and DLO system/shadow tables are refused). Mirrors /api/ddl/indexes; permissions indexes.create / indexes.delete.
  • Full-text search (DDL)fulltext_status, fulltext_eligibility, create_fulltext_catalog, create_fulltext_index (columns, changeTracking? AUTO|MANUAL|OFF), drop_fulltext_index (destructive). Mirrors /api/ddl/fulltext, reusing the Indexes gates (indexes.view / indexes.create / indexes.delete). If the Full-Text Search component isn’t installed on the engine, the two create tools refuse and tell you what to install, while fulltext_status and fulltext_eligibility simply report it (fullTextInstalled: false) so you can see why nothing is indexable.
  • Functions (DDL)list_functions (name, kind, the scalar returnType and the full parameter list, each with its declarable typeToken), get_function (one function’s stored definition, its sized returnType and every parameter’s typeToken), create_function (functionType SCALAR|INLINE_TABLE, parameters?, returnType?, body), alter_function (replace the parameters/return type/body — the function kind comes from the catalog, so an ALTER can never turn a scalar function into a table-valued one, and a scalar ALTER with no returnType is refused rather than defaulted), drop_function (destructive; system functions protected). Mirrors /api/ddl/functions; permissions functions.view / functions.create / functions.edit / functions.delete. Read with get_function and send the same returnType/typeTokens back — that round-trip is where an unsized type would silently become NVARCHAR(1). Type grammar for returnType / a parameter’s dataType: one SQL type with an optional inline size — INT, NVARCHAR(400), VARCHAR(MAX), DECIMAL(18,2), DATETIME2(3) (NCHAR/NVARCHAR 1-4000, CHAR/VARCHAR/BINARY/VARBINARY 1-8000, MAX only for the variable-length types; DECIMAL precision 1-38, scale ≤ precision; DATETIME2/TIME/DATETIMEOFFSET 0-7). Say the size you want: unsized VARCHAR/NVARCHAR/VARBINARY become (MAX) and DECIMAL (18,0), and a bare CHAR/NCHAR/BINARY is refused rather than silently becoming width 1.
  • Stored procedures (DDL)list_procedures (name, creation date and the full parameter list, each with its typeToken and isOutput), get_procedure (one procedure’s stored definition + the same parameter list), create_procedure (parameters? with direction INPUT|OUTPUT, body), alter_procedure (replace the signature and body — parameters replaces the signature, and the same type rules and name guard as create apply), drop_procedure (destructive; reserved system procedures refused). Mirrors /api/ddl/stored-procedures; permissions stored-procedures.view / stored-procedures.create / stored-procedures.edit / stored-procedures.delete. Creating or altering a procedure whose name starts sp_, xp_ or dt_ is refused — SQL Server looks those up in master first, so the object would shadow (or be shadowed by) a system procedure. Dropping one is still allowed: the drop only ever touches your own schema, so a stray sp_* object stays removable.
  • Triggers (DDL)create_trigger (form-defined: timing, event flags, an action of INSERT_INTO_TABLE/VALIDATE_AND_REJECT/UPDATE_COLUMN, optional condition — no free-form SQL), drop_trigger (destructive; reserved system/change-log triggers protected). Mirrors /api/ddl/triggers; permissions triggers.create / triggers.delete.
  • Schemas (DDL)list_schemas (with an isProtected flag), create_schema, drop_schema (destructive; dbo/DLO/sys/guest/db_* protected, and a non-empty schema fails with the SQL error). Mirrors the DCL /api/dcl/schemas endpoints; permissions schemas.view (list) / schemas.manage (create + drop).
  • KB semantic-search adminsync_kb_search_views (zero-drop (re)create of the per-KB vw_search_contenthub_<Code> views; obsolete views reported, never dropped — views.create), grant_kb_search_view (GRANT/revoke:true SELECT on a KB view to an API key’s DB principal — views.edit). Mirrors /api/ddl/search/kb-views/*; SQL 2025+ engine-gated.

Destructive toolsrestart_dab, revoke_api_key, delete_dq_rule, delete_relationship, removing an entity via set_entity_exposure, import_nl_definitions with mode:"replace", disable_event_capture, delete_webhook_subscription, disable_time_travel, disable_change_tracking, disable_change_logging, deactivate_user, delete_s3_connection, s3_delete_object, drop_view, drop_table, drop_column, drop_index, drop_fulltext_index, drop_function, drop_procedure, drop_trigger, drop_schema, crmpro_delete_process, crmpro_apply_template, txdownloaderpro_delete_process (and the TxDownloaderPro tools that replace a whole stored mapping), normalsync_catalog_table, normalsync_add_table, normalsync_set_row_filter, normalsync_resync_all, normalsync_resync_table, normalsync_clear_table_resync, odbcsync_register_bucket, odbcsync_allow_ip, odbcsync_save_agent_config, apisync_enable, apisync_save_endpoint_config, and run_schema_sweep — require confirm: true. disable_change_tracking asks for more than that: it takes a scoped confirm — confirm:"<tableName>" for one table, confirm:"DATABASE" for the whole database — and a bare confirm:true is refused. That is deliberate: disabling change tracking throws away every consumer’s sync watermark for those tables, so each one needs a full re-baseline before it can resume, and a database-wide disable un-registers every tracked table (re-enabling the database does not bring them back). Run list_change_tracking first and keep the output — it is the only record of what to restore. Config changes to exposure/settings/meanings/relationships persist immediately but reach the live Data API only after restart_dab. Revoking a key takes effect immediately across every surface, including cached MCP sessions. create_api_key and create_webhook_subscription each return their secret once in the tool result — capture it immediately. Every admin write is audited as mcp-admin:<tool>.

After a tool-surface update, restart your MCP client. An MCP client caches the tool list per session (it pulls the schema once at connect), so Claude Desktop / claude.ai won’t show the new tools until you restart the client or re-add the connector.