Skip to main content
Glama

foundry_contract

Test, deploy, and interact with Foundry smart contracts for development and gas analysis. Automatically uses MCP operator configuration for private keys and RPC URLs.

Instructions

Manage Foundry contract testing, deployment, and interaction.

OPERATIONS:

  • test: Run Forge tests with fuzzing and gas reports

  • create: Deploy single contract via forge create

  • script: Execute Solidity deployment script

  • call: Call read-only function via cast (FREE)

  • send: Send state-changing transaction via cast

  • anvil_start: Start local Anvil node (can fork from network)

  • anvil_stop: Stop Anvil local node

AUTO-RESOLUTION: privateKey and rpcUrl are OPTIONAL - if not provided, automatically uses MCP operator account configuration.

USE FOR: Testing, deployment, gas analysis, and local development.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
operationYesContract operation to perform
directoryNoAbsolute path to Foundry project directory
matchTestNoTest name filter (for test)
matchContractNoContract name filter (for test)
gasReportNoGenerate gas report (for test)
forkUrlNoRPC URL to fork from (for test/anvil_start)
verbosityNoOutput verbosity 1-5 (for test)
contractNameNoContract name (for create)
constructorArgsNoConstructor args (for create)
rpcUrlNoJSON-RPC URL (optional - auto-resolves from MCP network config)
privateKeyNoPrivate key for signing (optional - auto-uses MCP operator key)
scriptPathNoScript path (for script)
broadcastNoBroadcast transactions (for script)
addressNoContract address (for call/send)
signatureNoFunction signature (for call/send)
callArgsNoFunction arguments (for call/send)
valueNoETH/HBAR value (for send)
portNoPort number (for anvil_start)
forkBlockNoBlock to fork from (for anvil_start)

Implementation Reference

  • Primary handler function that executes the 'foundry_contract' tool. Routes to specific Foundry operations (test, create, script, call, send, anvil management) using imported foundryTools.
    export async function foundryContractManage(args: {
      operation: 'test' | 'create' | 'script' | 'call' | 'send' | 'anvil_start' | 'anvil_stop';
      // Common
      directory?: string;
      // Test-specific
      matchTest?: string;
      matchContract?: string;
      gasReport?: boolean;
      forkUrl?: string;
      verbosity?: number;
      // Create-specific
      contractName?: string;
      constructorArgs?: any[];
      rpcUrl?: string;
      privateKey?: string;
      // Script-specific
      scriptPath?: string;
      broadcast?: boolean;
      // Call/Send-specific
      address?: string;
      signature?: string;
      callArgs?: any[];
      value?: string;
      // Anvil-specific
      port?: number;
      forkBlock?: number;
    }): Promise<ToolResult> {
      try {
        logger.info('Foundry contract operation', { operation: args.operation });
    
        switch (args.operation) {
          case 'test':
            return await foundryTools.foundryTest({
              matchTest: args.matchTest,
              matchContract: args.matchContract,
              gasReport: args.gasReport,
              forkUrl: args.forkUrl,
              verbosity: args.verbosity,
              directory: args.directory,
            });
    
          case 'create':
            return await foundryTools.foundryCreate({
              contractPath: args.contractName!, // Using contractName as path
              constructorArgs: args.constructorArgs?.map(String),
              rpcUrl: args.rpcUrl!,
              privateKey: args.privateKey!,
            });
    
          case 'script':
            return await foundryTools.foundryScript({
              scriptPath: args.scriptPath!,
              rpcUrl: args.rpcUrl,
              broadcast: args.broadcast,
              privateKey: args.privateKey,
            });
    
          case 'call':
            return await foundryTools.foundryCall({
              address: args.address!,
              signature: args.signature!,
              args: args.callArgs,
              rpcUrl: args.rpcUrl,
            });
    
          case 'send':
            return await foundryTools.foundrySend({
              address: args.address!,
              signature: args.signature!,
              args: args.callArgs,
              rpcUrl: args.rpcUrl!,
              privateKey: args.privateKey!,
              value: args.value,
            });
    
          case 'anvil_start':
            return await foundryTools.foundryAnvilStart({
              port: args.port,
              forkUrl: args.forkUrl,
              chainId: args.forkBlock, // Use forkBlock as chainId if needed
            });
    
          case 'anvil_stop':
            return await foundryTools.foundryAnvilStop();
    
          default:
            throw new Error(`Unknown operation: ${args.operation}`);
        }
      } catch (error) {
        logger.error('Foundry contract operation failed', { operation: args.operation, error });
        return {
          success: false,
          error: error instanceof Error ? error.message : 'Unknown error',
        };
      }
    }
  • Input schema and description for the 'foundry_contract' tool, defining all supported operations and parameters.
      {
        name: 'foundry_contract',
        description: `Manage Foundry contract testing, deployment, and interaction.
    
    OPERATIONS:
    - test: Run Forge tests with fuzzing and gas reports
    - create: Deploy single contract via forge create
    - script: Execute Solidity deployment script
    - call: Call read-only function via cast (FREE)
    - send: Send state-changing transaction via cast
    - anvil_start: Start local Anvil node (can fork from network)
    - anvil_stop: Stop Anvil local node
    
    AUTO-RESOLUTION: privateKey and rpcUrl are OPTIONAL - if not provided, automatically uses MCP operator account configuration.
    
    USE FOR: Testing, deployment, gas analysis, and local development.`,
        inputSchema: {
          type: 'object' as const,
          properties: {
            operation: {
              type: 'string',
              enum: ['test', 'create', 'script', 'call', 'send', 'anvil_start', 'anvil_stop'],
              description: 'Contract operation to perform',
            },
            directory: { type: 'string', description: 'Absolute path to Foundry project directory' },
            matchTest: { type: 'string', description: 'Test name filter (for test)' },
            matchContract: { type: 'string', description: 'Contract name filter (for test)' },
            gasReport: { type: 'boolean', description: 'Generate gas report (for test)' },
            forkUrl: { type: 'string', description: 'RPC URL to fork from (for test/anvil_start)' },
            verbosity: { type: 'number', description: 'Output verbosity 1-5 (for test)' },
            contractName: { type: 'string', description: 'Contract name (for create)' },
            constructorArgs: { type: 'array', items: {}, description: 'Constructor args (for create)' },
            rpcUrl: { type: 'string', description: 'JSON-RPC URL (optional - auto-resolves from MCP network config)' },
            privateKey: { type: 'string', description: 'Private key for signing (optional - auto-uses MCP operator key)' },
            scriptPath: { type: 'string', description: 'Script path (for script)' },
            broadcast: { type: 'boolean', description: 'Broadcast transactions (for script)' },
            address: { type: 'string', description: 'Contract address (for call/send)' },
            signature: { type: 'string', description: 'Function signature (for call/send)' },
            callArgs: { type: 'array', items: {}, description: 'Function arguments (for call/send)' },
            value: { type: 'string', description: 'ETH/HBAR value (for send)' },
            port: { type: 'number', description: 'Port number (for anvil_start)' },
            forkBlock: { type: 'number', description: 'Block to fork from (for anvil_start)' },
          },
          required: ['operation'],
        },
      },
    ];
  • src/index.ts:656-658 (registration)
    Tool registration in the main MCP server request handler. Dispatches calls to the foundryContractManage handler function.
    case 'foundry_contract':
      result = await foundryContractManage(args as any);
      break;
