Skip to main content
Glama
wpfleger96

PagerDuty MCP Server

by wpfleger96

get_services

Retrieve PagerDuty services filtered by team, user context, or name query, or get details for a specific service ID.

Instructions

Get PagerDuty services by filters or get details for a specific service ID.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
service_idNoThe service ID to retrieve (optional, cannot be used with any other filters).
current_user_contextNoUse current user's team IDs to filter (default: True). Not used if `service_id` is provided.
team_idsNoFilter results to only services assigned to teams with the given IDs (optional, cannot be used with current_user_context). Not used if `service_id` is provided.
queryNoFilter services whose names contain the search query (optional). Not used if `service_id` is provided.
limitNoLimit the number of results (optional). Not used if `service_id` is provided.
includeNoList of fields to include in the response. If specified, only these fields will be returned for each service

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The `get_services` MCP tool handler function. Registered via @mcp.tool() decorator, it takes optional parameters (service_id, current_user_context, team_ids, query, limit, include). If service_id is provided, calls services.show_service(). Otherwise, validates team_ids/current_user_context and calls services.list_services().
    @mcp.tool()
    @tool_error_boundary
    @validation.validate_include_parameter(Service)
    async def get_services(
        *,
        service_id: Optional[str] = None,
        current_user_context: bool = True,
        team_ids: Optional[List[str]] = None,
        query: Optional[str] = None,
        limit: Optional[int] = None,
        include: Optional[List[str]] = None,
    ) -> Dict[str, Any]:
        """Get PagerDuty services by filters or get details for a specific service ID.
    
        Args:
            service_id (str): The service ID to retrieve (optional, cannot be used with any other filters).
            current_user_context (bool): Use current user's team IDs to filter (default: True). Not used if `service_id` is provided.
            team_ids (List[str]): Filter results to only services assigned to teams with the given IDs (optional, cannot be used with current_user_context). Not used if `service_id` is provided.
            query (str): Filter services whose names contain the search query (optional). Not used if `service_id` is provided.
            limit (int): Limit the number of results (optional). Not used if `service_id` is provided.
            include (List[str]): List of fields to include in the response. If specified, only these fields will be returned for each service
        """
        if service_id is not None:
            disallowed_filters_present = (
                team_ids is not None or query is not None or limit is not None
            )
            if disallowed_filters_present:
                raise ValueError(
                    "When `service_id` is provided, other filters (like team_ids, query, limit) cannot be used. See `docs://tools` for more information."
                )
    
            return await services.show_service(service_id=service_id, include=include)
    
        if current_user_context:
            if team_ids is not None:
                raise ValueError(
                    "Cannot specify team_ids when current_user_context is True. See `docs://tools` for more information."
                )
            user_context = await users.build_user_context()
            team_ids = user_context["team_ids"]
        elif not team_ids:
            raise ValueError(
                "Must specify at least team_ids when current_user_context is False. See `docs://tools` for more information."
            )
    
        return await services.list_services(
            team_ids=team_ids, query=query, limit=limit, include=include
        )
  • The `list_services` helper function. Builds query params (team_ids[], query), paginates using the PagerDuty /services endpoint, and parses the response using parse_list_response with the Service model.
    async def list_services(
        *,
        team_ids: Optional[List[str]] = None,
        query: Optional[str] = None,
        limit: Optional[int] = None,
        include: Optional[List[str]] = None,
    ) -> Dict[str, Any]:
        """List existing PagerDuty services. Exposed as MCP server tool.
    
        Args:
            team_ids (List[str]): Filter results to only services assigned to teams with the given IDs (optional)
            query (str): Filter services whose names contain the search query (optional)
            limit (int): Limit the number of results returned (optional)
            include (List[str]): List of fields to include in the response. If specified, only these fields will be returned for each service
    
        Returns:
            See the "Standard Response Format" section in `tools.md` for the complete standard response structure.
            The response will contain a list of services with their configuration and team assignments.
    
        Raises:
            See the "Error Handling" section in `tools.md` for common error scenarios.
        """
    
        pd_client = create_client()
    
        if team_ids is not None and not team_ids:
            raise ValueError("team_ids cannot be an empty list")
    
        params: Dict[str, Any] = {}
        if team_ids:
            params["team_ids[]"] = (
                team_ids  # PagerDuty API expects array parameters with [] suffix
            )
        if query:
            params["query"] = query
    
        try:
            response = await paginate(
                pd_client,
                SERVICES_URL,
                params=params,
                max_records=limit or DEFAULT_MAX_RESULTS,
                operation_name="list services",
            )
            return utils.parse_list_response(response, Service, "services", include=include)
        except Exception as e:
            utils.handle_api_error(e)
  • The `show_service` helper function. Fetches a single service by ID from the PagerDuty /services/{service_id} endpoint, validates via Service model, and returns standardized response.
    async def show_service(
        *, service_id: str, include: Optional[List[str]] = None
    ) -> Dict[str, Any]:
        """Get detailed information about a given service. Exposed as MCP server tool.
    
        Args:
            service_id (str): The ID of the service to get
            include (List[str]): List of fields to include in the response. If specified, only these fields will be returned for the service
    
        Returns:
            See the "Standard Response Format" section in `tools.md` for the complete standard response structure.
            The response will contain a single service with detailed configuration and team information.
    
        Raises:
            See the "Error Handling" section in `tools.md` for common error scenarios.
        """
    
        if not service_id:
            raise ValueError("service_id cannot be empty")
    
        pd_client = create_client()
    
        try:
            response = await safe_execute_async(
                lambda: pd_client.jget(f"{SERVICES_URL}/{service_id}"),
                f"fetch service {service_id}",
            )
            try:
                service_data = response["service"]
            except KeyError:
                raise RuntimeError(
                    f"Failed to fetch service {service_id}: Response missing 'service' field"
                )
    
            parsed_service = {}
            if service_data:
                model = Service.model_validate(service_data)
                parsed_service = model.to_clean_dict(include_fields=include)
    
            return utils.api_response_handler(
                results=parsed_service, resource_name="service"
            )
        except Exception as e:
            utils.handle_api_error(e)
  • Tool registration: The @mcp.tool() decorator on the get_services function registers it as an MCP tool.
    @mcp.tool()
    @tool_error_boundary
    @validation.validate_include_parameter(Service)
    async def get_services(
        *,
        service_id: Optional[str] = None,
        current_user_context: bool = True,
        team_ids: Optional[List[str]] = None,
        query: Optional[str] = None,
        limit: Optional[int] = None,
        include: Optional[List[str]] = None,
    ) -> Dict[str, Any]:
        """Get PagerDuty services by filters or get details for a specific service ID.
    
        Args:
            service_id (str): The service ID to retrieve (optional, cannot be used with any other filters).
            current_user_context (bool): Use current user's team IDs to filter (default: True). Not used if `service_id` is provided.
            team_ids (List[str]): Filter results to only services assigned to teams with the given IDs (optional, cannot be used with current_user_context). Not used if `service_id` is provided.
            query (str): Filter services whose names contain the search query (optional). Not used if `service_id` is provided.
            limit (int): Limit the number of results (optional). Not used if `service_id` is provided.
            include (List[str]): List of fields to include in the response. If specified, only these fields will be returned for each service
        """
        if service_id is not None:
            disallowed_filters_present = (
                team_ids is not None or query is not None or limit is not None
            )
            if disallowed_filters_present:
                raise ValueError(
                    "When `service_id` is provided, other filters (like team_ids, query, limit) cannot be used. See `docs://tools` for more information."
                )
    
            return await services.show_service(service_id=service_id, include=include)
    
        if current_user_context:
            if team_ids is not None:
                raise ValueError(
                    "Cannot specify team_ids when current_user_context is True. See `docs://tools` for more information."
                )
            user_context = await users.build_user_context()
            team_ids = user_context["team_ids"]
        elif not team_ids:
            raise ValueError(
                "Must specify at least team_ids when current_user_context is False. See `docs://tools` for more information."
            )
    
        return await services.list_services(
            team_ids=team_ids, query=query, limit=limit, include=include
        )
  • The Service Pydantic model defining the schema for service data returned by the tool. Fields: id, name, status, created_at, updated_at, description, teams, integrations.
    class Service(PagerDutyBaseModel):
        """A Pydantic model for a PagerDuty Service.
    
        Contains all fields available in the PagerDuty API response.
        Fields marked as excluded are intentionally omitted from MCP responses
        to optimize response size while maintaining clarity about available data.
        """
    
        # Essential fields for MCP responses - always present in PagerDuty API responses
        id: str
    
        # Core fields - present in full API responses but may be missing in simplified contexts
        name: Optional[str] = None
        status: Optional[str] = None
        created_at: Optional[str] = None
        updated_at: Optional[str] = None
    
        # Optional fields - can be None in API responses
        description: Optional[str] = None
    
        # Collections - present but can be empty
        teams: List[Reference] = []
        integrations: List[Reference] = []
    
        # API fields excluded from MCP responses for size optimization:
        # These fields are available in the PagerDuty API but excluded to reduce response size
        html_url: Optional[str] = Field(
            None, exclude=True, description="Excluded: Web UI URL"
        )
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It indicates a read operation but does not detail rate limits, pagination, or behavior on empty results. It is adequate for a simple retrieval tool but lacks depth.

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 a single concise sentence that front-loads the main action. It is efficient, though splitting into two sentences might improve readability.

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

Completeness4/5

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

Given the 100% schema coverage and presence of an output schema, the description is complete enough. It explains the two modes of operation, which is sufficient for this simple retrieval tool.

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 100%, so the schema already explains each parameter. The description adds only a high-level summary of the two modes, providing little extra meaning beyond the schema.

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

Purpose5/5

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

The description clearly states the tool retrieves PagerDuty services, with two modes: filtering or getting details for a specific ID. It distinguishes from sibling tools like get_incidents or get_teams.

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 does not explicitly state when to use this tool versus alternatives. However, it mentions the two modes, and the input schema provides constraints (e.g., service_id cannot be used with other filters), which implicitly guide usage.

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/wpfleger96/pagerduty-mcp-server'

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