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/cjs/index.js
CHANGED
|
@@ -166,7 +166,7 @@ var toolSchemas = {
|
|
|
166
166
|
}
|
|
167
167
|
},
|
|
168
168
|
executeOrder: {
|
|
169
|
-
description: "Executes a verified order. verifyOrder must be called before executeOrder.",
|
|
169
|
+
description: "Executes a verified order. verifyOrder must be called before executeOrder. user has to explicitly allow executeOrder.",
|
|
170
170
|
schema: {
|
|
171
171
|
type: "object",
|
|
172
172
|
properties: {
|
|
@@ -310,395 +310,19 @@ var toolSchemas = {
|
|
|
310
310
|
},
|
|
311
311
|
required: ["symbol"]
|
|
312
312
|
}
|
|
313
|
-
},
|
|
314
|
-
technicalAnalysis: {
|
|
315
|
-
description: "Performs comprehensive technical analysis on market data for a given symbol, including indicators like SMA, EMA, RSI, Bollinger Bands, and trading signals",
|
|
316
|
-
schema: {
|
|
317
|
-
type: "object",
|
|
318
|
-
properties: {
|
|
319
|
-
symbol: {
|
|
320
|
-
type: "string",
|
|
321
|
-
description: "The trading symbol to analyze (e.g., AAPL, MSFT, EURUSD)"
|
|
322
|
-
}
|
|
323
|
-
},
|
|
324
|
-
required: ["symbol"]
|
|
325
|
-
}
|
|
326
313
|
}
|
|
327
314
|
};
|
|
328
315
|
|
|
329
|
-
// src/tools/analytics.ts
|
|
330
|
-
function sum(numbers) {
|
|
331
|
-
return numbers.reduce((acc, val) => acc + val, 0);
|
|
332
|
-
}
|
|
333
|
-
var TechnicalAnalyzer = class {
|
|
334
|
-
prices;
|
|
335
|
-
volumes;
|
|
336
|
-
highs;
|
|
337
|
-
lows;
|
|
338
|
-
constructor(data) {
|
|
339
|
-
this.prices = data.map((d) => d.trade > 0 ? d.trade : d.midPrice);
|
|
340
|
-
this.volumes = data.map((d) => d.volume);
|
|
341
|
-
this.highs = data.map((d) => d.tradingSessionHighPrice > 0 ? d.tradingSessionHighPrice : d.trade);
|
|
342
|
-
this.lows = data.map((d) => d.tradingSessionLowPrice > 0 ? d.tradingSessionLowPrice : d.trade);
|
|
343
|
-
}
|
|
344
|
-
// Calculate Simple Moving Average
|
|
345
|
-
calculateSMA(data, period) {
|
|
346
|
-
const sma = [];
|
|
347
|
-
for (let i = period - 1; i < data.length; i++) {
|
|
348
|
-
const sum2 = data.slice(i - period + 1, i + 1).reduce((a, b) => a + b, 0);
|
|
349
|
-
sma.push(sum2 / period);
|
|
350
|
-
}
|
|
351
|
-
return sma;
|
|
352
|
-
}
|
|
353
|
-
// Calculate Exponential Moving Average
|
|
354
|
-
calculateEMA(data, period) {
|
|
355
|
-
const multiplier = 2 / (period + 1);
|
|
356
|
-
const ema = [data[0]];
|
|
357
|
-
for (let i = 1; i < data.length; i++) {
|
|
358
|
-
ema.push(data[i] * multiplier + ema[i - 1] * (1 - multiplier));
|
|
359
|
-
}
|
|
360
|
-
return ema;
|
|
361
|
-
}
|
|
362
|
-
// Calculate RSI
|
|
363
|
-
calculateRSI(data, period = 14) {
|
|
364
|
-
if (data.length < period + 1) return [];
|
|
365
|
-
const changes = [];
|
|
366
|
-
for (let i = 1; i < data.length; i++) {
|
|
367
|
-
changes.push(data[i] - data[i - 1]);
|
|
368
|
-
}
|
|
369
|
-
const gains = changes.map((change) => change > 0 ? change : 0);
|
|
370
|
-
const losses = changes.map((change) => change < 0 ? Math.abs(change) : 0);
|
|
371
|
-
let avgGain = gains.slice(0, period).reduce((a, b) => a + b, 0) / period;
|
|
372
|
-
let avgLoss = losses.slice(0, period).reduce((a, b) => a + b, 0) / period;
|
|
373
|
-
const rsi = [];
|
|
374
|
-
for (let i = period; i < changes.length; i++) {
|
|
375
|
-
const rs = avgGain / avgLoss;
|
|
376
|
-
rsi.push(100 - 100 / (1 + rs));
|
|
377
|
-
avgGain = (avgGain * (period - 1) + gains[i]) / period;
|
|
378
|
-
avgLoss = (avgLoss * (period - 1) + losses[i]) / period;
|
|
379
|
-
}
|
|
380
|
-
return rsi;
|
|
381
|
-
}
|
|
382
|
-
// Calculate Bollinger Bands
|
|
383
|
-
calculateBollingerBands(data, period = 20, stdDev = 2) {
|
|
384
|
-
if (data.length < period) return [];
|
|
385
|
-
const sma = this.calculateSMA(data, period);
|
|
386
|
-
const bands = [];
|
|
387
|
-
for (let i = 0; i < sma.length; i++) {
|
|
388
|
-
const dataSlice = data.slice(i, i + period);
|
|
389
|
-
const mean = sma[i];
|
|
390
|
-
const variance = dataSlice.reduce((sum2, price) => sum2 + (price - mean) ** 2, 0) / period;
|
|
391
|
-
const standardDeviation = Math.sqrt(variance);
|
|
392
|
-
bands.push({
|
|
393
|
-
upper: mean + standardDeviation * stdDev,
|
|
394
|
-
middle: mean,
|
|
395
|
-
lower: mean - standardDeviation * stdDev
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
return bands;
|
|
399
|
-
}
|
|
400
|
-
// Calculate maximum drawdown
|
|
401
|
-
calculateMaxDrawdown(prices) {
|
|
402
|
-
let maxPrice = prices[0];
|
|
403
|
-
let maxDrawdown = 0;
|
|
404
|
-
for (let i = 1; i < prices.length; i++) {
|
|
405
|
-
if (prices[i] > maxPrice) {
|
|
406
|
-
maxPrice = prices[i];
|
|
407
|
-
}
|
|
408
|
-
const drawdown = (maxPrice - prices[i]) / maxPrice;
|
|
409
|
-
if (drawdown > maxDrawdown) {
|
|
410
|
-
maxDrawdown = drawdown;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
return maxDrawdown;
|
|
414
|
-
}
|
|
415
|
-
// Calculate price changes for volatility
|
|
416
|
-
calculatePriceChanges() {
|
|
417
|
-
const changes = [];
|
|
418
|
-
for (let i = 1; i < this.prices.length; i++) {
|
|
419
|
-
changes.push((this.prices[i] - this.prices[i - 1]) / this.prices[i - 1]);
|
|
420
|
-
}
|
|
421
|
-
return changes;
|
|
422
|
-
}
|
|
423
|
-
// Generate comprehensive market analysis
|
|
424
|
-
analyze() {
|
|
425
|
-
const currentPrice = this.prices[this.prices.length - 1];
|
|
426
|
-
const startPrice = this.prices[0];
|
|
427
|
-
const sessionHigh = Math.max(...this.highs);
|
|
428
|
-
const sessionLow = Math.min(...this.lows);
|
|
429
|
-
const totalVolume = sum(this.volumes);
|
|
430
|
-
const avgVolume = totalVolume / this.volumes.length;
|
|
431
|
-
const priceChanges = this.calculatePriceChanges();
|
|
432
|
-
const volatility = priceChanges.length > 0 ? Math.sqrt(
|
|
433
|
-
priceChanges.reduce((sum2, change) => sum2 + change ** 2, 0) / priceChanges.length
|
|
434
|
-
) * Math.sqrt(252) * 100 : 0;
|
|
435
|
-
const sessionReturn = (currentPrice - startPrice) / startPrice * 100;
|
|
436
|
-
const pricePosition = (currentPrice - sessionLow) / (sessionHigh - sessionLow) * 100;
|
|
437
|
-
const trueVWAP = this.prices.reduce((sum2, price, i) => sum2 + price * this.volumes[i], 0) / totalVolume;
|
|
438
|
-
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;
|
|
439
|
-
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;
|
|
440
|
-
const maxDrawdown = this.calculateMaxDrawdown(this.prices);
|
|
441
|
-
return {
|
|
442
|
-
currentPrice,
|
|
443
|
-
startPrice,
|
|
444
|
-
sessionHigh,
|
|
445
|
-
sessionLow,
|
|
446
|
-
totalVolume,
|
|
447
|
-
avgVolume,
|
|
448
|
-
volatility,
|
|
449
|
-
sessionReturn,
|
|
450
|
-
pricePosition,
|
|
451
|
-
trueVWAP,
|
|
452
|
-
momentum5,
|
|
453
|
-
momentum10,
|
|
454
|
-
maxDrawdown
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
// Generate technical indicators
|
|
458
|
-
getTechnicalIndicators() {
|
|
459
|
-
return {
|
|
460
|
-
sma5: this.calculateSMA(this.prices, 5),
|
|
461
|
-
sma10: this.calculateSMA(this.prices, 10),
|
|
462
|
-
ema8: this.calculateEMA(this.prices, 8),
|
|
463
|
-
ema21: this.calculateEMA(this.prices, 21),
|
|
464
|
-
rsi: this.calculateRSI(this.prices, 14),
|
|
465
|
-
bollinger: this.calculateBollingerBands(this.prices, 20, 2)
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
// Generate trading signals
|
|
469
|
-
generateSignals() {
|
|
470
|
-
const analysis = this.analyze();
|
|
471
|
-
let bullishSignals = 0;
|
|
472
|
-
let bearishSignals = 0;
|
|
473
|
-
const signals = [];
|
|
474
|
-
if (analysis.currentPrice > analysis.trueVWAP) {
|
|
475
|
-
signals.push(
|
|
476
|
-
`\u2713 BULLISH: Price above VWAP (+${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
|
|
477
|
-
);
|
|
478
|
-
bullishSignals++;
|
|
479
|
-
} else {
|
|
480
|
-
signals.push(
|
|
481
|
-
`\u2717 BEARISH: Price below VWAP (${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
|
|
482
|
-
);
|
|
483
|
-
bearishSignals++;
|
|
484
|
-
}
|
|
485
|
-
if (analysis.momentum5 > 0 && analysis.momentum10 > 0) {
|
|
486
|
-
signals.push("\u2713 BULLISH: Positive momentum on both timeframes");
|
|
487
|
-
bullishSignals++;
|
|
488
|
-
} else if (analysis.momentum5 < 0 && analysis.momentum10 < 0) {
|
|
489
|
-
signals.push("\u2717 BEARISH: Negative momentum on both timeframes");
|
|
490
|
-
bearishSignals++;
|
|
491
|
-
} else {
|
|
492
|
-
signals.push("\u25D0 MIXED: Conflicting momentum signals");
|
|
493
|
-
}
|
|
494
|
-
const currentVolume = this.volumes[this.volumes.length - 1];
|
|
495
|
-
const volumeRatio = currentVolume / analysis.avgVolume;
|
|
496
|
-
if (volumeRatio > 1.2 && analysis.sessionReturn > 0) {
|
|
497
|
-
signals.push("\u2713 BULLISH: Above-average volume supporting upward move");
|
|
498
|
-
bullishSignals++;
|
|
499
|
-
} else if (volumeRatio > 1.2 && analysis.sessionReturn < 0) {
|
|
500
|
-
signals.push("\u2717 BEARISH: Above-average volume supporting downward move");
|
|
501
|
-
bearishSignals++;
|
|
502
|
-
} else {
|
|
503
|
-
signals.push("\u25D0 NEUTRAL: Volume not providing clear direction");
|
|
504
|
-
}
|
|
505
|
-
if (analysis.pricePosition > 65 && analysis.volatility > 30) {
|
|
506
|
-
signals.push("\u2717 BEARISH: High in range with elevated volatility - reversal risk");
|
|
507
|
-
bearishSignals++;
|
|
508
|
-
} else if (analysis.pricePosition < 35 && analysis.volatility > 30) {
|
|
509
|
-
signals.push("\u2713 BULLISH: Low in range with volatility - potential bounce");
|
|
510
|
-
bullishSignals++;
|
|
511
|
-
} else {
|
|
512
|
-
signals.push("\u25D0 NEUTRAL: Price position and volatility not extreme");
|
|
513
|
-
}
|
|
514
|
-
return { bullishSignals, bearishSignals, signals };
|
|
515
|
-
}
|
|
516
|
-
// Generate comprehensive JSON analysis
|
|
517
|
-
generateJSONAnalysis(symbol) {
|
|
518
|
-
const analysis = this.analyze();
|
|
519
|
-
const indicators = this.getTechnicalIndicators();
|
|
520
|
-
const signals = this.generateSignals();
|
|
521
|
-
const currentSMA5 = indicators.sma5.length > 0 ? indicators.sma5[indicators.sma5.length - 1] : null;
|
|
522
|
-
const currentSMA10 = indicators.sma10.length > 0 ? indicators.sma10[indicators.sma10.length - 1] : null;
|
|
523
|
-
const currentEMA8 = indicators.ema8[indicators.ema8.length - 1];
|
|
524
|
-
const currentEMA21 = indicators.ema21[indicators.ema21.length - 1];
|
|
525
|
-
const currentRSI = indicators.rsi.length > 0 ? indicators.rsi[indicators.rsi.length - 1] : null;
|
|
526
|
-
const currentBB = indicators.bollinger.length > 0 ? indicators.bollinger[indicators.bollinger.length - 1] : null;
|
|
527
|
-
const currentVolume = this.volumes[this.volumes.length - 1];
|
|
528
|
-
const volumeRatio = currentVolume / analysis.avgVolume;
|
|
529
|
-
const currentDrawdown = (analysis.sessionHigh - analysis.currentPrice) / analysis.sessionHigh * 100;
|
|
530
|
-
const rangeWidth = (analysis.sessionHigh - analysis.sessionLow) / analysis.sessionLow * 100;
|
|
531
|
-
const priceVsVWAP = (analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100;
|
|
532
|
-
const totalScore = signals.bullishSignals - signals.bearishSignals;
|
|
533
|
-
const overallSignal = totalScore > 0 ? "BULLISH_BIAS" : totalScore < 0 ? "BEARISH_BIAS" : "NEUTRAL";
|
|
534
|
-
const targetEntry = Math.max(analysis.sessionLow * 1.005, analysis.trueVWAP * 0.998);
|
|
535
|
-
const stopLoss = analysis.sessionLow * 0.995;
|
|
536
|
-
const profitTarget = analysis.sessionHigh * 0.995;
|
|
537
|
-
const riskRewardRatio = (profitTarget - analysis.currentPrice) / (analysis.currentPrice - stopLoss);
|
|
538
|
-
return {
|
|
539
|
-
symbol,
|
|
540
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
541
|
-
marketStructure: {
|
|
542
|
-
currentPrice: analysis.currentPrice,
|
|
543
|
-
startPrice: analysis.startPrice,
|
|
544
|
-
sessionHigh: analysis.sessionHigh,
|
|
545
|
-
sessionLow: analysis.sessionLow,
|
|
546
|
-
rangeWidth,
|
|
547
|
-
totalVolume: analysis.totalVolume,
|
|
548
|
-
sessionPerformance: analysis.sessionReturn,
|
|
549
|
-
positionInRange: analysis.pricePosition
|
|
550
|
-
},
|
|
551
|
-
volatility: {
|
|
552
|
-
impliedVolatility: analysis.volatility,
|
|
553
|
-
maxDrawdown: analysis.maxDrawdown * 100,
|
|
554
|
-
currentDrawdown
|
|
555
|
-
},
|
|
556
|
-
technicalIndicators: {
|
|
557
|
-
sma5: currentSMA5,
|
|
558
|
-
sma10: currentSMA10,
|
|
559
|
-
ema8: currentEMA8,
|
|
560
|
-
ema21: currentEMA21,
|
|
561
|
-
rsi: currentRSI,
|
|
562
|
-
bollingerBands: currentBB ? {
|
|
563
|
-
upper: currentBB.upper,
|
|
564
|
-
middle: currentBB.middle,
|
|
565
|
-
lower: currentBB.lower,
|
|
566
|
-
position: (analysis.currentPrice - currentBB.lower) / (currentBB.upper - currentBB.lower) * 100
|
|
567
|
-
} : null
|
|
568
|
-
},
|
|
569
|
-
volumeAnalysis: {
|
|
570
|
-
currentVolume,
|
|
571
|
-
averageVolume: Math.round(analysis.avgVolume),
|
|
572
|
-
volumeRatio,
|
|
573
|
-
trueVWAP: analysis.trueVWAP,
|
|
574
|
-
priceVsVWAP
|
|
575
|
-
},
|
|
576
|
-
momentum: {
|
|
577
|
-
momentum5: analysis.momentum5,
|
|
578
|
-
momentum10: analysis.momentum10,
|
|
579
|
-
sessionROC: analysis.sessionReturn
|
|
580
|
-
},
|
|
581
|
-
tradingSignals: {
|
|
582
|
-
...signals,
|
|
583
|
-
overallSignal,
|
|
584
|
-
signalScore: totalScore
|
|
585
|
-
},
|
|
586
|
-
riskManagement: {
|
|
587
|
-
targetEntry,
|
|
588
|
-
stopLoss,
|
|
589
|
-
profitTarget,
|
|
590
|
-
riskRewardRatio
|
|
591
|
-
}
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
};
|
|
595
|
-
var createTechnicalAnalysisHandler = (marketDataPrices) => {
|
|
596
|
-
return async (args) => {
|
|
597
|
-
try {
|
|
598
|
-
const symbol = args.symbol;
|
|
599
|
-
const priceHistory = marketDataPrices.get(symbol) || [];
|
|
600
|
-
if (priceHistory.length === 0) {
|
|
601
|
-
return {
|
|
602
|
-
content: [
|
|
603
|
-
{
|
|
604
|
-
type: "text",
|
|
605
|
-
text: `No price data available for ${symbol}. Please request market data first.`,
|
|
606
|
-
uri: "technicalAnalysis"
|
|
607
|
-
}
|
|
608
|
-
]
|
|
609
|
-
};
|
|
610
|
-
}
|
|
611
|
-
const analyzer = new TechnicalAnalyzer(priceHistory);
|
|
612
|
-
const analysis = analyzer.generateJSONAnalysis(symbol);
|
|
613
|
-
return {
|
|
614
|
-
content: [
|
|
615
|
-
{
|
|
616
|
-
type: "text",
|
|
617
|
-
text: `Technical Analysis for ${symbol}:
|
|
618
|
-
|
|
619
|
-
${JSON.stringify(analysis, null, 2)}`,
|
|
620
|
-
uri: "technicalAnalysis"
|
|
621
|
-
}
|
|
622
|
-
]
|
|
623
|
-
};
|
|
624
|
-
} catch (error) {
|
|
625
|
-
return {
|
|
626
|
-
content: [
|
|
627
|
-
{
|
|
628
|
-
type: "text",
|
|
629
|
-
text: `Error performing technical analysis: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
630
|
-
uri: "technicalAnalysis"
|
|
631
|
-
}
|
|
632
|
-
],
|
|
633
|
-
isError: true
|
|
634
|
-
};
|
|
635
|
-
}
|
|
636
|
-
};
|
|
637
|
-
};
|
|
638
|
-
|
|
639
316
|
// src/tools/marketData.ts
|
|
640
317
|
var import_fixparser = require("fixparser");
|
|
641
318
|
var import_quickchart_js = __toESM(require("quickchart-js"), 1);
|
|
642
319
|
var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
643
320
|
return async (args) => {
|
|
644
321
|
try {
|
|
645
|
-
parser.logger.log({
|
|
646
|
-
level: "info",
|
|
647
|
-
message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
|
|
648
|
-
});
|
|
649
322
|
const response = new Promise((resolve) => {
|
|
650
323
|
pendingRequests.set(args.mdReqID, resolve);
|
|
651
|
-
parser.logger.log({
|
|
652
|
-
level: "info",
|
|
653
|
-
message: `Registered callback for market data request ID: ${args.mdReqID}`
|
|
654
|
-
});
|
|
655
324
|
});
|
|
656
|
-
const entryTypes = args.mdEntryTypes || [
|
|
657
|
-
import_fixparser.MDEntryType.Bid,
|
|
658
|
-
import_fixparser.MDEntryType.Offer,
|
|
659
|
-
import_fixparser.MDEntryType.Trade,
|
|
660
|
-
import_fixparser.MDEntryType.IndexValue,
|
|
661
|
-
import_fixparser.MDEntryType.OpeningPrice,
|
|
662
|
-
import_fixparser.MDEntryType.ClosingPrice,
|
|
663
|
-
import_fixparser.MDEntryType.SettlementPrice,
|
|
664
|
-
import_fixparser.MDEntryType.TradingSessionHighPrice,
|
|
665
|
-
import_fixparser.MDEntryType.TradingSessionLowPrice,
|
|
666
|
-
import_fixparser.MDEntryType.VWAP,
|
|
667
|
-
import_fixparser.MDEntryType.Imbalance,
|
|
668
|
-
import_fixparser.MDEntryType.TradeVolume,
|
|
669
|
-
import_fixparser.MDEntryType.OpenInterest,
|
|
670
|
-
import_fixparser.MDEntryType.CompositeUnderlyingPrice,
|
|
671
|
-
import_fixparser.MDEntryType.SimulatedSellPrice,
|
|
672
|
-
import_fixparser.MDEntryType.SimulatedBuyPrice,
|
|
673
|
-
import_fixparser.MDEntryType.MarginRate,
|
|
674
|
-
import_fixparser.MDEntryType.MidPrice,
|
|
675
|
-
import_fixparser.MDEntryType.EmptyBook,
|
|
676
|
-
import_fixparser.MDEntryType.SettleHighPrice,
|
|
677
|
-
import_fixparser.MDEntryType.SettleLowPrice,
|
|
678
|
-
import_fixparser.MDEntryType.PriorSettlePrice,
|
|
679
|
-
import_fixparser.MDEntryType.SessionHighBid,
|
|
680
|
-
import_fixparser.MDEntryType.SessionLowOffer,
|
|
681
|
-
import_fixparser.MDEntryType.EarlyPrices,
|
|
682
|
-
import_fixparser.MDEntryType.AuctionClearingPrice,
|
|
683
|
-
import_fixparser.MDEntryType.SwapValueFactor,
|
|
684
|
-
import_fixparser.MDEntryType.DailyValueAdjustmentForLongPositions,
|
|
685
|
-
import_fixparser.MDEntryType.CumulativeValueAdjustmentForLongPositions,
|
|
686
|
-
import_fixparser.MDEntryType.DailyValueAdjustmentForShortPositions,
|
|
687
|
-
import_fixparser.MDEntryType.CumulativeValueAdjustmentForShortPositions,
|
|
688
|
-
import_fixparser.MDEntryType.FixingPrice,
|
|
689
|
-
import_fixparser.MDEntryType.CashRate,
|
|
690
|
-
import_fixparser.MDEntryType.RecoveryRate,
|
|
691
|
-
import_fixparser.MDEntryType.RecoveryRateForLong,
|
|
692
|
-
import_fixparser.MDEntryType.RecoveryRateForShort,
|
|
693
|
-
import_fixparser.MDEntryType.MarketBid,
|
|
694
|
-
import_fixparser.MDEntryType.MarketOffer,
|
|
695
|
-
import_fixparser.MDEntryType.ShortSaleMinPrice,
|
|
696
|
-
import_fixparser.MDEntryType.PreviousClosingPrice,
|
|
697
|
-
import_fixparser.MDEntryType.ThresholdLimitPriceBanding,
|
|
698
|
-
import_fixparser.MDEntryType.DailyFinancingValue,
|
|
699
|
-
import_fixparser.MDEntryType.AccruedFinancingValue,
|
|
700
|
-
import_fixparser.MDEntryType.TWAP
|
|
701
|
-
];
|
|
325
|
+
const entryTypes = args.mdEntryTypes || [import_fixparser.MDEntryType.Bid, import_fixparser.MDEntryType.Offer, import_fixparser.MDEntryType.TradeVolume];
|
|
702
326
|
const messageFields = [
|
|
703
327
|
new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.MarketDataRequest),
|
|
704
328
|
new import_fixparser.Field(import_fixparser.Fields.SenderCompID, parser.sender),
|
|
@@ -720,10 +344,6 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
|
720
344
|
});
|
|
721
345
|
const mdr = parser.createMessage(...messageFields);
|
|
722
346
|
if (!parser.connected) {
|
|
723
|
-
parser.logger.log({
|
|
724
|
-
level: "error",
|
|
725
|
-
message: "Not connected. Cannot send market data request."
|
|
726
|
-
});
|
|
727
347
|
return {
|
|
728
348
|
content: [
|
|
729
349
|
{
|
|
@@ -735,16 +355,8 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
|
735
355
|
isError: true
|
|
736
356
|
};
|
|
737
357
|
}
|
|
738
|
-
parser.logger.log({
|
|
739
|
-
level: "info",
|
|
740
|
-
message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
|
|
741
|
-
});
|
|
742
358
|
parser.send(mdr);
|
|
743
359
|
const fixData = await response;
|
|
744
|
-
parser.logger.log({
|
|
745
|
-
level: "info",
|
|
746
|
-
message: `Received market data response for request ID: ${args.mdReqID}`
|
|
747
|
-
});
|
|
748
360
|
return {
|
|
749
361
|
content: [
|
|
750
362
|
{
|
|
@@ -793,9 +405,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
793
405
|
const offerData = priceHistory.map((point) => point.offer);
|
|
794
406
|
const spreadData = priceHistory.map((point) => point.spread);
|
|
795
407
|
const volumeData = priceHistory.map((point) => point.volume);
|
|
796
|
-
const tradeData = priceHistory.map((point) => point.trade);
|
|
797
|
-
const vwapData = priceHistory.map((point) => point.vwap);
|
|
798
|
-
const twapData = priceHistory.map((point) => point.twap);
|
|
799
408
|
const config = {
|
|
800
409
|
type: "line",
|
|
801
410
|
data: {
|
|
@@ -825,30 +434,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
825
434
|
fill: false,
|
|
826
435
|
tension: 0.4
|
|
827
436
|
},
|
|
828
|
-
{
|
|
829
|
-
label: "Trade",
|
|
830
|
-
data: tradeData,
|
|
831
|
-
borderColor: "#ffc107",
|
|
832
|
-
backgroundColor: "rgba(255, 193, 7, 0.1)",
|
|
833
|
-
fill: false,
|
|
834
|
-
tension: 0.4
|
|
835
|
-
},
|
|
836
|
-
{
|
|
837
|
-
label: "VWAP",
|
|
838
|
-
data: vwapData,
|
|
839
|
-
borderColor: "#17a2b8",
|
|
840
|
-
backgroundColor: "rgba(23, 162, 184, 0.1)",
|
|
841
|
-
fill: false,
|
|
842
|
-
tension: 0.4
|
|
843
|
-
},
|
|
844
|
-
{
|
|
845
|
-
label: "TWAP",
|
|
846
|
-
data: twapData,
|
|
847
|
-
borderColor: "#6610f2",
|
|
848
|
-
backgroundColor: "rgba(102, 16, 242, 0.1)",
|
|
849
|
-
fill: false,
|
|
850
|
-
tension: 0.4
|
|
851
|
-
},
|
|
852
437
|
{
|
|
853
438
|
label: "Volume",
|
|
854
439
|
data: volumeData,
|
|
@@ -894,7 +479,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
894
479
|
content: [
|
|
895
480
|
{
|
|
896
481
|
type: "text",
|
|
897
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to generate
|
|
482
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
|
|
898
483
|
uri: "getStockGraph"
|
|
899
484
|
}
|
|
900
485
|
],
|
|
@@ -932,48 +517,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
|
|
|
932
517
|
bid: point.bid,
|
|
933
518
|
offer: point.offer,
|
|
934
519
|
spread: point.spread,
|
|
935
|
-
volume: point.volume
|
|
936
|
-
trade: point.trade,
|
|
937
|
-
indexValue: point.indexValue,
|
|
938
|
-
openingPrice: point.openingPrice,
|
|
939
|
-
closingPrice: point.closingPrice,
|
|
940
|
-
settlementPrice: point.settlementPrice,
|
|
941
|
-
tradingSessionHighPrice: point.tradingSessionHighPrice,
|
|
942
|
-
tradingSessionLowPrice: point.tradingSessionLowPrice,
|
|
943
|
-
vwap: point.vwap,
|
|
944
|
-
imbalance: point.imbalance,
|
|
945
|
-
openInterest: point.openInterest,
|
|
946
|
-
compositeUnderlyingPrice: point.compositeUnderlyingPrice,
|
|
947
|
-
simulatedSellPrice: point.simulatedSellPrice,
|
|
948
|
-
simulatedBuyPrice: point.simulatedBuyPrice,
|
|
949
|
-
marginRate: point.marginRate,
|
|
950
|
-
midPrice: point.midPrice,
|
|
951
|
-
emptyBook: point.emptyBook,
|
|
952
|
-
settleHighPrice: point.settleHighPrice,
|
|
953
|
-
settleLowPrice: point.settleLowPrice,
|
|
954
|
-
priorSettlePrice: point.priorSettlePrice,
|
|
955
|
-
sessionHighBid: point.sessionHighBid,
|
|
956
|
-
sessionLowOffer: point.sessionLowOffer,
|
|
957
|
-
earlyPrices: point.earlyPrices,
|
|
958
|
-
auctionClearingPrice: point.auctionClearingPrice,
|
|
959
|
-
swapValueFactor: point.swapValueFactor,
|
|
960
|
-
dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
|
|
961
|
-
cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
|
|
962
|
-
dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
|
|
963
|
-
cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
|
|
964
|
-
fixingPrice: point.fixingPrice,
|
|
965
|
-
cashRate: point.cashRate,
|
|
966
|
-
recoveryRate: point.recoveryRate,
|
|
967
|
-
recoveryRateForLong: point.recoveryRateForLong,
|
|
968
|
-
recoveryRateForShort: point.recoveryRateForShort,
|
|
969
|
-
marketBid: point.marketBid,
|
|
970
|
-
marketOffer: point.marketOffer,
|
|
971
|
-
shortSaleMinPrice: point.shortSaleMinPrice,
|
|
972
|
-
previousClosingPrice: point.previousClosingPrice,
|
|
973
|
-
thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
|
|
974
|
-
dailyFinancingValue: point.dailyFinancingValue,
|
|
975
|
-
accruedFinancingValue: point.accruedFinancingValue,
|
|
976
|
-
twap: point.twap
|
|
520
|
+
volume: point.volume
|
|
977
521
|
}))
|
|
978
522
|
},
|
|
979
523
|
null,
|
|
@@ -988,7 +532,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
|
|
|
988
532
|
content: [
|
|
989
533
|
{
|
|
990
534
|
type: "text",
|
|
991
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
|
|
535
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
|
|
992
536
|
uri: "getStockPriceHistory"
|
|
993
537
|
}
|
|
994
538
|
],
|
|
@@ -1096,7 +640,7 @@ Parameters verified:
|
|
|
1096
640
|
- Symbol: ${args.symbol}
|
|
1097
641
|
- TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
|
|
1098
642
|
|
|
1099
|
-
To execute this order, call the executeOrder tool with these exact same parameters
|
|
643
|
+
To execute this order, call the executeOrder tool with these exact same parameters.`,
|
|
1100
644
|
uri: "verifyOrder"
|
|
1101
645
|
}
|
|
1102
646
|
]
|
|
@@ -1292,210 +836,48 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
|
|
|
1292
836
|
executeOrder: createExecuteOrderHandler(parser, verifiedOrders, pendingRequests),
|
|
1293
837
|
marketDataRequest: createMarketDataRequestHandler(parser, pendingRequests),
|
|
1294
838
|
getStockGraph: createGetStockGraphHandler(marketDataPrices),
|
|
1295
|
-
getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
|
|
1296
|
-
technicalAnalysis: createTechnicalAnalysisHandler(marketDataPrices)
|
|
839
|
+
getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
|
|
1297
840
|
});
|
|
1298
841
|
|
|
1299
842
|
// src/utils/messageHandler.ts
|
|
1300
843
|
var import_fixparser3 = require("fixparser");
|
|
1301
|
-
function getEnumValue(enumObj, name) {
|
|
1302
|
-
return enumObj[name] || name;
|
|
1303
|
-
}
|
|
1304
844
|
function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
|
|
845
|
+
parser.logger.log({
|
|
846
|
+
level: "info",
|
|
847
|
+
message: `MCP Server received message: ${message.messageType}: ${message.description}`
|
|
848
|
+
});
|
|
1305
849
|
const msgType = message.messageType;
|
|
1306
|
-
if (msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh
|
|
850
|
+
if (msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh) {
|
|
1307
851
|
const symbol = message.getField(import_fixparser3.Fields.Symbol)?.value;
|
|
1308
|
-
const
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
compositeUnderlyingPrice: 0,
|
|
1327
|
-
simulatedSellPrice: 0,
|
|
1328
|
-
simulatedBuyPrice: 0,
|
|
1329
|
-
marginRate: 0,
|
|
1330
|
-
midPrice: 0,
|
|
1331
|
-
emptyBook: 0,
|
|
1332
|
-
settleHighPrice: 0,
|
|
1333
|
-
settleLowPrice: 0,
|
|
1334
|
-
priorSettlePrice: 0,
|
|
1335
|
-
sessionHighBid: 0,
|
|
1336
|
-
sessionLowOffer: 0,
|
|
1337
|
-
earlyPrices: 0,
|
|
1338
|
-
auctionClearingPrice: 0,
|
|
1339
|
-
swapValueFactor: 0,
|
|
1340
|
-
dailyValueAdjustmentForLongPositions: 0,
|
|
1341
|
-
cumulativeValueAdjustmentForLongPositions: 0,
|
|
1342
|
-
dailyValueAdjustmentForShortPositions: 0,
|
|
1343
|
-
cumulativeValueAdjustmentForShortPositions: 0,
|
|
1344
|
-
fixingPrice: 0,
|
|
1345
|
-
cashRate: 0,
|
|
1346
|
-
recoveryRate: 0,
|
|
1347
|
-
recoveryRateForLong: 0,
|
|
1348
|
-
recoveryRateForShort: 0,
|
|
1349
|
-
marketBid: 0,
|
|
1350
|
-
marketOffer: 0,
|
|
1351
|
-
shortSaleMinPrice: 0,
|
|
1352
|
-
previousClosingPrice: 0,
|
|
1353
|
-
thresholdLimitPriceBanding: 0,
|
|
1354
|
-
dailyFinancingValue: 0,
|
|
1355
|
-
accruedFinancingValue: 0,
|
|
1356
|
-
twap: 0
|
|
1357
|
-
};
|
|
1358
|
-
for (const entry of entries) {
|
|
1359
|
-
const entryType = entry.MDEntryType;
|
|
1360
|
-
const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
|
|
1361
|
-
const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
|
|
1362
|
-
const enumValue = getEnumValue(import_fixparser3.MDEntryType, entryType);
|
|
1363
|
-
switch (enumValue) {
|
|
1364
|
-
case import_fixparser3.MDEntryType.Bid:
|
|
1365
|
-
data.bid = price;
|
|
1366
|
-
break;
|
|
1367
|
-
case import_fixparser3.MDEntryType.Offer:
|
|
1368
|
-
data.offer = price;
|
|
1369
|
-
break;
|
|
1370
|
-
case import_fixparser3.MDEntryType.Trade:
|
|
1371
|
-
data.trade = price;
|
|
1372
|
-
break;
|
|
1373
|
-
case import_fixparser3.MDEntryType.IndexValue:
|
|
1374
|
-
data.indexValue = price;
|
|
1375
|
-
break;
|
|
1376
|
-
case import_fixparser3.MDEntryType.OpeningPrice:
|
|
1377
|
-
data.openingPrice = price;
|
|
1378
|
-
break;
|
|
1379
|
-
case import_fixparser3.MDEntryType.ClosingPrice:
|
|
1380
|
-
data.closingPrice = price;
|
|
1381
|
-
break;
|
|
1382
|
-
case import_fixparser3.MDEntryType.SettlementPrice:
|
|
1383
|
-
data.settlementPrice = price;
|
|
1384
|
-
break;
|
|
1385
|
-
case import_fixparser3.MDEntryType.TradingSessionHighPrice:
|
|
1386
|
-
data.tradingSessionHighPrice = price;
|
|
1387
|
-
break;
|
|
1388
|
-
case import_fixparser3.MDEntryType.TradingSessionLowPrice:
|
|
1389
|
-
data.tradingSessionLowPrice = price;
|
|
1390
|
-
break;
|
|
1391
|
-
case import_fixparser3.MDEntryType.VWAP:
|
|
1392
|
-
data.vwap = price;
|
|
1393
|
-
break;
|
|
1394
|
-
case import_fixparser3.MDEntryType.Imbalance:
|
|
1395
|
-
data.imbalance = size;
|
|
1396
|
-
break;
|
|
1397
|
-
case import_fixparser3.MDEntryType.TradeVolume:
|
|
1398
|
-
data.volume = size;
|
|
1399
|
-
break;
|
|
1400
|
-
case import_fixparser3.MDEntryType.OpenInterest:
|
|
1401
|
-
data.openInterest = size;
|
|
1402
|
-
break;
|
|
1403
|
-
case import_fixparser3.MDEntryType.CompositeUnderlyingPrice:
|
|
1404
|
-
data.compositeUnderlyingPrice = price;
|
|
1405
|
-
break;
|
|
1406
|
-
case import_fixparser3.MDEntryType.SimulatedSellPrice:
|
|
1407
|
-
data.simulatedSellPrice = price;
|
|
1408
|
-
break;
|
|
1409
|
-
case import_fixparser3.MDEntryType.SimulatedBuyPrice:
|
|
1410
|
-
data.simulatedBuyPrice = price;
|
|
1411
|
-
break;
|
|
1412
|
-
case import_fixparser3.MDEntryType.MarginRate:
|
|
1413
|
-
data.marginRate = price;
|
|
1414
|
-
break;
|
|
1415
|
-
case import_fixparser3.MDEntryType.MidPrice:
|
|
1416
|
-
data.midPrice = price;
|
|
1417
|
-
break;
|
|
1418
|
-
case import_fixparser3.MDEntryType.EmptyBook:
|
|
1419
|
-
data.emptyBook = 1;
|
|
1420
|
-
break;
|
|
1421
|
-
case import_fixparser3.MDEntryType.SettleHighPrice:
|
|
1422
|
-
data.settleHighPrice = price;
|
|
1423
|
-
break;
|
|
1424
|
-
case import_fixparser3.MDEntryType.SettleLowPrice:
|
|
1425
|
-
data.settleLowPrice = price;
|
|
1426
|
-
break;
|
|
1427
|
-
case import_fixparser3.MDEntryType.PriorSettlePrice:
|
|
1428
|
-
data.priorSettlePrice = price;
|
|
1429
|
-
break;
|
|
1430
|
-
case import_fixparser3.MDEntryType.SessionHighBid:
|
|
1431
|
-
data.sessionHighBid = price;
|
|
1432
|
-
break;
|
|
1433
|
-
case import_fixparser3.MDEntryType.SessionLowOffer:
|
|
1434
|
-
data.sessionLowOffer = price;
|
|
1435
|
-
break;
|
|
1436
|
-
case import_fixparser3.MDEntryType.EarlyPrices:
|
|
1437
|
-
data.earlyPrices = price;
|
|
1438
|
-
break;
|
|
1439
|
-
case import_fixparser3.MDEntryType.AuctionClearingPrice:
|
|
1440
|
-
data.auctionClearingPrice = price;
|
|
1441
|
-
break;
|
|
1442
|
-
case import_fixparser3.MDEntryType.SwapValueFactor:
|
|
1443
|
-
data.swapValueFactor = price;
|
|
1444
|
-
break;
|
|
1445
|
-
case import_fixparser3.MDEntryType.DailyValueAdjustmentForLongPositions:
|
|
1446
|
-
data.dailyValueAdjustmentForLongPositions = price;
|
|
1447
|
-
break;
|
|
1448
|
-
case import_fixparser3.MDEntryType.CumulativeValueAdjustmentForLongPositions:
|
|
1449
|
-
data.cumulativeValueAdjustmentForLongPositions = price;
|
|
1450
|
-
break;
|
|
1451
|
-
case import_fixparser3.MDEntryType.DailyValueAdjustmentForShortPositions:
|
|
1452
|
-
data.dailyValueAdjustmentForShortPositions = price;
|
|
1453
|
-
break;
|
|
1454
|
-
case import_fixparser3.MDEntryType.CumulativeValueAdjustmentForShortPositions:
|
|
1455
|
-
data.cumulativeValueAdjustmentForShortPositions = price;
|
|
1456
|
-
break;
|
|
1457
|
-
case import_fixparser3.MDEntryType.FixingPrice:
|
|
1458
|
-
data.fixingPrice = price;
|
|
1459
|
-
break;
|
|
1460
|
-
case import_fixparser3.MDEntryType.CashRate:
|
|
1461
|
-
data.cashRate = price;
|
|
1462
|
-
break;
|
|
1463
|
-
case import_fixparser3.MDEntryType.RecoveryRate:
|
|
1464
|
-
data.recoveryRate = price;
|
|
1465
|
-
break;
|
|
1466
|
-
case import_fixparser3.MDEntryType.RecoveryRateForLong:
|
|
1467
|
-
data.recoveryRateForLong = price;
|
|
1468
|
-
break;
|
|
1469
|
-
case import_fixparser3.MDEntryType.RecoveryRateForShort:
|
|
1470
|
-
data.recoveryRateForShort = price;
|
|
1471
|
-
break;
|
|
1472
|
-
case import_fixparser3.MDEntryType.MarketBid:
|
|
1473
|
-
data.marketBid = price;
|
|
1474
|
-
break;
|
|
1475
|
-
case import_fixparser3.MDEntryType.MarketOffer:
|
|
1476
|
-
data.marketOffer = price;
|
|
1477
|
-
break;
|
|
1478
|
-
case import_fixparser3.MDEntryType.ShortSaleMinPrice:
|
|
1479
|
-
data.shortSaleMinPrice = price;
|
|
1480
|
-
break;
|
|
1481
|
-
case import_fixparser3.MDEntryType.PreviousClosingPrice:
|
|
1482
|
-
data.previousClosingPrice = price;
|
|
1483
|
-
break;
|
|
1484
|
-
case import_fixparser3.MDEntryType.ThresholdLimitPriceBanding:
|
|
1485
|
-
data.thresholdLimitPriceBanding = price;
|
|
1486
|
-
break;
|
|
1487
|
-
case import_fixparser3.MDEntryType.DailyFinancingValue:
|
|
1488
|
-
data.dailyFinancingValue = price;
|
|
1489
|
-
break;
|
|
1490
|
-
case import_fixparser3.MDEntryType.AccruedFinancingValue:
|
|
1491
|
-
data.accruedFinancingValue = price;
|
|
1492
|
-
break;
|
|
1493
|
-
case import_fixparser3.MDEntryType.TWAP:
|
|
1494
|
-
data.twap = price;
|
|
1495
|
-
break;
|
|
852
|
+
const entries = message.getField(import_fixparser3.Fields.NoMDEntries)?.value;
|
|
853
|
+
let bid = 0;
|
|
854
|
+
let offer = 0;
|
|
855
|
+
let volume = 0;
|
|
856
|
+
const entryTypes = message.getFields(import_fixparser3.Fields.MDEntryType);
|
|
857
|
+
const entryPrices = message.getFields(import_fixparser3.Fields.MDEntryPx);
|
|
858
|
+
const entrySizes = message.getFields(import_fixparser3.Fields.MDEntrySize);
|
|
859
|
+
if (entryTypes && entryPrices && entrySizes) {
|
|
860
|
+
for (let i = 0; i < entries; i++) {
|
|
861
|
+
const entryType = entryTypes[i]?.value;
|
|
862
|
+
const entryPrice = Number.parseFloat(entryPrices[i]?.value);
|
|
863
|
+
const entrySize = Number.parseFloat(entrySizes[i]?.value);
|
|
864
|
+
if (entryType === import_fixparser3.MDEntryType.Bid) {
|
|
865
|
+
bid = entryPrice;
|
|
866
|
+
} else if (entryType === import_fixparser3.MDEntryType.Offer) {
|
|
867
|
+
offer = entryPrice;
|
|
868
|
+
}
|
|
869
|
+
volume += entrySize;
|
|
1496
870
|
}
|
|
1497
871
|
}
|
|
1498
|
-
|
|
872
|
+
const spread = offer - bid;
|
|
873
|
+
const timestamp = Date.now();
|
|
874
|
+
const data = {
|
|
875
|
+
timestamp,
|
|
876
|
+
bid,
|
|
877
|
+
offer,
|
|
878
|
+
spread,
|
|
879
|
+
volume
|
|
880
|
+
};
|
|
1499
881
|
if (!marketDataPrices.has(symbol)) {
|
|
1500
882
|
marketDataPrices.set(symbol, []);
|
|
1501
883
|
}
|
|
@@ -1505,14 +887,6 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
|
|
|
1505
887
|
prices.splice(0, prices.length - maxPriceHistory);
|
|
1506
888
|
}
|
|
1507
889
|
onPriceUpdate?.(symbol, data);
|
|
1508
|
-
const mdReqID = message.getField(import_fixparser3.Fields.MDReqID)?.value;
|
|
1509
|
-
if (mdReqID) {
|
|
1510
|
-
const callback = pendingRequests.get(mdReqID);
|
|
1511
|
-
if (callback) {
|
|
1512
|
-
callback(message);
|
|
1513
|
-
pendingRequests.delete(mdReqID);
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
890
|
} else if (msgType === import_fixparser3.Messages.ExecutionReport) {
|
|
1517
891
|
const reqId = message.getField(import_fixparser3.Fields.ClOrdID)?.value;
|
|
1518
892
|
const callback = pendingRequests.get(reqId);
|
|
@@ -1541,7 +915,7 @@ var MCPLocal = class extends MCPBase {
|
|
|
1541
915
|
*/
|
|
1542
916
|
marketDataPrices = /* @__PURE__ */ new Map();
|
|
1543
917
|
/**
|
|
1544
|
-
* Maximum number of price
|
|
918
|
+
* Maximum number of price points to store per symbol
|
|
1545
919
|
* @private
|
|
1546
920
|
*/
|
|
1547
921
|
MAX_PRICE_HISTORY = 1e5;
|
|
@@ -1650,39 +1024,6 @@ var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamable
|
|
|
1650
1024
|
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
1651
1025
|
var import_zod2 = require("zod");
|
|
1652
1026
|
var transports = {};
|
|
1653
|
-
function jsonSchemaToZod(schema) {
|
|
1654
|
-
if (schema.type === "object") {
|
|
1655
|
-
const shape = {};
|
|
1656
|
-
for (const [key, prop] of Object.entries(schema.properties || {})) {
|
|
1657
|
-
const propSchema = prop;
|
|
1658
|
-
if (propSchema.type === "string") {
|
|
1659
|
-
if (propSchema.enum) {
|
|
1660
|
-
shape[key] = import_zod2.z.enum(propSchema.enum);
|
|
1661
|
-
} else {
|
|
1662
|
-
shape[key] = import_zod2.z.string();
|
|
1663
|
-
}
|
|
1664
|
-
} else if (propSchema.type === "number") {
|
|
1665
|
-
shape[key] = import_zod2.z.number();
|
|
1666
|
-
} else if (propSchema.type === "boolean") {
|
|
1667
|
-
shape[key] = import_zod2.z.boolean();
|
|
1668
|
-
} else if (propSchema.type === "array") {
|
|
1669
|
-
if (propSchema.items.type === "string") {
|
|
1670
|
-
shape[key] = import_zod2.z.array(import_zod2.z.string());
|
|
1671
|
-
} else if (propSchema.items.type === "number") {
|
|
1672
|
-
shape[key] = import_zod2.z.array(import_zod2.z.number());
|
|
1673
|
-
} else if (propSchema.items.type === "boolean") {
|
|
1674
|
-
shape[key] = import_zod2.z.array(import_zod2.z.boolean());
|
|
1675
|
-
} else {
|
|
1676
|
-
shape[key] = import_zod2.z.array(import_zod2.z.any());
|
|
1677
|
-
}
|
|
1678
|
-
} else {
|
|
1679
|
-
shape[key] = import_zod2.z.any();
|
|
1680
|
-
}
|
|
1681
|
-
}
|
|
1682
|
-
return shape;
|
|
1683
|
-
}
|
|
1684
|
-
return {};
|
|
1685
|
-
}
|
|
1686
1027
|
var MCPRemote = class extends MCPBase {
|
|
1687
1028
|
/**
|
|
1688
1029
|
* Port number the server will listen on.
|
|
@@ -1725,7 +1066,7 @@ var MCPRemote = class extends MCPBase {
|
|
|
1725
1066
|
*/
|
|
1726
1067
|
marketDataPrices = /* @__PURE__ */ new Map();
|
|
1727
1068
|
/**
|
|
1728
|
-
* Maximum number of price
|
|
1069
|
+
* Maximum number of price points to store per symbol
|
|
1729
1070
|
* @private
|
|
1730
1071
|
*/
|
|
1731
1072
|
MAX_PRICE_HISTORY = 1e5;
|
|
@@ -1747,7 +1088,31 @@ var MCPRemote = class extends MCPBase {
|
|
|
1747
1088
|
this.parser,
|
|
1748
1089
|
this.pendingRequests,
|
|
1749
1090
|
this.marketDataPrices,
|
|
1750
|
-
this.MAX_PRICE_HISTORY
|
|
1091
|
+
this.MAX_PRICE_HISTORY,
|
|
1092
|
+
(symbol, data) => {
|
|
1093
|
+
this.mcpServer?.tool(
|
|
1094
|
+
"priceUpdate",
|
|
1095
|
+
{
|
|
1096
|
+
description: "Price update notification",
|
|
1097
|
+
schema: import_zod2.z.object({
|
|
1098
|
+
symbol: import_zod2.z.string(),
|
|
1099
|
+
timestamp: import_zod2.z.number(),
|
|
1100
|
+
bid: import_zod2.z.number(),
|
|
1101
|
+
offer: import_zod2.z.number(),
|
|
1102
|
+
spread: import_zod2.z.number(),
|
|
1103
|
+
volume: import_zod2.z.number()
|
|
1104
|
+
})
|
|
1105
|
+
},
|
|
1106
|
+
() => ({
|
|
1107
|
+
content: [
|
|
1108
|
+
{
|
|
1109
|
+
type: "text",
|
|
1110
|
+
text: JSON.stringify({ symbol, ...data })
|
|
1111
|
+
}
|
|
1112
|
+
]
|
|
1113
|
+
})
|
|
1114
|
+
);
|
|
1115
|
+
}
|
|
1751
1116
|
);
|
|
1752
1117
|
}
|
|
1753
1118
|
});
|
|
@@ -1809,15 +1174,7 @@ var MCPRemote = class extends MCPBase {
|
|
|
1809
1174
|
);
|
|
1810
1175
|
return;
|
|
1811
1176
|
}
|
|
1812
|
-
|
|
1813
|
-
await transport.handleRequest(req, res, parsed);
|
|
1814
|
-
} catch (error) {
|
|
1815
|
-
this.logger?.log({
|
|
1816
|
-
level: "error",
|
|
1817
|
-
message: `Error handling request: ${error}`
|
|
1818
|
-
});
|
|
1819
|
-
throw error;
|
|
1820
|
-
}
|
|
1177
|
+
await transport.handleRequest(req, res, parsed);
|
|
1821
1178
|
});
|
|
1822
1179
|
} else if (req.method === "GET" || req.method === "DELETE") {
|
|
1823
1180
|
if (!sessionId || !transports[sessionId]) {
|
|
@@ -1826,20 +1183,8 @@ var MCPRemote = class extends MCPBase {
|
|
|
1826
1183
|
return;
|
|
1827
1184
|
}
|
|
1828
1185
|
const transport = transports[sessionId];
|
|
1829
|
-
|
|
1830
|
-
await transport.handleRequest(req, res);
|
|
1831
|
-
} catch (error) {
|
|
1832
|
-
this.logger?.log({
|
|
1833
|
-
level: "error",
|
|
1834
|
-
message: `Error handling ${req.method} request: ${error}`
|
|
1835
|
-
});
|
|
1836
|
-
throw error;
|
|
1837
|
-
}
|
|
1186
|
+
await transport.handleRequest(req, res);
|
|
1838
1187
|
} else {
|
|
1839
|
-
this.logger?.log({
|
|
1840
|
-
level: "error",
|
|
1841
|
-
message: `Method not allowed: ${req.method}`
|
|
1842
|
-
});
|
|
1843
1188
|
res.writeHead(405);
|
|
1844
1189
|
res.end("Method Not Allowed");
|
|
1845
1190
|
}
|
|
@@ -1873,40 +1218,69 @@ var MCPRemote = class extends MCPBase {
|
|
|
1873
1218
|
});
|
|
1874
1219
|
return;
|
|
1875
1220
|
}
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1221
|
+
this.mcpServer.tool(
|
|
1222
|
+
"tools/list",
|
|
1223
|
+
{
|
|
1224
|
+
description: "List available tools",
|
|
1225
|
+
schema: import_zod2.z.object({})
|
|
1226
|
+
},
|
|
1227
|
+
async () => {
|
|
1228
|
+
return {
|
|
1229
|
+
content: [
|
|
1230
|
+
{
|
|
1231
|
+
type: "text",
|
|
1232
|
+
text: JSON.stringify(
|
|
1233
|
+
Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
|
|
1234
|
+
name,
|
|
1235
|
+
description,
|
|
1236
|
+
inputSchema: schema
|
|
1237
|
+
}))
|
|
1238
|
+
)
|
|
1239
|
+
}
|
|
1240
|
+
]
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1881
1243
|
);
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1244
|
+
this.mcpServer.tool(
|
|
1245
|
+
"tools/call",
|
|
1246
|
+
{
|
|
1247
|
+
description: "Call a tool",
|
|
1248
|
+
schema: import_zod2.z.object({
|
|
1249
|
+
name: import_zod2.z.string(),
|
|
1250
|
+
arguments: import_zod2.z.any(),
|
|
1251
|
+
_meta: import_zod2.z.object({
|
|
1252
|
+
progressToken: import_zod2.z.number()
|
|
1253
|
+
}).optional()
|
|
1254
|
+
})
|
|
1255
|
+
},
|
|
1256
|
+
async (request) => {
|
|
1257
|
+
const { name, arguments: args } = request;
|
|
1258
|
+
const toolHandlers = createToolHandlers(
|
|
1259
|
+
this.parser,
|
|
1260
|
+
this.verifiedOrders,
|
|
1261
|
+
this.pendingRequests,
|
|
1262
|
+
this.marketDataPrices
|
|
1263
|
+
);
|
|
1264
|
+
const handler = toolHandlers[name];
|
|
1265
|
+
if (!handler) {
|
|
1903
1266
|
return {
|
|
1904
|
-
content:
|
|
1905
|
-
|
|
1267
|
+
content: [
|
|
1268
|
+
{
|
|
1269
|
+
type: "text",
|
|
1270
|
+
text: `Tool not found: ${name}`,
|
|
1271
|
+
uri: name
|
|
1272
|
+
}
|
|
1273
|
+
],
|
|
1274
|
+
isError: true
|
|
1906
1275
|
};
|
|
1907
1276
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1277
|
+
const result = await handler(args);
|
|
1278
|
+
return {
|
|
1279
|
+
content: result.content,
|
|
1280
|
+
isError: result.isError
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
);
|
|
1910
1284
|
}
|
|
1911
1285
|
};
|
|
1912
1286
|
// Annotate the CommonJS export names for ESM import in node:
|