@se-studio/contentful-cms 3.15.3 → 3.15.5

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 (111) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/HOSTED.md +20 -0
  3. package/README.md +1 -1
  4. package/dist/commands/host-scaffold.d.ts.map +1 -1
  5. package/dist/commands/host-scaffold.js +7 -5
  6. package/dist/commands/host-scaffold.js.map +1 -1
  7. package/dist/contentful/cma-user-agent.d.ts +1 -1
  8. package/dist/editor-pack/load.d.ts.map +1 -1
  9. package/dist/editor-pack/load.js +14 -2
  10. package/dist/editor-pack/load.js.map +1 -1
  11. package/dist/generated/help-topics.d.ts.map +1 -1
  12. package/dist/generated/help-topics.js +1 -1
  13. package/dist/generated/help-topics.js.map +1 -1
  14. package/dist/generated/hosted-guide.d.ts +1 -1
  15. package/dist/generated/hosted-guide.d.ts.map +1 -1
  16. package/dist/generated/hosted-guide.js +1 -1
  17. package/dist/generated/hosted-guide.js.map +1 -1
  18. package/dist/generated/version.d.ts +1 -1
  19. package/dist/generated/version.js +1 -1
  20. package/dist/hosted/index.d.ts +1 -1
  21. package/dist/hosted/index.d.ts.map +1 -1
  22. package/dist/hosted/index.js +1 -1
  23. package/dist/hosted/index.js.map +1 -1
  24. package/dist/hosted/next/pages/CmsEditPage.d.ts.map +1 -1
  25. package/dist/hosted/next/pages/CmsEditPage.js +1 -1
  26. package/dist/hosted/next/pages/CmsEditPage.js.map +1 -1
  27. package/dist/hosted/next/pages/HomePage.d.ts.map +1 -1
  28. package/dist/hosted/next/pages/HomePage.js +1 -1
  29. package/dist/hosted/next/pages/HomePage.js.map +1 -1
  30. package/dist/hosted/next/routes/mcp.d.ts +1 -0
  31. package/dist/hosted/next/routes/mcp.d.ts.map +1 -1
  32. package/dist/hosted/next/routes/mcp.js +6 -1
  33. package/dist/hosted/next/routes/mcp.js.map +1 -1
  34. package/dist/hosted/next/routes/oauth-authorization-server.d.ts +1 -0
  35. package/dist/hosted/next/routes/oauth-authorization-server.d.ts.map +1 -1
  36. package/dist/hosted/next/routes/oauth-authorization-server.js +5 -1
  37. package/dist/hosted/next/routes/oauth-authorization-server.js.map +1 -1
  38. package/dist/hosted/next/routes/oauth-protected-resource-path.d.ts +13 -0
  39. package/dist/hosted/next/routes/oauth-protected-resource-path.d.ts.map +1 -0
  40. package/dist/hosted/next/routes/oauth-protected-resource-path.js +17 -0
  41. package/dist/hosted/next/routes/oauth-protected-resource-path.js.map +1 -0
  42. package/dist/hosted/next/routes/oauth-protected-resource.d.ts +1 -0
  43. package/dist/hosted/next/routes/oauth-protected-resource.d.ts.map +1 -1
  44. package/dist/hosted/next/routes/oauth-protected-resource.js +5 -1
  45. package/dist/hosted/next/routes/oauth-protected-resource.js.map +1 -1
  46. package/dist/hosted/next/routes/oauth-register.d.ts +1 -0
  47. package/dist/hosted/next/routes/oauth-register.d.ts.map +1 -1
  48. package/dist/hosted/next/routes/oauth-register.js +5 -1
  49. package/dist/hosted/next/routes/oauth-register.js.map +1 -1
  50. package/dist/hosted/next/routes/oauth-token.d.ts +1 -0
  51. package/dist/hosted/next/routes/oauth-token.d.ts.map +1 -1
  52. package/dist/hosted/next/routes/oauth-token.js +5 -1
  53. package/dist/hosted/next/routes/oauth-token.js.map +1 -1
  54. package/dist/hosted/oauth/cimd.d.ts +17 -0
  55. package/dist/hosted/oauth/cimd.d.ts.map +1 -0
  56. package/dist/hosted/oauth/cimd.js +300 -0
  57. package/dist/hosted/oauth/cimd.js.map +1 -0
  58. package/dist/hosted/oauth/complete.d.ts +1 -0
  59. package/dist/hosted/oauth/complete.d.ts.map +1 -1
  60. package/dist/hosted/oauth/complete.js +4 -0
  61. package/dist/hosted/oauth/complete.js.map +1 -1
  62. package/dist/hosted/oauth/config.d.ts +2 -0
  63. package/dist/hosted/oauth/config.d.ts.map +1 -1
  64. package/dist/hosted/oauth/config.js +4 -0
  65. package/dist/hosted/oauth/config.js.map +1 -1
  66. package/dist/hosted/oauth/cors.d.ts +4 -0
  67. package/dist/hosted/oauth/cors.d.ts.map +1 -0
  68. package/dist/hosted/oauth/cors.js +23 -0
  69. package/dist/hosted/oauth/cors.js.map +1 -0
  70. package/dist/hosted/oauth/handlers.d.ts.map +1 -1
  71. package/dist/hosted/oauth/handlers.js +57 -7
  72. package/dist/hosted/oauth/handlers.js.map +1 -1
  73. package/dist/hosted/oauth/log.d.ts +2 -0
  74. package/dist/hosted/oauth/log.d.ts.map +1 -1
  75. package/dist/hosted/oauth/log.js +4 -0
  76. package/dist/hosted/oauth/log.js.map +1 -1
  77. package/dist/hosted/oauth/redirect-hosts.d.ts +4 -0
  78. package/dist/hosted/oauth/redirect-hosts.d.ts.map +1 -0
  79. package/dist/hosted/oauth/redirect-hosts.js +47 -0
  80. package/dist/hosted/oauth/redirect-hosts.js.map +1 -0
  81. package/dist/hosted/oauth/refresh.d.ts +1 -0
  82. package/dist/hosted/oauth/refresh.d.ts.map +1 -1
  83. package/dist/hosted/oauth/refresh.js +2 -0
  84. package/dist/hosted/oauth/refresh.js.map +1 -1
  85. package/dist/hosted/oauth/scopes.d.ts +15 -0
  86. package/dist/hosted/oauth/scopes.d.ts.map +1 -0
  87. package/dist/hosted/oauth/scopes.js +21 -0
  88. package/dist/hosted/oauth/scopes.js.map +1 -0
  89. package/dist/hosted/oauth/store.d.ts +4 -0
  90. package/dist/hosted/oauth/store.d.ts.map +1 -1
  91. package/dist/hosted/oauth/store.js +3 -0
  92. package/dist/hosted/oauth/store.js.map +1 -1
  93. package/dist/mcp/server.d.ts.map +1 -1
  94. package/dist/mcp/server.js +2 -0
  95. package/dist/mcp/server.js.map +1 -1
  96. package/dist/mcp/tools/client-tools.d.ts +11 -0
  97. package/dist/mcp/tools/client-tools.d.ts.map +1 -0
  98. package/dist/mcp/tools/client-tools.js +215 -0
  99. package/dist/mcp/tools/client-tools.js.map +1 -0
  100. package/dist/staged-upload/store.d.ts +18 -0
  101. package/dist/staged-upload/store.d.ts.map +1 -1
  102. package/dist/staged-upload/store.js +73 -0
  103. package/dist/staged-upload/store.js.map +1 -1
  104. package/dist/staged-upload/types.d.ts +2 -0
  105. package/dist/staged-upload/types.d.ts.map +1 -1
  106. package/docs/help/workflow.md +1 -1
  107. package/docs/mcp/hosted-guide.md +11 -8
  108. package/package.json +1 -1
  109. package/skills/core/SKILL.md +2 -7
  110. package/skills/manifest.json +1 -1
  111. package/skills/setup/SKILL.md +23 -2
