Skip to main content
Glama

export_wallet

Export the agent's Solana wallet secret key to import into Phantom or Solflare. Requires owner key. Rate-limited to 5 exports per hour.

Instructions

Export the agent's Solana wallet secret key. Import into Phantom or Solflare to control the wallet directly. Requires owner key (auto-loaded from saved credentials). Rate-limited to 5 exports per hour.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
agent_idNoThe agent's profile ID. Auto-filled from saved credentials if omitted.
owner_keyNoThe owner key (cfm_own_xxx). Auto-filled from saved credentials if omitted.

Implementation Reference

  • The export_wallet tool handler. It sends a POST to the 'export-agent-wallet' API endpoint with agent_id, owner_id, and/or api_key. Returns the agent's Solana wallet secret key in base58 format formatted in a markdown response.
    // ── Tool: export_wallet ──
    
    server.tool(
      "export_wallet",
      "Export the agent's Solana wallet secret key in base58 format. Import into Phantom or Solflare to control the wallet directly. Rate-limited to 5 exports per hour.",
      {
        agent_id: z.string().optional().describe("The agent's profile ID. Auto-filled from saved credentials if omitted."),
        owner_id: z.string().optional().describe("The owner's profile ID. Auto-filled from saved credentials if omitted."),
        api_key: z.string().optional().describe("The agent's API key. Alternative auth method if owner_id is not available."),
      },
      async ({ agent_id, owner_id, api_key }) => {
        const saved = loadSavedAgents();
        const resolvedAgent = agent_id || (saved.length > 0 ? saved[saved.length - 1].agentId : null);
        const resolvedOwner = owner_id || getDefaultOwnerId();
        const resolvedApiKey = api_key || getDefaultApiKey();
    
        if (!resolvedAgent) {
          return { content: [{ type: "text", text: "No agent found. Create one first with `create_agent`, or pass agent_id." }], isError: true };
        }
    
        if (!resolvedOwner && !resolvedApiKey) {
          return { content: [{ type: "text", text: "Auth required: provide owner_id or api_key." }], isError: true };
        }
    
        const body: Record<string, string> = { agentId: resolvedAgent };
        if (resolvedOwner) body.ownerProfileId = resolvedOwner;
        if (resolvedApiKey) body.agentApiKey = resolvedApiKey;
    
        const result = (await apiPost("export-agent-wallet", body)) as any;
    
        if (!result.success) {
          return {
            content: [{ type: "text", text: `Export failed: ${result.error || "Unknown error"}` }],
            isError: true,
          };
        }
    
        return {
          content: [
            {
              type: "text",
              text: [
                `# Wallet Export: ${result.agent?.name || resolvedAgent}`,
                "",
                `**Wallet Address:** ${result.agent?.walletAddress || "unknown"}`,
                `**Network:** ${result.wallet?.network || "solana-devnet"}`,
                `**Format:** ${result.wallet?.format || "base58"}`,
                "",
                `**Secret Key:**`,
                `\`${result.wallet?.secretKey}\``,
                "",
                `Import this into Phantom or Solflare to control the wallet.`,
                `⚠️ Anyone with this key can move funds. Keep it safe.`,
              ].join("\n"),
            },
          ],
        };
      }
    );
  • Input schema for export_wallet: agent_id (optional string), owner_id (optional string), api_key (optional string) - all are optional with auto-fill from saved credentials.
    {
      agent_id: z.string().optional().describe("The agent's profile ID. Auto-filled from saved credentials if omitted."),
      owner_id: z.string().optional().describe("The owner's profile ID. Auto-filled from saved credentials if omitted."),
      api_key: z.string().optional().describe("The agent's API key. Alternative auth method if owner_id is not available."),
    },
  • The tool is registered via server.tool() call at line 1334-1336. This excerpt from a comment block documents the tool name 'export_wallet' and its parameters.
    ### export_wallet
    Export agent's Solana wallet secret key in base58 format. Import into Phantom/Solflare. Rate-limited: 5 per hour.
    | Param | Type | Required | Description |
    |-------|------|----------|-------------|
    | agent_id | string | No | Auto-filled from saved credentials |
    | owner_id | string | No | Auto-filled from saved credentials |
    | api_key | string | No | Alternative auth (agent API key) |
  • Actual MCP tool registration via server.tool('export_wallet', ...) - registers the tool with description about exporting Solana wallet secret key in base58 format.
    server.tool(
      "export_wallet",
      "Export the agent's Solana wallet secret key in base58 format. Import into Phantom or Solflare to control the wallet directly. Rate-limited to 5 exports per hour.",
  • The complete handler function for export_wallet. Resolves credentials from saved agents or provided params, calls the 'export-agent-wallet' API endpoint (apiPost), and returns the secret key in a formatted markdown response with wallet address, network details, and security warning.
    async ({ agent_id, owner_id, api_key }) => {
      const saved = loadSavedAgents();
      const resolvedAgent = agent_id || (saved.length > 0 ? saved[saved.length - 1].agentId : null);
      const resolvedOwner = owner_id || getDefaultOwnerId();
      const resolvedApiKey = api_key || getDefaultApiKey();
    
      if (!resolvedAgent) {
        return { content: [{ type: "text", text: "No agent found. Create one first with `create_agent`, or pass agent_id." }], isError: true };
      }
    
      if (!resolvedOwner && !resolvedApiKey) {
        return { content: [{ type: "text", text: "Auth required: provide owner_id or api_key." }], isError: true };
      }
    
      const body: Record<string, string> = { agentId: resolvedAgent };
      if (resolvedOwner) body.ownerProfileId = resolvedOwner;
      if (resolvedApiKey) body.agentApiKey = resolvedApiKey;
    
      const result = (await apiPost("export-agent-wallet", body)) as any;
    
      if (!result.success) {
        return {
          content: [{ type: "text", text: `Export failed: ${result.error || "Unknown error"}` }],
          isError: true,
        };
      }
    
      return {
        content: [
          {
            type: "text",
            text: [
              `# Wallet Export: ${result.agent?.name || resolvedAgent}`,
              "",
              `**Wallet Address:** ${result.agent?.walletAddress || "unknown"}`,
              `**Network:** ${result.wallet?.network || "solana-devnet"}`,
              `**Format:** ${result.wallet?.format || "base58"}`,
              "",
              `**Secret Key:**`,
              `\`${result.wallet?.secretKey}\``,
              "",
              `Import this into Phantom or Solflare to control the wallet.`,
              `⚠️ Anyone with this key can move funds. Keep it safe.`,
            ].join("\n"),
          },
        ],
      };
    }
Behavior4/5

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

Discloses rate limit (5 per hour) and that owner key is required (auto-loaded). No annotations exist, so description carries the burden. Could mention security implications of exporting a secret key.

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?

Three sentences, no fluff. Front-loaded with action, then purpose, then constraints. Each sentence earns its place.

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

Completeness4/5

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

Covers purpose, required auth, rate limit. Lacks explicit mention of output format (the secret key string), but 'export... secret key' implies the return value. Good for a simple tool.

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 covers 100% of parameters with descriptions, so baseline is 3. Description reinforces auto-fill behavior but adds no new meaning beyond the schema.

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?

Clearly states the tool exports the agent's Solana wallet secret key, with specific destinations (Phantom, Solflare). Distinguishes from sibling tools like create_agent or enter_position, which serve different purposes.

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?

Explicitly states when to use: to export secret key for importing into other wallets. No explicit when-not-to-use, but the sensitive nature and rate limit imply appropriate contexts.

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/abcxz/conviction-fm'

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