MCP and A2A Integration Boundaries
Why this chapter matters
MCP and A2A are often mentioned beside AG-UI and A2UI, but they operate at different boundaries. A frontend architect should know enough to avoid building the wrong integration surface.
- MCP: connects AI applications to external tools, data sources, and workflows.
- A2A: connects agents to other agents so they can communicate and coordinate.
- AG-UI: connects agents to user-facing applications.
- A2UI: describes generated UI in a renderable, declarative way.
The frontend usually should not become a direct universal tool broker. It should consume safe, application-level events and expose user actions through controlled contracts.
Core mental model
AI systems need three integration planes:
| Plane | Protocol family | Boundary question |
|---|---|---|
| Agent to user | AG-UI, app-specific event streams | How does the user see, steer, approve, and recover work? |
| Agent to tools/data | MCP, internal tool APIs | What can the agent access or execute? |
| Agent to agent | A2A, internal agent bus | How do agents discover, delegate, and coordinate? |
If the product has only one agent and a few internal tools, you may not need A2A. If tools are stable and owned by one backend, you may not need MCP immediately. But the boundaries still matter because they define ownership and risk.
MCP architecture
MCP standardizes how an AI application connects to external systems. In production terms, an MCP server exposes capabilities. An agent client can discover and invoke those capabilities under policy.
Frontend relevance:
- Tool names and descriptions influence what progress can be shown to users.
- Tool schemas influence approval UI and validation.
- Tool permissions influence which actions can be offered.
- Tool latency influences streaming states and timeout UX.
- Tool failure influences recovery paths.
Tool contract checklist
| Contract area | Required answer |
|---|---|
| Capability | What does the tool do, exactly? |
| Input schema | What arguments are allowed and validated? |
| Authorization | Who may invoke it and under what context? |
| Side effects | Does it read, write, notify, spend, or delete? |
| Idempotency | Can retries duplicate side effects? |
| Approval | Does a human need to confirm before execution? |
| Audit | What should be logged and retained? |
| Timeout | How long can it run before degradation? |
| Output | What structured result should be shown or hidden? |
A2A architecture
A2A is useful when independently built agents need to communicate. For example:
- a support agent asks a billing agent to inspect invoices
- a sales agent asks a compliance agent to review contract language
- a research agent delegates data collection to specialized agents
- an enterprise assistant coordinates with agents owned by different teams
Frontend relevance:
- Users need to know when work is delegated.
- Delegated work needs status and terminal outcomes.
- Permissions may differ across agents.
- Audit logs must show which agent did what.
- Failures should identify the failed delegation without exposing internal noise.
Boundary patterns
Pattern 1: Backend-owned tools
The application backend wraps all tools. The agent can only call internal APIs.
Use when:
- the product is early
- tool set is small
- security requirements are strict
- teams are not ready to operate MCP servers
Pattern 2: MCP behind backend policy
The backend exposes selected MCP capabilities to the agent runtime. The frontend sees only application events.
Use when:
- multiple tools need standard schemas
- teams want reusable AI integrations
- capabilities need discovery and governance
Pattern 3: A2A orchestration service
The application delegates to other agents through an agent gateway. The frontend receives unified workflow events.
Use when:
- multiple independently owned agents must cooperate
- agent discovery and interoperability are requirements
- a single frontend must track cross-agent workflows
Security model
Never assume the model should receive all tool capabilities. Capability exposure is a permissions decision.
Controls:
- least-privilege tool lists per user, tenant, and workflow
- explicit side-effect classification
- human approval for risky operations
- secrets never exposed to browser or prompt text
- audit trails across user, agent, tool, and resource
- rate limits and cost limits
- sandboxing for untrusted tools
- policy checks before and after tool execution
Observability model
Every cross-boundary action should be traceable:
| Event | Trace fields |
|---|---|
| Tool discovered | server, capability, version, policy result |
| Tool requested | workflow id, actor, arguments hash, risk class |
| Tool approved | approver, timestamp, edited arguments |
| Tool executed | latency, status, output shape, side effects |
| Agent delegated | source agent, target agent, task id |
| Agent responded | result status, confidence, artifacts |
Frontend events should reference these traces without dumping sensitive internals into the browser.
Capability design for MCP-style tools
A good tool is narrow, typed, and reviewable. A bad tool is a vague remote-control handle.
Bad:
{
"name": "crm_action",
"description": "Do things in the CRM",
"input": { "command": "string" }
}
Better:
{
"name": "draft_customer_email",
"description": "Create a draft email for a customer. Does not send.",
"input": {
"customerId": "string",
"purpose": "renewal | support_followup | onboarding",
"tone": "concise | formal | friendly",
"sourceIds": "string[]"
},
"sideEffect": "draft_only",
"requiresApproval": false
}
Best for risky actions:
{
"name": "send_customer_email",
"description": "Send an approved email draft to a customer.",
"input": {
"draftId": "string",
"approvedPayloadHash": "string",
"recipientCustomerId": "string"
},
"sideEffect": "external_notification",
"requiresApproval": true,
"idempotencyKey": "required"
}
The frontend approval UI depends on this metadata. Without side-effect class and approval requirements, the UI cannot explain risk clearly.
Tool risk classes
Classify tools before exposing them to an agent.
| Risk class | Examples | Frontend requirement |
|---|---|---|
| Read | search docs, inspect account, fetch usage | Show source/provenance where relevant |
| Draft | draft email, generate ticket, prepare report | Make editable and do not imply action was taken |
| Internal write | update CRM field, create internal task | Show confirmation and audit note |
| External notify | send email, post message, contact customer | Require approval with exact preview |
| Spend | buy ad, issue credit, provision resource | Require strong confirmation and policy checks |
| Destructive | delete data, revoke access, cancel contract | Usually disallow or require elevated workflow |
Do not expose high-risk classes until lower-risk classes are reliable.
A2A delegation contract
When one agent delegates to another, require a task contract:
{
"delegationId": "del_44",
"sourceAgent": "renewal-agent",
"targetAgent": "billing-agent",
"task": "Summarize unpaid invoices for Acme",
"userContext": {
"userId": "u_123",
"tenantId": "acme",
"role": "customer_success_manager"
},
"allowedData": ["invoice_summary", "payment_status"],
"forbiddenActions": ["send_invoice", "modify_payment_terms"],
"timeoutMs": 30000
}
Frontend display can be simple: "Checking billing status." The backend trace must be specific: target agent, policy context, allowed data, timeout, result, and failure.
Boundary escalation rules
Escalate architecture review when:
- a browser would call a tool server directly
- a tool can perform external side effects
- a tool has broad "execute command" semantics
- an agent can delegate to agents owned by another team
- tool output includes sensitive records
- generated UI includes actions backed by MCP tools
- a workflow crosses tenant, region, or compliance boundaries
These are not reasons to block all AI work. They are reasons to design the integration as infrastructure, not feature glue.
Frontend integration patterns
The frontend should almost always talk to an application backend, not directly to arbitrary MCP or A2A endpoints.
| Pattern | Shape | Use when |
|---|---|---|
| Backend mediator | Frontend -> app backend -> agent/tools | Default for product applications |
| Agent gateway | Frontend -> gateway -> multiple agents/tools | Multiple teams expose agent capabilities |
| Direct local MCP | Desktop/local app -> local MCP server | User-owned local tools/files with explicit consent |
| Embedded app/plugin | Frontend hosts sandboxed UI from external capability | Strong isolation and review are available |
For web SaaS products, backend mediation is the safest default because it centralizes auth, policy, cost, audit, redaction, and incident response.
Permission propagation model
Every tool or agent call should carry a policy context:
{
"policyContext": {
"userId": "u_123",
"tenantId": "acme",
"roles": ["customer_success_manager"],
"workflowId": "wf_491",
"dataScopes": ["crm:read", "tickets:read", "email:draft"],
"deniedScopes": ["billing:write", "email:send_without_approval"],
"region": "us",
"riskLevel": "medium"
}
}
The model may choose a tool, but deterministic policy decides whether the tool can run. The frontend should receive enough policy result to explain blocked actions without exposing sensitive policy internals.
Example user-facing copy:
- "I can draft this email, but sending requires approval."
- "Billing details are not available to your role."
- "This action requires a manager because it changes contract terms."
Tool output shaping
Tool output should be shaped before it reaches the frontend or model.
| Raw output problem | Shaped output behavior |
|---|---|
| Too much data | Summarize and include source ids or pagination |
| Sensitive fields | Redact or omit by policy |
| Untrusted rich text | Convert to plain text or sanitized format |
| Inconsistent errors | Normalize to typed error codes |
| Large binary/file | Return preview metadata and signed access flow |
| Ambiguous side effect | Return explicit status and idempotency key |
Frontend components should render shaped outputs. They should not parse raw tool logs.
A2A user experience model
Agent delegation can be visible without becoming noisy.
| Delegation state | User-facing text |
|---|---|
| Started | "Checking billing context" |
| Waiting | "Waiting for billing agent response" |
| Partial result | "Billing found 2 open invoices" |
| Failed recoverable | "Billing status is unavailable; continue without it?" |
| Denied | "Billing details are restricted for this account" |
| Completed | "Billing context included in the plan" |
The user does not need internal protocol details. They do need to understand why the task is waiting, what context was included, and what was omitted.
Integration test matrix
| Test | Expected result |
|---|---|
| User lacks tool permission | Tool is not invoked; UI explains limitation |
| Tool times out | Workflow pauses or degrades; retry is bounded |
| Tool returns unsafe content | Output is sanitized or rejected |
| Approval payload changes after preview | Approval is rejected due to hash mismatch |
| Agent delegates to unavailable agent | User sees partial workflow recovery |
| Tenant context missing | Call fails closed |
| Duplicate retry | Idempotency prevents duplicate side effects |
| Direct browser call attempted | Request is blocked by architecture/policy |
These tests are more important than testing the happy-path agent demo.
Scenario: MCP-backed email workflow
Flow:
- User asks the agent to follow up with a customer.
- Agent retrieves permitted customer context.
- Agent calls
draft_customer_email, a draft-only tool. - Frontend renders an editable draft with citations.
- User edits the email.
- Agent requests
send_customer_email. - Backend requires approval tied to the exact draft hash.
- User approves.
- Backend sends through the normal email service with idempotency key.
- Workflow records external notification audit event.
This is the difference between "agent sends email" and a real production integration. The latter has draft state, approval binding, idempotency, audit, and fallback.
Anti-patterns
- Giving agents broad tool access because "the model can decide."
- Letting the browser call MCP servers directly with user secrets.
- Treating agent-to-agent delegation as invisible backend implementation.
- Allowing tool descriptions to become prompt-injection attack surfaces.
- Failing to distinguish read-only tools from side-effect tools.
- Logging full sensitive tool outputs into analytics.
Verification checklist
- Each protocol boundary has a named owner.
- MCP-style tools have schemas, permissions, side-effect classification, and audit logs.
- A2A-style delegation has workflow correlation and user-visible status where relevant.
- The frontend receives safe events, not raw secret-bearing tool output.
- Risky actions require approval and are replay-safe or idempotent.
- Tool and agent failures have product-specific recovery states.
Exercises
- Classify five internal APIs as read-only, write, notify, spend, or delete.
- Design an approval UI for an MCP-style tool that sends an external message.
- Draw a workflow where one agent delegates to another and returns status to the frontend.
- Write a policy for which tools are exposed to which user roles.
Source lens
This chapter is based on Firecrawl research of the Model Context Protocol documentation, the A2A project material, and AG-UI's protocol-layer framing of MCP for tools/data, A2A for agent-to-agent interaction, and AG-UI for agent-to-user interaction.