@webiny/mcp 6.1.0 → 6.2.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.
@@ -6,8 +6,9 @@ description: >
6
6
  Use this skill when the developer is building a Next.js, Vue, Node.js, or any external app
7
7
  that needs to fetch or write content to Webiny, set up the SDK, use the Result pattern,
8
8
  list/get/create/update/publish entries, filter and sort queries, use TypeScript generics
9
- for type safety, work with the File Manager, or create API keys programmatically. Also
10
- covers the three API types (Read, Manage, Preview) and CmsEntryData typing.
9
+ for type safety, work with the File Manager, list languages, or create API keys programmatically.
10
+ Covers read vs preview mode, the `values` wrapper requirement, correct method names,
11
+ and the `fields` required parameter.
11
12
  ---
12
13
 
13
14
  # Webiny SDK
@@ -26,9 +27,9 @@ Initialize once and reuse:
26
27
 
27
28
  ```typescript
28
29
  // lib/webiny.ts
29
- import { Sdk } from "@webiny/sdk";
30
+ import { Webiny } from "@webiny/sdk";
30
31
 
31
- export const sdk = new Sdk({
32
+ export const webiny = new Webiny({
32
33
  token: process.env.WEBINY_API_TOKEN!,
33
34
  endpoint: process.env.WEBINY_API_ENDPOINT!,
34
35
  tenant: process.env.WEBINY_API_TENANT || "root"
@@ -36,30 +37,50 @@ export const sdk = new Sdk({
36
37
  ```
37
38
 
38
39
  - `token` -- API key token generated in Webiny Admin (Settings > API Keys)
39
- - `endpoint` -- The base CloudFront URL (e.g., `https://xxx.cloudfront.net`). Run `yarn webiny info` to find it.
40
+ - `endpoint` -- The base API URL, **without a trailing slash**. Run `yarn webiny info` in your Webiny project to find the API URL. For Website Builder projects use `NEXT_PUBLIC_WEBSITE_BUILDER_API_HOST`.
40
41
  - `tenant` -- Tenant ID, defaults to `"root"`
41
42
 
42
- ## The Three API Types
43
+ > **IMPORTANT:** Never add a trailing slash to `endpoint`. The SDK appends `/graphql` to the endpoint internally, so `https://xxx.cloudfront.net/` will break all requests.
43
44
 
44
- Webiny provides three separate GraphQL APIs:
45
+ ## The `fields` Parameter (Required)
45
46
 
46
- | API | URL Path | Returns | Can Write | Use For |
47
- | ----------- | -------------- | ------------------------------------- | --------- | ----------------------------- |
48
- | **Read** | `/cms/read` | Published entries only | No | Public-facing apps, SSG |
49
- | **Manage** | `/cms/manage` | All revisions (drafts + published) | Yes | Admin tools, content creation |
50
- | **Preview** | `/cms/preview` | Latest revisions (drafts + published) | No | Content preview |
47
+ Every SDK method requires a `fields` array that specifies which fields to return. Omitting it will cause a runtime error.
51
48
 
52
- The SDK automatically routes to the correct API based on the method:
49
+ - Use `"values.<fieldId>"` for content fields: `"values.name"`, `"values.price"`
50
+ - Use top-level field names for metadata: `"id"`, `"entryId"`, `"createdOn"`, `"status"`
51
+ - Use dot notation for nested fields: `"values.author.name"`
53
52
 
54
- - `listEntries`, `getEntry` -> Read API
55
- - `createEntry`, `updateEntry`, `publishEntry`, `unpublishEntry` -> Manage API
53
+ ```typescript
54
+ // Minimal fields -- just IDs
55
+ fields: ["id", "entryId"];
56
+
57
+ // Content fields
58
+ fields: ["id", "entryId", "values.name", "values.price", "values.description"];
59
+
60
+ // Nested reference fields
61
+ fields: ["id", "values.title", "values.author.name", "values.author.email"];
62
+ ```
63
+
64
+ ## CMS: Read vs Preview Mode
65
+
66
+ `webiny.cms.listEntries` and `webiny.cms.getEntry` accept a `preview` parameter to control which revisions are returned:
67
+
68
+ | `preview` | Returns | Use For |
69
+ | ----------------- | ------------------------------------ | -------------------------------- |
70
+ | `false` (default) | Published entries only | Public-facing apps, SSG |
71
+ | `true` | Latest revision (draft or published) | Content preview, editorial tools |
72
+
73
+ Write operations (`createEntry`, `updateEntryRevision`, etc.) are not affected by `preview`.
56
74
 
