# How to Implement Subscriptions for Real-Time Updates in MCP

> Learn to implement real-time subscriptions in Model Context Protocol MCP servers. Register RPC handlers, track sessions, and push update notifications for instant data synchronization. Explore the repository for code examples.

- Repository: [Model Context Protocol/servers](https://github.com/modelcontextprotocol/servers)
- Tags: how-to-guide
- Published: 2026-03-01

---

**Implement real-time subscriptions in Model Context Protocol (MCP) servers by registering `Subscribe` and `Unsubscribe` RPC handlers, tracking active sessions in a `Map<uri, Set<sessionId>>`, and pushing `notifications/resources/updated` messages through session-scoped intervals.**

The Model Context Protocol (MCP) enables servers to push live resource updates to connected clients through a subscription mechanism. This guide explains how to implement subscriptions for real-time updates in MCP using the reference implementation found in the `modelcontextprotocol/servers` repository, specifically within the *Everything* example server.

## Architecture of MCP Subscriptions

### Core Components

The subscription system relies on three coordinated mechanisms working together to manage client connections and message delivery:

1. **Subscription request handling** – Registers `Subscribe` and `Unsubscribe` RPCs to process client requests.
2. **Session-scoped update loops** – A timer that periodically emits `notifications/resources/updated` for each URI a client is subscribed to.
3. **Toggle tool** – The `toggle-subscriber-updates` tool allows clients to start or stop the periodic notifications for their session.

### Data Structures

The canonical tracking mechanism uses two primary data structures defined in [`src/everything/resources/subscriptions.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/resources/subscriptions.ts):

- **`subscriptions`**: A `Map<string, Set<string>>` mapping resource URIs to sets of active session IDs.
- **`subsUpdateIntervals`**: A `Map<string, NodeJS.Timeout>` storing timer handles for each session's update loop.

## Key Implementation Files

### [`src/everything/resources/subscriptions.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/resources/subscriptions.ts)

This file contains the core subscription logic, including request handlers and the simulated update loop. The `setSubscriptionHandlers` function registers the `Subscribe` and `Unsubscribe` RPCs, while `sendSimulatedResourceUpdates` walks through the subscriptions map to emit notifications.

### [`src/everything/tools/toggle-subscriber-updates.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/toggle-subscriber-updates.ts)

This tool exposes a user-facing interface to control the update loop. When invoked, it calls `beginSimulatedResourceUpdates` or `stopSimulatedResourceUpdates` to manage the 5-second interval for the requesting session.

### [`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts)

The server factory wires everything together. It instantiates the `McpServer`, enables the `resources.subscribe` capability, registers all handlers, and ensures cleanup routines stop active update loops when sessions terminate.

## Step-by-Step Implementation

### Registering Subscription Handlers

First, enable subscription capabilities and register the RPC handlers in your server initialization:

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp";
import { setSubscriptionHandlers } from "./resources/subscriptions";

const server = new McpServer({
  name: "my-server",
  version: "1.0.0",
  capabilities: {
    resources: {
      subscribe: true  // Enable subscription support
    }
  }
});

setSubscriptionHandlers(server);  // Registers Subscribe/Unsubscribe RPCs

```

### Managing Update Loops

Implement the session-scoped update mechanism to push notifications. The `sendSimulatedResourceUpdates` function in [`subscriptions.ts`](https://github.com/modelcontextprotocol/servers/blob/main/subscriptions.ts) demonstrates the pattern:

```typescript
const sendSimulatedResourceUpdates = async (sessionId: string) => {
  // Iterate through all subscribed URIs
  for (const [uri, sessionIds] of subscriptions.entries()) {
    if (sessionIds.has(sessionId)) {
      // Send notification to specific session
      await server.server.notification({
        method: "notifications/resources/updated",
        params: { uri }
      });
    }
  }
};

```

### Handling Cleanup

Ensure proper resource cleanup when sessions disconnect. Store interval handles and clear them on session end:

```typescript
const subsUpdateIntervals = new Map<string, NodeJS.Timeout>();

const beginSimulatedResourceUpdates = (sessionId: string) => {
  const interval = setInterval(() => {
    sendSimulatedResourceUpdates(sessionId);
  }, 5000); // 5-second interval
  
  subsUpdateIntervals.set(sessionId, interval);
};

// Cleanup on disconnect
const cleanupSession = (sessionId: string) => {
  stopSimulatedResourceUpdates(sessionId);
  // Remove session from all subscription sets
  for (const sessionIds of subscriptions.values()) {
    sessionIds.delete(sessionId);
  }
};

```

## Complete Code Example

Here is the complete pattern for implementing subscriptions for real-time updates in MCP:

```typescript
// 1. Register the subscription handlers (usually in your server factory)
import { setSubscriptionHandlers } from "./resources/subscriptions";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp";

const server = new McpServer({
  name: "example-server",
  version: "1.0.0",
  capabilities: {
    resources: { subscribe: true }
  }
});

setSubscriptionHandlers(server);   // Enables Subscribe/Unsubscribe RPCs

// 2. (Optional) Expose a tool to start/stop simulated updates
import { registerToggleSubscriberUpdatesTool } from "./tools/toggle-subscriber-updates";
registerToggleSubscriberUpdatesTool(server);

// 3. Client-side – subscribe to a resource URI
await client.request("resources/subscribe", {
  params: { uri: "myapp://example/resource/1" }
});

// 4. Client-side – turn on the simulated updater
await client.callTool("toggle-subscriber-updates");

// 5. Server pushes notifications every 5 seconds:
// {
//   method: "notifications/resources/updated",
//   params: { uri: "myapp://example/resource/1" }
// }

```

**Key implementation details to remember:**

- Include `resources: { subscribe: true }` in the server capabilities configuration.
- Call `setSubscriptionHandlers` before any client connects to register the RPC handlers with the transport layer.
- Use the `toggle-subscriber-updates` tool or implement custom timer logic if you require a different update cadence.

## Summary

- **Enable capabilities**: Set `resources.subscribe: true` in your `McpServer` configuration to signal subscription support to clients.
- **Register handlers**: Use `setSubscriptionHandlers` from [`src/everything/resources/subscriptions.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/resources/subscriptions.ts) to process `Subscribe` and `Unsubscribe` RPCs.
- **Track sessions**: Maintain a `Map<uri, Set<sessionId>>` to record which clients are listening to which resource URIs.
- **Push updates**: Implement `sendSimulatedResourceUpdates` to emit `notifications/resources/updated` messages via `server.server.notification`.
- **Manage lifecycle**: Store interval handles in `subsUpdateIntervals` and clear them in cleanup routines when sessions disconnect.

