Azure  

Building Cross-System Business Intelligence Agents with MCP

Business intelligence systems have traditionally depended on dashboards, scheduled reports, SQL queries, and analysts who know where the relevant data lives.

That model becomes difficult when business information is spread across multiple systems.

A sales question may require CRM data. Inventory questions may require an ERP or warehouse. Customer issues may live in a support platform. Operational metrics may come from databases or streaming systems.

An AI agent can provide a natural-language interface across these systems, but the difficult part is not simply connecting an LLM to several APIs.

The real engineering challenge is building a system that can discover the right data source, select the correct tool, respect permissions, combine results, and produce an answer that can be traced back to authoritative business data.

The Model Context Protocol (MCP) provides a standardized interface for AI applications to discover and invoke tools and access resources. MCP's architecture separates the host, client, and server responsibilities and defines tools, resources, and prompts as core primitives.

AWS has recently demonstrated an enterprise BI architecture built around Amazon Bedrock AgentCore, MCP servers, semantic metadata, and multiple data sources including Aurora, Redshift, S3 Tables, OpenSearch, and third-party SaaS systems.

For .NET developers, the same architecture can be implemented as a set of focused services rather than one large AI application.

The Business Intelligence Problem

Consider a question from a supply-chain manager:

Which products are likely to create inventory
problems next month, and which customers are affected?

That question may require information from:

CRM
 |
 +--> Customer accounts
 |
ERP
 |
 +--> Orders
 +--> Inventory
 |
Data Warehouse
 |
 +--> Historical sales
 |
Support System
 |
 +--> Customer issues

A conventional application might require custom integration code for every combination.

An agentic architecture can instead expose these capabilities through MCP:

                    AI Agent
                       |
        +--------------+--------------+
        |              |              |
        v              v              v
    CRM MCP        ERP MCP       Analytics MCP
        |              |              |
        v              v              v
      CRM          ERP / DB       Warehouse

The agent decides which tools are relevant to the question.

The MCP servers remain responsible for interacting with the underlying systems.

Why MCP Fits Cross-System BI

MCP provides a common protocol between an AI host and specialized servers.

The architecture separates responsibilities:

MCP Host
   |
   +--> MCP Client --> CRM MCP Server
   |
   +--> MCP Client --> ERP MCP Server
   |
   +--> MCP Client --> Analytics MCP Server

An MCP host can maintain separate client connections to multiple servers. MCP servers expose capabilities such as tools and resources through the protocol.

This separation is valuable because each business system can have its own integration boundary.

For example:

CRM MCP Server
    get_customer
    get_account_revenue

Inventory MCP Server
    get_inventory
    get_reorder_status

Sales MCP Server
    get_sales_history
    get_forecast

The agent does not need to understand the implementation details of every backend.

It needs to understand what each capability does.

A Practical Architecture

A production-oriented architecture can look like this:

                    User
                      |
                      v
                BI Agent / API
                      |
                      v
              Semantic Layer
                      |
          +-----------+-----------+
          |           |           |
          v           v           v
       CRM MCP     ERP MCP    Analytics MCP
          |           |           |
          v           v           v
        CRM          ERP       Warehouse

For larger environments, add centralized identity and policy:

                         Identity
                            |
                            v
User --> Agent --> Policy / Gateway
                  |
       +----------+----------+
       |          |          |
       v          v          v
    CRM MCP    ERP MCP    Data MCP
       |          |          |
       v          v          v
     SaaS        ERP       Database

AWS's recent autonomous BI architecture follows a similar layered approach, placing AgentCore between users and MCP connectors while using a semantic layer to help identify appropriate data sources.

Do Not Give the Agent Direct Database Access

A common first implementation is:

Agent
  |
  v
Database

This looks simple, but it creates several problems.

The model may:

  • Generate inefficient SQL.

  • Access tables it should not see.

  • Expose sensitive columns.

  • Ignore tenant boundaries.

  • Depend on internal schema details.

  • Produce inconsistent queries.

A safer design is:

Agent
  |
  v
MCP Tool
  |
  v
Business Logic
  |
  v
Database

For example:

get_customer_sales(customer_id, period)

is generally easier to govern than giving an agent unrestricted access to:

SELECT * FROM ...

The MCP tool becomes a controlled business capability.

Design Business-Level Tools

