@jahia/agentic 0.2.0 → 0.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.
Files changed (101) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +28 -0
  3. package/dist/claude/.claude/skills/jahia/SKILL.md +18 -10
  4. package/dist/claude/.claude/skills/jahia-content/SKILL.md +102 -84
  5. package/dist/claude/.claude/skills/jahia-content-create-content/SKILL.md +255 -280
  6. package/dist/claude/.claude/skills/jahia-content-explore-structure/SKILL.md +187 -96
  7. package/dist/claude/.claude/skills/jahia-content-media-upload/SKILL.md +197 -0
  8. package/dist/claude/.claude/skills/jahia-content-move-content/SKILL.md +160 -165
  9. package/dist/claude/.claude/skills/jahia-content-organize/SKILL.md +209 -0
  10. package/dist/claude/.claude/skills/jahia-content-publish/SKILL.md +181 -0
  11. package/dist/claude/.claude/skills/jahia-content-query-content/SKILL.md +122 -92
  12. package/dist/claude/.claude/skills/jahia-content-translate-content/SKILL.md +154 -225
  13. package/dist/claude/.claude/skills/jahia-dev-cypress/SKILL.md +150 -330
  14. package/dist/claude/.claude/skills/jahia-dev-query-content/SKILL.md +93 -296
  15. package/dist/claude/.claude/skills/jahia-jcr-sql2/SKILL.md +258 -0
  16. package/dist/claude/CLAUDE.md +1 -7
  17. package/dist/codex/.agents/skills/jahia/SKILL.md +18 -10
  18. package/dist/codex/.agents/skills/jahia-content/SKILL.md +102 -84
  19. package/dist/codex/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
  20. package/dist/codex/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
  21. package/dist/codex/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
  22. package/dist/codex/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
  23. package/dist/codex/.agents/skills/jahia-content-organize/SKILL.md +209 -0
  24. package/dist/codex/.agents/skills/jahia-content-publish/SKILL.md +181 -0
  25. package/dist/codex/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
  26. package/dist/codex/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
  27. package/dist/codex/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
  28. package/dist/codex/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
  29. package/dist/codex/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
  30. package/dist/codex/AGENTS.md +2 -4
  31. package/dist/copilot/.agents/skills/jahia/SKILL.md +18 -10
  32. package/dist/copilot/.agents/skills/jahia-content/SKILL.md +102 -84
  33. package/dist/copilot/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
  34. package/dist/copilot/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
  35. package/dist/copilot/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
  36. package/dist/copilot/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
  37. package/dist/copilot/.agents/skills/jahia-content-organize/SKILL.md +209 -0
  38. package/dist/copilot/.agents/skills/jahia-content-publish/SKILL.md +181 -0
  39. package/dist/copilot/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
  40. package/dist/copilot/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
  41. package/dist/copilot/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
  42. package/dist/copilot/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
  43. package/dist/copilot/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
  44. package/dist/copilot/AGENTS.md +2 -4
  45. package/dist/cursor/.agents/skills/jahia/SKILL.md +18 -10
  46. package/dist/cursor/.agents/skills/jahia-content/SKILL.md +102 -84
  47. package/dist/cursor/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
  48. package/dist/cursor/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
  49. package/dist/cursor/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
  50. package/dist/cursor/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
  51. package/dist/cursor/.agents/skills/jahia-content-organize/SKILL.md +209 -0
  52. package/dist/cursor/.agents/skills/jahia-content-publish/SKILL.md +181 -0
  53. package/dist/cursor/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
  54. package/dist/cursor/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
  55. package/dist/cursor/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
  56. package/dist/cursor/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
  57. package/dist/cursor/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
  58. package/dist/gemini/.agents/skills/jahia/SKILL.md +18 -10
  59. package/dist/gemini/.agents/skills/jahia-content/SKILL.md +102 -84
  60. package/dist/gemini/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
  61. package/dist/gemini/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
  62. package/dist/gemini/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
  63. package/dist/gemini/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
  64. package/dist/gemini/.agents/skills/jahia-content-organize/SKILL.md +209 -0
  65. package/dist/gemini/.agents/skills/jahia-content-publish/SKILL.md +181 -0
  66. package/dist/gemini/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
  67. package/dist/gemini/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
  68. package/dist/gemini/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
  69. package/dist/gemini/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
  70. package/dist/gemini/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
  71. package/dist/gemini/AGENTS.md +2 -4
  72. package/dist/gemini/GEMINI.md +2 -2
  73. package/dist/opencode/.agents/skills/jahia/SKILL.md +18 -10
  74. package/dist/opencode/.agents/skills/jahia-content/SKILL.md +102 -84
  75. package/dist/opencode/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
  76. package/dist/opencode/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
  77. package/dist/opencode/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
  78. package/dist/opencode/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
  79. package/dist/opencode/.agents/skills/jahia-content-organize/SKILL.md +209 -0
  80. package/dist/opencode/.agents/skills/jahia-content-publish/SKILL.md +181 -0
  81. package/dist/opencode/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
  82. package/dist/opencode/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
  83. package/dist/opencode/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
  84. package/dist/opencode/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
  85. package/dist/opencode/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
  86. package/dist/opencode/AGENTS.md +2 -4
  87. package/dist/windsurf/.windsurf/skills/jahia/SKILL.md +18 -10
  88. package/dist/windsurf/.windsurf/skills/jahia-content/SKILL.md +102 -84
  89. package/dist/windsurf/.windsurf/skills/jahia-content-create-content/SKILL.md +255 -280
  90. package/dist/windsurf/.windsurf/skills/jahia-content-explore-structure/SKILL.md +187 -96
  91. package/dist/windsurf/.windsurf/skills/jahia-content-media-upload/SKILL.md +197 -0
  92. package/dist/windsurf/.windsurf/skills/jahia-content-move-content/SKILL.md +160 -165
  93. package/dist/windsurf/.windsurf/skills/jahia-content-organize/SKILL.md +209 -0
  94. package/dist/windsurf/.windsurf/skills/jahia-content-publish/SKILL.md +181 -0
  95. package/dist/windsurf/.windsurf/skills/jahia-content-query-content/SKILL.md +122 -92
  96. package/dist/windsurf/.windsurf/skills/jahia-content-translate-content/SKILL.md +154 -225
  97. package/dist/windsurf/.windsurf/skills/jahia-dev-cypress/SKILL.md +150 -330
  98. package/dist/windsurf/.windsurf/skills/jahia-dev-query-content/SKILL.md +93 -296
  99. package/dist/windsurf/.windsurf/skills/jahia-jcr-sql2/SKILL.md +258 -0
  100. package/dist/windsurf/AGENTS.md +2 -4
  101. package/package.json +3 -3
