Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions capabilities/atlassian/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# atlassian

Wires Jira, Confluence, and Compass into chat and agents through Atlassian's hosted Rovo MCP server (`https://mcp.atlassian.com/v1/mcp`, first-party). It can **write** — create and update issues and pages — not just read, and there is no read-only mode: an agent acts with the full permissions of whoever authenticated.

## Setup

**OAuth (default).** On first connect the `atlassian` server shows as *needs authentication* in Services — click **Authenticate**, grant the Rovo scopes once in the browser, and the refresh token persists to `~/.dreadnode/mcp-auth.json`. The **first install on a new Atlassian site needs a site admin** to approve the app before anyone else can authenticate. For headless/CI, set `DREADNODE_HEADLESS=1` to log the auth URL instead of opening a browser.

If a connect ever fails and you go looking: Atlassian publishes no RFC 9728 protected-resource document, so discovery resolves through the authorization-server metadata on `mcp.atlassian.com`, which delegates to `cf.mcp.atlassian.com`. A 404 on `.well-known/oauth-protected-resource` is expected here — it isn't the fault.

**API token (unattended, optional).** Only works if a site admin enabled "authentication via API token" in Rovo MCP settings (off by default). Set the `ATLASSIAN_BASIC` secret to the base64 of `email:token`:

```bash
printf '%s:%s' you@example.com ATATT… | base64 | tr -d '\n'
```

Service-account API *keys* use Bearer instead: change `Basic` to `Bearer` in the manifest header and bind `${ATLASSIAN_API_KEY}`.

## Before you trust it

- **No read-only mode.** Scope is the authenticated identity's roles — under OAuth an agent can do anything you can. Use a scoped service account for unattended runs. (The `gitlab` and `github` connectors can enforce read-only server-side; this one and `azure-devops` cannot — the credential is the only boundary.)
- **Rate limits are low** — Atlassian publishes 500 calls/hour on Free and 1,000/hour on Standard, with Premium/Enterprise adding per-user allowance up to 10,000/hour. Bulk loops will hit them.
- **Not for FedRAMP or HIPAA workloads** — Atlassian states the MCP server doesn't currently support either.

Agent-facing usage — the per-product query languages (JQL/CQL) and idioms — lives in `skills/atlassian/`, not here.
62 changes: 62 additions & 0 deletions capabilities/atlassian/capability.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
schema: 1
name: atlassian
version: "1.0.0"
description: >
Connect to Atlassian Cloud (Jira, Confluence, Compass) from chat and
agents — search and read issues, pages, and components; create or
update issues and pages; bulk operations and JQL search. Talks
directly to Atlassian's hosted Rovo MCP server at
https://mcp.atlassian.com/v1/mcp; first use opens a browser
for OAuth (the authorization server lives on auth.atlassian.com),
then subsequent launches reconnect silently using a stored refresh
token (see ~/.dreadnode/mcp-auth.json).

mcp:
servers:
atlassian:
url: https://mcp.atlassian.com/v1/mcp
# Native HTTP MCP + Dreadnode-managed OAuth (CAP-MCP-011).
# Discovery note, since this one is not like Linear or GitLab:
# Atlassian publishes no RFC 9728 protected-resource document
# (the .well-known/oauth-protected-resource paths 404 and the 401
# carries no resource_metadata), so the client falls back to the
# authorization-server metadata at
# https://mcp.atlassian.com/.well-known/oauth-authorization-server
# — which names cf.mcp.atlassian.com for authorize/token/register
# and advertises DCR. That fallback is what makes this work; don't
# "fix" it to a protected-resource lookup. For non-interactive
# contexts (CI, headless eval), set DREADNODE_HEADLESS=1 and
# complete the flow manually.
auth:
type: oauth
client_name: dreadnode
headers:
# OAuth by default, or set ATLASSIAN_BASIC (base64 of
# `email:api_token`) for unattended Basic auth — admin must enable
# token auth on the Rovo MCP first. The optional header is dropped
# when the var is unset (CAP-MCP-013), so OAuth stays the default.
# Service-account API keys use Bearer instead — change "Basic" to
# "Bearer" and bind ${ATLASSIAN_API_KEY}.
Authorization:
value: "Basic ${ATLASSIAN_BASIC}"
optional: true
init_timeout: 60

skills:
- skills/atlassian/

author:
name: Dreadnode
url: https://dreadnode.io
license: MIT
repository: https://github.com/dreadnode/capabilities
keywords:
- atlassian
- jira
- confluence
- compass
- rovo
- issue-tracker
- wiki
- jql
- connector
87 changes: 87 additions & 0 deletions capabilities/atlassian/skills/atlassian/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
name: atlassian
description: Use when the user wants to connect to Jira, Confluence, or Compass — search issues with JQL, read or create issues and pages, link content across products, or set up Atlassian auth. The connector — not security tradecraft.
---

