odysseus-dev/odysseus · error · ValueError
Error: email MCP requires an authenticated owner or ODYSSEUS
Error message
Error: email MCP requires an authenticated owner or ODYSSEUS_MCP_EMAIL_OWNER when owner-scoped email accounts are configured.
What it means
ValueError (_OWNER_SCOPE_ERROR) raised while resolving the email MCP server's account config. When accounts in the database are owner-scoped (_mcp_owner_required true) but no authenticated owner is present and ODYSSEUS_MCP_EMAIL_OWNER is unset, the server refuses to start because it cannot tell which owner's mailboxes it may access.
Source
Thrown at mcp_servers/email_server.py:314
"smtp_security": os.environ.get("SMTP_SECURITY", ""),
"smtp_user": os.environ.get("SMTP_USER", ""),
"smtp_password": os.environ.get("SMTP_PASSWORD", ""),
"smtp_starttls": os.environ.get("SMTP_STARTTLS", "false").lower() == "true",
"smtp_ssl": os.environ.get("SMTP_SSL", "true").lower() == "true",
"from_address": os.environ.get("EMAIL_FROM", ""),
"archive_folder": os.environ.get("ARCHIVE_FOLDER", "Archive"),
"trash_folder": os.environ.get("TRASH_FOLDER", "Trash"),
"cache_db": os.environ.get(
"EMAIL_CACHE_DB",
EMAIL_CACHE_DB,
),
"account_id": None,
"account_name": None,
}
raw_rows = _read_accounts_from_db()
if _mcp_owner_required(raw_rows):
raise ValueError(_OWNER_SCOPE_ERROR)
rows = _filter_accounts_for_owner(raw_rows)
row = _resolve_account_from_rows(rows, account)
if _current_owner() and raw_rows and not rows:
raise ValueError("No email account is configured for the authenticated owner")
if account and rows and not row:
available = ", ".join(
f"{r.get('name') or r.get('imap_user')} <{r.get('imap_user') or r.get('from_address') or '?'}>"
for r in rows
)
raise ValueError(f"Email account not found for selector {account!r}. Available accounts: {available}")
if row:
cfg["account_id"] = row["id"]
cfg["account_name"] = row["name"]
cfg["imap_host"] = row["imap_host"] or cfg["imap_host"]
cfg["imap_port"] = int(row["imap_port"] or cfg["imap_port"])
cfg["imap_user"] = row["imap_user"] or cfg["imap_user"]
# Passwords in email_accounts are stored encrypted via
# src.secret_storage.encrypt — decrypt before handing to IMAPView on GitHub (pinned to f9235ebbf1)
Solutions
- Set ODYSSEUS_MCP_EMAIL_OWNER to the username whose email accounts should be used
- Or run the server within the authenticated app context so _current_owner() resolves
- If owner scoping is unwanted, remove owner values from the account rows so _mcp_owner_required returns false
Example fix
# before $ python mcp_servers/email_server.py # owner-scoped rows, no owner → ValueError # after $ ODYSSEUS_MCP_EMAIL_OWNER=alice python mcp_servers/email_server.py
Defensive patterns
Strategy: validation
Validate before calling
import os
owner = _current_owner() or os.environ.get('ODYSSEUS_MCP_EMAIL_OWNER')
rows = _read_accounts_from_db()
if _mcp_owner_required(rows) and not owner:
raise RuntimeError('Set ODYSSEY_MCP_EMAIL_OWNER before starting the email MCP server') Try / catch
try:
cfg = build_email_config()
except ValueError as e:
if 'authenticated owner' in str(e):
sys.exit('Set ODYSSEUS_MCP_EMAIL_OWNER=<username> and restart the email MCP server')
raise Prevention
- Set ODYSSEUS_MCP_EMAIL_OWNER in the service unit/launcher env
- Run the MCP server inside the authenticated app context when possible
- Document which account rows are owner-scoped when onboarding new owners
When it happens
Trigger: Starting/invoking the email MCP server (build of cfg) with owner-scoped account rows in the accounts DB while the request/context carries no owner and the ODYSSEUS_MCP_EMAIL_OWNER environment variable is empty.
Common situations: Running the MCP server as a standalone process without the app's auth context; env var lost in a new deployment or service file; accounts migrated to per-owner mode without updating the launcher.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- No email account is configured for the authenticated owner
- Admin only
- Email account not found for selector {account!r}. Available
- Email account {cfg.get('account_name') or account} has no SM
- No SMTP-capable email account configured
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/062932f526080516.
Report an issue: GitHub.