ima-claude 2.16.0 → 2.20.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.
Files changed (41) hide show
  1. package/README.md +16 -1
  2. package/dist/cli.js +9 -1
  3. package/package.json +1 -1
  4. package/plugins/ima-claude/.claude-plugin/plugin.json +2 -2
  5. package/plugins/ima-claude/agents/wp-developer.md +2 -1
  6. package/plugins/ima-claude/hooks/prompt_coach_digest.md +1 -1
  7. package/plugins/ima-claude/skills/agentic-workflows/SKILL.md +133 -0
  8. package/plugins/ima-claude/skills/agentic-workflows/references/phases/deliver.md +181 -0
  9. package/plugins/ima-claude/skills/agentic-workflows/references/phases/draft.md +99 -0
  10. package/plugins/ima-claude/skills/agentic-workflows/references/phases/gather.md +130 -0
  11. package/plugins/ima-claude/skills/agentic-workflows/references/phases/outline.md +106 -0
  12. package/plugins/ima-claude/skills/agentic-workflows/references/phases/review.md +137 -0
  13. package/plugins/ima-claude/skills/agentic-workflows/references/standards/draft-format.md +159 -0
  14. package/plugins/ima-claude/skills/agentic-workflows/references/standards/editorial-standards.md +160 -0
  15. package/plugins/ima-claude/skills/agentic-workflows/references/standards/outline-format.md +110 -0
  16. package/plugins/ima-claude/skills/agentic-workflows/references/templates/avada-construction-guide.md +263 -0
  17. package/plugins/ima-claude/skills/agentic-workflows/references/templates/avada-webinar-example.txt +275 -0
  18. package/plugins/ima-claude/skills/agentic-workflows/references/templates/cta-block-catalog.md +169 -0
  19. package/plugins/ima-claude/skills/agentic-workflows/references/templates/espo-email-preparation.md +241 -0
  20. package/plugins/ima-claude/skills/agentic-workflows/references/templates/webinar-recap-email-espo.html +339 -0
  21. package/plugins/ima-claude/skills/agentic-workflows/references/templates/webinar-reminder-email-espo.html +458 -0
  22. package/plugins/ima-claude/skills/agentic-workflows/references/workflows/editorial/webinar-summary.md +81 -0
  23. package/plugins/ima-claude/skills/design-to-code/SKILL.md +126 -0
  24. package/plugins/ima-claude/skills/design-to-code/references/guardrails.md +46 -0
  25. package/plugins/ima-claude/skills/design-to-code/references/phase-a-design-to-prompt.md +141 -0
  26. package/plugins/ima-claude/skills/design-to-code/references/phase-b-prompt-to-code.md +155 -0
  27. package/plugins/ima-claude/skills/design-to-code/references/prompt-template.md +95 -0
  28. package/plugins/ima-claude/skills/espocrm/SKILL.md +79 -0
  29. package/plugins/ima-claude/skills/espocrm-api/SKILL.md +360 -0
  30. package/plugins/ima-claude/skills/espocrm-api/references/where-operators.md +84 -0
  31. package/plugins/ima-claude/skills/functional-programmer/SKILL.md +15 -0
  32. package/plugins/ima-claude/skills/mcp-atlassian/SKILL.md +94 -14
  33. package/plugins/ima-claude/skills/mcp-atlassian/references/direct-api-attachments.md +115 -0
  34. package/plugins/ima-claude/skills/mcp-atlassian/references/direct-api-auth.md +103 -0
  35. package/plugins/ima-claude/skills/mcp-atlassian/references/direct-api-bulk.md +149 -0
  36. package/plugins/ima-claude/skills/mcp-atlassian/references/direct-api-misc.md +195 -0
  37. package/plugins/ima-claude/skills/mcp-atlassian/references/direct-api-sprints.md +158 -0
  38. package/plugins/ima-claude/skills/prompt-starter/SKILL.md +9 -6
  39. package/plugins/ima-claude/skills/wp-ddev/SKILL.md +264 -0
  40. package/plugins/ima-claude/skills/wp-ddev/references/ddev-commands.md +232 -0
  41. package/plugins/ima-claude/skills/wp-ddev/references/wp-cli-reference.md +406 -0
