#
tokens: 2742/50000 6/6 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── fetch.py
├── mcp.json
├── package-lock.json
├── package.json
├── README.md
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# MCP Stock Analysis Server by Akshay Bavkar

This is an MCP server that provides access to real-time and historical Indian stock data using the Yahoo Finance API. It allows stock data retrieval to be used as context by local LLMs via Claude Desktop, Cursor, and other MCP-compatible agents.

## Available Features

- **getStockQuote**: Get the current quote for an Indian stock.
- **getHistoricalData**: Get historical data for an Indian stock with custom intervals and periods.
---

## Setup

```bash
npm install mcp-stock-analysis
```

## Usage in Host
Configure your MCP client (e.g., Claude Desktop) to connect to the server:

```JSON
{
  "mcpServers": {
    "mcp-stock-analysis": {
      "command": "npx",
      "args": ["-y", "mcp-stock-analysis"],
    }
  }
}
```

## Tools
### `getStockQuote`
Get the current quote for a stock.

Input:

`symbol`: The stock symbol (e.g., RELIANCE.NS)

Output:
```JSON
{
  "symbol": "RELIANCE.NS",
  "price": 2748.15,
  "name": "Reliance Industries Ltd"
}
```

### `getHistoricalData`
Get historical data for a stock.

Input:

- `symbol`: the stock symbol (e.g., RELIANCE.NS)
- `interval`: the time interval for the data (`daily`, `weekly`, or `monthly`) (optional, default: `daily`)

Output:
```JSON
{
    "date": "2025-03-21T00:00:00+05:30",
    "open": 2735,
    "high": 2750,
    "low": 2725,
    "close": 2748.15,
    "volume": 21780769
}
```

JSON object containing the historical data. The structure of the output depends on the interval parameter.

## Contributing
Contributions are welcome! Please open an issue or pull request.


### License
MIT

```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "mcp-stock-analysis",
  "version": "1.0.0",
  "description": "MCP server for Indian stock market using yfinance",
  "type": "module",
  "main": "src/index.ts",
  "bin": {
    "mcp-stock-analysis": "dist/index.js"
  },
  "scripts": {
    "build": "tsc && chmod +x dist/index.js",
    "prepare": "npm run build",
    "start": "node dist/index.js"
  },
  "files": [
    "dist",
    "fetch.py"
  ],
  "dependencies": {
    "@modelcontextprotocol/sdk": "^0.0.8"
  },
  "devDependencies": {
    "typescript": "^5.3.3"
  }
}
```

--------------------------------------------------------------------------------
/fetch.py:
--------------------------------------------------------------------------------

```python
import sys
import yfinance as yf
import json

mode = sys.argv[1]
symbol = sys.argv[2]

if mode == "quote":
    stock = yf.Ticker(symbol)
    info = stock.info
    result = {
        "symbol": symbol,
        "price": float(info.get("currentPrice") or info.get("regularMarketPrice")),
        "name": info.get("shortName")
    }
    print(json.dumps(result))

elif mode == "history":
    period = sys.argv[3]
    interval = sys.argv[4]
    stock = yf.Ticker(symbol)
    hist = stock.history(period=period, interval=interval).reset_index()
    result = []
    for _, row in hist.iterrows():
        result.append({
            "date": row["Date"].isoformat(),
            "open": float(row["Open"]),
            "high": float(row["High"]),
            "low": float(row["Low"]),
            "close": float(row["Close"]),
            "volume": int(row["Volume"])
        })
    print(json.dumps(result))
```

--------------------------------------------------------------------------------
/mcp.json:
--------------------------------------------------------------------------------

