Skip to main content
Glama
netlify

Netlify MCP Server

Official
by netlify

netlify-deploy-services-updater

Deploy code from a local directory to a Netlify site by specifying the deployment path and site ID for automated publishing.

Instructions

Select and run one of the following Netlify write operations deploy-site

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
selectSchemaYes

Implementation Reference

  • Registers the 'netlify-deploy-services-updater' tool (non-verbose mode) as a grouped selector for deploy domain write operations. Dispatches to sub-tools like deploy-site based on selected operation.
      const paramsSchema = {
        // @ts-ignore
        selectSchema: tools.length > 1 ? z.union(tools.map(tool => toSelectorSchema(tool))) : toSelectorSchema(tools[0])
      };
    
      const friendlyOperationType = operationType === 'read' ? 'reader' : 'updater';
      const toolName = `netlify-${domain}-services-${friendlyOperationType}`;
      const toolDescription = `Select and run one of the following Netlify ${operationType} operations${readOnlyIndicator} ${toolOperations.join(', ')}`;
    
      server.registerTool(toolName, {
        description: toolDescription,
        inputSchema: paramsSchema,
        annotations: {
          readOnlyHint: operationType === 'read'
        }
      }, async (...args) => {
        checkCompatibility();
    
        try {
          await getNetlifyAccessToken(remoteMCPRequest);
        } catch (error: NetlifyUnauthError | any) {
          if (error instanceof NetlifyUnauthError && remoteMCPRequest) {
            throw new NetlifyUnauthError();
          }
    
          return {
            content: [{ type: "text", text: error?.message || 'Failed to get Netlify token' }],
            isError: true
          };
        }
    
        appendToLog(`${toolName} operation: ${JSON.stringify(args)}`);
    
        const selectedSchema = args[0]?.selectSchema as any;
    
        if (!selectedSchema) {
          return {
            content: [{ type: "text", text: 'Failed to select a valid operation. Retry the MCP operation but select the operation and provide the right inputs.' }]
          }
        }
    
        const operation = selectedSchema.operation;
    
        const subtool = tools.find(subtool => subtool.operation === operation);
    
        if (!subtool) {
          return {
            content: [{ type: "text", text: 'Agent called the wrong MCP tool for this operation.' }]
          }
        }
    
        const result = await subtool.cb(selectedSchema.params || {}, {request: remoteMCPRequest, isRemoteMCP: !!remoteMCPRequest});
    
        appendToLog(`${domain} operation result: ${JSON.stringify(result)}`);
    
        return {
          content: [{ type: "text", text: JSON.stringify(result) }]
        }
      });
    }
  • Core handler function (cb) for the deploy-site operation in local MCP mode. Zips the deploy directory, uploads to Netlify builds API, and returns deploy details.
    export const deploySiteDomainTool: DomainTool<typeof deploySiteParamsSchema> = {
      domain: 'deploy',
      operation: 'deploy-site',
      inputSchema: deploySiteParamsSchema,
      toolAnnotations: {
        readOnlyHint: false,
      },
      omitFromRemoteMCP: true,
      cb: async (params, {request}) => {
    
        const { deployDirectory } = params;
    
        if (!deployDirectory) {
          throw new Error("Missing required parameter: deployDirectory");
        }
    
        let siteId = params.siteId;
        if (!siteId) {
          siteId = await getSiteId({ projectDir: deployDirectory });
        }
    
        if (!siteId) {
          throw new Error("Missing required parameter: siteId. Get from .netlify/state.json file or use 'netlify link' CLI command to link to an existing site and get a site id.");
        }
        
        const {deployId, buildId} = await zipAndBuild({ deployDirectory, siteId, request });
        
        return JSON.stringify({ deployId, buildId, monitorDeployUrl: `https://app.netlify.com/sites/${siteId}/deploys/${deployId}` });
      }
    }
  • Zod input schema for the deploySiteDomainTool, defining parameters for site deployment.
    const deploySiteParamsSchema = z.object({
      deployDirectory: z.string().describe(`absolute file path to the directory containing the code that should be deployed. Must be the root of the project repo unless specified.`),
      siteId: z.string().optional().describe(`provide the site id of the site of this site. If the agent cannot find the siteId, the user must confirm this is a new site. NEVER assume the user wants a new site. Use 'netlify link' CLI command to link to an existing site and get a site id.`)
    });
  • Defines the deployDomainTools array containing read and write tools for the deploy domain, used by the grouped updater/reader.
    import { getDeployByIdDomainTool } from './get-deploy.js';
    import { getDeployBySiteIdDomainTool } from './get-deploy-for-site.js';
    import { deploySiteDomainTool, deploySiteRemotelyDomainTool } from './deploy-site.js';
    
    export const deployDomainTools = [getDeployByIdDomainTool, getDeployBySiteIdDomainTool, deploySiteDomainTool, deploySiteRemotelyDomainTool];
  • Handler (cb) for deploy-site in remote MCP mode, generates CLI command with proxy token for secure remote deployment.
    export const deploySiteRemotelyDomainTool: DomainTool<typeof deploySiteRemotelyParamsSchema> = {
      domain: 'deploy',
      operation: 'deploy-site',
      inputSchema: deploySiteRemotelyParamsSchema,
      omitFromLocalMCP: true,
      toolAnnotations: {
        readOnlyHint: false,
      },
      cb: async (params, {request}) => {
    
        const proxyToken = await createJWE({
          accessToken: await getNetlifyAccessToken(request),
          siteId: params.siteId,
          // TODO: in the future, lock this down even further
          apisAllowed: [
            {
              path: `/api/v1/sites/${params.siteId}/builds`,
              method: 'POST'
            },
            // allow reads of deploys
            {
              path: '/api/v1/deploys/:deploy_id',
              method: 'GET'
            }
          ]
        }, '30m');
    
        const proxyPath = `/proxy/${proxyToken}`;
        
        return `
    
    To deploy this to Netlify, run the following command within the source/repo directory:
    
    \`\`\`shell
    npx -y @netlify/mcp@latest --site-id ${params.siteId} --proxy-path "${getOAuthIssuer()}${proxyPath}"
    \`\`\`
    
    This command will upload the code repo and run a build in Netlify's build system.
    
    By default, the command will wait for the deployment to completely finish (which can take time). 
    If you want to skip waiting for the deployment to finish, you can add the \`--no-wait\` flag to the command.
    `
      }
    };
