Metadata-Version: 2.5
Name: dse-mcp
Version: 0.1.0
Summary: Dhaka Stock Exchange MCP server - live quotes, price history, fundamentals, market depth, news, technical indicators, screening, and a buy/sell analysis skill.
Project-URL: Homepage, https://github.com/ofsazib/dse-mcp
Project-URL: Repository, https://github.com/ofsazib/dse-mcp
Project-URL: Issues, https://github.com/ofsazib/dse-mcp/issues
Project-URL: Changelog, https://github.com/ofsazib/dse-mcp/blob/main/CHANGELOG.md
Author: Omar Faruk Sazib
License-Expression: MIT
License-File: LICENSE
Keywords: bangladesh,dhaka-stock-exchange,dse,finance,mcp,mcp-server,stock-market,trading
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.12
Requires-Dist: beautifulsoup4>=4.15.0
Requires-Dist: fastmcp>=4.0.3
Requires-Dist: httpx>=0.28.1
Requires-Dist: lxml>=6.1.3
Requires-Dist: pandas-ta-classic>=0.6.52
Requires-Dist: pandas>=3.0.5
Requires-Dist: pydantic-settings>=2.15.0
Requires-Dist: tenacity>=9.1.4
Requires-Dist: truststore>=0.10.4
Description-Content-Type: text/markdown

# dse-mcp

