Skip to main content
Glama

variable_copy

Copy environment variables from one Railway environment to another for migration, configuration sharing, or duplication workflows.

Instructions

[WORKFLOW] Copy variables from one environment to another

⚡️ Best for: ✓ Environment migration ✓ Configuration sharing ✓ Environment duplication

⚠️ Not for: × Single variable updates (use variable_set) × Temporary configuration changes

→ Prerequisites: service_list

→ Alternatives: variable_set

→ Next steps: deployment_trigger, service_restart

→ Related: variable_list, service_update

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectIdYesID of the project
sourceEnvironmentIdYesID of the source environment (usually obtained from project_info)
targetEnvironmentIdYesID of the target environment (usually obtained from project_info)
serviceIdNoID of the service (optional, if omitted copies shared variables)
overwriteNoWhether to overwrite existing variables in the target environment

Implementation Reference

  • Registers the 'variable_copy' MCP tool using createTool, providing formatted description, input schema, and handler function that delegates to VariableService.copyVariables
    createTool(
      "variable_copy",
      formatToolDescription({
        type: 'WORKFLOW',
        description: "Copy variables from one environment to another",
        bestFor: [
          "Environment migration",
          "Configuration sharing",
          "Environment duplication"
        ],
        notFor: [
          "Single variable updates (use variable_set)",
          "Temporary configuration changes"
        ],
        relations: {
          prerequisites: ["service_list"],
          nextSteps: ["deployment_trigger", "service_restart"],
          alternatives: ["variable_set"],
          related: ["variable_list", "service_update"]
        }
      }),
      {
        projectId: z.string().describe("ID of the project"),
        sourceEnvironmentId: z.string().describe("ID of the source environment (usually obtained from project_info)"),
        targetEnvironmentId: z.string().describe("ID of the target environment (usually obtained from project_info)"),
        serviceId: z.string().optional().describe("ID of the service (optional, if omitted copies shared variables)"),
        overwrite: z.boolean().optional().default(false).describe("Whether to overwrite existing variables in the target environment")
      },
      async ({ projectId, sourceEnvironmentId, targetEnvironmentId, serviceId, overwrite = false }) => {
        return variableService.copyVariables(projectId, sourceEnvironmentId, targetEnvironmentId, serviceId, overwrite);
      }
    )
  • Zod input schema defining parameters for the variable_copy tool: projectId, sourceEnvironmentId, targetEnvironmentId, optional serviceId, and optional overwrite flag
    {
      projectId: z.string().describe("ID of the project"),
      sourceEnvironmentId: z.string().describe("ID of the source environment (usually obtained from project_info)"),
      targetEnvironmentId: z.string().describe("ID of the target environment (usually obtained from project_info)"),
      serviceId: z.string().optional().describe("ID of the service (optional, if omitted copies shared variables)"),
      overwrite: z.boolean().optional().default(false).describe("Whether to overwrite existing variables in the target environment")
    },
  • Handler function for the variable_copy tool, which invokes VariableService.copyVariables with the provided parameters
    async ({ projectId, sourceEnvironmentId, targetEnvironmentId, serviceId, overwrite = false }) => {
      return variableService.copyVariables(projectId, sourceEnvironmentId, targetEnvironmentId, serviceId, overwrite);
    }
  • Core helper method implementing the variable copying logic: retrieves variables from source and target environments, filters based on overwrite flag, performs bulk upsert, and returns success/error responses
    async copyVariables(projectId: string, sourceEnvironmentId: string, targetEnvironmentId: string, serviceId?: string, overwrite: boolean = false) {
      try {
        // Get variables from source environment
        const sourceVars = await this.client.variables.getVariables(projectId, sourceEnvironmentId, serviceId);
    
        if (Object.keys(sourceVars).length === 0) {
          return createSuccessResponse({
            text: "No variables found in source environment to copy.",
            data: { copied: 0 }
          });
        }
    
        // Get variables from target environment
        const targetVars = await this.client.variables.getVariables(projectId, targetEnvironmentId, serviceId);
    
        // If not overwriting, filter out variables that already exist in target
        const varsToSet = overwrite
          ? sourceVars
          : Object.fromEntries(
              Object.entries(sourceVars).filter(([key]) => !(key in targetVars))
            );
    
        if (Object.keys(varsToSet).length === 0) {
          return createSuccessResponse({
            text: "All variables already exist in target environment.",
            data: { copied: 0 }
          });
        }
    
        // Bulk update the variables
        await this.bulkUpsertVariables(projectId, targetEnvironmentId, varsToSet, serviceId);
    
        const variableType = serviceId ? "service variables" : "shared environment variables";
        return createSuccessResponse({
          text: `Successfully copied ${Object.keys(varsToSet).length} ${variableType} to target environment`,
          data: { copied: Object.keys(varsToSet).length }
        });
      } catch (error) {
        return createErrorResponse(`Error copying variables: ${formatError(error)}`);
      }
    }
Behavior4/5

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

With no annotations provided, the description carries full burden and does well by explaining it's for copying variables between environments, mentioning optional service-specific copying, and implying it's a batch operation. However, it doesn't explicitly state whether this is a read-only or mutating operation, or discuss potential side effects like overwriting behavior (though the schema covers the overwrite parameter).

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?

The description is efficiently structured with clear sections (purpose, best for, not for, prerequisites, alternatives, next steps, related). Every sentence earns its place, and the information is front-loaded with the core purpose stated first.

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 tool with 5 parameters, no annotations, and no output schema, the description provides good context about when to use it, alternatives, prerequisites, and related operations. It could be more complete by explicitly stating whether this is a mutating operation and what the expected output looks like, but it covers most essential usage aspects well.

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 5 parameters thoroughly. The description adds minimal parameter-specific information beyond what's in the schema (e.g., mentioning 'shared variables' for the optional serviceId). This meets the baseline expectation when schema coverage is complete.

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 with specific verb ('Copy') and resource ('variables from one environment to another'), and distinguishes it from sibling tools like variable_set for single updates. The '[WORKFLOW]' label and context about environment migration/duplication further clarify its scope.

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

Usage Guidelines5/5

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

The description provides explicit guidance with 'Best for' and 'Not for' sections, naming specific alternatives (variable_set) and prerequisites (service_list). It also lists related tools and next steps, offering comprehensive usage context.

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/epitaphe360/railway-mcp'

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