```json
{
  "name": "mcp-stock-analysis",
  "version": "0.1.0",
  "description": "A stock analysis tool that provides real-time and historical stock data",
  "author": "Your Name",
  "tools": [
    {
      "id": "getStockQuote",
      "description": "Get the current price of an Indian stock",
      "parameters": {
        "symbol": {
          "type": "string",
          "description": "The stock symbol (e.g., RELIANCE.NS for Reliance Industries)"
        }
      }
    },
    {
      "id": "getHistoricalData",
      "description": "Fetch historical stock prices",
      "parameters": {
        "symbol": {
          "type": "string",
          "description": "The stock symbol (e.g., RELIANCE.NS for Reliance Industries)"
        },
        "period": {
          "type": "string",
          "description": "Time period (e.g., 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max)",
          "default": "1mo"
        },
        "interval": {
          "type": "string",
          "description": "Data interval (e.g., 1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo)",
          "default": "1d"
        }
      }
    }
  ],
  "command": "npx tsx index.ts",
  "cwd": "."
} 
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
// src/index.ts — MCP Server for Stock Analysis using yfinance (built for dist/ publishing)

import { spawn } from "child_process";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import {
  ListToolsRequestSchema,
  CallToolRequestSchema,
  CallToolRequest,
  CallToolResult,
  Tool
} from "@modelcontextprotocol/sdk/types.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

function runPythonScript(args: string[]): Promise<any> {
  return new Promise((resolve, reject) => {
    const proc = spawn("python3", ["fetch.py", ...args]);
    let output = "";
    let error = "";

    proc.stdout.on("data", (data) => (output += data));
    proc.stderr.on("data", (data) => (error += data));

    proc.on("close", (code) => {
      if (code === 0) {
        try {
          resolve(JSON.parse(output));
        } catch (err) {
          reject(`JSON parse error: ${err}`);
        }
      } else {
        reject(`Python error: ${error}`);
      }
    });
  });
}

const getStockQuoteTool: Tool = {
  name: "getStockQuote",
  description: "Get the current price of an Indian stock",
  inputSchema: {
    type: "object",
    properties: {
      symbol: { type: "string" }
    },
    required: ["symbol"]
  },
  outputSchema: {
    type: "object",
    properties: {
      symbol: { type: "string" },
      price: { type: "number" },
      name: { type: "string" }
    },
    required: ["symbol", "price", "name"]
  }
};

const getHistoricalDataTool: Tool = {
  name: "getHistoricalData",
  description: "Fetch historical stock prices",
  inputSchema: {
    type: "object",
    properties: {
      symbol: { type: "string" },
      period: { type: "string", default: "1mo" },
      interval: { type: "string", default: "1d" }
    },
    required: ["symbol"]
  },
  outputSchema: {
    type: "array",
    items: {
      type: "object",
      properties: {
        date: { type: "string" },
        open: { type: "number" },
        high: { type: "number" },
        low: { type: "number" },
        close: { type: "number" },
        volume: { type: "number" }
      },
      required: ["date", "open", "high", "low", "close", "volume"]
    }
  }
};

const server = new Server(
  {
    name: "mcp-stock-analysis",
    version: "0.1.0",
    description: "A stock analysis tool that provides real-time and historical stock data",
    author: "Gipti Labs",
    capabilities: {
      tools: {
        getStockQuote: {
          description: "Get the current price of an Indian stock",
          parameters: {
            symbol: {
              type: "string",
              description: "The stock symbol (e.g., RELIANCE.NS for Reliance Industries)"
            }
          }
        },
        getHistoricalData: {
          description: "Fetch historical stock prices",
          parameters: {
            symbol: {
              type: "string",
              description: "The stock symbol (e.g., RELIANCE.NS for Reliance Industries)"
            },
            period: {
              type: "string",
              description: "Time period (e.g., 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max)",
              default: "1mo"
            },
            interval: {
              type: "string",
              description: "Data interval (e.g., 1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo)",
              default: "1d"
            }
          }
        }
      }
    }
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [getStockQuoteTool, getHistoricalDataTool],
}));

server.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest): Promise<CallToolResult> => {
  const { name, arguments: args } = request.params;

  if (name === "getStockQuote") {
    try {
      const input = args as { symbol: string };
      const result = await runPythonScript(["quote", input.symbol]);
      return {
        content: [{ type: "text", text: JSON.stringify(result) }]
      };
    } catch (error) {
      return {
        content: [{ type: "text", text: `Error: ${error}` }],
        isError: true
      };
    }
  } else if (name === "getHistoricalData") {
    try {
      const input = args as { symbol: string; period?: string; interval?: string };
      const period = input.period || "1mo";
      const interval = input.interval || "1d";
      const result = await runPythonScript(["history", input.symbol, period, interval]);
      return {
        content: [{ type: "text", text: JSON.stringify(result) }]
      };
    } catch (error) {
      return {
        content: [{ type: "text", text: `Error: ${error}` }],
        isError: true
      };
    }
  } else {
    return {
      content: [{ type: "text", text: "Unknown tool" }],
      isError: true
    };
  }
});

const transport = new StdioServerTransport();
await server.connect(transport);
console.error("✅ MCP Server started and ready for requests...");

```