fixparser-plugin-mcp 9.1.7-c415bb75 → 9.1.7-c6228661

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.
Files changed (35) hide show
  1. package/build/cjs/MCPLocal.js +422 -10
  2. package/build/cjs/MCPLocal.js.map +4 -4
  3. package/build/cjs/MCPRemote.js +422 -66
  4. package/build/cjs/MCPRemote.js.map +4 -4
  5. package/build/cjs/index.js +422 -66
  6. package/build/cjs/index.js.map +4 -4
  7. package/build/esm/MCPLocal.mjs +422 -10
  8. package/build/esm/MCPLocal.mjs.map +4 -4
  9. package/build/esm/MCPRemote.mjs +422 -66
  10. package/build/esm/MCPRemote.mjs.map +4 -4
  11. package/build/esm/index.mjs +422 -66
  12. package/build/esm/index.mjs.map +4 -4
  13. package/build-examples/cjs/example_mcp_local.js +9 -7
  14. package/build-examples/cjs/example_mcp_local.js.map +4 -4
  15. package/build-examples/cjs/example_mcp_remote.js +9 -7
  16. package/build-examples/cjs/example_mcp_remote.js.map +4 -4
  17. package/build-examples/esm/example_mcp_local.mjs +9 -7
  18. package/build-examples/esm/example_mcp_local.mjs.map +4 -4
  19. package/build-examples/esm/example_mcp_remote.mjs +9 -7
  20. package/build-examples/esm/example_mcp_remote.mjs.map +4 -4
  21. package/package.json +2 -2
  22. package/types/MCPBase.d.ts +0 -49
  23. package/types/MCPLocal.d.ts +0 -32
  24. package/types/MCPRemote.d.ts +0 -58
  25. package/types/PluginOptions.d.ts +0 -6
  26. package/types/index.d.ts +0 -3
  27. package/types/schemas/index.d.ts +0 -15
  28. package/types/schemas/marketData.d.ts +0 -48
  29. package/types/schemas/schemas.d.ts +0 -168
  30. package/types/tools/index.d.ts +0 -17
  31. package/types/tools/marketData.d.ts +0 -40
  32. package/types/tools/order.d.ts +0 -12
  33. package/types/tools/parse.d.ts +0 -5
  34. package/types/tools/parseToJSON.d.ts +0 -5
  35. package/types/utils/messageHandler.d.ts +0 -12
@@ -310,17 +310,348 @@ 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
+ }
313
326
  }
314
327
  };
315
328
 
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
+
316
639
  // src/tools/marketData.ts
317
640
  var import_fixparser = require("fixparser");
318
641
  var import_quickchart_js = __toESM(require("quickchart-js"), 1);
