Skip to main content
Glama
vargahis

monarch-mcp

get_account_holdings

Retrieve investment holdings data for a specific Monarch Money account to view portfolio details and asset allocation.

Instructions

Get investment holdings for a specific account.

Args: account_id: The ID of the investment account

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
account_idYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The main handler function for the 'get_account_holdings' MCP tool. It's decorated with @mcp.tool() for registration and @_handle_mcp_errors for error handling. The function takes an account_id parameter, creates an async helper that gets the MonarchMoney client and calls client.get_account_holdings(account_id), then returns the JSON-serialized result.
    @mcp.tool()
    @_handle_mcp_errors("getting account holdings")
    def get_account_holdings(account_id: str) -> str:
        """
        Get investment holdings for a specific account.
    
        Args:
            account_id: The ID of the investment account
        """
    
        async def _get_holdings():
            client = await get_monarch_client()
            return await client.get_account_holdings(account_id)
    
        holdings = run_async(_get_holdings())
    
        return json.dumps(holdings, indent=2, default=str)
  • The _handle_mcp_errors decorator that wraps the get_account_holdings handler to provide comprehensive error handling. It catches RuntimeError, TransportServerError, TransportQueryError, TransportError, and generic Exception, returning user-friendly error messages.
    def _handle_mcp_errors(operation: str):
        """Decorator providing granular exception handling for MCP tool functions.
    
        Catches specific known exception types with appropriate log messages,
        with a catch-all for anything unexpected.  Every path returns a
        user-readable error string so the MCP tool never crashes.
        """
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kwargs):
                try:
                    return func(*args, **kwargs)
                except RuntimeError as exc:
                    logger.error("Runtime error %s: %s", operation, exc)
                    return f"Error {operation}: {exc}"
                except TransportServerError as exc:
                    code = getattr(exc, "code", "unknown")
                    logger.error(
                        "Monarch API HTTP %s error %s: %s", code, operation, exc,
                    )
                    return f"Error {operation}: Monarch API returned HTTP {code}: {exc}"
                except TransportQueryError as exc:
                    logger.error("Monarch API query error %s: %s", operation, exc)
                    return f"Error {operation}: API query failed: {exc}"
                except TransportError as exc:
                    logger.error(
                        "Monarch API connection error %s: %s", operation, exc,
                    )
                    return f"Error {operation}: connection error: {exc}"
                except Exception as exc:  # pylint: disable=broad-exception-caught
                    logger.error(
                        "Unexpected error %s: %s (%s)",
                        operation, exc, type(exc).__name__,
                    )
                    return f"Error {operation}: {exc}"
            return wrapper
        return decorator
  • The get_monarch_client async helper function that creates and returns a MonarchMoney client instance. It first tries to get an authenticated client from secure session storage, then falls back to environment credentials (MONARCH_EMAIL, MONARCH_PASSWORD).
    async def get_monarch_client() -> MonarchMoney:
        """Get or create MonarchMoney client instance using secure session storage."""
        # Try to get authenticated client from secure session
        client = secure_session.get_authenticated_client()
    
        if client is not None:
            logger.info("Using authenticated client from secure keyring storage")
            return client
    
        # If no secure session, try environment credentials
        email = os.getenv("MONARCH_EMAIL")
        password = os.getenv("MONARCH_PASSWORD")
    
        if email and password:
            try:
                client = MonarchMoney()
                await client.login(email, password)
                logger.info(
                    "Successfully logged into Monarch Money with environment credentials"
                )
    
                # Save the session securely
                secure_session.save_authenticated_session(client)
    
                return client
            except Exception as e:
                logger.error("Failed to login to Monarch Money: %s", e)
                raise
  • The @mcp.tool() decorator registers the get_account_holdings function as an MCP tool with the FastMCP server. FastMCP automatically generates the input schema from the function signature (account_id: str).
    @mcp.tool()
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It states the tool retrieves data ('Get'), implying a read-only operation, but fails to mention critical details like authentication requirements, rate limits, error handling, or what the output contains. This leaves significant gaps in understanding how the tool behaves in practice.

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 highly concise and well-structured, with a clear purpose statement followed by a brief parameter explanation. Every sentence serves a purpose without redundancy, making it easy to parse and understand quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (1 parameter, no annotations, but with an output schema), the description is minimally adequate. It covers the basic purpose and parameter, but lacks context on authentication, error cases, or how it fits with sibling tools. The presence of an output schema means return values are documented elsewhere, so the description does not need to explain outputs, but overall completeness is moderate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds minimal semantic context for the single parameter 'account_id', specifying it as 'The ID of the investment account'. With 0% schema description coverage, this provides some value, but it does not elaborate on format, validation, or sourcing of the ID. Since there is only one parameter, the baseline is 4, but the limited detail reduces the score to 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/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 ('Get') and resource ('investment holdings for a specific account'), making it immediately understandable. However, it does not explicitly differentiate from sibling tools like 'get_accounts' or 'get_account_history', which reduces its score from a perfect 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It lacks any mention of prerequisites, such as requiring authentication or account access, and does not clarify its role relative to sibling tools like 'get_accounts' or 'get_account_history', leaving usage context unclear.

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/vargahis/monarch-mcp'

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