All checks were successful
Build and Push Monarch MCP Docker Image / build (push) Successful in 8s
Implement automatic token refresh using stored credentials and TOTP MFA secret. When an API call fails with a 401/unauthorized error, the system now transparently re-authenticates using MONARCH_EMAIL, MONARCH_PASSWORD, and MONARCH_MFA_SECRET, then retries the original request. Changes: - Add refresh_authentication() function in auth.py for credential-based login - Create @retry_on_auth_error decorator to handle and retry failed auth calls - Apply decorator to all MCP tools (get_accounts, get_transactions, etc.) - Add MONARCH_MFA_SECRET to .env.example with documentation - Update login_setup.py to instruct users about required env vars - Replace PROBLEM.md with PLAN.md documenting the implementation
79 lines
2.6 KiB
Python
79 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Interactive Monarch Money login with MFA support.
|
|
Saves session securely and provides the token for Docker environment.
|
|
"""
|
|
|
|
import asyncio
|
|
import getpass
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Add src to sys.path
|
|
sys.path.insert(0, str(Path(__file__).parent / "src"))
|
|
|
|
from monarchmoney import MonarchMoney, RequireMFAException
|
|
from dotenv import load_dotenv
|
|
from monarch_mcp_custom.auth import save_token
|
|
|
|
|
|
async def main():
|
|
load_dotenv()
|
|
|
|
print("\n🏦 Monarch Money - Custom MCP Setup")
|
|
print("=" * 45)
|
|
print("This script will help you obtain an authentication token")
|
|
print("for use in your Docker .env file.\n")
|
|
|
|
mm = MonarchMoney()
|
|
|
|
try:
|
|
email = input("Email: ")
|
|
password = getpass.getpass("Password: ")
|
|
|
|
try:
|
|
await mm.login(email, password, use_saved_session=False, save_session=True)
|
|
print("✅ Login successful!")
|
|
except RequireMFAException:
|
|
print("🔐 MFA code required")
|
|
mfa_code = input("Two Factor Code: ")
|
|
await mm.multi_factor_authenticate(email, password, mfa_code)
|
|
print("✅ MFA authentication successful")
|
|
|
|
token = mm.token
|
|
if token:
|
|
print("\n" + "!" * 50)
|
|
print("🔑 YOUR MONARCH_TOKEN:")
|
|
print(f"\n{token}\n")
|
|
print("!" * 50)
|
|
print("\nCopy the token above into your .env file as:")
|
|
print(f"MONARCH_TOKEN={token}")
|
|
|
|
# Also save to local keyring for convenience
|
|
save_token(token)
|
|
print("\n✅ Token also saved to local system keyring.")
|
|
|
|
print("\n" + "=" * 50)
|
|
print("📝 IMPORTANT: For automatic re-authentication")
|
|
print("=" * 50)
|
|
print("\nIf you have MFA enabled on your Monarch account,")
|
|
print("add your MONARCH_MFA_SECRET to your .env file:")
|
|
print("\n MONARCH_MFA_SECRET=your_totp_secret_here")
|
|
print("\nYou should have saved this secret when you first")
|
|
print("set up Google Authenticator/Authy for Monarch Money.")
|
|
print("\nThis allows the MCP server to automatically re-authenticate")
|
|
print("when your token expires.")
|
|
print("\nYou also need to add your credentials:")
|
|
print(" MONARCH_EMAIL=your_email@example.com")
|
|
print(" MONARCH_PASSWORD=your_password")
|
|
print("=" * 50)
|
|
else:
|
|
print("❌ Failed to retrieve token from MonarchMoney instance.")
|
|
|
|
except Exception as e:
|
|
print(f"\n❌ Setup failed: {e}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|