diff --git a/capabilities/atlassian/README.md b/capabilities/atlassian/README.md new file mode 100644 index 0000000..bc82065 --- /dev/null +++ b/capabilities/atlassian/README.md @@ -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. diff --git a/capabilities/atlassian/capability.yaml b/capabilities/atlassian/capability.yaml new file mode 100644 index 0000000..d26add9 --- /dev/null +++ b/capabilities/atlassian/capability.yaml @@ -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 diff --git a/capabilities/atlassian/skills/atlassian/SKILL.md b/capabilities/atlassian/skills/atlassian/SKILL.md new file mode 100644 index 0000000..b97c4d6 --- /dev/null +++ b/capabilities/atlassian/skills/atlassian/SKILL.md @@ -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: . +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`. + +- **Confluence: CQL.** `space = "ENG" AND type = page AND title ~ "release"`. + +- **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. diff --git a/capabilities/azure-devops/README.md b/capabilities/azure-devops/README.md new file mode 100644 index 0000000..c958b53 --- /dev/null +++ b/capabilities/azure-devops/README.md @@ -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/`. diff --git a/capabilities/azure-devops/capability.yaml b/capabilities/azure-devops/capability.yaml new file mode 100644 index 0000000..702c252 --- /dev/null +++ b/capabilities/azure-devops/capability.yaml @@ -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 diff --git a/capabilities/azure-devops/skills/azure-devops/SKILL.md b/capabilities/azure-devops/skills/azure-devops/SKILL.md new file mode 100644 index 0000000..b448d0f --- /dev/null +++ b/capabilities/azure-devops/skills/azure-devops/SKILL.md @@ -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: . +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] +``` + + + +- 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`. diff --git a/capabilities/github/README.md b/capabilities/github/README.md new file mode 100644 index 0000000..3fc3672 --- /dev/null +++ b/capabilities/github/README.md @@ -0,0 +1,24 @@ +# github + +Wires GitHub into chat and agents by bundling GitHub's **official remote MCP server** (`https://api.githubcopilot.com/mcp/`) — issues, PRs, code search, Actions, Dependabot, code scanning. Ships no bespoke tool code; the value is the auth wiring, the toolset selection, and a skill. **Write-capable by default** — bounded by the PAT's permissions, with an optional server-side read-only lock (below). + +## Setup + +Authentication is a Personal Access Token sent as a Bearer header. Set `GITHUB_PAT` via the secrets screen (`/secrets`, F7) — or, if you're already on the `gh` CLI, `gh auth token` prints a reusable token (those rotate; mint a fine-grained PAT for unattended use). Grant the token read on the surfaces you need (Issues, Pull requests, Contents, Actions, Dependabot alerts) and write only where the agent must mutate. + +| Var | Default | Notes | +|-----|---------|-------| +| `GITHUB_PAT` | _(required)_ | Bearer token. Its scopes are the outer bound on everything the agent can do. | +| `GITHUB_READ_ONLY_MODE` | _(unset)_ | Set `true` and reload to send `X-MCP-Readonly` — the server then won't register mutating tools at all (58 → 38). A backstop for when the token is broader than the task. | + +**Read-only worth knowing:** the PAT's scopes are the real boundary, but the server-side flag above is a genuine second lock — the agent cannot call a tool that was never registered. Unset by default, so out of the box this is write-capable up to whatever the PAT allows. Among the tracker connectors only this one and `gitlab` can enforce read-only server-side; `linear`, `atlassian`, and `azure-devops` are credential-scoped only. + +**There is deliberately no OAuth/device flow** — GitHub's remote MCP doesn't support Dynamic Client Registration and its OAuth flow needs a `client_secret` an installed capability can't ship, so GitHub reserves OAuth for its own allowlisted hosts. A token is the only path here (unlike the `linear` / `atlassian` connectors). + +## Before you trust it + +- **The security tools are opt-in and we opt in for you.** GitHub's default toolset ships none of them; the manifest requests `actions`, `code_security`, `dependabot`, and `secret_protection` explicitly via `X-MCP-Toolsets`. That lands the surface at 58 tools rather than the bare default's 47 or `all`'s 95. Trim that header if you want a smaller context footprint. +- **Code-scanning / SARIF tools need GitHub Advanced Security** licensed on the target org — without it those paths return empty regardless of PAT scope. Dependabot alerts don't carry this dependency. +- **Enterprise changes the URL** (data-residency Cloud is `https://copilot-api..ghe.com/mcp`) or drops the remote server entirely (Enterprise Server → local Docker image). Both mean editing `capability.yaml` — see the skill. + +Query idioms (the issue-search DSL) and the Enterprise swap live in `skills/github/`. diff --git a/capabilities/github/capability.yaml b/capabilities/github/capability.yaml new file mode 100644 index 0000000..41be52b --- /dev/null +++ b/capabilities/github/capability.yaml @@ -0,0 +1,52 @@ +schema: 1 +name: github +version: "1.0.0" +description: > + Connect to GitHub from chat and agents — issues, pull requests, code + search, Actions, releases, Dependabot, and code scanning. Bundles + GitHub's official remote MCP server (https://api.githubcopilot.com/mcp/) + with PAT authentication. + +mcp: + servers: + github: + url: "https://api.githubcopilot.com/mcp/" + headers: + Authorization: "Bearer ${GITHUB_PAT}" + # The server's "default" toolset excludes Actions and every security + # surface, so the tools this capability advertises have to be + # requested explicitly. Measured against the live server: 47 tools on + # the bare default, 58 with the four toolsets below, 95 with "all". + # We take the 58 — the advertised surface, without paying context for + # discussions / gists / notifications / projects nobody asked for. + X-MCP-Toolsets: "default,actions,code_security,dependabot,secret_protection" + # Server-side read-only enforcement: when this header is present and + # not false/f/0/off, the server refuses to register mutating tools + # (58 -> 38 measured). Unset by default, so writes stay governed by + # the PAT's scopes; set GITHUB_READ_ONLY_MODE=true for a hard stop + # that survives an over-scoped token. Dropped entirely when unset + # (CAP-MCP-013), so the default path sends no empty header. + X-MCP-Readonly: + value: "${GITHUB_READ_ONLY_MODE}" + optional: true + init_timeout: 60 + +skills: + - skills/github/ + +author: + name: Dreadnode + url: https://dreadnode.io +license: MIT +repository: https://github.com/dreadnode/capabilities +keywords: + - github + - issues + - pull-requests + - issue-tracker + - project-management + - code-search + - actions + - dependabot + - code-scanning + - connector diff --git a/capabilities/github/skills/github/SKILL.md b/capabilities/github/skills/github/SKILL.md new file mode 100644 index 0000000..80eb82e --- /dev/null +++ b/capabilities/github/skills/github/SKILL.md @@ -0,0 +1,87 @@ +--- +name: github +description: Use when the user wants to connect to GitHub, search or read issues / PRs / code, create or update issues and PRs, inspect Actions runs, or review Dependabot / code-scanning alerts. The connector — not security tradecraft. +--- + +# GitHub + +Connector for GitHub via its official remote MCP server. The agent sees the +enabled tool surface (~58 tools) once the server loads — this skill covers what +the tool specs don't: auth, read-only scoping, the issue-search DSL, and the +non-obvious idioms. Security triage methodology — dedup, severity, SLA, owner +inference — is deliberately out of scope; pair this with whichever triage +capability your workflow uses. + +## Auth + +Token sent as a Bearer header — **no OAuth**. This is a GitHub-side limit: its +remote MCP server doesn't support Dynamic Client Registration and its OAuth web +flow needs a `client_secret` that can't ship in an installed tool, so OAuth is +reserved for GitHub's allowlisted first-party hosts (VS Code, Cursor, …). For this +connector, a token is the path. + +**Already using the `gh` CLI? Reuse its session — no new token.** + +```bash +gh auth token # copy the output into /secrets → GITHUB_PAT +``` + +Quickest path for most developers. `gh` OAuth tokens can rotate/expire, so for a +long-lived / unattended setup mint a fine-grained PAT instead: + +1. , scoped to the repos or + org you need, minimum permissions: + - **Read-only**: `Contents`, `Issues`, `Pull requests`, `Metadata` (Read), plus + `Code scanning alerts` + `Dependabot alerts` (Read) for security data. + - **Read + write**: add `Issues`, `Pull requests`, `Contents` (Write) only where needed. +2. Add `GITHUB_PAT` in the **secrets screen** (`/secrets` or `F7`) or the web app. + Confirm with `dn secret list`. Don't paste tokens into chat. + +Two independent read-only controls, and you want both: + +- **PAT scopes** — a token without `Write` permissions can't mutate. This is the + one that holds even if the server config changes. +- **Server-side** — set `GITHUB_READ_ONLY_MODE=true` (secrets screen or launching + shell) and reload. The manifest binds it to the remote server's `X-MCP-Readonly` + header, and the server then refuses to register mutating tools at all (58 → 38). + Unset by default, so writes stay governed by the PAT alone. + +The server-side flag is the useful backstop when the token is broader than the +task — the agent can't call what was never registered. + +**GitHub Enterprise.** Enterprise Cloud with data residency changes the URL to +`https://copilot-api..ghe.com/mcp` — swap `url:` in `capability.yaml`. +Enterprise Server (self-hosted) doesn't support the remote server; use the local +Docker image (`ghcr.io/github/github-mcp-server`) with a stdio `command:` entry. +Ask before doing this — the manifest changes aren't drive-by. + +## Issue search DSL + +`search_issues` takes GitHub's structured query (keyword tokens + `repo:`, `is:`, +`state:`, `label:`, `author:`, `assignee:`, `in:title`, `sort:` …) and covers +**both issues and PRs** — qualify with `is:issue` / `is:pr`. Prefer it over +`list_issues` for anything more specific than state. + +``` +repo:owner/name is:issue is:open label:bug author:alice +``` + +Reference: . + +## Idioms + +- **No implicit scope** — every tool call needs `owner` and `repo`. +- `issue_read` / `issue_write` are **dispatcher tools**: pick the `method` (`get`, + `get_comments`, `get_sub_issues`, `get_labels` for read; `create`, `update` for + write). Sub-issues are first-class via `sub_issue_write`. +- List label / type names (`list_issue_types`, `get_label`) rather than guessing them. +- **Dependabot + code-scanning alerts are the security surfaces.** They need the + token's `security_events` scope (or fine-grained `Code scanning alerts: Read` + + `Dependabot alerts: Read`): `list_dependabot_alerts`, `get_dependabot_alert`, + `list_code_scanning_alerts`, `get_code_scanning_alert`. These are **not** in the + server's default toolset — the manifest requests them via `X-MCP-Toolsets`. If + they're missing from the surface, that header is why, not the token. +- **Toolsets are a context lever.** The manifest ships `default`, `actions`, and the three + security toolsets (58 tools); `all` is 95. Trim or extend the `X-MCP-Toolsets` + header in `capability.yaml` to trade surface for context budget — + . diff --git a/capabilities/gitlab/README.md b/capabilities/gitlab/README.md new file mode 100644 index 0000000..d5a3058 --- /dev/null +++ b/capabilities/gitlab/README.md @@ -0,0 +1,24 @@ +# gitlab + +Connects chat and agents to GitLab (issues, merge requests, projects, pipelines, milestones, wikis) on gitlab.com or self-managed, by bundling the community **`@zereight/mcp-gitlab`** server (`npx`, pinned `2.1.43`). Not first-party — the pin is your trust boundary; bump it deliberately. Works on every tier including Free. + +## Setup + +| Var | Default | Notes | +|-----|---------|-------| +| `GITLAB_PAT` | _(required)_ | Personal access token — `read_api` scope for read-only, `api` for writes. Set via the secrets screen (`/secrets`, F7), not chat. | +| `GITLAB_API_URL` | `https://gitlab.com/api/v4` | Point at a self-managed instance: `https:///api/v4` (the `/api/v4` is required). | +| `GITLAB_READ_ONLY_MODE` | `true` | Read-only by default — at `true` the server doesn't register write tools at all. Set `false` and reload to enable writes (also needs an `api`-scoped token). | +| `GITLAB_USE_PIPELINE` | `true` | Pipeline / job / artifact tools. Off in the upstream default; on here. | +| `GITLAB_USE_WIKI` | `true` | Project and group wiki tools. Same story. | +| `GITLAB_USE_MILESTONE` | `true` | Milestone tools, including burndown events. Same story. | + +Setting any of the three `GITLAB_USE_*` vars to `false` trims that group back out — the read-only surface is 62 tools with all three off, 89 with them on, and 161 once writes are enabled. + +## Before you trust it + +- **Read-only here is real, not advisory.** At the default the server never registers a mutating tool, so an over-scoped token still can't write through this connector. That's stronger than the credential-only scoping in the `github` / `linear` / `atlassian` / `azure-devops` connectors — it's a property of this server, not something we built. +- **It's community-maintained.** That's the tradeoff for tier coverage and surface breadth. GitLab ships a first-party OAuth MCP that's token-free and moved from Premium to **Free in GitLab 19.2** — narrower and still beta, but first-party. If provenance matters more than surface, `skills/gitlab/SKILL.md` has the drop-in manifest block. +- **No snippet tools exist** in this server at any version, despite snippets being a GitLab feature. Use the REST API directly if you need them. + +Token setup, the OAuth swap, and filter idioms live in `skills/gitlab/`. diff --git a/capabilities/gitlab/capability.yaml b/capabilities/gitlab/capability.yaml new file mode 100644 index 0000000..d053135 --- /dev/null +++ b/capabilities/gitlab/capability.yaml @@ -0,0 +1,55 @@ +schema: 1 +name: gitlab +version: "1.0.0" +description: > + Connect to GitLab (gitlab.com or self-managed) from chat and agents — + issues, merge requests, projects, pipelines, milestones, wikis. Bundles + the community-maintained zereight/gitlab-mcp server with PAT auth — + works on every tier. Defaults to read-only, enforced server-side; flip + GITLAB_READ_ONLY_MODE to enable writes. GitLab's own OAuth MCP is a + token-free alternative on every tier since 19.2 — see SKILL.md. + +mcp: + servers: + gitlab: + command: "npx" + args: + - "-y" + # Pinned for a reproducible tool surface; bump deliberately. This + # is a community server — the pin is the trust boundary, so read + # the diff before moving it. + - "@zereight/mcp-gitlab@2.1.43" + env: + GITLAB_PERSONAL_ACCESS_TOKEN: "${GITLAB_PAT}" + GITLAB_API_URL: "${GITLAB_API_URL:-https://gitlab.com/api/v4}" + # Defaults read-only. To enable writes, set + # GITLAB_READ_ONLY_MODE=false (secrets screen or your launching + # shell) and reload the capability. The upstream server hides + # write tools entirely when this is true — real enforcement, + # measured at 89 tools read-only vs 161 read-write. + GITLAB_READ_ONLY_MODE: "${GITLAB_READ_ONLY_MODE:-true}" + # Off by default upstream — without these three, the pipeline, + # wiki, and milestone tools this capability advertises are never + # registered at all (62 tools instead of 89 in read-only mode). + USE_PIPELINE: "${GITLAB_USE_PIPELINE:-true}" + USE_GITLAB_WIKI: "${GITLAB_USE_WIKI:-true}" + USE_MILESTONE: "${GITLAB_USE_MILESTONE:-true}" + init_timeout: 60 + +skills: + - skills/gitlab/ + +author: + name: Dreadnode + url: https://dreadnode.io +license: MIT +repository: https://github.com/dreadnode/capabilities +keywords: + - gitlab + - issues + - merge-requests + - issue-tracker + - pipelines + - repos + - wiki + - connector diff --git a/capabilities/gitlab/skills/gitlab/SKILL.md b/capabilities/gitlab/skills/gitlab/SKILL.md new file mode 100644 index 0000000..e4a66f1 --- /dev/null +++ b/capabilities/gitlab/skills/gitlab/SKILL.md @@ -0,0 +1,87 @@ +--- +name: gitlab +description: Use when the user wants to connect to GitLab — search or read issues / MRs / projects, create or update issues and MRs, inspect pipelines, or set up GitLab auth. The connector — not security tradecraft. +--- + +# GitLab + +Connector for GitLab (gitlab.com or self-managed) via the community +`@zereight/mcp-gitlab` server. The agent sees the tool surface (89 tools read-only, +161 with writes) once it loads — this skill covers auth, the real read-only switch, +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 + +Two server options, and the tradeoff is surface vs. provenance — not tier. +**Default: the community PAT server**, which is GA and exposes by far the broader +surface. GitLab's own OAuth MCP (path B) is first-party and token-free but still +beta and much narrower. It moved from Premium to **Free in GitLab 19.2**, so it's +a real option on any tier when you'd rather not mint a PAT or take a dependency on +a community package. + +### A. Community server + PAT (default) + +1. Generate a PAT: + - gitlab.com: + - self-managed: `/-/user_settings/personal_access_tokens` +2. Scopes: **read-only** `read_api` (+ `read_repository` for code, `read_registry` + for the registry); **read + write** `api` (broad). +3. Add `GITLAB_PAT` in the **secrets screen** (`/secrets` or `F7`) or the web app. + Confirm with `dn secret list`. Don't paste tokens into chat. +4. Self-managed: also set `GITLAB_API_URL` (e.g. + `https://gitlab.example.com/api/v4` — the trailing `/api/v4` is required). + +### B. Official GitLab OAuth MCP (first-party; Free tier since 19.2) + +First-party MCP built into the instance, spec-compliant OAuth (RFC 9728 discovery ++ DCR/PKCE), no PAT — but much narrower, and beta since GitLab 18.6. Free tier and +up as of 19.2; on older instances it's Premium/Ultimate. Prerequisites live under +the instance's GitLab Duo settings. Replace the whole `gitlab:` block in +`capability.yaml`: + +```yaml +mcp: + servers: + gitlab: + url: https://gitlab.com/api/v4/mcp # self-managed: https:///api/v4/mcp + auth: + type: oauth + client_name: dreadnode + init_timeout: 60 +``` + +First connect opens a browser; tokens persist and refresh. `DREADNODE_HEADLESS=1` +for SSH/headless. Read-only here is the OAuth grant / role, not the env var below. + +## Read vs write — actually enforced + +Unlike most tracker connectors, the community server supports **real** read-only: +`GITLAB_READ_ONLY_MODE=true` (the capability's default) means write tools aren't +even registered. To enable writes, set `GITLAB_READ_ONLY_MODE=false` (secrets screen +or launching shell) and reload. The PAT's scopes still bound what's possible — pair +the flip with an `api`-scoped token. + +## Search & idioms + +No JQL-style DSL — structured filters (`state`, `labels`, `milestone`, `assignee`, +`author`) plus a free-text `search` field. Compose by argument. + +- `project_id` accepts the **path** (`group/project`) or the numeric ID. Path is + human-friendly; ID is stable across renames. +- **IID vs ID**: `iid` is project-scoped (`#42` in the UI), `id` is instance-global. + The tools generally take `iid` — pass `project_id` alongside it. +- Don't invent label / milestone names — list them first. +- Code search uses GitLab Advanced Search (Elasticsearch), Premium / self-managed only. +- Self-managed pipelines vary by tier (CI minutes, runners, security features). +- The server is **community-maintained**; the manifest pins + `@zereight/mcp-gitlab@2.1.43` for a reproducible tool surface. Bump it in + `capability.yaml` to adopt newer tools — and read the diff first, since the pin + is the trust boundary on a third-party package. +- **Pipelines, wikis, and milestones are off by default upstream.** The manifest + turns them on via `USE_PIPELINE` / `USE_GITLAB_WIKI` / `USE_MILESTONE` (62 tools + without them, 89 with, read-only). Set the corresponding `GITLAB_USE_*` var to + `false` to trim the surface back. +- There are **no snippet tools** in this server, at any version — if the user wants + snippets, that's the REST API directly, not this connector. diff --git a/capabilities/linear/README.md b/capabilities/linear/README.md new file mode 100644 index 0000000..13e5615 --- /dev/null +++ b/capabilities/linear/README.md @@ -0,0 +1,14 @@ +# linear + +Points the runtime at **Linear's own hosted MCP server** (`https://mcp.linear.app/mcp`) — Linear maintains the tool surface; this capability ships only the wiring and a skill. **Write-capable**: it can create and update issues, comment, and transition workflow state. There is no read-only flag — scope is the credential's grant. + +## Setup + +Two auth paths, same tool surface: + +- **OAuth (default)** — Services screen → `linear` → **Authenticate**; approve in the browser once, the refresh token persists to `~/.dreadnode/mcp-auth.json`. For headless/SSH set `DREADNODE_HEADLESS=1` (the auth URL is logged; forward the callback port it prints). +- **API key** — set `LINEAR_API_KEY` via the secrets screen (`/secrets`, F7); the header activates automatically and takes precedence over OAuth. For unattended/agent use, prefer an OAuth app install with `actor=app` over a personal key — actions attribute to the app and don't burn a billable seat. + +For enforced read-only, mint a Read-permission key — Linear supports per-key Read / Write / Admin permissions and team scoping, so this is a real boundary even though it lives in the credential rather than the server. (The `gitlab` and `github` connectors can additionally refuse to register write tools server-side; Linear, Atlassian, and Azure DevOps cannot.) + +Auth detail and filter idioms live in `skills/linear/`. diff --git a/capabilities/linear/capability.yaml b/capabilities/linear/capability.yaml new file mode 100644 index 0000000..4131bbf --- /dev/null +++ b/capabilities/linear/capability.yaml @@ -0,0 +1,51 @@ +schema: 1 +name: linear +version: "1.0.0" +description: > + Connect to Linear from chat and agents — search and read issues, + projects, cycles, and teams; create and update issues; comment and + transition state. Talks directly to Linear's hosted MCP server at + https://mcp.linear.app/mcp; first use opens a browser for OAuth, then + subsequent launches reconnect silently using a stored refresh token + (see ~/.dreadnode/mcp-auth.json). + +mcp: + servers: + linear: + url: https://mcp.linear.app/mcp + # Native HTTP MCP + Dreadnode-managed OAuth (CAP-MCP-011). On + # first connect the runtime opens the user's browser to Linear's + # OAuth authorize endpoint and receives the callback on a + # localhost ephemeral port. Tokens persist to disk and refresh + # transparently. 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 LINEAR_API_KEY for a static token + # (CI / service accounts). The optional header is dropped when + # the var is unset (CAP-MCP-013), so OAuth stays the default with + # no empty `Authorization: Bearer` on the wire. When the key is + # set, the static header wins and reactive OAuth stays dormant. + Authorization: + value: "Bearer ${LINEAR_API_KEY}" + optional: true + init_timeout: 60 + +skills: + - skills/linear/ + +author: + name: Dreadnode + url: https://dreadnode.io +license: MIT +repository: https://github.com/dreadnode/capabilities +keywords: + - linear + - issue-tracker + - project-management + - tickets + - tasks + - engineering-workflow + - connector diff --git a/capabilities/linear/skills/linear/SKILL.md b/capabilities/linear/skills/linear/SKILL.md new file mode 100644 index 0000000..f413bfe --- /dev/null +++ b/capabilities/linear/skills/linear/SKILL.md @@ -0,0 +1,62 @@ +--- +name: linear +description: Use when the user wants to connect to Linear, search or read Linear issues / projects / cycles, create or update issues, or set up Linear auth. The connector — not the triage workflow. +--- + +# Linear + +Connector for Linear via its official remote MCP server. The agent sees the tool +surface once it loads — this skill covers auth, scope, the filter model, 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 spec-compliant OAuth (RFC 8414 + 9728 + DCR + PKCE S256); the +runtime drives the flow — no `mcp-remote` bridge. + +### A. Interactive OAuth (default; individual users) + +On first connect, `linear` shows in the Services screen as `needs authentication`. +Click **Authenticate** → browser → approve; tokens persist to +`~/.dreadnode/mcp-auth.json` (mode 0600, keyed by server URL) and refresh silently. +To switch workspaces or after revoking access, Services → `linear` → +**Re-authenticate** (clears just this server's tokens). For SSH/headless, set +`DREADNODE_HEADLESS=1`; the auth URL is logged — complete it on a machine with a +browser and forward the callback port it prints (`ssh -R :localhost:`). + +### B. API key (service / agent accounts) + +For unattended use, **just set one secret** — no manifest edit. The server entry +carries an optional `Authorization` header bound to `LINEAR_API_KEY`: set it and the +static token wins, leave it unset and OAuth (A) stays default. + +1. Linear → **Settings → Account → Security & Access** → generate a key. Per-key + permissions (Read / Write / Admin) and team scoping are supported — pick **Read** + + one team for enforced, least-privilege read-only. +2. Add `LINEAR_API_KEY` in the **secrets screen** (`/secrets` or `F7`) or web app, + reload, confirm with `dn secret list`. Don't paste keys into chat. + +> **Agent identity.** When the consumer is an agent / service, prefer an OAuth app +> install with `actor=app` over a personal key — actions attribute to the app, not +> the installing user, and it doesn't burn a billable seat. +> . + +Scope is enforced by the **key or OAuth grant** — the tool surface is identical +either way, so a write-scoped key can mutate. Want read-only? Issue a read-only key. + +## Filters & idioms + +No JQL-style string — structured search with `team`, `state`, `assignee`, `project`, +`priority`, `labels`, plus a free-text `query`. Compose by argument, not a query +string. Reference: . + +- `ABC-123` (team prefix + number) is the canonical identifier — prefer it over + free-text when the user has it. Internal numeric IDs are a different thing and + rarely what the user means. +- `query` is broad — narrow with `team` / `state` / `project` rather than stuffing + keywords in. +- Use the team's **actual** workflow state names (list them with the team-info tool); + don't guess. Same for labels / projects before creating. +- Cycles are time-boxed — "the current cycle" shifts between calls.