@rishibhushan/jenkins-mcp-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +575 -0
- package/bin/jenkins-mcp.js +327 -0
- package/package.json +51 -0
- package/requirements.txt +12 -0
- package/src/jenkins_mcp_server/__init__.py +133 -0
- package/src/jenkins_mcp_server/__main__.py +19 -0
- package/src/jenkins_mcp_server/config.py +278 -0
- package/src/jenkins_mcp_server/jenkins_client.py +516 -0
- package/src/jenkins_mcp_server/server.py +1037 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Jenkins MCP Server - Node.js Wrapper
|
|
4
|
+
*
|
|
5
|
+
* This wrapper handles:
|
|
6
|
+
* - Python version detection (cross-platform)
|
|
7
|
+
* - Virtual environment creation
|
|
8
|
+
* - Dependency installation
|
|
9
|
+
* - Server execution
|
|
10
|
+
*
|
|
11
|
+
* Supports: Windows, macOS, Linux
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { spawn, spawnSync } = require('child_process');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
|
|
18
|
+
// Configuration
|
|
19
|
+
const projectRoot = path.join(__dirname, '..');
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
const isWindows = process.platform === 'win32';
|
|
22
|
+
|
|
23
|
+
// Color codes for terminal output (if supported)
|
|
24
|
+
const colors = {
|
|
25
|
+
reset: '\x1b[0m',
|
|
26
|
+
green: '\x1b[32m',
|
|
27
|
+
yellow: '\x1b[33m',
|
|
28
|
+
red: '\x1b[31m',
|
|
29
|
+
blue: '\x1b[34m'
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function log(message, color = 'reset') {
|
|
33
|
+
const colorCode = process.stdout.isTTY ? colors[color] : '';
|
|
34
|
+
const resetCode = process.stdout.isTTY ? colors.reset : '';
|
|
35
|
+
console.log(`${colorCode}${message}${resetCode}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function error(message) {
|
|
39
|
+
console.error(`${colors.red}ERROR: ${message}${colors.reset}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check for Python 3 installation
|
|
44
|
+
* @returns {string} Python command name
|
|
45
|
+
*/
|
|
46
|
+
function checkPython() {
|
|
47
|
+
const pythonCommands = isWindows
|
|
48
|
+
? ['python', 'py', 'python3']
|
|
49
|
+
: ['python3', 'python'];
|
|
50
|
+
|
|
51
|
+
log('Checking for Python 3...', 'blue');
|
|
52
|
+
|
|
53
|
+
for (const cmd of pythonCommands) {
|
|
54
|
+
try {
|
|
55
|
+
const result = spawnSync(cmd, ['--version'], {
|
|
56
|
+
stdio: 'pipe',
|
|
57
|
+
encoding: 'utf-8'
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (result.status === 0) {
|
|
61
|
+
const output = result.stdout || result.stderr;
|
|
62
|
+
if (output.includes('Python 3')) {
|
|
63
|
+
const version = output.trim();
|
|
64
|
+
log(`✓ Found ${version}`, 'green');
|
|
65
|
+
return cmd;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} catch (e) {
|
|
69
|
+
// Command not found, try next
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
error('Python 3 is required but not found.');
|
|
75
|
+
console.error('\nPlease install Python 3.8 or higher from:');
|
|
76
|
+
console.error(' https://www.python.org/downloads/');
|
|
77
|
+
console.error('\nAfter installation, restart your terminal and try again.');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get paths for virtual environment binaries
|
|
83
|
+
* @param {string} venvPath - Path to virtual environment
|
|
84
|
+
* @returns {Object} Paths to python and pip executables
|
|
85
|
+
*/
|
|
86
|
+
function getVenvPaths(venvPath) {
|
|
87
|
+
if (isWindows) {
|
|
88
|
+
return {
|
|
89
|
+
python: path.join(venvPath, 'Scripts', 'python.exe'),
|
|
90
|
+
pip: path.join(venvPath, 'Scripts', 'pip.exe')
|
|
91
|
+
};
|
|
92
|
+
} else {
|
|
93
|
+
return {
|
|
94
|
+
python: path.join(venvPath, 'bin', 'python'),
|
|
95
|
+
pip: path.join(venvPath, 'bin', 'pip')
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Create virtual environment if it doesn't exist
|
|
102
|
+
* @param {string} pythonCmd - Python command to use
|
|
103
|
+
* @returns {string} Path to virtual environment
|
|
104
|
+
*/
|
|
105
|
+
function ensureVenv(pythonCmd) {
|
|
106
|
+
const venvPath = path.join(projectRoot, '.venv');
|
|
107
|
+
|
|
108
|
+
if (fs.existsSync(venvPath)) {
|
|
109
|
+
log('✓ Virtual environment exists', 'green');
|
|
110
|
+
return venvPath;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
log('Creating Python virtual environment...', 'yellow');
|
|
114
|
+
|
|
115
|
+
const result = spawnSync(pythonCmd, ['-m', 'venv', venvPath], {
|
|
116
|
+
cwd: projectRoot,
|
|
117
|
+
stdio: 'inherit'
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (result.status !== 0) {
|
|
121
|
+
error('Failed to create virtual environment');
|
|
122
|
+
console.error('\nTroubleshooting:');
|
|
123
|
+
console.error(' 1. Ensure Python venv module is installed');
|
|
124
|
+
console.error(' 2. Check disk space and permissions');
|
|
125
|
+
console.error(' 3. Try manually: python3 -m venv .venv');
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
log('✓ Virtual environment created', 'green');
|
|
130
|
+
return venvPath;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Check if dependencies are installed
|
|
135
|
+
* @param {string} pipPath - Path to pip executable
|
|
136
|
+
* @returns {boolean} True if dependencies are installed
|
|
137
|
+
*/
|
|
138
|
+
function dependenciesInstalled(pipPath) {
|
|
139
|
+
try {
|
|
140
|
+
const result = spawnSync(pipPath, ['list'], {
|
|
141
|
+
stdio: 'pipe',
|
|
142
|
+
encoding: 'utf-8'
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (result.status === 0) {
|
|
146
|
+
const output = result.stdout || '';
|
|
147
|
+
// Check for key dependencies
|
|
148
|
+
return output.includes('python-jenkins') &&
|
|
149
|
+
output.includes('mcp') &&
|
|
150
|
+
output.includes('requests');
|
|
151
|
+
}
|
|
152
|
+
} catch (e) {
|
|
153
|
+
// If we can't check, assume not installed
|
|
154
|
+
}
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Install Python dependencies
|
|
160
|
+
* @param {string} venvPath - Path to virtual environment
|
|
161
|
+
*/
|
|
162
|
+
function installDependencies(venvPath) {
|
|
163
|
+
const { pip } = getVenvPaths(venvPath);
|
|
164
|
+
const requirementsPath = path.join(projectRoot, 'requirements.txt');
|
|
165
|
+
|
|
166
|
+
if (!fs.existsSync(requirementsPath)) {
|
|
167
|
+
error('requirements.txt not found');
|
|
168
|
+
console.error(`Expected at: ${requirementsPath}`);
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
log('Installing Python dependencies...', 'yellow');
|
|
173
|
+
log('This may take a minute...', 'blue');
|
|
174
|
+
|
|
175
|
+
const result = spawnSync(pip, ['install', '-r', requirementsPath], {
|
|
176
|
+
cwd: projectRoot,
|
|
177
|
+
stdio: 'inherit'
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
if (result.status !== 0) {
|
|
181
|
+
error('Failed to install dependencies');
|
|
182
|
+
console.error('\nTroubleshooting:');
|
|
183
|
+
console.error(' 1. Check your internet connection');
|
|
184
|
+
console.error(' 2. If behind a proxy, set HTTP_PROXY/HTTPS_PROXY env vars');
|
|
185
|
+
console.error(' 3. Try manually: .venv/bin/pip install -r requirements.txt');
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
log('✓ Dependencies installed', 'green');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Find the Python entry point
|
|
194
|
+
* @returns {Object} Entry point information
|
|
195
|
+
*/
|
|
196
|
+
function findEntryPoint() {
|
|
197
|
+
const mainPyPath = path.join(projectRoot, 'src', 'jenkins_mcp_server', '__main__.py');
|
|
198
|
+
|
|
199
|
+
if (fs.existsSync(mainPyPath)) {
|
|
200
|
+
return {
|
|
201
|
+
type: 'module',
|
|
202
|
+
args: ['-m', 'jenkins_mcp_server']
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Fallback options
|
|
207
|
+
const fallbacks = [
|
|
208
|
+
path.join(projectRoot, 'src', 'jenkins_mcp_server', 'server.py'),
|
|
209
|
+
path.join(projectRoot, 'src', 'main.py'),
|
|
210
|
+
path.join(projectRoot, 'main.py')
|
|
211
|
+
];
|
|
212
|
+
|
|
213
|
+
for (const filePath of fallbacks) {
|
|
214
|
+
if (fs.existsSync(filePath)) {
|
|
215
|
+
return {
|
|
216
|
+
type: 'script',
|
|
217
|
+
args: [filePath]
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
error('Could not find Python entry point');
|
|
223
|
+
console.error('\nExpected one of:');
|
|
224
|
+
console.error(' - src/jenkins_mcp_server/__main__.py (preferred)');
|
|
225
|
+
console.error(' - src/jenkins_mcp_server/server.py');
|
|
226
|
+
console.error(' - src/main.py');
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Run the Jenkins MCP Server
|
|
232
|
+
* @param {string} venvPath - Path to virtual environment
|
|
233
|
+
*/
|
|
234
|
+
function runServer(venvPath) {
|
|
235
|
+
const { python } = getVenvPaths(venvPath);
|
|
236
|
+
const entryPoint = findEntryPoint();
|
|
237
|
+
|
|
238
|
+
// Set up environment
|
|
239
|
+
const env = {
|
|
240
|
+
...process.env,
|
|
241
|
+
PYTHONPATH: path.join(projectRoot, 'src'),
|
|
242
|
+
PYTHONUNBUFFERED: '1' // Ensure output is not buffered
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const serverArgs = [...entryPoint.args, ...args];
|
|
246
|
+
|
|
247
|
+
log('Starting Jenkins MCP Server...', 'green');
|
|
248
|
+
log(`Command: ${python} ${serverArgs.join(' ')}`, 'blue');
|
|
249
|
+
|
|
250
|
+
const server = spawn(python, serverArgs, {
|
|
251
|
+
cwd: projectRoot,
|
|
252
|
+
stdio: 'inherit',
|
|
253
|
+
env: env,
|
|
254
|
+
shell: isWindows
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
server.on('error', (err) => {
|
|
258
|
+
error(`Failed to start server: ${err.message}`);
|
|
259
|
+
process.exit(1);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
server.on('close', (code) => {
|
|
263
|
+
if (code !== 0 && code !== null) {
|
|
264
|
+
log(`Server exited with code ${code}`, 'yellow');
|
|
265
|
+
}
|
|
266
|
+
process.exit(code || 0);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// Handle graceful shutdown
|
|
270
|
+
const cleanup = () => {
|
|
271
|
+
log('\nShutting down...', 'yellow');
|
|
272
|
+
server.kill('SIGTERM');
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
process.on('SIGINT', cleanup);
|
|
276
|
+
process.on('SIGTERM', cleanup);
|
|
277
|
+
|
|
278
|
+
// Windows doesn't support SIGINT/SIGTERM the same way
|
|
279
|
+
if (isWindows) {
|
|
280
|
+
process.on('SIGBREAK', cleanup);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Main execution flow
|
|
286
|
+
*/
|
|
287
|
+
function main() {
|
|
288
|
+
try {
|
|
289
|
+
// Check for help flag
|
|
290
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
291
|
+
console.log('Jenkins MCP Server - Node.js Wrapper');
|
|
292
|
+
console.log('\nUsage: jenkins-mcp-server [options]');
|
|
293
|
+
console.log('\nOptions:');
|
|
294
|
+
console.log(' --env-file PATH Path to custom .env file');
|
|
295
|
+
console.log(' --verbose, -v Enable verbose logging');
|
|
296
|
+
console.log(' --no-vscode Skip loading VS Code settings');
|
|
297
|
+
console.log(' --version Show version');
|
|
298
|
+
console.log(' --help, -h Show this help message');
|
|
299
|
+
process.exit(0);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Check Python availability
|
|
303
|
+
const pythonCmd = checkPython();
|
|
304
|
+
|
|
305
|
+
// Ensure virtual environment exists
|
|
306
|
+
const venvPath = ensureVenv(pythonCmd);
|
|
307
|
+
|
|
308
|
+
// Check and install dependencies if needed
|
|
309
|
+
const { pip } = getVenvPaths(venvPath);
|
|
310
|
+
if (!dependenciesInstalled(pip)) {
|
|
311
|
+
installDependencies(venvPath);
|
|
312
|
+
} else {
|
|
313
|
+
log('✓ Dependencies already installed', 'green');
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Run the server
|
|
317
|
+
runServer(venvPath);
|
|
318
|
+
|
|
319
|
+
} catch (err) {
|
|
320
|
+
error(`Unexpected error: ${err.message}`);
|
|
321
|
+
console.error(err.stack);
|
|
322
|
+
process.exit(1);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Run main function
|
|
327
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rishibhushan/jenkins-mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "AI-enabled Jenkins automation via Model Context Protocol (MCP)",
|
|
5
|
+
"main": "bin/jenkins-mcp.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"jenkins-mcp-server": "bin/jenkins-mcp.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/jenkins-mcp.js",
|
|
11
|
+
"test": "python -m pytest tests/",
|
|
12
|
+
"build": "python -m build"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"bin/",
|
|
16
|
+
"src/",
|
|
17
|
+
"requirements.txt",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=14.0.0"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"mcp",
|
|
26
|
+
"jenkins",
|
|
27
|
+
"ai",
|
|
28
|
+
"automation",
|
|
29
|
+
"ci-cd",
|
|
30
|
+
"devops",
|
|
31
|
+
"model-context-protocol",
|
|
32
|
+
"llm",
|
|
33
|
+
"chatgpt",
|
|
34
|
+
"claude"
|
|
35
|
+
],
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/rishibhushan/jenkins_mcp_server.git"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/rishibhushan/jenkins_mcp_server/issues"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/rishibhushan/jenkins_mcp_server#readme",
|
|
44
|
+
"author": "Rishi Bhushan",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"os": [
|
|
47
|
+
"darwin",
|
|
48
|
+
"linux",
|
|
49
|
+
"win32"
|
|
50
|
+
]
|
|
51
|
+
}
|
package/requirements.txt
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Jenkins MCP Server Package
|
|
3
|
+
|
|
4
|
+
Main entry point for the Jenkins MCP Server.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
import asyncio
|
|
9
|
+
import logging
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
from .config import get_settings, get_default_settings
|
|
13
|
+
from . import server
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def setup_logging(verbose: bool = False) -> None:
|
|
17
|
+
"""Configure logging for the application"""
|
|
18
|
+
level = logging.DEBUG if verbose else logging.INFO
|
|
19
|
+
|
|
20
|
+
logging.basicConfig(
|
|
21
|
+
level=level,
|
|
22
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
23
|
+
stream=sys.stderr
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Reduce noise from libraries
|
|
27
|
+
logging.getLogger('urllib3').setLevel(logging.WARNING)
|
|
28
|
+
logging.getLogger('requests').setLevel(logging.WARNING)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def main():
|
|
32
|
+
"""
|
|
33
|
+
Main entry point for the Jenkins MCP Server.
|
|
34
|
+
|
|
35
|
+
Parses command-line arguments, configures settings, and starts the server.
|
|
36
|
+
"""
|
|
37
|
+
parser = argparse.ArgumentParser(
|
|
38
|
+
description='Jenkins MCP Server - AI-enabled Jenkins automation',
|
|
39
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
40
|
+
epilog="""
|
|
41
|
+
Examples:
|
|
42
|
+
%(prog)s # Use default .env file
|
|
43
|
+
%(prog)s --env-file /path/to/.env # Use custom .env file
|
|
44
|
+
%(prog)s --verbose # Enable debug logging
|
|
45
|
+
%(prog)s --env-file custom.env --verbose # Combined options
|
|
46
|
+
|
|
47
|
+
Environment Variables:
|
|
48
|
+
JENKINS_URL Jenkins server URL (e.g., http://localhost:8080)
|
|
49
|
+
JENKINS_USERNAME Jenkins username
|
|
50
|
+
JENKINS_TOKEN Jenkins API token (recommended)
|
|
51
|
+
JENKINS_PASSWORD Jenkins password (alternative to token)
|
|
52
|
+
|
|
53
|
+
Configuration Priority:
|
|
54
|
+
1. Command-line arguments (--env-file)
|
|
55
|
+
2. VS Code settings.json
|
|
56
|
+
3. Environment variables
|
|
57
|
+
4. Default .env file
|
|
58
|
+
"""
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
'--env-file',
|
|
63
|
+
metavar='PATH',
|
|
64
|
+
help='Path to custom .env file with Jenkins credentials'
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
parser.add_argument(
|
|
68
|
+
'--verbose', '-v',
|
|
69
|
+
action='store_true',
|
|
70
|
+
help='Enable verbose/debug logging'
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
parser.add_argument(
|
|
74
|
+
'--version',
|
|
75
|
+
action='version',
|
|
76
|
+
version='jenkins-mcp-server 1.0.0'
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
parser.add_argument(
|
|
80
|
+
'--no-vscode',
|
|
81
|
+
action='store_true',
|
|
82
|
+
help='Skip loading settings from VS Code (use only .env/environment)'
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
args = parser.parse_args()
|
|
86
|
+
|
|
87
|
+
# Setup logging first
|
|
88
|
+
setup_logging(args.verbose)
|
|
89
|
+
logger = logging.getLogger(__name__)
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
# Load settings based on arguments
|
|
93
|
+
logger.info("Loading Jenkins configuration...")
|
|
94
|
+
|
|
95
|
+
settings = get_settings(
|
|
96
|
+
env_file=args.env_file,
|
|
97
|
+
load_vscode=not args.no_vscode
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Validate configuration
|
|
101
|
+
if not settings.is_configured:
|
|
102
|
+
logger.error("Jenkins configuration is incomplete!")
|
|
103
|
+
logger.error("Required: URL, username, and (token or password)")
|
|
104
|
+
logger.error("\nPlease configure via:")
|
|
105
|
+
logger.error(" 1. .env file (JENKINS_URL, JENKINS_USERNAME, JENKINS_TOKEN)")
|
|
106
|
+
logger.error(" 2. VS Code settings.json")
|
|
107
|
+
logger.error(" 3. Environment variables")
|
|
108
|
+
logger.error("\nFor help, run: %(prog)s --help" % {'prog': parser.prog})
|
|
109
|
+
sys.exit(1)
|
|
110
|
+
|
|
111
|
+
# Log configuration summary
|
|
112
|
+
logger.info(f"Jenkins server: {settings.url}")
|
|
113
|
+
logger.info(f"Username: {settings.username}")
|
|
114
|
+
logger.info(f"Authentication: {settings.auth_method}")
|
|
115
|
+
|
|
116
|
+
# Pass settings to server module
|
|
117
|
+
server.set_jenkins_settings(settings)
|
|
118
|
+
|
|
119
|
+
# Run the server
|
|
120
|
+
logger.info("Starting Jenkins MCP Server...")
|
|
121
|
+
asyncio.run(server.main())
|
|
122
|
+
|
|
123
|
+
except KeyboardInterrupt:
|
|
124
|
+
logger.info("Server stopped by user")
|
|
125
|
+
sys.exit(0)
|
|
126
|
+
except Exception as e:
|
|
127
|
+
logger.error(f"Failed to start server: {e}", exc_info=args.verbose)
|
|
128
|
+
sys.exit(1)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# Package metadata
|
|
132
|
+
__version__ = "1.0.0"
|
|
133
|
+
__all__ = ['main', 'server']
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Main entry point for running the Jenkins MCP Server as a module.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python -m jenkins_mcp_server [options]
|
|
7
|
+
|
|
8
|
+
Options:
|
|
9
|
+
--env-file PATH Path to custom .env file
|
|
10
|
+
--verbose, -v Enable verbose logging
|
|
11
|
+
--no-vscode Skip loading VS Code settings
|
|
12
|
+
--version Show version and exit
|
|
13
|
+
--help, -h Show help message
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from . import main
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
main()
|