Turn Microsoft Fabric and Power BI semantic models into AI-ready metadata from your laptop, with query guidance and an agent-readiness score so an AI agent can query them safely. Reads local .pbip/TMDL folders with no tenant or sign-in. Exports to LangChain, OpenAI, Semantic Kernel, and AutoGen, with cross-model governance, an MCP server, and a graph-necessity advisor.
8 tools with complete input schemas and descriptions. Naming follows verb_noun pattern (list_, analyze_, score_, assess_, generate_, guide_, governance_, diff_). Descriptions are detailed (100-400 chars) and explain WHEN to use each tool. Parameters are well-typed (string, boolean, array). However, output schemas are NOT documented, LLMs cannot see what fields to expect in responses. Error handling is implicit (tools return {"error": message} on exception) but lacks recovery guidance. No tool annotations (readOnlyHint, idempotentHint). Parameter descriptions could be more concise; some exceed 200 chars and bury key constraints.
Extract, classify, and score a single semantic model. Omit `pbip` to read a bundled sample model (Adventure Works, Contoso Sales, Enterprise Sales); pass a *.SemanticModel folder to read a real one. An unrecognised model name is an error, not a substitution. Returns score, breakdown, and high-level counts; use ``generate_schema`` for full detail.
Run the agent-readiness critic report for a single model. Omit `pbip` to read a bundled sample model (Adventure Works, Contoso Sales, Enterprise Sales); pass a *.SemanticModel folder to read a real one. An unrecognised model name is an error, not a substitution. Returns ranked findings (undescribed objects, ambiguous names, missing relationships, unreliable column types), each with a suggested fix, plus the same score/breakdown `score_model` returns.
Compare two ``workspace-summary.json`` payloads and return the delta. Inputs are JSON-encoded strings (not file paths) so the tool works in environments where the agent has the data in-memory but no shared filesystem with the server.
Generate the AI-ready schema dict for a model. Omit `pbip` to read a bundled sample model (Adventure Works, Contoso Sales, Enterprise Sales); pass a *.SemanticModel folder to read a real one. An unrecognised model name is an error, not a substitution. The schema is the same structure ``fabric-ai-meta analyze`` writes to ``ai-ready-schema.json``.
Output schemas not documented. LLMs cannot see what fields to expect from tool responses (e.g., analyze_model returns {score, breakdown, table_count, measure_count} but this is not declared in the tool definition). Forces LLMs to guess structure and risks parsing errors.
guide_query parameter descriptions are verbose (400+ chars) and bury key constraints. The refusal/redirect/excluded logic is explained in prose but not formalized as enum or structured output schema. LLMs must parse natural language to understand response structure.
No tool annotations (readOnlyHint, idempotentHint, destructiveHint). All 8 tools are READ_ONLY but this is not declared in the tool definition, only in the Risk field of the evaluation. Agents cannot infer safety properties from the schema.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2026-07-28+ | v2 |
Run the cross-model governance analysis for an entire workspace. Omit `pbip` to read the bundled sample models (Adventure Works, Contoso Sales, Enterprise Sales); pass a *.SemanticModel folder to read a real one. Returns naming inconsistencies, duplicate measure expressions, model score ranking, recommendations, and (when graph_necessity=True) a per-model graph_necessity assessment. `questions` is an optional inline list of real questions that sharpens that assessment (pass the list directly, not a path).
Guidance to read before writing a query against this model. Pass exactly one of `measure` (a measure name) or `column` (a raw column you were about to aggregate directly), plus an optional `dimensions` list of column names to group or filter by. Check `result["refusal"]` first: unlike the other tools, an unknown measure or column name here does NOT set `error` - it returns a normal dict with `refusal` set to a message and everything else empty (`measure: None`, `warnings: []`, `dimensions: {}`). Only a genuinely unrecognised MODEL name (or a missing `pbip` file) sets `error`, matching the other tools' convention. When `refusal` is `None`: `measure` carries the resolved measure's table, name, DAX and category. If you passed a raw `column` that a real measure already wraps, `redirect` also names that measure - `measure` and `redirect` are populated together in that case, not one or the other. `excluded` is set (instead of `warnings`) when the resolved measure is report plumbing (an icon, a color swatch, a formatted display string) rather than a business measure - the DAX is still returned so you can judge for yourself, but nothing else is computed for it. Otherwise `warnings` lists any traps found, e.g. semi-additive, ratio, hardcoded literal, an implicit business rule baked into the DAX, opaque calculation group, an ambiguous column name, or an unwrapped raw column with no verified aggregation. Each requested dimension resolves to a `status` of `resolved` (with a `join_path`), `ambiguous` (every reachable candidate is listed; none is picked for you - ask which one is meant), `unrelated` (the column exists but nothing connects it to this measure's table), or `not_found`. Omit `pbip` to read a bundled sample model; pass a *.SemanticModel folder to read a real one.
List semantic models available to this server. Omit `pbip` to read the bundled sample models (Adventure Works, Contoso Sales, Enterprise Sales); pass a *.SemanticModel folder to read a real one. An unrecognised model name is an error, not a substitution.
Compute the AI readiness score for a single model. Omit `pbip` to read a bundled sample model (Adventure Works, Contoso Sales, Enterprise Sales); pass a *.SemanticModel folder to read a real one. An unrecognised model name is an error, not a substitution. Returns ``{"score": float in [0, 1], "breakdown": dict[str, float]}``.
Error handling returns {"error": message} but does not categorize errors as retryable, user-fixable, or fatal. No recovery guidance (e.g., 'Try search_users() with a partial name'). LLMs receive raw exception strings with no actionable next step.
Parameters pbip and workspace appear in 7 of 8 tools but their interaction is not documented. When pbip is omitted, does workspace still apply to bundled models? Undocumented parameter relationships cause silent misuse.