Tool design has a major effect on agent reliability.

Avoid overly generic tools:

execute_sql
call_api
run_query

Prefer domain-oriented tools:

get_customer_revenue
get_inventory_position
get_open_orders
get_customer_support_summary
get_sales_trend

MCP tools include metadata and schemas that allow clients to discover available capabilities. The protocol defines tool discovery through tools/list and execution through tools/call.

For example, a tool might expose:

{
  "name": "get_customer_revenue",
  "description": "Returns revenue for a customer over a specified period.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "customerId": {
        "type": "string"
      },
      "from": {
        "type": "string"
      },
      "to": {
        "type": "string"
      }
    },
    "required": [
      "customerId",
      "from",
      "to"
    ]
  }
}

The schema gives the agent a constrained interface.

Build MCP Servers Around Domains

A useful organizational boundary is the business domain.

For example:

Sales MCP
    get_customer
    get_pipeline
    get_revenue

Inventory MCP
    get_stock
    get_reorder_points
    get_purchase_orders

Support MCP
    get_open_tickets
    get_customer_issues

Finance MCP
    get_invoice_status
    get_payment_history

This has several advantages.

Independent Ownership

The sales team can own the Sales MCP server while the supply-chain team owns Inventory MCP.

Independent Security

Each server can enforce its own authorization requirements.

Easier Evolution

Changing an ERP implementation does not require changing every agent.

Better Observability

Tool calls can be associated with a specific domain.

Use a Semantic Layer

Finding the correct system is often harder than executing the query.

Suppose an agent receives:

Show me our best customers.

What does "best" mean?

It could mean:

Revenue
Profit
Order frequency
Customer lifetime value
Growth

The agent needs business definitions, not just database schemas.

A semantic layer can define:

Metric: Revenue
Definition: Recognized sales value
Source: Sales warehouse
Currency: USD
Aggregation: SUM

and:

Metric: Inventory Risk
Definition: Projected demand exceeds available supply
Source: Inventory + Forecast

AWS's current autonomous BI architecture uses a semantic layer backed by SageMaker Data Catalog to help agents identify the appropriate data sources and understand what data exists across the enterprise.

This is an important architectural distinction:

Database Schema
      !=
Business Meaning

Resources vs Tools

MCP provides more than executable tools.

Resources allow servers to expose contextual information such as database schemas, files, and other application-specific data.

This creates a useful pattern:

MCP Server
 |
 +--> Resources
 |      |
 |      +--> Schema
 |      +--> Metric definitions
 |      +--> Business glossary
 |
 +--> Tools
        |
        +--> Query customer
        +--> Get revenue
        +--> Get inventory

For example, an analytics MCP server might expose:

resource://analytics/metrics/revenue
resource://analytics/metrics/gross-margin
resource://analytics/business-glossary

and tools such as:

get_revenue
get_margin
compare_periods

The resources provide context.

The tools perform operations.

Implementing a Simple MCP Server in .NET

A simplified domain service might look like this:

public sealed class SalesService
{
    private readonly SalesDbContext _db;

    public SalesService(SalesDbContext db)
    {
        _db = db;
    }

    public async Task<decimal> GetCustomerRevenueAsync(
        string customerId,
        DateOnly from,
        DateOnly to)
    {
        return await _db.Orders
            .Where(o =>
                o.CustomerId == customerId &&
                o.OrderDate >= from &&
                o.OrderDate <= to)
            .SumAsync(o => o.TotalAmount);
    }
}

The MCP tool should call this service rather than placing business logic directly inside the protocol layer.

Conceptually:

MCP Tool
   |
   v
SalesService
   |
   v
EF Core
   |
   v
PostgreSQL / SQL Server

This keeps the architecture testable.

Add Tenant Filtering at the Data Boundary

For a SaaS BI application, tenant isolation must not depend on the model.

Suppose every order contains:

public Guid TenantId { get; set; }

The service should enforce tenant context:

public async Task<decimal> GetRevenueAsync(
    Guid tenantId,
    string customerId)
{
    return await _db.Orders
        .Where(o =>
            o.TenantId == tenantId &&
            o.CustomerId == customerId)
        .SumAsync(o => o.TotalAmount);
}

The model should never be trusted to supply the tenant filter correctly.

The authorization boundary should establish it.

