Skip to main content
Glama
TylerFlar

claude-fidelity-mcp

by TylerFlar

fidelity_transfer

Transfer cash between two Fidelity accounts after validating the source account balance to prevent failed transactions.

Instructions

Transfer cash between two Fidelity accounts. Validates available balance before submitting.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
from_accountYesSource account number.
to_accountYesDestination account number.
amountYesDollar amount to transfer.

Implementation Reference

  • src/index.ts:357-396 (registration)
    Registration of the fidelity_transfer MCP tool with Zod schema validation for from_account, to_account, and amount. Imports and delegates to the transfer() function from ./accounts.js.
    server.tool(
      "fidelity_transfer",
      "Transfer cash between two Fidelity accounts. Validates available balance before submitting.",
      {
        from_account: z
          .string()
          .describe("Source account number."),
        to_account: z
          .string()
          .describe("Destination account number."),
        amount: z
          .number()
          .positive()
          .describe("Dollar amount to transfer."),
      },
      async ({ from_account, to_account, amount }) => {
        try {
          const result = await transfer(from_account, to_account, amount);
          return {
            content: [
              {
                type: "text",
                text: JSON.stringify(result, null, 2),
              },
            ],
            isError: !result.success,
          };
        } catch (e) {
          return {
            content: [
              {
                type: "text",
                text: `Transfer failed: ${e instanceof Error ? e.message : String(e)}`,
              },
            ],
            isError: true,
          };
        }
      }
    );
  • Core handler for fidelity_transfer. Navigates to Fidelity transfer page, selects from/to accounts, validates balance, fills amount, submits and confirms the transfer.
    export async function transfer(
      fromAccount: string,
      toAccount: string,
      amount: number
    ): Promise<{ success: boolean; message: string }> {
      const page = await getPage();
    
      await page.goto(TRANSFERS_URL, { waitUntil: "domcontentloaded" });
      await waitForLoadingComplete(page);
    
      // Select "From" account
      const fromDropdown = page.getByLabel("From");
      await fromDropdown.waitFor({ state: "visible", timeout: 15000 });
    
      const fromOptions = await fromDropdown.locator("option").all();
      let fromFound = false;
      for (const option of fromOptions) {
        const text = (await option.textContent()) ?? "";
        if (text.includes(fromAccount)) {
          await fromDropdown.selectOption({ label: text.trim() });
          fromFound = true;
          break;
        }
      }
      if (!fromFound) {
        return {
          success: false,
          message: `Source account ${fromAccount} not found.`,
        };
      }
    
      await page.waitForTimeout(500);
      await waitForLoadingComplete(page);
    
      // Check available balance
      try {
        const balanceCell = page.locator(
          "tr.pvd-table__row:nth-child(2) > td:nth-child(2)"
        );
        const balanceText = await balanceCell.textContent({ timeout: 5000 });
        if (balanceText) {
          const available = parseFloat(balanceText.replace(/[$,]/g, ""));
          if (amount > available) {
            return {
              success: false,
              message: `Insufficient funds. Available: $${available.toFixed(2)}, Requested: $${amount.toFixed(2)}`,
            };
          }
        }
      } catch {
        // Continue anyway
      }
    
      // Select "To" account
      const toDropdown = page.getByLabel("To", { exact: true });
      const toOptions = await toDropdown.locator("option").all();
      let toFound = false;
      for (const option of toOptions) {
        const text = (await option.textContent()) ?? "";
        if (text.includes(toAccount)) {
          await toDropdown.selectOption({ label: text.trim() });
          toFound = true;
          break;
        }
      }
      if (!toFound) {
        return {
          success: false,
          message: `Destination account ${toAccount} not found.`,
        };
      }
    
      await page.waitForTimeout(500);
    
      // Fill amount
      const amountInput = page.locator("#transfer-amount");
      await amountInput.fill(amount.toFixed(2));
    
      // Submit
      await page.getByRole("button", { name: "Continue" }).click();
      await waitForLoadingComplete(page);
    
      // Confirm
      try {
        await page.getByRole("button", { name: "Submit" }).click();
        await waitForLoadingComplete(page);
    
        const successText = page.getByText("Request submitted");
        await successText.waitFor({ state: "visible", timeout: 15000 });
    
        return {
          success: true,
          message: `Successfully transferred $${amount.toFixed(2)} from ${fromAccount} to ${toAccount}.`,
        };
      } catch (e) {
        return {
          success: false,
          message: `Transfer failed: ${e instanceof Error ? e.message : String(e)}`,
        };
      }
    }
  • Type definitions TransferRequest and TransferResult used by the transfer functionality.
    export interface TransferRequest {
      fromAccount: string;
      toAccount: string;
      amount: number;
    }
    
    export interface TransferResult {
      success: boolean;
      message: string;
    }
Behavior2/5

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

No annotations provided, so description carries full burden. It mentions 'Validates available balance before submitting' as a behavioral trait, but doesn't disclose other important aspects like whether the transfer is synchronous, what happens on failure, or auth requirements.

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?

Single sentence, no wasted words. Includes essential detail (balance validation). Highly concise and front-loaded.

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?

For a simple 3-parameter transfer with no output schema, description covers main purpose and a key behavioral aspect (validation). Could mention immediacy, fees, or confirmation, but overall reasonably complete.

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% with descriptions for all three parameters. Description adds no extra parameter-level info beyond what schema provides. Baseline 3 applies.

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 'Transfer cash between two Fidelity accounts', which is a specific verb+resource. It is distinct from siblings like 'fidelity_place_order' (for securities) and 'fidelity_get_accounts' (read-only).

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

Usage Guidelines3/5

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

Description implies use when moving cash between accounts, but lacks explicit guidance on when to use vs alternatives (e.g., batch orders or place order). No exclusions or prerequisites mentioned.

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/TylerFlar/claude-fidelity-mcp'

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