Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 9x | import { z } from 'zod';
import { requiredId, flexibleBoolean } from '../utils';
// ============================================================================
// manage_environment - CQRS Command Tool (discriminated union schema)
// Actions: create, update, stop, delete, update_deployment_status
// Deployments are folded in as the update_deployment_status action rather than a
// separate tool, keeping the MCP tool count lean.
// Uses z.discriminatedUnion() for type-safe action handling.
// ============================================================================
// --- Shared fields ---
const projectIdField = requiredId.describe(
"Project ID or URL-encoded path (e.g., 'my-group/my-project')",
);
const environmentIdField = z.coerce
.number()
.int()
.positive()
.describe('Numeric ID of the environment');
const tierField = z
.enum(['production', 'staging', 'testing', 'development', 'other'])
.describe('Deployment tier of the environment');
const externalUrlField = z
.string()
.url()
.describe(
'URL where the deployed environment can be reached (e.g., https://staging.example.com)',
);
const descriptionField = z.string().describe('Description of the environment');
// --- Action: create ---
const CreateEnvironmentSchema = z.object({
action: z.literal('create').describe('Create a new environment'),
project_id: projectIdField,
name: z.string().describe('Name of the environment'),
external_url: externalUrlField.optional(),
tier: tierField.optional(),
description: descriptionField.optional(),
});
// --- Action: update ---
const UpdateEnvironmentSchema = z.object({
action: z
.literal('update')
.describe('Update an existing environment (name cannot be changed via the API)'),
project_id: projectIdField,
environment_id: environmentIdField,
external_url: externalUrlField.optional(),
tier: tierField.optional(),
description: descriptionField.optional(),
});
// --- Action: stop ---
const StopEnvironmentSchema = z.object({
action: z.literal('stop').describe('Stop an environment (required before it can be deleted)'),
project_id: projectIdField,
environment_id: environmentIdField,
force: flexibleBoolean
.optional()
.describe('Force the stop, skipping the on_stop action if one is defined'),
});
// --- Action: delete ---
const DeleteEnvironmentSchema = z.object({
action: z.literal('delete').describe('Delete a stopped environment'),
project_id: projectIdField,
environment_id: environmentIdField,
});
// --- Action: update_deployment_status ---
const UpdateDeploymentStatusSchema = z.object({
action: z
.literal('update_deployment_status')
.describe(
'Update the status of a deployment. Only deployments not tied to a pipeline job can be updated.',
),
project_id: projectIdField,
deployment_id: z.coerce
.number()
.int()
.positive()
.describe('Numeric ID of the deployment to update'),
status: z.enum(['running', 'success', 'failed', 'canceled']).describe('New deployment status'),
});
// --- Discriminated union combining all actions ---
export const ManageEnvironmentSchema = z
.discriminatedUnion('action', [
CreateEnvironmentSchema,
UpdateEnvironmentSchema,
StopEnvironmentSchema,
DeleteEnvironmentSchema,
UpdateDeploymentStatusSchema,
])
// An update with no fields would send an empty body and be rejected by GitLab;
// require at least one updatable field.
.refine(
(data) =>
data.action !== 'update' ||
data.external_url !== undefined ||
data.tier !== undefined ||
data.description !== undefined,
{
message: 'update requires at least one of: external_url, tier, description',
path: ['external_url'],
},
);
// ============================================================================
// Type exports
// ============================================================================
export type ManageEnvironmentInput = z.infer<typeof ManageEnvironmentSchema>;
|