@@ -1,236 +1,231 @@
1
1
  ---
2
2
  name: jahia-content-move-content
3
- description: Moves and reorganizes JCR content nodes in Jahia. Use when asked to restructure content folders, nest flat content into sections, rename or move nodes, or tidy up a content tree.
3
+ description: Focused workflow for moving, copying, renaming, reordering, and deleting Jahia content via MCP tools. Use when asked to restructure an existing content tree safely.
4
4
  ---
5
5
 
6
6
  # Skill: jahia-content-move-content
7
7
 
8
- Reorganizes the JCR content tree moving nodes into sub-folders, renaming them, and reordering them — using the Jahia GraphQL API.
8
+ Reorganizes an existing content tree using MCP tools via the `jahia` MCP server.
9
+
10
+ > **Never call Jahia's GraphQL API directly.** Use only MCP tools. If a capability is missing, report it — do not work around with curl/GraphQL.
9
11
 
10
12
  ---
11
13
 
12
14
  ## Prerequisites
13
15
 
14
- - Jahia running at `http://localhost:8080`
15
- - Credentials: `root` / `root1234` (default)
16
- - GraphQL endpoint: `http://localhost:8080/modules/graphql`
17
-
18
- **Always include both auth flags:**
19
- ```bash
20
- curl -s -u root:root1234 \
21
- -H "Content-Type: application/json" \
22
- -H "Origin: http://localhost:8080" \
23
- -X POST http://localhost:8080/modules/graphql \
24
- -d '{"query": "..."}'
25
- ```
26
-
27
- > ⚠️ The `Origin` header is **required** — omitting it returns `Permission denied`.
16
+ - MCP server `jahia` connected with a valid API token
17
+ - Know the target `siteKey` (call `site.list` if unsure)
18
+ - Prefer `/jahia-content-explore-structure` first if the tree is unfamiliar
28
19
 
29
20
  ---
30
21
 
31
- ## Step 1 — Audit the current content tree
22
+ ## Step 1 — Audit the current tree
32
23
 
