Skip to main content
Glama

get_technical_summary

Analyzes technical indicators like RSI, MACD, and moving averages to generate Buy, Sell, or Neutral trading signals for financial symbols.

Instructions

Performs a technical analysis summary (RSI, MACD, Moving Averages). Returns a 'Buy', 'Sell', or 'Neutral' signal based on aggregated indicators.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
symbolYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The core handler function for the 'get_technical_summary' tool. Downloads 2y historical data using yfinance, computes RSI(14), MACD, SMA50, SMA200. Generates a score-based signal (STRONG BUY to STRONG SELL) with detailed reasons.
    def get_technical_summary(symbol: str) -> str:
        """
        Performs a technical analysis summary (RSI, MACD, Moving Averages).
        Returns a 'Buy', 'Sell', or 'Neutral' signal based on aggregated indicators.
        """
        try:
            # Need enough data for 200 SMA
            df = yf.download(symbol, period="2y", progress=False)
            if df.empty:
                return f"No data found for {symbol}"
                
            # Handle MultiIndex if present
            # yfinance structure: columns are (Price, Ticker)
            if isinstance(df.columns, pd.MultiIndex):
                # If we have a MultiIndex, we want the 'Close' level, and then the specific ticker
                # But usually df['Close'] gives us the Close column(s).
                pass 
                
            close = df['Close']
            if isinstance(close, pd.DataFrame):
                # If multiple tickers or just weird structure, take the first column
                close = close.iloc[:, 0]
                
            # 1. RSI
            rsi = ta.rsi(close, length=14)
            if rsi is None or rsi.empty:
                return f"Not enough data to calculate RSI for {symbol}"
            current_rsi = rsi.iloc[-1]
            
            # 2. MACD
            macd = ta.macd(close)
            if macd is None or macd.empty:
                return f"Not enough data to calculate MACD for {symbol}"
            
            # MACD_12_26_9, MACDh_12_26_9 (hist), MACDs_12_26_9 (signal)
            # Column names depend on pandas_ta version/settings, but usually standard
            macd_line = macd.iloc[-1, 0] # First column is usually MACD line
            macd_signal = macd.iloc[-1, 2] # Third column is usually Signal line
            
            # 3. Moving Averages
            sma_50 = ta.sma(close, length=50)
            sma_200 = ta.sma(close, length=200)
            
            if sma_50 is None or sma_50.empty:
                return "Not enough data for SMA 50"
            if sma_200 is None or sma_200.empty:
                # Fallback if 200 SMA not available (e.g. IPO recently)
                sma_200_val = 0
                has_200 = False
            else:
                sma_200_val = sma_200.iloc[-1]
                has_200 = True
                
            sma_50_val = sma_50.iloc[-1]
            current_price = close.iloc[-1]
            
            # Scoring Logic
            score = 0
            reasons = []
            
            # RSI Logic
            if current_rsi < 30:
                score += 1
                reasons.append(f"RSI is Oversold ({current_rsi:.2f})")
            elif current_rsi > 70:
                score -= 1
                reasons.append(f"RSI is Overbought ({current_rsi:.2f})")
            else:
                reasons.append(f"RSI is Neutral ({current_rsi:.2f})")
                
            # MACD Logic
            if macd_line > macd_signal:
                score += 1
                reasons.append("MACD Bullish Crossover")
            else:
                score -= 1
                reasons.append("MACD Bearish Crossover")
                
            # Trend Logic
            if current_price > sma_50_val:
                score += 1
                reasons.append("Price above 50 SMA (Bullish Trend)")
            else:
                score -= 1
                reasons.append("Price below 50 SMA (Bearish Trend)")
                
            if has_200:
                if current_price > sma_200_val:
                    score += 1
                    reasons.append("Price above 200 SMA (Long-term Bullish)")
                else:
                    score -= 1
                    reasons.append("Price below 200 SMA (Long-term Bearish)")
            else:
                reasons.append("200 SMA not available (Insufficient history)")
                
            # Final Verdict
            if score >= 2:
                signal = "STRONG BUY"
            elif score == 1:
                signal = "BUY"
            elif score == 0:
                signal = "NEUTRAL"
            elif score == -1:
                signal = "SELL"
            else:
                signal = "STRONG SELL"
                
            return (f"Technical Summary for {symbol}:\n"
                    f"Signal: {signal} (Score: {score})\n"
                    f"Price: ${current_price:.2f}\n"
                    f"--------------------------------\n"
                    f"Analysis:\n" + "\n".join([f"- {r}" for r in reasons]))
                    
        except Exception as e:
            return f"Error performing technical analysis: {str(e)}"
  • server.py:390-393 (registration)
    Registers the get_technical_summary tool (along with compute_indicators and rolling_stats) as an MCP tool using the register_tools helper function, which applies @mcp.tool() decorator.
    register_tools(
        [compute_indicators, rolling_stats, get_technical_summary],
        "Feature Engineering"
    )
  • server.py:16-16 (registration)
    Import statement bringing the get_technical_summary function into the MCP server module for registration.
    from tools.feature_engineering import compute_indicators, rolling_stats, get_technical_summary
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions the tool performs analysis and returns a signal, but lacks details on how the analysis is conducted (e.g., timeframes, data sources), whether it's read-only or has side effects, error handling, or performance characteristics like rate limits. This is a significant gap for a tool that likely involves complex calculations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured in two sentences: the first states the action and indicators, the second specifies the output. There's no wasted text, and it's front-loaded with the core purpose. However, it could be slightly more efficient by combining ideas, but it's already very tight.

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 complexity (technical analysis with multiple indicators) and the presence of an output schema (which likely covers return values), the description is minimally adequate. It explains what the tool does and the signal output, but lacks details on behavior, parameters, and usage context. With no annotations and low schema coverage, it should do more to compensate, but the output schema helps mitigate some gaps.

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 input schema has 1 parameter ('symbol') with 0% description coverage, meaning the schema provides no semantic details. The description doesn't add any parameter-specific information beyond what's implied by the tool's purpose (e.g., that 'symbol' likely refers to a financial instrument). It doesn't explain format, constraints, or examples, leaving the parameter minimally documented.

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: performing a technical analysis summary using specific indicators (RSI, MACD, Moving Averages) and returning a trading signal. It specifies the verb ('Performs'), resource ('technical analysis summary'), and outcome ('Buy', 'Sell', or 'Neutral' signal). However, it doesn't explicitly differentiate from sibling tools like 'compute_indicators' or 'run_backtest', which might also involve technical analysis.

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 doesn't mention when to choose this over sibling tools like 'compute_indicators' (which might compute raw indicators) or 'get_symbol_sentiment' (which might provide sentiment-based signals). There's no context on prerequisites, such as needing historical data or specific market conditions.

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/N-lia/MonteWalk'

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