@se-studio/contentful-cms 3.15.3 → 3.15.4
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/CHANGELOG.md +6 -0
- package/HOSTED.md +20 -0
- package/dist/commands/host-scaffold.d.ts.map +1 -1
- package/dist/commands/host-scaffold.js +5 -3
- package/dist/commands/host-scaffold.js.map +1 -1
- package/dist/contentful/cma-user-agent.d.ts +1 -1
- package/dist/editor-pack/load.d.ts.map +1 -1
- package/dist/editor-pack/load.js +14 -2
- package/dist/editor-pack/load.js.map +1 -1
- package/dist/generated/hosted-guide.d.ts +1 -1
- package/dist/generated/hosted-guide.d.ts.map +1 -1
- package/dist/generated/hosted-guide.js +1 -1
- package/dist/generated/hosted-guide.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/hosted/index.d.ts +1 -1
- package/dist/hosted/index.d.ts.map +1 -1
- package/dist/hosted/index.js +1 -1
- package/dist/hosted/index.js.map +1 -1
- package/dist/hosted/next/pages/CmsEditPage.d.ts.map +1 -1
- package/dist/hosted/next/pages/CmsEditPage.js +1 -1
- package/dist/hosted/next/pages/CmsEditPage.js.map +1 -1
- package/dist/hosted/next/pages/HomePage.d.ts.map +1 -1
- package/dist/hosted/next/pages/HomePage.js +1 -1
- package/dist/hosted/next/pages/HomePage.js.map +1 -1
- package/dist/hosted/next/routes/mcp.d.ts +1 -0
- package/dist/hosted/next/routes/mcp.d.ts.map +1 -1
- package/dist/hosted/next/routes/mcp.js +6 -1
- package/dist/hosted/next/routes/mcp.js.map +1 -1
- package/dist/hosted/next/routes/oauth-authorization-server.d.ts +1 -0
- package/dist/hosted/next/routes/oauth-authorization-server.d.ts.map +1 -1
- package/dist/hosted/next/routes/oauth-authorization-server.js +5 -1
- package/dist/hosted/next/routes/oauth-authorization-server.js.map +1 -1
- package/dist/hosted/next/routes/oauth-protected-resource-path.d.ts +13 -0
- package/dist/hosted/next/routes/oauth-protected-resource-path.d.ts.map +1 -0
- package/dist/hosted/next/routes/oauth-protected-resource-path.js +17 -0
- package/dist/hosted/next/routes/oauth-protected-resource-path.js.map +1 -0
- package/dist/hosted/next/routes/oauth-protected-resource.d.ts +1 -0
- package/dist/hosted/next/routes/oauth-protected-resource.d.ts.map +1 -1
- package/dist/hosted/next/routes/oauth-protected-resource.js +5 -1
- package/dist/hosted/next/routes/oauth-protected-resource.js.map +1 -1
- package/dist/hosted/oauth/cimd.d.ts +17 -0
- package/dist/hosted/oauth/cimd.d.ts.map +1 -0
- package/dist/hosted/oauth/cimd.js +300 -0
- package/dist/hosted/oauth/cimd.js.map +1 -0
- package/dist/hosted/oauth/complete.d.ts +1 -0
- package/dist/hosted/oauth/complete.d.ts.map +1 -1
- package/dist/hosted/oauth/complete.js +4 -0
- package/dist/hosted/oauth/complete.js.map +1 -1
- package/dist/hosted/oauth/config.d.ts +2 -0
- package/dist/hosted/oauth/config.d.ts.map +1 -1
- package/dist/hosted/oauth/config.js +4 -0
- package/dist/hosted/oauth/config.js.map +1 -1
- package/dist/hosted/oauth/cors.d.ts +4 -0
- package/dist/hosted/oauth/cors.d.ts.map +1 -0
- package/dist/hosted/oauth/cors.js +23 -0
- package/dist/hosted/oauth/cors.js.map +1 -0
- package/dist/hosted/oauth/handlers.d.ts.map +1 -1
- package/dist/hosted/oauth/handlers.js +57 -7
- package/dist/hosted/oauth/handlers.js.map +1 -1
- package/dist/hosted/oauth/log.d.ts +2 -0
- package/dist/hosted/oauth/log.d.ts.map +1 -1
- package/dist/hosted/oauth/log.js +4 -0
- package/dist/hosted/oauth/log.js.map +1 -1
- package/dist/hosted/oauth/redirect-hosts.d.ts +4 -0
- package/dist/hosted/oauth/redirect-hosts.d.ts.map +1 -0
- package/dist/hosted/oauth/redirect-hosts.js +47 -0
- package/dist/hosted/oauth/redirect-hosts.js.map +1 -0
- package/dist/hosted/oauth/refresh.d.ts +1 -0
- package/dist/hosted/oauth/refresh.d.ts.map +1 -1
- package/dist/hosted/oauth/refresh.js +2 -0
- package/dist/hosted/oauth/refresh.js.map +1 -1
- package/dist/hosted/oauth/scopes.d.ts +15 -0
- package/dist/hosted/oauth/scopes.d.ts.map +1 -0
- package/dist/hosted/oauth/scopes.js +21 -0
- package/dist/hosted/oauth/scopes.js.map +1 -0
- package/dist/hosted/oauth/store.d.ts +4 -0
- package/dist/hosted/oauth/store.d.ts.map +1 -1
- package/dist/hosted/oauth/store.js +3 -0
- package/dist/hosted/oauth/store.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +2 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/client-tools.d.ts +11 -0
- package/dist/mcp/tools/client-tools.d.ts.map +1 -0
- package/dist/mcp/tools/client-tools.js +215 -0
- package/dist/mcp/tools/client-tools.js.map +1 -0
- package/dist/staged-upload/store.d.ts +18 -0
- package/dist/staged-upload/store.d.ts.map +1 -1
- package/dist/staged-upload/store.js +73 -0
- package/dist/staged-upload/store.js.map +1 -1
- package/dist/staged-upload/types.d.ts +2 -0
- package/dist/staged-upload/types.d.ts.map +1 -1
- package/docs/mcp/hosted-guide.md +8 -0
- package/package.json +1 -1
- package/skills/manifest.json +1 -1
- 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,
|
|
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"}
|
package/docs/mcp/hosted-guide.md
CHANGED
|
@@ -294,6 +294,14 @@ Replace the server name and host with your site's deployment. The URL **must** e
|
|
|
294
294
|
|
|
295
295
|
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
296
|
|
|
297
|
+
## Other clients
|
|
298
|
+
|
|
299
|
+
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.
|
|
300
|
+
|
|
301
|
+
Cursor and VS Code: remote HTTP MCP, then OAuth. Gemini CLI: `url` under `mcpServers`.
|
|
302
|
+
|
|
303
|
+
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.
|
|
304
|
+
|
|
297
305
|
## Hosted connector rules
|
|
298
306
|
|
|
299
307
|
{{HOSTED_RULES}}
|
package/package.json
CHANGED
package/skills/manifest.json
CHANGED
|
@@ -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
|
|
5
|
+
"setup": "Guide a user through connecting hosted cms-edit MCP for Claude, ChatGPT, Grok, Cursor, or Gemini (OAuth)."
|
|
6
6
|
}
|
package/skills/setup/SKILL.md
CHANGED
|
@@ -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
|
|
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
|
|
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):
|