[![PyPI](https://img.shields.io/pypi/v/dse-mcp)](https://pypi.org/project/dse-mcp/)
[![Python](https://img.shields.io/pypi/pyversions/dse-mcp)](https://pypi.org/project/dse-mcp/)
[![CI](https://github.com/ofsazib/dse-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/ofsazib/dse-mcp/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![MCP](https://img.shields.io/badge/MCP-server-blue)](https://modelcontextprotocol.io)

A production-grade **Model Context Protocol (MCP) server for the Dhaka Stock
Exchange (DSE)** — live quotes, price history, fundamentals, order-book depth,
news, technical indicators, screening — plus a bundled **`dse-analysis` skill**
that teaches your agent a disciplined buy/sell workflow on top of those tools.

Data is scraped from [dsebd.org](https://www.dsebd.org) (DSE's official site) with
all of its production quirks handled: incomplete TLS chains, `--` placeholders,
comma-grouped numbers, invisible layout tables, market-hours-aware caching, and a
mirror-domain fallback. **Informational only — not investment advice. Not
affiliated with DSE.**

## Install

Requires Python 3.12+ (or just `uv`/`pipx`, which manage Python for you).

```bash
# Register with Claude Code (recommended)
claude mcp add dse -s user -- uvx dse-mcp
```

<details>
<summary>Other clients</summary>

**Claude Desktop** (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "dse": { "command": "uvx", "args": ["dse-mcp"] }
  }
}
```

**Cursor** (`~/.cursor/mcp.json`): same JSON shape as Claude Desktop.

**pipx:**

```bash
pipx install dse-mcp
# then register with the command "dse-mcp"
```

**Docker:**

```bash
docker run -i --rm ghcr.io/ofsazib/dse-mcp
```

</details>

## The dse-analysis skill

The repo ships an agent skill that turns these tools into a repeatable
buy/sell analysis workflow (market context → fundamentals → technicals → news →
verdict with confidence + risks):

```bash
# from a git clone of this repo
./scripts/install_skill.sh          # installs to ~/.claude, ~/.agents, ~/.zcode
```

Or copy `skills/dse-analysis/` into your client's skills directory manually.

## Tools (16)

Every response carries `market_status` (live/closed), `data_freshness`
(live/snapshot/stale), and `data_as_of` — so closed-market data is never mistaken
for live prices.

### Market
| Tool | Description |
|---|---|
| `market_status` | Live/closed, session hours, Dhaka time, next session |
| `market_summary` | DSEX/DS30/DSES + changes, totals for the latest session |
| `get_index_history(days)` | Daily index history (rolling one-year archive) |
| `top_movers(category)` | `gainers` \| `losers` \| `most_active` \| `turnover` |
| `sector_performance` | Advancing/declining + avg change per sector |

### Stock
| Tool | Description |
|---|---|
| `search_symbols(query)` | Fuzzy search over 636 bundled instruments (22 sectors) |
| `get_quote(symbol)` | LTP, day range, close, change, trades, value, volume |
| `get_price_history(symbol, start, end, days)` | Day-end OHLCV, oldest-first |
| `get_company_profile(symbol)` | Capital structure, listing year, 52w range, EPS block |
| `get_fundamentals(symbol)` | Analysis-ready: EPS, P/E, dividends, reserves, 52w |
| `get_market_depth(symbol)` | Live bid/ask levels + session stats |
| `get_news(symbol, days, limit)` | Company or market-wide news/disclosures |
| `get_pe_ratios()` | P/E table (interim/audited/trailing) for all instruments |

### Analysis & screening
| Tool | Description |
|---|---|
| `compute_indicators(symbol, ...)` | SMA50/200, RSI(14), MACD, Bollinger |
| `technical_summary(symbol)` | Trend, support/resistance, outlook + reasons |
| `screen_stocks(sector, pe_max, price_range, volume_min)` | Filter the live board |

## Trading-hours aware caching

- Market **live** (Sun–Thu 10:00–14:50 Asia/Dhaka): data cached 30s (depth is
  always fetched fresh).
- Market **closed**: the last session's snapshot is cached ~1h and **persisted to
  `~/.cache/dse-mcp/`**, so a restart still serves the last session (labeled
  `snapshot`).
- DSE unreachable: the persisted snapshot is served labeled `stale`.

## Configuration (optional)

All via environment variables with the `DSE_MCP_` prefix — see
[.env.example](.env.example). Useful ones:

| Variable | Default | Purpose |
|---|---|---|
| `DSE_MCP_RATE_LIMIT` | `5.0` | Outbound requests/second (token bucket) |
| `DSE_MCP_CACHE_TTL_OPEN` | `30` | Seconds, while the market is live |
| `DSE_MCP_CACHE_DIR` | `~/.cache/dse-mcp` | Snapshot persistence |
| `DSE_MCP_LOG_LEVEL` | `WARNING` | Logs go to stderr (never stdout — MCP) |

## Troubleshooting

- **`[SSL: CERTIFICATE_VERIFY_FAILED]`** — dsebd.org serves an incomplete TLS
  chain. dse-mcp uses the OS trust store (`truststore`), which handles it; do not
  replace it with `verify=False`.
- **Empty depth / quotes look frozen** — the market is closed (or a holiday).
  Check `market_status` and the response's `data_as_of`.
- **`DGEN: null`** — the DGEN index is retired from DSE's live pages; null is the
  honest value.

## Development

```bash
git clone https://github.com/ofsazib/dse-mcp && cd dse-mcp
uv sync                                   # Python 3.12 via uv
uv run pytest                             # 44 offline tests (recorded fixtures)
uv run ruff check .
uv run dse-mcp                            # run the server locally
npx @modelcontextprotocol/inspector uv run dse-mcp   # visual debugging
```

Re-record fixtures when dsebd.org markup changes: `uv run python scripts/record_fixtures.py`.
Rebuild the instrument bundle: `uv run python scripts/build_instruments.py`.
See [AGENTS.md](AGENTS.md) for architecture and [CONTRIBUTING.md](CONTRIBUTING.md)
to contribute.

## Legal

- Data source: [dsebd.org](https://www.dsebd.org) (Dhaka Stock Exchange). This
  project is an independent, unaffiliated open-source client; data remains the
  property of DSE.
- Nothing here is investment advice. DSE securities can be illiquid and subject to
  circuit breakers; verify everything against primary sources before acting.

## License

[MIT](LICENSE) © Omar Faruk Sazib
