interceptor_browser_get_storage_value
Get a specific browser storage value (localStorage or sessionStorage) by item ID from a launched target.
Instructions
Get one localStorage/sessionStorage value by item_id.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| target_id | Yes | Target ID from interceptor_browser_launch or interceptor_camoufox_launch | |
| storage_type | Yes | Storage type | |
| item_id | Yes | item_id from interceptor_browser_list_storage_keys | |
| origin | No | Optional origin override (must match current page origin) | |
| value_max_chars | No | Max characters for returned value (default: 20000) |
Implementation Reference
- src/tools/devtools.ts:453-525 (registration)Registers 'interceptor_browser_get_storage_value' as an MCP tool on the McpServer via server.tool() with zod schema for target_id, storage_type, item_id, origin, and value_max_chars.
server.tool( "interceptor_browser_get_storage_value", "Get one localStorage/sessionStorage value by item_id.", { target_id: z.string().describe("Target ID from interceptor_browser_launch or interceptor_camoufox_launch"), storage_type: z.enum(["local", "session"]).describe("Storage type"), item_id: z.string().describe("item_id from interceptor_browser_list_storage_keys"), origin: z.string().optional().describe("Optional origin override (must match current page origin)"), value_max_chars: z.number().optional().default(HARD_VALUE_CAP_CHARS) .describe(`Max characters for returned value (default: ${HARD_VALUE_CAP_CHARS})`), }, async ({ target_id, storage_type, item_id, origin, value_max_chars }) => { try { const parts = item_id.split("."); if (parts.length !== 4 || parts[0] !== "st") { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `Invalid item_id '${item_id}'` }) }] }; } const itemType = parts[1]; const itemOrigin = fromBase64UrlUtf8(parts[2]); const itemKey = fromBase64UrlUtf8(parts[3]); if (itemType !== storage_type) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `item_id storage_type '${itemType}' does not match requested '${storage_type}'` }) }] }; } const page = await getPageForTarget(target_id); const pageUrl = page.url(); const currentOrigin = getOriginFromUrl(pageUrl); if (!currentOrigin) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `No http(s) origin available for current page URL: '${pageUrl}'` }) }] }; } if (origin && origin !== currentOrigin) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `origin '${origin}' does not match current origin '${currentOrigin}'. Navigate first.` }) }] }; } if (itemOrigin !== currentOrigin) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `item_id origin '${itemOrigin}' does not match current origin '${currentOrigin}'. Navigate first.` }) }] }; } const maxChars = Math.max(0, Math.min(HARD_VALUE_CAP_CHARS, Math.trunc(value_max_chars ?? HARD_VALUE_CAP_CHARS))); const result = await page.evaluate( ({ stType, key, maxChars: mc }) => { const storage = stType === "local" ? localStorage : sessionStorage; const raw = storage.getItem(key); const v = typeof raw === "string" ? raw : ""; const valueLength = v.length; const truncated = mc > 0 && valueLength > mc; const value = mc > 0 ? (truncated ? v.slice(0, mc) : v) : v; return { key, value, valueLength, truncated }; }, { stType: storage_type, key: itemKey, maxChars }, ); return { content: [{ type: "text", text: truncateResult({ status: "success", target_id, origin: currentOrigin, storage_type, item_id, key: result.key, value: result.value, value_length: result.valueLength, value_truncated: result.truncated, value_max_chars: maxChars, }), }], }; } catch (e) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: errorToString(e) }) }] }; } }, ); - src/tools/devtools.ts:464-524 (handler)The async handler function that retrieves a storage value. It parses the item_id (format st.{type}.{base64origin}.{base64key}), validates it matches the storage_type, resolves the Playwright page via getPageForTarget, checks origin consistency, and uses page.evaluate() to read localStorage/sessionStorage. Returns the key, value, value_length, and whether it was truncated.
async ({ target_id, storage_type, item_id, origin, value_max_chars }) => { try { const parts = item_id.split("."); if (parts.length !== 4 || parts[0] !== "st") { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `Invalid item_id '${item_id}'` }) }] }; } const itemType = parts[1]; const itemOrigin = fromBase64UrlUtf8(parts[2]); const itemKey = fromBase64UrlUtf8(parts[3]); if (itemType !== storage_type) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `item_id storage_type '${itemType}' does not match requested '${storage_type}'` }) }] }; } const page = await getPageForTarget(target_id); const pageUrl = page.url(); const currentOrigin = getOriginFromUrl(pageUrl); if (!currentOrigin) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `No http(s) origin available for current page URL: '${pageUrl}'` }) }] }; } if (origin && origin !== currentOrigin) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `origin '${origin}' does not match current origin '${currentOrigin}'. Navigate first.` }) }] }; } if (itemOrigin !== currentOrigin) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `item_id origin '${itemOrigin}' does not match current origin '${currentOrigin}'. Navigate first.` }) }] }; } const maxChars = Math.max(0, Math.min(HARD_VALUE_CAP_CHARS, Math.trunc(value_max_chars ?? HARD_VALUE_CAP_CHARS))); const result = await page.evaluate( ({ stType, key, maxChars: mc }) => { const storage = stType === "local" ? localStorage : sessionStorage; const raw = storage.getItem(key); const v = typeof raw === "string" ? raw : ""; const valueLength = v.length; const truncated = mc > 0 && valueLength > mc; const value = mc > 0 ? (truncated ? v.slice(0, mc) : v) : v; return { key, value, valueLength, truncated }; }, { stType: storage_type, key: itemKey, maxChars }, ); return { content: [{ type: "text", text: truncateResult({ status: "success", target_id, origin: currentOrigin, storage_type, item_id, key: result.key, value: result.value, value_length: result.valueLength, value_truncated: result.truncated, value_max_chars: maxChars, }), }], }; } catch (e) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: errorToString(e) }) }] }; } }, - src/tools/devtools.ts:456-463 (schema)Zod schema definition for the tool's input parameters: target_id (string), storage_type (enum local/session), item_id (string), origin (optional string), value_max_chars (optional number, default 20000).
{ target_id: z.string().describe("Target ID from interceptor_browser_launch or interceptor_camoufox_launch"), storage_type: z.enum(["local", "session"]).describe("Storage type"), item_id: z.string().describe("item_id from interceptor_browser_list_storage_keys"), origin: z.string().optional().describe("Optional origin override (must match current page origin)"), value_max_chars: z.number().optional().default(HARD_VALUE_CAP_CHARS) .describe(`Max characters for returned value (default: ${HARD_VALUE_CAP_CHARS})`), }, - src/tools/devtools.ts:70-74 (helper)fromBase64UrlUtf8 helper function used to decode the base64url-encoded origin and key from the item_id parts.
function fromBase64UrlUtf8(s: string): string { let b64 = s.replaceAll("-", "+").replaceAll("_", "/"); while (b64.length % 4 !== 0) b64 += "="; return Buffer.from(b64, "base64").toString("utf8"); } - src/tools/devtools.ts:111-111 (registration)Export function registerDevToolsTools that registers all devtools tools including interceptor_browser_get_storage_value.
export function registerDevToolsTools(server: McpServer): void {