Behavior2/5

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

The annotation provides readOnlyHint=false, indicating this is a write operation. The description adds minimal context by calling it a 'write operation' and specifying 'deploy-site,' but doesn't disclose important behavioral traits like what gets deployed, whether this creates or updates deployments, authentication requirements, rate limits, or what happens on failure. With annotations covering only the read/write aspect, the description adds little value beyond what's already structured.

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

Conciseness3/5

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

The description is concise (one sentence) but not front-loaded with essential information. It wastes space on vague phrasing like 'Select and run one of the following Netlify write operations' instead of immediately stating the tool's purpose. While brief, it doesn't efficiently communicate value.

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 this is a write operation (readOnlyHint=false) with 1 parameter (though nested with multiple sub-parameters), no output schema, and 0% schema description coverage, the description is incomplete. It doesn't explain what the tool returns, what 'deploy-site' actually means operationally, or provide enough context for an agent to understand when and how to use this tool effectively.

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?

Schema description coverage is 0%, so the description carries full burden for parameter meaning. However, the description provides no information about parameters whatsoever - it doesn't mention deployDirectory, siteId, or any other inputs. The baseline is 3 because with 0% schema coverage, the description fails to compensate for the lack of parameter documentation in the schema.

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

Purpose2/5

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

The description 'Select and run one of the following Netlify write operations deploy-site' is tautological - it essentially restates the tool name 'netlify-deploy-services-updater' as 'deploy-site' without specifying what the operation actually does. It doesn't clearly state the verb+resource combination (e.g., 'deploy code to a Netlify site') or distinguish it from sibling tools like 'netlify-project-services-updater'.

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 is provided on when to use this tool versus alternatives. While the description mentions 'one of the following Netlify write operations,' it doesn't specify what those other operations might be or when to choose this specific 'deploy-site' operation. There's no context about prerequisites, when-not-to-use scenarios, or comparison with sibling tools.

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/netlify/netlify-mcp'

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