Skip to main content

Command Palette

Search for a command to run...

Integrate Microsoft Agent Framework with Microsoft Fabric Core MCP Server

Updated
7 min readView as Markdown
Integrate Microsoft Agent Framework with Microsoft Fabric Core MCP Server
S
From Synapse Analytics, Power BI, Spark, Microsoft Fabric,ASP.NET Core and recently Agentic AI on .NET I try to explore, learn and share all aspects of Microsoft Data Stack in this blog.

Microsoft Fabric is revolutionizing the data analytics space and is bringing together data integration, data engineering and data analytics under a unified platform. This reduces overall complexities involved maintaining multiple, disconnected tools and services.

Recently, the Fabric Core MCP Server was released. At the time of this writing this feature is in preview. So please test it thoroughly before you use it in your production environment.

Fabric Core MCP Server is a remote endpoint that enables AI agents to interact with the Microsoft Fabric ecosystem. This opens a window of opportunity where MAF Agents can seamlessly communicate with artifacts within the Microsoft Fabric Ecosystem which eventually can reduce the complexities involved in overall code and structural customization.

Couple of weeks ago I had published an article that demonstrated the integration MAF AIAgent with Azure Services. To be honest, there were a lot of nuts and bolts involved in getting this set up running. But leveraging Fabric Core MCP Server you skip all such complexities when it comes to integrating it with Microsoft Fabric.

In this article we will deep dive in how to integrate MAF AIAgent with Fabric MCP Server.

To get started, we have to setup a few delegated permissions for the service principal that we will use.

The service principal will impersonate the logged in user and based on the user permissions assigned to the user for a specific Fabric item, the AIAgent will interact with the underlying Fabric services.

I granted the following delegated permissions to the service principal that I will use.

We will use the usual Fabric scope : https://api.fabric.microsoft.com/.default and MSAL (Microsoft Authentication Library) for token generation and the Fabric MCP Server endpoint https://api.fabric.microsoft.com/v1/mcp/core

SetUp

There are two Entra users

sachin.nandanwar @ azureguru.net and sachin_nandanwar @ azureguru.net

User sachin.nandanwar @ azureguru.net is an admin on the Fabric tenant while the user sachin_nandanwar @ azureguru.net only has Viewer access on one of the Fabric workspaces called "My Test workspace"

We will test a few prompts that would allow us to interact with the workspace "My Test workspace" on the Fabric tenant.

Following is the list of all the tools available through the Fabric MCP server.

By a simple prompt, you could list workspaces, create workspaces, create/update/delete items and so and so forth.

Of course the outcome of these actions will be dependent on the level of access the logged in user has for the underlying objects.

As mentioned earlier, there are Entra two users

I will test the prompts by logging in with both users.

Code

Add the following references to your ASP.NET core project

dotnet add package Azure;
dotnet add package Azure.Core;
dotnet add package Microsoft.Agents.AI;
dotnet add package Azure.AI.OpenAI;
dotnet add package Microsoft.Extensions.AI;
dotnet add package ModelContextProtocol.Client;
dotnet add package Microsoft.Identity.Client;
dotnet add package Microsoft.Extensions.DependencyInjection;

Declare a bunch of variables in Program.cs

private static string RedirectURI = "http://localhost";
private static string clientId = "Service Principal Client Id";
private static string tenantId = "Fabric tenant Id";
private static readonly HttpClient client = new HttpClient();
private static string[] scopes = new string[] { "https://api.fabric.microsoft.com/.default" };
private static string Authority = $"https://login.microsoftonline.com/{tenantId}";
public static HttpClient Client => client;

Next , define an Authentication method that validates the user sign-in and delegated scopes using Microsoft Entra ID and returns AuthenticationResult.

ReturnAuthenticationResult >>

public async static Task <AuthenticationResult> ReturnAuthenticationResult() {
  string AccessToken;
  PublicClientApplicationBuilder PublicClientAppBuilder =
    PublicClientApplicationBuilder.Create(clientId)
    .WithAuthority(Authority)
    .WithCacheOptions(CacheOptions.EnableSharedCacheOptions)
    .WithRedirectUri(RedirectURI);

  IPublicClientApplication PublicClientApplication = PublicClientAppBuilder.Build();
  var accounts = await PublicClientApplication.GetAccountsAsync();
  AuthenticationResult result;
  try {

    result = await PublicClientApplication.AcquireTokenSilent(scopes, accounts.First())
      .ExecuteAsync()
      .ConfigureAwait(false);
  } catch {
    result = await PublicClientApplication.AcquireTokenInteractive(scopes)
      .ExecuteAsync()
      .ConfigureAwait(false);

  }
  return result;
}

