Announcing CIMD support for MCP Client registration
Learn more

Power BI MCP vs API for Developing AI Agents

Nishant Choudhary
Tech Evangelist

Microsoft now ships three Power BI-related MCP endpoints that do different jobs, and a REST API that has existed for years. They overlap on one thing, running DAX against a semantic model, and diverge on almost everything else. The MCP server can read a model's schema so an agent writes correct DAX; it cannot start a refresh. The REST API can refresh, rebind, deploy and grant access; it cannot tell the agent what columns exist. This guide compares what each path lets an agent do, the Entra identity each one puts you on, and how to run either across many customer tenants in production.

TL;DR

  • Microsoft now ships three Power BI-related MCP endpoints, and they do different jobs. Fabric IQ MCP is the generally available, read-only consumption server: six tools for finding reports and semantic models, reading schema, searching values, and running DAX. The Power BI Authoring MCP server edits semantic models (hosted in preview, local GA). The earlier Power BI Consumption MCP endpoint is still in preview and kept for existing integrations.
  • Fabric IQ MCP accepts only delegated Microsoft Entra ID OAuth with Item.Read.All and Item.Execute.All. Service principal and app-only auth are not supported. The Power BI REST API accepts delegated user tokens and service principals, which is the only way to run a headless agent with no user present.
  • The REST API covers what MCP leaves out: refreshes and refresh schedules, workspace access, deployment pipelines, push datasets, gateways, capacities, and report export. MCP covers what the REST API makes hard: the Power BI REST API has no operation that returns an import model's tables, columns, and measures as structured metadata (the Fabric getDefinition call returns the raw model definition as base64-encoded files, not an agent-ready schema), and executeQueries rejects INFO functions and DMVs. On the API path, the agent writes DAX blind.
  • In a multi-tenant agent, neither path removes per-user credential isolation. Both give you one Entra token per user per customer tenant, and both enforce row-level security only when the call runs as that user.
  • Scalekit's microsoftpowerbi connector exposes 77 Power BI REST API tools on per-user Entra OAuth, so the MCP vs API decision doesn't change your auth infrastructure.

The decision your Power BI agent forces first

Your agent needs to answer questions from your customers' Power BI: what drove last quarter's margin, which semantic model failed its overnight refresh, who has access to the Finance workspace. Microsoft ships hosted MCP servers for Power BI and a REST API that has existed for years. They overlap on one thing, running DAX against a semantic model, and diverge on almost everything else. The MCP server can read a model's schema so the agent writes correct DAX; it cannot start a refresh. The REST API can refresh, rebind, deploy, and grant access; it cannot tell the agent what columns exist. Then the tenant settings and Entra consent rules land on top. Here's how to pick.

What Power BI MCP and Power BI API actually are

Power BI MCP

Microsoft's Power BI MCP servers overview splits the job in two. For consumption, it points to Fabric IQ MCP, a remote, Microsoft-hosted server at https://fabriciq.svc.cloud.microsoft/v1/mcp/fabriciq over Streamable HTTP. Microsoft's docs state that it is generally available. It is read-only and works against Power BI reports and semantic models; dashboards, paginated reports, and Power BI apps are not supported. Auth is delegated OAuth 2.0 through Microsoft Entra ID, and no Power BI tenant setting gates it. Docs: Get started with the Fabric IQ MCP server.

For building, the Power BI Authoring MCP server creates and changes tables, measures, relationships, calculation groups, and security roles. It runs hosted at https://api.fabric.microsoft.com/v1/mcp/powerbi/authoring (preview) or locally from the @microsoft/powerbi-modeling-mcp package (GA). Microsoft's guidance is explicit: don't use it for consumption. Docs: Power BI Authoring MCP server.

The earlier Power BI Consumption MCP endpoint at https://api.fabric.microsoft.com/v1/mcp/powerbi remains in preview for existing integrations. It needs the tenant setting "Users can use the Power BI Model Context Protocol server endpoint (preview)". Docs: remote MCP server tools.

Power BI API

The Power BI REST API at https://api.powerbi.com/v1.0/myorg/ has 17 operation groups: Groups (workspaces), Datasets (semantic models), Reports, Dashboards, Dataflows, Apps, Capacities, Gateways, Imports, Pipelines, Push Datasets, Embed Token, Admin, and more. Every call carries a Microsoft Entra ID bearer token. You can get that token as a user through delegated permissions on an Entra app registration (Dataset.Read.All, Report.Read.All, Workspace.Read.All, and their ReadWrite variants), or as a service principal, where Entra scopes don't apply and access is managed through workspace roles and Fabric tenant settings.