@@ -0,0 +1,215 @@
1
+ import { z } from 'zod';
2
+ import { HOSTED_INLINE_MAX_BYTES } from '../../cli/hosted-inline-limit.js';
3
+ import { readCustomerPlaybook } from '../../hosted/customer-playbooks.js';
4
+ import { getRuntimeContext } from '../../runtime/context.js';
5
+ import { prefixHostedToolDescription } from '../hosted-metadata.js';
6
+ const READ_ONLY = {
7
+ readOnlyHint: true,
8
+ destructiveHint: false,
9
+ idempotentHint: true,
10
+ openWorldHint: true,
11
+ };
12
+ const DRAFT_WRITE = {
13
+ readOnlyHint: false,
14
+ destructiveHint: false,
15
+ idempotentHint: false,
16
+ openWorldHint: true,
17
+ };
18
+ function textResult(value) {
19
+ return {
20
+ content: [{ type: 'text', text: JSON.stringify(value) }],
21
+ };
22
+ }
23
+ /** Split cms-edit stdout into the command body and the trailing CMA stats line. */
24
+ export function parseCmsEditToolBody(raw) {
25
+ const trimmed = raw.trim();
26
+ const lines = trimmed.split('\n');
27
+ let body = trimmed;
28
+ const last = lines[lines.length - 1] ?? '';
29
+ try {
30
+ const stats = JSON.parse(last);
31
+ if (stats && typeof stats === 'object' && 'cma_requests' in stats) {
32
+ body = lines.slice(0, -1).join('\n').trim();
33
+ }
34
+ }
35
+ catch {
36
+ // The last line is part of the command body.
37
+ }
38
+ if (/\(exit code \d+\)\s*$/.test(body)) {
39
+ return { ok: false, data: null, error: body };
40
+ }
41
+ if (!body) {
42
+ return { ok: true, data: null };
43
+ }
44
+ try {
45
+ return { ok: true, data: JSON.parse(body) };
46
+ }
47
+ catch {
48
+ return { ok: true, data: body };
49
+ }
50
+ }
51
+ function asSearchResults(data) {
52
+ if (!Array.isArray(data)) {
53
+ return [];
54
+ }
55
+ const results = [];
56
+ for (const item of data) {
57
+ if (!item || typeof item !== 'object')
58
+ continue;
59
+ const row = item;
60
+ if (typeof row.id !== 'string' || row.id.length === 0)
61
+ continue;
62
+ const title = typeof row.title === 'string' && row.title.length > 0 ? row.title : row.id;
63
+ const url = typeof row.slug === 'string' && row.slug.length > 0 ? `/${row.slug}` : row.id;
64
+ results.push({ id: row.id, title, url });
65
+ }
66
+ return results;
67
+ }
68
+ function fetchDocument(id, data) {
69
+ const row = data && typeof data === 'object' ? data : undefined;
70
+ const title = typeof row?.title === 'string' && row.title.length > 0 ? row.title : id;
71
+ const url = typeof row?.slug === 'string' && row.slug.length > 0 ? `/${row.slug}` : id;
72
+ const text = typeof data === 'string' ? data : JSON.stringify(data);
73
+ return { id, title, text, url };
74
+ }
75
+ async function runParsed(runCmsEdit, args) {
76
+ return parseCmsEditToolBody(await runCmsEdit(args));
77
+ }
78
+ export function registerClientTools(server, runCmsEdit, hosted, editorPackPath) {
79
+ server.tool('search', prefixHostedToolDescription('Search Contentful entries (drafts and published). Returns id, title, and url for each hit. Does not publish.', hosted), {
80
+ query: z.string().describe('Full-text query'),
81
+ limit: z.number().int().min(1).max(20).optional().describe('Max results, default 10'),
82
+ }, READ_ONLY, async ({ query, limit }) => {
83
+ const args = ['search', '-n', String(limit ?? 10), '--json', '--', query];
84
+ const parsed = await runParsed(runCmsEdit, args);
85
+ if (!parsed.ok) {
86
+ return textResult({ results: [], error: parsed.error });
87
+ }
88
+ return textResult({ results: asSearchResults(parsed.data) });
89
+ });
90
+ server.tool('fetch', prefixHostedToolDescription('Fetch one Contentful entry by id. Returns id, title, text, and url. Draft content is included. Does not publish.', hosted), { id: z.string().describe('Contentful entry id') }, READ_ONLY, async ({ id }) => {
91
+ const parsed = await runParsed(runCmsEdit, ['read', id, '--id']);
92
+ if (!parsed.ok) {
93
+ return textResult({ id, title: id, text: parsed.error ?? 'read failed', url: id });
94
+ }
95
+ return textResult(fetchDocument(id, parsed.data));
96
+ });
97
+ server.tool('read_entry', prefixHostedToolDescription('Read one entry or one field by Contentful id. No editing session required.', hosted), {
98
+ id: z.string().describe('Contentful entry id'),
99
+ field: z.string().optional().describe('Field id. Omit to read the entry.'),
100
+ }, READ_ONLY, async ({ id, field }) => {
101
+ const args = field ? ['read', id, '--id', field] : ['read', id, '--id'];
102
+ const parsed = await runParsed(runCmsEdit, args);
103
+ return textResult(parsed.ok ? { ok: true, entry: parsed.data } : { ok: false, error: parsed.error });
104
+ });
105
+ server.tool('get_editor_guide', prefixHostedToolDescription('Read one site playbook (tasks-index, capabilities, checklist, overview, routing, or a task name). Call tasks-index first.', hosted), { resource: z.string().describe('Playbook name, for example tasks-index') }, READ_ONLY, async ({ resource }) => {
106
+ const playbook = readCustomerPlaybook(resource, editorPackPath);
107
+ if (!playbook) {
108
+ return textResult({
109
+ ok: false,
110
+ error: `Unknown playbook: ${resource}`,
111
+ hint: 'Call get_editor_guide with resource "tasks-index".',
112
+ });
113
+ }
114
+ return textResult({ ok: true, resource: playbook.name, content: playbook.text });
115
+ });
116
+ server.tool('set_field', prefixHostedToolDescription('Set one field on the open cms-edit session. Saves nothing until save_draft. Values over 8192 bytes must use append_text. Does not publish.', hosted), {
117
+ ref: z.string().describe('Session ref such as @c1, or an entry id'),
118
+ field: z.string().describe('Field id'),
119
+ value: z.string().describe('New value'),
120
+ mode: z
121
+ .enum(['scalar', 'link', 'links', 'richtext'])
122
+ .optional()
123
+ .describe('scalar (default), link, links, or richtext'),
124
+ }, DRAFT_WRITE, async ({ ref, field, value, mode }) => {
125
+ const bytes = Buffer.byteLength(value);
126
+ if (bytes > HOSTED_INLINE_MAX_BYTES) {
127
+ return textResult({
128
+ ok: false,
129
+ error: `value is ${String(bytes)} bytes. Call append_text (kind text or json), then cms_edit set/rtf with --staged.`,
130
+ });
131
+ }
132
+ const resolved = mode ?? 'scalar';
133
+ const args = resolved === 'richtext'
134
+ ? ['rtf', ref, field, '--content', value]
135
+ : resolved === 'link'
136
+ ? ['set', ref, field, '--link', '--', value]
137
+ : resolved === 'links'
138
+ ? ['set', ref, field, '--links', '--', value]
139
+ : ['set', ref, field, '--', value];
140
+ const parsed = await runParsed(runCmsEdit, args);
141
+ return textResult(parsed.ok ? { ok: true, result: parsed.data } : { ok: false, error: parsed.error });
142
+ });
143
+ server.tool('diff_draft', prefixHostedToolDescription('Show unsaved draft edits in the current session.', hosted), {}, READ_ONLY, async () => {
144
+ const parsed = await runParsed(runCmsEdit, ['diff']);
145
+ return textResult(parsed.ok ? { ok: true, diff: parsed.data } : { ok: false, error: parsed.error });
146
+ });
147
+ server.tool('save_draft', prefixHostedToolDescription('Write the open session to Contentful as drafts. Does not publish, unpublish, archive, or delete.', hosted), {}, DRAFT_WRITE, async () => {
148
+ const parsed = await runParsed(runCmsEdit, ['save']);
149
+ return textResult(parsed.ok ? { ok: true, result: parsed.data } : { ok: false, error: parsed.error });
150
+ });
151
+ server.tool('append_text', prefixHostedToolDescription('Upload long text or JSON without a shell. Start with fileName, mimeType, and kind. Repeat with uploadId and offset set to the bytes value from the previous call. Set final true on the last chunk, then pass uploadId to cms_edit --staged. Each chunk is at most 8192 bytes.', hosted), {
152
+ chunk: z.string().describe('Next piece of the file'),
153
+ final: z.boolean().describe('True on the last chunk'),
154
+ uploadId: z.string().optional().describe('Omit on the first chunk'),
155
+ offset: z
156
+ .number()
157
+ .int()
158
+ .min(0)
159
+ .optional()
160
+ .describe('Byte offset. 0 on the first chunk, then the bytes value from the previous call'),
161
+ fileName: z.string().optional().describe('Required on the first chunk'),
162
+ mimeType: z.string().optional().describe('text/html, text/plain, or application/json'),
163
+ kind: z
164
+ .enum(['text', 'json'])
165
+ .optional()
166
+ .describe('text or json. Required on the first chunk'),
167
+ }, DRAFT_WRITE, async ({ chunk, final, uploadId, fileName, mimeType, kind, offset }) => {
168
+ const bytes = Buffer.byteLength(chunk);
169
+ if (bytes > HOSTED_INLINE_MAX_BYTES) {
170
+ return textResult({
171
+ ok: false,
172
+ error: `chunk is ${String(bytes)} bytes. Send at most ${String(HOSTED_INLINE_MAX_BYTES)} bytes per call.`,
173
+ });
174
+ }
175
+ const context = getRuntimeContext();
176
+ const userId = context?.user?.userId;
177
+ const store = context?.stagedUploadStore;
178
+ if (!userId || !store) {
179
+ return textResult({
180
+ ok: false,
181
+ error: 'append_text requires hosted MCP (signed-in user and Redis).',
182
+ });
183
+ }
184
+ try {
185
+ let id = uploadId;
186
+ if (!id) {
187
+ if (!fileName || !mimeType || !kind) {
188
+ return textResult({
189
+ ok: false,
190
+ error: 'The first append_text call needs fileName, mimeType, and kind.',
191
+ });
192
+ }
193
+ id = await store.createPending({
194
+ userId,
195
+ fileName,
196
+ mimeType,
197
+ kind: kind,
198
+ });
199
+ }
200
+ const result = await store.appendText({
201
+ userId,
202
+ uploadId: id,
203
+ chunk,
204
+ final,
205
+ offset,
206
+ });
207
+ return textResult({ ok: true, ...result });
208
+ }
209
+ catch (error) {
210
+ const message = error instanceof Error ? error.message : String(error);
211
+ return textResult({ ok: false, error: message });
212
+ }
213
+ });
214
+ }
215
+ //# sourceMappingURL=client-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-tools.js","sourceRoot":"","sources":["../../../src/mcp/tools/client-tools.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,24 @@ export declare class StagedUploadStore {
18
18
  consume(userId: string, uploadId: string): Promise<StagedUploadConsumeResult>;
