Skip to main content
Glama
RayanZaki

MCP Google Contacts Server

by RayanZaki

search_contacts

Find contacts in Google Contacts by searching names, emails, or phone numbers with a query and optional result limit.

Instructions

Search contacts by name, email, or phone number.

Args: query: Search term to find in contacts max_results: Maximum number of results to return (default: 10)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
max_resultsNo

Implementation Reference

  • The main handler function for the 'search_contacts' MCP tool. Decorated with @mcp.tool(), it initializes the Google Contacts service, lists contacts, performs case-insensitive substring search across displayName, givenName, familyName, email, and phone fields, limits results, and formats output using format_contacts_list.
    @mcp.tool() async def search_contacts(query: str, max_results: int = 10) -> str: """Search contacts by name, email, or phone number. Args: query: Search term to find in contacts max_results: Maximum number of results to return (default: 10) """ service = init_service() if not service: return "Error: Google Contacts service is not available. Please check your credentials." try: # Get all contacts and filter locally with more flexible search all_contacts = service.list_contacts(max_results=max(100, max_results*2)) query = query.lower() matches = [] for contact in all_contacts: if (query in contact.get('displayName', '').lower() or query in contact.get('givenName', '').lower() or query in contact.get('familyName', '').lower() or query in str(contact.get('email', '')).lower() or query in str(contact.get('phone', '')).lower()): matches.append(contact) if len(matches) >= max_results: break if not matches: return f"No contacts found matching '{query}'." return f"Search results for '{query}':\n\n{format_contacts_list(matches)}" except Exception as e: return f"Error: Failed to search contacts - {str(e)}"
  • In the main server entrypoint, creates the FastMCP server instance and calls register_tools(mcp), which defines and registers the search_contacts tool (along with others) using the @mcp.tool() decorator.
    mcp = FastMCP("google-contacts") # Register all tools register_tools(mcp)
  • Global helper function init_service() used by search_contacts (and all tools) to lazily initialize the GoogleContactsService instance from env vars or credential files.
    def init_service() -> Optional[GoogleContactsService]: """Initialize and return a Google Contacts service instance. Returns: GoogleContactsService instance or None if initialization fails """ global contacts_service if contacts_service: return contacts_service try: # First try environment variables try: contacts_service = GoogleContactsService.from_env() print("Successfully loaded credentials from environment variables.") return contacts_service except GoogleContactsError: pass # Then try default file locations for path in config.credentials_paths: if path.exists(): try: print(f"Found credentials file at {path}") contacts_service = GoogleContactsService.from_file(path) print("Successfully loaded credentials from file.") return contacts_service except GoogleContactsError as e: print(f"Error with credentials at {path}: {e}") continue print("No valid credentials found. Please provide credentials to use Google Contacts.") return None except Exception as e: print(f"Error initializing Google Contacts service: {str(e)}") traceback.print_exc() return None
  • The GoogleContactsService.list_contacts() method called by search_contacts to fetch a batch of contacts for local filtering.
    def list_contacts(self, name_filter: Optional[str] = None, max_results: int = None) -> List[Dict[str, Any]]: """List contacts, optionally filtering by name. Args: name_filter: Optional filter to find contacts by name max_results: Maximum number of results to return Returns: List of contact dictionaries Raises: GoogleContactsError: If API request fails """ max_results = max_results or config.default_max_results try: # Get list of connections (contacts) results = self.service.people().connections().list( resourceName='people/me', pageSize=max_results, personFields='names,emailAddresses,phoneNumbers', sortOrder='FIRST_NAME_ASCENDING' ).execute() connections = results.get('connections', []) if not connections: return [] contacts = [] for person in connections: names = person.get('names', []) if not names: continue name = names[0] given_name = name.get('givenName', '') family_name = name.get('familyName', '') display_name = name.get('displayName', '') # Apply name filter if provided if name_filter and name_filter.lower() not in display_name.lower(): continue # Get email addresses emails = person.get('emailAddresses', []) email = emails[0].get('value') if emails else None # Get phone numbers phones = person.get('phoneNumbers', []) phone = phones[0].get('value') if phones else None contacts.append({ 'resourceName': person.get('resourceName'), 'givenName': given_name, 'familyName': family_name, 'displayName': display_name, 'email': email, 'phone': phone }) return contacts except HttpError as error: raise GoogleContactsError(f"Error listing contacts: {error}")

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/RayanZaki/mcp-google-contacts-server'

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