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
Integrates Harness MCP to manage CI/CD pipelines, Git repositories, and pull requests. Use it when you need to trigger deployments, review PRs, or sync PR comments and reviews with Jira issues.
/plugin marketplace add Lobbi-Docs/claude/plugin install jira-orchestrator@claude-orchestrationThis skill is limited to using the following tools:
AI-powered CD operations, Git repository and pull request management via Harness MCP Server.
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"
{
"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 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
| 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 |
repos = harness_list_repositories(
org_id="${HARNESS_ORG_ID}",
project_id="${HARNESS_PROJECT_ID}"
)
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)"
)
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}")
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_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"
connector:
name: jira-connector
identifier: jira_connector
type: Jira
spec:
jiraUrl: https://your-company.atlassian.net
auth:
type: UsernamePassword
spec:
username: your.email@company.com
passwordRef: jira_api_token
delegateSelectors:
- delegate-name
Required Scopes: read:jira-user, read:jira-work, write:jira-work
- 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
- 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
- step:
name: Jira Approval
type: JiraApproval
spec:
connectorRef: jira_connector
issueKey: <+pipeline.variables.jiraIssueKey>
approvalCriteria:
matchAnyCondition: true
conditions:
- key: Status
operator: equals
value: Approved
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"
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")
HARNESS_CODE_API="${HARNESS_BASE_URL}/code/api/v1"
curl -H "x-api-key: ${HARNESS_API_KEY}" \
-H "Content-Type: application/json" \
"${HARNESS_CODE_API}/repos/{repo-ref}/pullreq/{pr-number}/comments"
| 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 |
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!"}'
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
}'
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
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
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}"
}
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()
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
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")
repo = client.create_repository(
identifier="my-service",
description="User management service",
default_branch="main",
is_public=False,
readme=True,
license="MIT"
)
| 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} |
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")
documentation:
confluence:
base_url: "${CONFLUENCE_BASE_URL}"
space_key: "ENG"
auto_create:
enabled: true
on_work_start: true
readme:
auto_update: true
| 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 |
export HARNESS_LOG_LEVEL=debug
export MCP_DEBUG=true
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.