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
@@ -273,17 +273,348 @@ var toolSchemas = {
273
273
  },
274
274
  required: ["symbol"]
275
275
  }
276
+ },
277
+ technicalAnalysis: {
278
+ description: "Performs comprehensive technical analysis on market data for a given symbol, including indicators like SMA, EMA, RSI, Bollinger Bands, and trading signals",
279
+ schema: {
280
+ type: "object",
281
+ properties: {
282
+ symbol: {
283
+ type: "string",
284
+ description: "The trading symbol to analyze (e.g., AAPL, MSFT, EURUSD)"
285
+ }
286
+ },
287
+ required: ["symbol"]
288
+ }
276
289
  }
277
290
  };
278
291
 
292
+ // src/tools/analytics.ts
293
+ function sum(numbers) {
294
+ return numbers.reduce((acc, val) => acc + val, 0);
295
+ }
296
+ var TechnicalAnalyzer = class {
297
+ prices;
298
+ volumes;
299
+ highs;
300
+ lows;
301
+ constructor(data) {
302
+ this.prices = data.map((d) => d.trade > 0 ? d.trade : d.midPrice);
303
+ this.volumes = data.map((d) => d.volume);
304
+ this.highs = data.map((d) => d.tradingSessionHighPrice > 0 ? d.tradingSessionHighPrice : d.trade);
305
+ this.lows = data.map((d) => d.tradingSessionLowPrice > 0 ? d.tradingSessionLowPrice : d.trade);
306
+ }
307
+ // Calculate Simple Moving Average
308
+ calculateSMA(data, period) {
309
+ const sma = [];
310
+ for (let i = period - 1; i < data.length; i++) {
311
+ const sum2 = data.slice(i - period + 1, i + 1).reduce((a, b) => a + b, 0);
312
+ sma.push(sum2 / period);
313
+ }
314
+ return sma;
315
+ }
316
+ // Calculate Exponential Moving Average
317
+ calculateEMA(data, period) {
318
+ const multiplier = 2 / (period + 1);
319
+ const ema = [data[0]];
320
+ for (let i = 1; i < data.length; i++) {
321
+ ema.push(data[i] * multiplier + ema[i - 1] * (1 - multiplier));
322
+ }
323
+ return ema;
324
+ }
325
+ // Calculate RSI
326
+ calculateRSI(data, period = 14) {
327
+ if (data.length < period + 1) return [];
328
+ const changes = [];
329
+ for (let i = 1; i < data.length; i++) {
330
+ changes.push(data[i] - data[i - 1]);
331
+ }
332
+ const gains = changes.map((change) => change > 0 ? change : 0);
333
+ const losses = changes.map((change) => change < 0 ? Math.abs(change) : 0);
334
+ let avgGain = gains.slice(0, period).reduce((a, b) => a + b, 0) / period;
335
+ let avgLoss = losses.slice(0, period).reduce((a, b) => a + b, 0) / period;
336
+ const rsi = [];
337
+ for (let i = period; i < changes.length; i++) {
338
+ const rs = avgGain / avgLoss;
339
+ rsi.push(100 - 100 / (1 + rs));
340
+ avgGain = (avgGain * (period - 1) + gains[i]) / period;
341
+ avgLoss = (avgLoss * (period - 1) + losses[i]) / period;
342
+ }
343
+ return rsi;
344
+ }
345
+ // Calculate Bollinger Bands
346
+ calculateBollingerBands(data, period = 20, stdDev = 2) {
347
+ if (data.length < period) return [];
348
+ const sma = this.calculateSMA(data, period);
349
+ const bands = [];
350
+ for (let i = 0; i < sma.length; i++) {
351
+ const dataSlice = data.slice(i, i + period);
352
+ const mean = sma[i];
353
+ const variance = dataSlice.reduce((sum2, price) => sum2 + (price - mean) ** 2, 0) / period;
354
+ const standardDeviation = Math.sqrt(variance);
355
+ bands.push({
356
+ upper: mean + standardDeviation * stdDev,
357
+ middle: mean,
358
+ lower: mean - standardDeviation * stdDev
359
+ });
360
+ }
361
+ return bands;
362
+ }
363
+ // Calculate maximum drawdown
364
+ calculateMaxDrawdown(prices) {
365
+ let maxPrice = prices[0];
366
+ let maxDrawdown = 0;
367
+ for (let i = 1; i < prices.length; i++) {
368
+ if (prices[i] > maxPrice) {
369
+ maxPrice = prices[i];
370
+ }
371
+ const drawdown = (maxPrice - prices[i]) / maxPrice;
372
+ if (drawdown > maxDrawdown) {
373
+ maxDrawdown = drawdown;
374
+ }
375
+ }
376
+ return maxDrawdown;
377
+ }
378
+ // Calculate price changes for volatility
379
+ calculatePriceChanges() {
380
+ const changes = [];
381
+ for (let i = 1; i < this.prices.length; i++) {
382
+ changes.push((this.prices[i] - this.prices[i - 1]) / this.prices[i - 1]);
383
+ }
384
+ return changes;
385
+ }
386
+ // Generate comprehensive market analysis
387
+ analyze() {
388
+ const currentPrice = this.prices[this.prices.length - 1];
389
+ const startPrice = this.prices[0];
390
+ const sessionHigh = Math.max(...this.highs);
391
+ const sessionLow = Math.min(...this.lows);
392
+ const totalVolume = sum(this.volumes);
393
+ const avgVolume = totalVolume / this.volumes.length;
394
+ const priceChanges = this.calculatePriceChanges();
395
+ const volatility = priceChanges.length > 0 ? Math.sqrt(
396
+ priceChanges.reduce((sum2, change) => sum2 + change ** 2, 0) / priceChanges.length
397
+ ) * Math.sqrt(252) * 100 : 0;
398
+ const sessionReturn = (currentPrice - startPrice) / startPrice * 100;
399
+ const pricePosition = (currentPrice - sessionLow) / (sessionHigh - sessionLow) * 100;
400
+ const trueVWAP = this.prices.reduce((sum2, price, i) => sum2 + price * this.volumes[i], 0) / totalVolume;
401
+ 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;
402
+ 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;
403
+ const maxDrawdown = this.calculateMaxDrawdown(this.prices);
404
+ return {
405
+ currentPrice,
406
+ startPrice,
407
+ sessionHigh,
408
+ sessionLow,
409
+ totalVolume,
410
+ avgVolume,
411
+ volatility,
412
+ sessionReturn,
413
+ pricePosition,
414
+ trueVWAP,
415
+ momentum5,
416
+ momentum10,
417
+ maxDrawdown
418
+ };
419
+ }
420
+ // Generate technical indicators
421
+ getTechnicalIndicators() {
422
+ return {
423
+ sma5: this.calculateSMA(this.prices, 5),
424
+ sma10: this.calculateSMA(this.prices, 10),
425
+ ema8: this.calculateEMA(this.prices, 8),
426
+ ema21: this.calculateEMA(this.prices, 21),
427
+ rsi: this.calculateRSI(this.prices, 14),
428
+ bollinger: this.calculateBollingerBands(this.prices, 20, 2)
429
+ };
430
+ }
431
+ // Generate trading signals
432
+ generateSignals() {
433
+ const analysis = this.analyze();
434
+ let bullishSignals = 0;
435
+ let bearishSignals = 0;
436
+ const signals = [];
437
+ if (analysis.currentPrice > analysis.trueVWAP) {
438
+ signals.push(
439
+ `\u2713 BULLISH: Price above VWAP (+${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
440
+ );
441
+ bullishSignals++;
442
+ } else {
443
+ signals.push(
444
+ `\u2717 BEARISH: Price below VWAP (${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
445
+ );
446
+ bearishSignals++;
447
+ }
448
+ if (analysis.momentum5 > 0 && analysis.momentum10 > 0) {
449
+ signals.push("\u2713 BULLISH: Positive momentum on both timeframes");
450
+ bullishSignals++;
451
+ } else if (analysis.momentum5 < 0 && analysis.momentum10 < 0) {
452
+ signals.push("\u2717 BEARISH: Negative momentum on both timeframes");
453
+ bearishSignals++;
454
+ } else {
455
+ signals.push("\u25D0 MIXED: Conflicting momentum signals");
456
+ }
457
+ const currentVolume = this.volumes[this.volumes.length - 1];
458
+ const volumeRatio = currentVolume / analysis.avgVolume;
459
+ if (volumeRatio > 1.2 && analysis.sessionReturn > 0) {
460
+ signals.push("\u2713 BULLISH: Above-average volume supporting upward move");
461
+ bullishSignals++;
462
+ } else if (volumeRatio > 1.2 && analysis.sessionReturn < 0) {
463
+ signals.push("\u2717 BEARISH: Above-average volume supporting downward move");
464
+ bearishSignals++;
465
+ } else {
466
+ signals.push("\u25D0 NEUTRAL: Volume not providing clear direction");
467
+ }
468
+ if (analysis.pricePosition > 65 && analysis.volatility > 30) {
469
+ signals.push("\u2717 BEARISH: High in range with elevated volatility - reversal risk");
470
+ bearishSignals++;
471
+ } else if (analysis.pricePosition < 35 && analysis.volatility > 30) {
472
+ signals.push("\u2713 BULLISH: Low in range with volatility - potential bounce");
473
+ bullishSignals++;
474
+ } else {
475
+ signals.push("\u25D0 NEUTRAL: Price position and volatility not extreme");
476
+ }
477
+ return { bullishSignals, bearishSignals, signals };
478
+ }
479
+ // Generate comprehensive JSON analysis
480
+ generateJSONAnalysis(symbol) {
481
+ const analysis = this.analyze();
482
+ const indicators = this.getTechnicalIndicators();
483
+ const signals = this.generateSignals();
484
+ const currentSMA5 = indicators.sma5.length > 0 ? indicators.sma5[indicators.sma5.length - 1] : null;
485
+ const currentSMA10 = indicators.sma10.length > 0 ? indicators.sma10[indicators.sma10.length - 1] : null;
486
+ const currentEMA8 = indicators.ema8[indicators.ema8.length - 1];
487
+ const currentEMA21 = indicators.ema21[indicators.ema21.length - 1];
488
+ const currentRSI = indicators.rsi.length > 0 ? indicators.rsi[indicators.rsi.length - 1] : null;
489
+ const currentBB = indicators.bollinger.length > 0 ? indicators.bollinger[indicators.bollinger.length - 1] : null;
490
+ const currentVolume = this.volumes[this.volumes.length - 1];
491
+ const volumeRatio = currentVolume / analysis.avgVolume;
492
+ const currentDrawdown = (analysis.sessionHigh - analysis.currentPrice) / analysis.sessionHigh * 100;
493
+ const rangeWidth = (analysis.sessionHigh - analysis.sessionLow) / analysis.sessionLow * 100;
494
+ const priceVsVWAP = (analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100;
495
+ const totalScore = signals.bullishSignals - signals.bearishSignals;
496
+ const overallSignal = totalScore > 0 ? "BULLISH_BIAS" : totalScore < 0 ? "BEARISH_BIAS" : "NEUTRAL";
497
+ const targetEntry = Math.max(analysis.sessionLow * 1.005, analysis.trueVWAP * 0.998);
498
+ const stopLoss = analysis.sessionLow * 0.995;
499
+ const profitTarget = analysis.sessionHigh * 0.995;
500
+ const riskRewardRatio = (profitTarget - analysis.currentPrice) / (analysis.currentPrice - stopLoss);
501
+ return {
502
+ symbol,
503
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
504
+ marketStructure: {
505
+ currentPrice: analysis.currentPrice,
506
+ startPrice: analysis.startPrice,
507
+ sessionHigh: analysis.sessionHigh,
508
+ sessionLow: analysis.sessionLow,
509
+ rangeWidth,
510
+ totalVolume: analysis.totalVolume,
511
+ sessionPerformance: analysis.sessionReturn,
512
+ positionInRange: analysis.pricePosition
513
+ },
514
+ volatility: {
515
+ impliedVolatility: analysis.volatility,
516
+ maxDrawdown: analysis.maxDrawdown * 100,
517
+ currentDrawdown
518
+ },
519
+ technicalIndicators: {
520
+ sma5: currentSMA5,
521
+ sma10: currentSMA10,
522
+ ema8: currentEMA8,
523
+ ema21: currentEMA21,
524
+ rsi: currentRSI,
525
+ bollingerBands: currentBB ? {
526
+ upper: currentBB.upper,
527
+ middle: currentBB.middle,
528
+ lower: currentBB.lower,
529
+ position: (analysis.currentPrice - currentBB.lower) / (currentBB.upper - currentBB.lower) * 100
530
+ } : null
531
+ },
532
+ volumeAnalysis: {
533
+ currentVolume,
534
+ averageVolume: Math.round(analysis.avgVolume),
535
+ volumeRatio,
536
+ trueVWAP: analysis.trueVWAP,
537
+ priceVsVWAP
538
+ },
539
+ momentum: {
540
+ momentum5: analysis.momentum5,
541
+ momentum10: analysis.momentum10,
542
+ sessionROC: analysis.sessionReturn
543
+ },
544
+ tradingSignals: {
545
+ ...signals,
546
+ overallSignal,
547
+ signalScore: totalScore
548
+ },
549
+ riskManagement: {
550
+ targetEntry,
551
+ stopLoss,
552
+ profitTarget,
553
+ riskRewardRatio
554
+ }
555
+ };
556
+ }
557
+ };
558
+ var createTechnicalAnalysisHandler = (marketDataPrices) => {
559
+ return async (args) => {
560
+ try {
561
+ const symbol = args.symbol;
562
+ const priceHistory = marketDataPrices.get(symbol) || [];
563
+ if (priceHistory.length === 0) {
564
+ return {
565
+ content: [
566
+ {
567
+ type: "text",
568
+ text: `No price data available for ${symbol}. Please request market data first.`,
569
+ uri: "technicalAnalysis"
570
+ }
571
+ ]
572
+ };
573
+ }
574
+ const analyzer = new TechnicalAnalyzer(priceHistory);
575
+ const analysis = analyzer.generateJSONAnalysis(symbol);
576
+ return {
577
+ content: [
578
+ {
579
+ type: "text",
580
+ text: `Technical Analysis for ${symbol}:
581
+
582
+ ${JSON.stringify(analysis, null, 2)}`,
583
+ uri: "technicalAnalysis"
584
+ }
585
+ ]
586
+ };
587
+ } catch (error) {
588
+ return {
589
+ content: [
590
+ {
591
+ type: "text",
592
+ text: `Error performing technical analysis: ${error instanceof Error ? error.message : "Unknown error"}`,
593
+ uri: "technicalAnalysis"
594
+ }
595
+ ],
596
+ isError: true
597
+ };
598
+ }
599
+ };
600
+ };
601
+
279
602
  // src/tools/marketData.ts
280
603
  import { Field, Fields, MDEntryType, Messages } from "fixparser";
281
604
  import QuickChart from "quickchart-js";
282
605
  var createMarketDataRequestHandler = (parser, pendingRequests) => {
283
606
  return async (args) => {
284
607
  try {
608
+ parser.logger.log({
609
+ level: "info",
610
+ message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
611
+ });
285
612
  const response = new Promise((resolve) => {
286
613
  pendingRequests.set(args.mdReqID, resolve);
614
+ parser.logger.log({
615
+ level: "info",
616
+ message: `Registered callback for market data request ID: ${args.mdReqID}`
617
+ });
287
618
  });
288
619
  const entryTypes = args.mdEntryTypes || [
289
620
  MDEntryType.Bid,
@@ -352,6 +683,10 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
352
683
  });
353
684
  const mdr = parser.createMessage(...messageFields);
354
685
  if (!parser.connected) {
686
+ parser.logger.log({
687
+ level: "error",
688
+ message: "Not connected. Cannot send market data request."
689
+ });
355
690
  return {
356
691
  content: [
357
692
  {
@@ -363,8 +698,16 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
363
698
  isError: true
364
699
  };
365
700
  }
701
+ parser.logger.log({
702
+ level: "info",
703
+ message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
704
+ });
366
705
  parser.send(mdr);
367
706
  const fixData = await response;
707
+ parser.logger.log({
708
+ level: "info",
709
+ message: `Received market data response for request ID: ${args.mdReqID}`
710
+ });
368
711
  return {
369
712
  content: [
370
713
  {
@@ -413,6 +756,9 @@ var createGetStockGraphHandler = (marketDataPrices) => {
413
756
  const offerData = priceHistory.map((point) => point.offer);
414
757
  const spreadData = priceHistory.map((point) => point.spread);
415
758
  const volumeData = priceHistory.map((point) => point.volume);
759
+ const tradeData = priceHistory.map((point) => point.trade);
760
+ const vwapData = priceHistory.map((point) => point.vwap);
761
+ const twapData = priceHistory.map((point) => point.twap);
416
762
  const config = {
417
763
  type: "line",
418
764
  data: {
@@ -442,6 +788,30 @@ var createGetStockGraphHandler = (marketDataPrices) => {
442
788
  fill: false,
443
789
  tension: 0.4
444
790
  },
791
+ {
792
+ label: "Trade",
793
+ data: tradeData,
794
+ borderColor: "#ffc107",
795
+ backgroundColor: "rgba(255, 193, 7, 0.1)",
796
+ fill: false,
797
+ tension: 0.4
798
+ },
799
+ {
800
+ label: "VWAP",
801
+ data: vwapData,
802
+ borderColor: "#17a2b8",
803
+ backgroundColor: "rgba(23, 162, 184, 0.1)",
804
+ fill: false,
805
+ tension: 0.4
806
+ },
807
+ {
808
+ label: "TWAP",
809
+ data: twapData,
810
+ borderColor: "#6610f2",
811
+ backgroundColor: "rgba(102, 16, 242, 0.1)",
812
+ fill: false,
813
+ tension: 0.4
814
+ },
445
815
  {
446
816
  label: "Volume",
447
817
  data: volumeData,
@@ -487,7 +857,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
487
857
  content: [
488
858
  {
489
859
  type: "text",
490
- text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
860
+ text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
491
861
  uri: "getStockGraph"
492
862
  }
493
863
  ],
@@ -525,7 +895,48 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
525
895
  bid: point.bid,
526
896
  offer: point.offer,
527
897
  spread: point.spread,
528
- volume: point.volume
898
+ volume: point.volume,
899
+ trade: point.trade,
900
+ indexValue: point.indexValue,
901
+ openingPrice: point.openingPrice,
902
+ closingPrice: point.closingPrice,
903
+ settlementPrice: point.settlementPrice,
904
+ tradingSessionHighPrice: point.tradingSessionHighPrice,
905
+ tradingSessionLowPrice: point.tradingSessionLowPrice,
906
+ vwap: point.vwap,
907
+ imbalance: point.imbalance,
908
+ openInterest: point.openInterest,
909
+ compositeUnderlyingPrice: point.compositeUnderlyingPrice,
910
+ simulatedSellPrice: point.simulatedSellPrice,
911
+ simulatedBuyPrice: point.simulatedBuyPrice,
912
+ marginRate: point.marginRate,
913
+ midPrice: point.midPrice,
914
+ emptyBook: point.emptyBook,
915
+ settleHighPrice: point.settleHighPrice,
916
+ settleLowPrice: point.settleLowPrice,
917
+ priorSettlePrice: point.priorSettlePrice,
918
+ sessionHighBid: point.sessionHighBid,
919
+ sessionLowOffer: point.sessionLowOffer,
920
+ earlyPrices: point.earlyPrices,
921
+ auctionClearingPrice: point.auctionClearingPrice,
922
+ swapValueFactor: point.swapValueFactor,
923
+ dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
924
+ cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
925
+ dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
926
+ cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
927
+ fixingPrice: point.fixingPrice,
928
+ cashRate: point.cashRate,
929
+ recoveryRate: point.recoveryRate,
930
+ recoveryRateForLong: point.recoveryRateForLong,
931
+ recoveryRateForShort: point.recoveryRateForShort,
932
+ marketBid: point.marketBid,
933
+ marketOffer: point.marketOffer,
934
+ shortSaleMinPrice: point.shortSaleMinPrice,
935
+ previousClosingPrice: point.previousClosingPrice,
936
+ thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
937
+ dailyFinancingValue: point.dailyFinancingValue,
938
+ accruedFinancingValue: point.accruedFinancingValue,
939
+ twap: point.twap
529
940
  }))
530
941
  },
531
942
  null,
@@ -540,7 +951,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
540
951
  content: [
541
952
  {
542
953
  type: "text",
543
- text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
954
+ text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
544
955
  uri: "getStockPriceHistory"
545
956
  }
546
957
  ],
@@ -648,7 +1059,7 @@ Parameters verified:
648
1059
  - Symbol: ${args.symbol}
649
1060
  - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
650
1061
 
651
- To execute this order, call the executeOrder tool with these exact same parameters.`,
1062
+ To execute this order, call the executeOrder tool with these exact same parameters. Important: The user has to explicitly confirm before executeOrder is called!`,
652
1063
  uri: "verifyOrder"
653
1064
  }
654
1065
  ]
@@ -844,16 +1255,16 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
844
1255
  executeOrder: createExecuteOrderHandler(parser, verifiedOrders, pendingRequests),
845
1256
  marketDataRequest: createMarketDataRequestHandler(parser, pendingRequests),
846
1257
  getStockGraph: createGetStockGraphHandler(marketDataPrices),
847
- getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
1258
+ getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices),
1259
+ technicalAnalysis: createTechnicalAnalysisHandler(marketDataPrices)
848
1260
  });
849
1261
 
850
1262
  // src/utils/messageHandler.ts
851
1263
  import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
1264
+ function getEnumValue(enumObj, name) {
1265
+ return enumObj[name] || name;
1266
+ }
852
1267
  function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
853
- parser.logger.log({
854
- level: "info",
855
- message: `MCP Server received message: ${message.messageType}: ${message.description}`
856
- });
857
1268
  const msgType = message.messageType;
858
1269
  if (msgType === Messages3.MarketDataSnapshotFullRefresh || msgType === Messages3.MarketDataIncrementalRefresh) {
859
1270
  const symbol = message.getField(Fields3.Symbol)?.value;
@@ -911,7 +1322,8 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
911
1322
  const entryType = entry.MDEntryType;
912
1323
  const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
913
1324
  const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
914
- switch (entryType) {
1325
+ const enumValue = getEnumValue(MDEntryType2, entryType);
1326
+ switch (enumValue) {
915
1327
  case MDEntryType2.Bid:
916
1328
  data.bid = price;
917
1329
  break;
@@ -1303,25 +1715,13 @@ var MCPRemote = class extends MCPBase {
1303
1715
  }
1304
1716
  });
1305
1717
  this.httpServer = createServer(async (req, res) => {
1306
- this.logger?.log({
1307
- level: "info",
1308
- message: `Incoming request: ${req.method} ${req.url}`
1309
- });
1310
1718
  if (!req.url || !req.method) {
1311
- this.logger?.log({
1312
- level: "error",
1313
- message: "Invalid request: missing URL or method"
1314
- });
1315
1719
  res.writeHead(400);
1316
1720
  res.end("Bad Request");
1317
1721
  return;
1318
1722
  }
1319
1723
  if (req.url === "/mcp") {
1320
1724
  const sessionId = req.headers["mcp-session-id"];
1321
- this.logger?.log({
1322
- level: "info",
1323
- message: `MCP request received. Session ID: ${sessionId || "none"}, headers: ${req.headers}`
1324
- });
1325
1725
  if (req.method === "POST") {
1326
1726
  const bodyChunks = [];
1327
1727
  req.on("data", (chunk) => {
@@ -1332,47 +1732,23 @@ var MCPRemote = class extends MCPBase {
1332
1732
  const body = Buffer.concat(bodyChunks).toString();
1333
1733
  try {
1334
1734
  parsed = JSON.parse(body);
1335
- this.logger?.log({
1336
- level: "info",
1337
- message: `Parsed request body: ${JSON.stringify(parsed)}`
1338
- });
1339
1735
  } catch (err) {
1340
- this.logger?.log({
1341
- level: "error",
1342
- message: `Failed to parse JSON body: ${err}`
1343
- });
1344
1736
  res.writeHead(400);
1345
1737
  res.end(JSON.stringify({ error: "Invalid JSON" }));
1346
1738
  return;
1347
1739
  }
1348
1740
  let transport;
1349
1741
  if (sessionId && transports[sessionId]) {
1350
- this.logger?.log({
1351
- level: "info",
1352
- message: `Using existing transport for session: ${sessionId}`
1353
- });
1354
1742
  transport = transports[sessionId];
1355
1743
  } else if (!sessionId && req.method === "POST" && isInitializeRequest(parsed)) {
1356
- this.logger?.log({
1357
- level: "info",
1358
- message: "Creating new transport for initialization request"
1359
- });
1360
1744
  transport = new StreamableHTTPServerTransport({
1361
1745
  sessionIdGenerator: () => randomUUID(),
1362
1746
  onsessioninitialized: (sessionId2) => {
1363
- this.logger?.log({
1364
- level: "info",
1365
- message: `New session initialized: ${sessionId2}`
1366
- });
1367
1747
  transports[sessionId2] = transport;
1368
1748
  }
1369
1749
  });
1370
1750
  transport.onclose = () => {
1371
1751
  if (transport.sessionId) {
1372
- this.logger?.log({
1373
- level: "info",
1374
- message: `Session closed: ${transport.sessionId}`
1375
- });
1376
1752
  delete transports[transport.sessionId];
1377
1753
  }
1378
1754
  };
@@ -1383,10 +1759,6 @@ var MCPRemote = class extends MCPBase {
1383
1759
  this.setupTools();
1384
1760
  await this.mcpServer.connect(transport);
1385
1761
  } else {
1386
- this.logger?.log({
1387
- level: "error",
1388
- message: "Invalid request: No valid session ID provided"
1389
- });
1390
1762
  res.writeHead(400, { "Content-Type": "application/json" });
1391
1763
  res.end(
1392
1764
  JSON.stringify({
@@ -1402,10 +1774,6 @@ var MCPRemote = class extends MCPBase {
1402
1774
  }
1403
1775
  try {
1404
1776
  await transport.handleRequest(req, res, parsed);
1405
- this.logger?.log({
1406
- level: "info",
1407
- message: "Request handled successfully"
1408
- });
1409
1777
  } catch (error) {
1410
1778
  this.logger?.log({
1411
1779
  level: "error",
@@ -1416,10 +1784,6 @@ var MCPRemote = class extends MCPBase {
1416
1784
  });
1417
1785
  } else if (req.method === "GET" || req.method === "DELETE") {
1418
1786
  if (!sessionId || !transports[sessionId]) {
1419
- this.logger?.log({
1420
- level: "error",
1421
- message: `Invalid session ID for ${req.method} request: ${sessionId}`
1422
- });
1423
1787
  res.writeHead(400);
1424
1788
  res.end("Invalid or missing session ID");
1425
1789
  return;
@@ -1427,10 +1791,6 @@ var MCPRemote = class extends MCPBase {
1427
1791
  const transport = transports[sessionId];
1428
1792
  try {
1429
1793
  await transport.handleRequest(req, res);
1430
- this.logger?.log({
1431
- level: "info",
1432
- message: `${req.method} request handled successfully for session: ${sessionId}`
1433
- });
1434
1794
  } catch (error) {
1435
1795
  this.logger?.log({
1436
1796
  level: "error",
@@ -1447,10 +1807,6 @@ var MCPRemote = class extends MCPBase {
1447
1807
  res.end("Method Not Allowed");
1448
1808
  }
1449
1809
  } else {
1450
- this.logger?.log({
1451
- level: "error",
1452
- message: `Not found: ${req.url}`
1453
- });
1454
1810
  res.writeHead(404);
1455
1811
  res.end("Not Found");
1456
1812
  }