33
- Before moving anything, map out what exists and where:
34
-
35
- ```bash
36
- # List all content folders and their direct children
37
- curl -s -u root:root1234 \
38
- -H "Content-Type: application/json" \
39
- -H "Origin: http://localhost:8080" \
40
- -X POST http://localhost:8080/modules/graphql \
41
- -d '{
42
- "query": "{ jcr { nodeByPath(path: \"/sites/mySite/contents\") { descendants(fieldFilter: {filters: [{fieldName: \"primaryNodeType.name\", evaluation: EQUAL, value: \"jnt:contentFolder\"}]}) { nodes { path name } } } } }"
43
- }'
24
+ ```
25
+ tool: content.list
26
+ args: {
27
+ "parentPath": "/sites/SITE_KEY/home/about/main",
28
+ "limit": 50
29
+ }
44
30
  ```
45
31
 
46
- Or use a JCR-SQL2 query for a flat list of all content items:
32
+ For a broader view:
47
33
 
48
- ```bash
49
- curl -s -u root:root1234 \
50
- -H "Content-Type: application/json" \
51
- -H "Origin: http://localhost:8080" \
52
- -X POST http://localhost:8080/modules/graphql \
53
- -d '{
54
- "query": "{ jcr { nodesByQuery(query: \"SELECT * FROM [jnt:content] WHERE ISDESCENDANTNODE(\u0027/sites/mySite/contents\u0027) ORDER BY [jcr:path] ASC\", queryLanguage: SQL2) { nodes { path primaryNodeType { name } } } } }"
55
- }'
34
+ ```
35
+ tool: content.search
36
+ args: {
37
+ "siteKey": "SITE_KEY",
38
+ "nodeType": "jmix:droppableContent",
39
+ "locale": "en",
40
+ "sortBy": "jcr:created",
41
+ "order": "asc",
42
+ "limit": 50
43
+ }
56
44
  ```
57
45
 
58
46
  ---
59
47
 
60
- ## Step 2 — Create target sub-folders
61
-
62
- If destination folders don't exist yet, create them with `mix:title` for a proper display label:
48
+ ## Step 2 — Move, copy, rename, or reorder
63
49
 
64
- ```bash
65
- # Create a sub-folder
66
- curl -s -u root:root1234 \
67
- -H "Content-Type: application/json" \
68
- -H "Origin: http://localhost:8080" \
69
- -X POST http://localhost:8080/modules/graphql \
70
- -d '{
71
- "query": "mutation { jcr { addNode(parentPathOrId: \"/sites/mySite/contents/articles\", name: \"getting-started\", primaryNodeType: \"jnt:contentFolder\") { node { path } } } }"
72
- }'
50
+ ### Move a node
73
51
 
74
- # Set a human-readable title on the folder
75
- curl -s -u root:root1234 \
76
- -H "Content-Type: application/json" \
77
- -H "Origin: http://localhost:8080" \
78
- -X POST http://localhost:8080/modules/graphql \
79
- -d '{
80
- "query": "mutation { jcr { mutateNode(pathOrId: \"/sites/mySite/contents/articles/getting-started\") { addMixins(mixins: [\"mix:title\"]) mutateProperty(name: \"jcr:title\") { setValue(language: \"en\", value: \"Getting Started\") } } } }"
81
- }'
52
+ ```
53
+ tool: content.move
54
+ args: {
55
+ "path": "/sites/SITE_KEY/home/blog/main/old-article",
56
+ "destParentPath": "/sites/SITE_KEY/home/archive/main",
57
+ "newName": "archived-article"
58
+ }
82
59
  ```
83
60
 
84
- ---
61
+ ### Copy a node
85
62
 
86
- ## Step 3 — Move a node
63
+ ```
64
+ tool: content.copy
65
+ args: {
66
+ "path": "/sites/SITE_KEY/home/templates/main/hero-banner",
67
+ "destParentPath": "/sites/SITE_KEY/home/landing/main"
68
+ }
69
+ ```
87
70
 
88
- Use `move` on a `mutateNode` to relocate a node to a new parent. The node keeps its name:
71
+ ### Rename a node
89
72
 
90
- ```bash
91
- curl -s -u root:root1234 \
92
- -H "Content-Type: application/json" \
93
- -H "Origin: http://localhost:8080" \
94
- -X POST http://localhost:8080/modules/graphql \
95
- -d '{
96
- "query": "mutation { jcr { mutateNode(pathOrId: \"/sites/mySite/contents/articles/my-article\") { move(parentPathOrId: \"/sites/mySite/contents/articles/getting-started\") } } }"
97
- }'
98
73
  ```
74
+ tool: content.rename
75
+ args: {
76
+ "path": "/sites/SITE_KEY/home/about/main/old-name",
77
+ "newName": "new-name"
78
+ }
79
+ ```
80
+
81
+ ### Reorder siblings
99
82
 