19
19
  /** Read staged bytes without deleting (pipeline fetch). */
20
20
  peekFile(userId: string, uploadId: string): Promise<StagedUploadConsumeResult>;
21
+ private withSlotLock;
22
+ /**
23
+ * Append a text or JSON chunk into a pending slot. `final` marks the slot ready
24
+ * for `--staged` consume. Binary assets stay on the curl / direct intake path.
25
+ * `offset` is the byte length already stored. A retry of the same offset and
26
+ * chunk is a no-op.
27
+ */
28
+ appendText(params: {
29
+ userId: string;
30
+ uploadId: string;
31
+ chunk: string;
32
+ final: boolean;
33
+ offset?: number;
34
+ }): Promise<{
35
+ uploadId: string;
36
+ bytes: number;
37
+ complete: boolean;
38
+ }>;
21
39
  getRecord(userId: string, uploadId: string): Promise<StagedUploadRecord | null>;
22
40
  }
23
41
  //# sourceMappingURL=store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/staged-upload/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAM/D,OAAO,EAGL,KAAK,gBAAgB,EAEtB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA0BhF,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAF5B,YACmB,KAAK,EAAE,WAAW,EAClB,SAAS,SAAa,EACrC;IAEJ,OAAO,CAAC,OAAO;IAIT,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYnD;IAEK,aAAa,CAAC,MAAM,EAAE;QAC1B,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,gBAAgB,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqClB;IAEK,SAAS,CACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CAgC7B;IAEK,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAsBlF;IAED,2DAA2D;IACrD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAiBnF;IAEK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAEpF;CACF"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/staged-upload/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAM/D,OAAO,EAGL,KAAK,gBAAgB,EAEtB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA0BhF,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAF5B,YACmB,KAAK,EAAE,WAAW,EAClB,SAAS,SAAa,EACrC;IAEJ,OAAO,CAAC,OAAO;IAIT,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYnD;IAEK,aAAa,CAAC,MAAM,EAAE;QAC1B,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,gBAAgB,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqClB;IAEK,SAAS,CACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CAiC7B;IAEK,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAsBlF;IAED,2DAA2D;IACrD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAiBnF;YAEa,YAAY;IAiB1B;;;;;OAKG;IACG,UAAU,CAAC,MAAM,EAAE;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,OAAO,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAkElE;IAEK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAEpF;CACF"}