57
75
  ## The Result Pattern
58
76
 
59
77
  Every SDK method returns a `Result` object -- it never throws:
60
78
 
61
79
  ```typescript
62
- const result = await sdk.cms.listEntries({ modelId: "product", fields: ["id"] });
80
+ const result = await webiny.cms.listEntries({
81
+ modelId: "product",
82
+ fields: ["id", "values.name"]
83
+ });
63
84
 
64
85
  if (result.isOk()) {
65
86
  console.log(result.value.data); // success -- typed data
@@ -88,8 +109,9 @@ interface ProductCategory {
88
109
  slug: string;
89
110
  }
90
111
 
91
- const result = await sdk.cms.listEntries<Product>({
92
- modelId: "product"
112
+ const result = await webiny.cms.listEntries<Product>({
113
+ modelId: "product",
114
+ fields: ["id", "entryId", "values.name", "values.price", "values.sku"]
93
115
  });
94
116
 
95
117
  if (result.isOk()) {
@@ -106,9 +128,10 @@ Reference fields like `category` are typed as `CmsEntryData<T>`, which wraps ref
106
128
  ### List Entries
107
129
 
108
130
  ```typescript
109
- const result = await sdk.cms.listEntries<Product>({
131
+ const result = await webiny.cms.listEntries<Product>({
110
132
  modelId: "product",
111
- sort: ["values.name_ASC"],
133
+ fields: ["id", "entryId", "values.name", "values.price"],
134
+ sort: { "values.name": "asc" },
112
135
  limit: 10
113
136
  });
114
137
  ```
@@ -116,13 +139,14 @@ const result = await sdk.cms.listEntries<Product>({
116
139
  ### List with Filters
117
140
 
118
141
  ```typescript
119
- const result = await sdk.cms.listEntries<Product>({
142
+ const result = await webiny.cms.listEntries<Product>({
120
143
  modelId: "product",
144
+ fields: ["id", "entryId", "values.name", "values.price"],
121
145
  where: {
122
146
  "values.price_gte": 100,
123
147
  "values.name_contains": "Pro"
124
148
  },
125
- sort: ["values.price_DESC"]
149
+ sort: { "values.price": "desc" }
126
150
  });
127
151
  ```
128
152
 
@@ -140,78 +164,151 @@ const result = await sdk.cms.listEntries<Product>({
140
164
 
141
165
  ### Sort Format
142
166
 
143
- Sort strings follow the pattern `values.<fieldId>_ASC` or `values.<fieldId>_DESC`:
167
+ Sort is a `Record<string, "asc" | "desc">` object:
144
168
 
145
169
  ```typescript
146
- sort: ["values.name_ASC"]; // alphabetical
147
- sort: ["values.price_DESC"]; // highest price first
148
- sort: ["values.createdOn_DESC"]; // newest first
170
+ sort: { "values.name": "asc" } // alphabetical
171
+ sort: { "values.price": "desc" } // highest price first
172
+ sort: { "values.createdOn": "desc" } // newest first
149
173
  ```
150
174
 
151
175
  ### Get Single Entry
152
176
 
177
+ Use `where` with either `id` (revision ID) or `entryId`:
178
+
153
179
  ```typescript
154
- const result = await sdk.cms.getEntry<Product>({
180
+ // By revision ID
181
+ const result = await webiny.cms.getEntry<Product>({
155
182
  modelId: "product",
156
- id: "abc123#0001"
183
+ where: { id: "abc123#0001" },
184
+ fields: ["id", "entryId", "values.name", "values.price"]
185
+ });
186
+
187
+ // By entry ID (gets latest published revision)
188
+ const result = await webiny.cms.getEntry<Product>({
189
+ modelId: "product",
190
+ where: { entryId: "abc123" },
191
+ fields: ["id", "entryId", "values.name"]
157
192
  });
158
193
  ```
159
194
 
160
- ### The `fields` Parameter
195
+ ### Preview Mode (Drafts)
161
196
 
162
- Control which fields are returned:
197
+ Pass `preview: true` to `listEntries` or `getEntry` to access unpublished/draft content:
163
198
 
164
199
  ```typescript
165
- const result = await sdk.cms.listEntries<Product>({
200
+ const result = await webiny.cms.listEntries<Product>({
166
201
  modelId: "product",
167
- fields: ["id", "values.name", "values.price"]
202
+ fields: ["id", "entryId", "values.name"],
203
+ preview: true // returns drafts + published
168
204
  });
169
205
  ```
170
206
 
171
- When omitted, all fields are returned. The `depth` parameter (default: `1`) controls how deeply reference fields are resolved.
172
-
173
207
  ## Writing Data
174
208
 
209
+ > **CRITICAL:** Content fields MUST be wrapped inside a `values` key in the `data` object. Passing fields directly (without `values`) will result in an empty or malformed entry.
210
+
175
211
  ### Create an Entry
176
212
 
177
213
  ```typescript
178
- const result = await sdk.cms.createEntry({
214
+ const result = await webiny.cms.createEntry({
179
215
  modelId: "contactSubmission",
180
216
  data: {
181
- name: "John Doe",
182
- email: "john@example.com",
183
- message: "Hello from the contact form!"
184
- }
217
+ values: {
218
+ // ← REQUIRED: wrap all content fields in `values`
219
+ name: "John Doe",
220
+ email: "john@example.com",
221
+ message: "Hello from the contact form!"
222
+ }
223
+ },
224
+ fields: ["id", "entryId"]
185
225
  });
186
226
  ```
187
227
 
188
- ### Update an Entry
228
+ ### Update an Entry Revision
229
+
230
+ The method is `updateEntryRevision`, not `updateEntry`. Use `revisionId` (the full `entryId#revisionNumber`, e.g. `"abc123#0001"`):
189
231
 
190
232
  ```typescript
191
- const result = await sdk.cms.updateEntry({
233
+ const result = await webiny.cms.updateEntryRevision({
192
234
  modelId: "product",
193
- id: "abc123#0001",
235
+ revisionId: "abc123#0001", // ← note: revisionId, not id
194
236
  data: {
195
- price: 29.99
196
- }
237
+ values: {
238
+ // ← REQUIRED: wrap fields in `values`
239
+ price: 29.99
240
+ }
241
+ },
242
+ fields: ["id", "entryId", "values.price"]
197
243
  });
198
244
  ```
199
245
 
200
246
  ### Publish / Unpublish
201
247
 
248
+ The methods are `publishEntryRevision` and `unpublishEntryRevision`, not `publishEntry`/`unpublishEntry`. Both require `revisionId` and `fields`:
249
+
202
250
  ```typescript
203
- await sdk.cms.publishEntry({ modelId: "product", id: "abc123#0001" });
204
- await sdk.cms.unpublishEntry({ modelId: "product", id: "abc123#0001" });
251
+ await webiny.cms.publishEntryRevision({
252
+ modelId: "product",
253
+ revisionId: "abc123#0001",
254
+ fields: ["id", "entryId", "status"]
255
+ });
256
+
257
+ await webiny.cms.unpublishEntryRevision({
258
+ modelId: "product",
259
+ revisionId: "abc123#0001",
260
+ fields: ["id", "entryId", "status"]
261
+ });
262
+ ```
263
+
264
+ ### Delete an Entry Revision
265
+
266
+ ```typescript
267
+ await webiny.cms.deleteEntryRevision({
268
+ modelId: "product",
269
+ revisionId: "abc123#0001",
270
+ fields: []
271
+ });
272
+ ```
273
+
274
+ ## Languages
275
+
276
+ `webiny.languages.listLanguages()` returns all **enabled** languages — disabled languages are always filtered out server-side, so no filter parameter is needed.
277
+
278
+ ```typescript
279
+ import type { Language } from "@webiny/sdk";
280
+
281
+ const result = await webiny.languages.listLanguages();
282
+
283
+ if (result.isOk()) {
284
+ const languages: Language[] = result.value;
285
+ // languages[0].code, .name, .direction, .isDefault
286
+ }
287
+ ```
288
+
289
+ The `Language` type:
290
+
291
+ ```typescript
292
+ interface Language {
293
+ id: string;
294
+ code: string; // e.g. "en-US"
295
+ name: string; // e.g. "English (US)"
296
+ direction?: "ltr" | "rtl";
297
+ isDefault?: boolean;
298
+ }
205
299
  ```
206
300
 
207
301
  ## File Manager
208
302
 
209
303
  ```typescript
210
304
  // List files
211
- const files = await sdk.fileManager.listFiles({ limit: 20 });
305
+ const files = await webiny.fileManager.listFiles({
306
+ limit: 20,
307
+ fields: ["id", "key", "name", "size", "type", "src"]
308
+ });
212
309
 
213
- // Upload a file
214
- const uploaded = await sdk.fileManager.uploadFile({ file: myFile });
310
+ // Upload a file (returns presigned URL for direct S3 upload)
311
+ const uploaded = await webiny.fileManager.uploadFile({ file: myFile });
215
312
  ```
216
313
 
217
314
  ## Creating API Keys via Code
@@ -249,21 +346,38 @@ Register (**YOU MUST include the `.ts` file extension in the `src` prop** — om
249
346
 
250
347
  ## SDK Modules Reference
251
348
 
252
- | Module | Webiny App | What You Can Do |
253
- | -------------------- | --------------- | ----------------------------------------------------- |
254
- | `sdk.cms` | Headless CMS | List, get, create, update, publish, unpublish entries |
255
- | `sdk.fileManager` | File Manager | List, upload, and manage files and folders |
256
- | `sdk.websiteBuilder` | Website Builder | List and retrieve website builder content |
349
+ | Module | Webiny App | What You Can Do |
350
+ | ---------------------- | ------------- | --------------------------------------------------------------------- |
351
+ | `webiny.cms` | Headless CMS | List, get, create, update, publish, unpublish, delete entry revisions |
352
+ | `webiny.fileManager` | File Manager | List, upload, and manage files and folders |
353
+ | `webiny.tenantManager` | Multi-tenancy | Create, install, enable, disable tenants |
354
+ | `webiny.languages` | Languages | List enabled languages (id, code, name, direction, isDefault) |
355
+
356
+ ## Common Mistakes
357
+
358
+ | Mistake | Correct |
359
+ | --------------------------- | --------------------------------------- |
360
+ | `data: { name: "..." }` | `data: { values: { name: "..." } }` |
361
+ | `updateEntry(...)` | `updateEntryRevision(...)` |
362
+ | `publishEntry(...)` | `publishEntryRevision(...)` |
363
+ | `unpublishEntry(...)` | `unpublishEntryRevision(...)` |
364
+ | `sort: ["values.name_ASC"]` | `sort: { "values.name": "asc" }` |
365
+ | `getEntry({ id: "..." })` | `getEntry({ where: { id: "..." } })` |
366
+ | Omitting `fields` | Always provide `fields: [...]` |
367
+ | Trailing slash in endpoint | Remove trailing slash from endpoint URL |
257
368
 
258
369
  ## Quick Reference
259
370
 
260
371
  ```
261
- Install: npm install @webiny/sdk
262
- Import: import { Sdk } from "@webiny/sdk";
263
- Type import: import type { CmsEntryData } from "@webiny/sdk";
264
- Initialize: new Sdk({ token, endpoint, tenant })
265
- Result check: result.isOk() -> result.value.data / result.error.message
266
- API endpoint: yarn webiny info (in your Webiny project)
372
+ Install: npm install @webiny/sdk
373
+ Import: import { Webiny } from "@webiny/sdk";
374
+ Type import: import type { CmsEntryData } from "@webiny/sdk";
375
+ Initialize: new Webiny({ token, endpoint, tenant })
376
+ Result check: result.isOk() -> result.value.data / result.error.message
377
+ API endpoint: yarn webiny info (in your Webiny project) -- NO trailing slash
378
+ Preview mode: pass preview: true to listEntries / getEntry
379
+ fields required: every method needs a fields: string[] array
380
+ values wrapper: createEntry/updateEntryRevision data must use { values: { ... } }
267
381
  ```
268
382
 
269
383
  ## Related Skills