@dwlf/mcp-server 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +160 -0
- package/dist/client.d.ts +10 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +87 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/symbols.d.ts +4 -0
- package/dist/resources/symbols.d.ts.map +1 -0
- package/dist/resources/symbols.js +15 -0
- package/dist/resources/symbols.js.map +1 -0
- package/dist/tools/academy.d.ts +3 -0
- package/dist/tools/academy.d.ts.map +1 -0
- package/dist/tools/academy.js +130 -0
- package/dist/tools/academy.js.map +1 -0
- package/dist/tools/ai-summary.d.ts +4 -0
- package/dist/tools/ai-summary.d.ts.map +1 -0
- package/dist/tools/ai-summary.js +53 -0
- package/dist/tools/ai-summary.js.map +1 -0
- package/dist/tools/backtests.d.ts +4 -0
- package/dist/tools/backtests.d.ts.map +1 -0
- package/dist/tools/backtests.js +84 -0
- package/dist/tools/backtests.js.map +1 -0
- package/dist/tools/custom-events.d.ts +4 -0
- package/dist/tools/custom-events.d.ts.map +1 -0
- package/dist/tools/custom-events.js +72 -0
- package/dist/tools/custom-events.js.map +1 -0
- package/dist/tools/indicators.d.ts +4 -0
- package/dist/tools/indicators.d.ts.map +1 -0
- package/dist/tools/indicators.js +61 -0
- package/dist/tools/indicators.js.map +1 -0
- package/dist/tools/market-data.d.ts +4 -0
- package/dist/tools/market-data.d.ts.map +1 -0
- package/dist/tools/market-data.js +120 -0
- package/dist/tools/market-data.js.map +1 -0
- package/dist/tools/portfolio.d.ts +4 -0
- package/dist/tools/portfolio.d.ts.map +1 -0
- package/dist/tools/portfolio.js +70 -0
- package/dist/tools/portfolio.js.map +1 -0
- package/dist/tools/signals.d.ts +4 -0
- package/dist/tools/signals.d.ts.map +1 -0
- package/dist/tools/signals.js +69 -0
- package/dist/tools/signals.js.map +1 -0
- package/dist/tools/strategies.d.ts +4 -0
- package/dist/tools/strategies.d.ts.map +1 -0
- package/dist/tools/strategies.js +118 -0
- package/dist/tools/strategies.js.map +1 -0
- package/dist/tools/symbol-activations.d.ts +4 -0
- package/dist/tools/symbol-activations.d.ts.map +1 -0
- package/dist/tools/symbol-activations.js +191 -0
- package/dist/tools/symbol-activations.js.map +1 -0
- package/dist/tools/trades.d.ts +4 -0
- package/dist/tools/trades.d.ts.map +1 -0
- package/dist/tools/trades.js +180 -0
- package/dist/tools/trades.js.map +1 -0
- package/dist/tools/watchlist.d.ts +4 -0
- package/dist/tools/watchlist.d.ts.map +1 -0
- package/dist/tools/watchlist.js +50 -0
- package/dist/tools/watchlist.js.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DWLF / Andy Williams
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# @dwlf/mcp-server
|
|
2
|
+
|
|
3
|
+
MCP server for the [DWLF](https://www.dwlf.co.uk) market analysis platform. 45+ tools that turn market noise into semantic data AI agents can reason about — candles, indicators, support/resistance, events, strategies, backtests, portfolios, trade journals, symbol activations, and more.
|
|
4
|
+
|
|
5
|
+
Works with Claude Desktop, Cursor, VS Code, and any MCP-compatible client.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
The fastest way to get running — no cloning needed:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx -y @dwlf/mcp-server
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or install globally:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g @dwlf/mcp-server
|
|
19
|
+
dwlf-mcp-server
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
You'll need a `DWLF_API_KEY` environment variable. See [Getting an API Key](#getting-an-api-key) below.
|
|
23
|
+
|
|
24
|
+
## Claude Desktop
|
|
25
|
+
|
|
26
|
+
Add to your `claude_desktop_config.json`:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"mcpServers": {
|
|
31
|
+
"dwlf": {
|
|
32
|
+
"command": "npx",
|
|
33
|
+
"args": ["-y", "@dwlf/mcp-server"],
|
|
34
|
+
"env": {
|
|
35
|
+
"DWLF_API_KEY": "dwlf_sk_your_key_here"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Cursor
|
|
43
|
+
|
|
44
|
+
Add to `.cursor/mcp.json`:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"dwlf": {
|
|
50
|
+
"command": "npx",
|
|
51
|
+
"args": ["-y", "@dwlf/mcp-server"],
|
|
52
|
+
"env": {
|
|
53
|
+
"DWLF_API_KEY": "dwlf_sk_your_key_here"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## VS Code
|
|
61
|
+
|
|
62
|
+
Add to `.vscode/mcp.json`:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"mcp": {
|
|
67
|
+
"servers": {
|
|
68
|
+
"dwlf": {
|
|
69
|
+
"command": "npx",
|
|
70
|
+
"args": ["-y", "@dwlf/mcp-server"],
|
|
71
|
+
"env": {
|
|
72
|
+
"DWLF_API_KEY": "dwlf_sk_your_key_here"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Getting an API Key
|
|
81
|
+
|
|
82
|
+
1. Sign up at [dwlf.co.uk](https://www.dwlf.co.uk)
|
|
83
|
+
2. Go to **Settings → API Keys**
|
|
84
|
+
3. Create a new key — it starts with `dwlf_sk_`
|
|
85
|
+
4. Set it as `DWLF_API_KEY` in your MCP client config
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
| Variable | Required | Default | Description |
|
|
90
|
+
|----------|----------|---------|-------------|
|
|
91
|
+
| `DWLF_API_KEY` | Yes | — | Your DWLF API key (`dwlf_sk_...`) |
|
|
92
|
+
| `DWLF_API_URL` | No | `https://api.dwlf.co.uk` | API base URL |
|
|
93
|
+
|
|
94
|
+
## Tools
|
|
95
|
+
|
|
96
|
+
### Market Data
|
|
97
|
+
Get OHLCV candles, list symbols, support/resistance levels, and indicator events (crossovers, breakouts, divergences, candlestick patterns).
|
|
98
|
+
|
|
99
|
+
### Technical Indicators
|
|
100
|
+
RSI, MACD, EMA, Bollinger Bands, DSS, Ichimoku, trendlines, and more.
|
|
101
|
+
|
|
102
|
+
### Trade Signals
|
|
103
|
+
Active signals, signal history with P&L, and performance stats (win rate, avg return).
|
|
104
|
+
|
|
105
|
+
### Strategies
|
|
106
|
+
Create, update, compile, and browse visual trading strategies. List public community strategies.
|
|
107
|
+
|
|
108
|
+
### Backtesting
|
|
109
|
+
Run backtests (async), get results with Sharpe ratios, and aggregate performance summaries.
|
|
110
|
+
|
|
111
|
+
### Portfolio & Trade Journal
|
|
112
|
+
Portfolio holdings with P&L, historical snapshots, trade logging, notes, and plan templates.
|
|
113
|
+
|
|
114
|
+
### Symbol Activations
|
|
115
|
+
Activate symbols for event detection and strategy signal generation. Manage which symbols are actively monitored.
|
|
116
|
+
|
|
117
|
+
### Custom Events
|
|
118
|
+
Create custom indicator-based triggers (e.g. "DSS exits oversold with bullish cross").
|
|
119
|
+
|
|
120
|
+
### AI Summaries
|
|
121
|
+
Full account dashboard, single-symbol briefs, and strategy performance overviews — pre-aggregated for AI consumption.
|
|
122
|
+
|
|
123
|
+
### Academy
|
|
124
|
+
Browse educational tracks, read lessons, and search academy content.
|
|
125
|
+
|
|
126
|
+
## Example Prompts
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
"How's BTC looking right now?"
|
|
130
|
+
"Show me RSI and MACD for AAPL on the 4h chart"
|
|
131
|
+
"What active trade signals do we have?"
|
|
132
|
+
"Create a Golden Cross strategy using EMA 50/200"
|
|
133
|
+
"Backtest my strategy on NVDA over the last year"
|
|
134
|
+
"Log a long on ETH at 3,200 with stop at 3,050"
|
|
135
|
+
"Activate TSLA for my momentum strategy"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Development
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
git clone https://github.com/andywilliams/dwlf-mcp-server.git
|
|
142
|
+
cd dwlf-mcp-server
|
|
143
|
+
npm install
|
|
144
|
+
npm run build
|
|
145
|
+
DWLF_API_KEY=dwlf_sk_your_key npm run start
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
For hot reload during development:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
DWLF_API_KEY=dwlf_sk_your_key npm run dev
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Cookbook
|
|
155
|
+
|
|
156
|
+
For multi-step workflows, see [docs/cookbook.md](https://github.com/andywilliams/dwlf-mcp-server/blob/master/docs/cookbook.md).
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
[MIT](LICENSE) — DWLF / Andy Williams
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function normalizeSymbol(input: string): string;
|
|
2
|
+
export declare class DWLFClient {
|
|
3
|
+
private http;
|
|
4
|
+
constructor();
|
|
5
|
+
get<T = unknown>(path: string, params?: Record<string, unknown>): Promise<T>;
|
|
6
|
+
post<T = unknown>(path: string, data?: Record<string, unknown>): Promise<T>;
|
|
7
|
+
put<T = unknown>(path: string, data?: Record<string, unknown>): Promise<T>;
|
|
8
|
+
delete<T = unknown>(path: string): Promise<T>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAqBA,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAwBrD;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,IAAI,CAAgB;;IAsBtB,GAAG,CAAC,CAAC,GAAG,OAAO,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAmBP,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC;IAKP,GAAG,CAAC,CAAC,GAAG,OAAO,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC;IAKP,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAIpD"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
/**
|
|
3
|
+
* Normalize symbol input to DWLF's expected format (e.g. BTC-USD).
|
|
4
|
+
*
|
|
5
|
+
* Accepts:
|
|
6
|
+
* BTC, BTC/USD, BTC-USD, btc, btc/usd, BTCUSD
|
|
7
|
+
* Returns:
|
|
8
|
+
* BTC-USD (crypto) or AAPL (stocks — no suffix needed)
|
|
9
|
+
*
|
|
10
|
+
* Crypto assets get "-USD" appended when no quote currency is present.
|
|
11
|
+
* Known stock/ETF tickers pass through unchanged.
|
|
12
|
+
*/
|
|
13
|
+
const KNOWN_STOCKS = new Set([
|
|
14
|
+
'NVDA', 'TSLA', 'META', 'AAPL', 'AMZN', 'GOOG', 'GOOGL', 'MSFT', 'AMD',
|
|
15
|
+
'SLV', 'GDXJ', 'SILJ', 'AGQ', 'GLD', 'GDX', 'GOLD', // ETFs/metals
|
|
16
|
+
'MARA', 'RIOT', 'BTBT', 'CIFR', 'IREN', 'CLSK', // crypto miners
|
|
17
|
+
'COIN', 'MSTR', 'HUT', 'HIVE', 'BITF', 'WULF', // crypto-adjacent
|
|
18
|
+
'LSPD', 'SOFI', // fintech
|
|
19
|
+
]);
|
|
20
|
+
export function normalizeSymbol(input) {
|
|
21
|
+
let s = input.trim().toUpperCase();
|
|
22
|
+
// Already has separator: BTC/USD → BTC-USD, BTC-USD stays
|
|
23
|
+
if (s.includes('/')) {
|
|
24
|
+
return s.replace('/', '-');
|
|
25
|
+
}
|
|
26
|
+
if (s.includes('-')) {
|
|
27
|
+
return s;
|
|
28
|
+
}
|
|
29
|
+
// Known stock ticker — pass through as-is
|
|
30
|
+
if (KNOWN_STOCKS.has(s)) {
|
|
31
|
+
return s;
|
|
32
|
+
}
|
|
33
|
+
// Detect concatenated pair: BTCUSD, ETHUSD, SOLUSD etc.
|
|
34
|
+
const pairMatch = s.match(/^([A-Z]{2,5})(USD|USDT|EUR|GBP|BTC|ETH)$/);
|
|
35
|
+
if (pairMatch) {
|
|
36
|
+
return `${pairMatch[1]}-${pairMatch[2]}`;
|
|
37
|
+
}
|
|
38
|
+
// Bare crypto symbol: BTC → BTC-USD
|
|
39
|
+
return `${s}-USD`;
|
|
40
|
+
}
|
|
41
|
+
export class DWLFClient {
|
|
42
|
+
http;
|
|
43
|
+
constructor() {
|
|
44
|
+
const baseURL = process.env.DWLF_API_URL || 'https://api.dwlf.co.uk';
|
|
45
|
+
const apiKey = process.env.DWLF_API_KEY;
|
|
46
|
+
if (!apiKey) {
|
|
47
|
+
console.error('Warning: DWLF_API_KEY not set. Authenticated endpoints will fail.');
|
|
48
|
+
}
|
|
49
|
+
this.http = axios.create({
|
|
50
|
+
baseURL: `${baseURL}/v2`,
|
|
51
|
+
headers: {
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
...(apiKey ? { Authorization: `ApiKey ${apiKey}` } : {}),
|
|
54
|
+
},
|
|
55
|
+
timeout: 30000,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async get(path, params) {
|
|
59
|
+
// Filter out undefined params
|
|
60
|
+
const cleanParams = {};
|
|
61
|
+
if (params) {
|
|
62
|
+
for (const [key, value] of Object.entries(params)) {
|
|
63
|
+
if (value !== undefined) {
|
|
64
|
+
cleanParams[key] = value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const config = {
|
|
69
|
+
params: Object.keys(cleanParams).length > 0 ? cleanParams : undefined,
|
|
70
|
+
};
|
|
71
|
+
const response = await this.http.get(path, config);
|
|
72
|
+
return response.data;
|
|
73
|
+
}
|
|
74
|
+
async post(path, data) {
|
|
75
|
+
const response = await this.http.post(path, data);
|
|
76
|
+
return response.data;
|
|
77
|
+
}
|
|
78
|
+
async put(path, data) {
|
|
79
|
+
const response = await this.http.put(path, data);
|
|
80
|
+
return response.data;
|
|
81
|
+
}
|
|
82
|
+
async delete(path) {
|
|
83
|
+
const response = await this.http.delete(path);
|
|
84
|
+
return response.data;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { DWLFClient } from './client.js';
|
|
5
|
+
import { registerMarketDataTools } from './tools/market-data.js';
|
|
6
|
+
import { registerIndicatorTools } from './tools/indicators.js';
|
|
7
|
+
import { registerSignalTools } from './tools/signals.js';
|
|
8
|
+
import { registerWatchlistTools } from './tools/watchlist.js';
|
|
9
|
+
import { registerStrategyTools } from './tools/strategies.js';
|
|
10
|
+
import { registerBacktestTools } from './tools/backtests.js';
|
|
11
|
+
import { registerPortfolioTools } from './tools/portfolio.js';
|
|
12
|
+
import { registerTradeTools } from './tools/trades.js';
|
|
13
|
+
import { registerCustomEventTools } from './tools/custom-events.js';
|
|
14
|
+
import { registerAISummaryTools } from './tools/ai-summary.js';
|
|
15
|
+
import { registerAcademyTools } from './tools/academy.js';
|
|
16
|
+
import { registerSymbolActivationTools } from './tools/symbol-activations.js';
|
|
17
|
+
import { registerSymbolsResource } from './resources/symbols.js';
|
|
18
|
+
const server = new McpServer({
|
|
19
|
+
name: 'dwlf',
|
|
20
|
+
version: '0.3.0',
|
|
21
|
+
});
|
|
22
|
+
const client = new DWLFClient();
|
|
23
|
+
// Register all tools — Phase 1 (read)
|
|
24
|
+
registerMarketDataTools(server, client);
|
|
25
|
+
registerIndicatorTools(server, client);
|
|
26
|
+
registerSignalTools(server, client);
|
|
27
|
+
registerWatchlistTools(server, client);
|
|
28
|
+
// Register all tools — Phase 2 (read + write)
|
|
29
|
+
registerStrategyTools(server, client);
|
|
30
|
+
registerBacktestTools(server, client);
|
|
31
|
+
registerPortfolioTools(server, client);
|
|
32
|
+
registerTradeTools(server, client);
|
|
33
|
+
registerCustomEventTools(server, client);
|
|
34
|
+
// Register all tools — Phase 2b (symbol activation for events & strategies)
|
|
35
|
+
registerSymbolActivationTools(server, client);
|
|
36
|
+
// Register all tools — Phase 3 (AI summary endpoints)
|
|
37
|
+
registerAISummaryTools(server, client);
|
|
38
|
+
// Register all tools — Phase 4 (Academy — public CDN, no auth)
|
|
39
|
+
registerAcademyTools(server);
|
|
40
|
+
// Register resources
|
|
41
|
+
registerSymbolsResource(server, client);
|
|
42
|
+
// Start server with stdio transport
|
|
43
|
+
const transport = new StdioServerTransport();
|
|
44
|
+
await server.connect(transport);
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;AAEhC,sCAAsC;AACtC,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACxC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACvC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEvC,8CAA8C;AAC9C,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACvC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACnC,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEzC,4EAA4E;AAC5E,6BAA6B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C,sDAAsD;AACtD,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEvC,+DAA+D;AAC/D,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAE7B,qBAAqB;AACrB,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAExC,oCAAoC;AACpC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbols.d.ts","sourceRoot":"","sources":["../../src/resources/symbols.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,QAkBnB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function registerSymbolsResource(server, client) {
|
|
2
|
+
server.resource('symbols', 'dwlf://symbols', async (uri) => {
|
|
3
|
+
const symbols = await client.get('/market-data/symbols');
|
|
4
|
+
return {
|
|
5
|
+
contents: [
|
|
6
|
+
{
|
|
7
|
+
uri: uri.href,
|
|
8
|
+
mimeType: 'application/json',
|
|
9
|
+
text: JSON.stringify(symbols, null, 2),
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=symbols.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/resources/symbols.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,uBAAuB,CACrC,MAAiB,EACjB,MAAkB;IAElB,MAAM,CAAC,QAAQ,CACb,SAAS,EACT,gBAAgB,EAChB,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;QACzD,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"academy.d.ts","sourceRoot":"","sources":["../../src/tools/academy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA2DpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,QAuIrD"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
const ACADEMY_BASE = 'https://academy.dwlf.co.uk/live';
|
|
4
|
+
const MANIFEST_TTL_MS = 15 * 60 * 1000; // 15 minutes
|
|
5
|
+
// ── Cached manifest ───────────────────────────────────────────────
|
|
6
|
+
let cachedManifest = null;
|
|
7
|
+
let cacheTimestamp = 0;
|
|
8
|
+
async function getManifest() {
|
|
9
|
+
const now = Date.now();
|
|
10
|
+
if (cachedManifest && now - cacheTimestamp < MANIFEST_TTL_MS) {
|
|
11
|
+
return cachedManifest;
|
|
12
|
+
}
|
|
13
|
+
const { data } = await axios.get(`${ACADEMY_BASE}/manifest.json`, { timeout: 15000 });
|
|
14
|
+
cachedManifest = data;
|
|
15
|
+
cacheTimestamp = now;
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
// ── Image URL rewriter ────────────────────────────────────────────
|
|
19
|
+
function rewriteImageUrls(markdown) {
|
|
20
|
+
// Convert relative image paths to absolute CDN URLs
|
|
21
|
+
// Handles:  and 
|
|
22
|
+
return markdown.replace(/!\[([^\]]*)\]\((?:\.\/)?assets\//g, `;
|
|
23
|
+
}
|
|
24
|
+
// ── Tool registration ─────────────────────────────────────────────
|
|
25
|
+
export function registerAcademyTools(server) {
|
|
26
|
+
// 1. List all tracks and lessons
|
|
27
|
+
server.tool('dwlf_list_academy_tracks', 'List all DWLF Academy tracks and lessons. Use this to discover educational content about DWLF concepts — indicators, events, strategies, charting, and more.', {}, async () => {
|
|
28
|
+
try {
|
|
29
|
+
const manifest = await getManifest();
|
|
30
|
+
return {
|
|
31
|
+
content: [
|
|
32
|
+
{ type: 'text', text: JSON.stringify(manifest, null, 2) },
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: 'text',
|
|
41
|
+
text: `Error fetching academy manifest: ${error instanceof Error ? error.message : String(error)}`,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
isError: true,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
// 2. Get a single lesson by slug
|
|
49
|
+
server.tool('dwlf_get_academy_lesson', 'Get the full content of a DWLF Academy lesson by slug. Returns markdown. Use dwlf_list_academy_tracks first to find available lessons.', {
|
|
50
|
+
slug: z
|
|
51
|
+
.string()
|
|
52
|
+
.describe('Lesson slug from the academy manifest (e.g. "intro-to-indicators")'),
|
|
53
|
+
}, async ({ slug }) => {
|
|
54
|
+
try {
|
|
55
|
+
const { data } = await axios.get(`${ACADEMY_BASE}/lessons/${slug}.md`, { timeout: 15000, responseType: 'text' });
|
|
56
|
+
const content = rewriteImageUrls(data);
|
|
57
|
+
return {
|
|
58
|
+
content: [{ type: 'text', text: content }],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
const msg = axios.isAxiosError(error) && error.response?.status === 404
|
|
63
|
+
? `Lesson "${slug}" not found. Use dwlf_list_academy_tracks to see available lessons.`
|
|
64
|
+
: `Error fetching lesson "${slug}": ${error instanceof Error ? error.message : String(error)}`;
|
|
65
|
+
return {
|
|
66
|
+
content: [{ type: 'text', text: msg }],
|
|
67
|
+
isError: true,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
// 3. Search academy content by keyword
|
|
72
|
+
server.tool('dwlf_search_academy', 'Search DWLF Academy content by keyword. Searches track and lesson titles. Returns matching lessons with their track context.', {
|
|
73
|
+
query: z
|
|
74
|
+
.string()
|
|
75
|
+
.describe('Search term to match against track/lesson titles and descriptions'),
|
|
76
|
+
}, async ({ query }) => {
|
|
77
|
+
try {
|
|
78
|
+
const manifest = await getManifest();
|
|
79
|
+
const q = query.toLowerCase();
|
|
80
|
+
const results = [];
|
|
81
|
+
for (const track of manifest.tracks) {
|
|
82
|
+
const trackMatch = track.title.toLowerCase().includes(q) ||
|
|
83
|
+
track.description.toLowerCase().includes(q);
|
|
84
|
+
const matchedLessons = track.lessons.filter((l) => l.title.toLowerCase().includes(q));
|
|
85
|
+
if (trackMatch || matchedLessons.length > 0) {
|
|
86
|
+
results.push({
|
|
87
|
+
track: {
|
|
88
|
+
id: track.id,
|
|
89
|
+
title: track.title,
|
|
90
|
+
description: track.description,
|
|
91
|
+
},
|
|
92
|
+
matchedLessons: matchedLessons.length > 0
|
|
93
|
+
? matchedLessons
|
|
94
|
+
: trackMatch
|
|
95
|
+
? track.lessons
|
|
96
|
+
: [],
|
|
97
|
+
trackMatch,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (results.length === 0) {
|
|
102
|
+
return {
|
|
103
|
+
content: [
|
|
104
|
+
{
|
|
105
|
+
type: 'text',
|
|
106
|
+
text: `No academy content found for "${query}". Use dwlf_list_academy_tracks to browse all content.`,
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
content: [
|
|
113
|
+
{ type: 'text', text: JSON.stringify(results, null, 2) },
|
|
114
|
+
],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
{
|
|
121
|
+
type: 'text',
|
|
122
|
+
text: `Error searching academy: ${error instanceof Error ? error.message : String(error)}`,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
isError: true,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=academy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"academy.js","sourceRoot":"","sources":["../../src/tools/academy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-summary.d.ts","sourceRoot":"","sources":["../../src/tools/ai-summary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAE3D,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,QAgEnB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { normalizeSymbol } from '../client.js';
|
|
3
|
+
export function registerAISummaryTools(server, client) {
|
|
4
|
+
// 1. AI Dashboard
|
|
5
|
+
server.tool('dwlf_ai_dashboard', 'Get a complete account overview in a single call: watchlist with prices, active signals, open trades, portfolios, strategies, and recent events. Ideal for "what\'s going on?" queries. Requires markets:read permission; other sections degrade gracefully based on permissions.', {}, async () => {
|
|
6
|
+
try {
|
|
7
|
+
const data = await client.get('/ai/dashboard');
|
|
8
|
+
return {
|
|
9
|
+
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
return {
|
|
14
|
+
content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
15
|
+
isError: true,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
// 2. AI Symbol Brief
|
|
20
|
+
server.tool('dwlf_ai_symbol_brief', 'Get a condensed single-symbol view: latest price with change, recent candles, key indicators, S/R levels, recent events, and active signals. Perfect for "how\'s BTC doing?" queries.', {
|
|
21
|
+
symbol: z.string().describe('Symbol to get brief for (e.g. BTC, TSLA, NVDA)'),
|
|
22
|
+
}, async ({ symbol }) => {
|
|
23
|
+
try {
|
|
24
|
+
const normalized = normalizeSymbol(symbol);
|
|
25
|
+
const data = await client.get(`/ai/symbol-brief/${normalized}`);
|
|
26
|
+
return {
|
|
27
|
+
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
return {
|
|
32
|
+
content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
33
|
+
isError: true,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
// 3. AI Strategy Performance
|
|
38
|
+
server.tool('dwlf_ai_strategy_performance', 'Get all strategies with signal stats and performance metrics in a single call: total signals, active signals, win rate, avg R/R, total P&L, and per-strategy breakdowns.', {}, async () => {
|
|
39
|
+
try {
|
|
40
|
+
const data = await client.get('/ai/strategy-performance');
|
|
41
|
+
return {
|
|
42
|
+
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return {
|
|
47
|
+
content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
48
|
+
isError: true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=ai-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-summary.js","sourceRoot":"","sources":["../../src/tools/ai-summary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAc,eAAe,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,sBAAsB,CACpC,MAAiB,EACjB,MAAkB;IAElB,kBAAkB;IAClB,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,mRAAmR,EACnR,EAAE,EACF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YAC/C,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACjE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;gBACrG,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,qBAAqB;IACrB,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,uLAAuL,EACvL;QACE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;KAC9E,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QACnB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,oBAAoB,UAAU,EAAE,CAAC,CAAC;YAChE,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACjE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;gBACrG,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,6BAA6B;IAC7B,MAAM,CAAC,IAAI,CACT,8BAA8B,EAC9B,0KAA0K,EAC1K,EAAE,EACF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;YAC1D,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACjE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;gBACrG,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backtests.d.ts","sourceRoot":"","sources":["../../src/tools/backtests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAE3D,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,QAkGnB"}
|