Behavior4/5

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

With no annotations provided, the description carries the full burden and adds significant behavioral context. It discloses that 'privateKey and rpcUrl are OPTIONAL - if not provided, automatically uses MCP operator account configuration', which is crucial for understanding authentication and configuration. It also hints at cost implications ('call: Call read-only function via cast (FREE)') and operational scope (e.g., local development with Anvil).

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 well-structured with clear sections (OPERATIONS, AUTO-RESOLUTION, USE FOR) and front-loaded key information. It's appropriately sized for a complex tool with many operations, though some sentences could be more concise (e.g., the OPERATIONS list is verbose but necessary).

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?

Given the tool's high complexity (19 parameters, 7 operations), no annotations, and no output schema, the description does a good job of providing context. It covers purpose, usage, key behavioral traits (auto-resolution, free operations), and operational scope. However, it lacks details on error handling, response formats, or prerequisites (e.g., Foundry installation), leaving some gaps.

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 description coverage is 100%, so the schema already documents all 19 parameters thoroughly. The description adds minimal parameter semantics beyond the schema—it mentions optional auto-resolution for 'privateKey' and 'rpcUrl' and loosely ties some parameters to operations (e.g., 'matchTest' for 'test'), but doesn't provide additional syntax or format details. Baseline 3 is appropriate given high schema coverage.

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's purpose as 'Manage Foundry contract testing, deployment, and interaction' with a specific verb ('manage') and resource ('Foundry contract'), and it distinguishes from siblings like 'deploy_contract' and 'hardhat_contract' by specifying the Foundry framework context. The OPERATIONS list further clarifies the scope.

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?

The description provides explicit context for when to use this tool ('USE FOR: Testing, deployment, gas analysis, and local development'), which helps differentiate it from general-purpose siblings like 'rpc_call' or 'deploy_contract'. However, it lacks explicit exclusions or direct alternatives (e.g., when to use 'hardhat_contract' instead).

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/justmert/hashpilot'

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