Skip to main content
Glama

list_profiles

Retrieve all saved browser profiles with metadata including profile names, cookie counts, save dates, and descriptions to manage anti-detection browser configurations.

Instructions

List all saved browser profiles with metadata. Shows profile names, cookie counts, save dates, and descriptions.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • MCP tool handler for 'list_profiles'. Registers a server.tool call that takes no input parameters, calls the listProfiles helper from profiles.ts, and returns the profiles array with metadata.
    server.tool(
      "list_profiles",
      "List all saved browser profiles with metadata. Shows profile names, cookie counts, save dates, and descriptions.",
      {},
      async () => {
        try {
          const profiles = await listProfiles(deps.config.profilesDir);
          return okResult({
            profilesDir: deps.config.profilesDir,
            count: profiles.length,
            profiles
          });
        } catch (error) {
          return toErrorResult(error);
        }
      }
    );
  • Tool registration: calls server.tool('list_profiles', ...) inside registerProfileTools to register the tool with the MCP server.
    server.tool(
      "list_profiles",
  • The registerProfileTools function that registers all profile-related tools (save_profile, load_profile, list_profiles, delete_profile) onto the MCP server.
    export function registerProfileTools(server: McpServer, deps: ToolDeps): void {
      server.tool(
        "save_profile",
        "Save browser cookies from an active tab to a named profile on disk. Enables session persistence across restarts. Use after login to save authenticated state.",
        {
          tabId: z.string().min(1).describe("Tab ID to export cookies from"),
          profileId: z.string().min(1).describe("Profile name (alphanumeric, hyphens, underscores, dots, 1-64 chars)"),
          description: z.string().optional().describe("Optional description for this profile")
        },
        async (input: unknown) => {
          try {
            const parsed = z
              .object({
                tabId: z.string().min(1),
                profileId: z.string().min(1),
                description: z.string().optional()
              })
              .parse(input);
    
            const tracked = getTrackedTab(parsed.tabId);
            incrementToolCall(parsed.tabId);
    
            // Export cookies from the active tab
            const cookies = await deps.client.exportCookies(parsed.tabId, tracked.userId);
    
            // Save to disk
            const profile = await saveProfile(deps.config.profilesDir, parsed.profileId, tracked.userId, cookies, {
              description: parsed.description,
              lastUrl: tracked.url
            });
    
            return okResult({
              profileId: profile.profileId,
              cookieCount: profile.metadata.cookieCount,
              savedAt: profile.metadata.updatedAt,
              path: deps.config.profilesDir
            });
          } catch (error) {
            return toErrorResult(error);
          }
        }
      );
    
      server.tool(
        "load_profile",
        "Load a saved profile's cookies into an active browser tab. Restores login sessions without re-authentication. Use after create_tab to restore saved state.",
        {
          profileId: z.string().min(1).describe("Profile name to load"),
          tabId: z.string().min(1).describe("Tab ID to load cookies into")
        },
        async (input: unknown) => {
          try {
            const parsed = z
              .object({
                profileId: z.string().min(1),
                tabId: z.string().min(1)
              })
              .parse(input);
    
            const tracked = getTrackedTab(parsed.tabId);
            incrementToolCall(parsed.tabId);
    
            // Read profile from disk
            const profile = await loadProfile(deps.config.profilesDir, parsed.profileId);
    
            const userMismatch = profile.userId !== tracked.userId;
    
            // Import cookies into the session
            await deps.client.importCookies(tracked.userId, profile.cookies, tracked.tabId);
    
            return okResult({
              profileId: profile.profileId,
              cookieCount: profile.metadata.cookieCount,
              lastSaved: profile.metadata.updatedAt,
              description: profile.metadata.description,
              ...(userMismatch
                ? {
                    warning: `Profile was saved for userId "${profile.userId}" but loaded into "${tracked.userId}"`
                  }
                : {})
            });
          } catch (error) {
            return toErrorResult(error);
          }
        }
      );
    
      server.tool(
        "list_profiles",
        "List all saved browser profiles with metadata. Shows profile names, cookie counts, save dates, and descriptions.",
        {},
        async () => {
          try {
            const profiles = await listProfiles(deps.config.profilesDir);
            return okResult({
              profilesDir: deps.config.profilesDir,
              count: profiles.length,
              profiles
            });
          } catch (error) {
            return toErrorResult(error);
          }
        }
      );
    
      server.tool(
        "delete_profile",
        "Delete a saved browser profile from disk. Removes the profile's cookie data permanently.",
        {
          profileId: z.string().min(1).describe("Profile name to delete")
        },
        async (input: unknown) => {
          try {
            const parsed = z
              .object({
                profileId: z.string().min(1)
              })
              .parse(input);
    
            await deleteProfile(deps.config.profilesDir, parsed.profileId);
            return okResult({ deleted: parsed.profileId });
          } catch (error) {
            return toErrorResult(error);
          }
        }
      );
    }
  • The listProfiles async function that reads the profiles directory, iterates over .json files, loads each profile via loadProfile, and returns an array of profile metadata objects with profileId.
    export async function listProfiles(dir: string): Promise<Array<{ profileId: string } & ProfileMetadata>> {
      await ensureProfilesDir(dir);
    
      let files: string[];
      try {
        files = await readdir(dir);
      } catch {
        return [];
      }
    
      const profiles: Array<{ profileId: string } & ProfileMetadata> = [];
      for (const file of files) {
        if (!file.endsWith(".json")) continue;
        const profileId = file.replace(/\.json$/, "");
        try {
          const profile = await loadProfile(dir, profileId);
          profiles.push({ profileId, ...profile.metadata });
        } catch {
          /* skip corrupt files */
        }
      }
    
      return profiles;
    }
  • ProfileMetadata interface defining the shape of metadata returned by listProfiles: createdAt, updatedAt, lastUrl, description, cookieCount.
    export interface ProfileMetadata {
      createdAt: string;
      updatedAt: string;
      lastUrl?: string | null;
      description?: string | null;
      cookieCount: number;
    }
Behavior4/5

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

No annotations provided, so description carries burden. Clearly states it lists profiles (read-only) and shows metadata, implying no side effects. No contradictions.

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

Conciseness5/5

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

Two short sentences, no filler. Every word adds value: verb, resource, metadata fields.

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

Completeness5/5

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

Completely defines purpose and output for a simple list tool with no schema or parameters. No missing information.

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

Parameters4/5

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

No parameters defined; baseline 4 as per rules for 0-param tools. Description adds no extra param info, but none needed.

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?

Description clearly states verb 'list', resource 'browser profiles', and provides specific metadata (names, cookie counts, save dates, descriptions). Differentiates from sibling tools like save_profile, delete_profile, load_profile.

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

Usage Guidelines4/5

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

Implicitly clear it's for viewing all profiles with no alternatives for listing on this server. No explicit 'when-not' or exclusions, but context is sufficient given its simplicity.

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/redf0x1/camofox-mcp'

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