Notifications enable real-time, one-way communication between clients and servers. They’re used to signal events, state changes, and updates without requiring a response, making them perfect for keeping your application synchronized with server state.
Understanding Notifications
MCP notifications are JSON-RPC messages without response requirements. They enable:
- Real-time updates: Get notified when server state changes
- List synchronization: Tools, resources, and prompts list updates
- Custom events: Server-specific notifications for your application
- Progress tracking: Monitor long-running operations
Bidirectional: Both clients and servers can send notifications. Servers notify clients of changes, while clients notify servers of environment changes like root directories.
Notification Flow
Server → Client: Event notifications (tool lists changed, progress updates, custom events)
Client → Server: Environment notifications (roots changed, configuration updates)
Receiving Notifications (Server → Client)
Register a notification handler on your session using the on method:
import { MCPClient } from "mcp-use";
const client = new MCPClient({
mcpServers: {
myServer: { url: "http://localhost:3000/mcp" }
}
});
const session = await client.createSession("myServer");
// Register notification handler
session.on("notification", async (notification) => {
console.log(`Received: ${notification.method}`, notification.params);
});
Notification Structure
Notifications follow the JSON-RPC 2.0 format without an id field:
interface Notification {
method: string; // The notification method name
params?: Record<string, any>; // Optional parameters
}
Standard MCP Notifications
MCP defines several standard notification types that servers may send:
Sent when the server’s available tools have changed:
session.on("notification", async (notification) => {
if (notification.method === "notifications/tools/list_changed") {
console.log("Tools list updated - refreshing...");
// Refresh tools cache
const tools = await session.listTools();
console.log(`Now have ${tools.length} tools`);
}
});
Resources List Changed
Sent when resources have been added, removed, or modified:
session.on("notification", async (notification) => {
if (notification.method === "notifications/resources/list_changed") {
console.log("Resources updated");
const resources = await session.listAllResources();
// Update your UI or cache
}
});
Prompts List Changed
Sent when prompts have changed:
session.on("notification", async (notification) => {
if (notification.method === "notifications/prompts/list_changed") {
console.log("Prompts updated");
const prompts = await session.listPrompts();
// Update your UI or cache
}
});
Custom Notifications
Servers can send custom notifications with any method name:
session.on("notification", async (notification) => {
switch (notification.method) {
case "custom/heartbeat":
console.log(`Heartbeat #${notification.params?.count}`);
break;
case "custom/user-joined":
console.log(`User joined: ${notification.params?.username}`);
break;
case "custom/data-updated":
console.log("Data updated:", notification.params);
break;
default:
console.log(`Unknown notification: ${notification.method}`);
}
});
Sending Notifications (Client → Server)
Roots Changed
Roots represent directories or files that the client has access to. When you update roots, the client automatically sends a notifications/roots/list_changed notification to the server:
import { MCPClient, Root } from "mcp-use";
const client = new MCPClient({
mcpServers: {
myServer: { url: "http://localhost:3000/mcp" }
}
});
const session = await client.createSession("myServer");
// Set roots - this sends notifications/roots/list_changed to the server
await session.setRoots([
{ uri: "file:///home/user/project", name: "My Project" },
{ uri: "file:///home/user/data", name: "Data Directory" }
]);
// Get current roots
const roots = session.getRoots();
console.log(`Current roots: ${roots.length}`);
Initial Roots at Connection
You can provide initial roots when creating the connector:
import { HttpConnector, MCPSession } from "mcp-use";
const connector = new HttpConnector("http://localhost:3000/mcp", {
roots: [
{ uri: "file:///workspace", name: "Workspace" }
]
});
const session = new MCPSession(connector);
await session.connect();
await session.initialize();
// Later, update roots
await session.setRoots([
{ uri: "file:///workspace", name: "Workspace" },
{ uri: "file:///tmp/scratch", name: "Scratch" }
]);
TypeScript Types
Import the Notification type for type-safe handlers:
import { MCPClient, Notification, NotificationHandler } from "mcp-use";
// Type-safe handler
const handler: NotificationHandler = async (notification: Notification) => {
// notification.method is string
// notification.params is Record<string, any> | undefined
};
session.on("notification", handler);
Root Type
interface Root {
uri: string; // Must start with "file://"
name?: string; // Optional human-readable name
}
Requirements
Notifications require:
- Stateful Connection: The server must maintain sessions (stateful mode)
- Active Session: The client must have an active, initialized session
- Streaming Transport: Either SSE or Streamable HTTP transport
Notifications don’t work in stateless edge environments where sessions aren’t maintained between requests.
Next Steps