# Atlassian (Jira / Confluence / Compass)

Connector for Atlassian Cloud via the official Rovo remote MCP — one server, three
products. The agent sees the tool surface once it loads — this skill covers auth,
the per-product query languages, and the idioms. Security triage methodology —
dedup, severity, SLA, owner inference — is deliberately out of scope; pair this
with whichever triage capability your workflow uses.

## Auth

Native HTTP MCP with OAuth 2.1 + DCR; the runtime drives the flow, no
`mcp-remote` bridge. Atlassian doesn't publish an RFC 9728 protected-resource
document, so discovery resolves through the authorization-server metadata on
`mcp.atlassian.com`, which points at `cf.mcp.atlassian.com` for
authorize/token/register. Nothing to configure — but if you're debugging a failed
connect, that's the chain to walk, and it's why the `.well-known/
oauth-protected-resource` probes you'd try first come back 404.

### A. OAuth 2.1 (default)

On first connect, `atlassian` shows in Services as `needs authentication`. Click
**Authenticate** → browser → sign in and grant the Rovo scopes; tokens persist to
`~/.dreadnode/mcp-auth.json` (mode 0600) and refresh silently. Access respects your
existing Jira / Confluence / Compass roles. Switch sites / revoke via Services →
`atlassian` → **Re-authenticate**. SSH/headless: `DREADNODE_HEADLESS=1` logs the URL.

**First install on a new site needs a site admin** to complete consent once; until
then other users see "Your site admin must authorize this app." That's
Atlassian-side, not us.

### B. API token (only if your admin allowed it)

For unattended use, **just set one secret** — no manifest edit. The server entry
carries an optional `Authorization` header bound to `ATLASSIAN_BASIC`: set it and
Basic auth wins, leave it unset and OAuth (A) stays default.

1. Admin enables "authentication via API token" in **Rovo MCP server settings**
(off by default).
2. Generate a token: <https://id.atlassian.com/manage-profile/security/api-tokens>.
3. Personal tokens use **Basic** (`email:token`, base64). Interpolation can't
base64 for you — compute it and store the result as `ATLASSIAN_BASIC`:
```bash
printf '%s:%s' you@example.com ATATT… | base64 | tr -d '\n'; echo
```
Then reload. (Service-account API **keys** use Bearer — change `Basic` to `Bearer`
in the manifest header and bind `${ATLASSIAN_API_KEY}`.)

If the admin hasn't enabled token auth this path 401s with a clear error — unset the
secret and reload to fall back to OAuth. Token-auth agents bypass OAuth domain
allowlists and are governed by IP allowlist + token scopes instead. Don't paste
tokens into chat.

Read vs write is enforced by the user's **project / space roles** (or the token's
scopes on path B) — there's no protocol-level read-only mode.

## Query languages — know which product

- **Jira: JQL.** `project = "ENG" AND status = "Open" AND assignee = currentUser()
ORDER BY priority DESC`.
<https://support.atlassian.com/jira-service-management-cloud/docs/use-advanced-search-with-jira-query-language-jql/>
- **Confluence: CQL.** `space = "ENG" AND type = page AND title ~ "release"`.
<https://developer.atlassian.com/cloud/confluence/cql-fields/>
- **Compass:** structured typed filters (component type, owner team, dependencies),
not a DSL.

Prefer JQL / CQL with the search tool over post-filtering large lists. `ENG-123` is
the canonical Jira key — use it directly when the user has it. Always scope queries
(`project = …`) — instance-wide ones are slow and rate-limited.

## Idioms

- **Rate limits bite.** Free 500/hr; Standard / Premium / Enterprise 1000/hr base
(+20/user up to 10k/hr on higher tiers). Bulk loops blow through these — batch and
back off. The Rovo MCP supports bulk create from a spec / meeting notes: parse into
`{summary, description, …}` records, then create per record.
- The Rovo MCP is a **secure proxy, not a cache** — every call hits Atlassian Cloud;
"I just read it" doesn't mean it's unchanged. It can also link entities across
products (tickets ↔ a release-plan page ↔ a Compass component).
- `currentUser()` in JQL is the **OAuth user**, not the agent — with a service
account, "assigned to me" means the service account.
- Don't invent custom field IDs — list the project's fields when the schema isn't obvious.
- No FedRAMP / HIPAA workloads through this MCP.
23 changes: 23 additions & 0 deletions capabilities/azure-devops/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# azure-devops

