Skip to main content
Glama
netlify

Netlify MCP Server

Official
by netlify

netlify-team-services-reader

Read-only

Retrieve team information from Netlify services to manage access and resources. Use this tool to get team details or list all teams in your account.

Instructions

Select and run one of the following Netlify read operations (read-only) get-teams, get-team

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
selectSchemaYes

Implementation Reference

  • Registers the 'netlify-team-services-reader' tool when processing team domain read tools. Defines the selector schema, tool name, and dispatching handler that calls the appropriate subtool callback.
    } else {
      // 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) }]
        }
      });
    }
  • Defines the selector schema used for grouped tools like netlify-team-services-reader, including operation and optional params from subtool schemas.
    const toSelectorSchema = (domainTool: DomainTool<any>) => {
      return z.object({
        // domain: z.literal(domainTool.domain),
        operation: z.literal(domainTool.operation),
        params: domainTool.inputSchema.optional(),
    
        llmModelName: z.string().optional(),
        aiAgentName: z.string().optional()
      });
    }
  • Subtool handler for 'get-teams' operation: fetches teams from Netlify API and enriches data for LLM.
    export const getTeamsDomainTool: DomainTool<typeof getTeamsParamsSchema> = {
      domain: 'team',
      operation: 'get-teams',
      inputSchema: getTeamsParamsSchema,
      toolAnnotations: {
        readOnlyHint: true,
      },
      cb: async (_, {request}) => {
        return JSON.stringify(getEnrichedTeamModelForLLM(await getAPIJSONResult('/api/v1/accounts', {}, {}, request)));
      }
    }
  • Subtool handler for 'get-team' operation: fetches specific team by ID from Netlify API and enriches data for LLM.
    export const getTeamDomainTool: DomainTool<typeof getTeamParamsSchema> = {
      domain: 'team',
      operation: 'get-team',
      inputSchema: getTeamParamsSchema,
      toolAnnotations: {  
        readOnlyHint: true,
      },
      cb: async ({ teamId }, {request}) => {
        return JSON.stringify(getEnrichedTeamModelForLLM(await getAPIJSONResult(`/api/v1/accounts/${teamId}`, {}, {}, request)));
      }
    }
  • Helper function to enrich raw team data from API with additional LLM-friendly fields.
    export function getEnrichedTeamModelForLLM(teams: any[] | any) {
      if (!teams) {
        return [];
      }
    
      return (Array.isArray(teams) ? teams : [teams]).map((team: any) => {
    
        const fieldsToMap = ['id', 'name', 'slug', 'created_at', 'updated_at', 'members_count', 'enforce_mfa', 'type_name'];
    
        return ({
          ...Object.fromEntries(Object.entries(team).filter(([key]) => fieldsToMap.includes(key))),
          _enrichedFields: {
            currentUserRoleOnTeam: team.role,
            netlifyUrlForTeam: `https://app.netlify.com/teams/${team.slug}`
          }
        });
      });
    }
Behavior3/5

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

The description adds 'read-only' context, which aligns with the readOnlyHint=true annotation, providing no contradiction. It also specifies the available operations ('get-teams, get-team'), which gives behavioral insight beyond the annotation. However, it doesn't disclose other traits like rate limits, authentication needs, or response formats. With annotations covering safety, this adds moderate value.

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?

The description is concise and front-loaded in a single sentence, efficiently stating the tool's purpose and operations. There's no wasted text, and it directly communicates the essential information. However, it could be slightly more structured by separating operation details, but it's still highly efficient.

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

Completeness3/5

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

Given the tool's complexity (multiple operations under one tool), annotations provide read-only safety, but there's no output schema. The description covers the basic purpose and operations but lacks details on return values, error handling, or how to choose between operations. It's minimally adequate but has clear gaps for a tool with nested operation choices.

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 description doesn't add parameter semantics beyond what the input schema provides. It mentions 'select and run' operations but doesn't explain the 'selectSchema' structure or parameter details like 'teamId'. With schema description coverage at 0%, the description doesn't compensate for this gap. However, since there's effectively 1 parameter (the operation choice), the baseline is appropriate, but no extra value is added.

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 clearly states the tool's purpose: 'Select and run one of the following Netlify read operations (read-only) get-teams, get-team'. It specifies the verb ('select and run'), resource ('Netlify read operations'), and scope ('get-teams, get-team'). However, it doesn't explicitly differentiate from sibling tools like 'netlify-user-services-reader' or 'netlify-project-services-reader', which likely handle different resource types.

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

Usage Guidelines3/5

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

The description implies usage context by stating 'read operations (read-only)' and listing specific operations ('get-teams, get-team'), suggesting this tool is for retrieving team-related data. However, it doesn't provide explicit guidance on when to use this tool versus alternatives (e.g., 'netlify-user-services-reader' for user data) or any prerequisites. The usage is clear but lacks sibling differentiation and exclusions.

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