Add the following code in Program.cs to read settings from the config file appsettings.json

var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false)
.Build();

Read credentials and register Chatclient and return a ChatClientAgent

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

var credential = new AzureKeyCredential(configuration["AppSettings:ApiKey"]);

servicecollection.AddKeyedChatClient(
    "ChatClient",
    (
        sp =>
            new AzureOpenAIClient(new Uri(configuration["AppSettings:EndPoint"]), credential)
                .GetChatClient(configuration["AppSettings:Chat_DeploymentName"])
   .AsIChatClient()
    )
);

builder.Services.AddSingleton<ChatClientAgent>(sp =>
{
    return new ChatClientAgent(sp.GetKeyedService<IChatClient>("ChatClient"));
});

Now create a DI container to the ChatClientAgent

ServiceProvider serviceprovider = servicecollection.BuildServiceProvider();

var chatlient = serviceprovider.GetServices<ChatClientAgent>();

List<ChatClientAgent> lstchatclient = new(chatlient);

Create a client function that connects to the MCP endpoints and returns the MCP Server tool list.

      public static async Task < List < McpClientTool >> ConnectMCP() {
      AuthenticationResult result = await ReturnAuthenticationResult();

      var httpClient = new HttpClient {
        Timeout = Timeout.InfiniteTimeSpan
      };
      var transport = new ModelContextProtocol.Client.HttpClientTransport(
        new HttpClientTransportOptions {
          Endpoint = new Uri("https://api.fabric.microsoft.com/v1/mcp/core"),
            Name = "MCP Client",
            TransportMode = HttpTransportMode.AutoDetect,
            EnableStandaloneGetStream = false,
            AdditionalHeaders = new Dictionary < string, string > {
              {
                "Authorization",
                $ "Bearer {result.AccessToken}"
              }
            }
        },
        httpClient
      );

      var mcpClient = await McpClient.CreateAsync(transport);
      var tools = await mcpClient.ListToolsAsync();
      return tools.ToList();
    }

In the above code, we connect to MCP server endpoint through the MCP HttpClientTransport class and pass the bearer token through the method ReturnAuthenticationResult which returns an AuthenticationResult object.

Now, configure the ChatClientAgentOptions and set its Tools property to the method ConnectMCP() that was defined above.

  var options = new ChatClientAgentOptions()
  {
      ChatOptions = new ChatOptions()
      {
          Instructions = "You are a Fabric Agent and you execute the appropriate tools",
          ToolMode = AutoChatToolMode.Auto,
          Tools = [.. await ConnectMCP()]
      },
      Name = "Fabric Agent"
  };

Next, assign the options configured above to the ChatClient, create an AIAgent from it and then send a prompt to the agent.

var agent = lstchatclient [0].ChatClient.AsAIAgent(options);

AgentResponse  agentresponse = await agent.RunAsync("Create a lakehouse with name Fabric_MCP_LakeHouse in workspace My Test Workspace.");

Console.Write(agentresponse.Text);

Logging in as sachin.nandanwar @ azureguru.net and the lakehouse creation succeeds

Trying to do the same logging in as sachin_nandanwar @ azureguru.net

This is because sachin_nandanwar @ azureguru.net only has Viewer access for the workspace "My Test Workspace".

Now let me try to list items(semantic models) in the same workspace. The prompt should return list of the semantic models as the user (sachin_nandanwar @ azureguru.net ) has viewer access for the workspace.

The updated prompt is

AgentResponse  agentresponse = await agent.RunAsync("Provide a list of semantic models in My Test Workspace.");

Console.Write(agentresponse.Text);

There are many amazing things that you could do using the Fabric MCP Server tools, of course being limited to the underlying permissions the logged in user has.

But you might argue that all these features are already available through VS Code GitHub Copilot.

Yes it is, but what if you want to extend this functionality to other external applications or AI agents ?

This is where exposing your agent through MCP becomes particularly useful. Instead of limiting the functionality to a specific environment you can now make your agent available as an MCP tool for Fabric ecosystem that can be consumed by any MCP-compatible client.

Execution

Conclusion

Integrating the Microsoft Agent Framework (MAF) with the Fabric Core MCP Server provides a powerful way to extend AI agents with Fabric capabilities.

Through this article I tried to demonstrates how MAF and MCP can work together to connect AI agents with external data and services while maintaining authentication and integrating the Fabric security model.

Thanks for reading !!!

More from this blog