Talks to Azure DevOps — Boards, Repos, Pipelines, Wiki — from chat and agents by bundling Microsoft's official `@azure-devops/mcp` server (pinned `2.8.1`, run on demand via `npx`). It's **write-capable** (create and update work items and wiki pages); scope is governed by your Azure DevOps project roles, not an in-band toggle — this connector has no server-side read-only switch, so use a read-scoped principal for unattended runs.

## Setup

Auth delegates to the Azure CLI — the server reuses your `az login` token, nothing to paste:

1. `az login` with an account that can reach the target org.
2. Set `ADO_ORG` to the org **name** (e.g. `contoso`, not the URL) via the secrets screen (`/secrets`, F7).
3. Optionally set `ADO_PROJECT` / `ADO_TEAM` to answer the project / team picker the server would otherwise elicit per call. (These need `@azure-devops/mcp` ≥ 2.8.0 — the reason the pin is 2.8.1 and not lower.)

There is no server-side read-only switch here — unlike `gitlab` and `github`, the ADO server registers its write tools unconditionally, so a read-scoped principal is the only way to pin this read-only.

A preflight `checks:` block fails fast if `az` is missing, no session is live, or Node < 20. To switch off `az login`, edit `--authentication` in `capability.yaml` (`interactive`, `pat`, or `envvar` are upstream-supported).

## Tool surface

The `-d` list ships `core work work-items repositories wiki pipelines` — **76 tools**, against 90 if you let the upstream default to `all`. To enable more, append `test-plans` (+9), `advanced-security` (+2, GHAS alerts), or `search` as **separate list items** in `capability.yaml` and reload.

One trap worth knowing: `-d` is parsed as an array, so the domains must stay one-per-line. Collapsing them into a single `core,work,...` string is read as one unknown domain and the server silently serves all 90 tools instead of erroring.

WIQL idioms and the GHAS-alert path are in `skills/azure-devops/`.
82 changes: 82 additions & 0 deletions capabilities/azure-devops/capability.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
schema: 1
name: azure-devops
version: "1.0.0"
description: >
Connect to Azure DevOps (Boards, Repos, Pipelines, Wiki) from chat and
agents — query work items with WIQL, read PRs, inspect pipeline runs,
create or update work items and wiki pages. Test Plans and GHAS alerts
are one-line opt-ins. Bundles Microsoft's official local MCP server
(npx @azure-devops/mcp) with Azure CLI auth.

mcp:
servers:
ado:
command: "npx"
args:
- "-y"
# Pinned for a reproducible tool surface; bump deliberately.
# 2.8.1 is the floor, not just the current release: the
# ado_mcp_project / ado_mcp_team defaults below are read in
# shared/elicitations.js as of 2.8.0 and are inert on 2.7.x.
- "@azure-devops/mcp@2.8.1"
# Org is the first positional arg; flags follow it.
- "${ADO_ORG}"
# Delegate auth to the existing `az login` session (the `checks:`
# below enforce that one exists). Without this the upstream
# defaults to per-call interactive browser auth. Alternatives:
# "interactive", "pat" (PERSONAL_ACCESS_TOKEN), "envvar"
# (ADO_MCP_AUTH_TOKEN) — see SKILL.md.
- "--authentication"
- "azcli"
# Ticketing-focused subset — 62 tools without "pipelines", 76 with,
# against 90 for the upstream default of "all". Append
# "test-plans" (+9) or "advanced-security" (+2, GHAS alerts) as
# separate list items; SKILL.md covers what each unlocks.
# These MUST stay one-per-line: yargs parses -d as an array, so a
# single "core,work,..." item is read as one unknown domain and the
# server silently falls back to all 90 tools.
- "-d"
- "core"
- "work"
- "work-items"
- "repositories"
- "wiki"
- "pipelines"
env:
# Optional convenience defaults. The upstream elicits a project /
# team picker whenever a tool needs one and none was passed; these
# short-circuit that. Lowercase names are the upstream's, not a typo.
# Empty string is falsy there, so unset cleanly falls back to the
# picker rather than resolving to "".
ado_mcp_project: "${ADO_PROJECT:-}"
ado_mcp_team: "${ADO_TEAM:-}"
init_timeout: 60

checks:
- name: azure-cli
command: 'command -v az >/dev/null 2>&1'
- name: az-logged-in
command: 'az account show >/dev/null 2>&1'
- name: node-20-plus
command: 'command -v node >/dev/null 2>&1 && node --version | grep -Eq "^v(2[0-9]|[3-9][0-9])"'

skills:
- skills/azure-devops/

