The first MCP Server I ever installed

Here's the tutorial that got me started. The tutorial is great, but I found that I had to take different steps to get everything to work. So you could try following the original instructions, and if they don't work, then you can try the steps I've documented here.

Disclaimer: I am not good with python (yet), so I had to dink around a lot to get it to work.

Here the steps (I did this on Windows)...

First, make sure you have at least version 3.10 of Python installed because some of the packages we use will not work with older versions.

You'll also need to install the uv package manager. Depending on how you installed Python, there seems to be different ways to install it. I ran this command:

py -m pip install uv

But here are the install docs on the uv site

Setting Up the Project

Use uv to create a project (in a folder called mcp-stock-analyst):

uv init mcp-stock-analyst

Then cd into the folder:

cd mcp-stock-analyst

Create a virtual envirnoment for the project:

uv venv

Activate the virtual environment:

.venv\Scripts\activate

Note that (mcp-stock-analyst) will appear at the beginning of the terminal command line, which indicates that you are working in the project's virtual environment.

Side note: when you done working in the virtual environment, enter deactivate to go back to your original terminal.

Install the packages we'll be using:

uv add "mcp[cli]" yfinance

Create a file named stock_price_server.py in the current folder (not inside the my-env folder), and add this code to it:

from mcp.server.fastmcp import FastMCP
import yfinance as yf

# Create an MCP server with a custom name
mcp = FastMCP("Stock Price Server")

@mcp.tool()
def get_stock_price(symbol: str) -> float:
    """
    Retrieve the current stock price for the given ticker symbol.
    Returns the latest closing price as a float.
    """
    try:
        ticker = yf.Ticker(symbol)
        # Get today's historical data; may return empty if market is closed or symbol is invalid.
        data = ticker.history(period="1d")
        if not data.empty:
            # Use the last closing price from today's data
            price = data['Close'].iloc[-1]
            return float(price)
        else:
            # As a fallback, try using the regular market price from the ticker info
            info = ticker.info
            price = info.get("regularMarketPrice", None)
            if price is not None:
                return float(price)
            else:
                return -1.0  # Indicate failure
    except Exception:
        # Return -1.0 to indicate an error occurred when fetching the stock price
        return -1.0

@mcp.resource("stock://{symbol}")
def stock_resource(symbol: str) -> str:
    """
    Expose stock price data as a resource.
    Returns a formatted string with the current stock price for the given symbol.
    """
    price = get_stock_price(symbol)
    if price < 0:
        return f"Error: Could not retrieve price for symbol '{symbol}'."
    return f"The current price of '{symbol}' is ${price:.2f}."

@mcp.tool()
def get_stock_history(symbol: str, period: str = "1mo") -> str:
    """
    Retrieve historical data for a stock given a ticker symbol and a period.
    Returns the historical data as a CSV formatted string.
    
    Parameters:
        symbol: The stock ticker symbol.
        period: The period over which to retrieve historical data (e.g., '1mo', '3mo', '1y').
    """
    try:
        ticker = yf.Ticker(symbol)
        data = ticker.history(period=period)
        if data.empty:
            return f"No historical data found for symbol '{symbol}' with period '{period}'."
        # Convert the DataFrame to a CSV formatted string
        csv_data = data.to_csv()
        return csv_data
    except Exception as e:
        return f"Error fetching historical data: {str(e)}"

@mcp.tool()
def compare_stocks(symbol1: str, symbol2: str) -> str:
    """
    Compare the current stock prices of two ticker symbols.
    Returns a formatted message comparing the two stock prices.
    
    Parameters:
        symbol1: The first stock ticker symbol.
        symbol2: The second stock ticker symbol.
    """
    price1 = get_stock_price(symbol1)
    price2 = get_stock_price(symbol2)
    if price1 < 0 or price2 < 0:
        return f"Error: Could not retrieve data for comparison of '{symbol1}' and '{symbol2}'."
    if price1 > price2:
        result = f"{symbol1} (${price1:.2f}) is higher than {symbol2} (${price2:.2f})."
    elif price1 < price2:
        result = f"{symbol1} (${price1:.2f}) is lower than {symbol2} (${price2:.2f})."
    else:
        result = f"Both {symbol1} and {symbol2} have the same price (${price1:.2f})."
    return result

if __name__ == "__main__":
    mcp.run()

Testing with MCP Inspector

Run this command from the virtual environment terminal:

mcp dev stock_price_server.py

This will launch the mcp inspector web app that you can use to test your program. The port number it used was 6274, so go to: ** http://127.0.0.1:6274**.

Press the Connect button.

Note that the first time I launched the inspector, I was able to see it in the browser, but it could not connect to it. So I killed the inspector in the terminal and re ran the command to start it. Then it worked.

Click on the Tools tab, then click List Tools, this will display the tools that are created in the python program.

Click the get_stock_price tool, then enter a stock ticker symbol in the symbol textbox and click Run tool. It will return the price.

You can continue to experiment with the other tools in the same way.

Installing the MCP Server into Claude Desktop

The article says to run this command to install the tool into Claude Desktop, but it did not work for me:

mcp install stock_price_server.py --name "Stock Price Server"

So I had to manually install the server by editing the claude_desktop_config.json file, which is located at C:\Users\YOURHOMEDIRECTORY\AppData\Roaming\Claude

{
  "mcpServers": {
    "Stock Price Server": {
      "command": "C:\\Users\\myhomedir\\Desktop\\MyProjects\\mcp\\mcp-stock-analyst\\.venv\\Scripts\\python.exe",
      "args": [
        "C:\\Users\\myhomedir\\Desktop\\MyProjects\\mcp\\mcp-stock-analyst\\stock_price_server.py"
      ]
    }
  }
}

Note that you will have to adjust the paths for your environment.

Then I had to use Task Manager to kill the Claude app and restart it. After that, the 3 new tools showed up!

To make use of the MCP server tools, enter a prompt into Claude like this: 'Could you please compare the prices of Microsoft and Tesla stocks?' Claude will detect that the tools are relevant to the prompt and show an pop up that asks if it may use them.

Here's another prompt, which will invoke get_stock_history tool: "Could you please provide the historical data for Tesla over the past month?"