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
EntityNotFoundfor it untilset_entity_exposure {"entity":"…","expose":true}andrestart_dab {"confirm":true}. (2) A key created with a non-emptyscopereturns403 AuthorizationCheckFailedon every call until arestart_dabteaches DAB itskey_<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 / DAB —
list_exposed_entities,set_entity_exposure,get_entity_settings,set_entity_settings(per-entity settings incl. column meanings andkeyFields, 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 declarekeyFieldswhen they’re exposed; a keyless one is refused by name rather than taking the Data API down. - NL definitions —
get_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 simplyexport_nl_definitions’ output fed back:terms:[{term,definition,sqlHint?}]andentities:[{entity,description?,columns:[{name,type?,meaning}]}].columnsis a list, not the name→meaning mapset_entity_settingstakes;entityNameworks as an alias forentity; 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 —secretfor the keyless connectors,regionoutside HubSpot,baseUrloutside Salesforce/ServiceTitan, the agent trio outsideodbc; Salesforce/ServiceTitan credentials may be sent as structured fields the tool assembles the way the portal does). Anodbcconnection is only the agent’s mailbox (the agent still has to be installed and its handoff link minted in the portal/REST) and awebhookconnection needs an endpoint added in the portal before anything arrives — the create result states both. Plusupdate_import_connection(partial; supplyingsecretrotates it;writeMode: editorseeds sync anchors),test_import_connection(read-only credential probe) anddelete_import_connection(destructive →confirm:true; usepause_connectionto stop a connector without deleting it). - Import / sync setup —
list_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 carriesprovider,enumerable,erroredand areason, so “reachable and empty” is never confused with “can’t be listed” or “the probe failed”; an inbound webhook isenumerable:falseand 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 returnsstatus: "requested"because the run is queued for the agent’s next poll; an inbound webhook has nothing to trigger and is refused;full:trueneeds a source that can be enumerated.full:truealso works on tables with no rowversion — a full re-pull, flagged asfullResyncin 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). - Operability —
pause_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:truepauses ALL import/sync activity, in-flight runs still finish and queued work resumes when cleared; the optionalnoteshows 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; theapiKeyis write-only and kept when omitted; changing model/dimensions invalidates stored embeddings),test_embeddings(one live probe — connectivity plus a dimensions-match check). - Status —
get_schema_status(this tenant),get_data_quality_summary. - Data-quality rules —
list_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}), androw_count_parity({"tolerancePct":1}and/or{"toleranceRows":10}).row_count_paritytunes the full-mirror source-vs-destination check that runs during a sync: setenabled:falseto 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 relationships —
list_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 (cardinalitymanyby 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; returnsrestartNeeded: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). - Webhooks —
list_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:falsepauses delivery),delete_webhook_subscription,get_webhook_delivery_status(cursor, failure streak, dead-letters). - Change logging —
enable_change_loggingalso returnsrestartNeeded:truefor the same reason as event capture: it arms a trigger on the source table. - Time Travel / change tracking / change logging —
get_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:truealso 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’senabled/retentionDays/autoCleanupplus every table’senabled,trackColumnsUpdated,minValidVersionandcurrentVersion— capture this before you disable anything),enable_change_tracking/disable_change_tracking(omittablefor the database level; the disable takes a scoped confirm — see below),enable_change_logging/disable_change_logging(shadow table + trigger;dropShadow:truealso drops the shadow data). - RLS / permissions / roles —
list_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. - Docs —
get_help_docs(optionalsection),get_api_guide— return this Help / the API guide as markdown (mirror of the data plane’sgetHelpDocs/getAPIGuide). - Agent skills —
list_skillsreturns the skills this platform publishes (name plus what each one is for), andget_skill(name) returns one of them in full. These are the same skills thedlakeCLI ships, served live, so an AI client always reads the current version without upgrading anything. - API keys —
list_api_keys(metadata only, no hashes; each row includes its project, and an optionalprojectarg filters to one project),revoke_api_key,create_api_key(mints for the calling admin by default, or passtargetUserIdto own it by another user — admin-only, same escalation guard as the UI; passprojectto file the key under a project — get-or-create by name, case-insensitive, grouping only;expirationDaysmust 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 —CurrentSteptells the agent which step it is on);registration_capture_server_ipfor step 3 (the CRM step is guarded on it); step 4’s CRM groupregistration_crm_catalog,registration_crm_select,registration_crm_connect,registration_crm_finalizeplusregistration_crm_oauth_start/_status/_complete/_confirm_pinfor OAuth CRMs (two callback legs — see Connecting an OAuth CRM); and step 5’sregistration_connector_catalog,registration_connector_submit(optionalerpNamechanges 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 reportssyncAgentAllowed, 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 returnssyncAgentAllowedplus amessagessentence when that grant did not land) andregistration_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(hostingexpress,sourcedefaultorexplicit,defaultRuledefaultwhile the value is the resolved default and null once it is explicit,locked, and an express tenant’scontainerState/containerHost/containerPort) andregistration_hosting_set(hosting, required — refused withhosting_invalid,hosting_lockedonce the tenant is seeded, orhosting_unavailablewhere 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 needdab.view, changesdab.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 — theidit returns is therecordIdevery 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_exportandcrmpro_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 reportsbefore/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) andcrmpro_apply_template(destructive →confirm:true; replace-all — the list you send must be the complete desired selection). Reads needdab.view, changesdab.manage, and the whole group needs the Admin role (above). See CRMPro (forward sync) below. - Users —
list_users(read-only, no hashes),activate_user,deactivate_user(the tenant owner and your own account are refused). - On-prem agent —
get_agent_status(last seen, version, streaming diagnostics),trigger_agent_update(cancel:truewithdraws a pending push). - Export jobs —
list_export_jobs,cancel_export_job(this tenant’s running jobs only). - Audit —
query_audit_log(every DDL/admin op incl.mcp-admin:*; filter by operation/target/user; capped at 200 rows, default 50). - Notifications —
list_notifications(the calling user’s in-app notifications + unread count; newest first,max1-200 (default 50) andunreadOnlyto skip the read ones — the response reports themaxit applied, thetotalthat matched and whether it wastruncated, whileunreadCountstays your full unread total). - Schema sweep —
run_schema_sweep(runs the internal schema-migration self-heal against this tenant’s own database only;includeManual:truealso 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 throughdlake s3 put/getor 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; andexport_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; omitcolumnsto auto-discover the schema, same as the UI), ands3_detach_table(drop the external table; the S3 object is untouched). Reads use thedata.ingest.*view tier; writes (create/delete/upload/delete-object/export/attach/detach) requiredata.ingest.manage. - Views (DDL) —
list_views,get_view(definition + round-trippableselectStatement),create_view/alter_view(send ONLY the inner SELECT — the server wraps it asCREATE/ALTER VIEW [schema].[name] AS …, identifier-validated; the body itself is checked before anything runs — it must be a singleSELECT(orWITHCTE), no second statement, no blocked keyword such asOPENROWSET/OPENQUERY/OPENDATASOURCE, and a body that includes its ownCREATE VIEW/ALTER VIEWheader is refused by name. Aget_view→alter_viewround-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 asCREATE_VIEW/ALTER_VIEW/DROP_VIEWexactly 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-levelprimaryKey:[...]— the explicit alternative toingest_tabletype-inference),drop_table(destructive),add_column/alter_column/drop_column(single-columnALTER TABLE;drop_columndestructive),describe_table(read one table back column by column: the declarabletypeToken—NVARCHAR(400),DECIMAL(18,2)— that you can paste straight back intocreate_table/alter_column, plusdataType/maxLength/precision/scale,nullable,isPrimaryKey,isIdentity,isUnique,defaultValue, and the table’sprimaryKeylist andforeignKeys. This is how an agent verifies what it just built). Primary-key and identity columns are implicitly NOT NULL — leavenullableoff them; sendingnullable:trueon a PK or identity column is an error rather than being quietly ignored. Same validation and DLO system/shadow-table protection asPOST/PUT/DELETE /api/ddl/tables; permissionstables.view/tables.create/tables.delete/tables.edit; live afterrestart_dab. - Indexes (DDL) —
create_index(orderedcolumns,unique?),drop_index(destructive; a PRIMARY KEY index and DLO system/shadow tables are refused). Mirrors/api/ddl/indexes; permissionsindexes.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, whilefulltext_statusandfulltext_eligibilitysimply report it (fullTextInstalled: false) so you can see why nothing is indexable. - Functions (DDL) —
list_functions(name, kind, the scalarreturnTypeand the full parameter list, each with its declarabletypeToken),get_function(one function’s stored definition, its sizedreturnTypeand every parameter’stypeToken),create_function(functionTypeSCALAR|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 noreturnTypeis refused rather than defaulted),drop_function(destructive; system functions protected). Mirrors/api/ddl/functions; permissionsfunctions.view/functions.create/functions.edit/functions.delete. Read withget_functionand send the samereturnType/typeTokens back — that round-trip is where an unsized type would silently becomeNVARCHAR(1). Type grammar forreturnType/ a parameter’sdataType: 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,MAXonly 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 itstypeTokenandisOutput),get_procedure(one procedure’s stored definition + the same parameter list),create_procedure(parameters?withdirectionINPUT|OUTPUT,body),alter_procedure(replace the signature and body —parametersreplaces 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; permissionsstored-procedures.view/stored-procedures.create/stored-procedures.edit/stored-procedures.delete. Creating or altering a procedure whose name startssp_,xp_ordt_is refused — SQL Server looks those up inmasterfirst, 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 straysp_*object stays removable. - Triggers (DDL) —
create_trigger(form-defined:timing, event flags, anactionofINSERT_INTO_TABLE/VALIDATE_AND_REJECT/UPDATE_COLUMN, optionalcondition— no free-form SQL),drop_trigger(destructive; reserved system/change-log triggers protected). Mirrors/api/ddl/triggers; permissionstriggers.create/triggers.delete. - Schemas (DDL) —
list_schemas(with anisProtectedflag),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/schemasendpoints; permissionsschemas.view(list) /schemas.manage(create + drop). - KB semantic-search admin —
sync_kb_search_views(zero-drop (re)create of the per-KBvw_search_contenthub_<Code>views; obsolete views reported, never dropped —views.create),grant_kb_search_view(GRANT/revoke:trueSELECT on a KB view to an API key’s DB principal —views.edit). Mirrors/api/ddl/search/kb-views/*; SQL 2025+ engine-gated.
Destructive tools — restart_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.