diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 2a6e88d..b76e318 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fullstack-dev-kit", - "version": "0.19.16", + "version": "0.19.17", "description": "Issue-to-PR workflow kit for any tech stack. Fetch a user story from your tracker (Jira, Linear, GitHub Issues, Azure DevOps) and any linked Figma designs, implement with plan approval, enforce >95% coverage and a security pass, generate e2e tests, open the PR, fix review findings, and move the ticket to review.", "license": "Apache-2.0", "homepage": "https://github.com/theam/claude-dev-kit", diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e75039..46b7eec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ a release is only "live" for users once that is bumped and published. ## [Unreleased] ### Added +- **Jira REST fallback auto-activates when the MCP is blocked, and is documented up front.** Building on the REST fallback below: `issue-fetch` now checks the Atlassian MCP is actually usable first, and when it's **unavailable or blocked by policy** (e.g. an enterprise that disables third-party MCPs) and the `JIRA_*` env vars are present, it **uses REST automatically** and offers to **persist `authMode: "rest"`** so later runs skip the blocked MCP instead of retrying it. `dev-kit-setup` sets `authMode: "rest"` when it detects the MCP is blocked. The README's *Connect your tracker* section now documents the no-MCP path (the `.env` vars, where the token comes from) instead of leaving it in a footnote. Kit → **0.19.17**. - **Jira REST + token fallback (no MCP required).** Clients without the Atlassian MCP can now use Jira by setting `"authMode": "rest"` in the tracker config: `issue-fetch` and `issue-update` call the Jira REST API directly with credentials from the **environment** — `JIRA_EMAIL` + `JIRA_API_TOKEN` (Cloud, Basic auth) or `JIRA_PAT` (Server/DC, Bearer), plus `JIRA_BASE_URL` — kept in a git-ignored `.env`, never in `.claude/dev-kit.json` (which stays secret-free). Default stays `"mcp"`, and the kit falls back to REST automatically if the MCP is unavailable but the `JIRA_*` vars are present. `dev-kit-setup` offers the mode and resolves field IDs via the REST field API when there's no MCP. Removes the "MCP-only" adoption barrier for Jira and matches the token pattern already used by the Bitbucket/GitLab PR hosts. Kit → **0.19.16**. ### Fixed diff --git a/README.md b/README.md index 5f26284..2da955e 100644 --- a/README.md +++ b/README.md @@ -205,6 +205,20 @@ Authorization is **per developer, one-time** — it persists across sessions. Th > When authorizing an MCP via OAuth, complete the browser flow **immediately** — the link is tied to a live local callback and expires with it. Don't reuse old tabs or restart the session mid-flow. +**No Atlassian MCP? (enterprise-blocked, or you just don't use it.)** Jira also works over its **REST API** with a token — no MCP required. Set `"authMode": "rest"` in the tracker block of `.claude/dev-kit.json` and put the credentials in a **git-ignored `.env`** (never in the committed config): + +```bash +# Jira Cloud +JIRA_BASE_URL=https://.atlassian.net +JIRA_EMAIL=you@company.com +JIRA_API_TOKEN= + +# Jira Server / Data Center (instead of the two above) +# JIRA_PAT= +``` + +The kit also **detects this for you**: if the Atlassian MCP is unavailable or blocked and those `JIRA_*` vars are present, it uses REST automatically and offers to persist `authMode: "rest"` so later runs skip the blocked MCP. `dev-kit-setup` will set it up if you ask (*"connect Jira over REST"*). + --- # Using it @@ -313,4 +327,4 @@ The kit can share **anonymous token counts** so the maintainers can show aggrega [Apache 2.0](./LICENSE) © The Agile Monkeys. See [NOTICE](./NOTICE). -> Headless/CI runs can't do MCP OAuth. **Jira** already has a REST + token fallback for clients without the Atlassian MCP — set `"authMode": "rest"` in the tracker config and supply credentials via the environment (`JIRA_EMAIL` + `JIRA_API_TOKEN` for Cloud, or `JIRA_PAT` for Server/DC, plus `JIRA_BASE_URL`; keep them in a git-ignored `.env`, never in `.claude/dev-kit.json`). The other trackers' token fallbacks can be added the same way. +> Headless/CI runs can't do MCP OAuth. **Jira** has a REST + token fallback for exactly this (and for enterprise-blocked MCPs) — see [Connect your tracker](#connect-your-tracker-one-time) above (`"authMode": "rest"` + a git-ignored `.env`). The other trackers' token fallbacks can be added the same way. diff --git a/plugins/fullstack-dev-kit/.codex-plugin/plugin.json b/plugins/fullstack-dev-kit/.codex-plugin/plugin.json index 2d731b9..165edc6 100644 --- a/plugins/fullstack-dev-kit/.codex-plugin/plugin.json +++ b/plugins/fullstack-dev-kit/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fullstack-dev-kit", - "version": "0.19.16", + "version": "0.19.17", "description": "Issue-to-PR workflow for any tech stack: fetch stories from Jira/Linear/GitHub/Azure and Figma designs, plan-approval gate, adaptive quality + coverage gates, e2e generation, PR creation and review.", "author": { "name": "The Agile Monkeys", diff --git a/plugins/fullstack-dev-kit/.cursor-plugin/plugin.json b/plugins/fullstack-dev-kit/.cursor-plugin/plugin.json index d261cf1..efc45ef 100644 --- a/plugins/fullstack-dev-kit/.cursor-plugin/plugin.json +++ b/plugins/fullstack-dev-kit/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fullstack-dev-kit", - "version": "0.19.16", + "version": "0.19.17", "description": "Issue-to-PR workflow for any tech stack: fetch stories from Jira/Linear/GitHub/Azure and Figma designs, plan-approval gate, adaptive quality + coverage gates, e2e generation, PR creation and review.", "author": { "name": "The Agile Monkeys" diff --git a/plugins/fullstack-dev-kit/plugin.json b/plugins/fullstack-dev-kit/plugin.json index 3598298..b799687 100644 --- a/plugins/fullstack-dev-kit/plugin.json +++ b/plugins/fullstack-dev-kit/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "fullstack-dev-kit", - "version": "0.19.16", + "version": "0.19.17", "description": "Issue-to-PR workflow for any tech stack: fetch stories from Jira/Linear/GitHub/Azure and Figma designs, plan-approval gate, adaptive quality + coverage gates, e2e generation, PR creation and review.", "author": { "name": "The Agile Monkeys", diff --git a/plugins/fullstack-dev-kit/skills/dev-kit-setup/SKILL.md b/plugins/fullstack-dev-kit/skills/dev-kit-setup/SKILL.md index 917d1ec..2f871bc 100644 --- a/plugins/fullstack-dev-kit/skills/dev-kit-setup/SKILL.md +++ b/plugins/fullstack-dev-kit/skills/dev-kit-setup/SKILL.md @@ -31,7 +31,7 @@ Run the command for them when you can; the OAuth/browser sign-in is always the u ## 2. Discover per tracker ### Jira -- **Auth mode**: default is the **Atlassian MCP**. **If the client has no Atlassian MCP**, offer `authMode: "rest"` — the kit calls the Jira REST API with credentials from the **environment**: `JIRA_EMAIL` + `JIRA_API_TOKEN` (Cloud, Basic auth) or `JIRA_PAT` (Server/DC, Bearer), plus `JIRA_BASE_URL`. Store `authMode` in the config and tell the user to put the credentials in `.env` and add `.env` to `.gitignore` — they never go in `.claude/dev-kit.json`. +- **Auth mode**: default is the **Atlassian MCP**. **If the Atlassian MCP is unavailable or blocked** (not installed, not authorized, or disabled by an enterprise policy), set `authMode: "rest"` and persist it — so the kit stops retrying the blocked MCP and uses REST from then on. In REST mode the kit calls the Jira REST API with credentials from the **environment**: `JIRA_EMAIL` + `JIRA_API_TOKEN` (Cloud, Basic auth) or `JIRA_PAT` (Server/DC, Bearer), plus `JIRA_BASE_URL`. Tell the user to put the credentials in `.env` and add `.env` to `.gitignore` — they never go in `.claude/dev-kit.json`. - **Site**: list accessible sites via the Atlassian MCP — one → use it; several → ask which. (In `rest` mode, use `JIRA_BASE_URL` / the site the user gives.) - **Project key**: derive from the triggering ticket prefix and verify it exists; otherwise list projects and ask. - **Custom fields (auto-detect, no questions)**: resolve field IDs by matching names case-insensitively — Acceptance Criteria ("Acceptance Criteria"/"AC"), Sprint ("Sprint"), Story Points ("Story Points"/"Story point estimate"). If a name matches nothing, inspect a recent issue's custom fields; if still ambiguous, ask once showing the candidates. (In `rest` mode, resolve field IDs via `GET /rest/api/3/field`.) diff --git a/plugins/fullstack-dev-kit/skills/issue-fetch/SKILL.md b/plugins/fullstack-dev-kit/skills/issue-fetch/SKILL.md index f360e7b..0631538 100644 --- a/plugins/fullstack-dev-kit/skills/issue-fetch/SKILL.md +++ b/plugins/fullstack-dev-kit/skills/issue-fetch/SKILL.md @@ -45,7 +45,7 @@ Config: `site`, `cloudId`, `projectKey`, `fields` (custom field IDs for acceptan - Fetch: `GET /rest/api/3/issue/?fields=summary,description,status,comment,,,` (use `/rest/api/2/` on older Server). Read acceptance criteria from the configured `fields` IDs and comments from `fields.comment.comments`. - If a required env var is missing, **stop** and tell the user exactly which to set, and to add `.env` to `.gitignore` — never invent credentials or fetch without them. -**Automatic fallback.** If `authMode` is unset or `"mcp"` but the Atlassian MCP is unavailable/unauthorized and the `JIRA_*` env vars are present, use REST and say so. If neither the MCP nor the env credentials are available, stop and offer both paths (authorize the MCP, or set `authMode: "rest"` + the env vars). +**Automatic fallback (MCP unavailable or blocked).** When `authMode` is unset or `"mcp"`, first check the Atlassian MCP is actually usable. If it is **not** — not installed, not authorized, or **blocked by policy** (e.g. an enterprise that disables third-party MCPs) — and the `JIRA_*` env vars are present, **use REST automatically** and say so. Don't repeatedly retry a blocked MCP: when the block looks permanent (a policy/enterprise block rather than a missing one-time OAuth), **offer to persist `authMode: "rest"`** in `.claude/dev-kit.json` so every later run goes straight to REST. If neither the MCP nor the env credentials are available, stop and offer both paths (authorize the MCP, or set `authMode: "rest"` + the env vars). - If a configured field ID turns out to be invalid, re-run `dev-kit-setup` discovery for that field and update the config. diff --git a/skills/dev-kit-setup/SKILL.md b/skills/dev-kit-setup/SKILL.md index 917d1ec..2f871bc 100644 --- a/skills/dev-kit-setup/SKILL.md +++ b/skills/dev-kit-setup/SKILL.md @@ -31,7 +31,7 @@ Run the command for them when you can; the OAuth/browser sign-in is always the u ## 2. Discover per tracker ### Jira -- **Auth mode**: default is the **Atlassian MCP**. **If the client has no Atlassian MCP**, offer `authMode: "rest"` — the kit calls the Jira REST API with credentials from the **environment**: `JIRA_EMAIL` + `JIRA_API_TOKEN` (Cloud, Basic auth) or `JIRA_PAT` (Server/DC, Bearer), plus `JIRA_BASE_URL`. Store `authMode` in the config and tell the user to put the credentials in `.env` and add `.env` to `.gitignore` — they never go in `.claude/dev-kit.json`. +- **Auth mode**: default is the **Atlassian MCP**. **If the Atlassian MCP is unavailable or blocked** (not installed, not authorized, or disabled by an enterprise policy), set `authMode: "rest"` and persist it — so the kit stops retrying the blocked MCP and uses REST from then on. In REST mode the kit calls the Jira REST API with credentials from the **environment**: `JIRA_EMAIL` + `JIRA_API_TOKEN` (Cloud, Basic auth) or `JIRA_PAT` (Server/DC, Bearer), plus `JIRA_BASE_URL`. Tell the user to put the credentials in `.env` and add `.env` to `.gitignore` — they never go in `.claude/dev-kit.json`. - **Site**: list accessible sites via the Atlassian MCP — one → use it; several → ask which. (In `rest` mode, use `JIRA_BASE_URL` / the site the user gives.) - **Project key**: derive from the triggering ticket prefix and verify it exists; otherwise list projects and ask. - **Custom fields (auto-detect, no questions)**: resolve field IDs by matching names case-insensitively — Acceptance Criteria ("Acceptance Criteria"/"AC"), Sprint ("Sprint"), Story Points ("Story Points"/"Story point estimate"). If a name matches nothing, inspect a recent issue's custom fields; if still ambiguous, ask once showing the candidates. (In `rest` mode, resolve field IDs via `GET /rest/api/3/field`.) diff --git a/skills/issue-fetch/SKILL.md b/skills/issue-fetch/SKILL.md index f360e7b..0631538 100644 --- a/skills/issue-fetch/SKILL.md +++ b/skills/issue-fetch/SKILL.md @@ -45,7 +45,7 @@ Config: `site`, `cloudId`, `projectKey`, `fields` (custom field IDs for acceptan - Fetch: `GET /rest/api/3/issue/?fields=summary,description,status,comment,,,` (use `/rest/api/2/` on older Server). Read acceptance criteria from the configured `fields` IDs and comments from `fields.comment.comments`. - If a required env var is missing, **stop** and tell the user exactly which to set, and to add `.env` to `.gitignore` — never invent credentials or fetch without them. -**Automatic fallback.** If `authMode` is unset or `"mcp"` but the Atlassian MCP is unavailable/unauthorized and the `JIRA_*` env vars are present, use REST and say so. If neither the MCP nor the env credentials are available, stop and offer both paths (authorize the MCP, or set `authMode: "rest"` + the env vars). +**Automatic fallback (MCP unavailable or blocked).** When `authMode` is unset or `"mcp"`, first check the Atlassian MCP is actually usable. If it is **not** — not installed, not authorized, or **blocked by policy** (e.g. an enterprise that disables third-party MCPs) — and the `JIRA_*` env vars are present, **use REST automatically** and say so. Don't repeatedly retry a blocked MCP: when the block looks permanent (a policy/enterprise block rather than a missing one-time OAuth), **offer to persist `authMode: "rest"`** in `.claude/dev-kit.json` so every later run goes straight to REST. If neither the MCP nor the env credentials are available, stop and offer both paths (authorize the MCP, or set `authMode: "rest"` + the env vars). - If a configured field ID turns out to be invalid, re-run `dev-kit-setup` discovery for that field and update the config.