import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { CoolifyApiClient } from '../client/coolify-api';
import { CheckQuotaSchema, CheckNameConflictsSchema } from '../schemas';
import { logger, logToolInvocation } from '../utils/logger';
export const checkQuotaTool: Tool = {
name: 'coolify.check_quota',
description: 'Check if a project has reached its application quota',
inputSchema: {
type: 'object',
properties: {
projectId: {
type: 'string',
description: 'Project ID to check quota for',
},
},
required: ['projectId'],
},
};
export const checkNameConflictsTool: Tool = {
name: 'coolify.check_name_conflicts',
description: 'Check if an application name is available in a project',
inputSchema: {
type: 'object',
properties: {
projectId: {
type: 'string',
description: 'Project ID to check name in',
},
name: {
type: 'string',
description: 'Application name to check',
},
},
required: ['projectId', 'name'],
},
};
export async function handleCheckQuota(args: any, apiClient: CoolifyApiClient) {
logToolInvocation('coolify.check_quota', args);
try {
const validated = CheckQuotaSchema.parse(args);
const quota = await apiClient.checkProjectQuota(validated.projectId);
const withinLimit = quota.currentApps < quota.maxApps;
logger.info(`Quota check for project ${validated.projectId}: ${quota.currentApps}/${quota.maxApps}`);
return {
success: true,
withinLimit,
currentApps: quota.currentApps,
maxApps: quota.maxApps,
projectId: validated.projectId,
canCreateMore: withinLimit,
remainingSlots: Math.max(0, quota.maxApps - quota.currentApps),
};
} catch (error: any) {
logger.error('Failed to check quota', { error: error.message });
return {
success: false,
error: {
code: error.code || 'CHECK_QUOTA_ERROR',
message: error.message,
},
};
}
}
export async function handleCheckNameConflicts(args: any, apiClient: CoolifyApiClient) {
logToolInvocation('coolify.check_name_conflicts', args);
try {
const validated = CheckNameConflictsSchema.parse(args);
const isAvailable = await apiClient.checkNameAvailability(
validated.projectId,
validated.name
);
let conflictingApp = null;
if (!isAvailable) {
// Find the conflicting app
const apps = await apiClient.listApplications(validated.projectId);
conflictingApp = apps.find(app => app.name === validated.name);
}
logger.info(`Name availability check for '${validated.name}' in project ${validated.projectId}: ${isAvailable}`);
return {
success: true,
isAvailable,
conflictingApp,
projectName: validated.name,
projectId: validated.projectId,
canUseName: isAvailable,
};
} catch (error: any) {
logger.error('Failed to check name conflicts', { error: error.message });
return {
success: false,
error: {
code: error.code || 'CHECK_NAME_CONFLICTS_ERROR',
message: error.message,
},
};
}
}