@@ -0,0 +1,360 @@
1
+ ---
2
+ name: "espocrm-api"
3
+ description: >-
4
+ EspoCRM v9.x REST API patterns — authentication (API Key, HMAC), CRUD operations,
5
+ JSON WHERE filtering, relationship management, webhooks, mass operations, error
6
+ handling, and performance. Official PHP client and Node.js patterns. Use when:
7
+ calling EspoCRM API, building CRM integrations, querying CRM data, managing
8
+ webhooks, bulk CRM operations. Triggers on: EspoCRM API, CRM endpoint, CRM
9
+ query, CRM webhook, CRM filter, espo api, api/v1, X-Api-Key, HMAC auth,
10
+ entity CRUD.
11
+ ---
12
+
13
+ # EspoCRM REST API (v9.x)
14
+
15
+ Patterns for the EspoCRM REST API. External integrations, data pipelines, and automation.
16
+
17
+ **Base URL**: `https://{your-site}/api/v1/`
18
+ **Content-Type**: `application/json` (all requests)
19
+ **Parent skill**: `espocrm` (router — Salesforce mapping, shared context)
20
+ **Companion skills**: `php-fp` (PHP integrations), `js-fp-api` (Node integrations)
21
+ **Live docs**: Context7 `/espocrm/documentation`
22
+
23
+ ---
24
+
25
+ ## Authentication
26
+
27
+ Three methods, in order of recommendation:
28
+
29
+ ### 1. API Key (Simple, Recommended for Dev/Internal)
30
+
31
+ Create an API User at Administration > API Users. Authentication method: "API Key". Assign a Role for scope.
32
+
33
+ ```
34
+ X-Api-Key: {key_from_api_user_detail_view}
35
+ ```
36
+
37
+ One header. Done. Use when transport is already secured (HTTPS, internal network).
38
+
39
+ ### 2. HMAC (Production, Most Secure)
40
+
41
+ Create an API User with "HMAC" auth. Both API Key and Secret Key are generated. Secret never leaves your server.
42
+
43
+ ```
44
+ X-Hmac-Authorization: base64(apiKey + ':' + hmacSha256(METHOD + ' /' + uri, secretKey))
45
+ ```
46
+
47
+ Where `METHOD` is uppercase (GET, POST, PUT, DELETE) and `uri` is the path after `/api/v1/`.
48
+
49
+ ```php
50
+ // PHP
51
+ $string = $method . ' /' . $uri;
52
+ $hash = hash_hmac('sha256', $string, $secretKey);
53
+ $header = base64_encode($apiKey . ':' . $hash);
54
+ // X-Hmac-Authorization: $header
55
+ ```
56
+
57
+ ```javascript
58
+ // Node.js
59
+ import { createHmac } from 'node:crypto';
60
+ const hash = createHmac('sha256', secretKey).update(`${method} /${uri}`).digest('hex');
61
+ const header = Buffer.from(`${apiKey}:${hash}`).toString('base64');
62
+ // X-Hmac-Authorization: header
63
+ ```
64
+
65
+ ### 3. Basic / Token Auth (Session-Based Only)
66
+
67
+ ```
68
+ Espo-Authorization: base64(username + ':' + token)
69
+ ```
70
+
71
+ Obtain token via `GET App/user` with initial credentials. Only for session flows (SPA, frontend). Never for server-to-server.
72
+
73
+ ### Auth Decision
74
+
75
+ | Context | Method |
76
+ |---|---|
77
+ | Dev/testing, internal scripts | API Key |
78
+ | Production integrations | HMAC |
79
+ | Frontend SPA, session flows | Token auth |
80
+ | Never | Basic auth with plaintext password |
81
+
82
+ ---
83
+
84
+ ## CRUD Operations
85
+
86
+ All entity types share the same endpoint pattern. Replace `{Entity}` with the type name (Account, Contact, Lead, CMyCustomEntity, etc.).
87
+
88
+ ### List Records
89
+ ```
90
+ GET {Entity}
91
+ ```
92
+ Returns `{"list": [...], "total": N}`. Total is `-1` if more records exist (pagination needed), `-2` if count disabled.
93
+
94
+ ### Read One Record
95
+ ```
96
+ GET {Entity}/{id}
97
+ ```
98
+
99
+ ### Create
100
+ ```
101
+ POST {Entity}
102
+ {"name": "Acme Corp", "assignedUserId": "someUserId"}
103
+ ```
104
+ Returns the created record with generated `id`. Use `X-Skip-Duplicate-Check: true` to bypass duplicate detection.
105
+
106
+ ### Update (Partial)
107
+ ```
108
+ PUT {Entity}/{id}
109
+ {"status": "Closed Won"}
110
+ ```
111
+ Only send changed fields. Returns full updated record.
112
+
113
+ ### Delete
114
+ ```
115
+ DELETE {Entity}/{id}
116
+ ```
117
+ Returns `true`.
118
+
119
+ ### Endpoint Summary
120
+
121
+ | Operation | Method | Path |
122
+ |---|---|---|
123
+ | List | GET | `{Entity}` |
124
+ | Read | GET | `{Entity}/{id}` |
125
+ | Create | POST | `{Entity}` |
126
+ | Update | PUT | `{Entity}/{id}` |
127
+ | Delete | DELETE | `{Entity}/{id}` |
128
+ | List related | GET | `{Entity}/{id}/{link}` |
129
+ | Link | POST | `{Entity}/{id}/{link}` |
130
+ | Unlink | DELETE | `{Entity}/{id}/{link}` |
131
+ | Mass update | POST | `{Entity}/action/massUpdate` |
132
+ | Mass delete | POST | `{Entity}/action/massDelete` |
133
+ | Stream/notes | GET | `{Entity}/{id}/stream` |
134
+ | Webhook CRUD | POST/DELETE | `Webhook` / `Webhook/{id}` |
135
+ | Auth token | GET | `App/user` |
136
+ | Attachment up | POST | `Attachment` |
137
+ | Attachment down | GET | `Attachment/file/{id}` |
138
+ | OpenAPI spec | GET | `OpenApi` |
139
+
140
+ ---
141
+
142
+ ## Filtering & Search
143
+
144
+ Parameters go as query params or as a single JSON-encoded `searchParams` param.
145
+
146
+ ### Core Parameters
147
+
148
+ | Param | Type | Purpose |
149
+ |---|---|---|
150
+ | `select` | string | Comma-separated fields: `id,name,status` |
151
+ | `maxSize` | int | Records per page (max 200, default varies) |
152
+ | `offset` | int | Pagination offset |
153
+ | `orderBy` | string | Sort field |
154
+ | `order` | string | `asc` or `desc` |
155
+ | `where` | array | Filter conditions (see below) |
156
+ | `primaryFilter` | string | Named server-side filter (`open`, `onlyMy`, etc.) |
157
+ | `boolFilterList` | array | Boolean toggles: `["onlyMy", "followed"]` |
158
+
159
+ v9.0+ aliases (WAF-safe): `attributeSelect` for `select`, `whereGroup` for `where`.
160
+
161
+ ### WHERE Operators
162
+
163
+ Each filter is `{"type": "...", "attribute": "...", "value": "..."}`. Multiple items in the `where` array are implicitly ANDed. Use `{"type": "or", "value": [...]}` for OR logic.
164
+
165
+ **Operator categories**: equality (`equals`, `notEquals`), comparison (`greaterThan`, `lessThan`, `greaterThanOrEquals`, `lessThanOrEquals`), null (`isNull`, `isNotNull`), boolean (`isTrue`, `isFalse`), string (`contains`, `notContains`, `startsWith`, `endsWith`, `like`, `notLike`), set (`in`, `notIn`), relationship (`linkedWith`, `notLinkedWith`, `isLinked`, `isNotLinked`), date helpers (`today`, `past`, `future`, `lastSevenDays`, `currentMonth`, `lastMonth`, `currentYear`, `between`, `lastXDays`, `nextXDays`), logical (`or`, `and`).
166
+
167
+ Full operator reference with examples: `references/where-operators.md`
168
+
169
+ ---
170
+
171
+ ## Relationships
172
+
173
+ Link names are visible at Administration > Entity Manager > {Entity} > Relationships (4th column).
174
+
175
+ ### List Related Records
176
+ ```
177
+ GET Account/{id}/contacts?select=id,name,emailAddress&maxSize=50
178
+ ```
179
+ Same search params as list endpoint.
180
+
181
+ ### Link Records
182
+ ```
183
+ POST Account/{id}/contacts
184
+ {"id": "contactId"}
185
+ ```
186
+
187
+ Multiple at once:
188
+ ```json
189
+ {"ids": ["id1", "id2", "id3"]}
190
+ ```
191
+
192
+ Mass relate by filter:
193
+ ```json
194
+ {"massRelate": true, "where": [{"type": "equals", "attribute": "status", "value": "Active"}]}
195
+ ```
196
+
197
+ ### Unlink Records
198
+ ```
199
+ DELETE Account/{id}/contacts
200
+ {"id": "contactId"}
201
+ ```
202
+
203
+ Multiple: `{"ids": ["id1", "id2"]}`.
204
+
205
+ ---
206
+
207
+ ## Webhooks
208
+
209
+ ### Register
210
+ ```
211
+ POST Webhook
212
+ {"event": "Contact.create", "url": "https://your-server.com/hook"}
213
+ ```
214
+ Returns `{"id": "webhookId", "secretKey": "generatedKey"}`. Save both for signature verification.
215
+
216
+ ### Event Types
217
+ - `{Entity}.create` — record created (all attributes in payload)
218
+ - `{Entity}.update` — record updated (only changed attributes)
219
+ - `{Entity}.delete` — record removed (ID only)
220
+ - `{Entity}.fieldUpdate.{field}` — specific field changed
221
+
222
+ ### Payload Format
223
+ Always an array (even for single events):
224
+ ```json
225
+ [{"id": "abc123", "name": "Updated Name", "status": "Active"}]
226
+ ```
227
+
228
+ ### Signature Verification
229
+ The `Signature` header contains: `base64(webhookId + ':' + hmacSha256(rawBody, secretKey))`.
230
+
231
+ ```php
232
+ $expected = base64_encode($webhookId . ':' . hash_hmac('sha256', $rawBody, $secretKey));
233
+ $valid = hash_equals($expected, $_SERVER['HTTP_SIGNATURE']);
234
+ ```
235
+
236
+ ### Lifecycle
237
+ - Processed by scheduled job "Process Webhook Queue" (default: every 5 min)
238
+ - Failed deliveries are retried automatically
239
+ - Persistent failures deactivate the webhook
240
+ - Config: `webhookAllowedAddressList` in `data/config.php` for internal URLs
241
+
242
+ ### Delete
243
+ ```
244
+ DELETE Webhook/{id}
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Mass Operations
250
+
251
+ ### Mass Update
252
+ ```
253
+ POST Lead/action/massUpdate
254
+ ```
255
+
256
+ By IDs:
257
+ ```json
258
+ {"ids": ["id1", "id2"], "data": {"assignedUserId": "userId", "status": "In Process"}}
259
+ ```
260
+
261
+ By filter:
262
+ ```json
263
+ {"where": [{"type": "equals", "attribute": "status", "value": "New"}], "data": {"status": "Assigned"}}
264
+ ```
265
+
266
+ ### Mass Delete
267
+ ```
268
+ POST Lead/action/massDelete
269
+ ```
270
+ Same payload patterns — `ids` array or `where` filter.
271
+
272
+ ### No Bulk Create
273
+ There is no native batch create endpoint. For bulk ingestion:
274
+ 1. Loop individual POST requests with reasonable pacing
275
+ 2. Use the built-in Import feature (Administration > Import) for CSV
276
+ 3. Write a custom API action for batch processing if volume demands it
277
+
278
+ ### Important
279
+ API Before-Save Scripts (Formula) are **not executed** during mass update operations.
280
+
281
+ ---
282
+
283
+ ## Error Handling
284
+
285
+ ### Status Codes
286
+
287
+ | Code | Meaning | Action |
288
+ |---|---|---|
289
+ | 200 | Success | — |
290
+ | 400 | Bad Request | Check required fields, validation |
291
+ | 401 | Unauthorized | Check auth headers/credentials |
292
+ | 403 | Forbidden | Check API User role/ACL |
293
+ | 404 | Not Found | Record doesn't exist or no read access |
294
+ | 409 | Conflict | Duplicate detected or record locked |
295
+ | 500 | Server Error | Check `data/log` on server |
296
+
297
+ ### Error Details
298
+ Error reason is in the `X-Status-Reason` response header (not always in the body).
299
+
300
+ ### Duplicate Detection (409)
301
+ ```json
302
+ {"reason": "Duplicate", "data": {"idList": ["existingId1"]}}
303
+ ```
304
+ Bypass with `X-Skip-Duplicate-Check: true` header.
305
+
306
+ ---
307
+
308
+ ## Performance Best Practices
309
+
310
+ 1. **Select only needed fields** — `?select=id,name,status` avoids loading all attributes
311
+ 2. **Skip total count** — `X-No-Total: true` header skips the COUNT query on list requests
312
+ 3. **Paginate** — use `offset` + `maxSize` (keep maxSize at 50-100)
313
+ 4. **Use primary filters** — server-optimized named filters are faster than complex WHERE
314
+ 5. **Minimal API User roles** — dedicated API users with only required scopes
315
+ 6. **No native rate limiter** — implement at reverse proxy level (nginx, Apache) if needed
316
+ 7. **OpenAPI spec** — `GET OpenApi` returns full schema for your instance including custom entities (v9.3+, admin only)
317
+
318
+ ---
319
+
320
+ ## Client Libraries
321
+
322
+ ### PHP (Official — Preferred)
323
+
324
+ `composer require espocrm/php-espo-api-client`
325
+
326
+ Class: `Espo\ApiClient\Client`. Constructor takes base URL. Auth via `setApiKey()` or `setApiKey()` + `setSecretKey()` for HMAC. All requests through `$client->request(METHOD, path, params, payload)`.
327
+
328
+ ### Node.js
329
+
330
+ No official npm package. Build a thin client around `fetch` with:
331
+ - Base URL + `/api/v1/` prefix
332
+ - `X-Api-Key` header (or compute HMAC per-request)
333
+ - `Content-Type: application/json`
334
+ - Search params as JSON-encoded `searchParams` query param
335
+ - Error extraction from `X-Status-Reason` header on non-2xx responses
336
+
337
+ ---
338
+
339
+ ## Field Types & API Representation
340
+
341
+ | Field Type | JSON Type | Example |
342
+ |---|---|---|
343
+ | varchar | string | `"name": "Test"` |
344
+ | text | string | `"description": "Long text"` |
345
+ | int | number | `"quantity": 5` |
346
+ | float | number | `"rate": 4.5` |
347
+ | boolean | boolean | `"isActive": true` |
348
+ | enum | string | `"status": "New"` |
349
+ | multiEnum | string[] | `"tags": ["A", "B"]` |
350
+ | date | string | `"closeDate": "2025-06-15"` |
351
+ | datetime | string (UTC) | `"createdAt": "2025-06-15 14:30:00"` |
352
+ | currency | number + string | `"amount": 1000, "amountCurrency": "USD"` |
353
+ | link | string (ID) | `"accountId": "someId"` |
354
+ | linkMultiple | string[] + object | `"teamsIds": ["id1"], "teamsNames": {"id1": "Sales"}` |
355
+ | email | string | `"emailAddress": "test@example.com"` |
356
+ | phone | string | `"phoneNumber": "+1234567890"` |
357
+ | address | multiple fields | `"billingAddressStreet": "123 Main", "billingAddressCity": "NYC"` |
358
+ | file | string (ID) | `"fileId": "attachmentId"` |
359
+
360
+ All datetime values are UTC. Date format: `YYYY-MM-DD`. Datetime: `YYYY-MM-DD HH:mm:ss`.
@@ -0,0 +1,84 @@
1
+ # EspoCRM WHERE Filter Operators
2
+
3
+ Complete reference for the `where` array filter objects used in list/search requests.
4
+
5
+ Each filter: `{"type": "...", "attribute": "...", "value": "..."}`
6
+
7
+ ## Equality & Comparison
8
+
9
+ | Type | Value | Example |
10
+ |---|---|---|
11
+ | `equals` | any | `{"type": "equals", "attribute": "status", "value": "New"}` |
12
+ | `notEquals` | any | `{"type": "notEquals", "attribute": "status", "value": "Canceled"}` |
13
+ | `greaterThan` | number/date | `{"type": "greaterThan", "attribute": "amount", "value": 1000}` |
14
+ | `lessThan` | number/date | `{"type": "lessThan", "attribute": "amount", "value": 5000}` |
15
+ | `greaterThanOrEquals` | number/date | `{"type": "greaterThanOrEquals", "attribute": "probability", "value": 50}` |
16
+ | `lessThanOrEquals` | number/date | `{"type": "lessThanOrEquals", "attribute": "probability", "value": 100}` |
17
+
18
+ ## Null & Boolean
19
+
20
+ | Type | Notes |
21
+ |---|---|
22
+ | `isNull` | No `value` needed |
23
+ | `isNotNull` | No `value` needed |
24
+ | `isTrue` | Boolean field check |
25
+ | `isFalse` | Boolean field check |
26
+
27
+ ## String Matching
28
+
29
+ | Type | Value | Behavior |
30
+ |---|---|---|
31
+ | `contains` | string | `%value%` |
32
+ | `notContains` | string | NOT `%value%` |
33
+ | `startsWith` | string | `value%` |
34
+ | `endsWith` | string | `%value` |
35
+ | `like` | string | Raw LIKE pattern (use `%` wildcards) |
36
+ | `notLike` | string | Raw NOT LIKE pattern |
37
+
38
+ ## Set Membership
39
+
40
+ | Type | Value |
41
+ |---|---|
42
+ | `in` | array of strings/numbers: `["New", "Assigned"]` |
43
+ | `notIn` | array of strings/numbers: `["Canceled", "Recycled"]` |
44
+
45
+ ## Relationship Filters
46
+
47
+ | Type | Value | Notes |
48
+ |---|---|---|
49
+ | `linkedWith` | array of IDs | Records linked to ANY of the given IDs |
50
+ | `notLinkedWith` | array of IDs | Records NOT linked to any of the given IDs |
51
+ | `isLinked` | — | Has at least one linked record |
52
+ | `isNotLinked` | — | Has no linked records |
53
+
54
+ ## Date/Time Helpers
55
+
56
+ No `value` needed unless noted:
57
+
58
+ | Type | Notes |
59
+ |---|---|
60
+ | `today` | |
61
+ | `past` | |
62
+ | `future` | |
63
+ | `lastSevenDays` | |
64
+ | `currentMonth` | |
65
+ | `lastMonth` | |
66
+ | `currentQuarter` | |
67
+ | `currentYear` | |
68
+ | `lastXDays` | `value`: number of days |
69
+ | `nextXDays` | `value`: number of days |
70
+ | `between` | `value`: `["YYYY-MM-DD", "YYYY-MM-DD"]` |
71
+
72
+ ## Logical Combinators
73
+
74
+ Multiple items in the `where` array are implicitly **ANDed**.
75
+
76
+ For OR logic, wrap in a combinator:
77
+ ```json
78
+ {"type": "or", "value": [
79
+ {"type": "equals", "attribute": "status", "value": "New"},
80
+ {"type": "equals", "attribute": "status", "value": "Assigned"}
81
+ ]}
82
+ ```
83
+
84
+ Combinators nest: `and` and `or` can contain other combinators.
@@ -158,6 +158,21 @@ Every abstraction has a cost:
158
158
 
159
159
  **The question to ask:** Does this abstraction pay for itself? Will I use it enough to justify the cost? Would a junior developer understand it?
160
160
 
161
+ ### File Size as a Smell
162
+
163
+ Keep files under 500 lines. This isn't an arbitrary limit — it's a smell detector. A file approaching 500 lines almost certainly has multiple responsibilities that should be separated.
164
+
165
+ **When a file grows too large:**
166
+ - Split by responsibility, not by arbitrary line count
167
+ - A 300-line file with two unrelated concerns is worse than a 480-line file with one
168
+ - The goal is cohesion: each file should have a single, clear reason to exist
169
+
170
+ **Why this matters:**
171
+ - Readability: Developers can hold one file's purpose in their head
172
+ - Testability: Smaller, focused files are easier to test in isolation
173
+ - Navigation: Finding what you need is faster in a well-structured codebase
174
+ - Review: Code review quality drops sharply beyond 500 lines
175
+
161
176
  ### Context-Appropriate Complexity
162
177
 
163
178
  A CLI script has different needs than a production API.
@@ -1,19 +1,20 @@
1
1
  ---
2
2
  name: mcp-atlassian
3
3
  description: >-
4
- Atlassian MCP for Jira and Confluence operations (Claude's bundled integration).
5
- Token-efficient workflows for issue management, page creation, search, and user mentions.
4
+ Hybrid Atlassian integration — MCP-first for Jira/Confluence operations,
5
+ direct REST API (curl) for gaps the MCP doesn't cover.
6
6
  Use when: creating/editing Jira issues, searching with JQL/CQL, creating/updating Confluence
7
7
  pages, adding comments, transitioning issue status, looking up users, mentioning/tagging
8
- users in Jira or Confluence content, or any Atlassian Cloud operation. Triggers on: Jira,
9
- Confluence, JQL, CQL, sprint, epic, story, issue, wiki page, Atlassian, @mention in
10
- Jira/Confluence context. Provides 50-80% token savings over naive API usage through
11
- field filtering, pagination control, and format selection.
8
+ users in Jira or Confluence content, downloading/uploading attachments, sprint/board
9
+ management, bulk operations, or any Atlassian Cloud operation. Triggers on: Jira,
10
+ Confluence, JQL, CQL, sprint, epic, story, issue, wiki page, Atlassian, attachment,
11
+ board, backlog, @mention in Jira/Confluence context.
12
12
  ---
13
13
 
14
- # Atlassian MCP - Jira & Confluence Integration
14
+ # Atlassian Integration Hybrid MCP + Direct API
15
15
 
16
- Claude's bundled Atlassian MCP. All tools prefixed `mcp__claude_ai_Atlassian__`.
16
+ MCP-first: use bundled tools (prefixed `mcp__claude_ai_Atlassian__`) for covered operations.
17
+ Direct REST API (curl via Bash) for gaps. See [Decision Logic](#decision-logic) to pick the right approach.
17
18
 
18
19
  ## Bootstrap (Required First Call)
19
20
 
@@ -90,6 +91,51 @@ getAccessibleAtlassianResources → returns cloudId (UUID or site URL)
90
91
  | `search` | Rovo natural language search across Jira + Confluence |
91
92
  | `fetch` | Get detail by ARI (Atlassian Resource Identifier). Read-only |
92
93
 
94
+ ## Direct API — Gap Operations
95
+
96
+ When the MCP tools don't cover an operation, use `curl` via Bash with direct REST API calls.
97
+
98
+ ### When to Use Direct API
99
+
100
+ The MCP handles issue CRUD, transitions, comments, Confluence pages, and search well.
101
+ Use direct API **only** for operations not in the Tool Catalog above.
102
+
103
+ ### Auth Setup
104
+
105
+ Set ENV variables for direct API access. Two auth methods supported:
106
+
107
+ - **Gateway (Bearer)** — preferred for service accounts: `ATLASSIAN_CLOUD_ID` + `ATLASSIAN_BEARER_TOKEN`
108
+ - **Direct (Basic)** — fallback for personal tokens: `ATLASSIAN_DOMAIN` + `ATLASSIAN_EMAIL` + `ATLASSIAN_API_TOKEN`
109
+
110
+ Before first direct API call, verify auth works:
111
+ ```bash
112
+ curl -s -H "Authorization: Bearer $ATLASSIAN_BEARER_TOKEN" \
113
+ "https://api.atlassian.com/ex/jira/$ATLASSIAN_CLOUD_ID/rest/api/3/myself" | jq '.displayName'
114
+ ```
115
+
116
+ Full setup guide: [references/direct-api-auth.md](references/direct-api-auth.md)
117
+
118
+ ### Available Recipes
119
+
120
+ | Operation | Reference | Priority |
121
+ |-----------|-----------|----------|
122
+ | Attachment download/upload (Jira + Confluence) | [direct-api-attachments.md](references/direct-api-attachments.md) | P0 |
123
+ | Sprint/board management (Agile API) | [direct-api-sprints.md](references/direct-api-sprints.md) | P1 |
124
+ | Bulk operations (batch edit, bulk transition) | [direct-api-bulk.md](references/direct-api-bulk.md) | P1 |
125
+ | Comment edit/delete, watchers, components, versions, page deletion | [direct-api-misc.md](references/direct-api-misc.md) | P2 |
126
+
127
+ ### MCP vs Direct API Decision
128
+
129
+ ```
130
+ Can an MCP tool handle it? → Use the MCP tool (always preferred)
131
+ Attachment download/upload? → Direct API (references/direct-api-attachments.md)
132
+ Sprint or board operation? → Direct API (references/direct-api-sprints.md)
133
+ Bulk operation (5+ issues)? → Direct API (references/direct-api-bulk.md)
134
+ Edit/delete comment? → Direct API (references/direct-api-misc.md)
135
+ Watchers, components, versions? → Direct API (references/direct-api-misc.md)
136
+ Delete Confluence page? → Direct API (references/direct-api-misc.md)
137
+ ```
138
+
93
139
  ## User Mentions (@tagging)
94
140
 
95
141
  **This is the most error-prone area.** Follow these patterns exactly.
@@ -300,6 +346,28 @@ createConfluenceInlineComment(
300
346
  )
301
347
  ```