What your agent can actually do

Capability
Power BI MCP (Fabric IQ)
Power BI API
Find reports and semantic models by name
Yes
Limited: List per workspace, then filter
Read a model's tables, columns, and measures
Yes
Limited: No structured schema operation in the REST API; the Fabric definition call returns raw model files and the query endpoint rejects INFO functions and DMVs
Search stored values (is it "EMEA" or "Europe"?)
Yes
Limited: Hand-written DAX against a column you already know
Run DAX
Yes: 250 rows by default, configurable
Yes: 100,000 rows or 1,000,000 values
Report pages and visuals
Yes: Pages, visuals, filters, field bindings
Limited: Page names and order
Trigger and monitor refreshes
No
Yes
Refresh schedules and Power Query parameters
No
Yes
Workspace access audit and grants
No
Yes
Deployment pipelines
No
Yes
Push data into a model
No
Yes
Dashboards and apps
No: Not supported content
Yes
Export a report to PDF or PPTX
No
Yes: Export endpoint; not in the Scalekit connector

The split is clean. Fabric IQ MCP is the analyst's surface: find the model, learn its shape, ask it a question. The REST API is the operator's surface: keep models fresh, move content between stages, control who sees what. Model editing belongs to a third surface, the Authoring MCP server or the XMLA endpoint, and neither of the other two touches it.

What the MCP server makes easier

DAX is unforgiving. A query against 'Sales'[Amount] fails when the column is 'Fact Sales'[Net Amount], and a filter on "EMEA" returns nothing when the stored value is "Europe, Middle East & Africa". Fabric IQ MCP gives the model the context to get both right before it runs anything: GetSemanticModelSchema returns tables, columns, measures, relationships, and hierarchies, and ValueSearch resolves the literal. Writing the schema is the hard part. Not the API call.

On the REST API, the agent gets microsoftpowerbi_dataset_get (name, storage mode, refreshability) and a DAX endpoint. Discovering structure means either running exploratory EVALUATE TOPN(...) queries against tables whose names it guesses, or your team writing per-model context into the prompt. That works for one model. It does not survive a customer with 40.

The tradeoff is what MCP will not do. Fabric IQ queries one semantic model per ExecuteQuery call, holds no state between calls, and returns 250 rows by default, with larger results delivered as an embedded CSV resource that not every client handles.

The auth path each one puts you on

Power BI MCP: delegated Entra tokens, user present

Fabric IQ MCP uses delegated OAuth 2.0 with two Power BI Service scopes: Item.Read.All and Item.Execute.All. Microsoft states that service principal and app-only auth are not supported, and that there is no administrator-impersonation path. Every call runs as the signed-in user, which means row-level security and object-level security apply as they would in the Power BI portal. What the user can't do, the agent can't do.

Two Entra details shape deployment. The scopes don't require admin consent by default, but a tenant admin can restrict user consent or route requests through the admin approval workflow, so the first user at a regulated customer may hit a consent wall. And Entra ID does not support Dynamic Client Registration; Microsoft notes that some clients need a single-tenant app registration with a client-specified redirect URI. The hosted Authoring server has the same limitation, plus a tenant toggle a Fabric admin must enable.

The legacy Consumption endpoint behaves differently: it requires Build permission on the model, and Microsoft notes RLS is not enforced under service principal authentication. Fabric IQ requires neither a workspace role nor Build permission.

Power BI API: user tokens or a service principal

The REST API accepts the same delegated Entra tokens, scoped to Power BI Service permissions such as Dataset.Read.All for executeQueries and Dataset.ReadWrite.All for refreshes. It also accepts a service principal: an Entra app authenticating with its own client credentials, gated by the Fabric tenant setting "Service principals can call Fabric public APIs" and by workspace role assignments. That is the only way to run a Power BI agent with no user in the loop.

It comes with a hard edge. Microsoft's executeQueries reference says service principals are not supported for datasets with RLS or with SSO enabled, regardless of tenant settings. The impersonatedUserName parameter evaluates RLS as another UPN, which is useful for testing and dangerous as a default. An agent running on a service principal either cannot query your RLS-protected models or is querying models that have no RLS. Both outcomes deserve a design review.

executeQueries also needs the tenant setting "Dataset Execute Queries REST API" enabled under Integration settings, plus Build permission on the model. Plan for both in your customer onboarding checklist.

