tool_find_contact
Locate contacts in macOS Messages by name using fuzzy matching. Enter a name to retrieve relevant contact details quickly and accurately.
Instructions
Find a contact by name using fuzzy matching.
Args:
name: The name to search for
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
Input Schema (JSON Schema)
{
"properties": {
"name": {
"title": "Name",
"type": "string"
}
},
"required": [
"name"
],
"title": "tool_find_contactArguments",
"type": "object"
}
Implementation Reference
- mac_messages_mcp/server.py:78-108 (handler)Handler function decorated with @mcp.tool(), executes the tool logic by calling find_contact_by_name helper and formatting results.@mcp.tool() def tool_find_contact(ctx: Context, name: str) -> str: """ Find a contact by name using fuzzy matching. Args: name: The name to search for """ logger.info(f"Finding contact: {name}") try: matches = find_contact_by_name(name) if not matches: return f"No contacts found matching '{name}'." if len(matches) == 1: contact = matches[0] return f"Found contact: {contact['name']} ({contact['phone']}) with confidence {contact['score']:.2f}" else: # Format multiple matches result = [f"Found {len(matches)} contacts matching '{name}':"] for i, contact in enumerate(matches[:10]): # Limit to top 10 result.append(f"{i+1}. {contact['name']} ({contact['phone']}) - confidence {contact['score']:.2f}") if len(matches) > 10: result.append(f"...and {len(matches) - 10} more.") return "\n".join(result) except Exception as e: logger.error(f"Error in find_contact: {str(e)}") return f"Error finding contact: {str(e)}"
- mac_messages_mcp/messages.py:386-414 (helper)Core helper function that loads cached contacts, performs fuzzy matching using fuzzy_match, and returns scored contact matches.def find_contact_by_name(name: str) -> List[Dict[str, Any]]: """ Find contacts by name using fuzzy matching. Args: name: The name to search for Returns: List of matching contacts (may be multiple if ambiguous) """ contacts = get_cached_contacts() # Build a list of (name, phone) pairs to search through candidates = [(contact_name, phone) for phone, contact_name in contacts.items()] # Perform fuzzy matching matches = fuzzy_match(name, candidates) # Convert to a list of contact dictionaries results = [] for contact_name, phone, score in matches: results.append({ "name": contact_name, "phone": phone, "score": score }) return results
- mac_messages_mcp/messages.py:143-181 (helper)Fuzzy matching utility used by find_contact_by_name: checks exact, substring, then difflib ratio matching with cleaning.def fuzzy_match(query: str, candidates: List[Tuple[str, Any]], threshold: float = 0.6) -> List[Tuple[str, Any, float]]: """ Find fuzzy matches between query and a list of candidates. Args: query: The search string candidates: List of (name, value) tuples to search through threshold: Minimum similarity score (0-1) to consider a match Returns: List of (name, value, score) tuples for matches, sorted by score """ query = clean_name(query).lower() results = [] for name, value in candidates: clean_candidate = clean_name(name).lower() # Try exact match first (case insensitive) if query == clean_candidate: results.append((name, value, 1.0)) continue # Check if query is a substring of the candidate if query in clean_candidate: # Longer substring matches get higher scores score = len(query) / len(clean_candidate) * 0.9 # max 0.9 for substring if score >= threshold: results.append((name, value, score)) continue # Otherwise use difflib for fuzzy matching score = difflib.SequenceMatcher(None, query, clean_candidate).ratio() if score >= threshold: results.append((name, value, score)) # Sort results by score (highest first) return sorted(results, key=lambda x: x[2], reverse=True)