agentsclimarketplace

Data source connector

Skill bcastelino/powerbi-dashboard-generator/skills/data-source-connector

Agent Skills toolkit that turns plain-English requests into fully-formed, branded Power BI Desktop Projects (PBIP). Ten composable skills for source-agnostic semantic modeling, visual generation, and theming.

Install
npx -y skills add bcastelino/powerbi-dashboard-generator --skill data-source-connector

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Source-agnostic adapter that introspects any data storage (SQL databases, cloud warehouses, Excel/CSV files, OData/REST APIs, SharePoint lists) and emits a normalized data-model.json describing tables, columns, types, and relationships. Use this skill at the start of the dashboard pipeline whenever the user has not provided a structured data model. It also emits a clarification question list when schema cannot be auto-discovered, and produces the source-specific M-Code / import block consumed by semantic-mapper.

SKILL.md

10.8 KB, ~2.7k tokens by cl100k_base, as published. Nobody here has run it

Data Source Connector

Universal data-source adapter for the Power BI dashboard pipeline. This skill abstracts away the specifics of every supported source and produces a single, normalized artifact — data-model.json — that downstream skills (semantic-mapper, visual-selector, visual-generator) can consume without knowing where the data actually came from.

When to Use This Skill

  • The orchestrator (or the user) has identified a source but no structured data model exists
  • The agent needs to enumerate tables, columns, types, and relationships from any backend
  • A Genie YAML metric view is not available (use this skill instead of semantic-mapper's YAML path)
  • The agent needs the source-specific M-Code / connection block to embed in TMDL partitions

Supported Sources

Source Typetype valueRequired Inputs
Databricksdatabrickshostname, warehouse_id, catalog, schema
Snowflakesnowflakeaccount, warehouse, database, schema, role
BigQuerybigqueryproject, dataset
Azure Synapsesynapseserver, database
SQL Serversqlserverserver, database
PostgreSQLpostgreshost, port, database, schema
MySQLmysqlhost, port, database
Oracleoraclehost, port, service_name
Excelexcelpath (.xlsx file); each sheet becomes a table
CSVcsvpath or directory of CSVs; each file becomes a table
Parquetparquetpath or directory
ODataodataservice_url
REST APIrestbase_url, endpoints[], auth
SharePoint Listssharepointsite_url, list_names[]

Inputs

  • Source descriptor{ type, ...connection params } from the orchestrator or the user
  • Scope hint (optional) — which tables / sheets / endpoints to include (defaults to all)
  • Sampling preference (optional) — number of sample rows to capture per table (default 5)

Outputs

Primary: data-model.json

Source-agnostic, normalized representation. Schema:

{
  "source": {
    "type": "excel",
    "connection": { "path": "C:/data/sales.xlsx" },
    "discoveredAt": "2026-05-13T11:00:00Z"
  },
  "tables": [
    {
      "name": "fact_sales",
      "physicalName": "Orders",
      "role": "fact",
      "grain": "one row per order line",
      "rowCountEstimate": 50000,
      "columns": [
        {
          "name": "order_id",
          "physicalName": "OrderID",
          "dataType": "int64",
          "sourceProviderType": "bigint",
          "isPrimaryKey": true,
          "nullable": false
        },
        {
          "name": "customer_key",
          "physicalName": "CustomerID",
          "dataType": "int64",
          "sourceProviderType": "bigint",
          "isForeignKey": true,
          "foreignKey": { "table": "dim_customer", "column": "customer_key" }
        },
        {
          "name": "total_value",
          "physicalName": "TotalValue",
          "dataType": "double",
          "sourceProviderType": "double",
          "formatHint": "currency"
        }
      ],
      "sampleRows": [
        { "order_id": 1, "customer_key": 42, "total_value": 199.99 }
      ]
    }
  ],
  "relationships": [
    {
      "from": { "table": "fact_sales", "column": "customer_key" },
      "to":   { "table": "dim_customer", "column": "customer_key" },
      "cardinality": "many-to-one",
      "isActive": true,
      "inferredFrom": "naming convention"
    }
  ],
  "mCodeAdapter": {
    "mode": "import",
    "templates": {
      "fact_sales": "let Source = Excel.Workbook(File.Contents(\"C:/data/sales.xlsx\"), null, true), Orders_Sheet = Source{[Item=\"Orders\",Kind=\"Sheet\"]}[Data], #\"Promoted Headers\" = Table.PromoteHeaders(Orders_Sheet, [PromoteAllScalars=true]) in #\"Promoted Headers\""
    }
  },
  "openQuestions": [
    {
      "id": "q1",
      "scope": "relationship",
      "question": "Is the relationship between fact_sales.customer_key and dim_customer.customer_key correct? It was inferred from column-name similarity, not from a foreign key constraint."
    }
  ]
}

Secondary: Clarification report

If schema cannot be fully discovered (missing credentials, ambiguous grain, no FK constraints), emit openQuestions[] for the orchestrator to surface to the user.

Workflow

Step 1: Validate Connection Inputs

For each source type, check that required inputs are present. If any are missing, emit a clarification question and stop.

Examples:

  • databricks missing warehouse_id → ask: "What is the Databricks SQL warehouse ID?"
  • excel missing path → ask: "What is the full path to the Excel file?"
  • sqlserver missing credentials → ask: "Is this a trusted-connection database, or do I need a username and password?"

See references/clarification-questions.md for the full question bank.

Step 2: Probe the Source

Run scripts/introspect_source.py (or the source-specific adapter) to:

  1. List tables / sheets / endpoints
  2. For each table: list columns with native types, nullability, primary key flags
  3. Sample rows: pull 5 sample rows per table (configurable)
  4. Foreign key discovery:
    • If the source supports FK constraints (SQL databases) → use them directly
    • Otherwise → infer from column-name patterns (<table>_key, <table>_id, identical names across tables) and flag as inferredFrom: naming convention for user confirmation at Gate A

Step 3: Classify Tables (Fact vs. Dimension)

Heuristics:

SignalLikely Role
Has multiple FK columns + a numeric measure columnfact
Name contains fact_, sales, orders, transactions, eventsfact
Name contains dim_, customers, products, dates, geographydimension
Only one PK column + descriptive columnsdimension
Has a date column with daily continuitydate dimension

If unsure, add to openQuestions[] and ask the user at Gate A.

Step 4: Normalize Types

Map source-native types to TMDL types (consumed by semantic-mapper):

Source TypedataTypesourceProviderType
STRING, VARCHAR, NVARCHAR, TEXTstringnvarchar(65535)
INT, INTEGER, INT32int64int
BIGINT, LONGint64bigint
DOUBLE, FLOAT, REAL, DECIMAL, NUMERICdoubledouble
DATEdateTimedate
DATETIME, TIMESTAMP, DATETIME2dateTimedatetime2
BOOLEAN, BITbooleanbit

For Excel/CSV with no declared types, sniff from sample rows.

Step 5: Generate the M-Code Adapter Block

Each source has a different M-Code template. Per-source templates live in references/connection-patterns.md. Examples:

Databricks (DirectQuery):

let
    Source = DatabricksMultiCloud.Catalogs("<hostname>", "/sql/1.0/warehouses/<warehouse_id>", [Catalog = "", Database = ""]),
    <catalog>_Database = Source{[Name="<catalog>",Kind="Database"]}[Data],
    <schema>_Schema = <catalog>_Database{[Name="<schema>",Kind="Schema"]}[Data],
    <table>_Table = <schema>_Schema{[Name="<table>",Kind="Table"]}[Data]
in
    <table>_Table

Excel (Import):

let
    Source = Excel.Workbook(File.Contents("<path>"), null, true),
    <sheet>_Sheet = Source{[Item="<sheet>",Kind="Sheet"]}[Data],
    #"Promoted Headers" = Table.PromoteHeaders(<sheet>_Sheet, [PromoteAllScalars=true])
in
    #"Promoted Headers"

CSV (Import):

let
    Source = Csv.Document(File.Contents("<path>"), [Delimiter=",", Columns=<n>, Encoding=65001, QuoteStyle=QuoteStyle.Csv]),
    #"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true])
in
    #"Promoted Headers"

SQL Server (DirectQuery):

let
    Source = Sql.Database("<server>", "<database>"),
    <schema>_<table> = Source{[Schema="<schema>",Item="<table>"]}[Data]
in
    <schema>_<table>

The connector emits one M-Code block per table into data-model.jsonmCodeAdapter.templates.

Step 6: Mode Selection

Set mCodeAdapter.mode based on source:

SourceMode
Databricks, Snowflake, BigQuery, Synapse, SQL Server (large), OracledirectQuery
Excel, CSV, Parquet, SharePoint List, REST APIimport
Postgres, MySQLdirectQuery if user opts in, otherwise import

Step 7: Emit openQuestions

Append a question for every uncertainty:

  • Ambiguous fact/dimension classification
  • Inferred (not declared) foreign keys
  • Multiple date columns (which is the primary date?)
  • Tables with no measurable columns (skip or include?)
  • Files with multiple sheets where some look like junk (e.g., metadata, instructions)

Outputs Handed to Downstream

FileConsumerPurpose
data-model.jsonsemantic-mapper, visual-selector, nlq-dashboard-orchestratorNormalized model
data-model.json.openQuestions[]nlq-dashboard-orchestrator (Gate A)Drive clarification dialog
data-model.json.mCodeAdaptersemantic-mapperTMDL partition source blocks

Validation Checklist

  1. Every table has at least one column
  2. Every relationship references existing {table, column} on both sides
  3. Every column has both dataType and sourceProviderType
  4. Exactly zero or one date-dimension table is flagged as role: "date dimension" per date role
  5. At least one table is classified as fact
  6. mCodeAdapter.templates has one entry per table in tables[]
  7. openQuestions is empty OR every entry has a unique id and a non-empty question

Error Handling

ErrorResolution
Cannot reach sourceSurface error verbatim; ask user for corrected connection params
Authentication failedAsk user for credentials; never store them in data-model.json
Empty schema (no tables found)Stop and ask the user to verify scope
Table with zero columnsSkip and log a warning
Source type unsupportedAsk user to convert to a supported source (e.g., export DB query to CSV)

Resources

  • scripts/introspect_source.py — Main connector entry point; routes to source-specific adapters
  • references/connection-patterns.md — Per-source connection recipes and M-Code templates
  • references/clarification-questions.md — Standard question bank for missing/ambiguous inputs
  • references/data-model-schema.md — Full JSON schema for data-model.json

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.