Both paths still need per-user isolation

In a multi-tenant B2B agent, MCP's OAuth flow gives you a token per user. Direct API calls give you a credential per user. In neither case does the path itself solve storage, rotation, or revocation; those are infrastructure problems regardless of which path you choose.

Power BI adds a tenant boundary to both. Each customer has its own Entra tenant, its own consent policy, and its own tenant settings. A user token from Contoso's tenant cannot reach Fabrikam's workspaces, and an agent that serves both needs both tokens, stored separately and never confused.

Recommended reading: OAuth vs API keys for AI agents

What you own in production

On the MCP path

Microsoft owns the tool schemas, the DAX execution, and the endpoint. You own the Entra token per user, and you own how the client reacts when the tool surface changes. Microsoft tells clients to call tools/list instead of hard-coding schemas, tolerate additive tools and fields, and send the X-Variants: Fabric.Routing.FabricIQ.V1 header on every request to pin the tool contract. Power BI service throttling applies to metadata and DAX calls through MCP, and rate-limit errors are retryable with backoff.

Region is a quiet blocker. Fabric IQ MCP requires a tenant home region that supports all Fabric workloads; it is not available in Power BI-only regions or sovereign clouds. Some customers cannot use it at all, and your agent needs a fallback path for them.

On the API path

You own everything: schemas, pagination, retries, and every limit. executeQueries allows 120 query requests per minute per user regardless of the dataset, one query per call, one table per query, 100,000 rows or 1,000,000 values, and 15 MB per response. An agent that loops "refine the query" five times per question and serves 30 concurrent questions from one user account will hit 120 per minute quickly. Throttled calls return HTTP 429; back off before retrying.

Refresh is where licensing shows up. On shared capacity, a semantic model can start at most eight refreshes per day, counting scheduled refreshes, and enhanced refresh (table-level refresh, commit modes, parallelism) is not supported. On Premium capacity, the daily count is bounded by available resources, and a refresh fails if throttling exceeds one hour. An agent that "just refreshes the model" before every answer burns a Pro customer's daily budget by lunch.

Refreshes are asynchronous. microsoftpowerbi_dataset_refresh returns 202 Accepted; the agent has to poll microsoftpowerbi_dataset_refresh_history_list until the status leaves Unknown. That is a pipeline concern, not a chat concern.

Schema drift and versioning

The MCP surface is moving fast. Microsoft has already repositioned the original consumption endpoint as legacy, made Fabric IQ the supported consumption server, and split authoring into hosted and local variants with different auth options. Microsoft's own tools page warns that preview tool definitions, request formats, and response schemas may change. Pin the contract header, pin the tool names your agent depends on, and alert on unknown-tool errors.

The REST API is versioned at v1.0 and changes additively, but the semantics shift underneath it. Datasets became semantic models in the UI while the API kept the datasets path, tenant settings were renamed as Power BI moved into Fabric, and workspace permission changes can take time to show up in API calls. None of these break a request outright. All of them break an agent's assumptions.

When to use MCP, when to use the API

Use Power BI MCP when

  • You are building a conversational analytics agent in GitHub Copilot CLI, Copilot Studio, or your own agent, where a finance lead asks "what drove the margin drop in EMEA last quarter?" and the agent chains DiscoverArtifacts, GetSemanticModelSchema, ValueSearch, and ExecuteQuery.
  • The models are complex and the agent has no hand-written context for them; schema retrieval is the difference between correct DAX and plausible DAX.
  • RLS and OLS must apply exactly as they do for the user in the portal, with no service principal anywhere in the path.
  • A modeler wants an agent to refactor measures or add translations in a semantic model; that is the Authoring MCP server's job, ideally against PBIP files under source control.

Use the Power BI API when

  • The agent runs headless on a schedule, such as a nightly job that checks microsoftpowerbi_dataset_refresh_history_list across every workspace and posts failures to Slack, with no user present to sign in.
  • The workflow is operational: triggering refreshes, updating Power Query parameters, rebinding reports, deploying content through pipelines, or pushing rows into a push semantic model.
  • You need governance actions that MCP does not expose: auditing who holds Admin on a workspace with microsoftpowerbi_workspace_users_list, or granting Viewer access after an approval.
  • The customer's tenant sits in a region where Fabric IQ MCP is unavailable, or the content is dashboards, apps, or paginated reports.

The credential problem that exists on both paths

