forked from getsentry/XcodeBuildMCP
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
132 lines (110 loc) · 4.1 KB
/
index.ts
File metadata and controls
132 lines (110 loc) · 4.1 KB
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env node
/**
* XcodeBuildMCP - Main entry point
*
* This file serves as the entry point for the XcodeBuildMCP server, importing and registering
* all tool modules with the MCP server. It follows the platform-specific approach for Xcode tools.
*
* Responsibilities:
* - Creating and starting the MCP server
* - Registering all platform-specific tool modules
* - Configuring server options and logging
* - Handling server lifecycle events
*/
// Import Sentry instrumentation
import './utils/sentry.ts';
// Import server components
import { createServer, startServer } from './server/server.ts';
import { McpServer } from '@camsoft/mcp-sdk/server/mcp.js';
// Import MCP types for logging
import { SetLevelRequestSchema } from '@camsoft/mcp-sdk/types.js';
// Import utilities
import { log, setLogLevel, type LogLevel } from './utils/logger.ts';
// Import version
import { version } from './version.ts';
// Import xcodemake utilities
import { isXcodemakeEnabled, isXcodemakeAvailable } from './utils/xcodemake.ts';
// Import process for stdout configuration
import process from 'node:process';
// Import resource management
import { registerResources } from './core/resources.ts';
import {
registerDiscoveryTools,
registerAllToolsStatic,
registerSelectedWorkflows,
} from './utils/tool-registry.ts';
/**
* Main function to start the server
*/
async function main(): Promise<void> {
try {
// Check if xcodemake is enabled and available
if (isXcodemakeEnabled()) {
log('info', 'xcodemake is enabled, checking if available...');
const available = await isXcodemakeAvailable();
if (available) {
log('info', 'xcodemake is available and will be used for builds');
} else {
log(
'warn',
'xcodemake is enabled but could not be made available, falling back to xcodebuild',
);
}
} else {
log('debug', 'xcodemake is disabled, using standard xcodebuild');
}
// Create the server
const server = createServer();
// Register logging/setLevel handler
server.server.setRequestHandler(SetLevelRequestSchema, async (request) => {
const { level } = request.params;
setLogLevel(level as LogLevel);
log('info', `Client requested log level: ${level}`);
return {}; // Empty result as per MCP spec
});
// Make server available globally for dynamic tools
(globalThis as { mcpServer?: McpServer }).mcpServer = server;
// Check if dynamic tools mode is explicitly disabled
const isDynamicModeEnabled = process.env.XCODEBUILDMCP_DYNAMIC_TOOLS === 'true';
if (isDynamicModeEnabled) {
// DYNAMIC MODE: Start with discovery tools only
log('info', '🚀 Initializing server in dynamic tools mode...');
await registerDiscoveryTools(server);
log('info', '💡 Use discover_tools to enable additional workflows based on your task.');
} else {
// STATIC MODE: Check for selective workflows
const enabledWorkflows = process.env.XCODEBUILDMCP_ENABLED_WORKFLOWS;
if (enabledWorkflows) {
const workflowNames = enabledWorkflows.split(',');
log('info', `🚀 Initializing server with selected workflows: ${workflowNames.join(', ')}`);
await registerSelectedWorkflows(server, workflowNames);
} else {
log('info', '🚀 Initializing server in static tools mode...');
await registerAllToolsStatic(server);
}
}
await registerResources(server);
// Start the server
await startServer(server);
// Clean up on exit
process.on('SIGTERM', async () => {
await server.close();
process.exit(0);
});
process.on('SIGINT', async () => {
await server.close();
process.exit(0);
});
// Log successful startup
log('info', `XcodeBuildMCP server (version ${version}) started successfully`);
} catch (error) {
console.error('Fatal error in main():', error);
process.exit(1);
}
}
// Start the server
main().catch((error) => {
console.error('Unhandled exception:', error);
// Give Sentry a moment to send the error before exiting
setTimeout(() => process.exit(1), 1000);
});