@rishibhushan/jenkins-mcp-server 1.1.1 → 1.1.3

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.
@@ -73,6 +73,62 @@ function detectProxyConfig() {
73
73
  return activeProxies;
74
74
  }
75
75
 
76
+ /**
77
+ * Check npm config for proxy settings
78
+ * @returns {Object} npm proxy configuration
79
+ */
80
+ function checkNpmProxy() {
81
+ try {
82
+ const result = spawnSync('npm', ['config', 'list'], {
83
+ stdio: 'pipe',
84
+ encoding: 'utf-8'
85
+ });
86
+
87
+ if (result.status === 0) {
88
+ const output = result.stdout || '';
89
+ const proxyLines = output.split('\n').filter(line =>
90
+ line.toLowerCase().includes('proxy') && !line.includes('; ///')
91
+ );
92
+
93
+ if (proxyLines.length > 0) {
94
+ return {
95
+ found: true,
96
+ config: proxyLines.join('\n')
97
+ };
98
+ }
99
+ }
100
+ } catch (e) {
101
+ // npm not available or error
102
+ }
103
+ return { found: false };
104
+ }
105
+
106
+ /**
107
+ * Check pip config for proxy settings
108
+ * @returns {Object} pip proxy configuration
109
+ */
110
+ function checkPipProxy() {
111
+ try {
112
+ const result = spawnSync('pip3', ['config', 'list'], {
113
+ stdio: 'pipe',
114
+ encoding: 'utf-8'
115
+ });
116
+
117
+ if (result.status === 0) {
118
+ const output = result.stdout || '';
119
+ if (output.toLowerCase().includes('proxy')) {
120
+ return {
121
+ found: true,
122
+ config: output
123
+ };
124
+ }
125
+ }
126
+ } catch (e) {
127
+ // pip not available or error
128
+ }
129
+ return { found: false };
130
+ }
131
+
76
132
  /**
77
133
  * Test if proxy is reachable
78
134
  * @param {string} proxyUrl - Proxy URL to test
@@ -254,6 +310,32 @@ function showProxyTroubleshooting(activeProxies, canAccessDirectly, proxyWorks)
254
310
  console.error(colors.bold + colors.yellow + 'INSTALLATION FAILED - NETWORK CONFIGURATION ISSUE' + colors.reset);
255
311
  console.error('='.repeat(70));
256
312
 
313
+ // Check npm and pip config
314
+ const npmProxy = checkNpmProxy();
315
+ const pipProxy = checkPipProxy();
316
+
317
+ if (npmProxy.found) {
318
+ console.error('\n' + colors.red + '⚠️ FOUND PROXY IN NPM CONFIG!' + colors.reset);
319
+ console.error(colors.cyan + npmProxy.config + colors.reset);
320
+ console.error('\n' + colors.yellow + 'This is likely the cause of your issue!' + colors.reset);
321
+ console.error('\n' + colors.bold + 'FIX (run these commands):' + colors.reset);
322
+ console.error(colors.cyan + ' npm config delete proxy' + colors.reset);
323
+ console.error(colors.cyan + ' npm config delete https-proxy' + colors.reset);
324
+ console.error(colors.cyan + ' npm config delete http-proxy' + colors.reset);
325
+ console.error(colors.cyan + ' npm config --global delete proxy' + colors.reset);
326
+ console.error(colors.cyan + ' npm config --global delete https-proxy' + colors.reset);
327
+ console.error('\nThen run your command again.\n');
328
+ }
329
+
330
+ if (pipProxy.found) {
331
+ console.error('\n' + colors.red + '⚠️ FOUND PROXY IN PIP CONFIG!' + colors.reset);
332
+ console.error(colors.cyan + pipProxy.config + colors.reset);
333
+ console.error('\n' + colors.bold + 'FIX (run these commands):' + colors.reset);
334
+ console.error(colors.cyan + ' pip3 config unset global.proxy' + colors.reset);
335
+ console.error(colors.cyan + ' pip3 config unset user.proxy' + colors.reset);
336
+ console.error('\nOr edit/delete: ~/.config/pip/pip.conf\n');
337
+ }
338
+
257
339
  if (Object.keys(activeProxies).length > 0) {
258
340
  console.error('\n📡 Active proxy environment variables found:');
259
341
  for (const [key, value] of Object.entries(activeProxies)) {
@@ -450,6 +532,18 @@ function installDependencies(venvPath) {
450
532
 
451
533
  // Install package itself
452
534
  console.error('Installing jenkins-mcp-server package...');
535
+
536
+ // Verify pyproject.toml exists
537
+ const pyprojectPath = path.join(projectRoot, 'pyproject.toml');
538
+ if (!fs.existsSync(pyprojectPath)) {
539
+ error('pyproject.toml not found in project root');
540
+ console.error('\nProject root:', projectRoot);
541
+ console.error('Expected file:', pyprojectPath);
542
+ console.error('\nThis may be due to npx cache issues with special characters.');
543
+ console.error('Try clearing npx cache: npx clear-npx-cache');
544
+ process.exit(1);
545
+ }
546
+
453
547
  const packageArgs = ['install', '-e', '.'];
454
548
 
455
549
  const installPkg = spawnSync(pip, packageArgs, {
@@ -459,6 +553,20 @@ function installDependencies(venvPath) {
459
553
 
460
554
  if (installPkg.status !== 0) {
461
555
  error('Failed to install package');
556
+ console.error('\nProject root:', projectRoot);
557
+ console.error('Files in project root:');
558
+ try {
559
+ const files = fs.readdirSync(projectRoot);
560
+ console.error(files.join(', '));
561
+ } catch (e) {
562
+ console.error('Could not list files');
563
+ }
564
+
565
+ console.error('\n💡 TROUBLESHOOTING:');
566
+ console.error('1. The npx cache may have issues with the @ symbol in package name');
567
+ console.error('2. Try: npx clear-npx-cache && rm -rf ~/.npm/_npx');
568
+ console.error('3. Or install globally: npm install -g @rishibhushan/jenkins-mcp-server');
569
+ console.error(' Then run: jenkins-mcp-server --env-file /path/to/.env');
462
570
  process.exit(1);
463
571
  }
464
572
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rishibhushan/jenkins-mcp-server",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "AI-enabled Jenkins automation via Model Context Protocol (MCP)",
5
5
  "main": "bin/jenkins-mcp.js",
6
6
  "bin": {
@@ -9,13 +9,15 @@
9
9
  "scripts": {
10
10
  "start": "node bin/jenkins-mcp.js",
11
11
  "test": "python -m pytest tests/",
12
- "build": "python -m build"
12
+ "build": "python -m build",
13
+ "prepack": "npm run clean",
14
+ "clean": "find . -type d -name '__pycache__' -exec rm -rf {} + 2>/dev/null || true; find . -type d -name '*.egg-info' -exec rm -rf {} + 2>/dev/null || true"
13
15
  },
14
16
  "files": [
15
17
  "bin/",
16
- "src/",
18
+ "src/**/*.py",
19
+ "pyproject.toml",
17
20
  "requirements.txt",