Pick MCP and every user produces a delegated Entra grant with a refresh token, issued by their own tenant under their tenant's consent policy. Pick the API and you get the same delegated grants, plus a service principal secret or certificate per customer tenant for headless work. Neither path hands you a vault, a refresh scheduler, or a revocation hook.

Run the numbers. 30 customers with 8 analysts each is 240 Entra grants across 30 tenants. Each one must be encrypted at rest, bound to its user and tenant, refreshed before expiry, and invalidated when the analyst leaves or the customer's admin revokes consent. The tempting shortcut, one service principal per customer shared by every user of the agent, collapses 240 credentials into 30. It also turns off RLS for every query the agent runs, because service principals cannot query RLS models at all, and every action lands in the Power BI activity log under one app identity. Fewer secrets, larger blast radius per secret.

Scalekit's Power BI connector handles the Entra OAuth flow, token storage, and refresh per user, so the MCP vs API decision doesn't change your auth infrastructure. Your agent passes an identifier; the token never enters the agent runtime or the LLM context.

Recommended reading: why a token vault matters for AI agent workflows

How to connect a Power BI agent with Scalekit

Scalekit's microsoftpowerbi connector is an API-path connector with 77 Power BI REST API tools: 56 read-only and 21 write, with no destructive tools. It authenticates with OAuth against your own Entra app registration: each user signs in with their Microsoft work account once, and Scalekit stores and refreshes their tokens. Every tool call runs as that user, so their workspace roles and RLS apply.

Prerequisites and the connection name

Create a Microsoft Power BI connection in AgentKit > Connections in the Scalekit dashboard and copy its redirect URI. Register an app in Microsoft Entra ID, add that redirect URI, grant the delegated Power BI Service permissions your agent needs, and enter the app's client ID and client secret on the connection. The name you give the connection is the connection_name your code passes, and the string must match the dashboard exactly. This is the most common integration error.

For DAX tools, the customer's Fabric admin must enable "Dataset Execute Queries REST API", and the user needs Build permission on the semantic model. Copy SCALEKIT_ENVIRONMENT_URL, SCALEKIT_CLIENT_ID, and SCALEKIT_CLIENT_SECRET from Developers > API Credentials into .env.

pip install scalekit-sdk-python python-dotenv langchain-openai

Authorize each user once

get_or_create_connected_account returns the user's connected account. If it is not ACTIVE, get_authorization_link returns a Microsoft sign-in and consent link. The agent never sees the token.

