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;
@@ -1215,25 +1627,13 @@ var MCPRemote = class extends MCPBase {
1215
1627
  }
1216
1628
  });
1217
1629
  this.httpServer = (0, import_node_http.createServer)(async (req, res) => {
1218
- this.logger?.log({
1219
- level: "info",
1220
- message: `Incoming request: ${req.method} ${req.url}`
1221
- });
1222
1630
  if (!req.url || !req.method) {
1223
- this.logger?.log({
1224
- level: "error",
1225
- message: "Invalid request: missing URL or method"
1226
- });
1227
1631
  res.writeHead(400);
1228
1632
  res.end("Bad Request");
1229
1633
  return;
1230
1634
  }
1231
1635
  if (req.url === "/mcp") {
1232
1636
  const sessionId = req.headers["mcp-session-id"];
1233
- this.logger?.log({
1234
- level: "info",
1235
- message: `MCP request received. Session ID: ${sessionId || "none"}, headers: ${req.headers}`
1236
- });
1237
1637
  if (req.method === "POST") {
1238
1638
  const bodyChunks = [];
1239
1639
  req.on("data", (chunk) => {
@@ -1244,47 +1644,23 @@ var MCPRemote = class extends MCPBase {
1244
1644
  const body = Buffer.concat(bodyChunks).toString();
1245
1645
  try {
1246
1646
  parsed = JSON.parse(body);
1247
- this.logger?.log({
1248
- level: "info",
1249
- message: `Parsed request body: ${JSON.stringify(parsed)}`
1250
- });
1251
1647
  } catch (err) {
1252
- this.logger?.log({
1253
- level: "error",
1254
- message: `Failed to parse JSON body: ${err}`
1255
- });
1256
1648
  res.writeHead(400);
1257
1649
  res.end(JSON.stringify({ error: "Invalid JSON" }));
1258
1650
  return;
1259
1651
  }
1260
1652
  let transport;
1261
1653
  if (sessionId && transports[sessionId]) {
1262
- this.logger?.log({
1263
- level: "info",
1264
- message: `Using existing transport for session: ${sessionId}`
1265
- });
1266
1654
  transport = transports[sessionId];
1267
1655
  } else if (!sessionId && req.method === "POST" && (0, import_types.isInitializeRequest)(parsed)) {
1268
- this.logger?.log({
1269
- level: "info",
1270
- message: "Creating new transport for initialization request"
1271
- });
1272
1656
  transport = new import_streamableHttp.StreamableHTTPServerTransport({
1273
1657
  sessionIdGenerator: () => (0, import_node_crypto.randomUUID)(),
1274
1658
  onsessioninitialized: (sessionId2) => {
1275
- this.logger?.log({
1276
- level: "info",
1277
- message: `New session initialized: ${sessionId2}`
1278
- });
1279
1659
  transports[sessionId2] = transport;
1280
1660
  }
1281
1661
  });
1282
1662
  transport.onclose = () => {
1283
1663
  if (transport.sessionId) {
1284
- this.logger?.log({
1285
- level: "info",
1286
- message: `Session closed: ${transport.sessionId}`
1287
- });
1288
1664
  delete transports[transport.sessionId];
1289
1665
  }
1290
1666
  };
@@ -1295,10 +1671,6 @@ var MCPRemote = class extends MCPBase {
1295
1671
  this.setupTools();
1296
1672
  await this.mcpServer.connect(transport);
1297
1673
  } else {
1298
- this.logger?.log({
1299
- level: "error",
1300
- message: "Invalid request: No valid session ID provided"
1301
- });
1302
1674
  res.writeHead(400, { "Content-Type": "application/json" });
1303
1675
  res.end(
1304
1676
  JSON.stringify({
@@ -1314,10 +1686,6 @@ var MCPRemote = class extends MCPBase {
1314
1686
  }
1315
1687
  try {
1316
1688
  await transport.handleRequest(req, res, parsed);
1317
- this.logger?.log({
1318
- level: "info",
1319
- message: "Request handled successfully"
1320
- });
1321
1689
  } catch (error) {
1322
1690
  this.logger?.log({
1323
1691
  level: "error",
@@ -1328,10 +1696,6 @@ var MCPRemote = class extends MCPBase {
1328
1696
  });
1329
1697
  } else if (req.method === "GET" || req.method === "DELETE") {
1330
1698
  if (!sessionId || !transports[sessionId]) {
1331
- this.logger?.log({
1332
- level: "error",
1333
- message: `Invalid session ID for ${req.method} request: ${sessionId}`
1334
- });
1335
1699
  res.writeHead(400);
1336
1700
  res.end("Invalid or missing session ID");
1337
1701
  return;
@@ -1339,10 +1703,6 @@ var MCPRemote = class extends MCPBase {
1339
1703
  const transport = transports[sessionId];
1340
1704
  try {
1341
1705
  await transport.handleRequest(req, res);
1342
- this.logger?.log({
1343
- level: "info",
1344
- message: `${req.method} request handled successfully for session: ${sessionId}`
1345
- });
1346
1706
  } catch (error) {
1347
1707
  this.logger?.log({
1348
1708
  level: "error",
@@ -1359,10 +1719,6 @@ var MCPRemote = class extends MCPBase {
1359
1719
  res.end("Method Not Allowed");
1360
1720
  }
1361
1721
  } else {
1362
- this.logger?.log({
1363
- level: "error",
1364
- message: `Not found: ${req.url}`
1365
- });
1366
1722
  res.writeHead(404);
1367
1723
  res.end("Not Found");
1368
1724
  }