Skip to main content
Glama
webflow

Webflow

Official
by webflow

Data Pages Tool

data_pages_tool

List, retrieve metadata and content, update settings, and edit static text for Webflow pages.

Instructions

Data tool - Pages tool to perform actions like list pages, get page metadata, update page settings, get page content, and update static content

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionsYes

Implementation Reference

  • The actual handler function for the data_pages_tool - iterates over actions (list_pages, get_page_metadata, update_page_settings, get_page_content, update_static_content) and executes the corresponding helper functions.
        async ({ actions }) => {
          const result: Content[] = [];
          try {
            for (const action of actions) {
              if (action.list_pages) {
                const content = await listPages(action.list_pages);
                result.push(textContent(content));
              }
              if (action.get_page_metadata) {
                const content = await getPageMetadata(action.get_page_metadata);
                result.push(textContent(content));
              }
              if (action.update_page_settings) {
                const content = await updatePageSettings(
                  action.update_page_settings
                );
                result.push(textContent(content));
              }
              if (action.get_page_content) {
                const content = await getPageContent(action.get_page_content);
                result.push(textContent(content));
              }
              if (action.update_static_content) {
                const content = await updateStaticContent(
                  action.update_static_content
                );
                result.push(textContent(content));
              }
            }
            return toolResponse(result);
          } catch (error) {
            return formatErrorResponse(error);
          }
        }
      );
    }
  • Five helper handler functions (listPages, getPageMetadata, updatePageSettings, getPageContent, updateStaticContent) that make the actual Webflow API calls for the data_pages_tool.
    const listPages = async (arg: {
      site_id: string;
      localeId?: string;
      limit?: number;
      offset?: number;
    }) => {
      const response = await getClient().pages.list(
        arg.site_id,
        {
          localeId: arg.localeId,
          limit: arg.limit,
          offset: arg.offset,
        },
        requestOptions
      );
      return response;
    };
    
    const getPageMetadata = async (arg: {
      page_id: string;
      localeId?: string;
    }) => {
      const response = await getClient().pages.getMetadata(
        arg.page_id,
        {
          localeId: arg.localeId,
        },
        requestOptions
      );
      return response;
    };
    
    const updatePageSettings = async (arg: {
      page_id: string;
      localeId?: string;
      body: z.infer<typeof WebflowPageSchema>;
    }) => {
      const { seo, openGraph, slug, title, ...rest } = arg.body;
      const pageSettings = {
        ...(seo && { seo }),
        ...(openGraph && { openGraph }),
        ...(slug && { slug }),
        ...(title && { title }),
      };
      const response = await getClient().pages.updatePageSettings(
        arg.page_id,
        {
          localeId: arg.localeId,
          ...pageSettings,
          body: { ...rest, ...pageSettings },
        },
        requestOptions
      );
      return response;
    };
    
    const getPageContent = async (arg: {
      page_id: string;
      localeId?: string;
      limit?: number;
      offset?: number;
    }) => {
      const response = await getClient().pages.getContent(
        arg.page_id,
        {
          localeId: arg.localeId,
          limit: arg.limit,
          offset: arg.offset,
        },
        requestOptions
      );
      return response;
    };
    
    const updateStaticContent = async (arg: {
      page_id: string;
      localeId: string;
      nodes: any;
    }) => {
      const response = await getClient().pages.updateStaticContent(
        arg.page_id,
        {
          localeId: arg.localeId,
          nodes: arg.nodes,
        },
        requestOptions
      );
      return response;
    };
  • Registration of the 'data_pages_tool' via server.registerTool() including metadata (title, description, annotations) and the input schema with all five possible actions.
      server.registerTool(
        "data_pages_tool",
        {
          title: "Data Pages Tool",
          annotations: {
            readOnlyHint: false,
          },
          description:
            "Data tool - Pages tool to perform actions like list pages, get page metadata, update page settings, get page content, and update static content",
          inputSchema: {
            actions: z.array(
              z
                .object({
                  // GET https://api.webflow.com/v2/sites/:site_id/pages
                  list_pages: z
                    .object({
                      site_id: z
                        .string()
                        .describe("The site's unique ID, used to list its pages."),
                      localeId: z
                        .string()
                        .optional()
                        .describe(
                          "Unique identifier for a specific locale. Applicable when using localization."
                        ),
                      limit: z
                        .number()
                        .optional()
                        .describe(
                          "Maximum number of records to be returned (max limit: 100)"
                        ),
                      offset: z
                        .number()
                        .optional()
                        .describe(
                          "Offset used for pagination if the results have more than limit records."
                        ),
                    })
                    .optional()
                    .describe(
                      "List all pages within a site. Returns page metadata including IDs, titles, and slugs."
                    ),
                  // GET https://api.webflow.com/v2/pages/:page_id
                  get_page_metadata: z
                    .object({
                      page_id: z
                        .string()
                        .describe("Unique identifier for the page."),
                      localeId: z
                        .string()
                        .optional()
                        .describe(
                          "Unique identifier for a specific locale. Applicable when using localization."
                        ),
                    })
                    .optional()
                    .describe(
                      "Get metadata for a specific page including SEO settings, Open Graph data, and page status (draft/published)."
                    ),
                  // PUT https://api.webflow.com/v2/pages/:page_id
                  update_page_settings: z
                    .object({
                      page_id: z
                        .string()
                        .describe("Unique identifier for the page."),
                      localeId: z
                        .string()
                        .optional()
                        .describe(
                          "Unique identifier for a specific locale. Applicable when using localization."
                        ),
                      body: WebflowPageSchema,
                    })
                    .optional()
                    .describe(
                      "Update page settings including SEO metadata, Open Graph data, slug, and publishing status."
                    ),
                  // GET https://api.webflow.com/v2/pages/:page_id/dom
                  get_page_content: z
                    .object({
                      page_id: z
                        .string()
                        .describe("Unique identifier for the page."),
                      localeId: z
                        .string()
                        .optional()
                        .describe(
                          "Unique identifier for a specific locale. Applicable when using localization."
                        ),
                      limit: z
                        .number()
                        .optional()
                        .describe(
                          "Maximum number of records to be returned (max limit: 100)"
                        ),
                      offset: z
                        .number()
                        .optional()
                        .describe(
                          "Offset used for pagination if the results have more than limit records."
                        ),
                    })
                    .optional()
                    .describe(
                      "Get the content structure and data for a specific page including all elements and their properties for localization."
                    ),
                  // POST https://api.webflow.com/v2/pages/:page_id/dom
                  update_static_content: z
                    .object({
                      page_id: z
                        .string()
                        .describe("Unique identifier for the page."),
                      localeId: z
                        .string()
                        .describe(
                          "Unique identifier for a specific locale. Applicable when using localization."
                        ),
                      nodes: WebflowPageDomWriteNodesItemSchema,
                    })
                    .optional()
                    .describe(
                      "Update content on a static page in secondary locales by modifying text nodes and property overrides."
                    ),
                })
                .strict()
                .refine(
                  (d) =>
                    [
                      d.list_pages,
                      d.get_page_metadata,
                      d.update_page_settings,
                      d.get_page_content,
                      d.update_static_content,
                    ].filter(Boolean).length >= 1,
                  {
                    message:
                      "Provide at least one of list_pages, get_page_metadata, update_page_settings, get_page_content, update_static_content.",
                  }
                )
            ),
          },
        },
        async ({ actions }) => {
          const result: Content[] = [];
          try {
            for (const action of actions) {
              if (action.list_pages) {
                const content = await listPages(action.list_pages);
                result.push(textContent(content));
              }
              if (action.get_page_metadata) {
                const content = await getPageMetadata(action.get_page_metadata);
                result.push(textContent(content));
              }
              if (action.update_page_settings) {
                const content = await updatePageSettings(
                  action.update_page_settings
                );
                result.push(textContent(content));
              }
              if (action.get_page_content) {
                const content = await getPageContent(action.get_page_content);
                result.push(textContent(content));
              }
              if (action.update_static_content) {
                const content = await updateStaticContent(
                  action.update_static_content
                );
                result.push(textContent(content));
              }
            }
            return toolResponse(result);
          } catch (error) {
            return formatErrorResponse(error);
          }
        }
      );
    }
  • src/mcp.ts:56-56 (registration)
    Registration call in the main MCP server setup - registerPagesTools(server, getClient) wires up the data_pages_tool into the server.
    registerPagesTools(server, getClient);
  • Zod schema for WebflowPage used as the 'body' parameter type in the update_page_settings action of the data_pages_tool.
    export const WebflowPageSchema = z.object({
      id: z.string().describe("Unique identifier for a Page."),
      siteId: z.string().optional().describe("Unique identifier for the Site."),
      title: z.string().optional().describe("Title of the page."),
      slug: z
        .string()
        .optional()
        .describe("Slug of the page (derived from title)."),
      parentId: z
        .string()
        .optional()
        .describe("Unique identifier for the parent folder."),
      collectionId: z
        .string()
        .optional()
        .describe(
          "Unique identifier for the linked collection, NULL id the Page is not part of a collection."
        ),
      createdOn: z.date().optional().describe("Date when the page was created."),
      lastUpdated: z
        .date()
        .optional()
        .describe("Date when the page was last updated."),
      archived: z
        .boolean()
        .optional()
        .describe("Indicates if the page is archived."),
      draft: z.boolean().optional().describe("Indicates if the page is a draft."),
      canBranch: z
        .boolean()
        .optional()
        .describe("Indicates if the page can be branched."),
      isBranch: z
        .boolean()
        .optional()
        .describe("Indicates if the page is Branch of another page."),
      isMembersOnly: z
        .boolean()
        .optional()
        .describe(
          "Indicates whether the Page is restricted by Memberships Controls."
        ),
      seo: z
        .object({
          title: z
            .string()
            .optional()
            .describe("The Page title shown in search engine results."),
          description: z
            .string()
            .optional()
            .describe("The Page description shown in search engine results."),
        })
        .optional()
        .describe("SEO-related fields for the page."),
      openGraph: z
        .object({
          title: z
            .string()
            .optional()
            .describe("The title supplied to Open Graph annotations."),
          titleCopied: z
            .boolean()
            .optional()
            .describe(
              "Indicates the Open Graph title was copied from the SEO title."
            ),
          description: z
            .string()
            .optional()
            .describe("The description supplied to Open Graph annotations."),
          descriptionCopied: z
            .boolean()
            .optional()
            .describe(
              "Indicates the Open Graph description was copied from the SEO description."
            ),
        })
        .optional(),
      localeId: z
        .string()
        .optional()
        .describe(
          "Unique identifier for the page locale. Applicable when using localization."
        ),
      publishedPath: z
        .string()
        .optional()
        .describe("Relative path of the published page."),
    });
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate mutation (readOnlyHint=false); description mentions update actions but adds no behavioral context like auth needs, idempotency, or side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence efficiently lists actions; could be improved with bullet points or structured format but is not wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (5 sub-actions, nested parameters), the description is too brief. It omits batching capability, pagination hints, and localization usage beyond what schema provides.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema contains detailed descriptions for all sub-action parameters, so the tool description does not need to add parameter info. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description lists specific actions (list pages, get metadata, etc.) making the purpose clear, but does not differentiate from sibling tools like de_page_tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool vs alternatives; no prerequisites or context provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/webflow/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server