302
348
 
349
+ ### Download Attachments from an Issue (Hybrid)
350
+
351
+ ```
352
+ 1. getJiraIssue(issueIdOrKey: "PROJ-123", fields: ["attachment"])
353
+ → get attachment metadata (filename, content URL)
354
+ 2. curl -s -L -H "Authorization: Bearer $ATLASSIAN_BEARER_TOKEN" \
355
+ -o "mockup.png" "<content-url-from-step-1>"
356
+ ```
357
+
358
+ Full recipes: [references/direct-api-attachments.md](references/direct-api-attachments.md)
359
+
360
+ ### Move Issues to a Sprint (Direct API)
361
+
362
+ ```
363
+ 1. curl: GET /rest/agile/1.0/board?projectKeyOrId=PROJ → boardId
364
+ 2. curl: GET /rest/agile/1.0/board/{boardId}/sprint?state=active → sprintId
365
+ 3. curl: POST /rest/agile/1.0/sprint/{sprintId}/issue
366
+ body: {"issues": ["PROJ-101", "PROJ-102"]}
367
+ ```
368
+
369
+ Full recipes: [references/direct-api-sprints.md](references/direct-api-sprints.md)
370
+
303
371
  ## Decision Logic
304
372
 
305
373
  ```
@@ -328,12 +396,24 @@ Creating a Confluence page?
328
396
  → Need spaceId (NOT space key). Get from getConfluenceSpaces
329
397
  ```
