Skip to main content
Glama

foundry-copilot-mcp

Bring a Microsoft Foundry agent — and your Power BI semantic models — into GitHub Copilot Chat, over MCP.

Your agent already works in the Foundry playground. Your analysts already live in VS Code. This is the ~400 lines of glue in between, written to be read: three bridges, each one small enough to hold in your head.

Everything runs as the signed-in user, never a service principal. That is a design decision, not an omission — see Security.

The three bridges

1. A Foundry agent as a Copilot tool

The whole bridge, minus error handling:

project = AIProjectClient(endpoint=PROJECT_ENDPOINT, credential=DefaultAzureCredential())
client  = project.get_openai_client(agent_name=AGENT_NAME)   # pre-bound to your agent
reply   = client.responses.create(input=prompt).output_text

No model name, no system prompt on the client. The instructions, tools and model deployment stay server-side in Foundry, so you change the agent in the portal and every user picks it up on their next message — no redeploy, no version drift across machines.

docs/01-foundry-bridge.md

2. An MCP server that is also an MCP client

Plenty of people write MCP servers. Far fewer write a client — and that is where the interesting architecture lives. This server launches Microsoft's official Power BI modeling MCP server as a child process, speaks JSON-RPC to it over stdio, and re-exposes the result as one opinionated tool.

You get to add policy at the boundary: the child is launched --read-only by default, so no chain of LLM calls can quietly mutate a production model.

StdioMcpClient is generic — point it at any MCP server, not just this one.

docs/02-mcp-calls-mcp.md

3. Fabric GUIDs → names

The modeling server connects by name. What the user has in front of them is a Fabric URL full of GUIDs. So we resolve them against the Fabric REST API instead of asking people to go hunting for display names.

docs/03-fabric-rest.md

Related MCP server: Microsoft Fabric MCP Server

Tools exposed to Copilot

Tool

What it does

Writes?

ask_agent_tool

Puts a question to your Foundry agent

no

inspect_model

Connects to a semantic model and summarises it

no

show_measure

Shows the current DAX of one measure

no

update_measure_dax

Rewrites a measure

yes — needs confirm=True

resolve_fabric_ids

Turns the GUIDs in a Fabric URL into names

no

Getting started

Requirements: Python 3.11+, VS Code with GitHub Copilot, az login done. Node.js only if you want the Power BI tools (it runs the official server via npx).

git clone https://github.com/Nambu89/foundry-copilot-mcp
cd foundry-copilot-mcp
python -m venv .venv
.venv/Scripts/activate          # macOS/Linux: source .venv/bin/activate
pip install -r requirements.txt

cp .vscode/mcp.json.sample .vscode/mcp.json   # then fill in your endpoint and agent name

Check the Foundry connection before you trust it — and definitely before you demo it:

python -m foundry_mcp.server --selftest "Hello, who are you?"

Then open VS Code, switch Copilot Chat to Agent mode, and the tools show up. Ask it something like "ask the agent what it can do" or "inspect the model in samples/sample-model".

No Foundry project yet? The Power BI and TMDL parts work standalone, and samples/sample-model is a small semantic model you can point them at.

Security

Four decisions worth copying into whatever you build:

The user's identity, not a service principal. DefaultAzureCredential and the modeling server's interactive sign-in mean every read runs as the person asking. Row-level security therefore applies. Wire a service principal in and RLS is silently bypassed — users see rows they should not, with no error to warn you. That is the quietest data leak on this list.

Read-only by default. The one writing tool (update_measure_dax) needs an explicit confirm=True, and shows the current and proposed DAX first so a human can compare them.

Validation stays with the engine. Measure updates go through the official server's measure_operations/Update, so the tabular engine rejects invalid DAX. Hand-patching TMDL text would happily write a broken model.

No secrets in the repo. Configuration is environment variables in .vscode/mcp.json, which is gitignored. Only .vscode/mcp.json.sample is tracked.

Tests

pytest

21 tests, no network, no Azure, no Node.js — including fake MCP servers that exercise the real JSON-RPC framing, the notification handling and the timeout.

Talk

This repo backs a talk on connecting Microsoft Foundry agents to Copilot Chat over MCP. Slides and video will be linked here after the conference.

Licence

MIT — see LICENSE.

Available Tools

5 tools
ask_agent_toolA

Ask the Microsoft Foundry agent a question and return its answer.