author:
name: Dreadnode
url: https://dreadnode.io
license: MIT
repository: https://github.com/dreadnode/capabilities
keywords:
- azure-devops
- ado
- boards
- work-items
- wiql
- pipelines
- repos
- pull-requests
- wiki
- issue-tracker
- connector
83 changes: 83 additions & 0 deletions capabilities/azure-devops/skills/azure-devops/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
name: azure-devops
description: Use when the user wants to connect to Azure DevOps — query Boards work items with WIQL, read PRs, inspect pipeline runs, create or update work items and wiki pages, or set up ADO auth. The connector — not security tradecraft.
---

# Azure DevOps

Connector for Azure DevOps (Boards, Repos, Pipelines, Wiki, Test Plans) via
Microsoft's official MCP server. The agent sees the enabled tool surface (~76
tools on the shipped domains) once it loads — this skill covers auth, the domain
/ toolset model, WIQL, and the idioms. Security triage methodology — dedup,
severity, SLA, owner inference — is deliberately out of scope; pair this with
whichever triage capability your workflow uses.

## Auth

The manifest pins `--authentication azcli`, so the MCP **delegates to your existing
Azure CLI session** — no token to paste, no per-call browser prompt.

1. Install Azure CLI: <https://learn.microsoft.com/cli/azure/install-azure-cli>.
2. `az login` with an account that can reach the target ADO org.
3. Set `ADO_ORG` (the org **name**, e.g. `contoso`, not the URL) in the **secrets
screen** (`/secrets` or `F7`) or your launching shell. Optionally `ADO_PROJECT` /
`ADO_TEAM` — when a tool needs a project or team and the call didn't name one,
the server elicits a picker; these answer it up front. Needs the pinned
`@azure-devops/mcp` ≥ 2.8.0; they are inert on older builds.
4. The `checks:` fail fast if `az` is missing or `az account show` is empty — by
design, since `azcli` has nothing to delegate to without a live session.

First tool call may show a one-time org-consent browser prompt — that's Microsoft's
MSAL flow, not ours.

To switch modes, edit `--authentication` in `capability.yaml`:

| Mode | What | When |
|---|---|---|
| `azcli` (default) | Reuses the `az login` token | Box already signed into Azure CLI |
| `interactive` | Browser sign-in to Entra | No CLI session; human present |
| `pat` | base64 PAT from `PERSONAL_ACCESS_TOKEN` | Headless / non-Entra orgs |
| `envvar` | Raw bearer from `ADO_MCP_AUTH_TOKEN` | Token minted elsewhere |

Read vs write is enforced by **project roles** — a read-only principal can't mutate;
no in-band toggle. (The remote preview at `https://mcp.dev.azure.com/{org}` is
Entra-OAuth-only and doesn't support Claude Code yet — the local server is the right
default.)

## Toolset domains — keep the surface small

The upstream defaults to `all` (90 tools); the capability narrows that to 76 via
`-d`. Add domains as **separate list items** in `capability.yaml`, then reload
(`/capabilities` → reload) — a single comma-joined string is read as one unknown
domain and silently reverts to all 90.

| Domain | Shipped | Adds |
|---|---|---|
| `core` | ✅ | Project / team / org discovery (keep on) |
| `work` | ✅ | Iterations, teams, capacity |
| `work-items` | ✅ | Boards CRUD, WIQL |
| `repositories` | ✅ | Repos and PRs |
| `wiki` | ✅ | Wiki pages |
| `pipelines` | ✅ | Build / release runs, logs, artifacts |
| `test-plans` | — | Test plans and suites (+9 tools) |
| `search` | — | Cross-org search |
| `advanced-security` | — | GHAS alerts via `advsec_get_alerts` / `advsec_get_alert_details` (+2) — the only way to read them here, and they need GHAS licensed on the org |

## WIQL & idioms

WIQL is the SQL-shaped DSL for Boards; `@project` and `@me` are useful built-ins:

```sql
SELECT [System.Id], [System.Title], [System.State] FROM workitems
WHERE [System.TeamProject] = @project AND [System.WorkItemType] = 'Bug'
AND [System.State] <> 'Closed' ORDER BY [Microsoft.VSTS.Common.Priority]
```

<https://learn.microsoft.com/azure/devops/boards/queries/wiql-syntax>

- Filtered work-item reads are a **two-step chain**: `wit_query_by_wiql` (or
`wit_my_work_items`) returns IDs → `wit_get_work_items_batch_by_ids` hydrates them.
- Work-item IDs are **org-wide** integers (`wit_get_work_item, id=…`).
- `System.AreaPath` uses backslashes — escape them in JSON (`"Contoso\\Auth\\Identity"`).
Don't invent area paths / iterations; list them first.
- GHAS alerts (advanced-security domain) come from `advsec_get_alerts`.
Loading
Loading