Observed since 20 Oct, 16:54 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Bidirectional bridge between the Model Context Protocol (MCP) and AAEP
A bidirectional bridge between the Model Context Protocol (MCP) and the Agent Accessibility Event Protocol (AAEP). Demonstrates that the two protocols address orthogonal concerns and compose cleanly.
If you build agents that use MCP for tool integration and want them to also speak AAEP for accessibility, this bridge shows how.
MCP and AAEP solve different problems:
| Protocol | Addresses | Standardizes |
|---|---|---|
| MCP | Agent ↔ Tool/Resource | Tool discovery, invocation, resources, prompts |
| AAEP | Agent ↔ Assistive Technology | Lifecycle events, safety gating, output streaming for AT |
They are complementary, not competing. An agent using MCP for tool integration can simultaneously use AAEP for accessibility announcements; the two protocols address orthogonal concerns and do not conflict.
This bridge makes their cooperation concrete. It runs between an MCP-aware agent and an AAEP-aware AT, translating relevant signals in both directions.
The bridge is a small process that:
Specifically:
| MCP event | AAEP event emitted |
|---|---|
tools/list returns server capabilities | (no emission; metadata only) |
tools/call request (before execution) | aaep:agent.tool.invoked |
tools/call request, irreversible flagged | aaep:agent.awaiting.confirmation BEFORE the MCP call |
tools/call response success | aaep:agent.tool.completed (status=success) |
tools/call response error | aaep:agent.tool.completed (status=error) |
tools/call request times out | aaep:agent.tool.completed (status=timeout) |
| MCP server disconnects | aaep:agent.session.errored (error_category=network) |
resources/read | (optional; emitted as state.changed to reading_resource) |
prompts/get | (optional; emitted as state.changed to loading_prompt) |
The bridge also supports the reverse direction:
| AAEP signal | MCP action |
|---|---|
confirmation.reply decision=reject | Cancel pending tools/call request, return error to MCP client |
confirmation.reply decision=accept | Allow tools/call request to proceed to the MCP server |
clarification.reply response | Forward as additional context to the MCP server (advisory) |
cd examples/bridges/mcp-aaep-bridge
pip install -e .
Requires Python 3.10 or newer. The bridge depends on:
aaep-minimal-producer>=1.0.0 (reuses the emitter)mcp>=1.0.0 (the official MCP Python SDK)aiohttp>=3.9.0 (HTTP/SSE transport for AAEP subscribers)The bridge connects to an MCP server you've already set up. For example, if you have an MCP filesystem server:
# In one terminal: an MCP server
npx -y @modelcontextprotocol/server-filesystem /path/to/workspace
aaep-mcp-bridge \
--mcp-server "npx -y @modelcontextprotocol/server-filesystem /path/to/workspace" \
--aaep-port 8090
This starts a bridge that:
/events SSE endpoint on http://localhost:8090In another terminal:
aaep-listen --endpoint http://localhost:8090
In a third terminal, send an MCP request through the bridge (or have your agent connect to the bridge as if it were the MCP server directly):
# Example: list available tools (simple MCP request)
curl -X POST http://localhost:8090/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'
# Example: call a tool
curl -X POST http://localhost:8090/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "read_file",
"arguments": {"path": "/etc/hostname"}
}
}'
The AAEP subscriber (terminal with aaep-listen) will show:
[12:34:56.789] aaep:agent.tool.invoked Calling read_file via MCP.
tool: read_file
risk_level: low
irreversible: false
args_summary: path=/etc/hostname
[12:34:56.823] aaep:agent.tool.completed myhost.local
tool: read_file
status: success
For tools flagged as irreversible (configurable; see §"Risk Configuration" below), the bridge inserts an awaiting.confirmation event before the MCP call and blocks until the AT subscriber replies.
AT Subscriber MCP Server
↑ ↑
│ SSE /events │ stdio
│ POST /messages │ JSON-RPC
│ │
▼ ▼
┌────────────────────────────────────────────────────────────────┐
│ aaep-mcp-bridge process │
│ │
│ ┌──────────────┐ translation ┌──────────────┐ │
│ │ AAEP │ ───────────────▶│ MCP Client │ │
│ │ Producer │ │ (stdio) │ │
│ └──────────────┘ └──────────────┘ │
│ ▲ │ │
│ │ │ │
│ │ confirmation reply │ tool/call │
│ │ (accept/reject) │ response │
│ │ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ HTTP server: /mcp /events /messages │ │
│ └──────────────────────────────────────────┘ │
│ ▲ │
│ │ JSON-RPC │
│ │ HTTP │
└──────┼─────────────────────────────────────────────────────────┘
│
│
Agent (any LLM with MCP support)
The agent talks to the bridge as if it were the MCP server. The MCP server is unchanged. The AT is unchanged. The bridge is the glue.
By default, the bridge uses heuristics matching the python-minimal example to classify tool risk:
send_, delete_, transfer_, write_, execute_, publish_, make_payment → high-risk irreversibleTo override, provide a --risk-config JSON file:
{
"tool_overrides": {
"read_file": {"risk_level": "low", "irreversible": false},
"write_file": {"risk_level": "high", "irreversible": true},
"execute_command": {"risk_level": "high", "irreversible": true}
},
"default": {"risk_level": "low", "irreversible": false}
}
The bridge consults this map for every tools/call before deciding whether to emit awaiting.confirmation.
mcp-aaep-bridge/
├── README.md
├── pyproject.toml
├── aaep_mcp_bridge/
│ ├── __init__.py
│ ├── bridge.py # MCPToAAEPBridge — the core translator
│ ├── risk.py # Risk classification + override config
│ └── server.py # HTTP server combining /mcp + AAEP /events
└── tests/
└── test_bridge.py
This is a reference bridge, not production code. Specifically:
tools/call responses; if/when it does, this bridge will need updating.tools/*. Resources and prompts emit state.changed only.For production deployments, consider these as starting points to extend, not finished features to rely on.
../opentelemetry-aaep-bridge/ — sister bridge for OpenTelemetry../../subscribers/cli-debug/ — subscriber to test this bridge withpypistats · 62 observations shown. Missing days are unknown. Source category: overall: without mirrors.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-19 – 2026-10-19 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-18 – 2026-10-18 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-17 – 2026-10-17 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-16 – 2026-10-16 | 5 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-15 – 2026-10-15 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-13 – 2026-10-13 | 3 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-12 – 2026-10-12 | 3 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-11 – 2026-10-11 | 6 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-10 – 2026-10-10 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-09 – 2026-10-09 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-08 – 2026-10-08 | 6 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-07 – 2026-10-07 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-06 – 2026-10-06 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-05 – 2026-10-05 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-03 – 2026-10-03 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-10-01 – 2026-10-01 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-30 – 2026-09-30 | 3 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-29 – 2026-09-29 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-27 – 2026-09-27 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-26 – 2026-09-26 | 5 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-25 – 2026-09-25 | 3 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-24 – 2026-09-24 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-23 – 2026-09-23 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-18 – 2026-09-18 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-17 – 2026-09-17 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-12 – 2026-09-12 | 3 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-10 – 2026-09-10 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-09 – 2026-09-09 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-07 – 2026-09-07 | 4 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-05 – 2026-09-05 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-04 – 2026-09-04 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-03 – 2026-09-03 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-02 – 2026-09-02 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-09-01 – 2026-09-01 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-31 – 2026-08-31 | 3 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-30 – 2026-08-30 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-28 – 2026-08-28 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-27 – 2026-08-27 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-26 – 2026-08-26 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-24 – 2026-08-24 | 9 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-23 – 2026-08-23 | 3 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-21 – 2026-08-21 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-20 – 2026-08-20 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-18 – 2026-08-18 | 19 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-17 – 2026-08-17 | 4 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-15 – 2026-08-15 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-14 – 2026-08-14 | 8 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-13 – 2026-08-13 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-11 – 2026-08-11 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-09 – 2026-08-09 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-08 – 2026-08-08 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-06 – 2026-08-06 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-04 – 2026-08-04 | 3 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-03 – 2026-08-03 | 6 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-02 – 2026-08-02 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-08-01 – 2026-08-01 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-07-29 – 2026-07-29 | 11 | 2026-10-20T18:37:02.2632937Z |
| 2026-07-28 – 2026-07-28 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-07-27 – 2026-07-27 | 3 | 2026-10-20T18:37:02.2632937Z |
| 2026-07-24 – 2026-07-24 | 1 | 2026-10-20T18:37:02.2632937Z |
| 2026-07-23 – 2026-07-23 | 2 | 2026-10-20T18:37:02.2632937Z |
| 2026-07-22 – 2026-07-22 | 2 | 2026-10-20T18:37:02.2632937Z |
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 1.0.0 | 3 Jun 2026 | 7 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 16:54 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:1f059f638a4bc12026803b3cceb87e00a8d6e2a0567c930b11855298a4b74f8b