100
- > ⚠️ `move` does **not** support a `name` argument — use `rename` separately if needed.
83
+ ```
84
+ tool: content.reorder
85
+ args: {
86
+ "parentPath": "/sites/SITE_KEY/home/blog/main",
87
+ "nodeName": "featured-post",
88
+ "position": "FIRST"
89
+ }
90
+ ```
101
91
 
102
- ### Rename a node in place
92
+ Or place one node before another:
103
93
 
104
- ```bash
105
- curl -s -u root:root1234 \
106
- -H "Content-Type: application/json" \
107
- -H "Origin: http://localhost:8080" \
108
- -X POST http://localhost:8080/modules/graphql \
109
- -d '{
110
- "query": "mutation { jcr { mutateNode(pathOrId: \"/sites/mySite/contents/articles\") { rename(name: \"reference-pages\") } } }"
111
- }'
112
94
  ```
95
+ tool: content.reorder
96
+ args: {
97
+ "parentPath": "/sites/SITE_KEY/home/blog/main",
98
+ "nodeName": "featured-post",
99
+ "position": "INPLACE",
100
+ "beforeNodeName": "second-post"
101
+ }
102
+ ```
103
+
104
+ ---
113
105
 
114
- To move **and** rename, call `move` then `rename` in sequence, or combine in one mutation:
106
+ ## Step 3 Update content properties if needed
115
107
 
116
- ```graphql
117
- mutation {
118
- jcr {
119
- mutateNode(pathOrId: "/sites/mySite/contents/articles/old-name") {
120
- move(parentPathOrId: "/sites/mySite/contents/articles/getting-started")
121
- }
122
- rename: mutateNode(pathOrId: "/sites/mySite/contents/articles/getting-started/old-name") {
123
- rename(name: "new-name")
124
- }
108
+ ```
109
+ tool: content.update
110
+ args: {
111
+ "path": "/sites/SITE_KEY/home/about/main/intro-text",
112
+ "locale": "en",
113
+ "properties": {
114
+ "jcr:title": "Updated Title",
115
+ "text": "<p>New content here.</p>"
125
116
  }
126
117
  }
127
118
  ```
128
119
 
129
- ### Batch move with Python
120
+ ---
130
121
 
131
- ```python
132
- import subprocess, json
122
+ ## Step 4 — Delete correctly
133
123
 
134
- def gql(q):
135
- r = subprocess.run(["curl","-s","-u","root:root1234",
136
- "-H","Origin: http://localhost:8080",
137
- "-H","Content-Type: application/json",
138
- "-X","POST","http://localhost:8080/modules/graphql",
139
- "-d", json.dumps({"query": q})], capture_output=True, text=True)
140
- d = json.loads(r.stdout)
141
- if "errors" in d: print("ERR:", d["errors"][0]["message"][:80])
142
- return d
124
+ ### Draft-only content: hard delete
143
125
 
144
- moves = [
145
- ("/sites/mySite/contents/articles/getting-started",
146
- "/sites/mySite/contents/articles/core-concepts"),
147
- ("/sites/mySite/contents/articles/graphql-api",
148
- "/sites/mySite/contents/articles/api-reference"),
149
- ]
126
+ ```
127
+ tool: content.delete
128
+ args: { "path": "/sites/SITE_KEY/home/draft-page/main/temp-node" }
129
+ ```
150
130
 
151
- for src, dest in moves:
152
- r = gql(f'mutation {{ jcr {{ mutateNode(pathOrId: "{src}") {{ move(parentPathOrId: "{dest}") }} }} }}')
153
- ok = "errors" not in r
154
- print(f" {'✓' if ok else '✗'} {src.split('/')[-1]} → {dest.split('/')[-1]}")
131
+ ### Published content: mark for deletion, then publish the deletion
132
+
133
+ ```
134
+ tool: content.markForDeletion
135
+ args: { "path": "/sites/SITE_KEY/home/old-page" }
155
136
  ```
156
137
 
157
- ---
138
+ Publish the deletion to remove it from LIVE:
158
139
 
159
- ## Step 4 — Reorder siblings
140
+ ```
141
+ tool: publication.publish
142
+ args: {
143
+ "path": "/sites/SITE_KEY/home/old-page",
144
+ "languages": ["en"]
145
+ }
146
+ ```
160
147
 
161
- To control the display order within a folder, use `reorder` after moving:
148
+ Undo the mark if needed:
162
149
 
163
- ```bash
164
- curl -s -u root:root1234 \
165
- -H "Content-Type: application/json" \
166
- -H "Origin: http://localhost:8080" \
167
- -X POST http://localhost:8080/modules/graphql \
168
- -d '{
169
- "query": "mutation { jcr { mutateNode(pathOrId: \"/sites/mySite/contents/articles/intro\") { reorder(reorderNodes: {moveBeforeOrAfter: BEFORE, target: \"advanced\"}) } } }"
170
- }'
150
+ ```
151
+ tool: content.unmarkForDeletion
152
+ args: { "path": "/sites/SITE_KEY/home/old-page" }
171
153
  ```
172
154
 
173
155
  ---
174
156
 
175
- ## Step 5 — Publish after moving
176
-
177
- Moving a node unpublishes it in the live workspace. Always republish after reorganizing:
157
+ ## Step 5 — Check and publish after changes
178
158
 
179
- ```bash
180
- # Publish a single node
181
- curl -s -u root:root1234 \
182
- -H "Content-Type: application/json" \
183
- -H "Origin: http://localhost:8080" \
184
- -X POST http://localhost:8080/modules/graphql \
185
- -d '{
186
- "query": "mutation { jcr { mutateNode(pathOrId: \"/sites/mySite/contents/articles/getting-started/my-article\") { publish(languages: [\"en\"]) } } }"
187
- }'
159
+ Inspect publication status:
188
160
 
189
- # Publish everything under a folder at once
190
- curl -s -u root:root1234 \
191
- -H "Content-Type: application/json" \
192
- -H "Origin: http://localhost:8080" \
193
- -X POST http://localhost:8080/modules/graphql \
194
- -d '{
195
- "query": "mutation { jcr { mutateNodesByQuery(query: \"SELECT * FROM [jnt:content] WHERE ISDESCENDANTNODE(\u0027/sites/mySite/contents\u0027)\", queryLanguage: SQL2) { publish(languages: [\"en\"]) } } }"
196
- }'
161
+ ```
162
+ tool: publication.status
163
+ args: {
164
+ "path": "/sites/SITE_KEY/home/about",
165
+ "language": "en",
166
+ "subNodes": true,
167
+ "references": true
168
+ }
197
169
  ```
198
170
 
199
- ---
171
+ Publish the affected branch:
172
+
173
+ ```
174
+ tool: publication.publish
175
+ args: {
176
+ "path": "/sites/SITE_KEY/home/about",
177
+ "languages": ["en"]
178
+ }
179
+ ```
200
180
 
201
- ## Step 6 Verify
181
+ Unpublish if the goal is to remove content from LIVE while keeping EDIT:
202
182
 
203
- ```bash
204
- curl -s -u root:root1234 \
205
- -H "Content-Type: application/json" \
206
- -H "Origin: http://localhost:8080" \
207
- -X POST http://localhost:8080/modules/graphql \
208
- -d '{
209
- "query": "{ jcr { nodesByQuery(query: \"SELECT * FROM [jnt:content] WHERE ISDESCENDANTNODE(\u0027/sites/mySite/contents\u0027)\", queryLanguage: SQL2) { nodes { path } } } }"
210
- }'
183
+ ```
184
+ tool: publication.unpublish
185
+ args: {
186
+ "path": "/sites/SITE_KEY/home/about/main/outdated-section",
187
+ "languages": ["en"]
188
+ }
211
189
  ```
