web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

No record found.

News and Announcements icon
Community site session details

Community site session details

Session Id :
Dynamics 365 Community / Blogs / Learn with Subs / Challenges with BPA MCP ser...

Challenges with BPA MCP server and how to fix them

Subhad365 Profile Picture Subhad365 21 User Group Leader
Hiya friends, we have already seen the magnificent capabilities of BPA MCP server. It just not acts as an AI abstraction layer, enabling large language models (LLMs) to securely query and analyze ERP financial/dimensional data via natural language. It enables agents to perform instant tasks like variance detection and financial forecasting by providing structured access to BPA data models. I have covered the background, setup and process of handling BPA MCP servers, on a previous blog:
https://community.dynamics.com/blogs/post/?postid=72ab771f-1c08-f111-8407-7c1e52fd2cdc
And there is a very insightful blog by Ramit Paul to setup BPA server:
https://www.youtube.com/watch?v=qWafknUgGqM
And this one from Saurabh Bharti:
https://www.youtube.com/watch?v=6LKXuD5QB1E
However BPA MCP servers have certain limitations. For example, if you are asking it to plot any transaction trend:

Or with further options like:

The reason:
Copilot Studio cannot reliably render dynamically generated plot/chart images (for example, images produced at runtime by Python, Power BI export visuals, or external APIs) inside chat responses. When such images are referenced, Copilot Studio often shows a broken image placeholder instead.

Why this happens (root causes)

1. Copilot Studio chat UI does not support runtime image buffers

Plots generated dynamically (e.g., matplotlib, seaborn, Plotly static images) are typically:
  • Created in memory
  • Saved temporarily
  • Referenced via a URL or binary blob
Copilot Studio’s renderer:
  • Supports static, publicly accessible images
  • Does not support ephemeral or in‑memory images
So the image object exists, but the front-end cannot fetch it → broken image icon.

2. Restricted image sources & sandboxing

Copilot Studio enforces strict security boundaries:
Copilot chat cannot display images that are:
  • Behind authentication
  • Served from localhost / private APIs
  • Stored in temp storage
  • Generated inline (Base64, binary stream)
If your plot is coming from:
  • Azure Function output
  • Python runtime
  • Secure Blob without SAS
  • Power BI visual export API
…it will fail to render visually in chat.

3. Markdown + Adaptive Card limitations

Copilot Studio uses a restricted markdown and Adaptive Card renderer.
Unsupported patterns include:
  • <img> tags with dynamic URLs
  • Markdown images pointing to short‑lived links
  • Inline SVG or canvas-based charts
Even if the image URL is technically valid, the renderer may strip or fail silently.

4. Power BI visuals are especially affected
If your “plot image” comes from Power BI:
  • Exported visuals are often tenant‑secured
  • Share links may require interactive login
  • The Copilot chat sandbox cannot authenticate
Result: Copilot shows the caption text (like Vendor Purchase Trends) but not the image.

Quick fixes

Option 1

What can we do is to rephrase our instructions:

And then when you ask Copilot Studio to Plot:




Option 2

Another way is to pass on the information as a payload to Adaptive card. Adaptive cards are highly customizable and responsive instruments whereby you can send your JSON payloads to your card, asking it to render the plot as a chat response.
Ask me how:
Imagine the following JSON payload like this to an Adaptive card:
{
  "type": "AdaptiveCard",
  "version": "1.4",
  "body": [
    {
  "type": "TextBlock",
  "text": "Vendor-wise Purchase Trends",
  "weight": "Bolder",
  "size": "Medium"
    },
    {
       "type": "Image",
        "url": "https://quickchart.io/chart?c={type:'bar',data:{labels:['Acme   Office Supplies','Lande Packaging Supplies','Best Supplier - Europe','Fabrikam Supplier','Datum Receivers'],datasets:[{label:'Total Purchase Amount',data:[1000,100,50893.06,209,7340.2]}]}}",
        "size": "Stretch"
    }
 ] 
}

Checking this payload on https://adaptivecards.microsoft.com/designer.html (Uh, I love this site), you can paste this payload and you can see the effect:
 
You can follow the next few steps to make this dynamic in your Agent:

Step 1

Create a Prompt like this:

In the Text input, I am defining the JSON which I showed above. Please note that: there is a URL mentioned there. We need to scoop out the URL from the payload and need to pass it on as a variable:
{
  "type": "AdaptiveCard",
  "version": "1.4",
  "body": [
    {
      type: "TextBlock",
      text: “Plot demo on Adaptive cards”
      weight: "Bolder",
      size: "Medium"
    },
    {
      type: "Image",
      url: "${ImageURL}",
      size: "Stretch"
    }
  ]
}

Here, you see, ImageURL is a variable which we can pass on containing this info to Adaptive Card. But how would you do that?
Let me show you how.

Step 2

Create a topic that can accept an input variable:

And then in the message >> add an adaptive card which has a formula like this:

And finally in the instruction you need to mention something like this:

See here, I am passing the prompt first and then the topic to generate the Adaptive card.
So that when I am trying to ask the agent the same question, this is what I am getting:

That’s cool, ain’t so?
Signing off for now – coming back soon. Take care, much love and Namaste J

Comments

*This post is locked for comments