Use this for anything the agent is specialised in — its instructions, knowledge and tools all live server-side in Foundry, so you do not need to know how it works. Pass the user's request in plain language.

Do NOT use this to read a Power BI model: inspect_model does that directly and faster.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It adds useful context by explaining that the agent's instructions, knowledge, and tools live server-side, so the caller does not need to understand its internals. It does not mention potential latency, side effects, or authentication requirements, but for a straightforward ask-and-answer interaction this is acceptable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the core purpose is in the first sentence, followed by brief usage context and a clear exclusion. Every sentence adds value; there is no redundant or repeated information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with an output schema and few siblings, the description provides sufficient context: what it does, when to use it, how to phrase input, and when to avoid it. The explicit alternative and clear scope make it safe for an AI agent to select and invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has only a `prompt` string with no description (0% coverage). The description compensates by instructing the agent to pass the user's request in plain language and clarifying that the agent handles the domain semantics. This adds meaningful guidance for the single parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action ('Ask the Microsoft Foundry agent a question') and the result ('return its answer'). It also distinguishes itself from sibling tools by explicitly warning against using it for Power BI model reads, for which `inspect_model` is the appropriate alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It tells the agent when to use the tool ('anything the agent is specialised in') and how ('Pass the user's request in plain language'). It also provides an explicit exclusion: 'Do NOT use this to read a Power BI model' and names the better alternative, `inspect_model`.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

inspect_modelA

Connect to a Power BI semantic model and summarise what is in it.

Accepts either a Fabric workspace and semantic model (by display name OR by the GUIDs from the Fabric URL), or the path to a local PBIP / .SemanticModel folder.

Read-only: it never modifies the model. Authentication is the user's own, so their permissions and row-level security apply. Run this before show_measure.

ParametersJSON Schema
NameRequiredDescriptionDefault
modelNo
folderNo
workspaceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Without annotations, the description fully carries behavioral disclosure. It explicitly states the tool is read-only ('never modifies the model'), explains authentication and row-level security implications, and mentions the summarisation behavior. No contradictions with annotations exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, front-loaded with the core purpose, followed by parameter modes and safety/usage notes. Every sentence adds value, with no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers purpose, usage modes, safety (read-only), authentication effects, and sequencing. The output schema exists, so return values do not need elaboration. For a tool with 3 optional parameters and two usage modes, this is complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description compensates fully by explaining the two modes: workspace+model (by display name or GUID) or folder path. This directly maps to the three parameters (workspace, model, folder) and gives meaningful context for each.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool connects to a Power BI semantic model and summarises its contents. It distinguishes itself from siblings by explicitly noting it runs before `show_measure`, which helps differentiate it from related operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit usage context: 'Run this before `show_measure`' indicates the appropriate timing. It also explains the two possible input modes (Fabric workspace+model or local folder), giving clear guidance on when and how to use the tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_fabric_idsA

Turn the GUIDs in a Fabric URL into the display names the tools need.

Use when the user pastes a Fabric Studio link instead of typing names.

ParametersJSON Schema
NameRequiredDescriptionDefault
model_idNo
workspace_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry the full burden. It discloses the core conversion behavior but does not explicitly state whether the operation is read-only, requires authentication, or has any side effects. The non-destructive nature is implied but not clearly disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the verb, and every word serves a purpose. No waste or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple and the description covers purpose and usage, but there are gaps: parameter semantics are not explained and the return behavior is not described beyond 'display names.' The output schema exists but is not referenced or enriched. Adequate but with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage. The description mentions GUIDs and URLs, but it does not map workspace_id or model_id to specific URL components or explain what model_id (the optional parameter) is for. Users are left to guess parameter meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'Turn' and clearly states the resource: GUIDs in a Fabric URL converted to display names. It distinguishes this as a resolver tool from sibling tools like inspect_model or show_measure.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: 'when the user pastes a Fabric Studio link instead of typing names.' It does not mention when not to use or list alternatives besides the implied direct-name input, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

show_measureA

Show the current DAX expression of one measure, and the table it belongs to.

Call inspect_model first. Accepts Table[Measure], [Measure] or just the measure name, so you can paste a reference straight from an analysis report.

ParametersJSON Schema
NameRequiredDescriptionDefault
measureYes
model_labelNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the transparency burden. It discloses the dependency on inspect_model and the flexible input formats, which is useful. However, it does not explicitly state that the operation is read-only or describe any side effects, although 'Show' strongly implies non-mutating. It also omits error behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, with the purpose in the first sentence and supporting details following. No redundant phrases, and every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description adequately covers the main required parameter and the prerequisite call, and the output schema presumably handles return values. The only notable gap is the lack of explanation for 'model_label', but for a read-only display tool this is a minor omission.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It thoroughly explains the 'measure' parameter with accepted formats. However, the optional 'model_label' parameter is not mentioned at all, leaving a gap for a two-parameter tool. The partial explanation earns a score below the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Show the current DAX expression of one measure') and the resource ('the table it belongs to'). This distinguishes it from sibling tools like 'update_measure_dax' (which modifies) and 'inspect_model' (which inspects the whole model).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides an explicit prerequisite ('Call inspect_model first') which is a clear usage guideline. It also specifies the accepted input formats, helping the agent invoke it correctly. It does not explicitly mention alternatives, but the dependency and format hints are sufficient for typical use cases.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_measure_daxA

Write a new DAX expression for a measure. MODIFIES THE MODEL.

Read-only is the default everywhere else in this server; this is the one exception, and it is opt-in twice over: the caller must pass confirm=True, and the user needs write access (Contributor plus a read/write XMLA endpoint). Always show the user the current expression with show_measure and get their agreement before calling this.

The tabular engine validates the DAX, so an invalid expression is rejected rather than saved.

ParametersJSON Schema
NameRequiredDescriptionDefault
confirmNo
measureYes
model_labelNo
new_expressionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully owns the behavioral disclosure. It highlights the model-modifying nature, the double opt-in (confirm flag and write access), and the validation behavior ('an invalid expression is rejected rather than saved'), providing essential context beyond any schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact, front-loaded with the core action and a prominent warning, and every sentence contributes value. It covers purpose, permissions, workflow, and validation in five sentences without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple mutation tool and the presence of an output schema, the description provides all essential context: what it does, when to use it, prerequisites, and safety behavior. The inclusion of permission requirements and validation makes it complete enough for an agent to select and invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has zero property descriptions (0% coverage), so the description must compensate. It explicitly explains the critical confirm parameter ('must pass confirm=True') and implies measure/new_expression through the main sentence, but it does not mention model_label or provide format/syntax details. Partial coverage, not comprehensive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Write a new DAX expression for a measure.' It also clearly flags 'MODIFIES THE MODEL,' which distinguishes this from the read-only siblings like show_measure. This is unambiguous and differentiates the tool's intent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly instructs to use show_measure first: 'Always show the user the current expression with show_measure and get their agreement before calling this.' It also details the exact conditions required (confirm=True and write access), making it clear when and how to use this tool versus alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 5 tool updatesv0.1.0
    • First observedask_agent_tool
    • First observedinspect_model
    • First observedresolve_fabric_ids
    • First observedshow_measure
    • First observedupdate_measure_dax

TDQS

A4.2/5.0
Disambiguation4/5

Each tool has a clear role: agent questions, model inspection, measure lookup, measure update, and ID resolution. The only potential ambiguity is ask_agent_tool could be used for model tasks, but its description explicitly directs direct inspection to inspect_model.

Naming Consistency5/5

All tools follow a consistent verb_first snake_case pattern (ask_, inspect_, show_, update_, resolve_). Names clearly indicate action and target.

Tool Count5/5

5 tools is ideal for a focused server—enough to cover core operations without bloat.

Completeness3/5

Covers inspect and update workflows for measures, but lacks create/delete measure operations. The agent can fill gaps, but as a direct tool surface it is slightly incomplete.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Integrates Microsoft 365 enterprise data into GitHub Copilot and Claude Desktop using Microsoft 365 Copilot APIs. It enables natural language queries across SharePoint, OneDrive, emails, calendars, and Teams meetings while maintaining full enterprise permission enforcement.
    5
    10
    MIT
  • A
    license
    B
    quality
    D
    maintenance
    Enables AI assistants to interact with Microsoft Fabric and Power BI services through the Model Context Protocol. Users can manage workspaces, execute DAX queries, refresh datasets, and create Fabric notebooks using natural language.
    6
    22
    2
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Nambu89/foundry-copilot-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server