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:
| Tool | Permission |
|---|
| get_inventory | inventory:read |
| get_revenue | sales:read |
| get_customer | customer:read |
| get_invoice | finance:read |
| update_order | orders: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:
Source authority
Metric definition
Date filters
Currency
Aggregation
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
Use MCP servers as domain-specific integration boundaries.
Prefer business-level tools over generic SQL tools.
Use a semantic layer for business definitions and source discovery.
Keep read and write capabilities separate.
Enforce authorization outside the model.
Propagate tenant context through every downstream request.
Return compact, structured results.
Track data provenance for important answers.
Define authoritative sources for conflicting metrics.
Use timeouts and cancellation for external systems.
Support partial failure explicitly.
Parallelize independent tool calls where appropriate.
Instrument every MCP invocation.
Expose only the tools required by each agent.
Test prompt injection and unauthorized data access as part of the system's security testing.
Comparison: Direct APIs vs MCP-Based BI
| Approach | Direct API Integration | MCP-Based Integration |
|---|
| Agent interface | Custom per system | Standardized protocol |
| Tool discovery | Application-specific | MCP discovery |
| Domain boundaries | Custom | Natural MCP server boundaries |
| Reuse across agents | Requires integration work | MCP server can serve multiple clients |
| Security | Custom implementation | Protocol + application security |
| Business semantics | Custom | Can be exposed through resources/tools |
| Cross-system orchestration | Custom | Agent can coordinate multiple MCP clients |
| Governance | Application-specific | Can 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.