212
190
 
213
191
  ---
214
192
 
215
- ## Common errors
193
+ ## Step 6 — Verify the result
194
+
195
+ ```
196
+ tool: content.list
197
+ args: {
198
+ "parentPath": "/sites/SITE_KEY/home/about/main",
199
+ "limit": 50
200
+ }
201
+ ```
202
+
203
+ Or preview the page:
216
204
 
217
- | Error | Cause | Fix |
218
- |-------|-------|-----|
219
- | `Permission denied` | Missing `Origin` header | Add `-H "Origin: http://localhost:8080"` |
220
- | `ItemExistsException` | A node with that name already exists at the destination | Choose a different name or use `rename` after moving |
221
- | `PathNotFoundException` | Source or destination path doesn't exist | Verify paths with `nodeByPath` first |
222
- | `move` returns `null` | Node was already at that location | Verify the current path first |
223
- | Content disappears from live after move | Move unpublishes — normal JCR behaviour | Run `publish` after every move |
205
+ ```
206
+ tool: page.preview
207
+ args: { "path": "/sites/SITE_KEY/home/about" }
208
+ ```
224
209
 
225
210
  ---
226
211
 
227
212
  ## Workflow summary
228
213
 
229
214
  ```
230
- 1. Audit → list current paths and types
231
- 2. Plan map old paths to new paths/folders
232
- 3. CreateaddNode for any new folders needed
233
- 4. Move mutateNode { move(...) } for each item
234
- 5. Publish mutateNodesByQuery { publish(...) } for all affected content
235
- 6. Verify query back and confirm structure
215
+ 1. Audit → content.list / content.search
216
+ 2. Move/copy content.move / content.copy
217
+ 3. Renamecontent.rename
218
+ 4. Reorder content.reorder
219
+ 5. Delete content.delete or content.markForDeletion + publication.publish
220
+ 6. Publish publication.status + publication.publish / publication.unpublish
221
+ 7. Verify → content.list / page.preview
236
222
  ```