Authenticated User
        |
        v
Tenant Context
        |
        v
MCP Tool
        |
        v
Business Service
        |
        v
Tenant-filtered query

Authentication and Authorization

Cross-system BI often involves sensitive data.

The agent may access:

Revenue
Customer information
Contracts
Invoices
Inventory
Employee data

Authentication alone is insufficient.

MCP's transport layer supports authentication mechanisms, and the current protocol architecture treats authorization as part of the transport/security boundary.

A practical authorization model could be:

ToolPermission
get_inventoryinventory:read
get_revenuesales:read
get_customercustomer:read
get_invoicefinance:read
update_orderorders:write

Read-only BI agents should generally not receive write permissions simply because the underlying MCP server supports them.

Keep Read and Write Tools Separate

Consider:

get_order
cancel_order

These should not be treated as equivalent capabilities.

A reporting agent may need:

get_order

but should not automatically receive:

cancel_order

This is especially important because MCP tools are designed to be model-controlled capabilities.

For high-impact operations, introduce additional controls:

Agent
 |
 v
Authorization
 |
 v
Human Approval
 |
 v
Write Tool

For a BI application, most initial tools should be read-only.

Handling Cross-System Queries

Now consider:

Which customers are affected by low inventory?

The agent might reason:

1. Identify products with projected inventory shortages.
2. Find open orders for those products.
3. Identify customers associated with those orders.
4. Retrieve customer information.
5. Summarize the result.

The tool sequence could be:

get_inventory_risk()
       |
       v
get_open_orders(productIds)
       |
       v
get_customers(customerIds)
       |
       v
generate_summary()

This is where MCP becomes particularly useful.

Each system remains independently accessible while the agent orchestrates the overall workflow.

Avoid Returning Huge Datasets

An MCP tool should not return an entire table if the agent needs only a small summary.

Avoid:

{
  "rows": [
    "... thousands of records ..."
  ]
}

Prefer:

{
  "customerId": "C1001",
  "revenue": 125000,
  "orderCount": 42,
  "currency": "USD"
}

For analytical queries, return aggregated data when possible.

This reduces:

  • Token consumption

  • Latency

  • Memory requirements

  • Model confusion

The agent should receive enough information to reason about the business question, not an uncontrolled database dump.

Handle Data Provenance

An answer such as:

Customer ABC is at high risk.

is not enough for an enterprise BI system.

The response should be traceable.

For example:

Risk: High

Based on:
- Inventory forecast
- Open orders
- Customer revenue

Sources:
- Inventory MCP
- Sales MCP
- CRM MCP

Data evaluated:
2026-08-01 to 2026-08-31

The exact provenance format depends on the application.

The important principle is that users should be able to understand where important business conclusions originated.

Handle Conflicting Systems

Enterprise data often disagrees.

For example:

CRM:
Customer revenue = $1.2M

Warehouse:
Customer revenue = $1.15M

The agent should not silently choose one.

Define source authority.

For example:

Revenue
    |
    +--> Finance Warehouse = authoritative
    |
    +--> CRM = operational estimate

The semantic layer can document this rule.

The agent can then answer:

Finance records report $1.15M.
CRM currently shows $1.2M.
The finance warehouse is the authoritative source
for recognized revenue.

That is much more useful than pretending the data is consistent.

Query Planning Matters

Cross-system agents need a query-planning strategy.

A simple plan can be represented as:

Question
   |
   v
Intent
   |
   v
Required Metrics
   |
   v
Data Sources
   |
   v
Tool Calls
   |
   v
Validation
   |
   v
Synthesis

For example:

Question:
Why did revenue decline last month?

Required information:

Revenue by month
Revenue by region
Revenue by product
Customer churn

The agent can then select the appropriate tools.

This is more reliable than exposing dozens of unrelated APIs and expecting the model to discover the complete workflow from scratch.

Control Tool Discovery

MCP supports dynamic tool discovery through tools/list.

In a large enterprise, however, exposing hundreds of tools to every agent can create unnecessary complexity.

A better architecture can introduce tool catalogs:

Agent
 |
 v
Tool Catalog
 |
 +--> Sales Tools
 +--> Inventory Tools
 +--> Finance Tools
 +--> Support Tools

The agent receives only the tools relevant to its role.

For example:

Supply Chain Agent
    |
    +--> Inventory
    +--> Orders
    +--> Logistics

while:

Finance Agent
    |
    +--> Revenue
    +--> Invoices
    +--> Payments

This reduces the tool-selection problem and improves governance.

Parallelize Independent Tool Calls

Suppose an answer requires:

Revenue
Inventory
Support tickets

and the three operations are independent.

A .NET orchestration layer can execute them concurrently:

var revenueTask =
    sales.GetRevenueAsync(customerId, cancellationToken);

var inventoryTask =
    inventory.GetRiskAsync(customerId, cancellationToken);

var supportTask =
    support.GetOpenIssuesAsync(customerId, cancellationToken);

await Task.WhenAll(
    revenueTask,
    inventoryTask,
    supportTask);

Then combine the results.

This avoids unnecessary sequential waiting.

However, parallel execution should be applied only when the operations are genuinely independent and the downstream systems can handle the concurrency.

Add Timeouts and Cancellation

External enterprise systems fail.

Every tool call should have a bounded lifetime.

using var timeout =
    CancellationTokenSource.CreateLinkedTokenSource(
        cancellationToken);

timeout.CancelAfter(TimeSpan.FromSeconds(10));

var result = await inventoryService
    .GetInventoryAsync(
        productId,
        timeout.Token);

The agent should receive a structured failure rather than an indefinite wait.

For example:

{
  "success": false,
  "errorCode": "INVENTORY_TIMEOUT",
  "message": "Inventory service did not respond within the configured timeout."
}

The agent can then explain the limitation instead of fabricating a result.

Design for Partial Failure

Cross-system BI needs to handle partial results.

Suppose:

CRM       -> Success
Inventory -> Success
Finance   -> Timeout

The agent should not present a complete financial analysis.

Instead:

Customer risk analysis is available from CRM and inventory data.

Finance data could not be retrieved, so revenue impact
could not be verified.

This is an important distinction for production systems.

Missing data is not zero data.

Observability

A cross-system agent should produce a trace similar to:

Request ID: BI-8421

Agent
 |
 +--> CRM MCP
 |      180 ms
 |
 +--> Inventory MCP
 |      240 ms
 |
 +--> Sales MCP
        920 ms
 |
 v
Final response

Record:

  • Request ID

  • User identity

  • Tenant

  • Agent

  • MCP server

  • Tool name

  • Duration

  • Success/failure

  • Result size

  • Authorization decision

Avoid logging sensitive business data unnecessarily.

For enterprise systems, logs should help answer:

Who asked?
Which tools were called?
Why were they called?
Which systems responded?
What failed?
How long did it take?

Security Risks

Cross-system BI introduces several security concerns.

Over-Privileged Tools

A read-only agent should not have write access.

Cross-Tenant Leakage

Every downstream query should preserve tenant context.

Prompt Injection

External content retrieved through CRM, documents, tickets, or web-connected systems can contain malicious instructions.

Retrieved data should be treated as data, not trusted agent instructions.

Sensitive Data Exposure

Do not send unnecessary customer or financial information to the model.

Tool Confusion

Similar tool names can cause incorrect selection.

Use explicit names:

get_invoice_status
get_inventory_status

instead of:

get_status

Common Mistakes

Giving the Agent Direct SQL Access

This creates a broad and difficult-to-govern capability.

Building One Giant MCP Server

A server containing every enterprise operation becomes difficult to secure and maintain.

Ignoring Business Definitions

Database column names do not necessarily represent business meaning.

Returning Raw Tables

Large responses increase latency and model context usage.

Treating Missing Data as Zero

A failed tool call should remain a failed tool call.

Ignoring Source Authority

Conflicting systems need documented precedence.

Letting the Model Decide Authorization

Authorization belongs to application and infrastructure policy, not the LLM.

Exposing Every Tool to Every Agent

Tool catalogs should be aligned with agent responsibilities.

Troubleshooting Cross-System Agents

The Agent Selects the Wrong Tool

Check:

  • Tool names

  • Descriptions

  • Input schemas

  • Tool overlap

  • Tool catalog filtering

Use explicit business-oriented names.

The Agent Produces Incorrect Numbers

Check:

  1. Source authority

  2. Metric definition

  3. Date filters

  4. Currency

  5. Aggregation

  6. Tenant filters

