@softspark/ai-toolkit 2.1.3 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -578,28 +578,98 @@ Derived from the immutable safety constitution (5 articles):
578
578
  - **No Secrets in Code**: Never commit credentials, API keys, or sensitive configuration values
579
579
  <!-- TOOLKIT:ai-toolkit END -->
580
580
 
581
- <!-- TOOLKIT:jira-rules START -->
581
+ <!-- TOOLKIT:jira-mcp START -->
582
582
  <!-- Auto-injected by ai-toolkit. Re-run to update. -->
583
583
 
584
584
  # Jira MCP Server
585
585
 
586
- Tools: `sync_tasks`, `read_cached_tasks`, `update_task_status`, `add_task_comment`, `reassign_task`, `get_task_statuses`, `get_task_details`, `log_task_time`, `get_task_time_tracking`
586
+ Tools: `sync_tasks`, `read_cached_tasks`, `update_task_status`, `update_task`, `add_task_comment`, `reassign_task`, `get_task_statuses`, `get_task_details`, `get_project_language`, `log_task_time`, `get_task_time_tracking`, `list_comment_templates`, `add_templated_comment`, `create_task`, `search_tasks`
587
587
 
588
588
  ## Key Rules
589
589
 
590
- - **Always `sync_tasks` first** before reading cache may be stale.
591
- - **Time format:** `"2h 30m"` hours and minutes only, never days.
590
+ - **Always `sync_tasks` first** before reading -- cache may be stale.
591
+ - **Language first:** before writing ANY comment, description, or task content, call `get_project_language(project_key)` or check the `language` field in `get_task_details` response. Write ALL content in the project's configured language. Never assume Polish or English — always check first.
592
+ - **Time format:** `"2h 30m"` -- hours and minutes only, never days.
592
593
  - **Status changes:** call `get_task_statuses` first to check valid transitions.
593
594
  - **Multi-instance:** project key determines which Jira instance is used (mapped in config.json).
595
+ - **Comments are ADF:** `add_task_comment` converts markdown to ADF (Atlassian Document Format) automatically.
596
+ - **Templates:** use `list_comment_templates` to discover available templates, then `add_templated_comment` with `template_id` + `variables`.
594
597
 
595
598
  ## Workflow
596
599
 
597
- 1. `sync_tasks(jql="assignee=currentUser() AND status!=Done")` fetch fresh
598
- 2. `read_cached_tasks()` work offline
599
- 3. `get_task_details(task_key="PROJ-123")` deep dive
600
- 4. `update_task_status(...)` / `add_task_comment(...)` / `log_task_time(...)` mutate
601
-
602
- <!-- TOOLKIT:jira-rules END -->
600
+ 1. `sync_tasks(jql="assignee=currentUser() AND status!=Done")` -- fetch fresh
601
+ 2. `read_cached_tasks()` -- work offline
602
+ 3. `get_task_details(task_key="PROJ-123")` -- deep dive (description + comments as markdown)
603
+ 4. `update_task_status(...)` / `add_task_comment(...)` / `log_task_time(...)` -- mutate
604
+
605
+ ## Comment Templates (built-in)
606
+
607
+ | ID | Use for |
608
+ |----|---------|
609
+ | `status-update` | Progress report with completed/next/blockers |
610
+ | `blocker-notification` | Escalate blocking issue |
611
+ | `handoff-transition` | Task handoff between people |
612
+ | `review-request` | Request code review |
613
+ | `sprint-update` | Sprint progress report |
614
+ | `bug-report` | Structured bug report |
615
+ | `deployment-note` | Deployment documentation |
616
+ | `time-log-summary` | Time logging with description |
617
+
618
+ ## CLI Commands
619
+
620
+ | Command | Description |
621
+ |---------|-------------|
622
+ | `jira-mcp config init` | Initialize global config (~/.softspark/jira-mcp/) |
623
+ | `jira-mcp config add-project <key> <url>` | Add Jira project mapping |
624
+ | `jira-mcp config remove-project <key>` | Remove a project |
625
+ | `jira-mcp config list-projects` | Show configured projects with language |
626
+ | `jira-mcp config set-default <key>` | Set default project |
627
+ | `jira-mcp config set-credentials` | Set API credentials |
628
+ | `jira-mcp config set-language <lang>` | Set global default language |
629
+ | `jira-mcp config set-project-language <key> <lang>` | Set language for a specific project |
630
+ | `jira-mcp create <path>` | Create tasks from template (dry-run default) |
631
+ | `jira-mcp create-monthly` | Create monthly admin tasks |
632
+ | `jira-mcp cache sync-users` | Cache user list for reassignment |
633
+ | `jira-mcp cache sync-workflows` | Cache status transitions |
634
+ | `jira-mcp cache list-users` | Show cached users |
635
+ | `jira-mcp cache list-workflows` | Show cached workflows |
636
+
637
+ ## Architecture
638
+
639
+ Four layers -- each depends only on layers below:
640
+
641
+ 1. **Types & Config** (`config/`, `errors/`, `*/types.ts`) -- pure data, zero runtime deps
642
+ 2. **Infrastructure** (`connector/`, `cache/`, `adf/`, `templates/`) -- I/O and external APIs
643
+ 3. **Business Logic** (`operations/`, `bulk/`) -- orchestrates infrastructure
644
+ 4. **Entry Points** (`tools/`, `cli/`, `server.ts`) -- thin dispatchers
645
+
646
+ ## Coding Conventions
647
+
648
+ - **Strict TypeScript**: `strict: true`, NO `any`, `readonly` interfaces, `import type`, `.js` imports
649
+ - **Zod schemas** for all external data: `type Foo = z.infer<typeof FooSchema>`
650
+ - **Error classes**: extend `JiraMcpError` with `code` property
651
+ - **ADF round-trip**: `markdownToAdf()` for writes, `adfToMarkdown()` for reads -- NEVER throw
652
+ - **InstancePool**: singleton, lazy connectors, dedup by URL
653
+ - **Dual-write**: after Jira mutation, update local cache, return API result
654
+ - **Dry-run default**: `--execute` required for destructive operations
655
+ - **DI pattern**: handlers accept `deps?` parameter for testing
656
+ - **Config path**: ALWAYS `~/.softspark/jira-mcp/` via `GLOBAL_CONFIG_DIR` -- no manual config, no env vars in MCP client setup
657
+ - **SoftSpark standard**: all open-source tools use `~/.softspark/<tool-name>/` -- see SOP in rag-mcp `kb/procedures/softspark-config-standard.md`
658
+
659
+ ## Testing
660
+
661
+ - **Vitest**: 70% coverage threshold, `vi.fn()` for mocks
662
+ - **No real Jira API calls** in tests, use `tests/fixtures/mocks.ts`
663
+ - **Filesystem tests**: `os.tmpdir()` + `mkdtemp()`, NEVER write to `~/.softspark/`
664
+ - Quick pre-commit: `npm run typecheck && npm run lint && npm test && npm run build`
665
+
666
+ ## KB & SOPs
667
+
668
+ - `kb/reference/` -- architecture, api, configuration, adf, caching, templates
669
+ - `kb/howto/` -- setup, multi-instance, cli-usage
670
+ - `kb/procedures/` -- sop-pre-commit, sop-release, sop-post-release-testing
671
+
672
+ <!-- TOOLKIT:jira-mcp END -->
603
673
 