## Frequently Asked Questions

### How do I enable subscription capabilities in an MCP server?

Add `resources: { subscribe: true }` to the capabilities object when instantiating `McpServer`. This signals to clients that the server supports the `resources/subscribe` and `resources/unsubscribe` RPCs. Then call `setSubscriptionHandlers(server)` to register the actual request handlers before the server starts accepting connections.

### What is the purpose of the toggle-subscriber-updates tool?

The `toggle-subscriber-updates` tool provides a user-facing mechanism to start or stop the simulated update loop for a specific session. When invoked, it calls `beginSimulatedResourceUpdates` or `stopSimulatedResourceUpdates`, which manage a 5-second interval that periodically triggers `sendSimulatedResourceUpdates` to push notifications to subscribed clients.

### How does the server handle client disconnections in subscriptions?

The server maintains a `subsUpdateIntervals` map storing `NodeJS.Timeout` handles for each active session. When a session ends, the cleanup routine calls `stopSimulatedResourceUpdates` to clear the interval, then iterates through the `subscriptions` map to remove the disconnected session ID from all URI subscriber sets, preventing memory leaks and ghost notifications.

### Can I customize the notification interval for resource updates?

Yes, while the reference implementation uses a fixed 5-second interval in `beginSimulatedResourceUpdates`, you can modify the `setInterval` duration or replace the timer-based approach entirely. For production use, you might implement event-driven updates instead of polling, or adjust the interval based on resource volatility by passing a custom delay parameter to your update loop initialization function.