18
- "wheels/",
19
21
  "README.md",
20
22
  "LICENSE"
21
23
  ],
package/pyproject.toml ADDED
@@ -0,0 +1,190 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "jenkins-mcp-server"
7
+ version = "1.0.0"
8
+ description = "AI-enabled Jenkins automation via Model Context Protocol (MCP)"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Rishi Bhushan", email = "rishibharat2007@gmail.com"}
14
+ ]
15
+ maintainers = [
16
+ {name = "Rishi Bhushan", email = "rishibharat2007@example.com"}
17
+ ]
18
+ keywords = [
19
+ "mcp",
20
+ "jenkins",
21
+ "ai",
22
+ "automation",
23
+ "ci-cd",
24
+ "devops",
25
+ "model-context-protocol",
26
+ "llm"
27
+ ]
28
+ classifiers = [
29
+ "Development Status :: 4 - Beta",
30
+ "Intended Audience :: Developers",
31
+ "Intended Audience :: System Administrators",
32
+ "License :: OSI Approved :: MIT License",
33
+ "Operating System :: OS Independent",
34
+ "Programming Language :: Python :: 3",
35
+ "Programming Language :: Python :: 3.8",
36
+ "Programming Language :: Python :: 3.9",
37
+ "Programming Language :: Python :: 3.10",
38
+ "Programming Language :: Python :: 3.11",
39
+ "Programming Language :: Python :: 3.12",
40
+ "Topic :: Software Development :: Build Tools",
41
+ "Topic :: System :: Systems Administration",
42
+ "Topic :: Software Development :: Libraries :: Python Modules"
43
+ ]
44
+
45
+ dependencies = [
46
+ "mcp>=1.0.0",
47
+ "python-jenkins>=1.8.0",
48
+ "requests>=2.28.0",
49
+ "pydantic>=2.0.0",
50
+ "pydantic-settings>=2.0.0",
51
+ "python-dotenv>=1.0.0",
52
+ "urllib3>=2.0.0"
53
+ ]
54
+
55
+ [project.optional-dependencies]
56
+ dev = [
57
+ "pytest>=7.0.0",
58
+ "pytest-asyncio>=0.21.0",
59
+ "pytest-cov>=4.0.0",
60
+ "black>=23.0.0",
61
+ "ruff>=0.1.0",
62
+ "mypy>=1.0.0"
63
+ ]
64
+ test = [
65
+ "pytest>=7.0.0",
66
+ "pytest-asyncio>=0.21.0",
67
+ "pytest-cov>=4.0.0"
68
+ ]
69
+
70
+ [project.urls]
71
+ Homepage = "https://github.com/rishibhushan/jenkins_mcp_server"
72
+ Documentation = "https://github.com/rishibhushan/jenkins_mcp_server#readme"
73
+ Repository = "https://github.com/rishibhushan/jenkins_mcp_server.git"
74
+ "Bug Tracker" = "https://github.com/rishibhushan/jenkins_mcp_server/issues"
75
+ Changelog = "https://github.com/rishibhushan/jenkins_mcp_server/releases"
76
+
77
+ [project.scripts]
78
+ jenkins-mcp-server = "jenkins_mcp_server:main"
79
+
80
+ [tool.setuptools]
81
+ package-dir = {"" = "src"}
82
+
83
+ [tool.setuptools.packages.find]
84
+ where = ["src"]
85
+ include = ["jenkins_mcp_server*"]
86
+ exclude = ["tests*"]
87
+
88
+ [tool.setuptools.package-data]
89
+ jenkins_mcp_server = ["py.typed"]
90
+
91
+ # Black configuration
92
+ [tool.black]
93
+ line-length = 100
94
+ target-version = ['py38', 'py39', 'py310', 'py311']
95
+ include = '\.pyi?$'
96
+ extend-exclude = '''
97
+ /(
98
+ # directories
99
+ \.eggs
100
+ | \.git
101
+ | \.hg
102
+ | \.mypy_cache
103
+ | \.tox
104
+ | \.venv
105
+ | build
106
+ | dist
107
+ )/
108
+ '''
109
+
110
+ # Ruff configuration (fast linter)
111
+ [tool.ruff]
112
+ line-length = 100
113
+ target-version = "py38"
114
+ select = [
115
+ "E", # pycodestyle errors
116
+ "W", # pycodestyle warnings
117
+ "F", # pyflakes
118
+ "I", # isort
119
+ "B", # flake8-bugbear
120
+ "C4", # flake8-comprehensions
121
+ "UP", # pyupgrade
122
+ ]
123
+ ignore = [
124
+ "E501", # line too long (handled by black)
125
+ "B008", # do not perform function calls in argument defaults
126
+ "C901", # too complex
127
+ ]
128
+
129
+ [tool.ruff.per-file-ignores]
130
+ "__init__.py" = ["F401"] # unused imports in __init__.py
131
+
132
+ # MyPy configuration
133
+ [tool.mypy]
134
+ python_version = "3.8"
135
+ warn_return_any = true
136
+ warn_unused_configs = true
137
+ disallow_untyped_defs = false
138
+ disallow_incomplete_defs = false
139
+ check_untyped_defs = true
140
+ no_implicit_optional = true
141
+ warn_redundant_casts = true
142
+ warn_unused_ignores = true
143
+ warn_no_return = true
144
+ strict_equality = true
145
+
146
+ [[tool.mypy.overrides]]
147
+ module = [
148
+ "jenkins",
149
+ "mcp.*"
150
+ ]
151
+ ignore_missing_imports = true
152
+
153
+ # Pytest configuration
154
+ [tool.pytest.ini_options]
155
+ minversion = "7.0"
156
+ addopts = [
157
+ "-ra",
158
+ "--strict-markers",
159
+ "--strict-config",
160
+ "--showlocals",
161
+ "--tb=short"
162
+ ]
163
+ testpaths = ["tests"]
164
+ pythonpath = ["src"]
165
+ asyncio_mode = "auto"
166
+
167
+ # Coverage configuration
168
+ [tool.coverage.run]
169
+ source = ["src"]
170
+ branch = true
171
+ omit = [
172
+ "*/tests/*",
173
+ "*/__pycache__/*",
174
+ "*/.venv/*"
175
+ ]
176
+
177
+ [tool.coverage.report]
178
+ precision = 2
179
+ show_missing = true
180
+ skip_covered = false
181
+ exclude_lines = [
182
+ "pragma: no cover",
183
+ "def __repr__",
184
+ "raise AssertionError",
185
+ "raise NotImplementedError",
186
+ "if __name__ == .__main__.:",
187
+ "if TYPE_CHECKING:",
188
+ "class .*\\bProtocol\\):",
189
+ "@(abc\\.)?abstractmethod"
190
+ ]
@@ -40,12 +40,14 @@ class JenkinsClient:
40
40
  timeout support.
