harness-mcp-v2 0.5.0 → 0.5.2
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 +62 -40
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/prompts/build-deploy-app.d.ts +3 -0
- package/build/prompts/build-deploy-app.d.ts.map +1 -0
- package/build/prompts/build-deploy-app.js +184 -0
- package/build/prompts/build-deploy-app.js.map +1 -0
- package/build/prompts/feature-flag-rollout.js +1 -1
- package/build/prompts/feature-flag-rollout.js.map +1 -1
- package/build/prompts/index.d.ts.map +1 -1
- package/build/prompts/index.js +4 -0
- package/build/prompts/index.js.map +1 -1
- package/build/prompts/pending-approvals.js +1 -1
- package/build/tools/harness-create.d.ts.map +1 -1
- package/build/tools/harness-create.js +9 -4
- package/build/tools/harness-create.js.map +1 -1
- package/build/tools/harness-delete.d.ts.map +1 -1
- package/build/tools/harness-delete.js +9 -4
- package/build/tools/harness-delete.js.map +1 -1
- package/build/tools/harness-execute.d.ts.map +1 -1
- package/build/tools/harness-execute.js +8 -11
- package/build/tools/harness-execute.js.map +1 -1
- package/build/tools/harness-update.d.ts.map +1 -1
- package/build/tools/harness-update.js +9 -4
- package/build/tools/harness-update.js.map +1 -1
- package/build/utils/elicitation.d.ts +27 -0
- package/build/utils/elicitation.d.ts.map +1 -0
- package/build/utils/elicitation.js +50 -0
- package/build/utils/elicitation.js.map +1 -0
- package/build/utils/errors.js +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
An MCP (Model Context Protocol) server that gives AI agents full access to the Harness.io platform through 10 consolidated tools and 119+ resource types.
|
|
4
4
|
|
|
5
|
-
[](https://github.com/thisrohangupta/harness-mcp-v2/actions/workflows/ci.yml)
|
|
6
6
|
|
|
7
7
|
## Why Use This MCP Server
|
|
8
8
|
|
|
@@ -13,7 +13,7 @@ This server is built differently:
|
|
|
13
13
|
- **10 tools, 119+ resource types.** A registry-based dispatch system routes `harness_list`, `harness_get`, `harness_create`, etc. to any Harness resource — pipelines, services, environments, orgs, projects, feature flags, cost data, and more. The LLM picks from 10 tools instead of hundreds.
|
|
14
14
|
- **Full platform coverage.** 25 toolsets spanning CI/CD, GitOps, Feature Flags, Cloud Cost Management, Security Testing, Chaos Engineering, Internal Developer Portal, Software Supply Chain, and more. Not just pipelines — the entire Harness platform.
|
|
15
15
|
- **Multi-project workflows out of the box.** Agents discover organizations and projects dynamically — no hardcoded env vars needed. Ask "show failed executions across all projects" and the agent can navigate the full account hierarchy.
|
|
16
|
-
- **
|
|
16
|
+
- **26 prompt templates.** Pre-built prompts for common workflows: build & deploy apps end-to-end, debug failed pipelines, review DORA metrics, triage vulnerabilities, optimize cloud costs, audit access control, plan feature flag rollouts, review pull requests, approve pending pipelines, and more.
|
|
17
17
|
- **Works everywhere.** Stdio transport for local clients (Claude Desktop, Cursor, Windsurf), HTTP transport for remote/shared deployments, Docker and Kubernetes ready.
|
|
18
18
|
- **Zero-config start.** Just provide a Harness API key. Account ID is auto-extracted from PAT tokens, org/project defaults are optional, and toolset filtering lets you expose only what you need.
|
|
19
19
|
- **Extensible by design.** Adding a new Harness resource means adding a declarative data file — no new tool registration, no schema changes, no prompt updates.
|
|
@@ -25,17 +25,17 @@ This server is built differently:
|
|
|
25
25
|
No install required — just run it:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
npx harness-
|
|
28
|
+
npx harness-mcp-v2
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
That's it. Pass your Harness API key via environment variable or configure it in your AI client (see [Client Configuration](#client-configuration) below).
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
# Stdio transport (default — for Claude Desktop, Cursor, Windsurf, etc.)
|
|
35
|
-
HARNESS_API_KEY=pat.xxx npx harness-
|
|
35
|
+
HARNESS_API_KEY=pat.xxx npx harness-mcp-v2
|
|
36
36
|
|
|
37
37
|
# HTTP transport (for remote/shared deployments)
|
|
38
|
-
HARNESS_API_KEY=pat.xxx npx harness-
|
|
38
|
+
HARNESS_API_KEY=pat.xxx npx harness-mcp-v2 http --port 8080
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
> **Note:** The account ID is auto-extracted from PAT tokens (`pat.<accountId>.<tokenId>.<secret>`), so `HARNESS_ACCOUNT_ID` is only needed for non-PAT API keys.
|
|
@@ -43,10 +43,10 @@ HARNESS_API_KEY=pat.xxx npx harness-poc-mcp-server http --port 8080
|
|
|
43
43
|
### Option 2: Global Install
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
npm install -g harness-
|
|
46
|
+
npm install -g harness-mcp-v2
|
|
47
47
|
|
|
48
48
|
# Then run directly
|
|
49
|
-
harness-
|
|
49
|
+
harness-mcp-v2
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
### Option 3: Build from Source
|
|
@@ -54,8 +54,8 @@ harness-poc-mcp-server
|
|
|
54
54
|
For development or customization:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
|
-
git clone https://github.com/thisrohangupta/harness-
|
|
58
|
-
cd harness-
|
|
57
|
+
git clone https://github.com/thisrohangupta/harness-mcp-v2.git
|
|
58
|
+
cd harness-mcp-v2
|
|
59
59
|
pnpm install
|
|
60
60
|
pnpm build
|
|
61
61
|
|
|
@@ -68,7 +68,7 @@ pnpm inspect # Test with MCP Inspector
|
|
|
68
68
|
### CLI Usage
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
-
harness-mcp-
|
|
71
|
+
harness-mcp-v2 [stdio|http] [--port <number>]
|
|
72
72
|
|
|
73
73
|
Options:
|
|
74
74
|
--port <number> Port for HTTP transport (default: 3000, or PORT env var)
|
|
@@ -121,7 +121,7 @@ curl -X POST http://localhost:3000/mcp \
|
|
|
121
121
|
"mcpServers": {
|
|
122
122
|
"harness": {
|
|
123
123
|
"command": "npx",
|
|
124
|
-
"args": ["harness-
|
|
124
|
+
"args": ["harness-mcp-v2"],
|
|
125
125
|
"env": {
|
|
126
126
|
"HARNESS_API_KEY": "pat.xxx.xxx.xxx"
|
|
127
127
|
}
|
|
@@ -136,14 +136,14 @@ curl -X POST http://localhost:3000/mcp \
|
|
|
136
136
|
<summary>node (local install)</summary>
|
|
137
137
|
|
|
138
138
|
```bash
|
|
139
|
-
npm install -g harness-
|
|
139
|
+
npm install -g harness-mcp-v2
|
|
140
140
|
```
|
|
141
141
|
|
|
142
142
|
```json
|
|
143
143
|
{
|
|
144
144
|
"mcpServers": {
|
|
145
145
|
"harness": {
|
|
146
|
-
"command": "harness-
|
|
146
|
+
"command": "harness-mcp-v2",
|
|
147
147
|
"env": {
|
|
148
148
|
"HARNESS_API_KEY": "pat.xxx.xxx.xxx"
|
|
149
149
|
}
|
|
@@ -160,7 +160,7 @@ npm install -g harness-poc-mcp-server
|
|
|
160
160
|
<summary>npx (zero install)</summary>
|
|
161
161
|
|
|
162
162
|
```bash
|
|
163
|
-
claude mcp add harness -- npx harness-
|
|
163
|
+
claude mcp add harness -- npx harness-mcp-v2
|
|
164
164
|
```
|
|
165
165
|
|
|
166
166
|
</details>
|
|
@@ -169,8 +169,8 @@ claude mcp add harness -- npx harness-poc-mcp-server
|
|
|
169
169
|
<summary>node (local install)</summary>
|
|
170
170
|
|
|
171
171
|
```bash
|
|
172
|
-
npm install -g harness-
|
|
173
|
-
claude mcp add harness -- harness-
|
|
172
|
+
npm install -g harness-mcp-v2
|
|
173
|
+
claude mcp add harness -- harness-mcp-v2
|
|
174
174
|
```
|
|
175
175
|
|
|
176
176
|
</details>
|
|
@@ -187,7 +187,7 @@ Then set `HARNESS_API_KEY` in your environment or `.env` file.
|
|
|
187
187
|
"mcpServers": {
|
|
188
188
|
"harness": {
|
|
189
189
|
"command": "npx",
|
|
190
|
-
"args": ["harness-
|
|
190
|
+
"args": ["harness-mcp-v2"],
|
|
191
191
|
"env": {
|
|
192
192
|
"HARNESS_API_KEY": "pat.xxx.xxx.xxx"
|
|
193
193
|
}
|
|
@@ -202,14 +202,14 @@ Then set `HARNESS_API_KEY` in your environment or `.env` file.
|
|
|
202
202
|
<summary>node (local install)</summary>
|
|
203
203
|
|
|
204
204
|
```bash
|
|
205
|
-
npm install -g harness-
|
|
205
|
+
npm install -g harness-mcp-v2
|
|
206
206
|
```
|
|
207
207
|
|
|
208
208
|
```json
|
|
209
209
|
{
|
|
210
210
|
"mcpServers": {
|
|
211
211
|
"harness": {
|
|
212
|
-
"command": "harness-
|
|
212
|
+
"command": "harness-mcp-v2",
|
|
213
213
|
"env": {
|
|
214
214
|
"HARNESS_API_KEY": "pat.xxx.xxx.xxx"
|
|
215
215
|
}
|
|
@@ -230,7 +230,7 @@ npm install -g harness-poc-mcp-server
|
|
|
230
230
|
"mcpServers": {
|
|
231
231
|
"harness": {
|
|
232
232
|
"command": "npx",
|
|
233
|
-
"args": ["harness-
|
|
233
|
+
"args": ["harness-mcp-v2"],
|
|
234
234
|
"env": {
|
|
235
235
|
"HARNESS_API_KEY": "pat.xxx.xxx.xxx"
|
|
236
236
|
}
|
|
@@ -245,14 +245,14 @@ npm install -g harness-poc-mcp-server
|
|
|
245
245
|
<summary>node (local install)</summary>
|
|
246
246
|
|
|
247
247
|
```bash
|
|
248
|
-
npm install -g harness-
|
|
248
|
+
npm install -g harness-mcp-v2
|
|
249
249
|
```
|
|
250
250
|
|
|
251
251
|
```json
|
|
252
252
|
{
|
|
253
253
|
"mcpServers": {
|
|
254
254
|
"harness": {
|
|
255
|
-
"command": "harness-
|
|
255
|
+
"command": "harness-mcp-v2",
|
|
256
256
|
"env": {
|
|
257
257
|
"HARNESS_API_KEY": "pat.xxx.xxx.xxx"
|
|
258
258
|
}
|
|
@@ -271,7 +271,7 @@ Replace the command with the path to your built `index.js`:
|
|
|
271
271
|
```json
|
|
272
272
|
{
|
|
273
273
|
"command": "node",
|
|
274
|
-
"args": ["/absolute/path/to/harness-
|
|
274
|
+
"args": ["/absolute/path/to/harness-mcp-v2/build/index.js", "stdio"]
|
|
275
275
|
}
|
|
276
276
|
```
|
|
277
277
|
|
|
@@ -296,7 +296,7 @@ Register the server in your Docker MCP Gateway configuration:
|
|
|
296
296
|
"mcpServers": {
|
|
297
297
|
"harness": {
|
|
298
298
|
"command": "npx",
|
|
299
|
-
"args": ["harness-
|
|
299
|
+
"args": ["harness-mcp-v2"],
|
|
300
300
|
"env": {
|
|
301
301
|
"HARNESS_API_KEY": "pat.xxx.xxx.xxx"
|
|
302
302
|
}
|
|
@@ -314,7 +314,7 @@ Add the Harness MCP server to your [Portkey MCP Gateway](https://portkey.ai/feat
|
|
|
314
314
|
"mcpServers": {
|
|
315
315
|
"harness": {
|
|
316
316
|
"command": "npx",
|
|
317
|
-
"args": ["harness-
|
|
317
|
+
"args": ["harness-mcp-v2"],
|
|
318
318
|
"env": {
|
|
319
319
|
"HARNESS_API_KEY": "pat.xxx.xxx.xxx"
|
|
320
320
|
}
|
|
@@ -332,7 +332,7 @@ mcp_servers:
|
|
|
332
332
|
- name: harness
|
|
333
333
|
command: npx
|
|
334
334
|
args:
|
|
335
|
-
- harness-
|
|
335
|
+
- harness-mcp-v2
|
|
336
336
|
env:
|
|
337
337
|
HARNESS_API_KEY: "pat.xxx.xxx.xxx"
|
|
338
338
|
```
|
|
@@ -343,7 +343,7 @@ The server works with [Envoy AI Gateway's MCP support](https://aigateway.envoypr
|
|
|
343
343
|
|
|
344
344
|
```bash
|
|
345
345
|
# Start the server in HTTP mode
|
|
346
|
-
HARNESS_API_KEY=pat.xxx.xxx.xxx npx harness-
|
|
346
|
+
HARNESS_API_KEY=pat.xxx.xxx.xxx npx harness-mcp-v2 http --port 8080
|
|
347
347
|
```
|
|
348
348
|
|
|
349
349
|
Then configure Envoy to route to `http://localhost:8080/mcp` as an upstream MCP backend.
|
|
@@ -423,10 +423,10 @@ The server exposes 10 MCP tools. Every tool accepts `org_id` and `project_id` as
|
|
|
423
423
|
| `harness_describe` | Discover available resource types, operations, and fields. No API call — returns local registry metadata. |
|
|
424
424
|
| `harness_list` | List resources of a given type with filtering, search, and pagination. |
|
|
425
425
|
| `harness_get` | Get a single resource by its identifier. |
|
|
426
|
-
| `harness_create` | Create a new resource.
|
|
427
|
-
| `harness_update` | Update an existing resource.
|
|
428
|
-
| `harness_delete` | Delete a resource.
|
|
429
|
-
| `harness_execute` | Execute an action on a resource (run pipeline, toggle flag, sync app).
|
|
426
|
+
| `harness_create` | Create a new resource. Prompts for user confirmation via [elicitation](#elicitation). |
|
|
427
|
+
| `harness_update` | Update an existing resource. Prompts for user confirmation via [elicitation](#elicitation). |
|
|
428
|
+
| `harness_delete` | Delete a resource. Prompts for user confirmation via [elicitation](#elicitation). Destructive. |
|
|
429
|
+
| `harness_execute` | Execute an action on a resource (run pipeline, toggle flag, sync app). Prompts for user confirmation via [elicitation](#elicitation). |
|
|
430
430
|
| `harness_search` | Search across multiple resource types in parallel with a single query. |
|
|
431
431
|
| `harness_diagnose` | Aggregate execution details, pipeline YAML, and logs into a single diagnostic payload. |
|
|
432
432
|
| `harness_status` | Get a real-time project health dashboard — recent executions, failure rates, and deep links. |
|
|
@@ -470,7 +470,6 @@ The server exposes 10 MCP tools. Every tool accepts `org_id` and `project_id` as
|
|
|
470
470
|
"resource_type": "pipeline",
|
|
471
471
|
"action": "run",
|
|
472
472
|
"resource_id": "my-pipeline",
|
|
473
|
-
"confirmation": true,
|
|
474
473
|
"inputs": { "tag": "v1.2.3" }
|
|
475
474
|
}
|
|
476
475
|
```
|
|
@@ -483,8 +482,7 @@ The server exposes 10 MCP tools. Every tool accepts `org_id` and `project_id` as
|
|
|
483
482
|
"action": "toggle",
|
|
484
483
|
"resource_id": "new_checkout_flow",
|
|
485
484
|
"enable": true,
|
|
486
|
-
"environment": "production"
|
|
487
|
-
"confirmation": true
|
|
485
|
+
"environment": "production"
|
|
488
486
|
}
|
|
489
487
|
```
|
|
490
488
|
|
|
@@ -511,8 +509,7 @@ The server exposes 10 MCP tools. Every tool accepts `org_id` and `project_id` as
|
|
|
511
509
|
```json
|
|
512
510
|
{
|
|
513
511
|
"resource_type": "connector",
|
|
514
|
-
"body": { "connector": { "name": "My Docker Hub", "identifier": "my_docker", "type": "DockerRegistry" } }
|
|
515
|
-
"confirmation": true
|
|
512
|
+
"body": { "connector": { "name": "My Docker Hub", "identifier": "my_docker", "type": "DockerRegistry" } }
|
|
516
513
|
}
|
|
517
514
|
```
|
|
518
515
|
|
|
@@ -522,8 +519,7 @@ The server exposes 10 MCP tools. Every tool accepts `org_id` and `project_id` as
|
|
|
522
519
|
{
|
|
523
520
|
"resource_type": "trigger",
|
|
524
521
|
"resource_id": "nightly-trigger",
|
|
525
|
-
"pipeline_id": "my-pipeline"
|
|
526
|
-
"confirmation": true
|
|
522
|
+
"pipeline_id": "my-pipeline"
|
|
527
523
|
}
|
|
528
524
|
```
|
|
529
525
|
|
|
@@ -785,6 +781,7 @@ The server exposes 10 MCP tools. Every tool accepts `org_id` and `project_id` as
|
|
|
785
781
|
|
|
786
782
|
| Prompt | Description | Parameters |
|
|
787
783
|
|--------|-------------|------------|
|
|
784
|
+
| `build-deploy-app` | End-to-end CI/CD workflow: scan a git repo, generate CI pipeline (build & push Docker image), discover or generate K8s manifests, create CD pipeline, and deploy — with auto-retry on CI failures (up to 5 attempts) and CD failures (up to 3 attempts with user permission). On exhausted retries, provides Harness UI deep links to all created resources for manual investigation. | `repoUrl` (required), `imageName` (required), `projectId` (optional), `namespace` (optional) |
|
|
788
785
|
| `debug-pipeline-failure` | Analyze a failed execution: gathers execution details, pipeline YAML, and logs, then provides root cause analysis and suggested fixes | `executionId` (required), `projectId` (optional) |
|
|
789
786
|
| `create-pipeline` | Generate a new pipeline YAML from natural language requirements, reviewing existing resources for context | `description` (required), `projectId` (optional) |
|
|
790
787
|
| `onboard-service` | Walk through onboarding a new service with environments and a deployment pipeline | `serviceName` (required), `projectId` (optional) |
|
|
@@ -1018,6 +1015,7 @@ src/
|
|
|
1018
1015
|
pipeline-yaml.ts
|
|
1019
1016
|
execution-summary.ts
|
|
1020
1017
|
prompts/ # MCP prompt templates
|
|
1018
|
+
build-deploy-app.ts # DevOps: end-to-end build & deploy workflow
|
|
1021
1019
|
debug-pipeline.ts # DevOps: debug failed executions
|
|
1022
1020
|
create-pipeline.ts # DevOps: generate pipeline from requirements
|
|
1023
1021
|
onboard-service.ts # DevOps: onboard new service
|
|
@@ -1042,10 +1040,12 @@ src/
|
|
|
1042
1040
|
code-review.ts # Harness Code: PR code review
|
|
1043
1041
|
pr-summary.ts # Harness Code: auto-generate PR summary
|
|
1044
1042
|
branch-cleanup.ts # Harness Code: stale branch cleanup
|
|
1043
|
+
pending-approvals.ts # Approvals: find and act on pending approvals
|
|
1045
1044
|
utils/
|
|
1046
1045
|
cli.ts # CLI arg parsing (transport, port)
|
|
1047
1046
|
errors.ts # Error normalization
|
|
1048
1047
|
logger.ts # stderr-only logger
|
|
1048
|
+
progress.ts # MCP progress & logging notifications
|
|
1049
1049
|
rate-limiter.ts # Client-side rate limiting
|
|
1050
1050
|
deep-links.ts # Harness UI deep link builder
|
|
1051
1051
|
response-formatter.ts # Consistent MCP response formatting
|
|
@@ -1060,10 +1060,32 @@ tests/
|
|
|
1060
1060
|
registry.test.ts # Registry loading, filtering, dispatch tests
|
|
1061
1061
|
```
|
|
1062
1062
|
|
|
1063
|
+
## Elicitation
|
|
1064
|
+
|
|
1065
|
+
Write tools (`harness_create`, `harness_update`, `harness_delete`, `harness_execute`) use [MCP elicitation](https://modelcontextprotocol.io/specification/2025-03-26/server/utilities/elicitation) to prompt the user for confirmation before making changes. This gives real human-in-the-loop approval — the user sees what's about to happen and accepts or declines.
|
|
1066
|
+
|
|
1067
|
+
**How it works:**
|
|
1068
|
+
|
|
1069
|
+
1. The LLM calls a write tool (e.g. `harness_create` with a pipeline body)
|
|
1070
|
+
2. The server sends an elicitation request to the client with a summary of the operation
|
|
1071
|
+
3. The user sees the details and clicks **Accept** or **Decline**
|
|
1072
|
+
4. If accepted, the operation proceeds. If declined, it's blocked and the LLM is told
|
|
1073
|
+
|
|
1074
|
+
**Client support:**
|
|
1075
|
+
|
|
1076
|
+
| Client | Elicitation Support |
|
|
1077
|
+
|--------|-------------------|
|
|
1078
|
+
| Cursor | Yes |
|
|
1079
|
+
| Claude Desktop | Not yet |
|
|
1080
|
+
| Windsurf | Not yet |
|
|
1081
|
+
| MCP Inspector | Yes |
|
|
1082
|
+
|
|
1083
|
+
For clients that don't support elicitation, the server proceeds directly — the LLM already chose to call the tool, so its intent is trusted. As more clients add elicitation support, users will automatically get the confirmation dialog without any server changes.
|
|
1084
|
+
|
|
1063
1085
|
## Safety
|
|
1064
1086
|
|
|
1065
1087
|
- **Secrets are never exposed.** The `secret` resource type returns metadata only (name, type, scope) — secret values are never included in any response.
|
|
1066
|
-
- **Write operations
|
|
1088
|
+
- **Write operations prompt for confirmation.** `harness_create`, `harness_update`, `harness_delete`, and `harness_execute` use MCP elicitation to get user approval before proceeding (see [Elicitation](#elicitation)).
|
|
1067
1089
|
- **Rate limiting.** The client enforces a 10 requests/second limit to avoid hitting Harness API rate limits.
|
|
1068
1090
|
- **Retries with backoff.** Transient failures (HTTP 429, 5xx) are retried with exponential backoff and jitter.
|
|
1069
1091
|
- **No stdout logging.** All logs go to stderr to avoid corrupting the stdio JSON-RPC transport.
|
|
@@ -1078,7 +1100,7 @@ tests/
|
|
|
1078
1100
|
| HTTP `Invalid request` | Invalid JSON body or request body exceeded `HARNESS_MAX_BODY_SIZE_MB` | Validate JSON payload size/shape; increase `HARNESS_MAX_BODY_SIZE_MB` if needed |
|
|
1079
1101
|
| `Unknown resource_type "..."` from tools | Resource type is misspelled or filtered out via `HARNESS_TOOLSETS` | Call `harness_describe` (with optional `search_term`) to discover valid types |
|
|
1080
1102
|
| `Missing required field "... for path parameter ..."` | A project/org scoped call is missing identifiers | Set `HARNESS_DEFAULT_ORG_ID`/`HARNESS_DEFAULT_PROJECT_ID` or pass `org_id`/`project_id` per tool call |
|
|
1081
|
-
| `
|
|
1103
|
+
| `Operation declined by user` | User declined the elicitation confirmation dialog | The user chose not to proceed — verify the operation details and retry if intended |
|
|
1082
1104
|
| `body.template_yaml (or body.yaml) is required` for template create/update | Template APIs expect full YAML payload | Provide full `template_yaml` string in `body`; for deletes, pass `version_label` to delete one version (omit to delete all versions) |
|
|
1083
1105
|
|
|
1084
1106
|
## License
|
package/build/index.js
CHANGED
|
@@ -44,7 +44,7 @@ async function startStdio(config) {
|
|
|
44
44
|
* when bound to localhost (validates Host header against allowed hostnames).
|
|
45
45
|
*/
|
|
46
46
|
async function startHttp(config, port) {
|
|
47
|
-
const host = "127.0.0.1";
|
|
47
|
+
const host = process.env.HOST || "127.0.0.1";
|
|
48
48
|
const app = createMcpExpressApp({ host });
|
|
49
49
|
const maxBodySize = config.HARNESS_MAX_BODY_SIZE_MB * 1024 * 1024;
|
|
50
50
|
// Override the default express.json() limit to match our config
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAClF,OAAO,EAAE,UAAU,EAAe,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAEjC;;GAEG;AACH,SAAS,mBAAmB,CAAC,MAAc;IACzC,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,oCAAoC,EAAE,CAAC;QACtD,UAAU,EAAE,oBAAoB;KACjC,EACD,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,CAClC,CAAC;IAEF,gBAAgB,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,oBAAoB,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE3B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,UAAU,CAAC,MAAc;IACtC,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,GAAG,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,SAAS,CAAC,MAAc,EAAE,IAAY;IACnD,MAAM,IAAI,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-deploy-app.d.ts","sourceRoot":"","sources":["../../src/prompts/build-deploy-app.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0LpE"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import * as z from "zod/v4";
|
|
2
|
+
export function registerBuildDeployAppPrompt(server) {
|
|
3
|
+
server.prompt("build-deploy-app", "End-to-end workflow: scan a repo, generate CI/CD pipelines in Harness, build a Docker image, generate K8s manifests, and deploy", {
|
|
4
|
+
repoUrl: z.string().describe("Git repository URL (e.g. https://github.com/org/repo)"),
|
|
5
|
+
imageName: z.string().describe("Docker image name including registry (e.g. docker.io/myorg/myapp)"),
|
|
6
|
+
projectId: z.string().describe("Harness project identifier").optional(),
|
|
7
|
+
namespace: z.string().describe("Kubernetes namespace for deployment").optional(),
|
|
8
|
+
}, async ({ repoUrl, imageName, projectId, namespace }) => ({
|
|
9
|
+
messages: [{
|
|
10
|
+
role: "user",
|
|
11
|
+
content: {
|
|
12
|
+
type: "text",
|
|
13
|
+
text: `Build and deploy the application from "${repoUrl}" through Harness CI/CD.
|
|
14
|
+
|
|
15
|
+
Docker image: ${imageName}
|
|
16
|
+
${projectId ? `Project: ${projectId}` : ""}
|
|
17
|
+
${namespace ? `K8s namespace: ${namespace}` : "K8s namespace: default"}
|
|
18
|
+
|
|
19
|
+
IMPORTANT: Follow these steps IN ORDER. Complete each step before moving to the next.
|
|
20
|
+
Present the full plan and generated YAML for review before creating anything.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Phase 1: Local Discovery (no MCP tools)
|
|
25
|
+
|
|
26
|
+
### Step 0 — Clone & verify the repo
|
|
27
|
+
- Clone "${repoUrl}" locally (or git pull if already cloned)
|
|
28
|
+
- Run \`ls -la\` to inspect the project structure
|
|
29
|
+
|
|
30
|
+
### Step 1 — Scan for Dockerfile
|
|
31
|
+
- Look for a Dockerfile (or Dockerfile.*) in the repo root and subdirectories
|
|
32
|
+
- If no Dockerfile exists: analyze the codebase (language, framework, dependencies) and generate an optimized multi-stage Dockerfile. Commit it to the repo.
|
|
33
|
+
- If a Dockerfile exists: read it and verify it follows best practices (multi-stage build, non-root user, .dockerignore)
|
|
34
|
+
|
|
35
|
+
### Step 2 — Analyze the application
|
|
36
|
+
- Identify the language/framework, exposed ports, environment variables, and health check endpoints
|
|
37
|
+
- Note any databases or external services the app depends on
|
|
38
|
+
- This context is needed for K8s manifest generation in Phase 3
|
|
39
|
+
|
|
40
|
+
### Step 3 — Scan for existing Kubernetes manifests
|
|
41
|
+
- Search the repo for existing K8s manifests: look in \`k8s/\`, \`kubernetes/\`, \`deploy/\`, \`manifests/\`, \`helm/\`, \`.k8s/\`, or any \`*.yaml\`/\`*.yml\` files containing \`apiVersion\` and \`kind: Deployment\`
|
|
42
|
+
- If manifests exist: note their paths — these will be referenced by the Harness service definition in Phase 3
|
|
43
|
+
- If no manifests exist: flag that we need to generate them in Phase 3
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Phase 2: CI Pipeline — Build & Push (MCP tools)
|
|
48
|
+
|
|
49
|
+
### Step 4 — Check existing Harness resources
|
|
50
|
+
- Call harness_list with resource_type="connector"${projectId ? ` and project_id="${projectId}"` : ""} to find existing Docker registry and Git connectors
|
|
51
|
+
- Call harness_list with resource_type="service"${projectId ? ` and project_id="${projectId}"` : ""} to check if this service already exists
|
|
52
|
+
- Call harness_list with resource_type="environment"${projectId ? ` and project_id="${projectId}"` : ""} to see available environments
|
|
53
|
+
- Call harness_describe with resource_type="pipeline" to understand the pipeline schema
|
|
54
|
+
|
|
55
|
+
### Step 5 — Ensure connectors exist
|
|
56
|
+
- If no Docker registry connector exists: generate connector YAML for DockerHub (or the registry in "${imageName}") and present it for review
|
|
57
|
+
- If no Git connector exists for "${repoUrl}": generate a Git connector YAML and present it for review
|
|
58
|
+
- Create any missing connectors using harness_create with resource_type="connector" (only after user confirmation)
|
|
59
|
+
|
|
60
|
+
### Step 6 — Generate CI pipeline YAML
|
|
61
|
+
Generate a Harness CI pipeline that:
|
|
62
|
+
- Clones "${repoUrl}" using the Git connector
|
|
63
|
+
- Builds the Docker image from the Dockerfile found in Step 1
|
|
64
|
+
- Tags the image as "${imageName}:<+pipeline.sequenceId>"
|
|
65
|
+
- Pushes to the Docker registry using the Docker connector
|
|
66
|
+
- Includes a build test step if the repo has tests (e.g. npm test, go test, pytest)
|
|
67
|
+
|
|
68
|
+
Present the full pipeline YAML for review. Do NOT create it yet.
|
|
69
|
+
|
|
70
|
+
### Step 7 — Create & execute CI pipeline (with auto-retry)
|
|
71
|
+
- After user confirms the YAML, create it using harness_create with resource_type="pipeline"
|
|
72
|
+
- Execute it using harness_execute with resource_type="pipeline"
|
|
73
|
+
- Monitor progress using harness_status — poll until the execution completes or fails
|
|
74
|
+
|
|
75
|
+
**CI FAILURE RETRY LOOP (up to 5 attempts):**
|
|
76
|
+
If the CI pipeline fails:
|
|
77
|
+
1. Call harness_get to retrieve the full execution details and logs
|
|
78
|
+
2. Analyze the failure — identify the root cause (build error, test failure, Dockerfile issue, dependency problem, etc.)
|
|
79
|
+
3. Fix the issue locally:
|
|
80
|
+
- If it's a code/Dockerfile/config issue: edit the file in the repo, commit, and push the fix
|
|
81
|
+
- If it's a pipeline YAML issue: update the pipeline using harness_update with resource_type="pipeline"
|
|
82
|
+
- If it's a connector/credential issue: flag it to the user with a link to the connector in Harness
|
|
83
|
+
4. Re-execute the pipeline using harness_execute
|
|
84
|
+
5. Monitor again with harness_status
|
|
85
|
+
6. Repeat this loop up to 5 total attempts
|
|
86
|
+
|
|
87
|
+
If still failing after 5 attempts:
|
|
88
|
+
- Summarize all 5 failure reasons and the fixes attempted
|
|
89
|
+
- Provide Harness UI deep links to the pipeline and latest execution
|
|
90
|
+
- Say: "The CI build has failed 5 times. You may need to manually investigate. Here are links to the resources in Harness:"
|
|
91
|
+
- List all created resource links (pipeline, connectors, etc.)
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Phase 3: CD Pipeline — K8s Manifests & Deploy (MCP tools + local)
|
|
96
|
+
|
|
97
|
+
### Step 8 — Prepare Kubernetes manifests
|
|
98
|
+
**If manifests were found in Step 3:**
|
|
99
|
+
- Read and review the existing manifests
|
|
100
|
+
- Verify the image reference can be parameterized for Harness (e.g. \`${imageName}:<+artifact.tag>\`)
|
|
101
|
+
- Update the image field if needed, commit and push
|
|
102
|
+
|
|
103
|
+
**If no manifests were found in Step 3:**
|
|
104
|
+
- Generate K8s manifests based on the app analysis from Step 2:
|
|
105
|
+
- **Deployment**: with image "${imageName}:<+artifact.tag>", correct ports, resource requests/limits, liveness/readiness probes, and environment variables
|
|
106
|
+
- **Service**: ClusterIP or LoadBalancer matching the exposed ports
|
|
107
|
+
- **ConfigMap/Secret**: for any environment variables the app needs (secret values as placeholders only)
|
|
108
|
+
- Save the manifests in a \`k8s/\` directory in the repo
|
|
109
|
+
- Commit and push the manifests to the repo
|
|
110
|
+
- Present all manifests for review
|
|
111
|
+
|
|
112
|
+
### Step 9 — Create Harness service & environment
|
|
113
|
+
- Create (or update) a Harness service definition that references the K8s manifests from the repo:
|
|
114
|
+
- Service type: Kubernetes
|
|
115
|
+
- Manifest source: the Git connector from Step 5 pointing to the manifest path in the repo
|
|
116
|
+
- Artifact source: the Docker registry connector pointing to "${imageName}"
|
|
117
|
+
- Ensure a target environment exists (or create one) for the ${namespace || "default"} namespace
|
|
118
|
+
- Present the service and environment YAML for review before creating
|
|
119
|
+
|
|
120
|
+
### Step 10 — Generate CD pipeline YAML
|
|
121
|
+
Generate a Harness CD pipeline that:
|
|
122
|
+
- References the service and environment from Step 9
|
|
123
|
+
- Uses a Kubernetes deployment type
|
|
124
|
+
- Uses a Rolling deployment strategy
|
|
125
|
+
- Includes infrastructure definition targeting the ${namespace || "default"} namespace
|
|
126
|
+
- Includes a Verify step or health check after deployment
|
|
127
|
+
|
|
128
|
+
Present the full pipeline YAML for review. Do NOT create it yet.
|
|
129
|
+
|
|
130
|
+
### Step 11 — Create & execute CD pipeline (with auto-retry)
|
|
131
|
+
- After user confirms, create the CD pipeline using harness_create with resource_type="pipeline"
|
|
132
|
+
- Execute it using harness_execute with resource_type="pipeline"
|
|
133
|
+
- Monitor with harness_status — poll until the execution completes or fails
|
|
134
|
+
|
|
135
|
+
**CD FAILURE RETRY LOOP (up to 3 attempts):**
|
|
136
|
+
If the CD pipeline fails:
|
|
137
|
+
1. Call harness_get to retrieve execution details and deployment logs
|
|
138
|
+
2. Analyze the failure — identify root cause (manifest error, image pull failure, resource quota, RBAC, health check timeout, etc.)
|
|
139
|
+
3. Determine the fix:
|
|
140
|
+
- If it's a manifest issue: fix the K8s manifests in the repo, commit and push
|
|
141
|
+
- If it's a pipeline/infrastructure issue: update the pipeline using harness_update
|
|
142
|
+
- If it's a Harness configuration issue (connector, delegate, permissions): explain the issue clearly
|
|
143
|
+
4. Ask the user for permission to retry: "Deployment failed due to [reason]. I've applied [fix]. May I retry?"
|
|
144
|
+
5. On approval, re-execute the pipeline and monitor again
|
|
145
|
+
6. Repeat up to 3 total attempts
|
|
146
|
+
|
|
147
|
+
If still failing after 3 attempts:
|
|
148
|
+
- Summarize all failure reasons and fixes attempted
|
|
149
|
+
- Provide Harness UI deep links to ALL created resources:
|
|
150
|
+
- CI pipeline + latest execution
|
|
151
|
+
- CD pipeline + latest execution
|
|
152
|
+
- Service definition
|
|
153
|
+
- Environment
|
|
154
|
+
- Connectors
|
|
155
|
+
- Say: "The deployment has failed 3 times. You may need to manually update some configuration in Harness. Here are links to all the resources that were created:"
|
|
156
|
+
- List every resource with its Harness UI link
|
|
157
|
+
- Say: "Once you've resolved the issue in Harness, you can re-run this workflow to try again."
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
### Step 12 — Success: Verify & report
|
|
162
|
+
- Confirm the deployment succeeded via harness_status
|
|
163
|
+
- Call harness_get to retrieve final execution details
|
|
164
|
+
- Display a summary:
|
|
165
|
+
- CI: execution status, image tag pushed, build duration
|
|
166
|
+
- CD: execution status, deployment details, namespace
|
|
167
|
+
- Links: Harness UI links to both pipelines, service, and environment
|
|
168
|
+
- App URL: if determinable from the K8s service (LoadBalancer IP/hostname)
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
CRITICAL RULES:
|
|
173
|
+
- Do NOT create any resource (connector, pipeline, service) without showing the YAML and getting user confirmation first
|
|
174
|
+
- Do NOT skip steps — complete each one before proceeding
|
|
175
|
+
- On CI failure: auto-retry up to 5 times, fixing issues between each attempt
|
|
176
|
+
- On CD failure: analyze, fix, ask permission, retry up to 3 times
|
|
177
|
+
- After exhausting retries: provide Harness UI deep links to all created resources so the user can investigate manually
|
|
178
|
+
- Use existing connectors/services/environments when available — do not duplicate them
|
|
179
|
+
- Always reference existing K8s manifests from the repo when available — only generate new ones if none exist`,
|
|
180
|
+
},
|
|
181
|
+
}],
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=build-deploy-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-deploy-app.js","sourceRoot":"","sources":["../../src/prompts/build-deploy-app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAG5B,MAAM,UAAU,4BAA4B,CAAC,MAAiB;IAC5D,MAAM,CAAC,MAAM,CACX,kBAAkB,EAClB,iIAAiI,EACjI;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;QACrF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mEAAmE,CAAC;QACnG,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC,QAAQ,EAAE;QACvE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC,CAAC,QAAQ,EAAE;KACjF,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QACvD,QAAQ,EAAE,CAAC;gBACT,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,0CAA0C,OAAO;;gBAEjD,SAAS;EACvB,SAAS,CAAC,CAAC,CAAC,YAAY,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE;EACxC,SAAS,CAAC,CAAC,CAAC,kBAAkB,SAAS,EAAE,CAAC,CAAC,CAAC,wBAAwB;;;;;;;;;;WAU3D,OAAO;;;;;;;;;;;;;;;;;;;;;;;oDAuBkC,SAAS,CAAC,CAAC,CAAC,oBAAoB,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE;kDACnD,SAAS,CAAC,CAAC,CAAC,oBAAoB,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE;sDAC7C,SAAS,CAAC,CAAC,CAAC,oBAAoB,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE;;;;uGAIA,SAAS;oCAC5E,OAAO;;;;;YAK/B,OAAO;;uBAEI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wEAoCwC,SAAS;;;;;kCAK/C,SAAS;;;;;;;;;;;kEAWuB,SAAS;+DACZ,SAAS,IAAI,SAAS;;;;;;;;qDAQhC,SAAS,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8GAsDmC;iBACrG;aACF,CAAC;KACH,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -26,7 +26,7 @@ Steps:
|
|
|
26
26
|
6. **Safety gates**: Identify metrics or health checks between each phase
|
|
27
27
|
7. **Rollback plan**: Define conditions that trigger automatic rollback
|
|
28
28
|
|
|
29
|
-
Present the rollout plan for review. Use harness_execute with resource_type="feature_flag", action="toggle" to execute each phase
|
|
29
|
+
Present the rollout plan for review. Use harness_execute with resource_type="feature_flag", action="toggle" to execute each phase after user approval.`,
|
|
30
30
|
},
|
|
31
31
|
}],
|
|
32
32
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-flag-rollout.js","sourceRoot":"","sources":["../../src/prompts/feature-flag-rollout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAG5B,MAAM,UAAU,gCAAgC,CAAC,MAAiB;IAChE,MAAM,CAAC,MAAM,CACX,sBAAsB,EACtB,yEAAyE,EACzE;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;QAC1E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,QAAQ,EAAE;KAChE,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,EAAE,EAAE;QACtC,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,CAAC,iBAAiB,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,IAAI,EAAE,MAAe;oBACrB,OAAO,EAAE;wBACP,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,gDAAgD,cAAc;;;4FAGY,cAAc,IAAI,aAAa;kFACzC,aAAa;+EAChB,aAAa;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"feature-flag-rollout.js","sourceRoot":"","sources":["../../src/prompts/feature-flag-rollout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAG5B,MAAM,UAAU,gCAAgC,CAAC,MAAiB;IAChE,MAAM,CAAC,MAAM,CACX,sBAAsB,EACtB,yEAAyE,EACzE;QACE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;QAC1E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,QAAQ,EAAE;KAChE,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,EAAE,EAAE;QACtC,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,CAAC,iBAAiB,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,IAAI,EAAE,MAAe;oBACrB,OAAO,EAAE;wBACP,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,gDAAgD,cAAc;;;4FAGY,cAAc,IAAI,aAAa;kFACzC,aAAa;+EAChB,aAAa;;;;;;;;;;;uJAW2D;qBAC5I;iBACF,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAyCzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwC1D"}
|
package/build/prompts/index.js
CHANGED
|
@@ -28,6 +28,8 @@ import { registerPrSummaryPrompt } from "./pr-summary.js";
|
|
|
28
28
|
import { registerBranchCleanupPrompt } from "./branch-cleanup.js";
|
|
29
29
|
// Approval prompts
|
|
30
30
|
import { registerPendingApprovalsPrompt } from "./pending-approvals.js";
|
|
31
|
+
// Deployment workflow prompts
|
|
32
|
+
import { registerBuildDeployAppPrompt } from "./build-deploy-app.js";
|
|
31
33
|
export function registerAllPrompts(server) {
|
|
32
34
|
// Existing prompts
|
|
33
35
|
registerDebugPipelinePrompt(server);
|
|
@@ -60,5 +62,7 @@ export function registerAllPrompts(server) {
|
|
|
60
62
|
registerBranchCleanupPrompt(server);
|
|
61
63
|
// Approvals
|
|
62
64
|
registerPendingApprovalsPrompt(server);
|
|
65
|
+
// Deployment workflows
|
|
66
|
+
registerBuildDeployAppPrompt(server);
|
|
63
67
|
}
|
|
64
68
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEpE,iBAAiB;AACjB,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,+BAA+B,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,0BAA0B,CAAC;AAE5E,iBAAiB;AACjB,OAAO,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,mCAAmC,EAAE,MAAM,6BAA6B,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,oBAAoB;AACpB,OAAO,EAAE,iCAAiC,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAC;AAE7E,uBAAuB;AACvB,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAElE,mBAAmB;AACnB,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAExE,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,mBAAmB;IACnB,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,4BAA4B,CAAC,MAAM,CAAC,CAAC;IACrC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,4BAA4B,CAAC,MAAM,CAAC,CAAC;IACrC,4BAA4B,CAAC,MAAM,CAAC,CAAC;IAErC,SAAS;IACT,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,gCAAgC,CAAC,MAAM,CAAC,CAAC;IACzC,+BAA+B,CAAC,MAAM,CAAC,CAAC;IACxC,4BAA4B,CAAC,MAAM,CAAC,CAAC;IACrC,gCAAgC,CAAC,MAAM,CAAC,CAAC;IAEzC,SAAS;IACT,gCAAgC,CAAC,MAAM,CAAC,CAAC;IACzC,mCAAmC,CAAC,MAAM,CAAC,CAAC;IAC5C,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAElC,YAAY;IACZ,iCAAiC,CAAC,MAAM,CAAC,CAAC;IAC1C,4BAA4B,CAAC,MAAM,CAAC,CAAC;IACrC,8BAA8B,CAAC,MAAM,CAAC,CAAC;IACvC,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,gCAAgC,CAAC,MAAM,CAAC,CAAC;IAEzC,eAAe;IACf,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAEpC,YAAY;IACZ,8BAA8B,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,7 +27,7 @@ For each pending approval, show:
|
|
|
27
27
|
- A deep link to the execution in Harness
|
|
28
28
|
|
|
29
29
|
**Step 4: Offer to take action**
|
|
30
|
-
Ask me if I want to approve or reject any of the pending approvals. If I choose to act, use harness_execute with resource_type="approval_instance", action="approve" (or "reject"), approval_id=<id
|
|
30
|
+
Ask me if I want to approve or reject any of the pending approvals. If I choose to act, use harness_execute with resource_type="approval_instance", action="approve" (or "reject"), approval_id=<id>.
|
|
31
31
|
|
|
32
32
|
If no executions are waiting for approval, let me know the project is clear.`,
|
|
33
33
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-create.d.ts","sourceRoot":"","sources":["../../src/tools/harness-create.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"harness-create.d.ts","sourceRoot":"","sources":["../../src/tools/harness-create.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAKjE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA6BrG"}
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import * as z from "zod/v4";
|
|
2
2
|
import { jsonResult, errorResult } from "../utils/response-formatter.js";
|
|
3
3
|
import { isUserError, toMcpError } from "../utils/errors.js";
|
|
4
|
+
import { confirmViaElicitation } from "../utils/elicitation.js";
|
|
4
5
|
export function registerCreateTool(server, registry, client) {
|
|
5
|
-
server.tool("harness_create", "Create a new Harness resource.
|
|
6
|
+
server.tool("harness_create", "Create a new Harness resource. For pipelines, templates, and triggers — read the schema resource first (e.g. schema:///pipeline) to understand the required body format.", {
|
|
6
7
|
resource_type: z.string().describe("The type of resource to create (e.g. pipeline, service, environment, connector, trigger)"),
|
|
7
8
|
body: z.record(z.string(), z.unknown()).describe("The resource definition body (varies by resource type — typically the YAML or JSON spec)"),
|
|
8
|
-
confirmation: z.boolean().describe("Must be true to confirm the create operation").default(false),
|
|
9
9
|
org_id: z.string().describe("Organization identifier (overrides default)").optional(),
|
|
10
10
|
project_id: z.string().describe("Project identifier (overrides default)").optional(),
|
|
11
11
|
}, async (args) => {
|
|
12
12
|
try {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const elicit = await confirmViaElicitation({
|
|
14
|
+
server,
|
|
15
|
+
toolName: "harness_create",
|
|
16
|
+
message: `Create ${args.resource_type}?\n\n${JSON.stringify(args.body, null, 2)}`,
|
|
17
|
+
});
|
|
18
|
+
if (!elicit.proceed) {
|
|
19
|
+
return errorResult(`Operation ${elicit.reason} by user.`);
|
|
15
20
|
}
|
|
16
21
|
const result = await registry.dispatch(client, args.resource_type, "create", args);
|
|
17
22
|
return jsonResult(result);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-create.js","sourceRoot":"","sources":["../../src/tools/harness-create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAI5B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"harness-create.js","sourceRoot":"","sources":["../../src/tools/harness-create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAI5B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,QAAkB,EAAE,MAAqB;IAC7F,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,0KAA0K,EAC1K;QACE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0FAA0F,CAAC;QAC9H,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,0FAA0F,CAAC;QAC5I,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC,CAAC,QAAQ,EAAE;QACrF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC,CAAC,QAAQ,EAAE;KACrF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC;gBACzC,MAAM;gBACN,QAAQ,EAAE,gBAAgB;gBAC1B,OAAO,EAAE,UAAU,IAAI,CAAC,aAAa,QAAQ,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;aAClF,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,WAAW,CAAC,aAAa,MAAM,CAAC,MAAM,WAAW,CAAC,CAAC;YAC5D,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,IAA+B,CAAC,CAAC;YAC9G,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,WAAW,CAAC,GAAG,CAAC;gBAAE,OAAO,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtD,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-delete.d.ts","sourceRoot":"","sources":["../../src/tools/harness-delete.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"harness-delete.d.ts","sourceRoot":"","sources":["../../src/tools/harness-delete.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAKjE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAqCrG"}
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import * as z from "zod/v4";
|
|
2
2
|
import { jsonResult, errorResult } from "../utils/response-formatter.js";
|
|
3
3
|
import { isUserError, toMcpError } from "../utils/errors.js";
|
|
4
|
+
import { confirmViaElicitation } from "../utils/elicitation.js";
|
|
4
5
|
export function registerDeleteTool(server, registry, client) {
|
|
5
|
-
server.tool("harness_delete", "Delete a Harness resource.
|
|
6
|
+
server.tool("harness_delete", "Delete a Harness resource. This is destructive and cannot be undone.", {
|
|
6
7
|
resource_type: z.string().describe("The type of resource to delete (e.g. pipeline, trigger, connector)"),
|
|
7
8
|
resource_id: z.string().describe("The identifier of the resource to delete"),
|
|
8
|
-
confirmation: z.boolean().describe("Must be true to confirm the delete operation — this is destructive").default(false),
|
|
9
9
|
org_id: z.string().describe("Organization identifier (overrides default)").optional(),
|
|
10
10
|
project_id: z.string().describe("Project identifier (overrides default)").optional(),
|
|
11
11
|
pipeline_id: z.string().describe("Pipeline ID (for trigger deletes)").optional(),
|
|
12
12
|
environment_id: z.string().describe("Environment ID (for infrastructure deletes)").optional(),
|
|
13
13
|
}, async (args) => {
|
|
14
14
|
try {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const elicit = await confirmViaElicitation({
|
|
16
|
+
server,
|
|
17
|
+
toolName: "harness_delete",
|
|
18
|
+
message: `Delete ${args.resource_type} "${args.resource_id}"?\n\nThis is destructive and cannot be undone.`,
|
|
19
|
+
});
|
|
20
|
+
if (!elicit.proceed) {
|
|
21
|
+
return errorResult(`Operation ${elicit.reason} by user.`);
|
|
17
22
|
}
|
|
18
23
|
const def = registry.getResource(args.resource_type);
|
|
19
24
|
const input = { ...args };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-delete.js","sourceRoot":"","sources":["../../src/tools/harness-delete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAI5B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"harness-delete.js","sourceRoot":"","sources":["../../src/tools/harness-delete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAI5B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,QAAkB,EAAE,MAAqB;IAC7F,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,sEAAsE,EACtE;QACE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oEAAoE,CAAC;QACxG,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;QAC5E,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC,CAAC,QAAQ,EAAE;QACrF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC,CAAC,QAAQ,EAAE;QACpF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC,CAAC,QAAQ,EAAE;QAChF,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC,CAAC,QAAQ,EAAE;KAC9F,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC;gBACzC,MAAM;gBACN,QAAQ,EAAE,gBAAgB;gBAC1B,OAAO,EAAE,UAAU,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC,WAAW,iDAAiD;aAC5G,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,WAAW,CAAC,aAAa,MAAM,CAAC,MAAM,WAAW,CAAC,CAAC;YAC5D,CAAC;YAED,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACrD,MAAM,KAAK,GAA4B,EAAE,GAAG,IAAI,EAAE,CAAC;YACnD,IAAI,GAAG,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACxD,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC;YACpD,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;YACpF,OAAO,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7K,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,WAAW,CAAC,GAAG,CAAC;gBAAE,OAAO,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtD,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-execute.d.ts","sourceRoot":"","sources":["../../src/tools/harness-execute.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"harness-execute.d.ts","sourceRoot":"","sources":["../../src/tools/harness-execute.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAKjE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAsDtG"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as z from "zod/v4";
|
|
2
2
|
import { jsonResult, errorResult } from "../utils/response-formatter.js";
|
|
3
3
|
import { isUserError, toMcpError } from "../utils/errors.js";
|
|
4
|
+
import { confirmViaElicitation } from "../utils/elicitation.js";
|
|
4
5
|
export function registerExecuteTool(server, registry, client) {
|
|
5
6
|
server.tool("harness_execute", "Execute an action on a Harness resource: run/retry/interrupt pipelines, toggle feature flags, test connectors, sync GitOps apps, run chaos experiments.", {
|
|
6
7
|
resource_type: z.string().describe("The resource type (e.g. pipeline, execution, feature_flag, connector, gitops_application, chaos_experiment)"),
|
|
7
8
|
action: z.string().describe("The action to execute (e.g. run, retry, interrupt, toggle, test_connection, sync)"),
|
|
8
9
|
resource_id: z.string().describe("The primary identifier of the resource").optional(),
|
|
9
|
-
confirmation: z.boolean().describe("Must be true to confirm execution").default(false),
|
|
10
10
|
org_id: z.string().describe("Organization identifier (overrides default)").optional(),
|
|
11
11
|
project_id: z.string().describe("Project identifier (overrides default)").optional(),
|
|
12
12
|
// Dynamic fields for various actions
|
|
@@ -28,16 +28,13 @@ export function registerExecuteTool(server, registry, client) {
|
|
|
28
28
|
body: z.record(z.string(), z.unknown()).describe("Additional body payload for the action").optional(),
|
|
29
29
|
}, async (args) => {
|
|
30
30
|
try {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
.map(([name, spec]) => ` - ${name}: ${spec.actionDescription}`)
|
|
39
|
-
.join("\n");
|
|
40
|
-
return errorResult(`Execute operations require confirmation=true.\n\nAvailable actions for "${args.resource_type}":\n${actionList}`);
|
|
31
|
+
const elicit = await confirmViaElicitation({
|
|
32
|
+
server,
|
|
33
|
+
toolName: "harness_execute",
|
|
34
|
+
message: `Execute "${args.action}" on ${args.resource_type}${args.resource_id ? ` "${args.resource_id}"` : ""}?`,
|
|
35
|
+
});
|
|
36
|
+
if (!elicit.proceed) {
|
|
37
|
+
return errorResult(`Operation ${elicit.reason} by user.`);
|
|
41
38
|
}
|
|
42
39
|
// Map resource_id to the primary identifier field
|
|
43
40
|
const def = registry.getResource(args.resource_type);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-execute.js","sourceRoot":"","sources":["../../src/tools/harness-execute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAI5B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"harness-execute.js","sourceRoot":"","sources":["../../src/tools/harness-execute.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-update.d.ts","sourceRoot":"","sources":["../../src/tools/harness-update.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"harness-update.d.ts","sourceRoot":"","sources":["../../src/tools/harness-update.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAKjE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA4CrG"}
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import * as z from "zod/v4";
|
|
2
2
|
import { jsonResult, errorResult } from "../utils/response-formatter.js";
|
|
3
3
|
import { isUserError, toMcpError } from "../utils/errors.js";
|
|
4
|
+
import { confirmViaElicitation } from "../utils/elicitation.js";
|
|
4
5
|
export function registerUpdateTool(server, registry, client) {
|
|
5
|
-
server.tool("harness_update", "Update an existing Harness resource.
|
|
6
|
+
server.tool("harness_update", "Update an existing Harness resource. Response includes openInHarness link to the updated resource when applicable (e.g. pipeline, service).", {
|
|
6
7
|
resource_type: z.string().describe("The type of resource to update (e.g. pipeline, service, environment, connector, trigger)"),
|
|
7
8
|
resource_id: z.string().describe("The identifier of the resource to update"),
|
|
8
9
|
body: z.record(z.string(), z.unknown()).describe("The updated resource definition body"),
|
|
9
|
-
confirmation: z.boolean().describe("Must be true to confirm the update operation").default(false),
|
|
10
10
|
org_id: z.string().describe("Organization identifier (overrides default)").optional(),
|
|
11
11
|
project_id: z.string().describe("Project identifier (overrides default)").optional(),
|
|
12
12
|
pipeline_id: z.string().describe("Pipeline ID (for trigger updates)").optional(),
|
|
13
13
|
version_label: z.string().describe("Template version label (for template updates; defaults to body.version_label or v1)").optional(),
|
|
14
14
|
}, async (args) => {
|
|
15
15
|
try {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
const elicit = await confirmViaElicitation({
|
|
17
|
+
server,
|
|
18
|
+
toolName: "harness_update",
|
|
19
|
+
message: `Update ${args.resource_type} "${args.resource_id}"?\n\n${JSON.stringify(args.body, null, 2)}`,
|
|
20
|
+
});
|
|
21
|
+
if (!elicit.proceed) {
|
|
22
|
+
return errorResult(`Operation ${elicit.reason} by user.`);
|
|
18
23
|
}
|
|
19
24
|
const def = registry.getResource(args.resource_type);
|
|
20
25
|
const input = { ...args };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-update.js","sourceRoot":"","sources":["../../src/tools/harness-update.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAI5B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"harness-update.js","sourceRoot":"","sources":["../../src/tools/harness-update.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
export interface ElicitationResult {
|
|
4
|
+
/** Whether the operation should proceed. */
|
|
5
|
+
proceed: boolean;
|
|
6
|
+
/** Why the operation was stopped, if applicable. */
|
|
7
|
+
reason?: "declined" | "cancelled";
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Check whether the connected client advertises form elicitation support.
|
|
11
|
+
*/
|
|
12
|
+
export declare function clientSupportsElicitation(server: Server): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Prompt the user to confirm a write operation via MCP form elicitation.
|
|
15
|
+
*
|
|
16
|
+
* Shows a message with the operation details — the user simply accepts or
|
|
17
|
+
* declines. No form fields or checkboxes.
|
|
18
|
+
*
|
|
19
|
+
* If the client doesn't support elicitation (or the call throws),
|
|
20
|
+
* proceeds silently — the LLM already chose to call the tool.
|
|
21
|
+
*/
|
|
22
|
+
export declare function confirmViaElicitation({ server, toolName, message, }: {
|
|
23
|
+
server: McpServer;
|
|
24
|
+
toolName: string;
|
|
25
|
+
message: string;
|
|
26
|
+
}): Promise<ElicitationResult>;
|
|
27
|
+
//# sourceMappingURL=elicitation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elicitation.d.ts","sourceRoot":"","sources":["../../src/utils/elicitation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAKxE,MAAM,WAAW,iBAAiB;IAChC,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;CACnC;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGjE;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,EAC1C,MAAM,EACN,QAAQ,EACR,OAAO,GACR,EAAE;IACD,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgC7B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createLogger } from "./logger.js";
|
|
2
|
+
const log = createLogger("elicitation");
|
|
3
|
+
/**
|
|
4
|
+
* Check whether the connected client advertises form elicitation support.
|
|
5
|
+
*/
|
|
6
|
+
export function clientSupportsElicitation(server) {
|
|
7
|
+
const caps = server.getClientCapabilities();
|
|
8
|
+
return !!caps?.elicitation?.form;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Prompt the user to confirm a write operation via MCP form elicitation.
|
|
12
|
+
*
|
|
13
|
+
* Shows a message with the operation details — the user simply accepts or
|
|
14
|
+
* declines. No form fields or checkboxes.
|
|
15
|
+
*
|
|
16
|
+
* If the client doesn't support elicitation (or the call throws),
|
|
17
|
+
* proceeds silently — the LLM already chose to call the tool.
|
|
18
|
+
*/
|
|
19
|
+
export async function confirmViaElicitation({ server, toolName, message, }) {
|
|
20
|
+
if (!clientSupportsElicitation(server.server)) {
|
|
21
|
+
log.debug("Client does not support elicitation, proceeding", { toolName });
|
|
22
|
+
return { proceed: true };
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const result = await server.server.elicitInput({
|
|
26
|
+
mode: "form",
|
|
27
|
+
message,
|
|
28
|
+
requestedSchema: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
log.info("Elicitation response", { toolName, action: result.action });
|
|
34
|
+
if (result.action === "accept") {
|
|
35
|
+
return { proceed: true };
|
|
36
|
+
}
|
|
37
|
+
if (result.action === "decline") {
|
|
38
|
+
return { proceed: false, reason: "declined" };
|
|
39
|
+
}
|
|
40
|
+
return { proceed: false, reason: "cancelled" };
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
log.warn("Elicitation failed, proceeding without confirmation", {
|
|
44
|
+
toolName,
|
|
45
|
+
error: String(err),
|
|
46
|
+
});
|
|
47
|
+
return { proceed: true };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=elicitation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elicitation.js","sourceRoot":"","sources":["../../src/utils/elicitation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,GAAG,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;AASxC;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,MAAM,IAAI,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;IAC5C,OAAO,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC;AACnC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAC1C,MAAM,EACN,QAAQ,EACR,OAAO,GAKR;IACC,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9C,GAAG,CAAC,KAAK,CAAC,iDAAiD,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;YAC7C,IAAI,EAAE,MAAM;YACZ,OAAO;YACP,eAAe,EAAE;gBACf,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,EAAE;aACf;SACF,CAAC,CAAC;QAEH,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAEtE,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAChD,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACjD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,qDAAqD,EAAE;YAC9D,QAAQ;YACR,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;SACnB,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;AACH,CAAC"}
|
package/build/utils/errors.js
CHANGED
|
@@ -3,7 +3,7 @@ import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
|
|
|
3
3
|
* Error handling convention for tool handlers:
|
|
4
4
|
*
|
|
5
5
|
* return errorResult(msg) — for user-fixable problems the LLM can act on:
|
|
6
|
-
* bad resource_type,
|
|
6
|
+
* bad resource_type, unsupported operation, missing
|
|
7
7
|
* required fields, validation errors. These are plain Errors thrown by the
|
|
8
8
|
* registry/toolset layer. The LLM sees the message and can retry/adjust.
|
|
9
9
|
*
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harness-mcp-v2",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "MCP server for Harness.io CI/CD platform — 10 consolidated tools with registry-based dispatch",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "build/index.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"harness-
|
|
8
|
+
"harness-mcp-v2": "build/index.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"build/"
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"license": "Apache-2.0",
|
|
36
36
|
"repository": {
|
|
37
37
|
"type": "git",
|
|
38
|
-
"url": "https://github.com/thisrohangupta/harness-
|
|
38
|
+
"url": "https://github.com/thisrohangupta/harness-mcp-v2.git"
|
|
39
39
|
},
|
|
40
40
|
"bugs": {
|
|
41
|
-
"url": "https://github.com/thisrohangupta/harness-
|
|
41
|
+
"url": "https://github.com/thisrohangupta/harness-mcp-v2/issues"
|
|
42
42
|
},
|
|
43
|
-
"homepage": "https://github.com/thisrohangupta/harness-
|
|
43
|
+
"homepage": "https://github.com/thisrohangupta/harness-mcp-v2#readme",
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
46
46
|
"express": "^5.2.1",
|