Colombo Stock Exchange market data and analytics exposed through Model Context Protocol (MCP).
- Securities directory with caching
- Stock chart OHLCV fetch (daily/weekly/monthly)
- Market overview, top movers, sector screens
- Company profile lookup
- Index history (ASPI, S&P SL20) via TradingView
- Technical indicators (RSI, EMA, SMA, MACD, Bollinger, ATR, Stochastic, OBV, VWAP, Volume)
- Auto token retrieval and refresh using CSE username/password (optional)
core/ domain models and interfaces
infrastructure/ CSE and TradingView clients, token provider
services/ indicator and market processing services
mcp_server/ MCP server entry point and tool definitions
tests/ unit and integration tests
utils/ shared utilities
python -m venv .venvWindows PowerShell:
.\.venv\Scripts\Activate.ps1Install dependencies:
pip install -r requirements.txt- Copy
.env.exampleto.env. - Choose authentication mode.
Set:
CSE_AUTH_MODE=manual
CSE_ACCESS_TOKEN=your_token_hereGet CSE_ACCESS_TOKEN from CSE browser cookies after login (accessToken cookie).
Set:
CSE_AUTH_MODE=auto
CSE_USERNAME=your_username
CSE_PASSWORD=your_password
CSE_TOKEN_REFRESH_MARGIN_SECONDS=300
CSE_TOKEN_HTTP_TIMEOUT_SECONDS=30When CSE_AUTH_MODE=auto:
CSEClientinitializesCSEOIDCTokenProvider.- Provider performs OIDC + PKCE flow against CSE identity endpoints.
- Access token is returned and stored in-memory.
- Before token expiry margin, token is refreshed proactively.
- For protected chart requests, if first request fails, client force-refreshes token and retries once.
Note: retry logic is not tied to a specific status code (for example 417).
The server supports two transports:
stdio(default): best for desktop MCP clients that spawn the process.sse: best for remote/network MCP clients.
python -m mcp_server.server --transport stdiopython -m mcp_server.server --transport sse --port 8000SSE endpoint:
http://localhost:8000/sse
- Start server with
--transport sse. - Run inspector:
npx @anthropic-ai/mcp-inspector- In Inspector: transport
SSE, URLhttp://localhost:8000/sse.
Add in ~/.gemini/settings.json:
{
"mcpServers": {
"cse-mcp": {
"url": "http://localhost:8000/sse"
}
}
}Configure the client to start:
python -m mcp_server.server --transport stdioTotal tools: 24
| Tool | Description |
|---|---|
list_all_securities |
List all CSE securities (cached). |
get_security_id_by_symbol |
Get security ID for a symbol. |
list_sectors |
List available sectors/categories. |
list_stocks_by_sector |
List stocks inside a sector. |
get_company_profile |
Get company profile details. |
get_index_history |
Get historical index OHLC for ASPI or SP_SL20. |
list_supported_indices |
List supported index keys and metadata. |
get_market_overview |
Market-wide overview (indices, breadth, turnover, foreign activity). |
get_top_movers |
Top gainers/losers/volume/turnover movers. |
screen_stocks |
Filter/sort stocks using current-day snapshot fields. |
weekly_market_scan |
Bulk weekly scan across all stocks (see below). |
get_chart_data |
Fetch symbol OHLCV chart data. |
get_market_summary |
Full technical summary with all indicators. |
calculate_rsi |
Calculate RSI. |
calculate_ema |
Calculate EMA. |
calculate_sma |
Calculate SMA. |
calculate_macd |
Calculate MACD. |
calculate_bollinger_bands |
Calculate Bollinger Bands. |
calculate_atr |
Calculate ATR. |
calculate_stochastic |
Calculate Stochastic oscillator. |
calculate_obv |
Calculate OBV. |
calculate_vwap |
Calculate VWAP. |
calculate_volume |
Calculate volume analysis metrics. |
list_symbols |
List all available symbols only. |
Scans all CSE-listed stocks for weekly performance, volume anomalies, and potential trading opportunities. Returns a consolidated report in a single call instead of checking stocks individually.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
timeframe |
string | "1w" |
"1w" (5 days), "2w" (10 days), or "1m" (22 days) |
min_market_cap |
number | null |
Filter out stocks below this market cap (LKR) |
min_avg_daily_volume |
integer | 1000 |
Minimum average daily volume over the period |
volume_spike_threshold |
number | 2.0 |
Flag stocks where volume exceeds this multiple of their average |
top_n |
integer | 15 |
Results per category (max 50) |
include_sectors |
boolean | true |
Include sector tags and sector summary |
Output categories:
| Category | What it returns |
|---|---|
scan_metadata |
Scan date, timeframe, period dates, stock counts, filters applied |
market_context |
ASPI and S&P SL20 period change %, current values, turnover |
top_gainers |
Top N stocks by weekly price change (descending) |
top_losers |
Top N stocks by weekly price change (ascending) |
volume_anomalies |
Stocks where volume exceeds threshold vs 20-day average, tagged with price direction and signal note |
whale_dump_candidates |
Stocks with >= 5% price drop on below-average volume — possible single large seller, contrarian opportunity candidates |
sector_summary |
Average weekly change per sector, top/worst performer, sector vs ASPI comparison |
Notes:
- Requires auth (chart data endpoint). Uses concurrent fetching (~20 parallel requests) for performance.
- Typical scan time: 15-30 seconds for ~250 qualifying stocks.
- Volume baseline is computed from 20 trading days prior to the scan period.
- Broad market indices (e.g. ALL SHARE PRICE INDEX) are excluded from sector summary.
Run all tests:
pytestRun integration token test only:
pytest -q tests/test_token_provider_integration.py| Variable | Description | Default |
|---|---|---|
CSE_BASE_URL |
CSE base URL for API calls | https://www.cse.lk |
CSE_AUTH_MODE |
manual or auto |
manual |
CSE_ACCESS_TOKEN |
Manual access token | required in manual mode |
CSE_USERNAME |
CSE username for auto mode | - |
CSE_PASSWORD |
CSE password for auto mode | - |
CSE_TOKEN_REFRESH_MARGIN_SECONDS |
Refresh before expiry by this many seconds | 300 |
CSE_TOKEN_HTTP_TIMEOUT_SECONDS |
Timeout for token retrieval calls | 30 |
MCP_TRANSPORT |
Transport mode (stdio or sse) |
stdio |
MCP_PORT |
SSE port | 8000 |
SSL_CERTFILE |
SSL cert path for HTTPS SSE | unset |
SSL_KEYFILE |
SSL key path for HTTPS SSE | unset |
ruff check .
mypy .
pytestMIT