Skip to main content
Glama
4tal

MCP Google Contacts Server

by 4tal

list_contacts

Retrieve Google Contacts with optional name filtering and comprehensive field selection to manage your address book efficiently.

Instructions

List all contacts or filter by name with comprehensive field support.

    Args:
        name_filter: Optional filter to find contacts by name
        max_results: Maximum number of results to return (default: 100)
        include_all_fields: Whether to include all contact fields like addresses, birthdays, etc.
    

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
name_filterNo
max_resultsNo
include_all_fieldsNo

Implementation Reference

  • Handler function for the list_contacts tool, decorated with @mcp.tool() for registration. Includes parameter schema via type hints and docstring. Executes the tool logic by calling the service.
    @mcp.tool()
    async def list_contacts(
        name_filter: Optional[str] = None, max_results: int = 100, include_all_fields: bool = False
    ) -> str:
        """List all contacts or filter by name with comprehensive field support.
    
        Args:
            name_filter: Optional filter to find contacts by name
            max_results: Maximum number of results to return (default: 100)
            include_all_fields: Whether to include all contact fields like addresses, birthdays, etc.
        """
        service = init_service()
        if not service:
            return "Error: Google Contacts service is not available. Please check your credentials."
    
        try:
            contacts = service.list_contacts(name_filter, max_results, include_all_fields)
            return format_contacts_list(contacts)
        except Exception as e:
            return f"Error: Failed to list contacts - {str(e)}"
  • GoogleContactsService.list_contacts method: the primary helper that performs the Google People API calls to list and filter contacts.
    def list_contacts(
        self,
        name_filter: Optional[str] = None,
        max_results: int = None,
        include_all_fields: bool = False,
    ) -> List[Dict[str, Any]]:
        """List contacts, optionally filtering by name with pagination support.
    
        Args:
            name_filter: Optional filter to find contacts by name
            max_results: Maximum number of results to return
            include_all_fields: Whether to include all contact fields
    
        Returns:
            List of contact dictionaries
    
        Raises:
            GoogleContactsError: If API request fails
        """
        max_results = max_results or config.default_max_results
    
        try:
            contacts = []
            next_page_token = None
    
            # Use extended fields if requested
            person_fields = (
                ",".join(self.PERSON_FIELDS)
                if include_all_fields
                else "names,emailAddresses,phoneNumbers,addresses,organizations,birthdays,urls,biographies,relations,nicknames"
            )
    
            while len(contacts) < max_results:
                page_size = min(1000, max_results - len(contacts))  # Google API limit is 1000
    
                request_params = {
                    "resourceName": "people/me",
                    "pageSize": page_size,
                    "personFields": person_fields,
                    "sortOrder": "DISPLAY_NAME_ASCENDING",
                }
    
                if next_page_token:
                    request_params["pageToken"] = next_page_token
    
                results = self.service.people().connections().list(**request_params).execute()
    
                connections = results.get("connections", [])
                if not connections:
                    break
    
                for person in connections:
                    contact = self._format_contact_enhanced(person)
    
                    # Apply name filter if provided
                    if name_filter:
                        filter_lower = name_filter.lower()
                        if not any(
                            filter_lower in str(contact.get(field, "")).lower()
                            for field in ["displayName", "givenName", "familyName", "nickname"]
                        ):
                            continue
    
                    contacts.append(contact)
    
                    if len(contacts) >= max_results:
                        break
    
                next_page_token = results.get("nextPageToken")
                if not next_page_token:
                    break
    
            return contacts
  • format_contacts_list function: formats the list of contacts into a human-readable string output.
    def format_contacts_list(contacts: List[Dict[str, Any]]) -> str:
        """Format a list of contacts into a readable string with enhanced display.
    
        Args:
            contacts: List of contact dictionaries
    
        Returns:
            Formatted string representation of the contacts list
        """
        if not contacts:
            return "No contacts found."
    
        if isinstance(contacts, dict) and "status" in contacts and contacts["status"] == "error":
            return "Error: " + contacts.get("message", "Unknown error")
    
        parts = []
    
        for i, contact in enumerate(contacts, 1):
            # Create a compact summary for lists
            contact_summary = _format_contact_summary(contact, i)
            parts.append(contact_summary)
            parts.append("")  # Add blank line between contacts
    
        summary = "šŸ“Š Found " + str(len(contacts)) + " contact(s)"
    
        # Add statistics
        stats = _calculate_contact_stats(contacts)
        if stats:
            summary += "\nšŸ“ˆ Statistics: " + stats
    
        parts.append("=" * 50)
        parts.append(summary)
    
        return "\n".join(parts)
  • src/tools.py:64-75 (registration)
    register_tools function that orchestrates calling register_contact_tools(mcp), which defines and registers the list_contacts tool.
    def register_tools(mcp: FastMCP) -> None:
        """Register all Google Contacts tools with the MCP server.
    
        Args:
            mcp: FastMCP server instance
        """
        register_contact_tools(mcp)
        register_directory_tools(mcp)
        register_contact_group_tools(mcp)
    
    
    def register_contact_tools(mcp: FastMCP) -> None:
  • src/main.py:71-75 (registration)
    In main(), creation of FastMCP server and call to register_tools(mcp) to register all tools including list_contacts.
    mcp = FastMCP("google-contacts")
    
    # Register all tools
    register_tools(mcp)
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions 'comprehensive field support' and parameters like max_results and include_all_fields, but doesn't cover critical aspects such as pagination behavior, rate limits, authentication requirements, or what happens when no contacts match. For a list operation with 3 parameters, this leaves significant gaps.

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 efficiently structured with a clear purpose statement followed by parameter explanations in a formatted Args section. Every sentence adds value, and there's no redundant information. It could be slightly more front-loaded by integrating parameter hints into the main description, but it's well-organized.

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 3 parameters, no annotations, and no output schema, the description provides adequate basics (purpose and param semantics) but lacks completeness. It doesn't explain return format, error conditions, or behavioral traits like pagination, which are important for a list tool. It's minimally viable but has clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds meaningful context for all 3 parameters beyond the schema (which has 0% description coverage). It explains that 'name_filter' finds contacts by name, 'max_results' sets a limit with a default, and 'include_all_fields' controls inclusion of detailed data like addresses and birthdays. This compensates well for the lack of schema descriptions.

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: 'List all contacts or filter by name with comprehensive field support.' It specifies the verb ('List') and resource ('contacts'), and mentions filtering capability. However, it doesn't explicitly differentiate from sibling tools like 'search_contacts' or 'get_contact', which is why it doesn't achieve a perfect score.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like 'search_contacts', 'get_contact', or 'list_workspace_users'. It mentions filtering by name and field inclusion, but doesn't specify scenarios, prerequisites, or exclusions for tool selection.

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/4tal/mcp-google-contacts'

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