@@ -98,6 +98,7 @@ export class StagedUploadStore {
98
98
  mimeType: resolvedMime,
99
99
  byteLength: buffer.length,
100
100
  dataBase64: buffer.toString('base64'),
101
+ partialText: undefined,
101
102
  };
102
103
  await this.redis.set(key, JSON.stringify(record), { ex: STAGED_UPLOAD_TTL_SECONDS });
103
104
  return record;
@@ -141,6 +142,78 @@ export class StagedUploadStore {
141
142
  kind: stagedKindOrAsset(existing.kind),
142
143
  };
143
144
  }
145
+ async withSlotLock(userId, uploadId, fn) {
146
+ const lockKey = `${this.fullKey(userId, uploadId)}:lock`;
147
+ const acquired = await this.redis.set(lockKey, '1', { nx: true, ex: 30 });
148
+ if (acquired !== true) {
149
+ throw new Error('Staged upload is being updated. Retry this chunk.');
150
+ }
151
+ try {
152
+ return await fn();
153
+ }
154
+ finally {
155
+ await this.redis.del(lockKey);
156
+ }
157
+ }
158
+ /**
159
+ * Append a text or JSON chunk into a pending slot. `final` marks the slot ready
160
+ * for `--staged` consume. Binary assets stay on the curl / direct intake path.
161
+ * `offset` is the byte length already stored. A retry of the same offset and
162
+ * chunk is a no-op.
163
+ */
164
+ async appendText(params) {
165
+ return this.withSlotLock(params.userId, params.uploadId, async () => {
166
+ const key = this.fullKey(params.userId, params.uploadId);
167
+ const existing = parseRecord(await this.redis.get(key));
168
+ if (!existing || existing.userId !== params.userId || existing.uploadId !== params.uploadId) {
169
+ throw new Error('Staged upload slot not found or expired.');
170
+ }
171
+ const kind = stagedKindOrAsset(existing.kind);
172
+ if (kind === 'asset') {
173
+ throw new Error('append_text only accepts kind=text or kind=json slots.');
174
+ }
175
+ const stored = existing.status === 'ready'
176
+ ? Buffer.from(existing.dataBase64 ?? '', 'base64').toString('utf8')
177
+ : (existing.partialText ?? '');
178
+ const storedBytes = Buffer.byteLength(stored);
179
+ const chunkBytes = Buffer.byteLength(params.chunk);
180
+ const offset = params.offset ?? (storedBytes === 0 ? 0 : undefined);
181
+ if (offset === undefined) {
182
+ throw new Error('Pass offset from the previous append_text bytes value. Use 0 on the first chunk.');
183
+ }
184
+ if (offset < storedBytes) {
185
+ const storedBuf = Buffer.from(stored);
186
+ const chunkBuf = Buffer.from(params.chunk);
187
+ const slice = storedBuf.subarray(offset, offset + chunkBuf.length);
188
+ if (slice.length !== chunkBuf.length || !slice.equals(chunkBuf)) {
189
+ throw new Error('Staged upload chunk does not match the bytes already stored at that offset.');
190
+ }
191
+ return {
192
+ uploadId: params.uploadId,
193
+ bytes: storedBytes,
194
+ complete: existing.status === 'ready',
195
+ };
196
+ }
197
+ if (offset > storedBytes) {
198
+ throw new Error('Staged upload offset is past the stored text. Pass the bytes value from the previous append_text call.');
199
+ }
200
+ if (existing.status === 'ready') {
201
+ throw new Error('Staged upload already received.');
202
+ }
203
+ const next = `${stored}${params.chunk}`;
204
+ const bytes = storedBytes + chunkBytes;
205
+ if (bytes > hostedStagedMaxBytes()) {
206
+ throw new Error(`File exceeds hosted staged upload limit (${String(hostedStagedMaxBytes())} bytes).`);
207
+ }
208
+ if (!params.final) {
209
+ const record = { ...existing, partialText: next, byteLength: bytes };
210
+ await this.redis.set(key, JSON.stringify(record), { ex: STAGED_UPLOAD_TTL_SECONDS });
211
+ return { uploadId: params.uploadId, bytes, complete: false };
212
+ }
213
+ await this.storeFile(params.userId, params.uploadId, Buffer.from(next), existing.mimeType);
214
+ return { uploadId: params.uploadId, bytes, complete: true };
215
+ });
216
+ }
144
217
  async getRecord(userId, uploadId) {
145
218
  return parseRecord(await this.redis.get(this.fullKey(userId, uploadId)));
146
219
  }
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/staged-upload/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/staged-upload/store.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,8 @@ export interface StagedUploadRecord {
10
10
  byteLength?: number;
11
11
  status: StagedUploadStatus;
12
12
  dataBase64?: string;
13
+ /** UTF-8 text accumulated by append_text before the slot is marked ready. */
14
+ partialText?: string;
13
15
  createdAt: number;
14
16
  }
