diff --git a/docs/patterns.md b/docs/patterns.md index 3a6302c9..126e3e33 100644 --- a/docs/patterns.md +++ b/docs/patterns.md @@ -620,6 +620,29 @@ app.ontoolresult = (result) => { // e.g., saveState({ currentPage: 5 }); ``` +**Alternative: using the tool call ID from host context** + +If you don't need a server-generated UUID, use {@link types!McpUiHostContext `hostContext.toolInfo.id`} — the JSON-RPC tool call ID — as the storage key directly. No server-side changes needed: + + +```ts source="./patterns.tsx#persistDataToolCallId" +// Use the tool call ID as a stable localStorage key — no server-side UUID needed +const toolCallId = String(app.getHostContext()?.toolInfo?.id ?? "default"); + +function saveState(state: T): void { + if (!toolCallId) return; + try { localStorage.setItem(toolCallId, JSON.stringify(state)); } catch {} +} + +function loadState(): T | null { + if (!toolCallId) return null; + try { + const s = localStorage.getItem(toolCallId); + return s ? (JSON.parse(s) as T) : null; + } catch { return null; } +} +``` + For state that represents user effort (e.g., saved bookmarks, annotations, custom configurations), consider persisting it server-side using [app-only tools](#tools-that-are-private-to-apps) instead. Pass the `viewUUID` to the app-only tool to scope the saved data to that view instance. > [!NOTE] diff --git a/docs/patterns.tsx b/docs/patterns.tsx index 6b876926..b42875db 100644 --- a/docs/patterns.tsx +++ b/docs/patterns.tsx @@ -425,6 +425,29 @@ function persistViewState(app: App) { //#endregion persistData } +/** + * Example: Persisting view state using tool call ID (no server-side UUID needed) + */ +function persistViewStateWithToolCallId(app: App) { + //#region persistDataToolCallId + // Use the tool call ID as a stable localStorage key — no server-side UUID needed + const toolCallId = String(app.getHostContext()?.toolInfo?.id ?? "default"); + + function saveState(state: T): void { + if (!toolCallId) return; + try { localStorage.setItem(toolCallId, JSON.stringify(state)); } catch {} + } + + function loadState(): T | null { + if (!toolCallId) return null; + try { + const s = localStorage.getItem(toolCallId); + return s ? (JSON.parse(s) as T) : null; + } catch { return null; } + } + //#endregion persistDataToolCallId +} + /** * Example: Pausing computation-heavy views when out of view */