Skip to main content
Glama

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

TableJSON Schema
NameRequiredDescriptionDefault
target_idYesTarget ID from interceptor_browser_launch or interceptor_camoufox_launch
storage_typeYesStorage type
item_idYesitem_id from interceptor_browser_list_storage_keys
originNoOptional origin override (must match current page origin)
value_max_charsNoMax characters for returned value (default: 20000)

Implementation Reference

  • 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) }) }] };
        }
      },
    );
  • 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) }) }] };
      }
    },
  • 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})`),
    },
  • 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");
    }
  • Export function registerDevToolsTools that registers all devtools tools including interceptor_browser_get_storage_value.
    export function registerDevToolsTools(server: McpServer): void {
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description should disclose behavioral traits like non-destructiveness, side effects, or error handling. It only states the action, omitting whether the operation is read-only, what happens if the key is missing, or any rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with a single sentence, front-loading the verb and resource. However, it could be more structured by adding prerequisite context without becoming overly long.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 parameters, no output schema, and no annotations, the description is incomplete. It fails to explain optional fields like origin and value_max_chars, or how the tool integrates with sibling tools like browser navigation or snapshot.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds minimal meaning beyond the schema, as the key detail 'by item_id' is already present. No extra semantic value is provided.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool gets a value from localStorage or sessionStorage by item_id, using specific verbs and resources. It distinguishes from siblings that list keys or get cookies.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use or when-not-to-use guidance is provided. It does not mention prerequisites like obtaining target_id from launch or item_id from list_storage_keys, nor does it specify alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yfe404/proxy-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server