15
17
  export interface StagedUploadRequestResult {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/staged-upload/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,6EAA6E;IAC7E,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC9B,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,gBAAgB,CAAC;CACxB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/staged-upload/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,6EAA6E;IAC7E,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC9B,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,gBAAgB,CAAC;CACxB"}
@@ -177,7 +177,7 @@ Shows a summary of which entries have been modified and which fields changed.
177
177
  cms-edit save
178
178
  ```
179
179
 
180
- Writes all changes to Contentful as **drafts**. Nothing is published. A human must review and publish in the Contentful web app.
180
+ Writes all changes to Contentful as **drafts**. Publish, unpublish, and archive use `publish plan` then `publish apply` after an explicit yes, and only when the Contentful role allows it. AI Editor cannot.
181
181
 
182
182
  ---
183
183
 
@@ -6,12 +6,7 @@ Use this guide when editing Contentful draft content through a hosted MCP connec
6
6
 
7
7
  ## Safety rules
8
8
 
9
- cms-edit **cannot and will not**:
10
-
11
- - Publish or unpublish entries
12
- - Archive or delete published entries
13
-
14
- All `save` operations create **drafts only**. A human must review and publish in Contentful.
9
+ `save` writes **drafts only**. Publish, unpublish, and archive use `publish plan`, then `publish apply` after an explicit yes, and only when the signed-in Contentful role allows it. AI Editor cannot. Typed tools do not publish.
15
10
 
16
11
  **Assets:** Always **search and reuse** first (`index sync`, then `asset search`). Raster/video go through **`cms_edit_media`** (Drive, or intake then prepare → import). Video, and an image master over 4MB, is a presigned PUT (`intake: direct`) then prepare with `httpsUrls`. An image at or under 4MB uses a function POST then `stagedUploadIds`. Never `asset upload` jpeg/png/webp/gif/mp4, and never convert those files with local ffmpeg. SVG/PDF/Lottie: staged upload then `asset upload --staged`. **`--base64` is not supported on hosted MCP.**
17
12
 
@@ -131,10 +126,10 @@ Always run `diff` before `save`. To abandon changes: `["discard"]`.
131
126
  |------|-------|
132
127
  | Edit copy, add sections, create pages/articles | **Agent + cms-edit** (drafts) |
133
128
  | Upload new images and files | **Agent + cms-edit** — search/reuse first; raster/video via `cms_edit_media` import |
134
- | Publish approved drafts | **Contentful UI** |
129
+ | Publish, unpublish, or archive | **cms-edit** `publish plan`, then `publish apply` after an explicit yes, when the Contentful role allows it |
135
130
  | Edit copy directly in Contentful | **Avoid** — use cms-edit instead |
136
131
 
137
- cms-edit saves **drafts only**. A colleague must **publish in Contentful** for changes to go live.
132
+ cms-edit saves **drafts**. Going live needs that plan and an explicit yes. AI Editor cannot publish.
138
133
 
139
134
  ## Asset upload (hosted MCP)
140
135
 
@@ -294,6 +289,14 @@ Replace the server name and host with your site's deployment. The URL **must** e
294
289
 
295
290
  OAuth is two steps: Grok obtains an MCP token, then you sign in with Contentful to link your account. If the browser flashes and closes immediately, reconnect after upgrading cms-edit (loopback redirect handling).
296
291
 
292
+ ## Other clients
293
+
294
+ Paste the same `/api/mcp` URL. ChatGPT: Settings → Apps & Connectors → custom MCP server → OAuth → Contentful. Draft saves need a Business, Enterprise, or Edu workspace. Recreate the connector after a tool change.
295
+
296
+ Cursor and VS Code: remote HTTP MCP, then OAuth. Gemini CLI: `url` under `mcpServers`.
297
+
298
+ If the client has no shell, use `search`, `fetch`, `get_editor_guide`, `set_field`, `diff_draft`, `save_draft`, and `append_text` (chunks of at most 8192 bytes). `save_draft` writes drafts only.
299
+
297
300
  ## Hosted connector rules
298
301
 
299
302
  {{HOSTED_RULES}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@se-studio/contentful-cms",
3
- "version": "3.15.3",
3
+ "version": "3.15.5",
4
4
  "description": "CLI tool for AI agents to edit Contentful drafts and, when the user's role allows it, publish after an explicit yes",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,12 +25,7 @@ Use this skill when you need to read or edit content in Contentful using **hoste
25
25
 
26
26
  ## Safety Rules
27
27
 
28
- **This tool CANNOT and WILL NOT:**
29
- - Publish any entry
30
- - Unpublish any entry
31
- - Archive or delete published entries
32
-
33
- All `save` operations create **draft** versions. A human must review and publish in Contentful.
28
+ `save` writes **drafts**. Publish, unpublish, and archive use `publish plan`, then `publish apply` after an explicit yes, and only when the signed-in Contentful role allows it. AI Editor cannot. Do not publish as part of save.
34
29
 
35
30
  **Assets:** Upload **is** supported (`asset upload`). Default workflow: **search and reuse** existing assets first (`index sync` → `asset search`). Search by concept (`asset search --concept` / `--concept-all`) finds a subject and a tone, including files no page uses yet. Concepts are not blog tags. When uploading:
36
31
  - **Raster/video:** `cms_edit_request_staged_upload` → curl → `cms_edit_media` prepare → wait → catalog → import with real alt. Video, and an image master over 4MB, is a presigned direct PUT (100MB, `intake: direct`) then prepare with that URL. Smaller images still use `stagedUploadIds`. Never `asset upload --staged/--url/--base64` for jpeg/png/webp/gif/mp4. The stored asset is the processed file.
@@ -204,7 +199,7 @@ Shows a diff of all modified fields across all changed entries.
204
199
  cms-edit save
205
200
  ```
206
201
 
207
- Writes all changes to Contentful as **drafts**. The changes are visible in Contentful's web app but NOT live until a human publishes them.
202
+ Writes all changes to Contentful as **drafts**. They stay drafts until `publish plan` then `publish apply`, after an explicit yes, and only if the Contentful role allows it.
208
203
 
209
204
  After saving, the session is cleared automatically if all changes were saved.
210
205
 
@@ -2,5 +2,5 @@
2
2
  "core": "Edit Contentful drafts via hosted cms-edit MCP (open → snapshot → read → set/rtf → diff → save). Local CLI content commands are disabled.",
3
3
  "editor-tasks": "Route CMS editing intents to site task playbooks via tasks-index (hosted MCP resources or local editor-pack files).",
4
4
  "templates": "Create or edit templates (preContent, postContent, menu, footer, colours) in Contentful via cms-edit.",
5
- "setup": "Guide a user through connecting hosted cms-edit MCP for Claude or Grok (OAuth)."
5
+ "setup": "Guide a user through connecting hosted cms-edit MCP for Claude, ChatGPT, Grok, Cursor, or Gemini (OAuth)."
6
6
  }
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: contentful-cms-setup
3
- description: "Guide a user through connecting hosted cms-edit MCP for Claude or Grok (OAuth)."
3
+ description: "Guide a user through connecting hosted cms-edit MCP for Claude, ChatGPT, Grok, Cursor, or Gemini (OAuth)."
4
4
  ---
