Why MCP Needs Event Subscriptions
The Model Context Protocol is request/response by design. But tools that monitor, watch, and react in real-time need something more. Here's what we're proposing.
The Problem
MCP (Model Context Protocol) is a brilliant abstraction. It gives AI agents a standardized way to discover and use tools — call a function, get a result, move on. For most tools, this request/response model is perfect.
But some tools aren't transactional. They're continuous.
We hit this wall building NeuralDiff. Our SDK includes a watch() feature — a daemon that monitors your UI in real-time and fires events when visual regressions are detected. The daemon uses WebSockets internally. It's fast, it's efficient, and it works great.
Except it can't talk to the AI agent.
When Claude Code connects to our MCP server, it can call neuraldiff_capture and neuraldiff_compare. But it can't subscribe to change events. The agent has to poll — repeatedly calling tools in a loop, hoping to catch changes. That's wasteful, slow, and fundamentally at odds with how the underlying system actually works.
What Exists Today
MCP currently supports three transport mechanisms:
- stdio — Synchronous pipe. Agent writes to stdin, reads from stdout. Pure request/response.
- SSE (Server-Sent Events) — The server can push messages, but the client still initiates via HTTP POST. It's unidirectional push, not true bidirectional communication.
- Streamable HTTP — More flexible, but still HTTP semantics. Each interaction is a discrete request.
None of these support a model where the server says: "Hey, something just happened that you should know about" without the client asking first.
The Proposal: MCP Event Subscriptions
We're proposing a new primitive for MCP: event subscriptions. The concept is simple:
- MCP servers can declare events they emit, alongside their existing tools, resources, and prompts.
- Clients can subscribe to specific events.
- The server pushes notifications when those events occur, without the client polling.
Server Declaration
In the MCP server manifest, alongside tools and resources, servers would declare events:
{
"name": "neuraldiff",
"version": "1.1.0",
"tools": [ ... ],
"events": [
{
"name": "visual_regression_detected",
"description": "Fired when a visual change is detected during watch mode",
"schema": {
"type": "object",
"properties": {
"route": { "type": "string" },
"severity": { "enum": ["critical", "major", "minor", "info"] },
"changes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"category": { "type": "string" },
"description": { "type": "string" }
}
}
}
}
}
},
{
"name": "baseline_drift",
"description": "Fired when cumulative changes exceed a threshold"
}
]
}Client Subscription
The client sends a subscribe request, similar to how it calls a tool:
// Client → Server
{
"jsonrpc": "2.0",
"method": "events/subscribe",
"params": {
"event": "visual_regression_detected",
"filter": { "minSeverity": "minor" }
},
"id": 1
}
// Server → Client (acknowledgment)
{
"jsonrpc": "2.0",
"result": {
"subscriptionId": "sub_abc123",
"event": "visual_regression_detected"
},
"id": 1
}Server Push
When the event fires, the server sends a notification. No client request needed:
// Server → Client (push)
{
"jsonrpc": "2.0",
"method": "events/notification",
"params": {
"subscriptionId": "sub_abc123",
"event": "visual_regression_detected",
"data": {
"route": "/checkout",
"severity": "critical",
"changes": [
{
"category": "layout",
"description": "CTA button shifted 24px down"
},
{
"category": "color",
"description": "Primary button: #3b82f6 → #ef4444"
}
],
"timestamp": "2025-03-04T15:32:00Z"
}
}
}Why This Matters Beyond NeuralDiff
Visual regression monitoring is our use case, but the pattern is everywhere:
- Log monitoring tools — push when an error pattern is detected
- CI/CD integrations — push when a build finishes or a deployment completes
- Database watchers — push when a migration runs or data changes
- File system monitors — push when relevant files change on disk
- API health checks — push when an endpoint goes down or latency spikes
Any tool that fundamentally observes something over time is awkward in a pure request/response protocol. Today, the workarounds are polling (wasteful), long-lived tool calls that never return (hacky), or out-of-band communication (defeats the purpose of a protocol).
Transport Considerations
Event subscriptions would work naturally with SSE and Streamable HTTP transports, since both already support server-initiated messages. For stdio, the server would write notification JSON-RPC messages to stdout unprompted — which is already valid in the JSON-RPC spec, it's just not exercised in MCP today.
A WebSocket transport would be the ideal addition, providing true bidirectional communication. But the proposal doesn't require it — event subscriptions can work on existing transports.
Relationship to A2A
Google's Agent-to-Agent protocol (A2A) already supports asynchronous task updates — an agent can push status changes to its peer. This is great for agent-to-agent communication, but it's a different layer. MCP is about agent-to-tool communication, and tools need the same async capability.
In the near term, we're exploring A2A as a workaround — the NeuralDiff daemon could act as a peer agent that pushes findings via A2A while still exposing tools via MCP. But this feels like a patch. The right solution is MCP supporting events natively.
What's Next
We're drafting a formal proposal for the MCP specification repository. Our approach:
- Reference implementation — We'll implement event subscriptions in the NeuralDiff MCP server as a proof of concept, using stdio notifications.
- Spec draft — A formal extension to the MCP schema covering event declaration, subscription lifecycle, and notification delivery.
- Community feedback — We'll publish the proposal and implementation for review, then iterate based on feedback from the MCP community and other tool authors.
If you're building MCP servers that would benefit from push-based communication, we'd love to hear your use cases. The more real-world examples behind the proposal, the stronger it becomes.
NeuralDiff is an open-source visual regression detection system built for AI agents.
Follow our progress on GitHub.