netlify-project-services-updater
Update Netlify project settings including access controls, forms, environment variables, and project names through the Netlify MCP Server.
Instructions
Select and run one of the following Netlify write operations update-visitor-access-controls, update-forms, manage-form-submissions, update-project-name, manage-env-vars, create-new-project
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| selectSchema | Yes |
Implementation Reference
- src/tools/index.ts:154-197 (handler)Handler function that performs authentication, parses the selected operation from input, finds the corresponding project write tool, executes it, and returns the JSON result.}, 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) }] } });
- src/tools/index.ts:139-142 (schema)Input schema definition using Zod union over selector schemas for each project updater tool (operation + params).const paramsSchema = { // @ts-ignore selectSchema: tools.length > 1 ? z.union(tools.map(tool => toSelectorSchema(tool))) : toSelectorSchema(tools[0]) };
- src/tools/index.ts:148-154 (registration)Registers the 'netlify-project-services-updater' tool (toolName = `netlify-${domain}-services-updater` where domain='project') with its description, schema, and handler.server.registerTool(toolName, { description: toolDescription, inputSchema: paramsSchema, annotations: { readOnlyHint: operationType === 'read' } }, async (...args) => {
- Array of project domain tools. The write tools among these are dispatched to by the services-updater handler based on selected operation.export const projectDomainTools = [ getProjectDomainTool, getProjectsDomainTool, updateVisitorAccessControlsDomainTool, updateFormsDomainTool, getFormsForProjectDomainTool, manageFormSubmissionsDomainTool, updateProjectNameDomainTool, manageEnvVarsDomainTool, createNewProjectDomainTool, ]
- Example of a project domain tool definition, confirming domain='project' (read tool, but shows structure for write tools too). Note: individual write tools follow similar pattern with their own cb handlers.export const getProjectDomainTool: DomainTool<typeof getProjectParamsSchema> = { domain: 'project', operation: 'get-project', inputSchema: getProjectParamsSchema, toolAnnotations: { readOnlyHint: true, }, cb: async ({ siteId }, {request}) => { return JSON.stringify(getEnrichedSiteModelForLLM(await getAPIJSONResult(`/api/v1/sites/${siteId}`, {}, {}, request))); } }