Skip to main content
Glama
accounts.py•7.79 kB
""" Instantly MCP Server - Account Tools 6 tools for email account management operations. """ import json from typing import Any, Optional from urllib.parse import quote from ..client import get_client from ..models.accounts import ( ListAccountsInput, GetAccountInput, CreateAccountInput, UpdateAccountInput, ManageAccountStateInput, DeleteAccountInput, ) async def list_accounts(params: Optional[ListAccountsInput] = None) -> str: """ List email accounts with cursor-based pagination (100 per page). PAGINATION: If response contains pagination.next_starting_after, there are MORE results. Call again with starting_after=<that value> to get next page. Continue until pagination.next_starting_after is null. Status codes: 1=Active, 2=Paused, -1/-2/-3=Errors Provider codes: 1=IMAP, 2=Google, 3=Microsoft, 4=AWS Returns accounts with warmup status and campaign eligibility. """ client = get_client() # Handle case where params is None (for OpenAI/non-Claude clients) # Set default limit=100 to return more results by default if params is None: params = ListAccountsInput(limit=100) query_params = {} if params.limit: query_params["limit"] = params.limit else: # Default to 100 results if no limit specified query_params["limit"] = 100 if params.starting_after: query_params["starting_after"] = params.starting_after if params.search: query_params["search"] = params.search if params.status is not None: query_params["status"] = params.status if params.provider_code is not None: query_params["provider_code"] = params.provider_code if params.tag_ids: query_params["tag_ids"] = params.tag_ids result = await client.get("/accounts", params=query_params) # Add pagination guidance for LLMs if isinstance(result, dict): pagination = result.get("pagination", {}) next_cursor = pagination.get("next_starting_after") if next_cursor: result["_pagination_hint"] = f"MORE RESULTS AVAILABLE. Call list_accounts with starting_after='{next_cursor}' to get next page." return json.dumps(result, indent=2) async def get_account(params: GetAccountInput) -> str: """ Get account details, warmup status, and campaign eligibility by email. Returns comprehensive account information including: - Connection status and provider info - Warmup configuration and progress - Daily limits and sending gaps - Tracking domain settings """ client = get_client() email_encoded = quote(params.email, safe="") result = await client.get(f"/accounts/{email_encoded}") return json.dumps(result, indent=2) async def create_account(params: CreateAccountInput) -> str: """ Create email account with IMAP/SMTP credentials. Provider codes: - 1: IMAP (generic) - 2: Google Workspace - 3: Microsoft 365 - 4: AWS SES Requires valid IMAP and SMTP credentials for email sending. """ client = get_client() body = { "email": params.email, "first_name": params.first_name, "last_name": params.last_name, "provider_code": params.provider_code, "imap_username": params.imap_username, "imap_password": params.imap_password, "imap_host": params.imap_host, "imap_port": params.imap_port, "smtp_username": params.smtp_username, "smtp_password": params.smtp_password, "smtp_host": params.smtp_host, "smtp_port": params.smtp_port, } result = await client.post("/accounts", json=body) return json.dumps(result, indent=2) async def update_account(params: UpdateAccountInput) -> str: """ Update account settings (partial update). Common updates: - first_name, last_name: Display name - warmup: Warmup configuration (limit, advanced settings) - daily_limit: Max emails per day (1-100) - sending_gap: Minutes between emails (0-1440) - tracking_domain_name: Custom tracking domain Only include fields you want to update. """ client = get_client() email_encoded = quote(params.email, safe="") body = {} if params.first_name is not None: body["first_name"] = params.first_name if params.last_name is not None: body["last_name"] = params.last_name if params.warmup is not None: warmup_dict = params.warmup.model_dump(exclude_none=True) if warmup_dict: body["warmup"] = warmup_dict if params.daily_limit is not None: body["daily_limit"] = params.daily_limit if params.sending_gap is not None: body["sending_gap"] = params.sending_gap if params.enable_slow_ramp is not None: body["enable_slow_ramp"] = params.enable_slow_ramp if params.tracking_domain_name is not None: body["tracking_domain_name"] = params.tracking_domain_name if params.tracking_domain_status is not None: body["tracking_domain_status"] = params.tracking_domain_status if params.skip_cname_check is not None: body["skip_cname_check"] = params.skip_cname_check if params.remove_tracking_domain is not None: body["remove_tracking_domain"] = params.remove_tracking_domain if params.inbox_placement_test_limit is not None: body["inbox_placement_test_limit"] = params.inbox_placement_test_limit result = await client.patch(f"/accounts/{email_encoded}", json=body) return json.dumps(result, indent=2) async def manage_account_state(params: ManageAccountStateInput) -> str: """ Manage account state: pause, resume, enable/disable warmup, or test vitals. Actions: - pause: Stop all sending from this account - resume: Re-enable sending - enable_warmup: Start warmup process - disable_warmup: Stop warmup process - test_vitals: Test IMAP/SMTP connectivity Use test_vitals to diagnose connection issues. """ client = get_client() email_encoded = quote(params.email, safe="") action_endpoints = { "pause": f"/accounts/{email_encoded}/pause", "resume": f"/accounts/{email_encoded}/resume", "enable_warmup": "/accounts/warmup/enable", "disable_warmup": "/accounts/warmup/disable", "test_vitals": "/accounts/test/vitals", } endpoint = action_endpoints[params.action] # Different actions have different body requirements if params.action in ["pause", "resume"]: result = await client.post(endpoint) elif params.action in ["enable_warmup", "disable_warmup"]: # V2 API expects an array of emails for warmup enable/disable result = await client.post(endpoint, json={"emails": [params.email]}) else: # test_vitals # V2 API expects an array of emails for test vitals result = await client.post(endpoint, json={"emails": [params.email]}) return json.dumps(result, indent=2) async def delete_account(params: DeleteAccountInput) -> str: """ 🚨 PERMANENTLY delete an email account. CANNOT UNDO! This action: - Removes the account from all campaigns - Deletes all account data - Cannot be reversed Confirm with user before executing! """ client = get_client() email_encoded = quote(params.email, safe="") result = await client.delete(f"/accounts/{email_encoded}") return json.dumps({"success": True, "deleted": params.email, **result}, indent=2) # Export all account tools ACCOUNT_TOOLS = [ list_accounts, get_account, create_account, update_account, manage_account_state, delete_account, ]

Implementation Reference

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/bcharleson/instantly-mcp-python'

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