330
398
 
331
- ## What This MCP Does NOT Support
399
+ ## Limitations
400
+
401
+ ### Not Supported (no MCP or direct API recipe)
332
402
 
333
- - Direct Atlassian storage format (XML) - uses Markdown or ADF only
403
+ - Direct Atlassian storage format (XML) MCP uses Markdown or ADF only
334
404
  - Confluence page permissions management
335
- - Jira board/sprint management
336
- - Jira custom field creation
337
- - Attachment uploads
338
- - Bulk operations
405
+ - Jira custom field creation (reading custom fields via `editJiraIssue` may work)
339
406
  - Confluence page templates
407
+ - Jira automation rules / webhooks
408
+
409
+ ### Covered by Direct API (not in MCP, but recipes available)
410
+
411
+ | Gap | Recipe |
412
+ |-----|--------|
413
+ | Attachment download/upload | [direct-api-attachments.md](references/direct-api-attachments.md) |
414
+ | Sprint/board management | [direct-api-sprints.md](references/direct-api-sprints.md) |
415
+ | Bulk operations | [direct-api-bulk.md](references/direct-api-bulk.md) |
416
+ | Comment edit/delete | [direct-api-misc.md](references/direct-api-misc.md) |
417
+ | Watchers | [direct-api-misc.md](references/direct-api-misc.md) |
418
+ | Components & versions | [direct-api-misc.md](references/direct-api-misc.md) |
419
+ | Confluence page deletion | [direct-api-misc.md](references/direct-api-misc.md) |