Skip to main content
Glama
vic3custodio

Trade Surveillance Support MCP Server

by vic3custodio

parse_email_inquiry

Extracts key information from trade surveillance inquiry emails, including inquiry type, trade IDs, time periods, priority levels, and required actions for investigation.

Instructions

Parse a user inquiry email to extract key information for investigation.

This tool analyzes email content and extracts:
- Inquiry type (trade issue, report request, data verification, etc.)
- Related trade IDs or account numbers
- Time period of interest
- Priority level
- Required actions

Args:
    email_content: The full text content of the user's inquiry email
    
Returns:
    A dictionary containing parsed information including inquiry_type,
    trade_ids, time_period, priority, and suggested_actions

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
email_contentYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The async function parse_email_inquiry parses the email content to extract trade IDs, account numbers, time periods, inquiry type, priority level, and generates suggested actions using regex patterns and keyword matching.
    async def parse_email_inquiry(email_content: str) -> dict[str, Any]:
        """
        Parse a user inquiry email to extract key information for investigation.
        
        This tool analyzes email content and extracts:
        - Inquiry type (trade issue, report request, data verification, etc.)
        - Related trade IDs or account numbers
        - Time period of interest
        - Priority level
        - Required actions
        
        Args:
            email_content: The full text content of the user's inquiry email
            
        Returns:
            A dictionary containing parsed information including inquiry_type,
            trade_ids, time_period, priority, and suggested_actions
        """
        import re
        from datetime import datetime, timedelta
        
        content_lower = email_content.lower()
        
        # Extract trade IDs (common patterns: TRD123456, TRADE-123456, T-123456, #123456)
        trade_id_patterns = [
            r'\bTRD[\-_]?\d{5,10}\b',
            r'\bTRADE[\-_]?\d{5,10}\b',
            r'\bT[\-_]\d{5,10}\b',
            r'#\d{5,10}\b',
            r'\btrade\s+(?:id|number|ref)[\s:]+(\d{5,10})\b'
        ]
        trade_ids = []
        for pattern in trade_id_patterns:
            matches = re.findall(pattern, email_content, re.IGNORECASE)
            trade_ids.extend(matches)
        trade_ids = list(set(trade_ids))  # Remove duplicates
        
        # Extract account numbers (common patterns: ACC123456, ACCT-123456, Account: 123456)
        account_patterns = [
            r'\bACC(?:T)?[\-_]?\d{5,10}\b',
            r'\baccount[\s:]+(\d{5,10})\b'
        ]
        account_numbers = []
        for pattern in account_patterns:
            matches = re.findall(pattern, email_content, re.IGNORECASE)
            account_numbers.extend(matches)
        account_numbers = list(set(account_numbers))
        
        # Extract time periods (dates, ranges, relative times)
        time_period = None
        date_patterns = [
            r'\b(\d{1,2}[-/]\d{1,2}[-/]\d{2,4})\b',  # MM/DD/YYYY or DD-MM-YYYY
            r'\b(\d{4}[-/]\d{1,2}[-/]\d{1,2})\b',    # YYYY-MM-DD
            r'\b(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{1,2},?\s+\d{4}\b',
            r'\b\d{1,2}\s+(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{4}\b'
        ]
        
        dates_found = []
        for pattern in date_patterns:
            dates_found.extend(re.findall(pattern, email_content, re.IGNORECASE))
        
        # Check for relative time references
        if 'last week' in content_lower or 'past week' in content_lower:
            time_period = "last_week"
        elif 'last month' in content_lower or 'past month' in content_lower:
            time_period = "last_month"
        elif 'yesterday' in content_lower:
            time_period = "yesterday"
        elif 'today' in content_lower or 'this morning' in content_lower:
            time_period = "today"
        elif 'last 7 days' in content_lower or 'past 7 days' in content_lower:
            time_period = "last_7_days"
        elif 'last 30 days' in content_lower or 'past 30 days' in content_lower:
            time_period = "last_30_days"
        elif dates_found:
            time_period = dates_found[0] if isinstance(dates_found[0], str) else str(dates_found[0])
        
        # Determine inquiry type based on keywords
        inquiry_type = "general_inquiry"
        inquiry_keywords = {
            "trade_issue": ["trade error", "failed trade", "trade problem", "transaction failed", "execution issue"],
            "report_request": ["generate report", "need report", "send report", "report for", "can you provide"],
            "data_verification": ["verify", "check data", "confirm", "validate", "reconcile"],
            "settlement_inquiry": ["settlement", "settle", "payment", "clearing"],
            "compliance_check": ["compliance", "audit", "regulatory", "regulation"],
            "position_inquiry": ["position", "holdings", "balance", "exposure"],
            "transaction_history": ["transaction history", "trade history", "past trades", "historical"]
        }
        
        for inq_type, keywords in inquiry_keywords.items():
            if any(keyword in content_lower for keyword in keywords):
                inquiry_type = inq_type
                break
        
        # Determine priority based on urgency indicators
        priority = "medium"
        high_priority_words = ["urgent", "asap", "immediately", "critical", "emergency", "high priority"]
        low_priority_words = ["when you can", "no rush", "low priority", "whenever"]
        
        if any(word in content_lower for word in high_priority_words):
            priority = "high"
        elif any(word in content_lower for word in low_priority_words):
            priority = "low"
        
        # Generate suggested actions based on inquiry type
        suggested_actions = []
        if inquiry_type == "report_request":
            suggested_actions = [
                "Search for relevant report config files",
                "Identify appropriate Java report generator",
                "Execute report generation",
                "Send report to requester"
            ]
        elif inquiry_type == "trade_issue":
            suggested_actions = [
                "Search trade transaction records",
                "Check for error logs",
                "Verify trade details",
                "Generate diagnostic report"
            ]
        elif inquiry_type == "data_verification":
            suggested_actions = [
                "Query relevant data sources",
                "Run reconciliation checks",
                "Generate verification report"
            ]
        elif inquiry_type == "settlement_inquiry":
            suggested_actions = [
                "Search settlement config files",
                "Check settlement status",
                "Generate settlement report"
            ]
        elif inquiry_type == "compliance_check":
            suggested_actions = [
                "Search compliance config files",
                "Run audit checks",
                "Generate compliance report"
            ]
        else:
            suggested_actions = [
                "Analyze inquiry details",
                "Search for relevant config files",
                "Identify appropriate action"
            ]
        
        result = {
            "status": "parsed",
            "inquiry_type": inquiry_type,
            "trade_ids": trade_ids,
            "account_numbers": account_numbers,
            "time_period": time_period,
            "priority": priority,
            "suggested_actions": suggested_actions,
            "raw_content_preview": email_content[:300] + "..." if len(email_content) > 300 else email_content,
            "content_length": len(email_content)
        }
        
        logger.info(f"Parsed email inquiry: {inquiry_type}, Priority: {priority}, Found {len(trade_ids)} trade IDs")
        return result
  • The @mcp.tool() decorator registers the parse_email_inquiry function as an MCP tool on the FastMCP server instance.
    @mcp.tool()
Behavior4/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 effectively describes what the tool does (analyzes email content to extract specific information) and outlines the return structure, though it lacks details on error handling, performance limits, or authentication needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded, starting with a clear purpose statement followed by bullet points of extracted information and a concise specification of arguments and returns. Every sentence adds value without redundancy.

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 tool's moderate complexity (1 parameter, no annotations, but with an output schema), the description is largely complete: it explains the purpose, parameter semantics, and return values. The output schema reduces the need to detail return structure, though additional context like error cases or limitations could enhance completeness.

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?

Schema description coverage is 0%, so the description must compensate. It adds meaning by specifying that 'email_content' is 'the full text content of the user's inquiry email', clarifying the parameter's purpose beyond the schema's basic type and title. However, it does not detail format constraints or examples.

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's purpose with a specific verb ('parse') and resource ('user inquiry email'), and distinguishes it from sibling tools by focusing on email analysis rather than report execution, summary generation, metadata rebuilding, or code/config searching.

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 ('for investigation') but does not explicitly state when to use this tool versus alternatives. No exclusions or prerequisites are mentioned, leaving the agent to infer appropriate scenarios based on the purpose alone.

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/vic3custodio/mcp_test_2'

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