604
674
  <!-- TOOLKIT:rag-mcp-rules START -->
605
675
  <!-- Auto-injected by ai-toolkit. Re-run to update. -->
package/CHANGELOG.md CHANGED
@@ -7,6 +7,32 @@ Versioning follows [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ---
9
9
 
10
+ ## v2.3.0 — Jira MCP Template & Cross-Editor Sync (2026-04-14)
11
+
12
+ ### Added
13
+ - **Jira MCP template** — `ai-toolkit mcp add jira` installs `@softspark/jira-mcp` via global binary. Templates now support `postInstall` field for first-time setup hints shown after `mcp add`, `mcp install`, and `mcp show`. MCP template count: 25 → 26.
14
+ - **MCP template tracking** — globally installed templates are recorded in `state.json`. `ai-toolkit update` automatically syncs tracked templates to Claude global config. `ai-toolkit status` shows tracked MCP templates. "Install once, sync everywhere."
15
+
16
+ ### Fixed
17
+ - **Claude MCP config paths** — corrected to `~/.claude.json` (global) and `.mcp.json` (project) per official Claude Code docs. Previously wrote to `~/.claude/settings.json` and `.claude/settings.local.json`.
18
+ - **Jira MCP template uses global binary** — `jira-mcp` instead of `npx -y` for faster startup and offline support
19
+
20
+ ---
21
+
22
+ ## v2.2.0 — URL Rules & Registry Safety (2026-04-14)
23
+
24
+ ### Added
25
+ - **URL rule registration** — `ai-toolkit add-rule https://...` registers rules from HTTPS URLs. URL-sourced rules are tracked in `rules/sources.json` and auto-refreshed on every `ai-toolkit update`. Falls back to cached local copy on network failure.
26
+ - **Version consistency validation** — `validate.py --strict` now cross-checks `package.json`, `manifest.json`, and `plugin.json` versions match
27
+
28
+ ### Fixed
29
+ - **Project registry race condition** — parallel `install --local` during `ai-toolkit update` could silently drop registry entries. Fixed with `fcntl.flock` exclusive lock, atomic writes (tempfile + rename), and deferred sequential registration after parallel phase.
30
+ - **Version drift** — `manifest.json` and `plugin.json` were stuck at 1.9.0 since v2.0.0, now synced
31
+ - **Language rules count** — ARCHITECTURE.md claimed 70 files, actual is 68
32
+ - **Skills catalog tiers** — added missing Tier 1.5 (planning pipeline + design/architecture)
33
+
34
+ ---
35
+
10
36
  ## v2.1.3 — Idempotent Update Fix (2026-04-13)
11
37
 
12
38
  ### Fixed
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
7
  [![Skills](https://img.shields.io/badge/skills-92-brightgreen)](app/skills/)
8
8
  [![Agents](https://img.shields.io/badge/agents-44-blue)](app/agents/)
9
- [![Tests](https://img.shields.io/badge/tests-598%20passing-success)](tests/)
9
+ [![Tests](https://img.shields.io/badge/tests-606%20passing-success)](tests/)
10
10
 
11
11
  ---
12
12
 
@@ -142,7 +142,7 @@ ai-toolkit/
142
142
  │ └── ARCHITECTURE.md # Full system design
143
143
  ├── kb/ # Reference docs, procedures, plans
144
144
  ├── scripts/ # Validation, install, evaluation scripts
145
- ├── tests/ # Bats test suite (598 tests)
145
+ ├── tests/ # Bats test suite (606 tests)
146
146
  └── CHANGELOG.md
147
147
  ```
148
148
 
@@ -174,7 +174,7 @@ ai-toolkit/
174
174
 
175
175
  **68 language rules** — 13 languages, 5 categories each. Auto-detected or explicit `--lang`. See [Language Rules](kb/reference/language-rules.md).
176
176
 
177
- **25 MCP templates** — Ready-to-use configs for GitHub, PostgreSQL, Slack, Sentry, and more. See [MCP Templates](kb/reference/mcp-templates.md).
177
+ **26 MCP templates** — Ready-to-use configs for GitHub, PostgreSQL, Slack, Jira, Sentry, and more. See [MCP Templates](kb/reference/mcp-templates.md).
178
178
 
179
179
  See [Unique Features](kb/reference/unique-features.md) for detailed descriptions of all differentiators.
180
180
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ai-toolkit",
3
3
  "description": "Professional-grade Claude Code toolkit with persona presets, skill security auditor, expanded lifecycle hooks, experimental opt-in plugin packs, benchmark harvesting, and multi-tool support.",
4
- "version": "1.9.0",
4
+ "version": "2.3.0",
5
5
  "author": {
6
6
  "name": "SoftSpark",
7
7
  "url": "https://github.com/softspark"
@@ -302,9 +302,9 @@ Lead Session (You)
302
302
  ## Extension Points
303
303
 
304
304
  ### MCP Templates (25)
305
- `app/plugins/mcp-templates/` ships 25 ready-to-use MCP server config templates (filesystems, databases, GitHub, Slack, etc.). Opt-in via `ai-toolkit install --modules mcp-templates` or activated automatically with `--profile strict|full`.
305
+ `app/plugins/mcp-templates/` ships 26 ready-to-use MCP server config templates (filesystems, databases, GitHub, Slack, etc.). Opt-in via `ai-toolkit install --modules mcp-templates` or activated automatically with `--profile strict|full`.
306
306
 
307
- ### Language Rules (70 files, 13 languages)
307
+ ### Language Rules (68 files, 13 languages)
308
308
  `app/rules/` contains per-language coding rules. Supported languages: TypeScript, Python, Go, Rust, Java, Kotlin, Swift, Dart, C#, PHP, C++, Ruby, and common (shared). Auto-detected from project files via `--auto-detect` or selected with `--modules rules-<lang>`.
309
309
 
310
310
  Language rules are propagated to **all configured editors** — not just Claude. `dir_rules_shared.build_language_rules()` reads `app/rules/<lang>/*.md`, strips frontmatter, and returns combined content per language. Each directory-based generator (Cursor, Windsurf, Cline, Roo, Augment, Antigravity, Codex) emits `ai-toolkit-lang-<lang>` files in its native format. Registered custom rules (`~/.softspark/ai-toolkit/rules/`) are similarly propagated as `ai-toolkit-custom-<name>` files via `build_registered_rules()`.
@@ -77,6 +77,7 @@ Example -- adding GitHub to `.mcp.json`:
77
77
  | `vercel` | Vercel deployments and settings |
78
78
  | `datadog` | Datadog monitoring and metrics |
79
79
  | `grafana` | Grafana dashboards and alerting |
80
+ | `jira` | Jira multi-instance routing, ADF, caching, comment templates |
80
81
  | `custom-template` | Empty template for custom servers |
81
82
 
82
83
  ## Contributing a new template
@@ -100,6 +101,7 @@ Example -- adding GitHub to `.mcp.json`:
100
101
  ```
101
102
 
102
103
  2. Use `${ENV_VAR}` syntax for any secrets or tokens
103
- 3. Keep the `name` field matching the filename (without `.json`)
104
- 4. Update this README table
105
- 5. Run `python3 scripts/validate.py` to verify
104
+ 3. Optional: add `"postInstall": "setup instructions"` for first-time config hints
105
+ 4. Keep the `name` field matching the filename (without `.json`)
106
+ 5. Update this README table
107
+ 6. Run `python3 scripts/validate.py` to verify
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "jira",
3
+ "description": "Jira integration — multi-instance routing, ADF formatting, task caching, and comment templates",
4
+ "mcpServers": {
5
+ "jira": {
6
+ "command": "jira-mcp",
7
+ "args": []
8
+ }
9
+ },
10
+ "postInstall": "Run 'npm install -g @softspark/jira-mcp && jira-mcp config init' to install and set up credentials."
11
+ }
package/bin/ai-toolkit.js CHANGED
@@ -63,7 +63,7 @@ const COMMANDS = {
63
63
  status: 'Show installed modules, version, and profile from state.json',
64
64
  reset: 'Wipe and recreate project-local configs from scratch (requires --local)',
65
65
  uninstall: 'Remove ai-toolkit from ~/.claude/',
66
- 'add-rule': 'Register a rule file in ~/.softspark/ai-toolkit/rules/ (applied on every install/update)',
66
+ 'add-rule': 'Register a rule file or URL in ~/.softspark/ai-toolkit/rules/ (URL rules auto-refresh on update)',
67
67
  'remove-rule': 'Unregister a rule from ~/.softspark/ai-toolkit/rules/ and remove its block from CLAUDE.md',
68
68
  'inject-hook': 'Inject external hooks into ~/.claude/settings.json (tagged with _source for idempotent updates)',
69
69
  'remove-hook': 'Remove injected hooks by source name from ~/.claude/settings.json',
@@ -232,8 +232,8 @@ function showHelp() {
232
232
  console.log(' <source-name> Source tag to remove (derived from hooks filename stem)');
233
233
  console.log(' [target-dir] Target dir containing .claude/settings.json (default: $HOME)');
234
234
  console.log('\nOptions for add-rule:');
235
- console.log(' <rule-file> Path to .md rule file to register globally');
236
- console.log(' [rule-name] Override rule name (default: filename without .md)');
235
+ console.log(' <rule-file> Path to .md rule file or HTTPS URL to register globally');
236
+ console.log(' [rule-name] Override rule name (default: filename/URL stem without .md)');
237
237
  console.log('\nOptions for plugin:');
238
238
  console.log(' install <name> Install a plugin pack (--editor claude|codex|all)');
239
239
  console.log(' install --all Install all available plugin packs for selected editor(s)');
@@ -333,16 +333,18 @@ function handleRemoveRule(args) {
333
333
  }
334
334
 
335
335
  /**
336
- * Handle `ai-toolkit add-rule` -- validates rule file, resolves absolute path.
336
+ * Handle `ai-toolkit add-rule` -- validates rule file/URL, resolves absolute path.
337
337
  * @param {string[]} args
338
338
  */
339
339
  function handleAddRule(args) {
340
340
  const ruleFile = args[0];
341
341
  if (!ruleFile) {
342
- console.error('Usage: ai-toolkit add-rule <rule-file> [rule-name]');
342
+ console.error('Usage: ai-toolkit add-rule <rule-file-or-url> [rule-name]');
343
343
  process.exit(1);
344
344
  }
345
- const absRuleFile = path.resolve(CWD, ruleFile);
345
+ // Pass URLs through directly (don't resolve as filesystem path)
346
+ const isUrl = ruleFile.startsWith('https://') || ruleFile.startsWith('http://');
347
+ const absRuleFile = isUrl ? ruleFile : path.resolve(CWD, ruleFile);
346
348
  const ruleName = args[1];
347
349
  run(scriptPath('add_rule.py'), ruleName ? [absRuleFile, ruleName] : [absRuleFile]);
348
350
  }
@@ -319,6 +319,7 @@ Follow this sequence before every `npm publish` / `git tag`:
319
319
 
320
320
  ```bash
321
321
  # Edit package.json version field (semver: X.Y.Z)
322
+ # Sync package-lock.json: npm install --package-lock-only
322
323
  # Add entry to CHANGELOG.md
323
324
  ```
324
325
 
@@ -108,8 +108,9 @@ The canonical version lives in `package.json`. These files **must** match:
108
108
  | `README.md` | Badge counts, "What You Get" table |
109
109
  | `app/ARCHITECTURE.md` | Section headings with counts |
110
110
 
111
- > **Tip:** `validate.py --strict` and `npm test` (metadata contract tests) catch
112
- > count drift automatically. If tests pass, counts are correct.
111
+ > **Tip:** `validate.py --strict` catches count drift AND version mismatches
112
+ > (package.json vs manifest.json vs plugin.json) automatically.
113
+ > If validation passes, counts and versions are correct.
113
114
 
114
115
  ### Verification command
115
116
 
@@ -335,7 +335,7 @@ Severity levels: HIGH (blocks deployment), WARN (should fix), INFO (best practic
335
335
  ## Extension Points
336
336
 
337
337
  ### MCP Templates
338
- `app/plugins/mcp-templates/` contains 25 ready-to-use MCP server config templates. Opt-in via `ai-toolkit install --modules mcp-templates` or activated automatically with `--profile strict|full`.
338
+ `app/plugins/mcp-templates/` contains 26 ready-to-use MCP server config templates. Opt-in via `ai-toolkit install --modules mcp-templates` or activated automatically with `--profile strict|full`.
339
339
 
340
340
  ### Language Rules
341
341
  `app/rules/` provides language-specific rule files covering 13 languages (TypeScript, Python, Go, Rust, Java, Kotlin, Swift, Dart, C#, PHP, C++, Ruby, common). Auto-detected from project files via `--auto-detect` or selectable with `--modules rules-<lang>`. See README.md for current count.
@@ -43,7 +43,7 @@ Usage: ai-toolkit <command> [options]
43
43
 
44
44
  | Command | Description |
45
45
  |---------|-------------|
46
- | `mcp list` | List available MCP server templates (25 templates) |
46
+ | `mcp list` | List available MCP server templates (26 templates) |
47
47
  | `mcp editors` | List editors with native MCP config adapters and scopes |
48
48
  | `mcp add <name> [names...]` | Add MCP server template(s) to `.mcp.json` |
49
49
  | `mcp install --editor <name[,..]> [names...]` | Install templates into native editor MCP config |
@@ -39,7 +39,7 @@ Modules are defined in `manifest.json` at the repository root. There are 17 modu
39
39
  | `rules-php` | PHP-specific rules (5 files) | auto-detect |
40
40
  | `rules-cpp` | C++-specific rules (5 files) | auto-detect |
41
41
  | `rules-ruby` | Ruby-specific rules (5 files) | auto-detect |
42
- | `mcp-templates` | 25 MCP server config templates | strict, full |
42
+ | `mcp-templates` | 26 MCP server config templates | strict, full |
43
43
 
44
44
  ## Profiles
45
45
 
@@ -6,14 +6,14 @@ tags: [mcp, templates, servers, configuration, editors]
6
6
  version: "1.1.0"
7
7
  created: "2026-04-07"
8
8
  last_updated: "2026-04-12"
9
- description: "Reference for 25 MCP server templates plus native editor MCP installation support."
9
+ description: "Reference for 26 MCP server templates plus native editor MCP installation support."
10
10
  ---
11
11
 
12
12
  # MCP Server Templates
13
13
 
14
14
  ## Overview
15
15
 
16
- ai-toolkit ships 25 ready-to-use MCP server configuration templates in `app/mcp-templates/`. Each template is a JSON file that defines the canonical `mcpServers` block for a specific service. Templates can be merged into the project's `.mcp.json` and rendered into editor-native MCP config files via the `ai-toolkit mcp` CLI subcommand.
16
+ ai-toolkit ships 26 ready-to-use MCP server configuration templates in `app/mcp-templates/`. Each template is a JSON file that defines the canonical `mcpServers` block for a specific service. Templates can be merged into the project's `.mcp.json` and rendered into editor-native MCP config files via the `ai-toolkit mcp` CLI subcommand.
17
17
 
18
18
  ## CLI
19
19
 
@@ -17,7 +17,9 @@ All functionality is unified under skills. Task and hybrid skills are user-invoc
17
17
 
18
18
  | Tier | Skills | When |
19
19
  |------|--------|------|
20
- | **1 — Quick single-agent** | `/debug`, `/review`, `/refactor`, `/analyze`, `/docs`, `/plan`, `/explain` | One concern, fast |
20
+ | **1 — Quick single-agent** | `/debug`, `/review`, `/refactor`, `/analyze`, `/docs`, `/plan`, `/explain`, `/tdd`, `/grill-me`, `/triage-issue` | One concern, fast |
21
+ | **1.5 — Product planning** | `/write-a-prd` → `/prd-to-plan` → `/prd-to-issues` | Interview-driven PRD → vertical-slice plan → GitHub issues |
22
+ | **1.5 — Design & architecture** | `/design-an-interface`, `/architecture-audit`, `/refactor-plan`, `/ubiquitous-language`, `/qa-session` | Parallel sub-agent exploration |
21
23
  | **2 — Multi-agent workflow** | `/workflow <type>` | Cross-cutting task with known pattern |
22
24
  | **3 — Custom parallelism** | `/orchestrate`, `/swarm` | No predefined workflow matches |
23
25
 
package/llms-full.txt CHANGED
@@ -3441,6 +3441,7 @@ Follow this sequence before every `npm publish` / `git tag`:
3441
3441
 
3442
3442
  ```bash
3443
3443
  # Edit package.json version field (semver: X.Y.Z)
3444
+ # Sync package-lock.json: npm install --package-lock-only
3444
3445
  # Add entry to CHANGELOG.md
3445
3446
  ```
3446
3447
 
@@ -3619,8 +3620,9 @@ The canonical version lives in `package.json`. These files **must** match:
3619
3620
  | `README.md` | Badge counts, "What You Get" table |
3620
3621
  | `app/ARCHITECTURE.md` | Section headings with counts |
3621
3622
 
3622
- > **Tip:** `validate.py --strict` and `npm test` (metadata contract tests) catch
3623
- > count drift automatically. If tests pass, counts are correct.
3623
+ > **Tip:** `validate.py --strict` catches count drift AND version mismatches
3624
+ > (package.json vs manifest.json vs plugin.json) automatically.
3625
+ > If validation passes, counts and versions are correct.
3624
3626
 
3625
3627
  ### Verification command
3626
3628
 
@@ -4772,7 +4774,7 @@ Severity levels: HIGH (blocks deployment), WARN (should fix), INFO (best practic
4772
4774
  ## Extension Points
4773
4775
 
4774
4776
  ### MCP Templates
4775
- `app/plugins/mcp-templates/` contains 25 ready-to-use MCP server config templates. Opt-in via `ai-toolkit install --modules mcp-templates` or activated automatically with `--profile strict|full`.
4777
+ `app/plugins/mcp-templates/` contains 26 ready-to-use MCP server config templates. Opt-in via `ai-toolkit install --modules mcp-templates` or activated automatically with `--profile strict|full`.
4776
4778
 
4777
4779
  ### Language Rules
4778
4780
  `app/rules/` provides language-specific rule files covering 13 languages (TypeScript, Python, Go, Rust, Java, Kotlin, Swift, Dart, C#, PHP, C++, Ruby, common). Auto-detected from project files via `--auto-detect` or selectable with `--modules rules-<lang>`. See README.md for current count.
@@ -5162,7 +5164,7 @@ Usage: ai-toolkit <command> [options]
5162
5164
 
5163
5165
  | Command | Description |
5164
5166
  |---------|-------------|
5165
- | `mcp list` | List available MCP server templates (25 templates) |
5167
+ | `mcp list` | List available MCP server templates (26 templates) |
5166
5168
  | `mcp editors` | List editors with native MCP config adapters and scopes |
5167
5169
  | `mcp add <name> [names...]` | Add MCP server template(s) to `.mcp.json` |
5168
5170
  | `mcp install --editor <name[,..]> [names...]` | Install templates into native editor MCP config |
@@ -7812,7 +7814,7 @@ Modules are defined in `manifest.json` at the repository root. There are 17 modu
7812
7814
  | `rules-php` | PHP-specific rules (5 files) | auto-detect |
7813
7815
  | `rules-cpp` | C++-specific rules (5 files) | auto-detect |
7814
7816
  | `rules-ruby` | Ruby-specific rules (5 files) | auto-detect |
7815
- | `mcp-templates` | 25 MCP server config templates | strict, full |
7817
+ | `mcp-templates` | 26 MCP server config templates | strict, full |
7816
7818
 
7817
7819
  ## Profiles
7818
7820
 
@@ -8016,14 +8018,14 @@ tags: [mcp, templates, servers, configuration, editors]
8016
8018
  version: "1.1.0"
8017
8019
  created: "2026-04-07"
8018
8020
  last_updated: "2026-04-12"
8019
- description: "Reference for 25 MCP server templates plus native editor MCP installation support."
8021
+ description: "Reference for 26 MCP server templates plus native editor MCP installation support."
8020
8022
  ---
8021
8023
 
8022
8024
  # MCP Server Templates
8023
8025
 
8024
8026
  ## Overview
8025
8027
 
8026
- ai-toolkit ships 25 ready-to-use MCP server configuration templates in `app/mcp-templates/`. Each template is a JSON file that defines the canonical `mcpServers` block for a specific service. Templates can be merged into the project's `.mcp.json` and rendered into editor-native MCP config files via the `ai-toolkit mcp` CLI subcommand.
8028
+ ai-toolkit ships 26 ready-to-use MCP server configuration templates in `app/mcp-templates/`. Each template is a JSON file that defines the canonical `mcpServers` block for a specific service. Templates can be merged into the project's `.mcp.json` and rendered into editor-native MCP config files via the `ai-toolkit mcp` CLI subcommand.
8027
8029
 
8028
8030
  ## CLI
8029
8031
 
@@ -8518,7 +8520,9 @@ All functionality is unified under skills. Task and hybrid skills are user-invoc
8518
8520
 
8519
8521
  | Tier | Skills | When |
8520
8522
  |------|--------|------|
8521
- | **1 — Quick single-agent** | `/debug`, `/review`, `/refactor`, `/analyze`, `/docs`, `/plan`, `/explain` | One concern, fast |
8523
+ | **1 — Quick single-agent** | `/debug`, `/review`, `/refactor`, `/analyze`, `/docs`, `/plan`, `/explain`, `/tdd`, `/grill-me`, `/triage-issue` | One concern, fast |
8524
+ | **1.5 — Product planning** | `/write-a-prd` → `/prd-to-plan` → `/prd-to-issues` | Interview-driven PRD → vertical-slice plan → GitHub issues |
8525
+ | **1.5 — Design & architecture** | `/design-an-interface`, `/architecture-audit`, `/refactor-plan`, `/ubiquitous-language`, `/qa-session` | Parallel sub-agent exploration |
8522
8526
  | **2 — Multi-agent workflow** | `/workflow <type>` | Cross-cutting task with known pattern |
8523
8527
  | **3 — Custom parallelism** | `/orchestrate`, `/swarm` | No predefined workflow matches |
8524
8528
 
package/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.9.0",
2
+ "version": "2.3.0",
3
3
  "components": {
4
4
  "agents": {
5
5
  "description": "44 specialized agents (orchestrator, backend, frontend, security, devops, etc.)",
@@ -146,7 +146,7 @@
146
146
  "auto_detect": ["Gemfile", "*.gemspec"]
147
147
  },
148
148
  "mcp-templates": {
149
- "description": "25 MCP server config templates",
149
+ "description": "26 MCP server config templates",
150
150
  "default": false
151
151
  }
152
152
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softspark/ai-toolkit",
3
- "version": "2.1.3",
3
+ "version": "2.3.0",
4
4
  "description": "Professional-grade AI coding toolkit: 92 skills, 44 agents, multi-platform support (Claude, Cursor, Windsurf, Copilot, Gemini, Cline, Roo Code, Aider, Augment, Google Antigravity, Codex CLI), machine-enforced safety constitution, persona presets, skill security auditor, expanded lifecycle hooks, 11 plugin packs, and benchmark tooling.",
5
5
  "keywords": [
6
6
  "claude",
@@ -1,52 +1,94 @@
1
1
  #!/usr/bin/env python3
2
- """add-rule -- Register a rule file in ~/.softspark/ai-toolkit/rules/.
2
+ """add-rule -- Register a rule file or URL in ~/.softspark/ai-toolkit/rules/.
3
3
 
4
4
  Registered rules are automatically injected into all AI tool configs
5
- on next 'ai-toolkit install' or 'ai-toolkit update':
5
+ on next 'ai-toolkit install' or 'ai-toolkit update'.
6
+ URL-sourced rules are auto-refreshed on every update.
7
+
6
8
  Global: Claude, Cursor, Windsurf, Gemini, Augment
7
9
  Local (--local): all of the above + Copilot, Cline, Roo, Aider, Antigravity
8
10
 
9
11
  Usage:
10
- add_rule.py <rule-file> [rule-name]
12
+ add_rule.py <rule-file-or-url> [rule-name]
11
13
 
12
14
  Arguments:
13
- rule-file Path to .md file with the rule content
14
- rule-name Override the rule name (default: filename without .md)
15
+ rule-file-or-url Path to .md file or HTTPS URL to register globally
16
+ rule-name Override the rule name (default: filename without .md)
15
17
  """
16
18
  from __future__ import annotations
17
19
 
18
20
  import re
19
21
  import shutil
20
22
  import sys
23
+ import urllib.parse
21
24
  from pathlib import Path
22
25
 
23
26
  sys.path.insert(0, str(Path(__file__).resolve().parent))
24
27
 
25
28
 
29
+ def _name_from_url(url: str) -> str:
30
+ """Derive a rule name from a URL's last path segment."""
31
+ parsed = urllib.parse.urlparse(url)
32
+ filename = parsed.path.rstrip("/").split("/")[-1]
33
+ stem = filename.rsplit(".", 1)[0] if "." in filename else filename
34
+ return re.sub(r"[^a-zA-Z0-9_-]", "", stem)
35
+
36
+
26
37
  def main() -> None:
27
- """Register a rule file in the global rules directory."""
38
+ """Register a rule file or URL in the global rules directory."""
28
39
  if len(sys.argv) < 2:
29
- print("Usage: add_rule.py <rule-file> [rule-name]", file=sys.stderr)
40
+ print("Usage: add_rule.py <rule-file-or-url> [rule-name]", file=sys.stderr)
30
41
  sys.exit(1)
31
42
 
32
- rule_file = Path(sys.argv[1])
33
- if not rule_file.is_file():
34
- print(f"Rule file not found: {rule_file}", file=sys.stderr)
35
- sys.exit(1)
43
+ source = sys.argv[1]
44
+ is_url = source.startswith("https://") or source.startswith("http://")
36
45
 
37
- rule_name = sys.argv[2] if len(sys.argv) > 2 else rule_file.stem
38
- rule_name = re.sub(r"[^a-zA-Z0-9_-]", "", rule_name)
39
- if not rule_name:
40
- print("Error: rule name is empty after sanitization", file=sys.stderr)
46
+ if is_url and source.startswith("http://"):
47
+ print("Error: only HTTPS URLs are supported. Use https:// for security.", file=sys.stderr)
41
48
  sys.exit(1)
49
+
42
50
  from paths import RULES_DIR
43
51
  rules_dir = RULES_DIR
44
52
  rules_dir.mkdir(parents=True, exist_ok=True)
45
53
 
46
- dest = rules_dir / f"{rule_name}.md"
47
- shutil.copy2(rule_file, dest)
54
+ if is_url:
55
+ from rule_sources import fetch_url, register_url_source
56
+
57
+ rule_name = sys.argv[2] if len(sys.argv) > 2 else _name_from_url(source)
58
+ rule_name = re.sub(r"[^a-zA-Z0-9_-]", "", rule_name)
59
+ if not rule_name:
60
+ print("Error: could not derive rule name from URL. Provide one explicitly.", file=sys.stderr)
61
+ sys.exit(1)
62
+
63
+ try:
64
+ data = fetch_url(source)
65
+ except Exception as exc:
66
+ print(f"Error fetching URL: {exc}", file=sys.stderr)
67
+ sys.exit(1)
68
+
69
+ dest = rules_dir / f"{rule_name}.md"
70
+ dest.write_bytes(data)
71
+ register_url_source(rules_dir, rule_name, source)
72
+
73
+ print(f"Registered: '{rule_name}' -> {dest}")
74
+ print(f"Source URL: {source} (auto-refreshed on update)")
75
+ else:
76
+ rule_file = Path(source)
77
+ if not rule_file.is_file():
78
+ print(f"Rule file not found: {rule_file}", file=sys.stderr)
79
+ sys.exit(1)
80
+
81
+ rule_name = sys.argv[2] if len(sys.argv) > 2 else rule_file.stem
82
+ rule_name = re.sub(r"[^a-zA-Z0-9_-]", "", rule_name)
83
+ if not rule_name:
84
+ print("Error: rule name is empty after sanitization", file=sys.stderr)
85
+ sys.exit(1)
86
+
87
+ dest = rules_dir / f"{rule_name}.md"
88
+ shutil.copy2(rule_file, dest)
89
+
90
+ print(f"Registered: '{rule_name}' -> {dest}")
48
91
 
49
- print(f"Registered: '{rule_name}' -> {dest}")
50
92
  print()
51
93
  print("Apply now:")
52
94
  print(" ai-toolkit update # global (Claude, Cursor, Windsurf, Gemini, Augment)")
@@ -212,6 +212,7 @@ def parse_args(argv: list[str]) -> dict:
212
212
  "editors": "",
213
213
  "config": "",
214
214
  "refresh_base": False,
215
+ "skip_register": False,
215
216
  }
216
217
  i = 0
217
218
  while i < len(argv):
@@ -268,6 +269,8 @@ def parse_args(argv: list[str]) -> dict:
268
269
  cfg["config"] = argv[i] if i < len(argv) else ""
269
270
  elif arg == "--refresh-base":
270
271
  cfg["refresh_base"] = True
272
+ elif arg == "--skip-register":
273
+ cfg["skip_register"] = True
271
274
  elif arg.startswith("-"):
272
275
  print(f"Unknown option: {arg}")
273
276
  sys.exit(1)
@@ -426,7 +429,40 @@ def install_claude_code(target_dir: Path, hooks_scripts_dir: Path,
426
429
  print()
427
430
  print(f" Available: {count_agents()} agents, {count_skills()} skills")
428
431
 
429
- inject_rules(claude_dir, target_dir, rules_dir, only, skip, dry_run)
432
+ inject_rules(claude_dir, target_dir, rules_dir, only, skip, dry_run,
433
+ refresh_urls=True)
434
+
435
+ _sync_mcp_templates(dry_run)
436
+
437
+
438
+ def _sync_mcp_templates(dry_run: bool) -> None:
439
+ """Re-install tracked MCP templates into Claude global config."""
440
+ from install_steps.install_state import get_mcp_templates
441
+
442
+ templates = get_mcp_templates()
443
+ if not templates:
444
+ return
445
+
446
+ if dry_run:
447
+ print(f" Would sync MCP templates: {', '.join(templates)}")
448
+ return
449
+
450
+ from mcp_editors import install_servers
451
+
452
+ servers: dict = {}
453
+ for name in templates:
454
+ try:
455
+ tpl_path = app_dir / "mcp-templates" / f"{name}.json"
456
+ if tpl_path.is_file():
457
+ import json as _json
458
+ data = _json.loads(tpl_path.read_text(encoding="utf-8"))
459
+ servers.update(data.get("mcpServers", {}))
460
+ except Exception:
461
+ pass # Skip broken templates silently
462
+
463
+ if servers:
464
+ install_servers(["claude"], servers, scope="global")
465
+ print(f" MCP synced: {', '.join(templates)}")
430
466
 
431
467
 
432
468
  VALID_PERSONAS = ("backend-lead", "frontend-lead", "devops-eng", "junior-dev")
@@ -711,7 +747,9 @@ def main() -> None:
711
747
  )
712
748
 
713
749
  # Register project in global registry (for `ai-toolkit update` propagation)
714
- if local:
750
+ # Skipped when called from update_projects.py (--skip-register) to avoid
751
+ # concurrent writes to projects.json during parallel updates.
752
+ if local and not cfg.get("skip_register"):
715
753
  extends_source = ""
716
754
  if extends_info:
717
755
  extends_source = extends_info.get("source", "")