home / skills / markus41 / claude / harness-mcp
This skill helps you manage Harness MCP driven CD operations, Git workflows, and Jira synchronization for seamless pipelines.
npx playbooks add skill markus41/claude --skill harness-mcpReview the files below or copy the command above to add this skill to your agents.
---
name: harness-mcp
description: Harness MCP (Model Context Protocol) server integration for AI-powered CD operations, pipeline management, Git repositories, pull requests, code review comments, and bidirectional Jira synchronization
allowed-tools:
- Bash
- Read
- Write
- Edit
- Glob
- Grep
- Task
- WebFetch
- WebSearch
dependencies:
- harness-cd
- jira-orchestration
triggers:
- harness mcp
- harness ai
- harness connector
- harness pipeline
- harness jira
- harness git
- harness pr
- harness pull request
- harness repository
- harness comment
- harness workspace
- harness multi-repo
- harness create repo
- mcp server
- cd automation
- harness confluence
- documentation sync
- link confluence
- readme docs
- issue documentation
---
# Harness MCP Skill
AI-powered CD operations, Git repository and pull request management via Harness MCP Server.
## Prerequisites
### Environment Variables
```bash
export HARNESS_API_KEY="your-api-key"
export HARNESS_DEFAULT_ORG_ID="your-org-id"
export HARNESS_DEFAULT_PROJECT_ID="your-project-id"
export HARNESS_BASE_URL="https://app.harness.io"
export HARNESS_ACCOUNT_ID="your-account-id"
```
### API Token Generation
1. Navigate to **Account Settings > API Keys** in Harness UI
2. Click **+ API Key**
3. Set permissions (minimum: pipeline execution, connector management)
4. Store securely
## MCP Server Configuration
### Claude Code
```json
{
"mcpServers": {
"harness": {
"command": "npx",
"args": ["-y", "@anthropic-ai/mcp-harness"],
"env": {
"HARNESS_API_KEY": "${HARNESS_API_KEY}",
"HARNESS_DEFAULT_ORG_ID": "${HARNESS_DEFAULT_ORG_ID}",
"HARNESS_DEFAULT_PROJECT_ID": "${HARNESS_DEFAULT_PROJECT_ID}",
"HARNESS_BASE_URL": "${HARNESS_BASE_URL}"
}
}
}
}
```
### Docker
```bash
docker run -e HARNESS_API_KEY=$HARNESS_API_KEY \
-e HARNESS_DEFAULT_ORG_ID=$HARNESS_DEFAULT_ORG_ID \
-e HARNESS_DEFAULT_PROJECT_ID=$HARNESS_DEFAULT_PROJECT_ID \
harness/mcp-server:latest
```
## Available MCP Tools
| Category | Tool | Purpose |
|----------|------|---------|
| **Connectors** | `harness_get_connector`, `harness_list_connectors`, `harness_get_connector_catalogue` | Manage connectors |
| **Pipelines** | `harness_list_pipelines`, `harness_get_pipeline`, `harness_trigger_pipeline` | Pipeline operations |
| **Executions** | `harness_get_execution`, `harness_list_executions`, `harness_get_execution_url` | Track executions |
| **Dashboards** | `harness_list_dashboards`, `harness_get_dashboard` | Dashboard data |
| **Repos** | `harness_get_repository`, `harness_list_repositories` | Repository management |
| **Pull Requests** | `harness_get_pull_request`, `harness_list_pull_requests`, `harness_create_pull_request`, `harness_get_pull_request_checks`, `harness_get_pull_request_activities` | PR operations |
## Git & Pull Request Workflows
### List Repositories
```python
repos = harness_list_repositories(
org_id="${HARNESS_ORG_ID}",
project_id="${HARNESS_PROJECT_ID}"
)
```
### Create Pull Request
```python
pr = harness_create_pull_request(
repo_id="my-application",
title="PROJ-123: Feature title",
source_branch="feature/PROJ-123",
target_branch="main",
description="## Summary\nImplements feature.\n## Jira\n[PROJ-123](https://company.atlassian.net/browse/PROJ-123)"
)
```
### Get PR Activities (Comments, Reviews)
```python
activities = harness_get_pull_request_activities(repo_id="my-app", pr_number=42)
for activity in activities:
if activity.type == "comment":
print(f"Comment by {activity.author} at {activity.file_path}:{activity.line_number}")
elif activity.type == "review":
print(f"Review by {activity.author}: {activity.state}")
```
### Sync PR Comments to Jira
```python
activities = harness_get_pull_request_activities(repo_id="my-app", pr_number=42)
review_summary = []
for activity in activities:
if activity.type == "review":
review_summary.append(f"- **{activity.author}**: {activity.state}")
jira_add_comment(issue_key="PROJ-123",
body=f"## PR Review\n**PR:** [#{42}]({pr.url})\n**Status:** {pr.state}\n\n" + "\n".join(review_summary))
```
### PR-to-Jira Status Mapping
```yaml
pr_sync:
enabled: true
jira_key_patterns:
- title: "^([A-Z]+-\\d+)"
- branch: "feature/([A-Z]+-\\d+)"
transitions:
pr_created: { transition: "In Review", comment: "PR created: {pr_url}" }
pr_approved: { transition: "Approved", comment: "PR approved by {approver}" }
pr_merged: { transition: "Done", comment: "PR merged to {target_branch}" }
fields:
pr_url: "customfield_10200"
pr_status: "customfield_10201"
reviewers: "customfield_10202"
```
## Jira Connector Setup
### Create Connector
```yaml
connector:
name: jira-connector
identifier: jira_connector
type: Jira
spec:
jiraUrl: https://your-company.atlassian.net
auth:
type: UsernamePassword
spec:
username: [email protected]
passwordRef: jira_api_token
delegateSelectors:
- delegate-name
```
**Required Scopes:** `read:jira-user`, `read:jira-work`, `write:jira-work`
### Jira Create Step in Pipeline
```yaml
- step:
name: Create Jira Issue
type: JiraCreate
spec:
connectorRef: jira_connector
projectKey: PROJ
issueType: Task
fields:
- name: Summary
value: "Deployment: <+pipeline.name> - <+pipeline.sequenceId>"
- name: Priority
value: Medium
```
### Jira Update Step
```yaml
- step:
name: Update Jira Issue
type: JiraUpdate
spec:
connectorRef: jira_connector
issueKey: <+pipeline.variables.jiraIssueKey>
fields:
- name: Status
value: Done
transitionTo:
transitionName: Done
status: Done
```
### Jira Approval Step
```yaml
- step:
name: Jira Approval
type: JiraApproval
spec:
connectorRef: jira_connector
issueKey: <+pipeline.variables.jiraIssueKey>
approvalCriteria:
matchAnyCondition: true
conditions:
- key: Status
operator: equals
value: Approved
```
## Integration with Jira Orchestrator
### Configuration
```yaml
harness:
account:
account_id: "${HARNESS_ACCOUNT_ID}"
org_id: "${HARNESS_ORG_ID}"
project_id: "${HARNESS_PROJECT_ID}"
api:
base_url: "https://app.harness.io"
api_key: "${HARNESS_API_KEY}"
mcp:
enabled: true
tools:
- harness_get_connector
- harness_list_pipelines
- harness_get_execution
jira_connector_ref: "jira_connector"
sync:
auto_create_issues: true
auto_transition: true
environments:
dev: "In Development"
staging: "In QA"
prod: "Released"
```
### MCP Tool Usage
```python
connector = harness_get_connector(connector_id="jira_connector", org_id="default", project_id="my_project")
executions = harness_list_executions(pipeline_id="deploy_pipeline", limit=10)
execution = harness_get_execution(execution_id="abc123", org_id="default", project_id="my_project")
```
## REST API for PR Operations
### Base URL
```bash
HARNESS_CODE_API="${HARNESS_BASE_URL}/code/api/v1"
```
### Authentication
```bash
curl -H "x-api-key: ${HARNESS_API_KEY}" \
-H "Content-Type: application/json" \
"${HARNESS_CODE_API}/repos/{repo-ref}/pullreq/{pr-number}/comments"
```
### Key Endpoints
| Operation | Method | Endpoint |
|-----------|--------|----------|
| Create Comment | POST | `/v1/repos/{repo}/pullreq/{pr}/comments` |
| Create Code Comment | POST | `/v1/repos/{repo}/pullreq/{pr}/comments` (with `path`, `line_start`, `line_end`) |
| Submit Review | POST | `/v1/repos/{repo}/pullreq/{pr}/reviews` |
| Add Reviewer | POST | `/v1/repos/{repo}/pullreq/{pr}/reviewers` |
| Merge PR | POST | `/v1/repos/{repo}/pullreq/{pr}/merge` |
### Create General Comment
```bash
curl -X POST "${HARNESS_CODE_API}/repos/${REPO}/pullreq/${PR}/comments" \
-H "x-api-key: ${HARNESS_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"text": "Great work!"}'
```
### Create Code Comment
```bash
curl -X POST "${HARNESS_CODE_API}/repos/${REPO}/pullreq/${PR}/comments" \
-H "x-api-key: ${HARNESS_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"text": "Consider adding null check",
"path": "src/auth.ts",
"line_start": 42,
"line_end": 45,
"line_start_new": true,
"line_end_new": true
}'
```
### Submit Review
```bash
curl -X POST "${HARNESS_CODE_API}/repos/${REPO}/pullreq/${PR}/reviews" \
-H "x-api-key: ${HARNESS_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"commit_sha": "abc123", "decision": "approved"}'
```
**Decision Values:** `approved`, `changereq`, `reviewed`
### Merge PR
```bash
curl -X POST "${HARNESS_CODE_API}/repos/${REPO}/pullreq/${PR}/merge" \
-H "x-api-key: ${HARNESS_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"method": "squash",
"source_sha": "abc123",
"title": "feat: Add auth",
"delete_source_branch": true
}'
```
**Merge Methods:** `merge`, `squash`, `rebase`, `fast-forward`
## Bash Helper Functions
```bash
export HARNESS_CODE_API="${HARNESS_BASE_URL:-https://app.harness.io}/code/api/v1"
harness_pr_comment() {
local repo="$1" pr="$2" text="$3"
curl -s -X POST "${HARNESS_CODE_API}/repos/${repo}/pullreq/${pr}/comments" \
-H "x-api-key: ${HARNESS_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"text\": \"${text}\"}"
}
harness_pr_approve() {
local repo="$1" pr="$2" commit_sha="$3"
curl -s -X POST "${HARNESS_CODE_API}/repos/${repo}/pullreq/${pr}/reviews" \
-H "x-api-key: ${HARNESS_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"commit_sha\": \"${commit_sha}\", \"decision\": \"approved\"}"
}
harness_pr_merge() {
local repo="$1" pr="$2" method="${3:-squash}" source_sha="$4" title="$5"
curl -s -X POST "${HARNESS_CODE_API}/repos/${repo}/pullreq/${pr}/merge" \
-H "x-api-key: ${HARNESS_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"method\": \"${method}\", \"source_sha\": \"${source_sha}\", \"title\": \"${title}\", \"delete_source_branch\": true}"
}
```
## Python Client
```python
import requests, os
from typing import Optional, Literal
class HarnessCodeAPI:
def __init__(self, api_key: str = None, base_url: str = None):
self.api_key = api_key or os.environ.get("HARNESS_API_KEY")
self.base_url = base_url or os.environ.get("HARNESS_BASE_URL", "https://app.harness.io")
self.api_url = f"{self.base_url}/code/api/v1"
self.headers = {"x-api-key": self.api_key, "Content-Type": "application/json"}
def create_comment(self, repo: str, pr_number: int, text: str, path: Optional[str] = None,
line_start: Optional[int] = None, line_end: Optional[int] = None,
parent_id: Optional[int] = None) -> dict:
url = f"{self.api_url}/repos/{repo}/pullreq/{pr_number}/comments"
data = {"text": text}
if parent_id:
data["parent_id"] = parent_id
elif path and line_start:
data.update({"path": path, "line_start": line_start, "line_end": line_end or line_start,
"line_start_new": True, "line_end_new": True})
return requests.post(url, headers=self.headers, json=data).json()
def submit_review(self, repo: str, pr_number: int, commit_sha: str,
decision: Literal["approved", "changereq", "reviewed"]) -> dict:
url = f"{self.api_url}/repos/{repo}/pullreq/{pr_number}/reviews"
data = {"commit_sha": commit_sha, "decision": decision}
return requests.post(url, headers=self.headers, json=data).json()
def approve(self, repo: str, pr_number: int, commit_sha: str) -> dict:
return self.submit_review(repo, pr_number, commit_sha, "approved")
def merge(self, repo: str, pr_number: int, source_sha: str,
method: Literal["merge", "squash", "rebase", "fast-forward"] = "squash",
title: Optional[str] = None, delete_source_branch: bool = True,
dry_run: bool = False) -> dict:
url = f"{self.api_url}/repos/{repo}/pullreq/{pr_number}/merge"
data = {"method": method, "source_sha": source_sha, "delete_source_branch": delete_source_branch, "dry_run": dry_run}
if title:
data["title"] = title
return requests.post(url, headers=self.headers, json=data).json()
```
## Multi-Repository Workspace Support
### Configuration
```yaml
harness:
workspace:
repositories:
- identifier: frontend-app
path: ./frontend
jira_project: FRONT
- identifier: backend-api
path: ./backend
jira_project: BACK
auto_create_repos: true
default_branch: main
review:
cross_repo_review: true
jira:
sync_enabled: true
aggregate_prs: true
```
### Python API
```python
from lib.harness_code_api import HarnessCodeAPI
client = HarnessCodeAPI()
repos = client.setup_workspace_repos([
{"identifier": "frontend", "path": "./frontend"},
{"identifier": "backend", "path": "./backend"}
])
prs = client.get_workspace_prs(repo_identifiers=["frontend", "backend"], state="open", jira_key="PROJ-123")
```
## Repository Creation
### Python
```python
repo = client.create_repository(
identifier="my-service",
description="User management service",
default_branch="main",
is_public=False,
readme=True,
license="MIT"
)
```
### REST API
| Operation | Method | Endpoint |
|-----------|--------|----------|
| List Repos | GET | `/v1/repos` |
| Get Repo | GET | `/v1/repos/{repo}` |
| Create Repo | POST | `/v1/repos` |
| Update Repo | PATCH | `/v1/repos/{repo}` |
| Delete Repo | DELETE | `/v1/repos/{repo}` |
## Confluence Documentation Integration
### Auto-Documentation
```python
from lib.confluence_doc_linker import ConfluenceDocLinker
linker = ConfluenceDocLinker()
docs = linker.ensure_issue_docs("PROJ-123")
linker.link_readme_to_confluence(readme_path="./README.md", jira_key="PROJ-123")
```
### Configuration
```yaml
documentation:
confluence:
base_url: "${CONFLUENCE_BASE_URL}"
space_key: "ENG"
auto_create:
enabled: true
on_work_start: true
readme:
auto_update: true
```
## Troubleshooting
| Issue | Solution |
|-------|----------|
| Invalid API Key | Regenerate in Harness UI |
| Network timeout | Check delegate connectivity |
| Permission denied | Verify API key permissions |
| Jira unreachable | Check firewall/proxy |
### Debug Logging
```bash
export HARNESS_LOG_LEVEL=debug
export MCP_DEBUG=true
```
## Best Practices
1. Use Harness Secrets for credentials
2. Select delegates with direct Jira network access
3. Configure error handling with retries
4. Enable logging for all operations
5. Scope API tokens to minimum permissions
## Related Resources
- [Harness MCP Server](https://developer.harness.io/docs/platform/harness-aida/harness-mcp-server/)
- [Harness Code Repository](https://developer.harness.io/docs/code-repository/)
- [PR Review](https://developer.harness.io/docs/code-repository/pull-requests/review-pr/)
- [PR Merge](https://developer.harness.io/docs/code-repository/pull-requests/merge-pr/)
- [Jira Connector Setup](https://developer.harness.io/docs/platform/connectors/ticketing-systems/connect-to-jira/)
- [Jira Steps in CD](https://developer.harness.io/docs/continuous-delivery/x-platform-cd-features/cd-steps/ticketing-systems/create-jira-issues-in-cd-stages/)
This skill integrates Harness MCP (Model Context Protocol) server capabilities to manage CD operations, pipelines, Git repositories, pull requests, code review comments, and bidirectional Jira synchronization. I provide tools and helpers for triggering pipelines, inspecting executions, managing connectors, performing PR workflows, and syncing PR state and comments with Jira. The skill is designed for automation in CI/CD and developer workflow orchestration.
I expose MCP tools and REST endpoints to list and manipulate connectors, pipelines, executions, repositories, and pull requests. The integration uses a Harness API key and org/project context to call the Harness Code API for comments, reviews, merges, and repository management. I also offer Jira connector configuration and pipeline steps to create, update, and transition Jira issues automatically based on PR and pipeline events.
What credentials are required to use this integration?
You need a Harness API key with pipeline and connector permissions, plus a Jira connector (username+API token) with read/write scopes for work and users.
How does PR-to-Jira synchronization identify the Jira issue?
Synchronization uses configurable regex patterns on PR titles and branch names to extract Jira keys, and maps PR events to Jira transitions and custom fields.