import os from dotenv import load_dotenv from scalekit import ScalekitClient load_dotenv() scalekit_client = ScalekitClient( env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"], ) actions = scalekit_client.actions CONNECTION_NAME = "microsoftpowerbi" # must match the connection name in AgentKit > Connections identifier = "user_123" # your app's stable ID for this user account = actions.get_or_create_connected_account( connection_name=CONNECTION_NAME, identifier=identifier, ) if account.connected_account.status != "ACTIVE": link = actions.get_authorization_link( connection_name=CONNECTION_NAME, identifier=identifier, ) print("Authorize Power BI:", link.link) input("Press Enter after signing in with Microsoft...") account = actions.get_or_create_connected_account( connection_name=CONNECTION_NAME, identifier=identifier, ) if account.connected_account.status != "ACTIVE": raise RuntimeError(f"Power BI is {account.connected_account.status}, not ACTIVE")

Retrieve the Power BI tools this user can call

This is not a catalog load. The agent asks for the tools this user's connected account is authorized to call, narrowed to the seven a reporting Q&A agent needs. Loading all 77 would put microsoftpowerbi_workspace_user_add and microsoftpowerbi_report_rebind in front of a model whose job is to read.

Note that Scalekit labels microsoftpowerbi_dataset_execute_queries as a write tool because the underlying call is a POST. It reads data and changes nothing, so it belongs in a read-only agent.

ANALYST_TOOLS = [ "microsoftpowerbi_workspaces_list", "microsoftpowerbi_datasets_list", "microsoftpowerbi_dataset_get", "microsoftpowerbi_reports_list", "microsoftpowerbi_report_pages_list", "microsoftpowerbi_dataset_execute_queries", "microsoftpowerbi_dataset_refresh_history_list", ] tools = actions.langchain.get_tools( identifier=identifier, connection_names=[CONNECTION_NAME], tool_names=ANALYST_TOOLS, page_size=100, ) tool_map = {t.name: t for t in tools} print(sorted(tool_map))

Run the agent loop

The loop sends the question, executes whatever tools the model asks for as this user, and feeds results back until the model answers in plain text. The system prompt compensates for the REST API's missing schema operation by telling the model to probe before it aggregates.

from langchain_core.messages import HumanMessage, SystemMessage, ToolMessage from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o").bind_tools(tools) messages = [ SystemMessage( "You are a Power BI reporting assistant. Find workspace and semantic model IDs " "with the list tools before querying. Before aggregating, run a small " "EVALUATE TOPN(5, ...) query on each table you plan to use, to confirm " "table and column names. " "Check refresh history and state how current the data is in your answer." ), HumanMessage( "In the Finance workspace, what were total sales by region last quarter, " "and when did the sales model last refresh successfully?" ), ] while True: response = llm.invoke(messages) messages.append(response) if not response.tool_calls: print(response.content) break for tc in response.tool_calls: tool = tool_map.get(tc["name"]) if tool: result = tool.invoke(tc["args"]) else: result = f"Unknown tool: {tc['name']}" messages.append(ToolMessage(content=str(result), tool_call_id=tc["id"]))

Deterministic calls with execute_tool

For pipelines, skip the model. execute_tool runs one tool with a fixed input and returns data plus an execution_id you can log. This job runs a fixed DAX query against a known model as the connected user, so RLS applies to the result.

WORKSPACE_ID = os.environ["POWERBI_WORKSPACE_ID"] # from microsoftpowerbi_workspaces_list DATASET_ID = os.environ["POWERBI_DATASET_ID"] # from microsoftpowerbi_datasets_list result = actions.execute_tool( tool_name="microsoftpowerbi_dataset_execute_queries", tool_input={ "workspace_id": WORKSPACE_ID, "dataset_id": DATASET_ID, "query": "EVALUATE TOPN(10, 'Sales', 'Sales'[Amount], DESC)", "include_nulls": True, }, connection_name=CONNECTION_NAME, identifier=identifier, ) print(result.execution_id, result.data)

The same call pattern covers the operational surface MCP does not have. This check pulls the last five refreshes for the model so a monitoring job can flag a Failed status with its serviceExceptionJson.

refreshes = actions.execute_tool( tool_name="microsoftpowerbi_dataset_refresh_history_list", tool_input={ "workspace_id": WORKSPACE_ID, "dataset_id": DATASET_ID, "top": 5, }, connection_name=CONNECTION_NAME, identifier=identifier, ) print(refreshes.execution_id, refreshes.data)

The connector covers the Power BI REST API, not the Admin group or report export. If your agent needs ExportTo or tenant-wide admin scans, register a custom connector for that surface and make proxied calls through actions.request(), keeping the same connected account and vault model.

Multi-tool, multi-tenant Power BI agents on a virtual MCP server

The microsoftpowerbi connector has 77 tools. At roughly 200 tokens per tool definition, that is about 15,400 tokens before the agent reads a question, and the decision space includes granting workspace access and deploying pipelines. The fix is not better prompting. It is surface reduction. A Scalekit virtual MCP server declares exactly which tools an agent role can see, and session tokens keep each run bound to one user's connected accounts. It also gives MCP-native clients a Power BI endpoint that can do what Fabric IQ cannot, such as reading refresh history. Docs: set up a virtual MCP server.

Create the server once per agent role

from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping vmcp = actions.mcp.create_config( name="powerbi-refresh-monitor", description="Checks Power BI semantic model refreshes and posts failures to Slack", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="microsoftpowerbi", tools=[ "microsoftpowerbi_workspaces_list", "microsoftpowerbi_datasets_list", "microsoftpowerbi_dataset_refresh_history_list", ], ), McpConfigConnectionToolMapping( connection_name="slack", tools=["slack_send_message"], ), ], ) print(vmcp.config.id, vmcp.config.mcp_server_url)

Mint a session token per user, per run

One server definition serves every user. Before each run, check that the user's Power BI and Slack accounts are active, then mint a short-lived session token scoped to them. Any MCP client that speaks streamable HTTP can connect; this example uses langchain-mcp-adapters (pip install langchain-mcp-adapters).