319
642
  var createMarketDataRequestHandler = (parser, pendingRequests) => {
320
643
  return async (args) => {
321
644
  try {
645
+ parser.logger.log({
646
+ level: "info",
647
+ message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
648
+ });
322
649
  const response = new Promise((resolve) => {
323
650
  pendingRequests.set(args.mdReqID, resolve);
651
+ parser.logger.log({
652
+ level: "info",
653
+ message: `Registered callback for market data request ID: ${args.mdReqID}`
654
+ });
324
655
  });
325
656
  const entryTypes = args.mdEntryTypes || [
326
657
  import_fixparser.MDEntryType.Bid,
@@ -389,6 +720,10 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
389
720
  });
390
721
  const mdr = parser.createMessage(...messageFields);
391
722
  if (!parser.connected) {
723
+ parser.logger.log({
724
+ level: "error",
725
+ message: "Not connected. Cannot send market data request."
726
+ });
392
727
  return {
393
728
  content: [
394
729
  {
@@ -400,8 +735,16 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
400
735
  isError: true
401
736
  };
402
737
  }
738
+ parser.logger.log({
739
+ level: "info",
740
+ message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
741
+ });
403
742
  parser.send(mdr);
404
743
  const fixData = await response;
744
+ parser.logger.log({
745
+ level: "info",
746
+ message: `Received market data response for request ID: ${args.mdReqID}`
747
+ });
405
748
  return {
406
749
  content: [
407
750
  {
@@ -450,6 +793,9 @@ var createGetStockGraphHandler = (marketDataPrices) => {
450
793
  const offerData = priceHistory.map((point) => point.offer);
451
794
  const spreadData = priceHistory.map((point) => point.spread);
452
795
  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);
453
799
  const config = {
454
800
  type: "line",
455
801
  data: {
@@ -479,6 +825,30 @@ var createGetStockGraphHandler = (marketDataPrices) => {
479
825
  fill: false,
480
826
  tension: 0.4
481
827
  },
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
+ },
482
852
  {
483
853
  label: "Volume",
484
854
  data: volumeData,
@@ -524,7 +894,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
524
894
  content: [
525
895
  {
526
896
  type: "text",
527
- text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
897
+ text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
528
898
  uri: "getStockGraph"
529
899
  }
530
900
  ],
@@ -562,7 +932,48 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
562
932
  bid: point.bid,
563
933
  offer: point.offer,
564
934
  spread: point.spread,
565
- volume: point.volume
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
566
977
  }))
567
978
  },
568
979
  null,
@@ -577,7 +988,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
577
988
  content: [
578
989
  {
579
990
  type: "text",
580
- text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
991
+ text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
581
992
  uri: "getStockPriceHistory"
582
993
  }
583
994
  ],
@@ -685,7 +1096,7 @@ Parameters verified:
685
1096
  - Symbol: ${args.symbol}
686
1097
  - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
687
1098
 
688
- To execute this order, call the executeOrder tool with these exact same parameters.`,
1099
+ To execute this order, call the executeOrder tool with these exact same parameters. Important: The user has to explicitly confirm before executeOrder is called!`,
689
1100
  uri: "verifyOrder"
690
1101
  }
691
1102
  ]
@@ -881,16 +1292,16 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
881
1292
  executeOrder: createExecuteOrderHandler(parser, verifiedOrders, pendingRequests),
882
1293
  marketDataRequest: createMarketDataRequestHandler(parser, pendingRequests),
883
1294
  getStockGraph: createGetStockGraphHandler(marketDataPrices),
884
- getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
1295
+ getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices),
1296
+ technicalAnalysis: createTechnicalAnalysisHandler(marketDataPrices)
885
1297
  });
886
1298
 
887
1299
  // src/utils/messageHandler.ts
888
1300
  var import_fixparser3 = require("fixparser");
1301
+ function getEnumValue(enumObj, name) {
1302
+ return enumObj[name] || name;
1303
+ }
889
1304
  function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
890
- parser.logger.log({
891
- level: "info",
892
- message: `MCP Server received message: ${message.messageType}: ${message.description}`
893
- });
894
1305
  const msgType = message.messageType;
