mcp-xcode
Version:
MCP server that wraps Xcode command-line tools for iOS/macOS development workflows
49 lines • 2.02 kB
JavaScript
import { execSync } from 'child_process';
import { access, constants, stat } from 'fs/promises';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
export async function validateXcodeInstallation() {
try {
execSync('which xcodebuild', { stdio: 'ignore' });
}
catch {
throw new McpError(ErrorCode.InternalError, 'Xcode command line tools not found. Please install with: xcode-select --install');
}
}
export async function validateProjectPath(projectPath) {
try {
await access(projectPath, constants.F_OK);
const stats = await stat(projectPath);
if (!stats.isDirectory()) {
throw new McpError(ErrorCode.InvalidParams, `Project path is not a directory: ${projectPath}`);
}
const isXcodeProject = projectPath.endsWith('.xcodeproj') || projectPath.endsWith('.xcworkspace');
if (!isXcodeProject) {
throw new McpError(ErrorCode.InvalidParams, `Invalid Xcode project path. Must end with .xcodeproj or .xcworkspace: ${projectPath}`);
}
}
catch (error) {
if (error instanceof McpError) {
throw error;
}
throw new McpError(ErrorCode.InvalidParams, `Project path not found or inaccessible: ${projectPath}`);
}
}
export function validateScheme(scheme) {
if (!scheme || scheme.trim().length === 0) {
throw new McpError(ErrorCode.InvalidParams, 'Scheme name is required and cannot be empty');
}
}
export function validateDeviceId(deviceId) {
if (!deviceId || deviceId.trim().length === 0) {
throw new McpError(ErrorCode.InvalidParams, 'Device ID is required and cannot be empty');
}
}
export function sanitizePath(path) {
// Basic path sanitization to prevent injection
return path.replace(/[;&|`$(){}[\]]/g, '');
}
export function escapeShellArg(arg) {
// Escape shell arguments to prevent command injection
return `"${arg.replace(/[\\$"`]/g, '\\$&')}"`;
}
//# sourceMappingURL=validation.js.map