import asyncio from datetime import timedelta from langchain_mcp_adapters.client import MultiServerMCPClient config_id = vmcp.config.id mcp_server_url = vmcp.config.mcp_server_url user_id = "user_123" accounts = actions.mcp.list_mcp_connected_accounts( config_id=config_id, identifier=user_id, include_auth_link=True, ) not_ready = [ a for a in accounts.connected_accounts if str(a.connected_account_status).upper() != "ACTIVE" ] for a in not_ready: print(f"{a.connection_name} is {a.connected_account_status}: {a.authentication_link}") if not_ready: raise RuntimeError("Connect the accounts above before starting this run") session_token = actions.mcp.create_session_token( mcp_config_id=config_id, identifier=user_id, expiry=timedelta(minutes=30), ).token async def load_tools(): client = MultiServerMCPClient( { "scalekit": { "transport": "streamable_http", "url": mcp_server_url, "headers": {"Authorization": f"Bearer {session_token}"}, } } ) return await client.get_tools() mcp_tools = asyncio.run(load_tools()) print([t.name for t in mcp_tools])

The agent sees four tools. The endpoint is static; the identity is per-user.

Observability: every Power BI action tied to a user

Every execute_tool call returns an execution_id, and every execution is attributed to a connected account, which maps to one of your users in one customer tenant. When a customer asks which agent run rebound a report or triggered the refresh that ate their last slot of the day, the answer is a lookup, not an investigation. Power BI's own activity log records the operation under the Entra identity that made it; your execution log records which user, which run, and which prompt asked for it.

A shared service principal breaks both halves. The activity log shows one app identity for every user, your side can only prove the shared credential did it, and RLS-protected models were never queryable in the first place. Shared credentials are a single-user solution. They do not survive a second user.

Recommended reading: audit trails for agent auth

Which one to build against

If your agent answers business questions from semantic models inside Copilot or your own agent, and the customer's tenant region supports it, use Fabric IQ MCP. It gives the model the schema and value context that makes DAX correct, and it enforces RLS by construction. If your agent keeps Power BI running, refreshing models, monitoring failures, managing access, or deploying content, use the REST API; MCP has no tools for any of that, and only the API supports a headless identity. Many production agents will need both: MCP for the question, the API for the operations behind it.

Either way, the credential problem is the same, and that's what needs production-grade infrastructure. One delegated Entra grant per user, per customer tenant, stored, refreshed, and revoked on your side.

FAQs

Does Microsoft have an official Power BI MCP server?

Yes, three. Fabric IQ MCP is the generally available, read-only consumption server with six tools for finding reports and semantic models, reading schema, searching values and running DAX. The Power BI Authoring MCP server edits semantic models, hosted in preview and generally available locally. The earlier Power BI consumption endpoint remains in preview for existing integrations and needs a tenant setting.

What can the Power BI REST API do that Fabric IQ MCP cannot?

Operations: trigger and monitor refreshes, manage refresh schedules and Power Query parameters, audit and grant workspace access, deploy content through pipelines, push rows into a push dataset, list dashboards and apps, and export reports. MCP has no tools for any of that, and only the API supports a headless identity through a service principal.

Does the Power BI MCP server support service principals?

No. Fabric IQ MCP accepts only delegated Microsoft Entra ID OAuth, with no app-only auth and no administrator impersonation, so every call runs as the signed-in user and row-level security applies as it does in the portal. The REST API accepts service principals, but Microsoft states they are not supported for datasets with row-level security or single sign-on enabled.

What are the Power BI query limits for agents?

The DAX query endpoint allows 120 requests per minute per user, one query per call, one table per query, 100,000 rows or one million values, and 15 MB per response, returning 429 when throttled. Refreshes are limited too: a semantic model on shared capacity can start at most eight refreshes a day, so an agent that refreshes before every answer burns a customer's budget by lunch.

When should an agent use the Power BI API instead of MCP?

When it runs headless on a schedule, such as a nightly job that checks refresh history across workspaces and posts failures; when the work is operational, such as refreshes, parameter updates, report rebinding or pipeline deployments; when it needs governance actions like auditing workspace admins; or when the customer's tenant sits in a region where Fabric IQ MCP is unavailable.

How does Scalekit connect an AI agent to Power BI?

The Power BI connector exposes 77 REST API tools on per-user Entra OAuth against your own app registration. Each user signs in with their Microsoft work account once, Scalekit stores and refreshes the tokens in the token vault, every call runs as that user so their workspace roles and row-level security apply, a virtual MCP server narrows the tools per agent role, and every execution is attributed to that user and tenant.

Build your Power BI agent with Scalekit

Browse the Scalekit Microsoft Power BI connector and the Power BI connector docs with the full tool list. See Scalekit pricing, or talk to us.

No items found.
Agent
Auth Quickstart
On this page
Share this article
Scalekit
Find us on ProductHunt

Acquire enterprise customers with
‍zero upfront cost.

Every feature unlocked. No hidden fees.