895
1306
  if (msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh || msgType === import_fixparser3.Messages.MarketDataIncrementalRefresh) {
896
1307
  const symbol = message.getField(import_fixparser3.Fields.Symbol)?.value;
@@ -948,7 +1359,8 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
948
1359
  const entryType = entry.MDEntryType;
949
1360
  const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
950
1361
  const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
951
- switch (entryType) {
1362
+ const enumValue = getEnumValue(import_fixparser3.MDEntryType, entryType);
1363
+ switch (enumValue) {
952
1364
  case import_fixparser3.MDEntryType.Bid:
953
1365
  data.bid = price;
954
1366
  break;
@@ -1340,25 +1752,13 @@ var MCPRemote = class extends MCPBase {
1340
1752
  }
1341
1753
  });
1342
1754
  this.httpServer = (0, import_node_http.createServer)(async (req, res) => {
1343
- this.logger?.log({
1344
- level: "info",
1345
- message: `Incoming request: ${req.method} ${req.url}`
1346
- });
1347
1755
  if (!req.url || !req.method) {
1348
- this.logger?.log({
1349
- level: "error",
1350
- message: "Invalid request: missing URL or method"
1351
- });
1352
1756
  res.writeHead(400);
1353
1757
  res.end("Bad Request");
1354
1758
  return;
1355
1759
  }
1356
1760
  if (req.url === "/mcp") {
1357
1761
  const sessionId = req.headers["mcp-session-id"];
1358
- this.logger?.log({
1359
- level: "info",
1360
- message: `MCP request received. Session ID: ${sessionId || "none"}, headers: ${req.headers}`
1361
- });
1362
1762
  if (req.method === "POST") {
1363
1763
  const bodyChunks = [];
1364
1764
  req.on("data", (chunk) => {
@@ -1369,47 +1769,23 @@ var MCPRemote = class extends MCPBase {
1369
1769
  const body = Buffer.concat(bodyChunks).toString();
1370
1770
  try {
1371
1771
  parsed = JSON.parse(body);
1372
- this.logger?.log({
1373
- level: "info",
1374
- message: `Parsed request body: ${JSON.stringify(parsed)}`
1375
- });
1376
1772
  } catch (err) {
1377
- this.logger?.log({
1378
- level: "error",
1379
- message: `Failed to parse JSON body: ${err}`
1380
- });
1381
1773
  res.writeHead(400);
1382
1774
  res.end(JSON.stringify({ error: "Invalid JSON" }));
1383
1775
  return;
1384
1776
  }
1385
1777
  let transport;
1386
1778
  if (sessionId && transports[sessionId]) {
1387
- this.logger?.log({
1388
- level: "info",
1389
- message: `Using existing transport for session: ${sessionId}`
1390
- });
1391
1779
  transport = transports[sessionId];
1392
1780
  } else if (!sessionId && req.method === "POST" && (0, import_types.isInitializeRequest)(parsed)) {
1393
- this.logger?.log({
1394
- level: "info",
1395
- message: "Creating new transport for initialization request"
1396
- });
1397
1781
  transport = new import_streamableHttp.StreamableHTTPServerTransport({
1398
1782
  sessionIdGenerator: () => (0, import_node_crypto.randomUUID)(),
1399
1783
  onsessioninitialized: (sessionId2) => {
1400
- this.logger?.log({
1401
- level: "info",
1402
- message: `New session initialized: ${sessionId2}`
1403
- });
1404
1784
  transports[sessionId2] = transport;
1405
1785
  }
1406
1786
  });
1407
1787
  transport.onclose = () => {
1408
1788
  if (transport.sessionId) {
1409
- this.logger?.log({
1410
- level: "info",
1411
- message: `Session closed: ${transport.sessionId}`
1412
- });
1413
1789
  delete transports[transport.sessionId];
1414
1790
  }
1415
1791
  };
@@ -1420,10 +1796,6 @@ var MCPRemote = class extends MCPBase {
1420
1796
  this.setupTools();
1421
1797
  await this.mcpServer.connect(transport);
1422
1798
  } else {
1423
- this.logger?.log({
1424
- level: "error",
1425
- message: "Invalid request: No valid session ID provided"
1426
- });
1427
1799
  res.writeHead(400, { "Content-Type": "application/json" });
1428
1800
  res.end(
1429
1801
  JSON.stringify({
@@ -1439,10 +1811,6 @@ var MCPRemote = class extends MCPBase {
1439
1811
  }
1440
1812
  try {
1441
1813
  await transport.handleRequest(req, res, parsed);
1442
- this.logger?.log({
1443
- level: "info",
1444
- message: "Request handled successfully"
1445
- });
1446
1814
  } catch (error) {
1447
1815
  this.logger?.log({
1448
1816
  level: "error",
@@ -1453,10 +1821,6 @@ var MCPRemote = class extends MCPBase {
1453
1821
  });
1454
1822
  } else if (req.method === "GET" || req.method === "DELETE") {
1455
1823
  if (!sessionId || !transports[sessionId]) {
1456
- this.logger?.log({
1457
- level: "error",
1458
- message: `Invalid session ID for ${req.method} request: ${sessionId}`
1459
- });
1460
1824
  res.writeHead(400);
1461
1825
  res.end("Invalid or missing session ID");
1462
1826
  return;
@@ -1464,10 +1828,6 @@ var MCPRemote = class extends MCPBase {
1464
1828
  const transport = transports[sessionId];
1465
1829
  try {
1466
1830
  await transport.handleRequest(req, res);
1467
- this.logger?.log({
1468
- level: "info",
1469
- message: `${req.method} request handled successfully for session: ${sessionId}`
1470
- });
1471
1831
  } catch (error) {
1472
1832
  this.logger?.log({
1473
1833
  level: "error",
@@ -1484,10 +1844,6 @@ var MCPRemote = class extends MCPBase {
1484
1844
  res.end("Method Not Allowed");
1485
1845
  }
1486
1846
  } else {
1487
- this.logger?.log({
1488
- level: "error",
1489
- message: `Not found: ${req.url}`
1490
- });
1491
1847
  res.writeHead(404);
1492
1848
  res.end("Not Found");
1493
1849
  }