41
41
  """
42
42
 
43
- def __init__(self, settings: Optional[JenkinsSettings] = None):
43
+ def __init__(self, settings: Optional[JenkinsSettings] = None, test_connection: bool = False):
44
44
  """
45
45
  Initialize Jenkins client.
46
46
 
47
47
  Args:
48
48
  settings: JenkinsSettings instance. If None, uses default settings.
49
+ test_connection: If True, test connection during initialization.
50
+ Set to False for MCP list_resources to avoid blocking.
49
51
 
50
52
  Raises:
51
53
  JenkinsConnectionError: If unable to connect to Jenkins
@@ -72,8 +74,10 @@ class JenkinsClient:
72
74
  # Cache for python-jenkins server instance
73
75
  self._server: Optional[jenkins.Jenkins] = None
74
76
 
75
- # Test connection
76
- self._test_connection()
77
+ # Only test connection if explicitly requested
78
+ # This prevents blocking during MCP initialization
79
+ if test_connection:
80
+ self._test_connection()
77
81
 
78
82
  def _test_connection(self) -> None:
79
83
  """Test connection to Jenkins server (with configurable timeout)"""
@@ -475,12 +479,16 @@ class JenkinsClient:
475
479
  _default_client: Optional[JenkinsClient] = None
476
480
 
477
481
 
478
- def get_jenkins_client(settings: Optional[JenkinsSettings] = None) -> JenkinsClient:
482
+ def get_jenkins_client(
483
+ settings: Optional[JenkinsSettings] = None,
484
+ test_connection: bool = False
485
+ ) -> JenkinsClient:
479
486
  """
480
487
  Get Jenkins client instance.
481
488
 
482
489
  Args:
483
490
  settings: Optional JenkinsSettings. If None, uses default settings.
491
+ test_connection: If True, test connection during initialization.
484
492
 
485
493
  Returns:
486
494
  JenkinsClient instance
@@ -492,16 +500,10 @@ def get_jenkins_client(settings: Optional[JenkinsSettings] = None) -> JenkinsCli
492
500
 
493
501
  if settings is not None:
494
502
  # Always create new client with custom settings
495
- return JenkinsClient(settings)
503
+ return JenkinsClient(settings, test_connection=test_connection)
496
504
 
497
505
  # Use cached default client
498
506
  if _default_client is None:
499
- _default_client = JenkinsClient()
507
+ _default_client = JenkinsClient(test_connection=test_connection)
500
508
 
501
509
  return _default_client
502
-
503
-
504
- def reset_default_client() -> None:
505
- """Reset the default client (useful for testing or reconfiguration)"""
506
- global _default_client
507
- _default_client = None
@@ -120,10 +120,15 @@ async def handle_list_resources() -> list[types.Resource]:
120
120
  """