5
5
 
6
6
  # Skill: cms-edit Setup
7
7
 
8
- Use this skill when the user wants to connect Claude or Grok to their Contentful site via **hosted cms-edit MCP**.
8
+ Use this skill when the user wants to connect Claude, ChatGPT, Grok, Cursor, VS Code, or Gemini CLI to their Contentful site via **hosted cms-edit MCP**.
9
9
 
10
10
  Local stdio MCP and the setup wizard are **not supported**. Editors connect through the site's `/cms-edit` onboarding flow.
11
11
 
@@ -68,6 +68,27 @@ Full guide: `packages/contentful-cms/docs/mcp/hosted-guide.md` (Grok Build secti
68
68
 
69
69
  ---
70
70
 
71
+ ## Hosted setup (ChatGPT and other remote MCP clients)
72
+
73
+ The MCP URL is the same URL as Claude (`https://<host>/api/mcp`). The client must speak remote Streamable HTTP and OAuth. There is no local stdio server and no OpenAPI Action.
74
+
75
+ ### ChatGPT
76
+
77
+ 1. Settings → **Apps & Connectors** → create a custom MCP server
78
+ 2. Paste the MCP URL and choose **OAuth**
79
+ 3. Sign in with **Contentful**
80
+ 4. Ask it to call `search` or `cms_edit_version`
81
+
82
+ Draft writes (`set_field`, `save_draft`) need a Business, Enterprise, or Edu workspace. Pro can be read-only. ChatGPT freezes the tool list at connect time: after a cms-edit upgrade, remove the connector and add it again.
83
+
84
+ Clients that cannot run a shell use `append_text` for bodies over 8192 bytes, then `cms_edit` with `--staged`. `save_draft` does not publish.
85
+
86
+ ### Cursor, VS Code, Gemini CLI
87
+
88
+ Add the MCP URL as a remote HTTP server and complete OAuth. Cursor: `~/.cursor/mcp.json` `url`. VS Code: `.vscode/mcp.json` `servers` with `type: http`. Gemini CLI: `mcpServers.<name>.url`.
89
+
90
+ ---
91
+
71
92
  ## Developers (CLI + skills, not local MCP)
72
93
 
73
94
  For engineering work in a site repo (Cursor, Grok, terminal):