Skip to main content
Glama
debtstack-ai

DebtStack MCP Server

resolve_bond

Look up bond details using CUSIP, ISIN, or descriptive text to retrieve comprehensive bond information for financial analysis.

Instructions

Look up a bond by CUSIP, ISIN, or description. Use when you have a partial bond identifier and need full details. Example: 'RIG 8% 2027' or 'CUSIP 893830AK8'

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesBond identifier - CUSIP, ISIN, or description (e.g., 'RIG 8% 2027')

Implementation Reference

  • The MCP tool handler that processes resolve_bond requests. It detects the identifier type (CUSIP, ISIN, or free-text), builds the appropriate parameters, calls the API endpoint, and formats the response with confidence scores.
    elif name == "resolve_bond":
        query = arguments.get("query", "").strip()
        params = {}
    
        # Detect identifier type
        if len(query) == 9 and query.isalnum():
            params["cusip"] = query
        elif len(query) == 12 and query[:2].isalpha():
            params["isin"] = query
        else:
            params["q"] = query
            params["match_mode"] = "fuzzy"
    
        result = api_get("/bonds/resolve", params)
        matches = result.get("data", {}).get("matches", [])
    
        if not matches:
            return [TextContent(type="text", text=f"No bonds found matching '{query}'.")]
    
        text = f"Found {len(matches)} match(es) for '{query}':\n\n"
        for m in matches:
            conf = m.get("confidence", 0)
            bond = m.get("bond", {})
            text += f"**Confidence: {conf:.0%}**\n"
            text += format_bond(bond) + "\n\n"
    
        return [TextContent(type="text", text=text)]
  • MCP tool registration for resolve_bond with its name, description, and input schema defining the 'query' parameter as required.
    Tool(
        name="resolve_bond",
        description=(
            "Look up a bond by CUSIP, ISIN, or description. "
            "Use when you have a partial bond identifier and need full details. "
            "Example: 'RIG 8% 2027' or 'CUSIP 893830AK8'"
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "Bond identifier - CUSIP, ISIN, or description (e.g., 'RIG 8% 2027')"
                }
            },
            "required": ["query"]
        }
    ),
  • Pydantic BaseModel schema defining the ResolveBondInput with a required 'query' field for bond identifier resolution.
    class ResolveBondInput(BaseModel):
        """Input for bond resolution tool."""
        query: str = Field(
            ...,
            description="Bond identifier to resolve - can be CUSIP, ISIN, or description (e.g., 'RIG 8% 2027')"
        )
  • Async API client method that implements the actual resolve_bond call, accepting various parameters (q, cusip, isin, ticker, coupon, maturity_year) and making an HTTP GET request to /bonds/resolve endpoint.
    async def resolve_bond(
        self,
        q: Optional[str] = None,
        cusip: Optional[str] = None,
        isin: Optional[str] = None,
        ticker: Optional[str] = None,
        coupon: Optional[float] = None,
        maturity_year: Optional[int] = None,
        match_mode: str = "fuzzy",
        limit: int = 5,
    ) -> Dict[str, Any]:
        """
        Resolve bond identifiers - map descriptions to CUSIPs, ISINs, etc.
    
        Args:
            q: Free-text search (e.g., "RIG 8% 2027")
            cusip: Exact CUSIP lookup
            isin: Exact ISIN lookup
            ticker: Company ticker
            coupon: Coupon rate (%)
            maturity_year: Maturity year
            match_mode: "exact" or "fuzzy"
            limit: Max matches to return
    
        Returns:
            Dictionary with matches and confidence scores
    
        Example:
            # Resolve a bond description
            result = await client.resolve_bond(q="RIG 8% 2027")
            print(result["data"]["matches"][0]["bond"]["cusip"])
        """
        params = {
            "match_mode": match_mode,
            "limit": limit,
        }
    
        if q:
            params["q"] = q
        if cusip:
            params["cusip"] = cusip
        if isin:
            params["isin"] = isin
        if ticker:
            params["ticker"] = ticker
        if coupon is not None:
            params["coupon"] = coupon
        if maturity_year is not None:
            params["maturity_year"] = maturity_year
    
        client = await self._get_client()
        response = await client.get("/bonds/resolve", params=params)
        response.raise_for_status()
        return response.json()
  • LangChain BaseTool implementation for resolve_bond that provides the same identifier detection logic (CUSIP/ISIN/fuzzy text) and delegates to the API wrapper's resolve_bond method.
    class DebtStackResolveBondTool(BaseTool):
        """Resolve bond identifiers - CUSIP, ISIN, or descriptions."""
    
        name: str = "debtstack_resolve_bond"
        description: str = (
            "Resolve a bond identifier to get full details. "
            "Accepts CUSIP, ISIN, or free-text description (e.g., 'RIG 8% 2027'). "
            "Returns matching bonds with confidence scores, useful for identifier lookup "
            "or when you have a partial bond description."
        )
        args_schema: Type[BaseModel] = ResolveBondInput
        api_wrapper: DebtStackAPIWrapper
    
        def _run(
            self,
            query: str,
            run_manager: Optional[CallbackManagerForToolRun] = None,
        ) -> str:
            # Detect if it's a CUSIP (9 chars alphanumeric) or ISIN (12 chars starting with letters)
            query = query.strip()
            params = {}
    
            if len(query) == 9 and query.isalnum():
                params["cusip"] = query
            elif len(query) == 12 and query[:2].isalpha():
                params["isin"] = query
            else:
                params["q"] = query
                params["match_mode"] = "fuzzy"
    
            result = self.api_wrapper.resolve_bond(**params)
            return json.dumps(result, indent=2, default=str)
Behavior3/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. It describes the lookup behavior and accepts partial identifiers, which is helpful. However, it doesn't disclose important behavioral traits like whether this is a read-only operation, what happens with ambiguous matches, error handling, or rate limits. The description adds some context but leaves significant gaps.

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 extremely concise and well-structured in just two sentences. The first sentence states the purpose and usage, while the second provides concrete examples. Every word earns its place with no redundancy or fluff.

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 moderate complexity (single parameter lookup), 100% schema coverage, but no annotations or output schema, the description is adequate but incomplete. It explains what the tool does and when to use it, but lacks information about return values, error conditions, and behavioral constraints that would be important for proper tool invocation.

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?

Schema description coverage is 100%, so the schema already documents the single parameter thoroughly. The description adds minimal value beyond the schema by providing example formats ('RIG 8% 2027' or 'CUSIP 893830AK8'), but doesn't explain parameter semantics beyond what's in the schema description. This meets the baseline for high schema coverage.

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

Purpose5/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 specific verbs ('look up', 'need full details') and resource ('bond'), and distinguishes it from sibling tools like 'search_bonds' by specifying it's for lookup by identifier rather than general searching. It provides concrete examples that reinforce the purpose.

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

Usage Guidelines5/5

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

The description explicitly states when to use this tool ('Use when you have a partial bond identifier and need full details'), providing clear context for its application. It also implies when not to use it (e.g., for general searching where 'search_bonds' would be more appropriate), though it doesn't name alternatives directly.

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/debtstack-ai/debtstack-python'

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