One Slow System Delays Everything

Measure each MCP call independently.

If independent calls are being executed sequentially, consider controlled parallel execution.

One System Is Unavailable

Return structured partial failure information and make the final answer explicitly state which data could not be retrieved.

Data From Another Tenant Appears

Treat this as a security incident.

Check tenant propagation from:

Identity
  |
  v
Agent
  |
  v
MCP
  |
  v
Business Service
  |
  v
Database

The tenant boundary must be enforced independently of the model.

Best Practices

  1. Use MCP servers as domain-specific integration boundaries.

  2. Prefer business-level tools over generic SQL tools.

  3. Use a semantic layer for business definitions and source discovery.

  4. Keep read and write capabilities separate.

  5. Enforce authorization outside the model.

  6. Propagate tenant context through every downstream request.

  7. Return compact, structured results.

  8. Track data provenance for important answers.

  9. Define authoritative sources for conflicting metrics.

  10. Use timeouts and cancellation for external systems.

  11. Support partial failure explicitly.

  12. Parallelize independent tool calls where appropriate.

  13. Instrument every MCP invocation.

  14. Expose only the tools required by each agent.

  15. Test prompt injection and unauthorized data access as part of the system's security testing.

Comparison: Direct APIs vs MCP-Based BI

ApproachDirect API IntegrationMCP-Based Integration
Agent interfaceCustom per systemStandardized protocol
Tool discoveryApplication-specificMCP discovery
Domain boundariesCustomNatural MCP server boundaries
Reuse across agentsRequires integration workMCP server can serve multiple clients
SecurityCustom implementationProtocol + application security
Business semanticsCustomCan be exposed through resources/tools
Cross-system orchestrationCustomAgent can coordinate multiple MCP clients
GovernanceApplication-specificCan combine catalogs, policies, and server boundaries

MCP does not remove the need for application architecture.

It provides a standardized interoperability layer.

Conclusion

Cross-system business intelligence is one of the more practical applications for MCP because enterprise data rarely exists in one system.

A useful architecture separates the responsibilities:

User
 |
 v
AI Agent
 |
 v
Semantic Layer
 |
 v
MCP Tool Selection
 |
 +--> CRM MCP
 |
 +--> ERP MCP
 |
 +--> Analytics MCP
 |
 +--> Support MCP
 |
 v
Authoritative Business Data

MCP provides standardized mechanisms for clients to discover and invoke tools and access contextual resources, while recent enterprise architectures are demonstrating how MCP connectors can sit between AI agents and databases, warehouses, operational systems, and SaaS applications.

For .NET teams, the most important design decision is not which LLM to use.

It is deciding where business logic, authorization, data ownership, and tool boundaries belong.

Keep those responsibilities outside the model.

Use MCP to expose focused capabilities.

Use semantic metadata to describe what the data means.

Use authorization to control what the agent can access.

And make every important answer traceable to the systems that produced it.

That approach turns MCP from a collection of API wrappers into a governed integration layer for enterprise AI.

Frequently Asked Questions

Can MCP connect an AI agent to multiple databases?

Yes. An MCP host can manage multiple MCP clients, with each client maintaining a connection to a particular MCP server. Those servers can expose capabilities backed by different databases or enterprise systems.

Should an MCP server expose raw SQL execution?

It can be technically possible, but it is generally a poor default for governed enterprise BI. Domain-specific tools provide a narrower and more controllable interface.

What is the role of a semantic layer?

A semantic layer provides business meaning around metrics, entities, definitions, and source systems. It helps the agent understand which data source should answer a business question rather than relying only on database schema names.

Can MCP servers connect to SaaS applications?

Yes. MCP servers can expose tools that call external APIs. AWS's current enterprise BI architecture specifically describes MCP connectivity to third-party SaaS systems such as Salesforce, SAP, and ServiceNow.

Should the agent have access to every enterprise system?

No. Tool access should follow the agent's role, user permissions, tenant boundaries, and business requirements.

What happens when one data source is unavailable?

The agent should return a partial result and clearly identify the unavailable source. It should never silently substitute missing data with a guessed value.

Is MCP itself a business intelligence platform?

No. MCP is an interoperability protocol for context exchange between AI applications and servers. The BI logic, semantic definitions, authorization, data governance, and analytics architecture still belong to the application and platform design.