netlify-extension-services-reader
Retrieve Netlify extension information by listing available extensions or getting detailed specifications for specific extensions.
Instructions
Select and run one of the following Netlify read operations (read-only) get-extensions, get-full-extension-details
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| selectSchema | Yes |
Implementation Reference
- src/tools/index.ts:144-154 (registration)Registers the netlify-extension-services-reader tool for the extension domain read operations.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) => {
- src/tools/index.ts:155-197 (handler)Main handler logic for netlify-extension-services-reader: authenticates, selects sub-operation (e.g. 'get-extensions'), executes the corresponding DomainTool callback, and returns JSON result.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) }] } });
- Sub-handler for 'get-extensions' operation: fetches and returns list of available extensions.export const getExtensionsDomainTool: DomainTool<typeof getExtensionsParamsSchema> = { domain: 'extension', operation: 'get-extensions', inputSchema: getExtensionsParamsSchema, toolAnnotations: { readOnlyHint: true, }, cb: async () => { return JSON.stringify({ context: 'This list of extensions is available to any Netlify team. This list DOES NOT inform if the extension is installed or configured for a particular team or account.', extensions: await getExtensions() }); } }
- Sub-handler for 'get-full-extension-details' operation: fetches details for a specific extension.export const getFullExtensionDetailsDomainTool: DomainTool<typeof getFullExtensionDetailsParamsSchema> = { domain: 'extension', operation: 'get-full-extension-details', inputSchema: getFullExtensionDetailsParamsSchema, toolAnnotations: { readOnlyHint: true, }, cb: async ({ extensionSlug, teamId }, {request}) => { return JSON.stringify(await getExtension({ extensionSlug, accountId: teamId, request })); } }
- Utility function that fetches the list of all available Netlify extensions from the SDK API.export const getExtensions = async (): Promise<NetlifyExtension[]> => { const res = await unauthenticatedFetch(`${sdkBaseUrl}/integrations`); if (!res.ok) { throw new Error(`Failed to fetch extensions`); } return await res.json(); }