Skip to content

Commit a37d426

Browse files
authored
Merge pull request #21 from webflow/feat/create-collection-and-fields
feat: add collection create, field create, and field update tools
2 parents ff7a7a1 + 17504fd commit a37d426

4 files changed

Lines changed: 146 additions & 8 deletions

File tree

README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,27 +70,32 @@ A Node.js server implementing Model Context Protocol (MCP) for Webflow using the
7070

7171
### Sites
7272

73-
````ts
73+
```
7474
sites - list; // List all sites
7575
sites - get; // Get site details
7676
sites - publish; // Publish site changes
77-
````
77+
```
7878

7979
### Pages
8080

81-
````ts
81+
```
8282
pages - list; // List all pages
8383
pages - get - metadata; // Get page metadata
8484
pages - update - page - settings; // Update page settings
8585
pages - get - content; // Get page content
8686
pages - update - static - content; // Update page content
87-
````
87+
```
8888

8989
### CMS
9090

91-
```ts
91+
```
9292
collections - list; // List collections
9393
collections - get; // Get collection details
94+
collections - create; // Create a collection
95+
collection - fields - create - static; // Create a static field
96+
collection - fields - create - option; // Create an option field
97+
collection - fields - create - reference; // Create a reference field
98+
collection - fields - update; // Update a custom field
9499
collections - items - create - item - live; // Create items
95100
collections - items - update - items - live; // Update items
96101
```

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "webflow-mcp-server",
3-
"version": "0.2.1",
3+
"version": "0.3.0",
44
"type": "module",
55
"main": "dist/index.js",
66
"bin": {

src/index.ts

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,139 @@ server.tool(
249249
}
250250
);
251251

252+
export const StaticFieldSchema = z.object({
253+
id: z.string().optional(),
254+
isEditable: z.boolean().optional(),
255+
isRequired: z.boolean().optional(),
256+
type: z.union([
257+
z.literal("Color"),
258+
z.literal("DateTime"),
259+
z.literal("Email"),
260+
z.literal("File"),
261+
z.literal("Image"),
262+
z.literal("Link"),
263+
z.literal("MultiImage"),
264+
z.literal("Number"),
265+
z.literal("Phone"),
266+
z.literal("PlainText"),
267+
z.literal("RichText"),
268+
z.literal("Switch"),
269+
z.literal("Video")
270+
]),
271+
displayName: z.string(),
272+
helpText: z.string().optional()
273+
})
274+
275+
export const OptionFieldSchema = z.object({
276+
id: z.string().optional(),
277+
isEditable: z.boolean().optional(),
278+
isRequired: z.boolean().optional(),
279+
type: z.literal("Option"),
280+
displayName: z.string(),
281+
helpText: z.string().optional(),
282+
metadata: z.object({
283+
options: z.array(
284+
z.object({
285+
name: z.string(),
286+
id: z.string().optional()
287+
})
288+
)
289+
})
290+
})
291+
292+
export const ReferenceFieldSchema = z.object({
293+
id: z.string().optional(),
294+
isEditable: z.boolean().optional(),
295+
isRequired: z.boolean().optional(),
296+
type: z.union([z.literal("MultiReference"), z.literal("Reference")]),
297+
displayName: z.string(),
298+
helpText: z.string().optional(),
299+
metadata: z.object({
300+
collectionId: z.string()
301+
})
302+
})
303+
304+
// request: Webflow.CollectionsCreateRequest
305+
// NOTE: Cursor agent seems to struggle when provided with z.union(...), so we simplify the type here
306+
export const WebflowCollectionsCreateRequestSchema = z.object({
307+
displayName: z.string(),
308+
singularName: z.string(),
309+
slug: z.string().optional(),
310+
})
311+
312+
// POST https://api.webflow.com/v2/sites/:site_id/collections
313+
server.tool(
314+
"collections_create",
315+
{
316+
site_id: z.string(),
317+
request: WebflowCollectionsCreateRequestSchema
318+
},
319+
async ({ site_id, request }) => {
320+
const response = await client.collections.create(site_id, request);
321+
return { content: [{ type: "text", text: JSON.stringify(response) }] };
322+
}
323+
);
324+
325+
// POST https://api.webflow.com/v2/collections/:collection_id/fields
326+
server.tool(
327+
"collection_fields_create_static",
328+
{
329+
collection_id: z.string(),
330+
request: StaticFieldSchema
331+
},
332+
async ({ collection_id, request }) => {
333+
const response = await client.collections.fields.create(collection_id, request);
334+
return { content: [{ type: "text", text: JSON.stringify(response) }] };
335+
}
336+
)
337+
338+
// POST https://api.webflow.com/v2/collections/:collection_id/fields
339+
server.tool(
340+
"collection_fields_create_option",
341+
{
342+
collection_id: z.string(),
343+
request: OptionFieldSchema
344+
},
345+
async ({ collection_id, request }) => {
346+
const response = await client.collections.fields.create(collection_id, request);
347+
return { content: [{ type: "text", text: JSON.stringify(response) }] };
348+
}
349+
)
350+
351+
// POST https://api.webflow.com/v2/collections/:collection_id/fields
352+
server.tool(
353+
"collection_fields_create_reference",
354+
{
355+
collection_id: z.string(),
356+
request: ReferenceFieldSchema
357+
},
358+
async ({ collection_id, request }) => {
359+
const response = await client.collections.fields.create(collection_id, request);
360+
return { content: [{ type: "text", text: JSON.stringify(response) }] };
361+
}
362+
)
363+
364+
// request: Webflow.collections.FieldUpdate
365+
export const WebflowCollectionsFieldUpdateSchema = z.object({
366+
isRequired: z.boolean().optional(),
367+
displayName: z.string().optional(),
368+
helpText: z.string().optional()
369+
})
370+
371+
// PATCH https://api.webflow.com/v2/collections/:collection_id/fields/:field_id
372+
server.tool(
373+
"collection_fields_update",
374+
{
375+
collection_id: z.string(),
376+
field_id: z.string(),
377+
request: WebflowCollectionsFieldUpdateSchema
378+
},
379+
async ({ collection_id, field_id, request }) => {
380+
const response = await client.collections.fields.update(collection_id, field_id, request);
381+
return { content: [{ type: "text", text: JSON.stringify(response) }] };
382+
}
383+
)
384+
252385
// request: Webflow.collections.ItemsCreateItemLiveRequest
253386
const WebflowCollectionsItemsCreateItemLiveRequestSchema = z.object({
254387
items: z

0 commit comments

Comments
 (0)