fixparser-plugin-mcp 9.1.7-38cee007 → 9.1.7-3c6fd297
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/build/cjs/MCPLocal.js +40 -666
- package/build/cjs/MCPLocal.js.map +4 -4
- package/build/cjs/MCPRemote.js +126 -752
- package/build/cjs/MCPRemote.js.map +4 -4
- package/build/cjs/index.js +127 -753
- package/build/cjs/index.js.map +4 -4
- package/build/esm/MCPLocal.mjs +40 -666
- package/build/esm/MCPLocal.mjs.map +4 -4
- package/build/esm/MCPRemote.mjs +126 -752
- package/build/esm/MCPRemote.mjs.map +4 -4
- package/build/esm/index.mjs +127 -753
- package/build/esm/index.mjs.map +4 -4
- package/build-examples/cjs/example_mcp_local.js +7 -9
- package/build-examples/cjs/example_mcp_local.js.map +4 -4
- package/build-examples/cjs/example_mcp_remote.js +7 -9
- package/build-examples/cjs/example_mcp_remote.js.map +4 -4
- package/build-examples/esm/example_mcp_local.mjs +7 -9
- package/build-examples/esm/example_mcp_local.mjs.map +4 -4
- package/build-examples/esm/example_mcp_remote.mjs +6 -8
- package/build-examples/esm/example_mcp_remote.mjs.map +4 -4
- package/package.json +2 -2
- package/types/MCPBase.d.ts +49 -0
- package/types/MCPLocal.d.ts +40 -0
- package/types/MCPRemote.d.ts +66 -0
- package/types/PluginOptions.d.ts +6 -0
- package/types/index.d.ts +3 -0
- package/types/schemas/index.d.ts +15 -0
- package/types/schemas/schemas.d.ts +168 -0
- package/types/tools/index.d.ts +17 -0
- package/types/tools/marketData.d.ts +40 -0
- package/types/tools/order.d.ts +12 -0
- package/types/tools/parse.d.ts +5 -0
- package/types/tools/parseToJSON.d.ts +5 -0
- package/types/utils/messageHandler.d.ts +18 -0
package/build/esm/MCPRemote.mjs
CHANGED
|
@@ -132,7 +132,7 @@ var toolSchemas = {
|
|
|
132
132
|
}
|
|
133
133
|
},
|
|
134
134
|
executeOrder: {
|
|
135
|
-
description: "Executes a verified order. verifyOrder must be called before executeOrder.",
|
|
135
|
+
description: "Executes a verified order. verifyOrder must be called before executeOrder. user has to explicitly allow executeOrder.",
|
|
136
136
|
schema: {
|
|
137
137
|
type: "object",
|
|
138
138
|
properties: {
|
|
@@ -276,330 +276,7 @@ var toolSchemas = {
|
|
|
276
276
|
},
|
|
277
277
|
required: ["symbol"]
|
|
278
278
|
}
|
|
279
|
-
},
|
|
280
|
-
technicalAnalysis: {
|
|
281
|
-
description: "Performs comprehensive technical analysis on market data for a given symbol, including indicators like SMA, EMA, RSI, Bollinger Bands, and trading signals",
|
|
282
|
-
schema: {
|
|
283
|
-
type: "object",
|
|
284
|
-
properties: {
|
|
285
|
-
symbol: {
|
|
286
|
-
type: "string",
|
|
287
|
-
description: "The trading symbol to analyze (e.g., AAPL, MSFT, EURUSD)"
|
|
288
|
-
}
|
|
289
|
-
},
|
|
290
|
-
required: ["symbol"]
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
// src/tools/analytics.ts
|
|
296
|
-
function sum(numbers) {
|
|
297
|
-
return numbers.reduce((acc, val) => acc + val, 0);
|
|
298
|
-
}
|
|
299
|
-
var TechnicalAnalyzer = class {
|
|
300
|
-
prices;
|
|
301
|
-
volumes;
|
|
302
|
-
highs;
|
|
303
|
-
lows;
|
|
304
|
-
constructor(data) {
|
|
305
|
-
this.prices = data.map((d) => d.trade > 0 ? d.trade : d.midPrice);
|
|
306
|
-
this.volumes = data.map((d) => d.volume);
|
|
307
|
-
this.highs = data.map((d) => d.tradingSessionHighPrice > 0 ? d.tradingSessionHighPrice : d.trade);
|
|
308
|
-
this.lows = data.map((d) => d.tradingSessionLowPrice > 0 ? d.tradingSessionLowPrice : d.trade);
|
|
309
|
-
}
|
|
310
|
-
// Calculate Simple Moving Average
|
|
311
|
-
calculateSMA(data, period) {
|
|
312
|
-
const sma = [];
|
|
313
|
-
for (let i = period - 1; i < data.length; i++) {
|
|
314
|
-
const sum2 = data.slice(i - period + 1, i + 1).reduce((a, b) => a + b, 0);
|
|
315
|
-
sma.push(sum2 / period);
|
|
316
|
-
}
|
|
317
|
-
return sma;
|
|
318
|
-
}
|
|
319
|
-
// Calculate Exponential Moving Average
|
|
320
|
-
calculateEMA(data, period) {
|
|
321
|
-
const multiplier = 2 / (period + 1);
|
|
322
|
-
const ema = [data[0]];
|
|
323
|
-
for (let i = 1; i < data.length; i++) {
|
|
324
|
-
ema.push(data[i] * multiplier + ema[i - 1] * (1 - multiplier));
|
|
325
|
-
}
|
|
326
|
-
return ema;
|
|
327
|
-
}
|
|
328
|
-
// Calculate RSI
|
|
329
|
-
calculateRSI(data, period = 14) {
|
|
330
|
-
if (data.length < period + 1) return [];
|
|
331
|
-
const changes = [];
|
|
332
|
-
for (let i = 1; i < data.length; i++) {
|
|
333
|
-
changes.push(data[i] - data[i - 1]);
|
|
334
|
-
}
|
|
335
|
-
const gains = changes.map((change) => change > 0 ? change : 0);
|
|
336
|
-
const losses = changes.map((change) => change < 0 ? Math.abs(change) : 0);
|
|
337
|
-
let avgGain = gains.slice(0, period).reduce((a, b) => a + b, 0) / period;
|
|
338
|
-
let avgLoss = losses.slice(0, period).reduce((a, b) => a + b, 0) / period;
|
|
339
|
-
const rsi = [];
|
|
340
|
-
for (let i = period; i < changes.length; i++) {
|
|
341
|
-
const rs = avgGain / avgLoss;
|
|
342
|
-
rsi.push(100 - 100 / (1 + rs));
|
|
343
|
-
avgGain = (avgGain * (period - 1) + gains[i]) / period;
|
|
344
|
-
avgLoss = (avgLoss * (period - 1) + losses[i]) / period;
|
|
345
|
-
}
|
|
346
|
-
return rsi;
|
|
347
|
-
}
|
|
348
|
-
// Calculate Bollinger Bands
|
|
349
|
-
calculateBollingerBands(data, period = 20, stdDev = 2) {
|
|
350
|
-
if (data.length < period) return [];
|
|
351
|
-
const sma = this.calculateSMA(data, period);
|
|
352
|
-
const bands = [];
|
|
353
|
-
for (let i = 0; i < sma.length; i++) {
|
|
354
|
-
const dataSlice = data.slice(i, i + period);
|
|
355
|
-
const mean = sma[i];
|
|
356
|
-
const variance = dataSlice.reduce((sum2, price) => sum2 + (price - mean) ** 2, 0) / period;
|
|
357
|
-
const standardDeviation = Math.sqrt(variance);
|
|
358
|
-
bands.push({
|
|
359
|
-
upper: mean + standardDeviation * stdDev,
|
|
360
|
-
middle: mean,
|
|
361
|
-
lower: mean - standardDeviation * stdDev
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
return bands;
|
|
365
|
-
}
|
|
366
|
-
// Calculate maximum drawdown
|
|
367
|
-
calculateMaxDrawdown(prices) {
|
|
368
|
-
let maxPrice = prices[0];
|
|
369
|
-
let maxDrawdown = 0;
|
|
370
|
-
for (let i = 1; i < prices.length; i++) {
|
|
371
|
-
if (prices[i] > maxPrice) {
|
|
372
|
-
maxPrice = prices[i];
|
|
373
|
-
}
|
|
374
|
-
const drawdown = (maxPrice - prices[i]) / maxPrice;
|
|
375
|
-
if (drawdown > maxDrawdown) {
|
|
376
|
-
maxDrawdown = drawdown;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
return maxDrawdown;
|
|
380
|
-
}
|
|
381
|
-
// Calculate price changes for volatility
|
|
382
|
-
calculatePriceChanges() {
|
|
383
|
-
const changes = [];
|
|
384
|
-
for (let i = 1; i < this.prices.length; i++) {
|
|
385
|
-
changes.push((this.prices[i] - this.prices[i - 1]) / this.prices[i - 1]);
|
|
386
|
-
}
|
|
387
|
-
return changes;
|
|
388
|
-
}
|
|
389
|
-
// Generate comprehensive market analysis
|
|
390
|
-
analyze() {
|
|
391
|
-
const currentPrice = this.prices[this.prices.length - 1];
|
|
392
|
-
const startPrice = this.prices[0];
|
|
393
|
-
const sessionHigh = Math.max(...this.highs);
|
|
394
|
-
const sessionLow = Math.min(...this.lows);
|
|
395
|
-
const totalVolume = sum(this.volumes);
|
|
396
|
-
const avgVolume = totalVolume / this.volumes.length;
|
|
397
|
-
const priceChanges = this.calculatePriceChanges();
|
|
398
|
-
const volatility = priceChanges.length > 0 ? Math.sqrt(
|
|
399
|
-
priceChanges.reduce((sum2, change) => sum2 + change ** 2, 0) / priceChanges.length
|
|
400
|
-
) * Math.sqrt(252) * 100 : 0;
|
|
401
|
-
const sessionReturn = (currentPrice - startPrice) / startPrice * 100;
|
|
402
|
-
const pricePosition = (currentPrice - sessionLow) / (sessionHigh - sessionLow) * 100;
|
|
403
|
-
const trueVWAP = this.prices.reduce((sum2, price, i) => sum2 + price * this.volumes[i], 0) / totalVolume;
|
|
404
|
-
const momentum5 = this.prices.length > 5 ? (currentPrice - this.prices[Math.max(0, this.prices.length - 6)]) / this.prices[Math.max(0, this.prices.length - 6)] * 100 : 0;
|
|
405
|
-
const momentum10 = this.prices.length > 10 ? (currentPrice - this.prices[Math.max(0, this.prices.length - 11)]) / this.prices[Math.max(0, this.prices.length - 11)] * 100 : 0;
|
|
406
|
-
const maxDrawdown = this.calculateMaxDrawdown(this.prices);
|
|
407
|
-
return {
|
|
408
|
-
currentPrice,
|
|
409
|
-
startPrice,
|
|
410
|
-
sessionHigh,
|
|
411
|
-
sessionLow,
|
|
412
|
-
totalVolume,
|
|
413
|
-
avgVolume,
|
|
414
|
-
volatility,
|
|
415
|
-
sessionReturn,
|
|
416
|
-
pricePosition,
|
|
417
|
-
trueVWAP,
|
|
418
|
-
momentum5,
|
|
419
|
-
momentum10,
|
|
420
|
-
maxDrawdown
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
|
-
// Generate technical indicators
|
|
424
|
-
getTechnicalIndicators() {
|
|
425
|
-
return {
|
|
426
|
-
sma5: this.calculateSMA(this.prices, 5),
|
|
427
|
-
sma10: this.calculateSMA(this.prices, 10),
|
|
428
|
-
ema8: this.calculateEMA(this.prices, 8),
|
|
429
|
-
ema21: this.calculateEMA(this.prices, 21),
|
|
430
|
-
rsi: this.calculateRSI(this.prices, 14),
|
|
431
|
-
bollinger: this.calculateBollingerBands(this.prices, 20, 2)
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
// Generate trading signals
|
|
435
|
-
generateSignals() {
|
|
436
|
-
const analysis = this.analyze();
|
|
437
|
-
let bullishSignals = 0;
|
|
438
|
-
let bearishSignals = 0;
|
|
439
|
-
const signals = [];
|
|
440
|
-
if (analysis.currentPrice > analysis.trueVWAP) {
|
|
441
|
-
signals.push(
|
|
442
|
-
`\u2713 BULLISH: Price above VWAP (+${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
|
|
443
|
-
);
|
|
444
|
-
bullishSignals++;
|
|
445
|
-
} else {
|
|
446
|
-
signals.push(
|
|
447
|
-
`\u2717 BEARISH: Price below VWAP (${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
|
|
448
|
-
);
|
|
449
|
-
bearishSignals++;
|
|
450
|
-
}
|
|
451
|
-
if (analysis.momentum5 > 0 && analysis.momentum10 > 0) {
|
|
452
|
-
signals.push("\u2713 BULLISH: Positive momentum on both timeframes");
|
|
453
|
-
bullishSignals++;
|
|
454
|
-
} else if (analysis.momentum5 < 0 && analysis.momentum10 < 0) {
|
|
455
|
-
signals.push("\u2717 BEARISH: Negative momentum on both timeframes");
|
|
456
|
-
bearishSignals++;
|
|
457
|
-
} else {
|
|
458
|
-
signals.push("\u25D0 MIXED: Conflicting momentum signals");
|
|
459
|
-
}
|
|
460
|
-
const currentVolume = this.volumes[this.volumes.length - 1];
|
|
461
|
-
const volumeRatio = currentVolume / analysis.avgVolume;
|
|
462
|
-
if (volumeRatio > 1.2 && analysis.sessionReturn > 0) {
|
|
463
|
-
signals.push("\u2713 BULLISH: Above-average volume supporting upward move");
|
|
464
|
-
bullishSignals++;
|
|
465
|
-
} else if (volumeRatio > 1.2 && analysis.sessionReturn < 0) {
|
|
466
|
-
signals.push("\u2717 BEARISH: Above-average volume supporting downward move");
|
|
467
|
-
bearishSignals++;
|
|
468
|
-
} else {
|
|
469
|
-
signals.push("\u25D0 NEUTRAL: Volume not providing clear direction");
|
|
470
|
-
}
|
|
471
|
-
if (analysis.pricePosition > 65 && analysis.volatility > 30) {
|
|
472
|
-
signals.push("\u2717 BEARISH: High in range with elevated volatility - reversal risk");
|
|
473
|
-
bearishSignals++;
|
|
474
|
-
} else if (analysis.pricePosition < 35 && analysis.volatility > 30) {
|
|
475
|
-
signals.push("\u2713 BULLISH: Low in range with volatility - potential bounce");
|
|
476
|
-
bullishSignals++;
|
|
477
|
-
} else {
|
|
478
|
-
signals.push("\u25D0 NEUTRAL: Price position and volatility not extreme");
|
|
479
|
-
}
|
|
480
|
-
return { bullishSignals, bearishSignals, signals };
|
|
481
279
|
}
|
|
482
|
-
// Generate comprehensive JSON analysis
|
|
483
|
-
generateJSONAnalysis(symbol) {
|
|
484
|
-
const analysis = this.analyze();
|
|
485
|
-
const indicators = this.getTechnicalIndicators();
|
|
486
|
-
const signals = this.generateSignals();
|
|
487
|
-
const currentSMA5 = indicators.sma5.length > 0 ? indicators.sma5[indicators.sma5.length - 1] : null;
|
|
488
|
-
const currentSMA10 = indicators.sma10.length > 0 ? indicators.sma10[indicators.sma10.length - 1] : null;
|
|
489
|
-
const currentEMA8 = indicators.ema8[indicators.ema8.length - 1];
|
|
490
|
-
const currentEMA21 = indicators.ema21[indicators.ema21.length - 1];
|
|
491
|
-
const currentRSI = indicators.rsi.length > 0 ? indicators.rsi[indicators.rsi.length - 1] : null;
|
|
492
|
-
const currentBB = indicators.bollinger.length > 0 ? indicators.bollinger[indicators.bollinger.length - 1] : null;
|
|
493
|
-
const currentVolume = this.volumes[this.volumes.length - 1];
|
|
494
|
-
const volumeRatio = currentVolume / analysis.avgVolume;
|
|
495
|
-
const currentDrawdown = (analysis.sessionHigh - analysis.currentPrice) / analysis.sessionHigh * 100;
|
|
496
|
-
const rangeWidth = (analysis.sessionHigh - analysis.sessionLow) / analysis.sessionLow * 100;
|
|
497
|
-
const priceVsVWAP = (analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100;
|
|
498
|
-
const totalScore = signals.bullishSignals - signals.bearishSignals;
|
|
499
|
-
const overallSignal = totalScore > 0 ? "BULLISH_BIAS" : totalScore < 0 ? "BEARISH_BIAS" : "NEUTRAL";
|
|
500
|
-
const targetEntry = Math.max(analysis.sessionLow * 1.005, analysis.trueVWAP * 0.998);
|
|
501
|
-
const stopLoss = analysis.sessionLow * 0.995;
|
|
502
|
-
const profitTarget = analysis.sessionHigh * 0.995;
|
|
503
|
-
const riskRewardRatio = (profitTarget - analysis.currentPrice) / (analysis.currentPrice - stopLoss);
|
|
504
|
-
return {
|
|
505
|
-
symbol,
|
|
506
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
507
|
-
marketStructure: {
|
|
508
|
-
currentPrice: analysis.currentPrice,
|
|
509
|
-
startPrice: analysis.startPrice,
|
|
510
|
-
sessionHigh: analysis.sessionHigh,
|
|
511
|
-
sessionLow: analysis.sessionLow,
|
|
512
|
-
rangeWidth,
|
|
513
|
-
totalVolume: analysis.totalVolume,
|
|
514
|
-
sessionPerformance: analysis.sessionReturn,
|
|
515
|
-
positionInRange: analysis.pricePosition
|
|
516
|
-
},
|
|
517
|
-
volatility: {
|
|
518
|
-
impliedVolatility: analysis.volatility,
|
|
519
|
-
maxDrawdown: analysis.maxDrawdown * 100,
|
|
520
|
-
currentDrawdown
|
|
521
|
-
},
|
|
522
|
-
technicalIndicators: {
|
|
523
|
-
sma5: currentSMA5,
|
|
524
|
-
sma10: currentSMA10,
|
|
525
|
-
ema8: currentEMA8,
|
|
526
|
-
ema21: currentEMA21,
|
|
527
|
-
rsi: currentRSI,
|
|
528
|
-
bollingerBands: currentBB ? {
|
|
529
|
-
upper: currentBB.upper,
|
|
530
|
-
middle: currentBB.middle,
|
|
531
|
-
lower: currentBB.lower,
|
|
532
|
-
position: (analysis.currentPrice - currentBB.lower) / (currentBB.upper - currentBB.lower) * 100
|
|
533
|
-
} : null
|
|
534
|
-
},
|
|
535
|
-
volumeAnalysis: {
|
|
536
|
-
currentVolume,
|
|
537
|
-
averageVolume: Math.round(analysis.avgVolume),
|
|
538
|
-
volumeRatio,
|
|
539
|
-
trueVWAP: analysis.trueVWAP,
|
|
540
|
-
priceVsVWAP
|
|
541
|
-
},
|
|
542
|
-
momentum: {
|
|
543
|
-
momentum5: analysis.momentum5,
|
|
544
|
-
momentum10: analysis.momentum10,
|
|
545
|
-
sessionROC: analysis.sessionReturn
|
|
546
|
-
},
|
|
547
|
-
tradingSignals: {
|
|
548
|
-
...signals,
|
|
549
|
-
overallSignal,
|
|
550
|
-
signalScore: totalScore
|
|
551
|
-
},
|
|
552
|
-
riskManagement: {
|
|
553
|
-
targetEntry,
|
|
554
|
-
stopLoss,
|
|
555
|
-
profitTarget,
|
|
556
|
-
riskRewardRatio
|
|
557
|
-
}
|
|
558
|
-
};
|
|
559
|
-
}
|
|
560
|
-
};
|
|
561
|
-
var createTechnicalAnalysisHandler = (marketDataPrices) => {
|
|
562
|
-
return async (args) => {
|
|
563
|
-
try {
|
|
564
|
-
const symbol = args.symbol;
|
|
565
|
-
const priceHistory = marketDataPrices.get(symbol) || [];
|
|
566
|
-
if (priceHistory.length === 0) {
|
|
567
|
-
return {
|
|
568
|
-
content: [
|
|
569
|
-
{
|
|
570
|
-
type: "text",
|
|
571
|
-
text: `No price data available for ${symbol}. Please request market data first.`,
|
|
572
|
-
uri: "technicalAnalysis"
|
|
573
|
-
}
|
|
574
|
-
]
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
const analyzer = new TechnicalAnalyzer(priceHistory);
|
|
578
|
-
const analysis = analyzer.generateJSONAnalysis(symbol);
|
|
579
|
-
return {
|
|
580
|
-
content: [
|
|
581
|
-
{
|
|
582
|
-
type: "text",
|
|
583
|
-
text: `Technical Analysis for ${symbol}:
|
|
584
|
-
|
|
585
|
-
${JSON.stringify(analysis, null, 2)}`,
|
|
586
|
-
uri: "technicalAnalysis"
|
|
587
|
-
}
|
|
588
|
-
]
|
|
589
|
-
};
|
|
590
|
-
} catch (error) {
|
|
591
|
-
return {
|
|
592
|
-
content: [
|
|
593
|
-
{
|
|
594
|
-
type: "text",
|
|
595
|
-
text: `Error performing technical analysis: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
596
|
-
uri: "technicalAnalysis"
|
|
597
|
-
}
|
|
598
|
-
],
|
|
599
|
-
isError: true
|
|
600
|
-
};
|
|
601
|
-
}
|
|
602
|
-
};
|
|
603
280
|
};
|
|
604
281
|
|
|
605
282
|
// src/tools/marketData.ts
|
|
@@ -608,63 +285,10 @@ import QuickChart from "quickchart-js";
|
|
|
608
285
|
var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
609
286
|
return async (args) => {
|
|
610
287
|
try {
|
|
611
|
-
parser.logger.log({
|
|
612
|
-
level: "info",
|
|
613
|
-
message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
|
|
614
|
-
});
|
|
615
288
|
const response = new Promise((resolve) => {
|
|
616
289
|
pendingRequests.set(args.mdReqID, resolve);
|
|
617
|
-
parser.logger.log({
|
|
618
|
-
level: "info",
|
|
619
|
-
message: `Registered callback for market data request ID: ${args.mdReqID}`
|
|
620
|
-
});
|
|
621
290
|
});
|
|
622
|
-
const entryTypes = args.mdEntryTypes || [
|
|
623
|
-
MDEntryType.Bid,
|
|
624
|
-
MDEntryType.Offer,
|
|
625
|
-
MDEntryType.Trade,
|
|
626
|
-
MDEntryType.IndexValue,
|
|
627
|
-
MDEntryType.OpeningPrice,
|
|
628
|
-
MDEntryType.ClosingPrice,
|
|
629
|
-
MDEntryType.SettlementPrice,
|
|
630
|
-
MDEntryType.TradingSessionHighPrice,
|
|
631
|
-
MDEntryType.TradingSessionLowPrice,
|
|
632
|
-
MDEntryType.VWAP,
|
|
633
|
-
MDEntryType.Imbalance,
|
|
634
|
-
MDEntryType.TradeVolume,
|
|
635
|
-
MDEntryType.OpenInterest,
|
|
636
|
-
MDEntryType.CompositeUnderlyingPrice,
|
|
637
|
-
MDEntryType.SimulatedSellPrice,
|
|
638
|
-
MDEntryType.SimulatedBuyPrice,
|
|
639
|
-
MDEntryType.MarginRate,
|
|
640
|
-
MDEntryType.MidPrice,
|
|
641
|
-
MDEntryType.EmptyBook,
|
|
642
|
-
MDEntryType.SettleHighPrice,
|
|
643
|
-
MDEntryType.SettleLowPrice,
|
|
644
|
-
MDEntryType.PriorSettlePrice,
|
|
645
|
-
MDEntryType.SessionHighBid,
|
|
646
|
-
MDEntryType.SessionLowOffer,
|
|
647
|
-
MDEntryType.EarlyPrices,
|
|
648
|
-
MDEntryType.AuctionClearingPrice,
|
|
649
|
-
MDEntryType.SwapValueFactor,
|
|
650
|
-
MDEntryType.DailyValueAdjustmentForLongPositions,
|
|
651
|
-
MDEntryType.CumulativeValueAdjustmentForLongPositions,
|
|
652
|
-
MDEntryType.DailyValueAdjustmentForShortPositions,
|
|
653
|
-
MDEntryType.CumulativeValueAdjustmentForShortPositions,
|
|
654
|
-
MDEntryType.FixingPrice,
|
|
655
|
-
MDEntryType.CashRate,
|
|
656
|
-
MDEntryType.RecoveryRate,
|
|
657
|
-
MDEntryType.RecoveryRateForLong,
|
|
658
|
-
MDEntryType.RecoveryRateForShort,
|
|
659
|
-
MDEntryType.MarketBid,
|
|
660
|
-
MDEntryType.MarketOffer,
|
|
661
|
-
MDEntryType.ShortSaleMinPrice,
|
|
662
|
-
MDEntryType.PreviousClosingPrice,
|
|
663
|
-
MDEntryType.ThresholdLimitPriceBanding,
|
|
664
|
-
MDEntryType.DailyFinancingValue,
|
|
665
|
-
MDEntryType.AccruedFinancingValue,
|
|
666
|
-
MDEntryType.TWAP
|
|
667
|
-
];
|
|
291
|
+
const entryTypes = args.mdEntryTypes || [MDEntryType.Bid, MDEntryType.Offer, MDEntryType.TradeVolume];
|
|
668
292
|
const messageFields = [
|
|
669
293
|
new Field(Fields.MsgType, Messages.MarketDataRequest),
|
|
670
294
|
new Field(Fields.SenderCompID, parser.sender),
|
|
@@ -686,10 +310,6 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
|
686
310
|
});
|
|
687
311
|
const mdr = parser.createMessage(...messageFields);
|
|
688
312
|
if (!parser.connected) {
|
|
689
|
-
parser.logger.log({
|
|
690
|
-
level: "error",
|
|
691
|
-
message: "Not connected. Cannot send market data request."
|
|
692
|
-
});
|
|
693
313
|
return {
|
|
694
314
|
content: [
|
|
695
315
|
{
|
|
@@ -701,16 +321,8 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
|
701
321
|
isError: true
|
|
702
322
|
};
|
|
703
323
|
}
|
|
704
|
-
parser.logger.log({
|
|
705
|
-
level: "info",
|
|
706
|
-
message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
|
|
707
|
-
});
|
|
708
324
|
parser.send(mdr);
|
|
709
325
|
const fixData = await response;
|
|
710
|
-
parser.logger.log({
|
|
711
|
-
level: "info",
|
|
712
|
-
message: `Received market data response for request ID: ${args.mdReqID}`
|
|
713
|
-
});
|
|
714
326
|
return {
|
|
715
327
|
content: [
|
|
716
328
|
{
|
|
@@ -759,9 +371,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
759
371
|
const offerData = priceHistory.map((point) => point.offer);
|
|
760
372
|
const spreadData = priceHistory.map((point) => point.spread);
|
|
761
373
|
const volumeData = priceHistory.map((point) => point.volume);
|
|
762
|
-
const tradeData = priceHistory.map((point) => point.trade);
|
|
763
|
-
const vwapData = priceHistory.map((point) => point.vwap);
|
|
764
|
-
const twapData = priceHistory.map((point) => point.twap);
|
|
765
374
|
const config = {
|
|
766
375
|
type: "line",
|
|
767
376
|
data: {
|
|
@@ -791,30 +400,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
791
400
|
fill: false,
|
|
792
401
|
tension: 0.4
|
|
793
402
|
},
|
|
794
|
-
{
|
|
795
|
-
label: "Trade",
|
|
796
|
-
data: tradeData,
|
|
797
|
-
borderColor: "#ffc107",
|
|
798
|
-
backgroundColor: "rgba(255, 193, 7, 0.1)",
|
|
799
|
-
fill: false,
|
|
800
|
-
tension: 0.4
|
|
801
|
-
},
|
|
802
|
-
{
|
|
803
|
-
label: "VWAP",
|
|
804
|
-
data: vwapData,
|
|
805
|
-
borderColor: "#17a2b8",
|
|
806
|
-
backgroundColor: "rgba(23, 162, 184, 0.1)",
|
|
807
|
-
fill: false,
|
|
808
|
-
tension: 0.4
|
|
809
|
-
},
|
|
810
|
-
{
|
|
811
|
-
label: "TWAP",
|
|
812
|
-
data: twapData,
|
|
813
|
-
borderColor: "#6610f2",
|
|
814
|
-
backgroundColor: "rgba(102, 16, 242, 0.1)",
|
|
815
|
-
fill: false,
|
|
816
|
-
tension: 0.4
|
|
817
|
-
},
|
|
818
403
|
{
|
|
819
404
|
label: "Volume",
|
|
820
405
|
data: volumeData,
|
|
@@ -860,7 +445,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
860
445
|
content: [
|
|
861
446
|
{
|
|
862
447
|
type: "text",
|
|
863
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to generate
|
|
448
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
|
|
864
449
|
uri: "getStockGraph"
|
|
865
450
|
}
|
|
866
451
|
],
|
|
@@ -898,48 +483,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
|
|
|
898
483
|
bid: point.bid,
|
|
899
484
|
offer: point.offer,
|
|
900
485
|
spread: point.spread,
|
|
901
|
-
volume: point.volume
|
|
902
|
-
trade: point.trade,
|
|
903
|
-
indexValue: point.indexValue,
|
|
904
|
-
openingPrice: point.openingPrice,
|
|
905
|
-
closingPrice: point.closingPrice,
|
|
906
|
-
settlementPrice: point.settlementPrice,
|
|
907
|
-
tradingSessionHighPrice: point.tradingSessionHighPrice,
|
|
908
|
-
tradingSessionLowPrice: point.tradingSessionLowPrice,
|
|
909
|
-
vwap: point.vwap,
|
|
910
|
-
imbalance: point.imbalance,
|
|
911
|
-
openInterest: point.openInterest,
|
|
912
|
-
compositeUnderlyingPrice: point.compositeUnderlyingPrice,
|
|
913
|
-
simulatedSellPrice: point.simulatedSellPrice,
|
|
914
|
-
simulatedBuyPrice: point.simulatedBuyPrice,
|
|
915
|
-
marginRate: point.marginRate,
|
|
916
|
-
midPrice: point.midPrice,
|
|
917
|
-
emptyBook: point.emptyBook,
|
|
918
|
-
settleHighPrice: point.settleHighPrice,
|
|
919
|
-
settleLowPrice: point.settleLowPrice,
|
|
920
|
-
priorSettlePrice: point.priorSettlePrice,
|
|
921
|
-
sessionHighBid: point.sessionHighBid,
|
|
922
|
-
sessionLowOffer: point.sessionLowOffer,
|
|
923
|
-
earlyPrices: point.earlyPrices,
|
|
924
|
-
auctionClearingPrice: point.auctionClearingPrice,
|
|
925
|
-
swapValueFactor: point.swapValueFactor,
|
|
926
|
-
dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
|
|
927
|
-
cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
|
|
928
|
-
dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
|
|
929
|
-
cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
|
|
930
|
-
fixingPrice: point.fixingPrice,
|
|
931
|
-
cashRate: point.cashRate,
|
|
932
|
-
recoveryRate: point.recoveryRate,
|
|
933
|
-
recoveryRateForLong: point.recoveryRateForLong,
|
|
934
|
-
recoveryRateForShort: point.recoveryRateForShort,
|
|
935
|
-
marketBid: point.marketBid,
|
|
936
|
-
marketOffer: point.marketOffer,
|
|
937
|
-
shortSaleMinPrice: point.shortSaleMinPrice,
|
|
938
|
-
previousClosingPrice: point.previousClosingPrice,
|
|
939
|
-
thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
|
|
940
|
-
dailyFinancingValue: point.dailyFinancingValue,
|
|
941
|
-
accruedFinancingValue: point.accruedFinancingValue,
|
|
942
|
-
twap: point.twap
|
|
486
|
+
volume: point.volume
|
|
943
487
|
}))
|
|
944
488
|
},
|
|
945
489
|
null,
|
|
@@ -954,7 +498,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
|
|
|
954
498
|
content: [
|
|
955
499
|
{
|
|
956
500
|
type: "text",
|
|
957
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
|
|
501
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
|
|
958
502
|
uri: "getStockPriceHistory"
|
|
959
503
|
}
|
|
960
504
|
],
|
|
@@ -1062,7 +606,7 @@ Parameters verified:
|
|
|
1062
606
|
- Symbol: ${args.symbol}
|
|
1063
607
|
- TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
|
|
1064
608
|
|
|
1065
|
-
To execute this order, call the executeOrder tool with these exact same parameters
|
|
609
|
+
To execute this order, call the executeOrder tool with these exact same parameters.`,
|
|
1066
610
|
uri: "verifyOrder"
|
|
1067
611
|
}
|
|
1068
612
|
]
|
|
@@ -1258,210 +802,48 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
|
|
|
1258
802
|
executeOrder: createExecuteOrderHandler(parser, verifiedOrders, pendingRequests),
|
|
1259
803
|
marketDataRequest: createMarketDataRequestHandler(parser, pendingRequests),
|
|
1260
804
|
getStockGraph: createGetStockGraphHandler(marketDataPrices),
|
|
1261
|
-
getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
|
|
1262
|
-
technicalAnalysis: createTechnicalAnalysisHandler(marketDataPrices)
|
|
805
|
+
getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
|
|
1263
806
|
});
|
|
1264
807
|
|
|
1265
808
|
// src/utils/messageHandler.ts
|
|
1266
809
|
import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
|
|
1267
|
-
function getEnumValue(enumObj, name) {
|
|
1268
|
-
return enumObj[name] || name;
|
|
1269
|
-
}
|
|
1270
810
|
function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
|
|
811
|
+
parser.logger.log({
|
|
812
|
+
level: "info",
|
|
813
|
+
message: `MCP Server received message: ${message.messageType}: ${message.description}`
|
|
814
|
+
});
|
|
1271
815
|
const msgType = message.messageType;
|
|
1272
|
-
if (msgType === Messages3.MarketDataSnapshotFullRefresh
|
|
816
|
+
if (msgType === Messages3.MarketDataSnapshotFullRefresh) {
|
|
1273
817
|
const symbol = message.getField(Fields3.Symbol)?.value;
|
|
1274
|
-
const
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
compositeUnderlyingPrice: 0,
|
|
1293
|
-
simulatedSellPrice: 0,
|
|
1294
|
-
simulatedBuyPrice: 0,
|
|
1295
|
-
marginRate: 0,
|
|
1296
|
-
midPrice: 0,
|
|
1297
|
-
emptyBook: 0,
|
|
1298
|
-
settleHighPrice: 0,
|
|
1299
|
-
settleLowPrice: 0,
|
|
1300
|
-
priorSettlePrice: 0,
|
|
1301
|
-
sessionHighBid: 0,
|
|
1302
|
-
sessionLowOffer: 0,
|
|
1303
|
-
earlyPrices: 0,
|
|
1304
|
-
auctionClearingPrice: 0,
|
|
1305
|
-
swapValueFactor: 0,
|
|
1306
|
-
dailyValueAdjustmentForLongPositions: 0,
|
|
1307
|
-
cumulativeValueAdjustmentForLongPositions: 0,
|
|
1308
|
-
dailyValueAdjustmentForShortPositions: 0,
|
|
1309
|
-
cumulativeValueAdjustmentForShortPositions: 0,
|
|
1310
|
-
fixingPrice: 0,
|
|
1311
|
-
cashRate: 0,
|
|
1312
|
-
recoveryRate: 0,
|
|
1313
|
-
recoveryRateForLong: 0,
|
|
1314
|
-
recoveryRateForShort: 0,
|
|
1315
|
-
marketBid: 0,
|
|
1316
|
-
marketOffer: 0,
|
|
1317
|
-
shortSaleMinPrice: 0,
|
|
1318
|
-
previousClosingPrice: 0,
|
|
1319
|
-
thresholdLimitPriceBanding: 0,
|
|
1320
|
-
dailyFinancingValue: 0,
|
|
1321
|
-
accruedFinancingValue: 0,
|
|
1322
|
-
twap: 0
|
|
1323
|
-
};
|
|
1324
|
-
for (const entry of entries) {
|
|
1325
|
-
const entryType = entry.MDEntryType;
|
|
1326
|
-
const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
|
|
1327
|
-
const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
|
|
1328
|
-
const enumValue = getEnumValue(MDEntryType2, entryType);
|
|
1329
|
-
switch (enumValue) {
|
|
1330
|
-
case MDEntryType2.Bid:
|
|
1331
|
-
data.bid = price;
|
|
1332
|
-
break;
|
|
1333
|
-
case MDEntryType2.Offer:
|
|
1334
|
-
data.offer = price;
|
|
1335
|
-
break;
|
|
1336
|
-
case MDEntryType2.Trade:
|
|
1337
|
-
data.trade = price;
|
|
1338
|
-
break;
|
|
1339
|
-
case MDEntryType2.IndexValue:
|
|
1340
|
-
data.indexValue = price;
|
|
1341
|
-
break;
|
|
1342
|
-
case MDEntryType2.OpeningPrice:
|
|
1343
|
-
data.openingPrice = price;
|
|
1344
|
-
break;
|
|
1345
|
-
case MDEntryType2.ClosingPrice:
|
|
1346
|
-
data.closingPrice = price;
|
|
1347
|
-
break;
|
|
1348
|
-
case MDEntryType2.SettlementPrice:
|
|
1349
|
-
data.settlementPrice = price;
|
|
1350
|
-
break;
|
|
1351
|
-
case MDEntryType2.TradingSessionHighPrice:
|
|
1352
|
-
data.tradingSessionHighPrice = price;
|
|
1353
|
-
break;
|
|
1354
|
-
case MDEntryType2.TradingSessionLowPrice:
|
|
1355
|
-
data.tradingSessionLowPrice = price;
|
|
1356
|
-
break;
|
|
1357
|
-
case MDEntryType2.VWAP:
|
|
1358
|
-
data.vwap = price;
|
|
1359
|
-
break;
|
|
1360
|
-
case MDEntryType2.Imbalance:
|
|
1361
|
-
data.imbalance = size;
|
|
1362
|
-
break;
|
|
1363
|
-
case MDEntryType2.TradeVolume:
|
|
1364
|
-
data.volume = size;
|
|
1365
|
-
break;
|
|
1366
|
-
case MDEntryType2.OpenInterest:
|
|
1367
|
-
data.openInterest = size;
|
|
1368
|
-
break;
|
|
1369
|
-
case MDEntryType2.CompositeUnderlyingPrice:
|
|
1370
|
-
data.compositeUnderlyingPrice = price;
|
|
1371
|
-
break;
|
|
1372
|
-
case MDEntryType2.SimulatedSellPrice:
|
|
1373
|
-
data.simulatedSellPrice = price;
|
|
1374
|
-
break;
|
|
1375
|
-
case MDEntryType2.SimulatedBuyPrice:
|
|
1376
|
-
data.simulatedBuyPrice = price;
|
|
1377
|
-
break;
|
|
1378
|
-
case MDEntryType2.MarginRate:
|
|
1379
|
-
data.marginRate = price;
|
|
1380
|
-
break;
|
|
1381
|
-
case MDEntryType2.MidPrice:
|
|
1382
|
-
data.midPrice = price;
|
|
1383
|
-
break;
|
|
1384
|
-
case MDEntryType2.EmptyBook:
|
|
1385
|
-
data.emptyBook = 1;
|
|
1386
|
-
break;
|
|
1387
|
-
case MDEntryType2.SettleHighPrice:
|
|
1388
|
-
data.settleHighPrice = price;
|
|
1389
|
-
break;
|
|
1390
|
-
case MDEntryType2.SettleLowPrice:
|
|
1391
|
-
data.settleLowPrice = price;
|
|
1392
|
-
break;
|
|
1393
|
-
case MDEntryType2.PriorSettlePrice:
|
|
1394
|
-
data.priorSettlePrice = price;
|
|
1395
|
-
break;
|
|
1396
|
-
case MDEntryType2.SessionHighBid:
|
|
1397
|
-
data.sessionHighBid = price;
|
|
1398
|
-
break;
|
|
1399
|
-
case MDEntryType2.SessionLowOffer:
|
|
1400
|
-
data.sessionLowOffer = price;
|
|
1401
|
-
break;
|
|
1402
|
-
case MDEntryType2.EarlyPrices:
|
|
1403
|
-
data.earlyPrices = price;
|
|
1404
|
-
break;
|
|
1405
|
-
case MDEntryType2.AuctionClearingPrice:
|
|
1406
|
-
data.auctionClearingPrice = price;
|
|
1407
|
-
break;
|
|
1408
|
-
case MDEntryType2.SwapValueFactor:
|
|
1409
|
-
data.swapValueFactor = price;
|
|
1410
|
-
break;
|
|
1411
|
-
case MDEntryType2.DailyValueAdjustmentForLongPositions:
|
|
1412
|
-
data.dailyValueAdjustmentForLongPositions = price;
|
|
1413
|
-
break;
|
|
1414
|
-
case MDEntryType2.CumulativeValueAdjustmentForLongPositions:
|
|
1415
|
-
data.cumulativeValueAdjustmentForLongPositions = price;
|
|
1416
|
-
break;
|
|
1417
|
-
case MDEntryType2.DailyValueAdjustmentForShortPositions:
|
|
1418
|
-
data.dailyValueAdjustmentForShortPositions = price;
|
|
1419
|
-
break;
|
|
1420
|
-
case MDEntryType2.CumulativeValueAdjustmentForShortPositions:
|
|
1421
|
-
data.cumulativeValueAdjustmentForShortPositions = price;
|
|
1422
|
-
break;
|
|
1423
|
-
case MDEntryType2.FixingPrice:
|
|
1424
|
-
data.fixingPrice = price;
|
|
1425
|
-
break;
|
|
1426
|
-
case MDEntryType2.CashRate:
|
|
1427
|
-
data.cashRate = price;
|
|
1428
|
-
break;
|
|
1429
|
-
case MDEntryType2.RecoveryRate:
|
|
1430
|
-
data.recoveryRate = price;
|
|
1431
|
-
break;
|
|
1432
|
-
case MDEntryType2.RecoveryRateForLong:
|
|
1433
|
-
data.recoveryRateForLong = price;
|
|
1434
|
-
break;
|
|
1435
|
-
case MDEntryType2.RecoveryRateForShort:
|
|
1436
|
-
data.recoveryRateForShort = price;
|
|
1437
|
-
break;
|
|
1438
|
-
case MDEntryType2.MarketBid:
|
|
1439
|
-
data.marketBid = price;
|
|
1440
|
-
break;
|
|
1441
|
-
case MDEntryType2.MarketOffer:
|
|
1442
|
-
data.marketOffer = price;
|
|
1443
|
-
break;
|
|
1444
|
-
case MDEntryType2.ShortSaleMinPrice:
|
|
1445
|
-
data.shortSaleMinPrice = price;
|
|
1446
|
-
break;
|
|
1447
|
-
case MDEntryType2.PreviousClosingPrice:
|
|
1448
|
-
data.previousClosingPrice = price;
|
|
1449
|
-
break;
|
|
1450
|
-
case MDEntryType2.ThresholdLimitPriceBanding:
|
|
1451
|
-
data.thresholdLimitPriceBanding = price;
|
|
1452
|
-
break;
|
|
1453
|
-
case MDEntryType2.DailyFinancingValue:
|
|
1454
|
-
data.dailyFinancingValue = price;
|
|
1455
|
-
break;
|
|
1456
|
-
case MDEntryType2.AccruedFinancingValue:
|
|
1457
|
-
data.accruedFinancingValue = price;
|
|
1458
|
-
break;
|
|
1459
|
-
case MDEntryType2.TWAP:
|
|
1460
|
-
data.twap = price;
|
|
1461
|
-
break;
|
|
818
|
+
const entries = message.getField(Fields3.NoMDEntries)?.value;
|
|
819
|
+
let bid = 0;
|
|
820
|
+
let offer = 0;
|
|
821
|
+
let volume = 0;
|
|
822
|
+
const entryTypes = message.getFields(Fields3.MDEntryType);
|
|
823
|
+
const entryPrices = message.getFields(Fields3.MDEntryPx);
|
|
824
|
+
const entrySizes = message.getFields(Fields3.MDEntrySize);
|
|
825
|
+
if (entryTypes && entryPrices && entrySizes) {
|
|
826
|
+
for (let i = 0; i < entries; i++) {
|
|
827
|
+
const entryType = entryTypes[i]?.value;
|
|
828
|
+
const entryPrice = Number.parseFloat(entryPrices[i]?.value);
|
|
829
|
+
const entrySize = Number.parseFloat(entrySizes[i]?.value);
|
|
830
|
+
if (entryType === MDEntryType2.Bid) {
|
|
831
|
+
bid = entryPrice;
|
|
832
|
+
} else if (entryType === MDEntryType2.Offer) {
|
|
833
|
+
offer = entryPrice;
|
|
834
|
+
}
|
|
835
|
+
volume += entrySize;
|
|
1462
836
|
}
|
|
1463
837
|
}
|
|
1464
|
-
|
|
838
|
+
const spread = offer - bid;
|
|
839
|
+
const timestamp = Date.now();
|
|
840
|
+
const data = {
|
|
841
|
+
timestamp,
|
|
842
|
+
bid,
|
|
843
|
+
offer,
|
|
844
|
+
spread,
|
|
845
|
+
volume
|
|
846
|
+
};
|
|
1465
847
|
if (!marketDataPrices.has(symbol)) {
|
|
1466
848
|
marketDataPrices.set(symbol, []);
|
|
1467
849
|
}
|
|
@@ -1471,14 +853,6 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
|
|
|
1471
853
|
prices.splice(0, prices.length - maxPriceHistory);
|
|
1472
854
|
}
|
|
1473
855
|
onPriceUpdate?.(symbol, data);
|
|
1474
|
-
const mdReqID = message.getField(Fields3.MDReqID)?.value;
|
|
1475
|
-
if (mdReqID) {
|
|
1476
|
-
const callback = pendingRequests.get(mdReqID);
|
|
1477
|
-
if (callback) {
|
|
1478
|
-
callback(message);
|
|
1479
|
-
pendingRequests.delete(mdReqID);
|
|
1480
|
-
}
|
|
1481
|
-
}
|
|
1482
856
|
} else if (msgType === Messages3.ExecutionReport) {
|
|
1483
857
|
const reqId = message.getField(Fields3.ClOrdID)?.value;
|
|
1484
858
|
const callback = pendingRequests.get(reqId);
|
|
@@ -1491,39 +865,6 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
|
|
|
1491
865
|
|
|
1492
866
|
// src/MCPRemote.ts
|
|
1493
867
|
var transports = {};
|
|
1494
|
-
function jsonSchemaToZod(schema) {
|
|
1495
|
-
if (schema.type === "object") {
|
|
1496
|
-
const shape = {};
|
|
1497
|
-
for (const [key, prop] of Object.entries(schema.properties || {})) {
|
|
1498
|
-
const propSchema = prop;
|
|
1499
|
-
if (propSchema.type === "string") {
|
|
1500
|
-
if (propSchema.enum) {
|
|
1501
|
-
shape[key] = z.enum(propSchema.enum);
|
|
1502
|
-
} else {
|
|
1503
|
-
shape[key] = z.string();
|
|
1504
|
-
}
|
|
1505
|
-
} else if (propSchema.type === "number") {
|
|
1506
|
-
shape[key] = z.number();
|
|
1507
|
-
} else if (propSchema.type === "boolean") {
|
|
1508
|
-
shape[key] = z.boolean();
|
|
1509
|
-
} else if (propSchema.type === "array") {
|
|
1510
|
-
if (propSchema.items.type === "string") {
|
|
1511
|
-
shape[key] = z.array(z.string());
|
|
1512
|
-
} else if (propSchema.items.type === "number") {
|
|
1513
|
-
shape[key] = z.array(z.number());
|
|
1514
|
-
} else if (propSchema.items.type === "boolean") {
|
|
1515
|
-
shape[key] = z.array(z.boolean());
|
|
1516
|
-
} else {
|
|
1517
|
-
shape[key] = z.array(z.any());
|
|
1518
|
-
}
|
|
1519
|
-
} else {
|
|
1520
|
-
shape[key] = z.any();
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
return shape;
|
|
1524
|
-
}
|
|
1525
|
-
return {};
|
|
1526
|
-
}
|
|
1527
868
|
var MCPRemote = class extends MCPBase {
|
|
1528
869
|
/**
|
|
1529
870
|
* Port number the server will listen on.
|
|
@@ -1566,7 +907,7 @@ var MCPRemote = class extends MCPBase {
|
|
|
1566
907
|
*/
|
|
1567
908
|
marketDataPrices = /* @__PURE__ */ new Map();
|
|
1568
909
|
/**
|
|
1569
|
-
* Maximum number of price
|
|
910
|
+
* Maximum number of price points to store per symbol
|
|
1570
911
|
* @private
|
|
1571
912
|
*/
|
|
1572
913
|
MAX_PRICE_HISTORY = 1e5;
|
|
@@ -1588,7 +929,31 @@ var MCPRemote = class extends MCPBase {
|
|
|
1588
929
|
this.parser,
|
|
1589
930
|
this.pendingRequests,
|
|
1590
931
|
this.marketDataPrices,
|
|
1591
|
-
this.MAX_PRICE_HISTORY
|
|
932
|
+
this.MAX_PRICE_HISTORY,
|
|
933
|
+
(symbol, data) => {
|
|
934
|
+
this.mcpServer?.tool(
|
|
935
|
+
"priceUpdate",
|
|
936
|
+
{
|
|
937
|
+
description: "Price update notification",
|
|
938
|
+
schema: z.object({
|
|
939
|
+
symbol: z.string(),
|
|
940
|
+
timestamp: z.number(),
|
|
941
|
+
bid: z.number(),
|
|
942
|
+
offer: z.number(),
|
|
943
|
+
spread: z.number(),
|
|
944
|
+
volume: z.number()
|
|
945
|
+
})
|
|
946
|
+
},
|
|
947
|
+
() => ({
|
|
948
|
+
content: [
|
|
949
|
+
{
|
|
950
|
+
type: "text",
|
|
951
|
+
text: JSON.stringify({ symbol, ...data })
|
|
952
|
+
}
|
|
953
|
+
]
|
|
954
|
+
})
|
|
955
|
+
);
|
|
956
|
+
}
|
|
1592
957
|
);
|
|
1593
958
|
}
|
|
1594
959
|
});
|
|
@@ -1650,15 +1015,7 @@ var MCPRemote = class extends MCPBase {
|
|
|
1650
1015
|
);
|
|
1651
1016
|
return;
|
|
1652
1017
|
}
|
|
1653
|
-
|
|
1654
|
-
await transport.handleRequest(req, res, parsed);
|
|
1655
|
-
} catch (error) {
|
|
1656
|
-
this.logger?.log({
|
|
1657
|
-
level: "error",
|
|
1658
|
-
message: `Error handling request: ${error}`
|
|
1659
|
-
});
|
|
1660
|
-
throw error;
|
|
1661
|
-
}
|
|
1018
|
+
await transport.handleRequest(req, res, parsed);
|
|
1662
1019
|
});
|
|
1663
1020
|
} else if (req.method === "GET" || req.method === "DELETE") {
|
|
1664
1021
|
if (!sessionId || !transports[sessionId]) {
|
|
@@ -1667,20 +1024,8 @@ var MCPRemote = class extends MCPBase {
|
|
|
1667
1024
|
return;
|
|
1668
1025
|
}
|
|
1669
1026
|
const transport = transports[sessionId];
|
|
1670
|
-
|
|
1671
|
-
await transport.handleRequest(req, res);
|
|
1672
|
-
} catch (error) {
|
|
1673
|
-
this.logger?.log({
|
|
1674
|
-
level: "error",
|
|
1675
|
-
message: `Error handling ${req.method} request: ${error}`
|
|
1676
|
-
});
|
|
1677
|
-
throw error;
|
|
1678
|
-
}
|
|
1027
|
+
await transport.handleRequest(req, res);
|
|
1679
1028
|
} else {
|
|
1680
|
-
this.logger?.log({
|
|
1681
|
-
level: "error",
|
|
1682
|
-
message: `Method not allowed: ${req.method}`
|
|
1683
|
-
});
|
|
1684
1029
|
res.writeHead(405);
|
|
1685
1030
|
res.end("Method Not Allowed");
|
|
1686
1031
|
}
|
|
@@ -1714,40 +1059,69 @@ var MCPRemote = class extends MCPBase {
|
|
|
1714
1059
|
});
|
|
1715
1060
|
return;
|
|
1716
1061
|
}
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1062
|
+
this.mcpServer.tool(
|
|
1063
|
+
"tools/list",
|
|
1064
|
+
{
|
|
1065
|
+
description: "List available tools",
|
|
1066
|
+
schema: z.object({})
|
|
1067
|
+
},
|
|
1068
|
+
async () => {
|
|
1069
|
+
return {
|
|
1070
|
+
content: [
|
|
1071
|
+
{
|
|
1072
|
+
type: "text",
|
|
1073
|
+
text: JSON.stringify(
|
|
1074
|
+
Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
|
|
1075
|
+
name,
|
|
1076
|
+
description,
|
|
1077
|
+
inputSchema: schema
|
|
1078
|
+
}))
|
|
1079
|
+
)
|
|
1080
|
+
}
|
|
1081
|
+
]
|
|
1082
|
+
};
|
|
1083
|
+
}
|
|
1722
1084
|
);
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1085
|
+
this.mcpServer.tool(
|
|
1086
|
+
"tools/call",
|
|
1087
|
+
{
|
|
1088
|
+
description: "Call a tool",
|
|
1089
|
+
schema: z.object({
|
|
1090
|
+
name: z.string(),
|
|
1091
|
+
arguments: z.any(),
|
|
1092
|
+
_meta: z.object({
|
|
1093
|
+
progressToken: z.number()
|
|
1094
|
+
}).optional()
|
|
1095
|
+
})
|
|
1096
|
+
},
|
|
1097
|
+
async (request) => {
|
|
1098
|
+
const { name, arguments: args } = request;
|
|
1099
|
+
const toolHandlers = createToolHandlers(
|
|
1100
|
+
this.parser,
|
|
1101
|
+
this.verifiedOrders,
|
|
1102
|
+
this.pendingRequests,
|
|
1103
|
+
this.marketDataPrices
|
|
1104
|
+
);
|
|
1105
|
+
const handler = toolHandlers[name];
|
|
1106
|
+
if (!handler) {
|
|
1744
1107
|
return {
|
|
1745
|
-
content:
|
|
1746
|
-
|
|
1108
|
+
content: [
|
|
1109
|
+
{
|
|
1110
|
+
type: "text",
|
|
1111
|
+
text: `Tool not found: ${name}`,
|
|
1112
|
+
uri: name
|
|
1113
|
+
}
|
|
1114
|
+
],
|
|
1115
|
+
isError: true
|
|
1747
1116
|
};
|
|
1748
1117
|
}
|
|
1749
|
-
|
|
1750
|
-
|
|
1118
|
+
const result = await handler(args);
|
|
1119
|
+
return {
|
|
1120
|
+
content: result.content,
|
|
1121
|
+
isError: result.isError
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
);
|
|
1751
1125
|
}
|
|
1752
1126
|
};
|
|
1753
1127
|
export {
|