Skip to main content
Glama
debugg-ai

Debugg AI MCP

Official
by debugg-ai

Update Environment

update_environment

Update an environment's name, URL, or description by providing its UUID. Only specified fields change; others remain untouched. Returns the updated environment object or an error if the UUID does not exist.

Instructions

Patch an environment by UUID. Only specified fields (name, url, description) change — other fields are left intact. Returns {updated: true, environment: {...}} with the updated resource. Defaults to the project resolved from the current git repo; pass projectUuid to target a different project. Returns isError:true with NotFound when the uuid doesn't exist.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
uuidYesUUID of the environment to update. Required.
nameNoOptional: new name.
urlNoOptional: new base URL.
descriptionNoOptional: new description.
projectUuidNoOptional: UUID of the target project. Defaults to git-auto-detect.

Implementation Reference

  • Main handler function that executes the update_environment tool logic. It patches environment fields (name/url/description), and handles credential sub-actions: remove, update, add. Resolves projectUuid via git repo detection if not provided. Returns structured response with updated environment and credential changes.
    export async function updateEnvironmentHandler(
      input: UpdateEnvironmentInput,
      _context: ToolContext,
    ): Promise<ToolResponse> {
      const start = Date.now();
      logger.toolStart('update_environment', {
        uuid: input.uuid,
        hasEnvPatch: !!(input.name || input.url || input.description),
        addCount: input.addCredentials?.length ?? 0,
        updateCount: input.updateCredentials?.length ?? 0,
        removeCount: input.removeCredentialIds?.length ?? 0,
        projectUuid: input.projectUuid,
      });
    
      try {
        const client = new DebuggAIServerClient(config.api.key);
        await client.init();
    
        let projectUuid = input.projectUuid;
        if (!projectUuid) {
          const repoName = detectRepoName();
          if (!repoName) return notFound(input.uuid, 'no git repo detected and no projectUuid provided');
          const project = await client.findProjectByRepoName(repoName);
          if (!project) return notFound(input.uuid, `no project found for repo "${repoName}"`);
          projectUuid = project.uuid;
        }
    
        // ── Env field patch (only if any env field is present) ──────────────────
        const hasEnvPatch = input.name !== undefined || input.url !== undefined || input.description !== undefined;
        let environment: any = null;
        if (hasEnvPatch) {
          try {
            environment = await client.updateEnvironment(projectUuid, input.uuid, {
              name: input.name, url: input.url, description: input.description,
            });
          } catch (err: any) {
            if (err?.statusCode === 404 || err?.response?.status === 404) {
              return notFound(input.uuid, `backend returned 404 for project ${projectUuid}`);
            }
            throw err;
          }
        } else {
          // Echo the uuid so the response shape stays consistent. Include projectUuid
          // for downstream tooling. Only populate `environment` if we patched.
          environment = { uuid: input.uuid };
        }
    
        // ── Cred sub-actions (remove → update → add) ────────────────────────────
        const warnings: Array<{ op: 'add' | 'update' | 'remove'; label?: string; uuid?: string; error: string }> = [];
        const addedCredentials: SafeCredential[] = [];
        const updatedCredentials: SafeCredential[] = [];
        const removedCredentialIds: string[] = [];
    
        if (input.removeCredentialIds) {
          for (const credUuid of input.removeCredentialIds) {
            try {
              await client.deleteCredential(projectUuid, input.uuid, credUuid);
              removedCredentialIds.push(credUuid);
            } catch (err: any) {
              warnings.push({ op: 'remove', uuid: credUuid, error: err?.message ?? String(err) });
            }
          }
        }
    
        if (input.updateCredentials) {
          for (const patch of input.updateCredentials) {
            try {
              const updated = await client.updateCredential(
                projectUuid, input.uuid, patch.uuid,
                {
                  label: patch.label,
                  username: patch.username,
                  password: patch.password,
                  role: patch.role,
                },
              );
              updatedCredentials.push(stripPassword(updated));
            } catch (err: any) {
              warnings.push({ op: 'update', uuid: patch.uuid, error: err?.message ?? String(err) });
            }
          }
        }
    
        if (input.addCredentials) {
          for (const seed of input.addCredentials) {
            try {
              const cred = await client.createCredential(projectUuid, input.uuid, {
                label: seed.label,
                username: seed.username,
                password: seed.password,
                role: seed.role,
              });
              addedCredentials.push(stripPassword(cred));
            } catch (err: any) {
              warnings.push({ op: 'add', label: seed.label, error: err?.message ?? String(err) });
            }
          }
        }
    
        // ── Build response ──────────────────────────────────────────────────────
        const payload: Record<string, any> = {
          updated: hasEnvPatch,
          environment,
        };
        if (addedCredentials.length > 0) payload.addedCredentials = addedCredentials;
        if (updatedCredentials.length > 0) payload.updatedCredentials = updatedCredentials;
        if (removedCredentialIds.length > 0) payload.removedCredentialIds = removedCredentialIds;
        if (warnings.length > 0) payload.credentialWarnings = warnings;
    
        logger.toolComplete('update_environment', Date.now() - start);
        return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
      } catch (error) {
        logger.toolError('update_environment', error as Error, Date.now() - start);
        throw handleExternalServiceError(error, 'DebuggAI', 'update_environment');
      }
    }
  • Zod schema and inferred TypeScript type for UpdateEnvironmentInput. Defines input shape: uuid (required), optional name/url/description/projectUuid, plus credential mutation arrays (addCredentials, updateCredentials, removeCredentialIds).
    export const UpdateEnvironmentInputSchema = z.object({
      uuid: z.string().uuid(),
      name: z.string().min(1).optional(),
      url: z.string().url().optional(),
      description: z.string().optional(),
      projectUuid: z.string().uuid().optional(),
      addCredentials: z.array(CredentialSeedSchema).optional(),
      updateCredentials: z.array(CredentialUpdateSchema).optional(),
      removeCredentialIds: z.array(z.string().uuid()).optional(),
    }).strict();
    export type UpdateEnvironmentInput = z.infer<typeof UpdateEnvironmentInputSchema>;
  • tools/index.ts:24-59 (registration)
    Tool registration: buildUpdateEnvironmentTool() and buildValidatedUpdateEnvironmentTool() are called in initTools() to register update_environment in the tool registry.
    export function initTools(ctx: ProjectContext | null): void {
      const tools: Tool[] = [
        buildTestPageChangesTool(ctx),
        buildTriggerCrawlTool(ctx),
        buildProbePageTool(),
        buildSearchProjectsTool(),
        buildSearchEnvironmentsTool(),
        buildCreateEnvironmentTool(),
        buildUpdateEnvironmentTool(),
        buildDeleteEnvironmentTool(),
        buildUpdateProjectTool(),
        buildDeleteProjectTool(),
        buildSearchExecutionsTool(),
        buildCreateProjectTool(),
      ];
      const validated: ValidatedTool[] = [
        buildValidatedTestPageChangesTool(ctx),
        buildValidatedTriggerCrawlTool(ctx),
        buildValidatedProbePageTool(),
        buildValidatedSearchProjectsTool(),
        buildValidatedSearchEnvironmentsTool(),
        buildValidatedCreateEnvironmentTool(),
        buildValidatedUpdateEnvironmentTool(),
        buildValidatedDeleteEnvironmentTool(),
        buildValidatedUpdateProjectTool(),
        buildValidatedDeleteProjectTool(),
        buildValidatedSearchExecutionsTool(),
        buildValidatedCreateProjectTool(),
      ];
    
      _tools = tools;
      _validatedTools = validated;
    
      toolRegistry.clear();
      for (const v of validated) toolRegistry.set(v.name, v);
    }
  • Service-layer helper method that calls the backend API (PATCH api/v1/projects/{projectUuid}/environments/{envUuid}/) to update environment fields.
    public async updateEnvironment(
      projectUuid: string,
      envUuid: string,
      patch: { name?: string; url?: string; description?: string },
    ): Promise<{ uuid: string; name: string; url: string; isActive: boolean; description: string | null; endpointType: string }> {
      if (!this.tx) throw new Error('Client not initialized — call init() first');
      const body: Record<string, any> = {};
      if (patch.name !== undefined) body.name = patch.name;
      if (patch.url !== undefined) body.url = patch.url;
      if (patch.description !== undefined) body.description = patch.description;
      const e = await this.tx.patch<any>(
        `api/v1/projects/${projectUuid}/environments/${envUuid}/`,
        body,
      );
      return {
        uuid: envUuid, // echo from input; backend PATCH response omits it
        name: e.name,
        url: e.url ?? '',
        isActive: e.isActive,
        description: e.description ?? null,
        endpointType: e.endpointType,
      };
    }
  • Tool definition file: buildUpdateEnvironmentTool() constructs the Tool object with name 'update_environment', description, and inputSchema. buildValidatedUpdateEnvironmentTool() wraps it with Zod schema and handler.
    export function buildUpdateEnvironmentTool(): Tool {
      return {
        name: 'update_environment',
        title: 'Update Environment',
        description: DESCRIPTION,
        inputSchema: {
          type: 'object',
          properties: {
            uuid: { type: 'string', description: 'UUID of the environment to update. Required.' },
            name: { type: 'string', description: 'Optional: new name.', minLength: 1 },
            url: { type: 'string', description: 'Optional: new base URL.' },
            description: { type: 'string', description: 'Optional: new description.' },
            projectUuid: { type: 'string', description: 'Optional: UUID of the target project. Defaults to git-auto-detect.' },
          },
          required: ['uuid'],
          additionalProperties: false,
        },
      };
    }
    
    export function buildValidatedUpdateEnvironmentTool(): ValidatedTool {
      const tool = buildUpdateEnvironmentTool();
      return { ...tool, inputSchema: UpdateEnvironmentInputSchema, handler: updateEnvironmentHandler };
    }
Behavior4/5

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

With no annotations, the description discloses that it's a partial update (other fields left intact), returns a specific response object, and returns isError:true with NotFound for missing UUIDs. It could mention idempotency or permissions but is sufficient.

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?

Four sentences with action front-loaded. Each sentence adds unique information (purpose, behavior, default, error handling). Slightly verbose but efficient.

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 no output schema, description includes return shape. Error behavior is covered. Parameter count and details are adequately addressed. Could mention relationship to other search/drive tools but not necessary.

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?

Schema coverage is 100%, so baseline is 3. Description adds value by noting that only specified fields change for name/url/description and that projectUuid defaults to git-auto-detect, which is not fully captured in the schema descriptions.

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 it patches an environment by UUID and specifies which fields are updatable (name, url, description), distinguishing it from create_environment and delete_environment.

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?

It explains when to use (partial update of specified fields) and mentions default project detection via git repo with optional override via projectUuid. However, it doesn't explicitly contrast with sibling tools like update_project.

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/debugg-ai/debugg-ai-mcp'

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