diff --git a/pyproject.toml b/pyproject.toml index 879e205..ffd50fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mcp-mailu" -version = "0.4.1" +version = "0.4.2" description = "FastMCP server for Mailu email server API integration" authors = [ {name = "Ryan Malloy", email = "ryan@supported.systems"} diff --git a/src/mcp_mailu/server.py b/src/mcp_mailu/server.py index 952b3fb..e0976a2 100644 --- a/src/mcp_mailu/server.py +++ b/src/mcp_mailu/server.py @@ -218,6 +218,127 @@ def create_mcp_server() -> FastMCP: # ===== TOOLS (ACTIONS) ===== + # List tools for Claude Desktop + @mcp.tool() + async def list_users() -> str: + """List all users in the Mailu instance.""" + try: + async with get_mailu_client() as mailu_client: + response = await mailu_client.get("/user") + response.raise_for_status() + users = response.json() + return f"Found {len(users)} users: {json.dumps(users, indent=2)}" + except Exception as e: + return f"Error listing users: {e}" + + @mcp.tool() + async def list_domains() -> str: + """List all domains in the Mailu instance.""" + try: + async with get_mailu_client() as mailu_client: + response = await mailu_client.get("/domain") + response.raise_for_status() + domains = response.json() + return f"Found {len(domains)} domains: {json.dumps(domains, indent=2)}" + except Exception as e: + return f"Error listing domains: {e}" + + @mcp.tool() + async def list_aliases() -> str: + """List all aliases in the Mailu instance.""" + try: + async with get_mailu_client() as mailu_client: + response = await mailu_client.get("/alias") + response.raise_for_status() + aliases = response.json() + return f"Found {len(aliases)} aliases: {json.dumps(aliases, indent=2)}" + except Exception as e: + return f"Error listing aliases: {e}" + + @mcp.tool() + async def list_alternative_domains() -> str: + """List all alternative domains in the Mailu instance.""" + try: + async with get_mailu_client() as mailu_client: + response = await mailu_client.get("/alternative") + response.raise_for_status() + alternatives = response.json() + return f"Found {len(alternatives)} alternative domains: {json.dumps(alternatives, indent=2)}" + except Exception as e: + return f"Error listing alternative domains: {e}" + + @mcp.tool() + async def list_relays() -> str: + """List all relays in the Mailu instance.""" + try: + async with get_mailu_client() as mailu_client: + response = await mailu_client.get("/relay") + response.raise_for_status() + relays = response.json() + return f"Found {len(relays)} relays: {json.dumps(relays, indent=2)}" + except Exception as e: + return f"Error listing relays: {e}" + + @mcp.tool() + async def get_user(email: str) -> str: + """Get details of a specific user.""" + try: + async with get_mailu_client() as mailu_client: + response = await mailu_client.get(f"/user/{email}") + response.raise_for_status() + user = response.json() + return f"User details for {email}: {json.dumps(user, indent=2)}" + except Exception as e: + return f"Error getting user {email}: {e}" + + @mcp.tool() + async def get_domain(domain: str) -> str: + """Get details of a specific domain.""" + try: + async with get_mailu_client() as mailu_client: + response = await mailu_client.get(f"/domain/{domain}") + response.raise_for_status() + domain_data = response.json() + return f"Domain details for {domain}: {json.dumps(domain_data, indent=2)}" + except Exception as e: + return f"Error getting domain {domain}: {e}" + + @mcp.tool() + async def get_alias(alias: str) -> str: + """Get details of a specific alias.""" + try: + async with get_mailu_client() as mailu_client: + response = await mailu_client.get(f"/alias/{alias}") + response.raise_for_status() + alias_data = response.json() + return f"Alias details for {alias}: {json.dumps(alias_data, indent=2)}" + except Exception as e: + return f"Error getting alias {alias}: {e}" + + @mcp.tool() + async def list_domain_users(domain: str) -> str: + """List all users in a specific domain.""" + try: + async with get_mailu_client() as mailu_client: + response = await mailu_client.get(f"/domain/{domain}/users") + response.raise_for_status() + users = response.json() + return f"Found {len(users)} users in domain {domain}: {json.dumps(users, indent=2)}" + except Exception as e: + return f"Error listing users for domain {domain}: {e}" + + @mcp.tool() + async def list_domain_managers(domain: str) -> str: + """List all managers for a specific domain.""" + try: + async with get_mailu_client() as mailu_client: + response = await mailu_client.get(f"/domain/{domain}/manager") + response.raise_for_status() + managers = response.json() + return f"Found {len(managers)} managers for domain {domain}: {json.dumps(managers, indent=2)}" + except Exception as e: + return f"Error listing managers for domain {domain}: {e}" + # User management tools @mcp.tool() async def create_user(email: str, raw_password: str, comment: str = "", quota_bytes: int = 0, diff --git a/uv.lock b/uv.lock index 84dedf6..466cd52 100644 --- a/uv.lock +++ b/uv.lock @@ -613,7 +613,7 @@ wheels = [ [[package]] name = "mcp-mailu" -version = "0.4.0" +version = "0.4.1" source = { editable = "." } dependencies = [ { name = "fastmcp" },