Skip to main content
Glama
netlify

Netlify MCP Server

Official
by netlify

netlify-project-services-reader

Retrieve Netlify project details, list projects, or access form data for specific sites using the Netlify MCP Server's read operations.

Instructions

Select and run one of the following Netlify read operations (read-only) get-project, get-projects, get-forms-for-project

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
selectSchemaYes

Implementation Reference

  • Handler function for the 'netlify-project-services-reader' tool. It authenticates with Netlify, parses the selected sub-operation from input, finds the corresponding read-only project tool, executes its callback, and returns the JSON-stringified 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) }] } });
  • Registration block for grouped domain tools. For domain='project' and operationType='read', registers 'netlify-project-services-reader' with selector schema over read-only project tools.
    // Register tools grouped by domain with selector (uses anyOf/union) 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) }] } }); }
  • Input schema definition for netlify-project-services-reader: a selector (selectSchema) that is a union over each read-only project tool's operation + params schema.
    const paramsSchema = { // @ts-ignore selectSchema: tools.length > 1 ? z.union(tools.map(tool => toSelectorSchema(tool))) : toSelectorSchema(tools[0]) };
  • Array of all project domain tools. Read-only ones (those with toolAnnotations.readOnlyHint=true, like get-project and get-projects) are grouped under netlify-project-services-reader.
    export const projectDomainTools = [ getProjectDomainTool, getProjectsDomainTool, updateVisitorAccessControlsDomainTool, updateFormsDomainTool, getFormsForProjectDomainTool, manageFormSubmissionsDomainTool, updateProjectNameDomainTool, manageEnvVarsDomainTool, createNewProjectDomainTool, ]
  • Sub-handler (cb function) for the 'get-project' operation, executed by netlify-project-services-reader when selected.
    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))); } }

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