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?
Join the conversation! Your thoughts help the community grow.