-
Notifications
You must be signed in to change notification settings - Fork 0
Subscriptions
Jeffrie Budde edited this page Nov 25, 2025
·
1 revision
Real-time resource updates are built in. Works with STDIO, SSE, and WebSocket (see Transports for connectionId handling).
- Client calls
resources/subscribewith a URI. - Server validates the resource and returns
{ id, uri, created_at, client_id }. - Server sends
notifications/resources/updatedwhen content changes. - Client can unsubscribe via
resources/unsubscribeor list viaresources/list_subscriptions.
use fastrmcp::prelude::*;
use fastrmcp_macros::{resource, tool};
use std::sync::atomic::{AtomicU64, Ordering};
static COUNTER: AtomicU64 = AtomicU64::new(0);
#[resource("counter://value")]
async fn counter() -> Result<String> {
Ok(serde_json::json!({ "value": COUNTER.load(Ordering::SeqCst) }).to_string())
}
#[tool]
async fn increment() -> Result<u64> {
Ok(COUNTER.fetch_add(1, Ordering::SeqCst) + 1)
}
#[tokio::main]
async fn main() -> Result<()> {
FastMCP::new("subs").version("1.0.0").run().await
}- Resources made with
#[resource]are subscribable automatically. - To emit notifications manually (e.g., from a background task), use
server.subscription_manager().notify_uri(uri, content).await?wherecontentisResourceContent.
- Subscribe:
{"jsonrpc":"2.0","id":1,"method":"resources/subscribe","params":{"uri":"counter://value"}}- Notification (server → client):
{"jsonrpc":"2.0","method":"notifications/resources/updated","params":{"subscription_id":"<uuid>","uri":"counter://value","content":{"uri":"counter://value","mimeType":"application/json","text":"{\"value\":2}"},"timestamp":1699565000}}- Unsubscribe:
{"jsonrpc":"2.0","id":2,"method":"resources/unsubscribe","params":{"subscriptionId":"<uuid>"}}}- List:
{"jsonrpc":"2.0","id":3,"method":"resources/list_subscriptions"}- Background tasks can push updates on intervals or external triggers. Check
SubscriptionManager::subscription_count_for_uribefore expensive work. - SSE clients must include
connectionIdwhen posting messages; WebSocket clients can be targeted viametadata.connectionIdin server-initiated requests (otherwise current connection).
- Unknown URI →
ResourceNotFound/MethodNotFound. - Missing
connectionIdon SSE POSTs when multiple clients are connected will be rejected (400 Bad Request). - Validate payload schemas in tools/resources to avoid
InvalidParamserrors that break subscription flows.
Related: Transports Guide • Troubleshooting for debugging tips • Examples for a full demo.