Skip to main content
Glama
burhank928

PSX MCP Server

by burhank928
README.md
# PSX MCP Server (Modified for Remote/Cloud Deployment)

Based on [PSX-MCP-Server](https://github.com/ahad-raza24/PSX-MCP-Server) by Ahad Raza, modified with HTTP transport, API key authentication, and cloud deployment support. See [LICENSE](LICENSE) for the original MIT license.

A Model Context Protocol (MCP) server that provides tools to scrape and access Pakistan Stock Exchange (PSX) market data.

## What's Changed From the Original

This fork modifies the original stdio-only local server to also run as a
remotely-hosted HTTP service, so it can be deployed to a cloud platform and
connected to Claude (or any other MCP client) from anywhere, not just from a
process running on the same machine.

| File | Change |
|---|---|
| `src/psx_mcp/server.py` | Added an `ApiKeyMiddleware` class that checks every incoming MCP request for a valid `X-API-Key` header (read from the `PSX_MCP_API_KEY` environment variable). Added an unauthenticated `/health` route for hosting-provider uptime checks. Added a `streamable-http` transport branch to the `__main__` block. |
| `scripts/start_server.py` | **Bug fix:** this script had its own separate `mcp.run()` call with no transport arguments, which was silently overriding the HTTP transport settings added in `server.py` and defaulting back to `stdio`. Fixed to read `PORT` from the environment and launch with `transport="streamable-http", host="0.0.0.0"`. |
| `requirements.txt` | Added `starlette>=0.37.0` explicitly, since `server.py` now imports it directly for the `/health` route (previously only pulled in indirectly via `fastmcp`). |
| `Dockerfile` | Changed exposed port from `3000` to `8080`/dynamic `PORT` to match cloud platform conventions (Render, Cloud Run, etc. inject their own `PORT` value at runtime). |
| `LICENSE` | Added — the original repo declared MIT in `pyproject.toml` but did not include the license file itself. |

All 12 original tools (`market_data`, `intraday`, `history`, `sector`,
`gainers`, `losers`, `date_range`, `time_range`, `ohlcv`, `multi_ohlcv`,
`price_at_time`, `volume_analysis`) are unchanged and work identically to the
original — only the transport layer and authentication were added.

### Running remotely vs. locally

- **Original / local use (stdio):** still works exactly as documented below,
  for use with a local MCP client like Gemini CLI or Claude Desktop's local
  config.
- **New / remote use (HTTP):** set `PSX_MCP_API_KEY` and optionally `PORT`,
  then run `python scripts/start_server.py` — the server now listens on
  `http://0.0.0.0:$PORT/mcp` and requires the `X-API-Key` header on every
  request. This is what allows deployment to Render, Cloud Run, or any other
  container host.

---

## 🎥 Demo Video

![PSX MCP Server Demo](assets/PSX_MCPServer%20Demo%20-%20Ahad.mov)

*Watch this demo to see the PSX MCP Server in action with real-time market data!*

## Features

This MCP server provides **12 powerful tools** for comprehensive PSX data access:

### 📊 Basic Tools (Simple & Intuitive)
1. **market_data()** - Get current market data for all 460+ stocks listed on PSX
2. **intraday(symbol)** - Get intraday time series data for a specific stock
3. **history(symbol)** - Get end-of-day historical data for a specific stock (past 5 years)
4. **sector(sector)** - Search stocks by sector
5. **gainers(limit)** - Get top gaining stocks
6. **losers(limit)** - Get top losing stocks

### 🎯 Advanced Tools (Clean & Powerful)
7. **date_range(symbol, start, end)** - Get EOD data for specific date range (YYYY-MM-DD format)
8. **time_range(symbol, start, end)** - Get intraday data for specific time range (YYYY-MM-DD HH:MM:SS format)
9. **ohlcv(symbol)** - Get OHLCV (Open, High, Low, Close, Volume) data for specific stock
10. **multi_ohlcv(symbols)** - Get OHLCV data for multiple stocks (comma-separated symbols)
11. **price_at_time(symbol, timestamp)** - Get closest price data at specific Unix timestamp
12. **volume_analysis(symbol, days)** - Analyze volume patterns over specified number of days

## Installation

### Option 1: Direct Installation (local, stdio)
1. Install dependencies:
```bash
pip install -r requirements.txt
```

2. Configure Gemini CLI (copy and customize the template):
```bash
cp gemini_config.template.json gemini_config.json
# Edit gemini_config.json with your project path
```

3. Run the MCP server:
```bash
python scripts/start_server.py
```

### Option 2: Development Installation
1. Install with development tools:
```bash
make setup
# or
pip install -e ".[dev]"
```

2. Run with Makefile:
```bash
make run-server
```

### Option 3: Docker (local or cloud deployment)
1. Build the Docker image:
```bash
docker build -t psx-mcp-server .
```

2. Run the container (requires `PSX_MCP_API_KEY` to be set — see below):
```bash
docker run -p 8000:8000 -e PSX_MCP_API_KEY=your-key-here -e PORT=8000 psx-mcp-server
```

### Option 4: Remote HTTP mode (new)
Set the required environment variable and run directly:
```bash
export PSX_MCP_API_KEY=your-long-random-key-here
export PORT=8000   # optional, defaults to 8000
python scripts/start_server.py
```
The server will be reachable at `http://localhost:8000/mcp` (or your deployed
URL) and requires the `X-API-Key` header on every MCP request. An
unauthenticated health check is available at `/health`.

## Configuration

### Template Files
The project includes template configuration files for easy setup:

- **`gemini_config.template.json`** - Simple Gemini CLI configuration template
- **`mcp_config.template.json`** - Advanced MCP configuration template with additional settings

### Quick Setup (local stdio)
1. Copy the template file:
```bash
cp gemini_config.template.json gemini_config.json
```

2. Edit the configuration with your project path:
```json
{
  "mcpServers": {
    "psx-scraper": {
      "command": "python",
      "args": ["/your/actual/path/scripts/start_server.py"],
      "env": {
        "PYTHONPATH": "/your/actual/path/src"
      }
    }
  }
}
```

3. Connect Gemini CLI:
```bash
gemini --config gemini_config.json
```

### Environment Variables (remote/HTTP mode)

| Variable | Required | Description |
|---|---|---|
| `PSX_MCP_API_KEY` | Yes, for HTTP mode | Shared secret required in the `X-API-Key` header on every MCP request. Set this as a secret in your hosting provider's dashboard — never commit it to the repo. |
| `PORT` | No | Port to bind to. Most hosting platforms (Render, Cloud Run) set this automatically. Defaults to `8000`. |

## Development

### Available Commands
```bash
make help          # Show all available commands
make test          # Run test suite
make lint          # Run linting checks
make format        # Format code with black
make run-demo      # Run demonstrations
make clean         # Clean build artifacts
```

## Data Sources

The server scrapes data from the following PSX endpoints:

- `https://dps.psx.com.pk/market-watch` - Market watch data
- `https://dps.psx.com.pk/timeseries/int/{SYMBOL}` - Intraday data
- `https://dps.psx.com.pk/timeseries/eod/{SYMBOL}` - End-of-day data

## Usage

The server can be used with any MCP client, such as Gemini CLI, Claude
Desktop, or claude.ai (via a custom connector, in HTTP mode). The tools
return JSON data that can be processed by the client.

### Example Queries

**Basic Data (Super Simple):**
- "Show me market data" → `market_data()`
- "Get HBL intraday data" → `intraday('HBL')`
- "Show HBL history" → `history('HBL')`
- "Find banking stocks" → `sector('Banking')`
- "Top 5 gainers" → `gainers(5)`

**Advanced Filtering (Clean & Intuitive):**
- "HBL data from Jan to Feb" → `date_range('HBL', '2024-01-01', '2024-02-01')`
- "HBL intraday 9AM to 3PM" → `time_range('HBL', '2024-10-04 09:00:00', '2024-10-04 15:00:00')`
- "HBL OHLCV data" → `ohlcv('HBL')`
- "OHLCV for HBL,OGDC" → `multi_ohlcv('HBL,OGDC')`
- "HBL volume analysis" → `volume_analysis('HBL', 30)`

### Example Stock Symbols

- HBL - Habib Bank Limited
- OGDC - Oil and Gas Development Company
- PTC - Pakistan Telecommunication Company
- LUCK - Lucky Cement
- ENGRO - Engro Corporation

## Data Models

### Stock Data
- Symbol, Sector, Listed In
- LDCP, Open, High, Low, Current prices
- Change amount and percentage
- Volume traded

### Time Series Data
- Unix timestamp
- Price/Close price
- Volume
- Open price (for EOD data)

## Error Handling

All tools include proper error handling and return error messages in JSON format if requests fail.

## Notes on Data Reliability

This server scrapes PSX's public website (`dps.psx.com.pk`) directly — it is
not an official PSX API. It provides price/volume/OHLCV data only, not
fundamentals (EPS, profit, dividends, corporate actions). Verify any figure
that will inform an actual trading decision against PSX's primary filings
before acting on it.