Update Environment
update_environmentUpdate environment fields and manage credentials in a single call. Add, update, or remove login credentials while changing name, URL, or description.
Instructions
Patch an environment by UUID. Updates fields and/or manages credentials in a single call.
ENVIRONMENT FIELDS (all optional — only specified fields change):
name, url, description
CREDENTIAL MANAGEMENT:
addCredentials: [{label, username, password, role?}] — add one or more login credentials to this environment
updateCredentials: [{uuid, label?, username?, password?, role?}] — patch existing credentials by UUID
removeCredentialIds: ["", ...] — delete credentials by UUID
Operations run in order: remove → update → add. All credential ops are best-effort — failures go to credentialWarnings without blocking the rest. Passwords are write-only and NEVER returned in responses.
Returns {updated, environment, addedCredentials?, updatedCredentials?, removedCredentialIds?, credentialWarnings?}. Returns isError:true with NotFound when the env uuid doesn't exist.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| uuid | Yes | UUID of the environment to update. Required. | |
| name | No | Optional: new name. | |
| url | No | Optional: new base URL. | |
| description | No | Optional: new description. | |
| projectUuid | No | Optional: UUID of the target project. Defaults to git-auto-detect. | |
| addCredentials | No | Add new login credentials to the environment. Each entry requires label, username, password. role is optional. | |
| updateCredentials | No | Patch existing credentials by UUID. Only specified fields change. | |
| removeCredentialIds | No | UUIDs of credentials to delete. |
Implementation Reference
- Main handler for the update_environment tool. Receives input (uuid, optional fields, credential operations), resolves the project, patches the environment, and performs credential sub-actions (remove → update → add) with best-effort warnings.
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'); } } - types/index.ts:112-122 (schema)Zod schema and TypeScript type for update_environment input. Validates uuid (required), optional env fields, and credential sub-operations.
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/updateEnvironment.ts:19-78 (registration)Tool registration: builds the tool definition (name 'update_environment', inputSchema, description) and wires it to the handler. Registered in tools/index.ts via buildUpdateEnvironmentTool() and buildValidatedUpdateEnvironmentTool().
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.' }, addCredentials: { type: 'array', description: 'Add new login credentials to the environment. Each entry requires label, username, password. role is optional.', items: { type: 'object', properties: { label: { type: 'string', description: 'Human-readable name (e.g. "admin user", "test account").' }, username: { type: 'string', description: 'Login email or username.' }, password: { type: 'string', description: 'Password. Write-only — never returned.' }, role: { type: 'string', description: 'Optional role tag (e.g. "admin", "guest").' }, }, required: ['label', 'username', 'password'], additionalProperties: false, }, }, updateCredentials: { type: 'array', description: 'Patch existing credentials by UUID. Only specified fields change.', items: { type: 'object', properties: { uuid: { type: 'string', description: 'UUID of the credential to update.' }, label: { type: 'string' }, username: { type: 'string' }, password: { type: 'string', description: 'Write-only — never returned.' }, role: { type: 'string' }, }, required: ['uuid'], additionalProperties: false, }, }, removeCredentialIds: { type: 'array', description: 'UUIDs of credentials to delete.', items: { type: 'string' }, }, }, required: ['uuid'], additionalProperties: false, }, }; } export function buildValidatedUpdateEnvironmentTool(): ValidatedTool { const tool = buildUpdateEnvironmentTool(); return { ...tool, inputSchema: UpdateEnvironmentInputSchema, handler: updateEnvironmentHandler }; } - tools/index.ts:42-64 (registration)Registration of the tool in the central tool registry's list of unvalidated Tool definitions.
buildUpdateEnvironmentTool(), buildDeleteEnvironmentTool(), buildUpdateProjectTool(), buildDeleteProjectTool(), buildSearchExecutionsTool(), buildCreateProjectTool(), buildCreateTestSuiteTool(), buildSearchTestSuitesTool(), buildDeleteTestSuiteTool(), buildCreateTestCaseTool(), buildUpdateTestCaseTool(), buildDeleteTestCaseTool(), buildRunTestSuiteTool(), buildGetTestSuiteResultsTool(), ]; const validated: ValidatedTool[] = [ buildValidatedTestPageChangesTool(ctx), buildValidatedTriggerCrawlTool(ctx), buildValidatedProbePageTool(), buildValidatedSearchProjectsTool(), buildValidatedSearchEnvironmentsTool(), buildValidatedCreateEnvironmentTool(), buildValidatedUpdateEnvironmentTool(),