121
121
  List available Jenkins resources.
122
122
  Each job is exposed as a resource with jenkins:// URI scheme.
123
+
124
+ Enhanced with timeout to prevent MCP initialization delays.
123
125
  """
124
126
  try:
125
- client = get_jenkins_client(get_settings())
126
- jobs = client.get_jobs()
127
+ # Wrap in async timeout to prevent blocking MCP initialization
128
+ async with asyncio.timeout(3): # 3 second timeout
129
+ client = get_jenkins_client(get_settings())
130
+ # Run blocking get_jobs() in thread pool
131
+ jobs = await asyncio.to_thread(client.get_jobs)
127
132
 
128
133
  return [
129
134
  types.Resource(
@@ -134,13 +139,24 @@ async def handle_list_resources() -> list[types.Resource]:
134
139
  )
135
140
  for job in jobs
136
141
  ]
142
+ except asyncio.TimeoutError:
143
+ # Jenkins server not reachable (probably not on VPN/corporate network)
144
+ logger.warning("Jenkins server not reachable within 3 seconds - likely not on corporate network")
145
+ return [
146
+ types.Resource(
147
+ uri=AnyUrl("jenkins://offline"),
148
+ name="Jenkins Server Offline",
149
+ description="Jenkins server not reachable. Connect to VPN/corporate network and restart. Tools will still work when connected.",
150
+ mimeType="text/plain",
151
+ )
152
+ ]
137
153
  except Exception as e:
138
154
  logger.error(f"Failed to list resources: {e}")
139
155
  return [
140
156
  types.Resource(
141
157
  uri=AnyUrl("jenkins://error"),
142
158
  name="Error connecting to Jenkins",
143
- description=f"Error: {str(e)}",
159
+ description=f"Error: {str(e)}. Check your configuration and network connection.",
144
160
  mimeType="text/plain",
145
161
  )
146
162
  ]
@@ -1,624 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: jenkins-mcp-server
3
- Version: 1.0.0
4
- Summary: AI-enabled Jenkins automation via Model Context Protocol (MCP)
5
- Author-email: Rishi Bhushan <rishibharat2007@gmail.com>
6
- Maintainer-email: Rishi Bhushan <rishibharat2007@example.com>
7
- License: MIT
8
- Project-URL: Homepage, https://github.com/rishibhushan/jenkins_mcp_server
9
- Project-URL: Documentation, https://github.com/rishibhushan/jenkins_mcp_server#readme
10
- Project-URL: Repository, https://github.com/rishibhushan/jenkins_mcp_server.git
11
- Project-URL: Bug Tracker, https://github.com/rishibhushan/jenkins_mcp_server/issues
12
- Project-URL: Changelog, https://github.com/rishibhushan/jenkins_mcp_server/releases
13
- Keywords: mcp,jenkins,ai,automation,ci-cd,devops,model-context-protocol,llm
14
- Classifier: Development Status :: 4 - Beta
15
- Classifier: Intended Audience :: Developers
16
- Classifier: Intended Audience :: System Administrators
17
- Classifier: License :: OSI Approved :: MIT License
18
- Classifier: Operating System :: OS Independent
19
- Classifier: Programming Language :: Python :: 3
20
- Classifier: Programming Language :: Python :: 3.8
21
- Classifier: Programming Language :: Python :: 3.9
22
- Classifier: Programming Language :: Python :: 3.10
23
- Classifier: Programming Language :: Python :: 3.11
24
- Classifier: Programming Language :: Python :: 3.12
25
- Classifier: Topic :: Software Development :: Build Tools
26
- Classifier: Topic :: System :: Systems Administration
27
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
28
- Requires-Python: >=3.8
29
- Description-Content-Type: text/markdown
30
- Requires-Dist: mcp>=1.0.0
31
- Requires-Dist: python-jenkins>=1.8.0
32
- Requires-Dist: requests>=2.28.0
33
- Requires-Dist: pydantic>=2.0.0
34
- Requires-Dist: pydantic-settings>=2.0.0
35
- Requires-Dist: python-dotenv>=1.0.0
36
- Requires-Dist: urllib3>=2.0.0
37
- Provides-Extra: dev
38
- Requires-Dist: pytest>=7.0.0; extra == "dev"
39
- Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
40
- Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
41
- Requires-Dist: black>=23.0.0; extra == "dev"
42
- Requires-Dist: ruff>=0.1.0; extra == "dev"
43
- Requires-Dist: mypy>=1.0.0; extra == "dev"
44
- Provides-Extra: test
45
- Requires-Dist: pytest>=7.0.0; extra == "test"
46
- Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
47
- Requires-Dist: pytest-cov>=4.0.0; extra == "test"
48
-
49
- # 🧠 Jenkins MCP Server
50
-
51
- **Jenkins MCP Server** is an AI-enabled Model Context Protocol (MCP) server that exposes Jenkins automation through natural-language commands.
52
-
53
- Designed to work seamlessly with automation clients such as:
54
- - 🖥️ **VS Code MCP** - Direct integration with Claude in VS Code
55
- - 🔌 **Any MCP-compatible client** - Universal compatibility
56
-
57
- ## ✨ About codebase
58
-
59
- - ✅ **Codebase** - cleaner, more maintainable
60
- - ✅ **Error messages** - Know exactly what's wrong and how to fix it
61
- - ✅ **Flexible configuration** - Multiple ways to configure (VS Code, .env, environment)
62
- - ✅ **Cross-platform** - Seamless support for Windows, macOS, and Linux
63
- - ✅ **Logging** - Professional logging with `--verbose` flag
64
- - ✅ **Dependency management** - Automatic detection and installation
65
-
66
- ---
67
-
68
- ## 📦 Features
69
-
70
- This project includes:
71
- - 🐍 Python backend powered by `python-jenkins`
72
- - 📦 Node.js `npx` wrapper for zero-install execution
73
- - 🔄 Automatic virtual environment creation + dependency installation
74
- - 🌐 Corporate proxy/certificate auto-detection support
75
- - 🪟 Windows, macOS, and Linux support
76
- - 🛠️ **20 Jenkins management tools**
77
-
78
- ### 🧩 Build Operations
79
- | Tool Name | Description | Required Fields | Optional Fields |
80
- |---|---|---|---|
81
- | `trigger-build` | Trigger a Jenkins job build with optional parameters | `job_name` | `parameters` |
82
- | `stop-build` | Stop a running Jenkins build | `job_name`, `build_number` | *(none)* |
83
-
84
- ### 📊 Job Information
85
- | Tool Name | Description | Required Fields | Optional Fields |
86
- |---|---|---|---|
87
- | `list-jobs` | List all Jenkins jobs with optional filtering | *(none)* | `filter` |
88
- | `get-job-details` | Get detailed information about a Jenkins job | `job_name` | *(none)* |
89
-
90
- ### 🛠️ Build Information
91
- | Tool Name | Description | Required Fields | Optional Fields |
92
- |---|---|---|---|
93
- | `get-build-info` | Get information about a specific build | `job_name`, `build_number` | *(none)* |
94
- | `get-build-console` | Get console output from a build | `job_name`, `build_number` | *(none)* |
95
- | `get-last-build-number` | Get the last build number for a job | `job_name` | *(none)* |
96
- | `get-last-build-timestamp` | Get the timestamp of the last build | `job_name` | *(none)* |
97
-
98
- ### 🧩 Job Management
99
- | Tool Name | Description | Required Fields | Optional Fields |
100
- |---|---|---|---|
101
- | `create-job` | Create a new Jenkins job with XML configuration | `job_name`, `config_xml` | *(none)* |
102
- | `create-job-from-copy` | Create a new job by copying an existing one | `new_job_name`, `source_job_name` | *(none)* |
103
- | `create-job-from-data` | Create a job from structured data (auto-generated XML) | `job_name`, `config_data` | `root_tag` |
104
- | `delete-job` | Delete an existing job | `job_name` | *(none)* |
105
- | `enable-job` | Enable a disabled Jenkins job | `job_name` | *(none)* |
106
- | `disable-job` | Disable a Jenkins job | `job_name` | *(none)* |
107
- | `rename-job` | Rename an existing Jenkins job | `job_name`, `new_name` | *(none)* |
108
-
109
- ### ⚙️ Job Configuration
110
- | Tool Name | Description | Required Fields | Optional Fields |
111
- |---|---|---|---|
112
- | `get-job-config` | Fetch job XML configuration | `job_name` | *(none)* |
113
- | `update-job-config` | Update job XML configuration | `job_name`, `config_xml` | *(none)* |
114
-
115
- ### 🖥️ System Information
116
- | Tool Name | Description | Required Fields | Optional Fields |
117
- |---|---|---|---|
118
- | `get-queue-info` | Get Jenkins build queue info | *(none)* | *(none)* |
119
- | `list-nodes` | List all Jenkins nodes | *(none)* | *(none)* |
120
- | `get-node-info` | Get information about a Jenkins node | `node_name` | *(none)* |
121
-
122
- ---
123
-
124
- ## 🚀 Quick Start
125
-
126
- ### Prerequisites
127
-
128
- **Node.js** (v14 or higher) is required for the npx wrapper.
129
-
130
- <details>
131
- <summary><b>Windows Installation</b></summary>
132
-
133
- ```powershell
134
- # Using winget (recommended)
135
- winget install OpenJS.NodeJS.LTS
136
-
137
- # Verify installation
138
- node -v
139
- npm -v
140
- ```
141
-
142
- Or download manually from https://nodejs.org/
143
- </details>
144
-
145
- <details>
146
- <summary><b>macOS Installation</b></summary>
147
-
148
- ```bash
149
- # Install nvm (Node Version Manager)
150
- curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
151
-
152
- # Reload shell
153
- source ~/.nvm/nvm.sh
154
-
155
- # Install Node LTS
156
- nvm install --lts
157
- nvm use --lts
158
-
159
- # Verify installation
160
- node -v
161
- npm -v
162
- ```
163
- </details>
164
-
165
- <details>
166
- <summary><b>Linux Installation</b></summary>
167
-
168
- ```bash
169
- # Ubuntu/Debian
170
- curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
171
- sudo apt-get install -y nodejs
172
-
173
- # Fedora/RHEL
174
- curl -fsSL https://rpm.nodesource.com/setup_lts.x | sudo bash -
175
- sudo dnf install -y nodejs
176
-
177
- # Verify installation
178
- node -v
179
- npm -v
180
- ```
181
- </details>
182
-
183
- ---
184
-
185
- ## ⚙️ Configuration
186
-
187
- Jenkins MCP Server supports multiple configuration methods. Choose the one that works best for you:
188
-
189
- ### Option 1: VS Code Settings (Recommended)
190
-
191
- Add to your VS Code `settings.json`:
192
-
193
- ```json
194
- {
195
- "jenkins-mcp-server": {
196
- "jenkins": {
197
- "url": "http://jenkins.example.com:8080",
198
- "username": "your-username",
199
- "token": "your-api-token"
200
- }
201
- }
202
- }
203
- ```
204
-
205
- **Where to find settings.json:**
206
- - **Windows**: `%APPDATA%\Code\User\settings.json`
207
- - **macOS**: `~/Library/Application Support/Code/User/settings.json`
208
- - **Linux**: `~/.config/Code/User/settings.json`
209
-
210
- ### Option 2: Environment File (.env)
211
-
212
- Rename `.env.template` to `.env`
213
- ```bash
214
- cp .env.template .env
215
- ```
216
-
217
- In the `.env` file in your project directory:
218
-
219
- ```bash
220
- JENKINS_URL=http://jenkins.example.com:8080
221
- JENKINS_USERNAME=your-username
222
- JENKINS_TOKEN=your-api-token
223
- ```
224
-
225
- **Note**: Use API token instead of password for better security.
226
-
227
- ### Option 3: Environment Variables
228
-
229
- ```bash
230
- # Linux/macOS
231
- export JENKINS_URL=http://jenkins.example.com:8080
232
- export JENKINS_USERNAME=your-username
233
- export JENKINS_TOKEN=your-api-token
234
-
235
- # Windows (PowerShell)
236
- $env:JENKINS_URL="http://jenkins.example.com:8080"
237
- $env:JENKINS_USERNAME="your-username"
238
- $env:JENKINS_TOKEN="your-api-token"
239
- ```
240
-
241
- ### Configuration Priority
242
-
243
- Settings are loaded in this order (later overrides earlier):
244
- 1. Default `.env` file
245
- 2. Environment variables
246
- 3. Custom `.env` file (via `--env-file`)
247
- 4. VS Code settings
248
- 5. Direct parameters
249
-
250
- ### Getting Your Jenkins API Token
251
-
252
- 1. Log into Jenkins
253
- 2. Click your name (top right) → **Configure**
254
- 3. Scroll to **API Token** section
255
- 4. Click **Add new Token**
256
- 5. Give it a name and click **Generate**
257
- 6. Copy the token (⚠️ it won't be shown again!)
258
-
259
- ---
260
-
261
- ## 🚀 Installation/Running the Server
262
-
263
- ### Option 1: Using npx (No Installation Required)
264
- ```bash
265
- npx @rishibhushan/jenkins-mcp-server --env-file .env
266
- ```
267
-
268
- ### Option 2: Global Installation
269
- ```bash
270
- # Install globally
271
- npm install -g @rishibhushan/jenkins-mcp-server
272
-
273
- # Run
274
- jenkins-mcp-server --env-file .env
275
- ```
276
-
277
- ### Option 3: From GitHub
278
- ```bash
279
- npx github:rishibhushan/jenkins_mcp_server --env-file .env
280
- ```
281
-
282
- [//]: # ([![npm version]&#40;https://badge.fury.io/js/jenkins-mcp-server.svg&#41;]&#40;https://www.npmjs.com/package/@rishibhushan/jenkins-mcp-server&#41;)
283
-
284
- [//]: # ([![npm downloads]&#40;https://img.shields.io/npm/dm/jenkins-mcp-server.svg&#41;]&#40;https://www.npmjs.com/package/@rishibhushan/jenkins-mcp-server&#41;)
285
-
286
- ---
287
-
288
- This automatically:
289
- - ✅ Installs all dependencies
290
- - ✅ Starts the Jenkins MCP server
291
-
292
- ### Method 2: Direct Python Execution
293
-
294
- ```bash
295
- # Create virtual environment
296
- python3 -m venv .venv
297
-
298
- # Activate virtual environment
299
- # Linux/macOS:
300
- source .venv/bin/activate
301
- # Windows:
302
- .venv\Scripts\activate
303
-
304
- # Install dependencies
305
- pip install -r requirements.txt
306
-
307
- # Run the server
308
- python -m jenkins_mcp_server --env-file /path/to/.env
309
- ```
310
-
311
- ### Command-Line Options
312
-
313
- ```
314
- jenkins-mcp-server [options]
315
-
316
- Options:
317
- --env-file PATH Path to custom .env file
318
- --verbose, -v Enable verbose/debug logging
319
- --no-vscode Skip loading VS Code settings
320
- --version Show version information
321
- --help, -h Show help message
322
- ```
323
-
324
- ---
325
-
326
- ## 🔌 Integration Examples
327
-
328
- ### VS Code MCP Client
329
-
330
- Add to your VS Code `mcp.json`:
331
-
332
- ```json
333
- {
334
- "servers": {
335
- "jenkins": {
336
- "type": "stdio",
337
- "command": "npx",
338
- "args": [
339
- "@rishibhushan/jenkins-mcp-server"
340
- ]
341
- }
342
- }
343
- }
344
- ```
345
-
346
- Or `setting.json` with `.env` file and proxy settings:
347
- ```json
348
- {
349
- "mcp": {
350
- "servers": {
351
- "jenkins": {
352
- "type": "stdio",
353
- "command": "npx",
354
- "args": [
355
- "@rishibhushan/jenkins-mcp-server",
356
- "--verbose",
357
- "--env-file",
358
- "/path/to/.env"
359
- ],
360
- "env": {
361
- "HTTP_PROXY": "http://proxy.example.com:8080",
362
- "HTTPS_PROXY": "http://proxy.example.com:8080",
363
- "NO_PROXY": "localhost,127.0.0.1,.example.com"
364
- }
365
- }
366
- }
367
- }
368
- }
369
- ```
370
-
371
- ### Claude Desktop
372
-
373
- Add to `claude_desktop_config.json`:
374
-
375
- ```json
376
- {
377
- "mcpServers": {
378
- "jenkins": {
379
- "command": "npx",
380
- "args": [
381
- "@rishibhushan/jenkins-mcp-server",
382
- "--env-file",
383
- "/path/to/.env"
384
- ]
385
- }
386
- }
387
- }
388
- ```
389
-
390
- **Where to find claude_desktop_config.json:**
391
- - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
392
- - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
393
- - **Linux**: `~/.config/Claude/claude_desktop_config.json`
394
-
395
- ---
396
-
397
- ## 💡 Usage Examples
398
-
399
- ### Natural Language Commands
400
-
401
- Once configured, you can use natural language with your MCP client:
402
-
403
- ```
404
- "List all Jenkins jobs"
405
- "List jobs with 'backend' in the name" - # Filter jobs containing "backend"
406
- "Show me all production jobs" - # Filter jobs containing "prod"
407
- "Show me the last build of my-project"
408
- "Trigger a build for deploy-prod with parameter env=production"
409
- "What's in the build queue?"
410
- "Show me the console output of build #42 for backend-service"
411
- "Create a new job called test-job by copying prod-job"
412
- "Disable the old-job"
413
- ```
414
-
415
- ### Programmatic Usage (Python)
416
-
417
- ```python
418
- from config import get_settings
419
- from jenkins_client import get_jenkins_client
420
-
421
- # Load settings
422
- settings = get_settings()
423
-
424
- # Create client
425
- client = get_jenkins_client(settings)
426
-
427
- # List jobs
428
- all_jobs = client.get_jobs()
429
- for job in all_jobs:
430
- print(f"Job: {job['name']} - Status: {job['color']}")
431
-
432
- # Filter in Python
433
- backend_jobs = [job for job in all_jobs if 'backend' in job['name'].lower()]
434
-
435
- # Trigger a build
436
- result = client.build_job(
437
- "my-job",
438
- parameters={"BRANCH": "main", "ENV": "staging"}
439
- )
440
- print(f"Build queued: {result['queue_id']}")
441
- print(f"Build number: {result['build_number']}")
442
-
443
- # Get console output
444
- if result['build_number']:
445
- output = client.get_build_console_output(
446
- "my-job",
447
- result['build_number']
448
- )
449
- print(output)
450
- ```
451
-
452
- ---
453
-
454
- ## 🔧 Troubleshooting
455
-
456
- ### Python Not Found
457
- ```
458
- Error: Python 3 is required but not found.
459
- ```
460
- **Solution**: Install Python 3.8+ from https://www.python.org/downloads/
461
-
462
- ### Configuration Issues
463
- ```
464
- ERROR: Jenkins configuration is incomplete!
465
- ```
466
- **Solution**: Verify you have set `JENKINS_URL`, `JENKINS_USERNAME`, and `JENKINS_TOKEN`
467
-
468
- Check your configuration:
469
- ```bash
470
- # View .env file
471
- cat .env
472
-
473
- # Check environment variables
474
- env | grep JENKINS
475
-
476
- # Check VS Code settings
477
- cat ~/.config/Code/User/settings.json | grep jenkins
478
- ```
479
-
480
- ### Connection Failed
481
- ```
482
- Failed to connect to Jenkins at http://localhost:8080
483
- ```
484
- **Solution**:
485
- 1. Verify Jenkins is running: `curl http://localhost:8080/api/json`
486
- 2. Check firewall settings
487
- 3. Verify URL is correct (include port if needed)
488
- 4. Test authentication credentials
489
-
490
- ### Dependency Installation Failed
491
- ```
492
- Failed to install dependencies
493
- ```
494
- **Solution**:
495
- 1. Check internet connection
496
- 2. If behind a proxy, set `HTTP_PROXY` and `HTTPS_PROXY` environment variables
497
- 3. Try manual installation: `.venv/bin/pip install -r requirements.txt`
498
-
499
- ### Enable Debug Logging
500
-
501
- Run with verbose flag to see detailed logs:
502
- ```bash
503
- jenkins-mcp-server --verbose
504
- ```
505
-
506
- ---
507
-
508
- ## 🧪 Development & Testing
509
-
510
- ### Run Tests
511
- ```bash
512
- # Install test dependencies
513
- pip install pytest pytest-asyncio
514
-
515
- # Run tests
516
- pytest tests/ -v
517
- ```
518
-
519
- ### Build Package
520
- ```bash
521
- # Install build tools
522
- pip install build
523
-
524
- # Build distribution
525
- python -m build
526
-
527
- # This creates:
528
- # - dist/jenkins_mcp_server-1.0.0.tar.gz
529
- # - dist/jenkins_mcp_server-1.0.0-py3-none-any.whl
530
- ```
531
-
532
- ### Local Development
533
- ```bash
534
- # Clone repository
535
- git clone https://github.com/rishibhushan/jenkins_mcp_server.git
536
- cd jenkins_mcp_server
537
-
538
- # Install in editable mode
539
- pip install -e .
540
-
541
- # Make changes, then test
542
- jenkins-mcp-server --verbose
543
- ```
544
-
545
- ---
546
-
547
- ## 📚 Project Structure
548
-
549
- ```
550
- jenkins_mcp_server/
551
- ├── bin/
552
- │ └── jenkins-mcp.js # Node.js wrapper script
553
- ├── src/
554
- │ └── jenkins_mcp_server/
555
- │ ├── __init__.py # Package initialization & main()
556
- │ ├── __main__.py # Entry point for python -m
557
- │ ├── config.py # Configuration management
558
- │ ├── jenkins_client.py # Jenkins API client
559
- │ └── server.py # MCP server implementation
560
- ├── tests/ # Test suite
561
- ├── requirements.txt # Python dependencies
562
- ├── package.json # Node.js configuration
563
- └── README.md # This file
564
- ```
565
-
566
- ---
567
-
568
- ## 🔒 Security Best Practices
569
-
570
- 1. **Never commit `.env` files** - Add to `.gitignore`
571
- 2. **Use API tokens**, not passwords - More secure and revocable
572
- 3. **Rotate tokens regularly** - Generate new tokens periodically
573
- 4. **Use environment-specific configs** - Separate dev/staging/prod credentials
574
- 5. **Review permissions** - Only grant necessary Jenkins permissions
575
- 6. **Keep dependencies updated** - Run `pip install --upgrade -r requirements.txt`
576
-
577
- ---
578
-
579
- ## 🤝 Contributing
580
-
581
- Contributions are welcome! Please feel free to submit a Pull Request.
582
-
583
- 1. Fork the repository
584
- 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
585
- 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
586
- 4. Push to the branch (`git push origin feature/AmazingFeature`)
587
- 5. Open a Pull Request
588
-
589
- ---
590
-
591
- ## 📝 License
592
-
593
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
594
-
595
- ---
596
-
597
- ## 🙏 Acknowledgments
598
-
599
- - Built on the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)
600
- - Powered by [python-jenkins](https://python-jenkins.readthedocs.io/)
601
- - Inspired by the need for AI-powered DevOps automation
602
-
603
- ---
604
-
605
- ## 📞 Support
606
-
607
- - **Issues**: https://github.com/rishibhushan/jenkins_mcp_server/issues
608
- - **Discussions**: https://github.com/rishibhushan/jenkins_mcp_server/discussions
609
-
610
- ---
611
-
612
- ## 🗺️ Roadmap
613
-
614
- - [ ] Add pipeline support
615
- - [ ] Multi-Jenkins instance management
616
- - [ ] Build artifact management
617
- - [ ] Advanced filtering and search
618
- - [ ] Real-time build monitoring
619
- - [ ] Webhook integration
620
- - [ ] Docker container support
621
-
622
- ---
623
-
624
- **Made with ❤️ by [Rishi Bhushan](https://github.com/rishibhushan)**
@@ -1,13 +0,0 @@
1
- README.md
2
- pyproject.toml
3
- src/jenkins_mcp_server/__init__.py
4
- src/jenkins_mcp_server/__main__.py
5
- src/jenkins_mcp_server/config.py
6
- src/jenkins_mcp_server/jenkins_client.py
7
- src/jenkins_mcp_server/server.py
8
- src/jenkins_mcp_server.egg-info/PKG-INFO
9
- src/jenkins_mcp_server.egg-info/SOURCES.txt
10
- src/jenkins_mcp_server.egg-info/dependency_links.txt
11
- src/jenkins_mcp_server.egg-info/entry_points.txt
12
- src/jenkins_mcp_server.egg-info/requires.txt
13
- src/jenkins_mcp_server.egg-info/top_level.txt
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- jenkins-mcp-server = jenkins_mcp_server:main
@@ -1,20 +0,0 @@
1
- mcp>=1.0.0
2
- python-jenkins>=1.8.0
3
- requests>=2.28.0
4
- pydantic>=2.0.0
5
- pydantic-settings>=2.0.0
6
- python-dotenv>=1.0.0
7
- urllib3>=2.0.0
8
-
9
- [dev]
10
- pytest>=7.0.0
11
- pytest-asyncio>=0.21.0
12
- pytest-cov>=4.0.0
13
- black>=23.0.0
14
- ruff>=0.1.0
15
- mypy>=1.0.0
16
-
17
- [test]
18
- pytest>=7.0.0
19
- pytest-asyncio>=0.21.0
20
- pytest-cov>=4.0.0
@@ -1 +0,0 @@
1
- jenkins_mcp_server