| name | databricks | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| displayName | Databricks AI Dev Kit | ||||||||||
| description | Comprehensive Databricks development toolkit with 44 MCP tools (180+ operations) and 35+ skills for building data pipelines, ML workflows, dashboards, jobs, and applications on Databricks platform. | ||||||||||
| keywords |
|
||||||||||
| author | Databricks Solutions |
The Databricks AI Dev Kit Power provides comprehensive access to the Databricks Lakehouse platform through 44 MCP tools (180+ operations) and 35+ expert steering files for every Databricks capability — pipelines, jobs, dashboards, ML, governance, and apps.
Key capabilities:
- SQL & Compute: Execute SQL on warehouses, run Python/Scala on clusters, manage compute lifecycle
- Pipelines & Jobs: Build Spark Declarative Pipelines (streaming tables, CDC, SCD Type 2, Auto Loader) and orchestrate multi-task DAGs
- Unity Catalog: Manage tables, volumes, grants, tags, storage credentials, system tables, and metric views
- AI/BI Dashboards: Create interactive visualizations, KPIs, and analytics dashboards
- Genie Spaces: Natural-language data exploration over governed datasets
- Agent Bricks: Build Knowledge Assistants (RAG) and Multi-Agent Supervisors
- Vector Search: Semantic search and RAG with managed indexes
- Model Serving: Deploy ML models and AI agents to scalable endpoints
- MLflow: Track experiments, evaluate models, instrument tracing, query metrics
- Lakebase: Provisioned and autoscale managed PostgreSQL for OLTP workloads
- Databricks Apps: Full-stack web applications on the Lakehouse
- Asset Bundles: Infrastructure-as-code for Databricks resources
Authentication: Requires a Databricks workspace and either an OAuth-authenticated CLI profile, an existing ~/.databrickscfg profile, or a Personal Access Token (PAT).
This Power's steering files are downloaded from the ai-dev-kit repository during onboarding and copied into the Power's steering/ directory. Skills load on-demand based on your task.
| Skill | Domain | Description |
|---|---|---|
| databricks-spark-declarative-pipelines | Data Engineering | Streaming tables, CDC, SCD Type 2, Auto Loader |
| databricks-spark-structured-streaming | Data Engineering | Kafka, stateful ops, stream joins |
| databricks-jobs | Data Engineering | Scheduled workflows, multi-task DAGs, serverless |
| databricks-zerobus-ingest | Data Engineering | Zero-copy ingestion |
| databricks-iceberg | Data Engineering | Iceberg tables, UniForm, interop |
| databricks-aibi-dashboards | Analytics | Interactive visualizations, KPIs, analytics |
| databricks-dbsql | Analytics | SQL best practices, materialized views |
| databricks-genie | Analytics | Natural language data exploration |
| databricks-metric-views | Analytics | Reusable business metrics |
| databricks-unity-catalog | Governance | Tables, volumes, governance, system tables |
| databricks-agent-bricks | AI/ML | Knowledge Assistants, Supervisor Agents |
| databricks-vector-search | AI/ML | Semantic search and RAG applications |
| databricks-model-serving | AI/ML | Deploy ML models and AI agents |
| databricks-mlflow-evaluation | AI/ML | Model evaluation, scoring, traces |
| databricks-ai-functions | AI/ML | AI functions, forecasting, document processing |
| databricks-synthetic-data-gen | AI/ML | Synthetic data generation |
| databricks-app-python | App Development | Full-stack web applications |
| databricks-app-apx | App Development | App frontend/backend patterns |
| databricks-lakebase-provisioned | App Development | Managed PostgreSQL (provisioned) |
| databricks-lakebase-autoscale | App Development | Managed PostgreSQL (autoscale) |
| databricks-bundles | Platform | Databricks Asset Bundles |
| databricks-config | Platform | Workspace configuration |
| databricks-python-sdk | Platform | Python SDK patterns and examples |
| databricks-unstructured-pdf-generation | Platform | PDF generation and upload |
| databricks-docs | Platform | Documentation search |
| mlflow-onboarding | MLflow | MLflow getting started |
| instrumenting-with-mlflow-tracing | MLflow | MLflow tracing instrumentation |
| querying-mlflow-metrics | MLflow | Querying MLflow metrics |
| retrieving-mlflow-traces | MLflow | Retrieving MLflow traces |
| searching-mlflow-docs | MLflow | Searching MLflow documentation |
| analyze-mlflow-trace | MLflow | Analyzing MLflow traces |
| analyze-mlflow-chat-session | MLflow | Analyzing MLflow chat sessions |
| agent-evaluation | MLflow | Agent evaluation patterns |
| spark-python-data-source | Data Engineering | Custom Spark data sources |
This Power installs all available skills (currently 35+, and growing --skills-profile all). Skills are markdown files that load on demand based on the task at hand — having the full set present incurs no runtime cost, and it avoids re-running the installer when work crosses domains (e.g., an ML engineer who occasionally builds a dashboard). Persona-specific subsets are not used.
Package: databricks-solutions/ai-dev-kit (databricks-mcp-server)
Connection: Local Python process (uv venv) configured via ~/.kiro/settings/mcp.json
44 tools spanning 180+ operations. The most frequently used are itemized below; see the full category index further down.
-
execute_sql — Run a SQL statement on a SQL warehouse
- Required:
statement(string),warehouse_id(string) - Optional:
catalog,schema,parameters,wait_timeout - Returns: Result rows, schema, statement state
- Required:
-
execute_sql_multi — Run multiple SQL statements in sequence
- Required:
statements(string[]),warehouse_id(string) - Returns: Results per statement
- Required:
-
execute_code — Execute Python/Scala/R/SQL on an interactive cluster
- Required:
cluster_id(string),language(string),code(string) - Returns: Execution output
- Required:
-
manage_cluster — Create / get / list / start / restart / terminate / edit clusters
- Required:
action(string) - Optional: cluster spec fields per action
- Returns: Cluster object or list
- Required:
-
manage_sql_warehouse — Create / get / list / start / stop / edit / delete SQL warehouses
- Required:
action(string) - Optional: warehouse spec fields per action
- Returns: Warehouse object or list
- Required:
-
manage_warehouse — Companion warehouse helper for SQL workflows
- Required:
action(string) - Returns: Warehouse state
- Required:
-
list_compute — List available compute resources (clusters + warehouses)
- Optional:
filter_type - Returns: Compute summary
- Optional:
-
get_table_stats_and_schema — Inspect table schema, row counts, partitioning
- Required:
table_name(fully-qualified, e.g.catalog.schema.table) - Returns: Schema, statistics, partition info
- Required:
-
manage_jobs — Create / get / list / update / delete jobs
- Required:
action(string) - Optional: job spec (
tasks,schedule,parameters,email_notifications) - Returns: Job object or list
- Required:
-
manage_job_runs — Run / wait / cancel / get-output for job runs
- Required:
action(string),job_idorrun_id - Returns: Run state, output, logs
- Required:
-
manage_pipeline — Create / get / list / update / delete Spark Declarative Pipelines (DLT)
- Required:
action(string) - Optional: pipeline spec, libraries, target schema
- Returns: Pipeline object
- Required:
-
manage_pipeline_run — Start / stop / get-update for pipeline runs
- Required:
action(string),pipeline_id - Returns: Run/update state
- Required:
-
manage_uc_objects — Create / get / list / update / delete catalogs, schemas, tables, volumes, functions
- Required:
action(string),object_type(string) - Optional: object spec
- Returns: UC object or list
- Required:
-
manage_uc_grants — Grant / revoke / list privileges on UC objects
- Required:
action(string),securable_type,full_name - Returns: Permission assignments
- Required:
-
manage_uc_storage — Manage external locations and storage credentials
- Required:
action(string) - Returns: Storage credential / external location
- Required:
-
manage_uc_tags — Apply / remove tags on UC objects
- Required:
action(string),object,tags - Returns: Tag assignments
- Required:
-
manage_uc_connections — Manage federated catalog connections
- Required:
action(string) - Returns: Connection object
- Required:
-
manage_uc_sharing — Manage Delta Sharing shares and recipients
- Required:
action(string) - Returns: Share / recipient
- Required:
-
manage_uc_monitors — Manage Lakehouse Monitoring profiles
- Required:
action(string),table_name - Returns: Monitor state
- Required:
-
manage_uc_security_policies — Manage row-level / column-level security policies
- Required:
action(string) - Returns: Policy object
- Required:
-
manage_metric_views — Create / list / update reusable business metrics
- Required:
action(string) - Returns: Metric view definition
- Required:
-
manage_dashboard — Create / get / list / delete / publish AI/BI dashboards
- Required:
action(string) - Optional: dashboard JSON, draft/publish flags
- Returns: Dashboard object
- Required:
-
manage_genie — Create / list / configure Genie Spaces
- Required:
action(string) - Returns: Genie Space object
- Required:
-
ask_genie — Ask a question against a Genie Space
- Required:
space_id,question - Returns: Generated SQL, result rows, explanation
- Required:
-
manage_ka — Create / list / update Knowledge Assistants (RAG agents)
- Required:
action(string) - Returns: Knowledge Assistant object
- Required:
-
manage_mas — Create / list / update Multi-Agent Supervisors
- Required:
action(string) - Returns: Multi-Agent Supervisor object
- Required:
-
manage_serving_endpoint — Get / list / query serving endpoints
- Required:
action(string) - Optional:
endpoint_name,inputs(for query) - Returns: Endpoint object or model output
- Required:
-
manage_vs_endpoint — Create / list / delete vector search endpoints
- Required:
action(string) - Returns: VS endpoint object
- Required:
-
manage_vs_index — Create / list / sync / delete vector search indexes
- Required:
action(string) - Returns: VS index object
- Required:
-
manage_vs_data — Upsert / delete documents in a direct-access VS index
- Required:
action(string),index_name,data - Returns: Operation status
- Required:
-
query_vs_index — Similarity search against a VS index
- Required:
index_name,query_textorquery_vector - Optional:
num_results,filters - Returns: Top-k matched documents
- Required:
-
manage_lakebase_database — Create / get / list / delete Lakebase databases
- Required:
action(string) - Returns: Lakebase database object
- Required:
-
manage_lakebase_branch — Manage Lakebase branches
- Required:
action(string) - Returns: Branch state
- Required:
-
manage_lakebase_sync — Configure Lakebase ↔ UC sync
- Required:
action(string) - Returns: Sync configuration
- Required:
-
generate_lakebase_credential — Issue short-lived Lakebase credentials
- Required:
database_name - Returns: Credential
- Required:
-
manage_app — Create / get / list / delete / deploy Databricks Apps
- Required:
action(string) - Returns: App object
- Required:
-
manage_workspace_files — Read / write / list / delete workspace files
- Required:
action(string),path - Returns: File contents or status
- Required:
-
manage_volume_files — Read / write / list / delete volume files
- Required:
action(string),path - Returns: File contents or status
- Required:
-
get_volume_folder_details — Inspect a UC volume folder
- Required:
volume_path - Returns: Folder listing with metadata
- Required:
-
manage_workspace — Workspace-level operations (notebooks, folders, permissions)
- Required:
action(string) - Returns: Workspace object
- Required:
-
get_current_user — Identify the authenticated principal
- No parameters required
- Returns: User profile, workspace, entitlements
-
generate_and_upload_pdf — Render HTML to PDF and upload to a volume
- Required:
html,volume_path - Returns: Uploaded file path
- Required:
-
list_tracked_resources — List resources created/tracked by this MCP session
- Optional:
resource_type - Returns: Tracked resources
- Optional:
-
delete_tracked_resource — Delete a previously tracked resource
- Required:
resource_type,resource_id - Returns: Deletion status
- Required:
| Category | Tool count | Operations |
|---|---|---|
| SQL & Compute | 8 | execute_sql, execute_sql_multi, execute_code, manage_cluster, manage_sql_warehouse, manage_warehouse, list_compute, get_table_stats_and_schema |
| Jobs & Pipelines | 4 | manage_jobs, manage_job_runs, manage_pipeline, manage_pipeline_run |
| Unity Catalog | 9 | manage_uc_objects, manage_uc_grants, manage_uc_storage, manage_uc_tags, manage_uc_connections, manage_uc_sharing, manage_uc_monitors, manage_uc_security_policies, manage_metric_views |
| Dashboards / Genie / Agents | 5 | manage_dashboard, manage_genie, ask_genie, manage_ka, manage_mas |
| Model Serving / Vector Search | 5 | manage_serving_endpoint, manage_vs_endpoint, manage_vs_index, manage_vs_data, query_vs_index |
| Lakebase / Apps / Files | 8 | manage_lakebase_database, manage_lakebase_branch, manage_lakebase_sync, generate_lakebase_credential, manage_app, manage_workspace_files, manage_volume_files, get_volume_folder_details |
| Workspace / Utilities | 5 | manage_workspace, get_current_user, generate_and_upload_pdf, list_tracked_resources, delete_tracked_resource |
Run a query on a warehouse:
usePower("databricks", "databricks", "execute_sql", {
"statement": "SELECT current_catalog(), current_schema()",
"warehouse_id": "abc123def456"
})
// Returns: Single-row result with current catalog and schemaInspect a table:
usePower("databricks", "databricks", "get_table_stats_and_schema", {
"table_name": "main.sales.orders"
})
// Returns: Columns, types, row count, partition infoCreate a job:
usePower("databricks", "databricks", "manage_jobs", {
"action": "create",
"name": "nightly_orders_etl",
"tasks": [{
"task_key": "transform",
"notebook_task": { "notebook_path": "/Workspace/etl/transform_orders" },
"job_cluster_key": "main"
}],
"schedule": { "quartz_cron_expression": "0 0 2 * * ?", "timezone_id": "UTC" }
})
// Returns: job_id of the created jobRun and wait:
usePower("databricks", "databricks", "manage_job_runs", {
"action": "run_now_and_wait",
"job_id": 123456789
})
// Returns: Run state and task outputsCreate a streaming pipeline:
usePower("databricks", "databricks", "manage_pipeline", {
"action": "create",
"name": "bronze_to_silver_orders",
"target": "main.silver",
"libraries": [{ "notebook": { "path": "/Workspace/dlt/orders_silver" } }],
"continuous": true
})
// Returns: pipeline_idCreate a managed table:
usePower("databricks", "databricks", "manage_uc_objects", {
"action": "create",
"object_type": "table",
"full_name": "main.sandbox.customer",
"columns": [
{ "name": "id", "type_text": "BIGINT" },
{ "name": "email", "type_text": "STRING" }
]
})
// Returns: Table object with metadataGrant SELECT to a group:
usePower("databricks", "databricks", "manage_uc_grants", {
"action": "grant",
"securable_type": "table",
"full_name": "main.sales.orders",
"principal": "analysts",
"privileges": ["SELECT"]
})
// Returns: Updated permission assignmentsAsk Genie a natural-language question:
usePower("databricks", "databricks", "ask_genie", {
"space_id": "01ef...",
"question": "What were the top 5 products by revenue last month?"
})
// Returns: Generated SQL, result rows, narrative explanationSimilarity search over a managed index:
usePower("databricks", "databricks", "query_vs_index", {
"index_name": "main.search.docs_idx",
"query_text": "How do I configure Auto Loader for Parquet?",
"num_results": 5
})
// Returns: Top-5 matched documents with scoresQuery an endpoint:
usePower("databricks", "databricks", "manage_serving_endpoint", {
"action": "query",
"endpoint_name": "claims-classifier",
"inputs": { "dataframe_records": [{ "claim_text": "..." }] }
})
// Returns: Model predictions// Step 1: Create the bronze→silver pipeline
const pipeline = usePower("databricks", "databricks", "manage_pipeline", {
"action": "create",
"name": "orders_silver",
"target": "main.silver",
"libraries": [{ "notebook": { "path": "/Workspace/dlt/orders_silver" } }]
})
// Step 2: Wrap the pipeline in a scheduled job
const job = usePower("databricks", "databricks", "manage_jobs", {
"action": "create",
"name": "orders_silver_orchestrator",
"tasks": [{
"task_key": "run_dlt",
"pipeline_task": { "pipeline_id": pipeline.pipeline_id }
}],
"schedule": { "quartz_cron_expression": "0 0 * * * ?", "timezone_id": "UTC" }
})
// Step 3: Trigger an initial run and wait
const run = usePower("databricks", "databricks", "manage_job_runs", {
"action": "run_now_and_wait",
"job_id": job.job_id
})
// Step 4: Verify rows landed in silver
const stats = usePower("databricks", "databricks", "get_table_stats_and_schema", {
"table_name": "main.silver.orders"
})// Step 1: Create the table
usePower("databricks", "databricks", "manage_uc_objects", {
"action": "create",
"object_type": "table",
"full_name": "main.analytics.daily_revenue",
"columns": [
{ "name": "day", "type_text": "DATE" },
{ "name": "revenue", "type_text": "DECIMAL(18,2)" }
]
})
// Step 2: Grant access
usePower("databricks", "databricks", "manage_uc_grants", {
"action": "grant",
"securable_type": "table",
"full_name": "main.analytics.daily_revenue",
"principal": "analysts",
"privileges": ["SELECT"]
})
// Step 3: Tag for discovery
usePower("databricks", "databricks", "manage_uc_tags", {
"action": "set",
"object": { "type": "table", "full_name": "main.analytics.daily_revenue" },
"tags": { "domain": "finance", "tier": "gold" }
})
// Step 4: Publish a dashboard
usePower("databricks", "databricks", "manage_dashboard", {
"action": "create",
"name": "Daily Revenue",
"warehouse_id": "abc123def456",
"dataset_query": "SELECT * FROM main.analytics.daily_revenue ORDER BY day DESC"
})// Step 1: Create a vector search endpoint
usePower("databricks", "databricks", "manage_vs_endpoint", {
"action": "create",
"name": "kb-endpoint"
})
// Step 2: Create an index over governed docs
usePower("databricks", "databricks", "manage_vs_index", {
"action": "create",
"endpoint_name": "kb-endpoint",
"index_name": "main.kb.docs_idx",
"source_table": "main.kb.docs",
"primary_key": "doc_id",
"embedding_source_column": "content"
})
// Step 3: Wire up the Knowledge Assistant
const ka = usePower("databricks", "databricks", "manage_ka", {
"action": "create",
"name": "internal-kb-assistant",
"vector_index": "main.kb.docs_idx"
})
// Step 4: Query Genie or the assistant directly
usePower("databricks", "databricks", "query_vs_index", {
"index_name": "main.kb.docs_idx",
"query_text": "What is our incident escalation policy?",
"num_results": 5
})The MCP server runs SQL through Databricks SQL warehouses (Photon-accelerated ANSI SQL with Delta and Unity Catalog extensions).
Three-part naming (always use it):
SELECT * FROM <catalog>.<schema>.<table>Time travel:
SELECT * FROM main.sales.orders VERSION AS OF 42;
SELECT * FROM main.sales.orders TIMESTAMP AS OF '2026-05-01';MERGE for upserts:
MERGE INTO target t USING source s ON t.id = s.id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;Materialized views (Delta Live / DBSQL):
CREATE MATERIALIZED VIEW main.gold.orders_daily AS
SELECT order_date, COUNT(*) AS n FROM main.silver.orders GROUP BY order_date;Streaming tables (DLT):
CREATE OR REFRESH STREAMING TABLE bronze_orders
AS SELECT * FROM cloud_files('/Volumes/main/raw/orders', 'json');- Always fully qualify with
catalog.schema.table— UC enforces three-part naming - Use parameter markers for user input:
:param_name(passed inparametersarg) - Set a
wait_timeoutfor long queries (e.g.,"30s"); poll with subsequent calls if needed - Prefer warehouses over clusters for SQL — cheaper, faster cold start, Photon-enabled
- Use
OPTIMIZEandVACUUMon Delta tables for performance/storage hygiene - Check warehouse state before executing — start with
list_computeif unsure
- Start with
get_current_userto confirm workspace, profile, and entitlements before doing real work - Use SQL warehouses for SQL — they're cheaper, auto-suspend, and Photon-accelerated
- Use Unity Catalog three-part names everywhere (
catalog.schema.object) - Tag and grant on creation — wire up
manage_uc_tagsandmanage_uc_grantsimmediately aftermanage_uc_objects - Track resources — use
list_tracked_resourcesto audit what this session created; clean up withdelete_tracked_resource - Pin pipelines and jobs to specific cluster policies for cost control
- Validate schemas with
get_table_stats_and_schemabefore writing transformations - Prefer DLT (manage_pipeline) over hand-rolled jobs for streaming and CDC
- Wait on runs explicitly (
run_now_and_wait) when downstream steps depend on output - Load skill files on demand — don't pre-load all 35+ skills; the on-demand pattern is faster
- Don't run SQL on interactive clusters when a warehouse will do — cost spikes and cold-start delays
- Don't omit catalog/schema — relying on session defaults breaks portability
- Don't hardcode warehouse IDs or job IDs — fetch them with
list_computeandmanage_jobs(action: list) - Don't grant
ALL_PRIVILEGESwhenSELECTorMODIFYis enough - Don't create resources without tagging — UC tags are the only durable discovery mechanism
- Don't skip
wait_timeoutonexecute_sql— the default may not suit long-running statements - Don't disable workspace safeguards (deletion protection, cluster policies) without explicit need
- Don't store PATs in source code — use
~/.databrickscfgprofiles or environment variables
Cause: mcp.json has "disabled": true (default state ships disabled for safety).
Solution:
- Complete the onboarding steps (see Configuration)
- Set
"disabled": falsein~/.kiro/settings/mcp.jsonunder the Power'smcpServers.databricksentry - Reload Kiro to reconnect the server
Cause: Profile in ~/.databrickscfg is missing, expired, or doesn't match DATABRICKS_CONFIG_PROFILE.
Solution:
- Run
databricks auth login --profile <name>to refresh OAuth - Or update
mcp.jsonto use explicitDATABRICKS_HOST+DATABRICKS_TOKENenv vars - Verify with
get_current_user— it should return a valid user
Cause: Compute is stopped; execute_sql / execute_code requires a running compute.
Solution:
- Use
manage_sql_warehouse(action: start) ormanage_cluster(action: start) - Or rely on serverless warehouses — they auto-start on first query
- Re-run the original tool call
Cause: The authenticated user lacks the required UC privilege. Solution:
- Use
manage_uc_grants(action: list) to inspect current grants - Have a metastore admin grant the missing privilege
- Confirm
USE CATALOGandUSE SCHEMAare also granted (often forgotten)
Cause: A DLT expectation rejected rows. Solution:
- Inspect pipeline events with
manage_pipeline_run(action: get_update) - Loosen
EXPECTconstraints or move toEXPECT ... ON VIOLATION DROP ROWif the data is genuinely dirty - Check upstream sources for schema drift
Cause: Installer non-zero exit can be misleading; sometimes the genuine failure is a missing prerequisite. Solution:
- Verify
uvandgitare installed and onPATH - Re-run with
--forceand watch for the line that mentionsuv venvfailing - Check disk space in
$HOME
Cause: The upstream databricks-solutions/apx repository ships SKILL.md with a frontmatter name:
field (apx) that doesn't match the directory name (databricks-app-apx) the installer creates. Kiro flags the
mismatch but loads the skill anyway.
Impact: None — the skill is functional, just registered under a different internal name. The warning is cosmetic.
Solution: No action needed. Patching the local file is not durable (the next skill update overwrites it).
The proper fix is upstream: file an issue at https://github.com/databricks-solutions/apx requesting the
frontmatter name: field be aligned with the distributed directory name.
- uv — Python package manager (install)
- git — Version control
- Databricks workspace — AWS, Azure, or GCP
- Databricks CLI (optional, for OAuth login) — install
The installer pulls skills from four upstream sources (databricks-solutions/ai-dev-kit/databricks-skills/, mlflow/skills/, databricks-solutions/apx/, databricks/databricks-agent-skills/) and writes them into ~/.kiro/skills/. To track exactly which skills this Power is responsible for — so we can move them precisely in Step 2 and clean them up precisely on uninstall — snapshot the directory before the installer runs.
# Snapshot the pre-install state (empty list is fine if the directory doesn't exist yet)
mkdir -p "$HOME/.kiro/skills"
ls -1 "$HOME/.kiro/skills" 2>/dev/null | sort > /tmp/kiro-skills-before.txt
# Run the installer
bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.sh) --tools kiro --global --silentThe installer may exit non-zero even on success. Verify with:
ls ~/.ai-dev-kit/.venv/bin/python && ls ~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py && ls ~/.kiro/skills/ | head -5
Installer flags:
--tools kiro— Configure for Kiro only--global— Install skills to~/.kiro/skills/and MCP config to~/.kiro/settings/mcp.json--silent— Non-interactive (defaults: all skills, DEFAULT profile)--profile PROFILE_NAME— Use a specific Databricks CLI profile--force— Reinstall even if up to date--skills-only— Skip MCP server setup
Use the pre-install snapshot from Step 1 to compute exactly which skill directories the installer added. Persist that list as a manifest inside the Power's installed directory so future updates and the uninstall flow operate on the exact same set of files (no glob guessing, no leftover skills, no accidental deletion of unrelated files).
Agent execution note: Run the bash block below as a single inline bash -c '...' invocation. Do not write it to a scratch file like /tmp/kiro-step2.sh
first — Kiro's sandbox blocks Write-tool writes to /tmp/, even though shell-internal redirects (e.g., > /tmp/kiro-skills-after.txt from inside
bash -c) are allowed. Skipping the file-write attempt avoids a noisy "Access denied" error and lets execution succeed on the first try.
POWER_DIR="$HOME/.kiro/powers/installed/databricks"
POWER_STEERING="$POWER_DIR/steering"
MANIFEST="$POWER_DIR/.skill-manifest.txt"
# Snapshot post-install state
ls -1 "$HOME/.kiro/skills" 2>/dev/null | sort > /tmp/kiro-skills-after.txt
# Compute the diff: skills that exist now but didn't before. This is what the installer added.
comm -13 /tmp/kiro-skills-before.txt /tmp/kiro-skills-after.txt > "$MANIFEST.tmp"
# Reset the steering directory and write the manifest
rm -rf "$POWER_STEERING"
mkdir -p "$POWER_STEERING"
mv "$MANIFEST.tmp" "$MANIFEST"
# Copy each manifested skill into the Power's steering directory, then delete the original
while IFS= read -r skill; do
[ -z "$skill" ] && continue
src="$HOME/.kiro/skills/$skill"
if [ -e "$src" ]; then
cp -r "$src" "$POWER_STEERING/$skill"
rm -rf "$src"
fi
done < "$MANIFEST"
# Clean up scratch files
rm -f /tmp/kiro-skills-before.txt /tmp/kiro-skills-after.txt
echo "Installed $(wc -l < "$MANIFEST" | tr -d ' ') skills to $POWER_STEERING"
echo "Manifest saved to $MANIFEST"Why this is more robust than glob-based cleanup:
- The manifest captures the exact set of skills the installer wrote, regardless of upstream naming conventions or new skill sources added later
- Uninstall and update flows can replay the manifest to remove or refresh only what the Power owns — no risk of deleting skills installed by other tools
- The manifest is human-readable; you can
cat ~/.kiro/powers/installed/databricks/.skill-manifest.txtto audit what the Power is responsible for
Edge case — incremental reinstall: if comm -13 returns an empty manifest (e.g., you re-ran Step 1 without first removing ~/.kiro/skills/), the installer detected the skills were already installed and skipped them. In that case, regenerate the manifest from the existing steering directory:
ls -1 "$POWER_STEERING" 2>/dev/null | sort > "$MANIFEST"This scopes skills to the Power (loaded only when the Power is active) and removes duplicates from the global skills namespace. Click Update on the Databricks Power in Kiro afterward to refresh the steering files list.
⚠️ Agent behavior (REQUIRED): Kiro's user-levelmcp.jsonschema requires a top-levelmcpServerskey to exist (even if empty) alongside thepowersblock. After a fresh install of just this Power, that top-level key may be missing, and Kiro will surface this error:Invalid mcp.json format in user directory: [{ "code": "invalid_type", "expected": "object", "received": "undefined", "path": ["mcpServers"], "message": "Required" }]Before proceeding to Step 3, the agent MUST check
~/.kiro/settings/mcp.jsonand fix it if needed.
Three cases to handle:
Case 1 — File does not exist. Create it with the minimum valid shape:
{
"mcpServers": {},
"powers": {
"mcpServers": {}
}
}Case 2 — File exists but the top-level mcpServers key is missing. This is the usual post-install state. Add the key without disturbing anything else:
Before:
{
"powers": {
"mcpServers": {
"power-databricks-databricks": { ... }
}
}
}After:
{
"mcpServers": {},
"powers": {
"mcpServers": {
"power-databricks-databricks": { ... }
}
}
}Case 3 — Top-level mcpServers already exists (e.g., the ai-dev-kit installer wrote its own databricks entry there, or another Power did). Leave it alone — schema is already valid. Proceed to Step 3.
Idempotent fix command (Unix; uses jq if available, otherwise prints instructions):
MCP_CFG="$HOME/.kiro/settings/mcp.json"
if [ ! -f "$MCP_CFG" ]; then
mkdir -p "$(dirname "$MCP_CFG")"
printf '%s\n' '{' ' "mcpServers": {},' ' "powers": { "mcpServers": {} }' '}' > "$MCP_CFG"
echo "Created $MCP_CFG with minimum valid shape."
elif command -v jq >/dev/null 2>&1; then
if ! jq -e '.mcpServers' "$MCP_CFG" >/dev/null 2>&1; then
tmp=$(mktemp)
jq '. + {mcpServers: (.mcpServers // {})}' "$MCP_CFG" > "$tmp" && mv "$tmp" "$MCP_CFG"
echo "Added top-level mcpServers: {} to $MCP_CFG."
else
echo "Top-level mcpServers already present — no changes needed."
fi
else
echo "jq not installed. Open $MCP_CFG and ensure the top-level object contains a 'mcpServers' key (use {} if you have no top-level MCP servers)."
fiAfter fixing, reload Kiro to clear the validation error before continuing to Step 2.6.
⚠️ Agent behavior (REQUIRED): Step 1's installer (install.sh) writes a top-levelmcpServers.databricksentry to~/.kiro/settings/mcp.json. That entry was designed for users running ai-dev-kit without a Kiro Power — for our flow it is a duplicate registration of the same MCP server the Power owns. Leaving both entries in place causes Kiro to launch two copies of the server (same binary, two different env blocks), which can confuse tool routing.The agent MUST delete the top-level
mcpServers.databricksentry after the installer runs, leaving only the Power's entry underpowers.mcpServers.power-databricks-databricks.
Idempotent fix command:
MCP_CFG="$HOME/.kiro/settings/mcp.json"
if command -v jq >/dev/null 2>&1; then
if jq -e '.mcpServers.databricks' "$MCP_CFG" >/dev/null 2>&1; then
tmp=$(mktemp)
jq 'del(.mcpServers.databricks)' "$MCP_CFG" > "$tmp" && mv "$tmp" "$MCP_CFG"
echo "Removed standalone mcpServers.databricks entry."
else
echo "No standalone entry to remove — already clean."
fi
else
echo "jq not installed. Open $MCP_CFG and delete the 'mcpServers.databricks' object manually, leaving 'mcpServers' as {} or with other entries you intentionally configured."
fiBefore:
{
"mcpServers": {
"databricks": {
"command": "/Users/<you>/.ai-dev-kit/.venv/bin/python",
"args": ["/Users/<you>/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"],
"defer_loading": true,
"env": { "DATABRICKS_CONFIG_PROFILE": "DEFAULT" }
}
},
"powers": {
"mcpServers": {
"power-databricks-databricks": { ... }
}
}
}After:
{
"mcpServers": {},
"powers": {
"mcpServers": {
"power-databricks-databricks": { ... }
}
}
}Reload Kiro to drop the now-removed standalone server connection. The Power's entry under powers.mcpServers is the one that runs from here on.
If you have OTHER MCP servers (not
databricks) under top-levelmcpServersthat you intentionally configured for non-Power use, thejqsnippet above leaves them alone — it only removes thedatabrickskey.
⚠️ Agent behavior (REQUIRED): The Power's bundledmcp.jsonships with~/.ai-dev-kit/...paths (tilde for the user's home directory). Kiro copies these paths verbatim into~/.kiro/settings/mcp.jsonunderpowers.mcpServers.power-databricks-databricks. Node'schild_process.spawn()does not expand~— it looks for a literal directory named~, which doesn't exist, and the MCP server fails to launch with:Error connecting to MCP server: spawn ~/.ai-dev-kit/.venv/bin/python ENOENTThe agent MUST replace
~with the absolute home path in bothcommandand every entry inargsbefore the server can launch.
Idempotent fix command:
MCP_CFG="$HOME/.kiro/settings/mcp.json"
HOME_PATH="$HOME"
if command -v jq >/dev/null 2>&1; then
tmp=$(mktemp)
jq --arg h "$HOME_PATH" '
if .powers.mcpServers["power-databricks-databricks"] then
.powers.mcpServers["power-databricks-databricks"].command |= ($h + (.|ltrimstr("~"))) |
.powers.mcpServers["power-databricks-databricks"].args |= map($h + (.|ltrimstr("~")))
else . end
' "$MCP_CFG" > "$tmp" && mv "$tmp" "$MCP_CFG"
echo "Expanded ~ to $HOME_PATH in command and args."
else
echo "jq not installed. Open $MCP_CFG and replace ~/.ai-dev-kit/... with $HOME/.ai-dev-kit/... in both 'command' and every entry of 'args'."
fiBefore:
"command": "~/.ai-dev-kit/.venv/bin/python",
"args": ["~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"]After (assuming $HOME = /Users/visvenky):
"command": "/Users/visvenky/.ai-dev-kit/.venv/bin/python",
"args": ["/Users/visvenky/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"]The transformation is per-user (your $HOME ends up baked in), so this fix has to run on each developer's machine — it can't be pre-applied in the bundled file.
Verify the binaries exist at the expanded paths:
ls -la "$HOME/.ai-dev-kit/.venv/bin/python"
ls -la "$HOME/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"If either is missing, Step 1's installer didn't complete — re-run it. Otherwise, reload Kiro; the ENOENT error should clear.
The Power ships with a baseline mcp.json that uses an env-var reference for the profile name and is disabled by default for safety. Pick one of the four options below and apply the matching "after" configuration.
⚠️ Agent behavior during onboarding (REQUIRED):Before configuring or modifying any credentials, the agent MUST:
Check for existing credentials in two locations:
- The top-level
mcpServersblock in~/.kiro/settings/mcp.json(e.g., from a prior installation or another Databricks-using Power)- Profiles in
~/.databrickscfgShow the user enough to identify the credentials, but never the full secret. The user needs to recognize which credential they are looking at — show identifiers and short prefix/suffix fingerprints — but the bulk of the secret must not be echoed.
Display this Hide this Profile name (e.g., [DEFAULT],[prod-aws])— Workspace host URL — auth_typefield value— client_id(full — it's a public identifier)client_secret(only first 4 + last 4 chars; never the middle)PAT in the form dapi+ 4 chars +***+ last 4 chars (e.g.,dapi5f2a***4f2c), plus token comment if presentThe middle of the PAT OAuth secret first 4 + ***+ last 4 chars (e.g.,abcd***9z8y), plus last-modified date if knownThe middle of the secret OAuth U2M auth_type = databricks-clilabel onlyCached access/refresh tokens from ~/.databricks/token-cache.jsonPreserving the
dapiprefix on PATs makes the token type unmistakable; the 4-char fingerprints on either side are enough for the user to recognize a credential they generated themselves (matching it against their notes or a credential manager) without exposing usable token material.Ask for explicit confirmation before reusing detected credentials. Repeat the credential fingerprint inline in each reuse choice so the user sees exactly what they are authorizing at the moment of decision (don't make them scroll back up to the summary). Offer:
- One reuse choice per detected credential — each with its host + masked token/secret fingerprint inline (e.g., "Reuse the [prod-aws] PAT — host
https://<your-workspace>.cloud.databricks.com, tokendapi5f2a***4f2c")- One choice to configure a different authentication option (A / B / C / D below)
- One choice to skip — the user will edit
mcp.jsonthemselvesNever copy credentials between configurations without explicit user approval. Silent reuse is not acceptable, even when the credentials appear identical or compatible.
Present the choices neutrally. Do not label any option as "recommended", "quickest", or "easiest" — credential reuse is the user's decision on its merits, not the agent's recommendation.
Always present all four options in A → B → C → D order, even when no credentials are detected for a given option. Do not skip an option because detection found nothing for it — instead, show it with the "no credentials found, here's how to set up" path. Skipping options (e.g., showing only B/C/D, or A/C/D) makes the list look broken and confuses the user. The list must always read A, B, C, D — never B, C, D or A, B, D.
Example of an acceptable summary the agent shows the user:
Found existing Databricks configuration: ~/.kiro/settings/mcp.json (top-level mcpServers.databricks): host = https://<your-workspace>.cloud.databricks.com auth method = OAuth U2M (via DATABRICKS_CONFIG_PROFILE=DEFAULT) ~/.databrickscfg: [DEFAULT] host = https://<your-workspace>.cloud.databricks.com auth_type = databricks-cli [prod-aws] host = https://<your-workspace-prod>.cloud.databricks.com auth_type = pat token = dapi5f2a***4f2c (dapi prefix + 4 + last 4) comment = "Power onboarding 2026-05-19" [ci-sp] host = https://<your-workspace>.cloud.databricks.com client_id = 1a2b3c4d-5e6f-7890-abcd-ef1234567890 client_secret = abcd***9z8y (first 4 + last 4 only) Would you like to: 1. Reuse the [DEFAULT] profile for this Power (host: https://<your-workspace>.cloud.databricks.com, auth: OAuth U2M) 2. Reuse the [prod-aws] PAT for this Power (host: https://<your-workspace-prod>.cloud.databricks.com, token: dapi5f2a***4f2c) 3. Reuse the [ci-sp] service principal for this Power (host: https://<your-workspace>.cloud.databricks.com, client_id: 1a2b3c4d-..., secret: abcd***9z8y) 4. Configure a different auth option (A / B / C / D below) 5. Skip — I'll edit mcp.json myself
This is the file you'll find at ~/.kiro/powers/installed/databricks/mcp.json immediately after installation. The ${DATABRICKS_CONFIG_PROFILE} reference is resolved from your shell environment when Kiro launches the server.
{
"mcpServers": {
"databricks": {
"command": "~/.ai-dev-kit/.venv/bin/python",
"args": ["~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"],
"env": {
"DATABRICKS_CONFIG_PROFILE": "${DATABRICKS_CONFIG_PROFILE}"
},
"disabled": true
}
}
}All four options below modify the runtime MCP config at
~/.kiro/settings/mcp.json(underpowers.mcpServers.power-databricks-databricks), not the bundled file above. Kiro mirrors the bundled config there during Power activation.Where credentials are read from: the MCP server reads its environment from the
envblock ofmcp.jsonat the moment Kiro launches it. Pick the option whose env block matches the credentials you have, then editmcp.jsondirectly.
The cleanest long-term setup is to keep all your Databricks credentials in one place: ~/.databrickscfg. Every Databricks tool on your machine — the CLI, Terraform provider, VS Code extension, local notebooks, this Power — reads the same file, so you set it up once and get a consistent identity everywhere. Switching environments becomes a one-line shell change (export DATABRICKS_CONFIG_PROFILE=u2m-prod) instead of editing mcp.json every time.
Use a naming convention that encodes both the environment and the auth method, so it's obvious what each profile does at a glance: <auth>-<env> (e.g., u2m-dev, m2m-dev, pat-dev, then the same for qa and prod).
Step-by-step:
-
Create your U2M profiles first with
databricks auth login— one per environment. The CLI writes the[u2m-*]blocks for you:databricks auth login --host https://<dev-workspace>.cloud.databricks.com --profile u2m-dev databricks auth login --host https://<qa-workspace>.cloud.databricks.com --profile u2m-qa databricks auth login --host https://<prod-workspace>.cloud.databricks.com --profile u2m-prod
-
Add M2M and PAT profiles by hand if you need them. Open
~/.databrickscfgin an editor and append blocks. The CLI does not write these for you. -
Lock the file down so secrets aren't world-readable:
chmod 600 ~/.databrickscfg
Reference template — fill in only the environments and auth methods you actually use:
# ~/.databrickscfg
# Naming: <auth>-<env>
# Auth methods: u2m (interactive), m2m (service principal), pat (legacy)
[u2m-dev]
host = https://<dev-workspace>.cloud.databricks.com
auth_type = databricks-cli
[u2m-qa]
host = https://<qa-workspace>.cloud.databricks.com
auth_type = databricks-cli
[u2m-prod]
host = https://<prod-workspace>.cloud.databricks.com
auth_type = databricks-cli
[m2m-dev]
host = https://<dev-workspace>.cloud.databricks.com
client_id = <dev-service-principal-application-id>
client_secret = <dev-oauth-secret>
[m2m-qa]
host = https://<qa-workspace>.cloud.databricks.com
client_id = <qa-service-principal-application-id>
client_secret = <qa-oauth-secret>
[m2m-prod]
host = https://<prod-workspace>.cloud.databricks.com
client_id = <prod-service-principal-application-id>
client_secret = <prod-oauth-secret>
[pat-dev]
host = https://<dev-workspace>.cloud.databricks.com
token = dapi...
[pat-qa]
host = https://<qa-workspace>.cloud.databricks.com
token = dapi...
[pat-prod]
host = https://<prod-workspace>.cloud.databricks.com
token = dapi...Switching environments at runtime:
export DATABRICKS_CONFIG_PROFILE=u2m-dev # work in dev
# Kiro restart / MCP server reconnect
export DATABRICKS_CONFIG_PROFILE=u2m-prod # switch to prod
# Kiro restart / MCP server reconnectThe Power's mcp.json env block stays exactly what ships by default — {"DATABRICKS_CONFIG_PROFILE": "${DATABRICKS_CONFIG_PROFILE}"} — and Option A handles all three auth methods because the Databricks SDK reads the profile and picks the matching flow. This means you almost never need Options B / C / D once your ~/.databrickscfg is set up.
When you don't need this:
- You only ever work against one Databricks workspace with one auth method → a single
[DEFAULT]profile (or the env-var options below) is fine. - You don't have permission to install/run
databricks auth loginand don't want to hand-write profiles → skip to Options C or D and use shell env vars directly.
Quick reference (try in this order — A first if you've used Databricks CLI before):
| Option | Method | Best for | Token lifetime | Status |
|---|---|---|---|---|
| A | Existing ~/.databrickscfg profile |
You already have a working profile | Depends on the underlying auth in the profile | Recommended (check first) |
| B | OAuth U2M (CLI login) | Interactive use by a human, no existing profile | 1 h, auto-refreshed | Recommended |
| C | OAuth M2M (service principal) | Headless / CI/CD / production agents | 1 h access token; secret up to 730 days | Recommended |
| D | Personal Access Token (PAT) | Tools that don't support OAuth | Up to 730 days; auto-revoked after 90 days unused | Legacy — Databricks recommends OAuth instead |
Reference: OAuth U2M · OAuth M2M · PAT (legacy)
This is the first option to try because it reuses what you already have. If you've used the Databricks CLI before, run other Databricks tools (Terraform, VS Code extension, notebooks), or have a profile set up via databricks auth login, manual editing, or a configuration-management tool — just point the env reference at it. The underlying auth method (OAuth U2M, OAuth M2M, or PAT) is whatever the profile already uses. If no profile exists, fall through to Option B.
Agent reuse-detection for Option A: The agent MUST enumerate every profile in
~/.databrickscfg, showing host,auth_type, and a credential fingerprint appropriate to the profile's auth method, so the user can pick one explicitly. Example:Profiles in ~/.databrickscfg: 1. [DEFAULT] host = https://<your-workspace>.cloud.databricks.com auth_type = databricks-cli (OAuth U2M — no static credential) 2. [prod-aws] host = https://<your-workspace-prod>.cloud.databricks.com auth_type = pat token = dapi5f2a***4f2c (dapi prefix + 4 + last 4) 3. [ci-sp] host = https://<your-workspace>.cloud.databricks.com client_id = 1a2b3c4d-5e6f-7890-abcd-ef1234567890 client_secret = abcd***9z8y (first 4 + last 4 only)If
~/.databrickscfgdoes not exist or has no profiles, the agent MUST say so explicitly — e.g., "No~/.databrickscfgprofiles found. To create one, see Option B (OAuth U2M viadatabricks auth login) below." — and offer to switch the user to Option B.
Export the chosen profile name in your shell (substitute the profile you actually want — DEFAULT, prod-aws, u2m-dev, etc.):
export DATABRICKS_CONFIG_PROFILE=<profile-name>Before (as shipped):
{
"mcpServers": {
"databricks": {
"command": "~/.ai-dev-kit/.venv/bin/python",
"args": ["~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"],
"env": {
"DATABRICKS_CONFIG_PROFILE": "${DATABRICKS_CONFIG_PROFILE}"
},
"disabled": true
}
}
}After (Option A applied — same env reference, just enable the server):
{
"mcpServers": {
"databricks": {
"command": "~/.ai-dev-kit/.venv/bin/python",
"args": ["~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"],
"env": {
"DATABRICKS_CONFIG_PROFILE": "${DATABRICKS_CONFIG_PROFILE}"
},
"disabled": false
}
}
}Per Databricks docs, "Values in
.databrickscfgtake precedence over environment variables" — so if your profile has ahostset, that takes precedence overDATABRICKS_HOST.
OAuth user-to-machine: the Databricks CLI opens a browser, you authenticate as yourself, and credentials land in ~/.databrickscfg. Each access token is valid for one hour and is auto-refreshed by the Databricks SDK. This is the safest interactive flow because there's no long-lived secret to leak.
Agent reuse-detection for Option B: If
~/.databrickscfgcontains profiles withauth_type = databricks-cli, the agent MUST list each one with its host so the user can pick which to use, e.g.:Found OAuth U2M profiles in ~/.databrickscfg: 1. [DEFAULT] host = https://<your-workspace>.cloud.databricks.com 2. [prod-aws] host = https://<your-workspace-prod>.cloud.databricks.com 3. Run a fresh databricks auth login (creates a new profile)If no U2M profiles exist, say so explicitly and walk the user through
databricks auth loginbelow.
databricks auth login --host https://<your-workspace>.cloud.databricks.com --profile DEFAULTThis writes a profile to ~/.databrickscfg like:
[DEFAULT]
host = https://<your-workspace>.cloud.databricks.com
auth_type = databricks-cliThen export the profile name in your shell so the ${DATABRICKS_CONFIG_PROFILE} reference in mcp.json resolves correctly when Kiro launches the MCP server:
export DATABRICKS_CONFIG_PROFILE=DEFAULTBefore (~/.kiro/settings/mcp.json — Power entry as shipped):
{
"mcpServers": {
"databricks": {
"command": "~/.ai-dev-kit/.venv/bin/python",
"args": ["~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"],
"env": {
"DATABRICKS_CONFIG_PROFILE": "${DATABRICKS_CONFIG_PROFILE}"
},
"disabled": true
}
}
}After (Option B applied):
{
"mcpServers": {
"databricks": {
"command": "~/.ai-dev-kit/.venv/bin/python",
"args": ["~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"],
"env": {
"DATABRICKS_CONFIG_PROFILE": "${DATABRICKS_CONFIG_PROFILE}"
},
"disabled": false
}
}
}The only edit is "disabled": true → "disabled": false. The env reference and shell variable do the rest.
OAuth machine-to-machine: a Databricks service principal authenticates with client_id + client_secret and the SDK auto-issues 1-hour access tokens with no browser flow. Use this for production agents, scheduled jobs, and shared environments. Per Databricks docs, this is intended for "unattended processes, such as automated CLI commands or REST API calls made from scripts or applications."
Agent reuse-detection for Option C: If
~/.databrickscfgcontains profiles withclient_idset, or the shell environment hasDATABRICKS_CLIENT_ID/DATABRICKS_CLIENT_SECRET, the agent MUST list each candidate with itsclient_id(full) and secret fingerprint so the user can recognize it, e.g.:Found OAuth M2M credentials: 1. ~/.databrickscfg [ci-sp] host = https://<your-workspace>.cloud.databricks.com client_id = 1a2b3c4d-5e6f-7890-abcd-ef1234567890 client_secret = abcd***9z8y (first 4 + last 4 only) 2. Shell env DATABRICKS_CLIENT_ID host = https://<your-workspace>.cloud.databricks.com client_id = 9z8y7x6w-...-fedcba0987654321 client_secret = wxyz***1234 (first 4 + last 4 only) 3. Generate a new service principal + OAuth secret (steps below)If no M2M credentials are detected, say so explicitly and walk the user through the Prerequisites below.
Prerequisites:
- Create a service principal in the Databricks account console (Identity and access → Service principals)
- Grant workspace entitlements and permissions so the SP can do what you need
- Generate an OAuth secret — Settings → Identity and access → Service principals → select SP → Secrets tab → Generate secret. Set lifetime up to 730 days (max). Copy
client_idandclient_secretimmediately — the secret is shown only once. A service principal can have up to 5 active OAuth secrets.
Export the three environment variables in your shell so the ${VAR} references in mcp.json resolve when Kiro launches the MCP server:
export DATABRICKS_HOST="https://<your-workspace>.cloud.databricks.com"
export DATABRICKS_CLIENT_ID="<service-principal-application-id>"
export DATABRICKS_CLIENT_SECRET="<oauth-secret>"Before (as shipped):
{
"mcpServers": {
"databricks": {
"command": "~/.ai-dev-kit/.venv/bin/python",
"args": ["~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"],
"env": {
"DATABRICKS_CONFIG_PROFILE": "${DATABRICKS_CONFIG_PROFILE}"
},
"disabled": true
}
}
}After (Option C applied — replace profile env with host + client credentials):
{
"mcpServers": {
"databricks": {
"command": "~/.ai-dev-kit/.venv/bin/python",
"args": ["~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"],
"env": {
"DATABRICKS_HOST": "${DATABRICKS_HOST}",
"DATABRICKS_CLIENT_ID": "${DATABRICKS_CLIENT_ID}",
"DATABRICKS_CLIENT_SECRET": "${DATABRICKS_CLIENT_SECRET}"
},
"disabled": false
}
}
}Never hardcode
client_secretin the JSON file. Reference it through${DATABRICKS_CLIENT_SECRET}and source it from a secret manager (HashiCorp Vault, AWS Secrets Manager, OS keychain) or environment-injection mechanism appropriate to your runtime.ai-dev-kit's MCP server README only documents PAT and profile auth, but the underlying Databricks SDK's unified-auth chain detects M2M credentials automatically — no MCP-server-side change required beyond the env block above.
Databricks officially marks PAT as legacy. From the docs: "Where possible, Databricks recommends using OAuth instead of PATs for user account authentication because OAuth provides stronger security." Use this only if Options A–C aren't available — for example, an automated tool that doesn't support OAuth and where you can't use a service principal.
Agent reuse-detection for Option D: If
~/.databrickscfgcontains profiles withtokenset (orauth_type = pat), or the shell environment hasDATABRICKS_TOKEN, or the top-levelmcpServersblock in~/.kiro/settings/mcp.jsonalready has a PAT configured, the agent MUST list each candidate with its host and PAT fingerprint, e.g.:Found existing PATs: 1. ~/.kiro/settings/mcp.json (top-level mcpServers.databricks) host = https://<your-workspace>.cloud.databricks.com token = dapi5f2a***4f2c (dapi prefix + 4 + last 4) 2. ~/.databrickscfg [prod-aws] host = https://<your-workspace-prod>.cloud.databricks.com token = dapie8cf***84fc (dapi prefix + 4 + last 4) comment = "Power onboarding 2026-05-19" 3. Generate a new PAT (workspace UI steps below)If no PAT is detected, say so explicitly and walk the user through the Generate a PAT in the workspace UI steps below.
PATs are simple bearer tokens. Constraints worth knowing:
- Lifetime up to ~730 days (set at creation)
- "Databricks automatically revokes PATs that haven't been used for 90 days"
- Up to 600 PATs per workspace
- "You can't use personal access tokens to automate Databricks account-level functionality"
Generate a PAT in the workspace UI:
- Top bar → username → Settings → Developer
- Next to Access tokens, click Manage → Generate new token
- Add a comment, set lifetime in days, optionally restrict scopes
- Click Generate and copy the token immediately (it is shown only once)
Export the host and token in your shell so the ${VAR} references in mcp.json resolve when Kiro launches the MCP server:
export DATABRICKS_HOST="https://<your-workspace>.cloud.databricks.com"
export DATABRICKS_TOKEN="dapi..."Before (as shipped):
{
"mcpServers": {
"databricks": {
"command": "~/.ai-dev-kit/.venv/bin/python",
"args": ["~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"],
"env": {
"DATABRICKS_CONFIG_PROFILE": "${DATABRICKS_CONFIG_PROFILE}"
},
"disabled": true
}
}
}After (Option D applied — replace profile env with host + token):
{
"mcpServers": {
"databricks": {
"command": "~/.ai-dev-kit/.venv/bin/python",
"args": ["~/.ai-dev-kit/repo/databricks-mcp-server/run_server.py"],
"env": {
"DATABRICKS_HOST": "${DATABRICKS_HOST}",
"DATABRICKS_TOKEN": "${DATABRICKS_TOKEN}"
},
"disabled": false
}
}
}Never hardcode a PAT in the JSON file. Always reference it through
${DATABRICKS_TOKEN}and keep the secret in your shell environment, a secret manager, or your OS keychain.
After saving, Kiro auto-reconnects the MCP server. Verify by calling:
usePower("databricks", "databricks", "get_current_user", {})
// Returns: { user_name: "...", workspace_url: "...", entitlements: [...] }A successful response confirms auth, env-var resolution, and server enablement are all wired correctly.
Re-run the snapshot/installer/diff pattern from Steps 1 and 2 so the manifest gets regenerated with any newly-added or removed skills:
# 1. Snapshot the current Power-owned manifest as the "before" baseline
POWER_DIR="$HOME/.kiro/powers/installed/databricks"
ls -1 "$POWER_DIR/steering" 2>/dev/null | sort > /tmp/kiro-skills-before.txt
# 2. Re-run the installer in skills-only force-refresh mode
bash <(curl -sL https://raw.githubusercontent.com/databricks-solutions/ai-dev-kit/main/install.sh) --tools kiro --global --skills-only --force --silent
# 3. Re-run Step 2's diff-and-move snippet to refresh the manifest and steering directoryAfter updating, click Update on the Power in Kiro to pick up any new skills.
The manifest makes uninstall surgical — only the skills this Power owns get removed:
POWER_DIR="$HOME/.kiro/powers/installed/databricks"
MANIFEST="$POWER_DIR/.skill-manifest.txt"
if [ -f "$MANIFEST" ]; then
while IFS= read -r skill; do
[ -z "$skill" ] && continue
rm -rf "$HOME/.kiro/skills/$skill"
done < "$MANIFEST"
fi
rm -rf "$POWER_DIR"This will not touch skills installed by other tools or other Powers, even if they happen to share a name prefix.
- Start with
get_current_userto verify your identity, workspace, and entitlements - Use
list_computefirst when you don't know warehouse/cluster IDs — never hardcode them - Prefer
ask_geniefor ad-hoc questions — it generates SQL and explanations in one shot - Lean on the steering files — each skill encodes idiomatic patterns and gotchas for its domain
- Use Asset Bundles (
databricks-bundlesskill) for production-grade resource definitions over imperative tool calls - Combine
manage_uc_objects+manage_uc_grants+manage_uc_tagsin every table-creation flow - Wait explicitly on long-running runs with
run_now_and_waitrather than polling - Track and clean up sandbox resources with
list_tracked_resources/delete_tracked_resource - Use
get_table_stats_and_schemabefore authoring transformations — schema-on-read surprises are common - Keep
disabled: trueuntil onboarding is complete — flip it only after auth is verified
© 2026 Databricks, Inc. All rights reserved.
The source in this Power is provided subject to the Databricks License. The MCP server and skills installed by this Power are sourced from the databricks-solutions/ai-dev-kit repository and are governed by the same license. See ai-dev-kit's LICENSE.md and NOTICE.txt for full terms and third-party attribution.
Support:
- Power packaging / installation issues — github.com/venkatavaradhanv/databricks/issues
- MCP server, skills, or installer issues — github.com/databricks-solutions/ai-dev-kit/issues
- Databricks platform support — help.databricks.com
- Privacy — databricks.com/legal/privacynotice
Package: databricks-solutions/ai-dev-kit (databricks-mcp-server)
Source: github.com/databricks-solutions/ai-dev-kit
License: Databricks License
Connection: Local Python process via ~/.kiro/settings/mcp.json