223
+
224
+ ---
225
+
226
+ ## Related skills
227
+
228
+ - `/jahia-content-organize` — fuller reorganization lifecycle and patterns
229
+ - `/jahia-content-explore-structure` — understand the tree before changing it
230
+ - `/jahia-content-publish` — publication readiness, publish, and unpublish flows
231
+
@@ -0,0 +1,209 @@
1
+ ---
2
+ name: jahia-content-organize
3
+ description: Moves, copies, renames, reorders, and deletes Jahia content via MCP tools. Use when asked to reorganize a site structure, duplicate content, or manage the deletion lifecycle.
4
+ ---
5
+
6
+ # Skill: jahia-content-organize
7
+
8
+ Covers structural content-tree operations using MCP tools via the `jahia` MCP server.
9
+
10
+ > **Never call Jahia's GraphQL API directly.** Use only MCP tools. If a capability is missing, report it — do not work around with curl/GraphQL.
11
+
12
+ ---
13
+
14
+ ## Move content
15
+
16
+ ```
17
+ tool: content.move
18
+ args: {
19
+ "path": "/sites/SITE_KEY/home/blog/main/old-article",
20
+ "destParentPath": "/sites/SITE_KEY/home/archive/main",
21
+ "newName": "archived-article"
22
+ }
23
+ ```
24
+
25
+ - `newName` is optional
26
+ - the entire subtree moves with the node
27
+ - the move happens in EDIT; publish afterward
28
+
29
+ ## Copy content
30
+
31
+ ```
32
+ tool: content.copy
33
+ args: {
34
+ "path": "/sites/SITE_KEY/home/templates/main/hero-banner",
35
+ "destParentPath": "/sites/SITE_KEY/home/landing/main"
36
+ }
37
+ ```
38
+
39
+ - deep copy, including children and properties
40
+ - the copy gets a new UUID
41
+ - use `excludeChildTypes` when you need to skip specific child node types
42
+
43
+ ## Rename content
44
+
45
+ ```
46
+ tool: content.rename
47
+ args: {
48
+ "path": "/sites/SITE_KEY/home/about/main/old-name",
49
+ "newName": "new-name"
50
+ }
51
+ ```
52
+
53
+ Use `content.update` on `jcr:title` when you need to change the display title rather than the node name.
54
+
55
+ ## Reorder siblings
56
+
57
+ ```
58
+ tool: content.reorder
59
+ args: {
60
+ "parentPath": "/sites/SITE_KEY/home/blog/main",
61
+ "nodeName": "featured-post",
62
+ "position": "FIRST"
63
+ }
64
+ ```
65
+
66
+ Place a node before a specific sibling:
67
+
68
+ ```
69
+ tool: content.reorder
70
+ args: {
71
+ "parentPath": "/sites/SITE_KEY/home/blog/main",
72
+ "nodeName": "featured-post",
73
+ "position": "INPLACE",
74
+ "beforeNodeName": "second-post"
75
+ }
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Delete content
81
+
82
+ ### Draft-only content
83
+
84
+ Hard delete immediately:
85
+
86
+ ```
87
+ tool: content.delete
88
+ args: { "path": "/sites/SITE_KEY/home/draft-page/main/temp-node" }
89
+ ```
90
+
91
+ ### Published content
92
+
93
+ Mark the node for deletion first:
94
+
95
+ ```
96
+ tool: content.markForDeletion
97
+ args: { "path": "/sites/SITE_KEY/home/blog/main/old-post" }
98
+ ```
99
+
100
+ Publish the deletion to propagate it to LIVE:
101
+
102
+ ```
103
+ tool: publication.publish
104
+ args: {
105
+ "path": "/sites/SITE_KEY/home/blog/main/old-post",
106
+ "languages": ["en"]
107
+ }
108
+ ```
109
+
110
+ Undo the mark if needed:
111
+
112
+ ```
113
+ tool: content.unmarkForDeletion
114
+ args: { "path": "/sites/SITE_KEY/home/blog/main/old-post" }
115
+ ```
116
+
117
+ You cannot hard-delete already published content without first going through the deletion lifecycle.
118
+
119
+ ---
120
+
121
+ ## Reorganization patterns
122
+
123
+ ### Move several items into a new section
124
+
125
+ ```
126
+ # 1. Audit the current branch
127
+ tool: content.list
128
+ args: { "parentPath": "/sites/SITE_KEY/home/news/main" }
129
+
130
+ # 2. Move items
131
+ tool: content.move
132
+ args: {
133
+ "path": "/sites/SITE_KEY/home/news/main/item-1",
134
+ "destParentPath": "/sites/SITE_KEY/home/archive/main"
135
+ }
136
+
137
+ tool: content.move
138
+ args: {
139
+ "path": "/sites/SITE_KEY/home/news/main/item-2",
140
+ "destParentPath": "/sites/SITE_KEY/home/archive/main"
141
+ }
142
+
143
+ # 3. Publish the affected branch
144
+ tool: publication.publish
145
+ args: {
146
+ "path": "/sites/SITE_KEY/home/archive",
147
+ "languages": ["en"]
148
+ }
149
+ ```
150
+
151
+ ### Duplicate a page structure
152
+
153
+ ```
154
+ # 1. Copy the page
155
+ tool: content.copy
156
+ args: {
157
+ "path": "/sites/SITE_KEY/home/template-page",
158
+ "destParentPath": "/sites/SITE_KEY/home"
159
+ }
160
+
161
+ # 2. Rename the copy
162
+ tool: content.rename
163
+ args: {
164
+ "path": "/sites/SITE_KEY/home/template-page1",
165
+ "newName": "new-section"
166
+ }
167
+
168
+ # 3. Update the page title
169
+ tool: content.update
170
+ args: {
171
+ "path": "/sites/SITE_KEY/home/new-section",
172
+ "locale": "en",
173
+ "properties": {
174
+ "jcr:title": "New Section"
175
+ }
176
+ }
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Key rules
182
+
183
+ | Rule | Detail |
184
+ |------|--------|
185
+ | Publish after reorganization | Moves, copies, renames, and reorders affect EDIT first |
186
+ | No hard-delete of published nodes | Use `content.markForDeletion` plus `publication.publish` |
187
+ | Move includes the subtree | Children move with the selected node |
188
+ | Name conflicts fail | Moves and renames validate uniqueness |
189
+ | Reorder stays within one parent | Use `content.move` to change parents, `content.reorder` to change sibling order |
190
+
191
+ ---
192
+
193
+ ## Common errors
194
+
195
+ | Error | Cause | Fix |
196
+ |-------|-------|-----|
197
+ | `NODE_NOT_FOUND` | Source path does not exist | Verify with `content.get` or `content.list` |
198
+ | `NODE_EXISTS` | Target name already exists | Choose a different `newName` |
199
+ | `CANNOT_DELETE_PUBLISHED` | Attempted hard delete on published content | Use `content.markForDeletion` |
200
+ | `DEST_NOT_FOUND` | Destination parent does not exist | Verify with `content.get` |
201
+
202
+ ---
203
+
204
+ ## Related skills
205
+
206
+ - `/jahia-content-explore-structure` — inspect the tree before reorganizing it
207
+ - `/jahia-content-publish` — publish after moves, copies, reorders, or deletions
208
+ - `/jahia-content-move-content` — focused move and deletion workflow for an existing branch
209
+