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
@@ -276,17 +276,348 @@ var toolSchemas = {
276
276
  },
277
277
  required: ["symbol"]
278
278
  }
279
+ },
280
+ technicalAnalysis: {
281
+ description: "Performs comprehensive technical analysis on market data for a given symbol, including indicators like SMA, EMA, RSI, Bollinger Bands, and trading signals",
282
+ schema: {
283
+ type: "object",
284
+ properties: {
285
+ symbol: {
286
+ type: "string",
287
+ description: "The trading symbol to analyze (e.g., AAPL, MSFT, EURUSD)"
288
+ }
289
+ },
290
+ required: ["symbol"]
291
+ }
279
292
  }
280
293
  };
281
294
 
295
+ // src/tools/analytics.ts
296
+ function sum(numbers) {
297
+ return numbers.reduce((acc, val) => acc + val, 0);
298
+ }
299
+ var TechnicalAnalyzer = class {
300
+ prices;
301
+ volumes;
302
+ highs;
303
+ lows;
304
+ constructor(data) {
305
+ this.prices = data.map((d) => d.trade > 0 ? d.trade : d.midPrice);
306
+ this.volumes = data.map((d) => d.volume);
307
+ this.highs = data.map((d) => d.tradingSessionHighPrice > 0 ? d.tradingSessionHighPrice : d.trade);
308
+ this.lows = data.map((d) => d.tradingSessionLowPrice > 0 ? d.tradingSessionLowPrice : d.trade);
309
+ }
310
+ // Calculate Simple Moving Average
311
+ calculateSMA(data, period) {
312
+ const sma = [];
313
+ for (let i = period - 1; i < data.length; i++) {
314
+ const sum2 = data.slice(i - period + 1, i + 1).reduce((a, b) => a + b, 0);
315
+ sma.push(sum2 / period);
316
+ }
317
+ return sma;
318
+ }
319
+ // Calculate Exponential Moving Average
320
+ calculateEMA(data, period) {
321
+ const multiplier = 2 / (period + 1);
322
+ const ema = [data[0]];
323
+ for (let i = 1; i < data.length; i++) {
324
+ ema.push(data[i] * multiplier + ema[i - 1] * (1 - multiplier));
325
+ }
326
+ return ema;
327
+ }
328
+ // Calculate RSI
329
+ calculateRSI(data, period = 14) {
330
+ if (data.length < period + 1) return [];
331
+ const changes = [];
332
+ for (let i = 1; i < data.length; i++) {
333
+ changes.push(data[i] - data[i - 1]);
334
+ }
335
+ const gains = changes.map((change) => change > 0 ? change : 0);
336
+ const losses = changes.map((change) => change < 0 ? Math.abs(change) : 0);
337
+ let avgGain = gains.slice(0, period).reduce((a, b) => a + b, 0) / period;
338
+ let avgLoss = losses.slice(0, period).reduce((a, b) => a + b, 0) / period;
339
+ const rsi = [];
340
+ for (let i = period; i < changes.length; i++) {
341
+ const rs = avgGain / avgLoss;
342
+ rsi.push(100 - 100 / (1 + rs));
343
+ avgGain = (avgGain * (period - 1) + gains[i]) / period;
344
+ avgLoss = (avgLoss * (period - 1) + losses[i]) / period;
345
+ }
346
+ return rsi;
347
+ }
348
+ // Calculate Bollinger Bands
349
+ calculateBollingerBands(data, period = 20, stdDev = 2) {
350
+ if (data.length < period) return [];
351
+ const sma = this.calculateSMA(data, period);
352
+ const bands = [];
353
+ for (let i = 0; i < sma.length; i++) {
354
+ const dataSlice = data.slice(i, i + period);
355
+ const mean = sma[i];
356
+ const variance = dataSlice.reduce((sum2, price) => sum2 + (price - mean) ** 2, 0) / period;
357
+ const standardDeviation = Math.sqrt(variance);
358
+ bands.push({
359
+ upper: mean + standardDeviation * stdDev,
360
+ middle: mean,
361
+ lower: mean - standardDeviation * stdDev
362
+ });
363
+ }
364
+ return bands;
365
+ }
366
+ // Calculate maximum drawdown
367
+ calculateMaxDrawdown(prices) {
368
+ let maxPrice = prices[0];
369
+ let maxDrawdown = 0;
370
+ for (let i = 1; i < prices.length; i++) {
371
+ if (prices[i] > maxPrice) {
372
+ maxPrice = prices[i];
373
+ }
374
+ const drawdown = (maxPrice - prices[i]) / maxPrice;
375
+ if (drawdown > maxDrawdown) {
376
+ maxDrawdown = drawdown;
377
+ }
378
+ }
379
+ return maxDrawdown;
380
+ }
381
+ // Calculate price changes for volatility
382
+ calculatePriceChanges() {
383
+ const changes = [];
384
+ for (let i = 1; i < this.prices.length; i++) {
385
+ changes.push((this.prices[i] - this.prices[i - 1]) / this.prices[i - 1]);
386
+ }
387
+ return changes;
388
+ }
389
+ // Generate comprehensive market analysis
390
+ analyze() {
391
+ const currentPrice = this.prices[this.prices.length - 1];
392
+ const startPrice = this.prices[0];
393
+ const sessionHigh = Math.max(...this.highs);
394
+ const sessionLow = Math.min(...this.lows);
395
+ const totalVolume = sum(this.volumes);
396
+ const avgVolume = totalVolume / this.volumes.length;
397
+ const priceChanges = this.calculatePriceChanges();
398
+ const volatility = priceChanges.length > 0 ? Math.sqrt(
399
+ priceChanges.reduce((sum2, change) => sum2 + change ** 2, 0) / priceChanges.length
400
+ ) * Math.sqrt(252) * 100 : 0;
401
+ const sessionReturn = (currentPrice - startPrice) / startPrice * 100;
402
+ const pricePosition = (currentPrice - sessionLow) / (sessionHigh - sessionLow) * 100;
403
+ const trueVWAP = this.prices.reduce((sum2, price, i) => sum2 + price * this.volumes[i], 0) / totalVolume;
404
+ const momentum5 = this.prices.length > 5 ? (currentPrice - this.prices[Math.max(0, this.prices.length - 6)]) / this.prices[Math.max(0, this.prices.length - 6)] * 100 : 0;
405
+ const momentum10 = this.prices.length > 10 ? (currentPrice - this.prices[Math.max(0, this.prices.length - 11)]) / this.prices[Math.max(0, this.prices.length - 11)] * 100 : 0;
406
+ const maxDrawdown = this.calculateMaxDrawdown(this.prices);
407
+ return {
408
+ currentPrice,
409
+ startPrice,
410
+ sessionHigh,
411
+ sessionLow,
412
+ totalVolume,
413
+ avgVolume,
414
+ volatility,
415
+ sessionReturn,
416
+ pricePosition,
417
+ trueVWAP,
418
+ momentum5,
419
+ momentum10,
420
+ maxDrawdown
421
+ };
422
+ }
423
+ // Generate technical indicators
424
+ getTechnicalIndicators() {
425
+ return {
426
+ sma5: this.calculateSMA(this.prices, 5),
427
+ sma10: this.calculateSMA(this.prices, 10),
428
+ ema8: this.calculateEMA(this.prices, 8),
429
+ ema21: this.calculateEMA(this.prices, 21),
430
+ rsi: this.calculateRSI(this.prices, 14),
431
+ bollinger: this.calculateBollingerBands(this.prices, 20, 2)
432
+ };
433
+ }
434
+ // Generate trading signals
435
+ generateSignals() {
436
+ const analysis = this.analyze();
437
+ let bullishSignals = 0;
438
+ let bearishSignals = 0;
439
+ const signals = [];
440
+ if (analysis.currentPrice > analysis.trueVWAP) {
441
+ signals.push(
442
+ `\u2713 BULLISH: Price above VWAP (+${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
443
+ );
444
+ bullishSignals++;
445
+ } else {
446
+ signals.push(
447
+ `\u2717 BEARISH: Price below VWAP (${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
448
+ );
449
+ bearishSignals++;
450
+ }
451
+ if (analysis.momentum5 > 0 && analysis.momentum10 > 0) {
452
+ signals.push("\u2713 BULLISH: Positive momentum on both timeframes");
453
+ bullishSignals++;
454
+ } else if (analysis.momentum5 < 0 && analysis.momentum10 < 0) {
455
+ signals.push("\u2717 BEARISH: Negative momentum on both timeframes");
456
+ bearishSignals++;
457
+ } else {
458
+ signals.push("\u25D0 MIXED: Conflicting momentum signals");
459
+ }
460
+ const currentVolume = this.volumes[this.volumes.length - 1];
461
+ const volumeRatio = currentVolume / analysis.avgVolume;
462
+ if (volumeRatio > 1.2 && analysis.sessionReturn > 0) {
463
+ signals.push("\u2713 BULLISH: Above-average volume supporting upward move");
464
+ bullishSignals++;
465
+ } else if (volumeRatio > 1.2 && analysis.sessionReturn < 0) {
466
+ signals.push("\u2717 BEARISH: Above-average volume supporting downward move");
467
+ bearishSignals++;
468
+ } else {
469
+ signals.push("\u25D0 NEUTRAL: Volume not providing clear direction");
470
+ }
471
+ if (analysis.pricePosition > 65 && analysis.volatility > 30) {
472
+ signals.push("\u2717 BEARISH: High in range with elevated volatility - reversal risk");
473
+ bearishSignals++;
474
+ } else if (analysis.pricePosition < 35 && analysis.volatility > 30) {
475
+ signals.push("\u2713 BULLISH: Low in range with volatility - potential bounce");
476
+ bullishSignals++;
477
+ } else {
478
+ signals.push("\u25D0 NEUTRAL: Price position and volatility not extreme");
479
+ }
480
+ return { bullishSignals, bearishSignals, signals };
481
+ }
482
+ // Generate comprehensive JSON analysis
483
+ generateJSONAnalysis(symbol) {
484
+ const analysis = this.analyze();
485
+ const indicators = this.getTechnicalIndicators();
486
+ const signals = this.generateSignals();
487
+ const currentSMA5 = indicators.sma5.length > 0 ? indicators.sma5[indicators.sma5.length - 1] : null;
488
+ const currentSMA10 = indicators.sma10.length > 0 ? indicators.sma10[indicators.sma10.length - 1] : null;
489
+ const currentEMA8 = indicators.ema8[indicators.ema8.length - 1];
490
+ const currentEMA21 = indicators.ema21[indicators.ema21.length - 1];
491
+ const currentRSI = indicators.rsi.length > 0 ? indicators.rsi[indicators.rsi.length - 1] : null;
492
+ const currentBB = indicators.bollinger.length > 0 ? indicators.bollinger[indicators.bollinger.length - 1] : null;
493
+ const currentVolume = this.volumes[this.volumes.length - 1];
494
+ const volumeRatio = currentVolume / analysis.avgVolume;
495
+ const currentDrawdown = (analysis.sessionHigh - analysis.currentPrice) / analysis.sessionHigh * 100;
496
+ const rangeWidth = (analysis.sessionHigh - analysis.sessionLow) / analysis.sessionLow * 100;
497
+ const priceVsVWAP = (analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100;
498
+ const totalScore = signals.bullishSignals - signals.bearishSignals;
499
+ const overallSignal = totalScore > 0 ? "BULLISH_BIAS" : totalScore < 0 ? "BEARISH_BIAS" : "NEUTRAL";
500
+ const targetEntry = Math.max(analysis.sessionLow * 1.005, analysis.trueVWAP * 0.998);
501
+ const stopLoss = analysis.sessionLow * 0.995;
502
+ const profitTarget = analysis.sessionHigh * 0.995;
503
+ const riskRewardRatio = (profitTarget - analysis.currentPrice) / (analysis.currentPrice - stopLoss);
504
+ return {
505
+ symbol,
506
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
507
+ marketStructure: {
508
+ currentPrice: analysis.currentPrice,
509
+ startPrice: analysis.startPrice,
510
+ sessionHigh: analysis.sessionHigh,
511
+ sessionLow: analysis.sessionLow,
512
+ rangeWidth,
513
+ totalVolume: analysis.totalVolume,
514
+ sessionPerformance: analysis.sessionReturn,
515
+ positionInRange: analysis.pricePosition
516
+ },
517
+ volatility: {
518
+ impliedVolatility: analysis.volatility,
519
+ maxDrawdown: analysis.maxDrawdown * 100,
520
+ currentDrawdown
521
+ },
522
+ technicalIndicators: {
523
+ sma5: currentSMA5,
524
+ sma10: currentSMA10,
525
+ ema8: currentEMA8,
526
+ ema21: currentEMA21,
527
+ rsi: currentRSI,
528
+ bollingerBands: currentBB ? {
529
+ upper: currentBB.upper,
530
+ middle: currentBB.middle,
531
+ lower: currentBB.lower,
532
+ position: (analysis.currentPrice - currentBB.lower) / (currentBB.upper - currentBB.lower) * 100
533
+ } : null
534
+ },
535
+ volumeAnalysis: {
536
+ currentVolume,
537
+ averageVolume: Math.round(analysis.avgVolume),
538
+ volumeRatio,
539
+ trueVWAP: analysis.trueVWAP,
540
+ priceVsVWAP
541
+ },
542
+ momentum: {
543
+ momentum5: analysis.momentum5,
544
+ momentum10: analysis.momentum10,
545
+ sessionROC: analysis.sessionReturn
546
+ },
547
+ tradingSignals: {
548
+ ...signals,
549
+ overallSignal,
550
+ signalScore: totalScore
551
+ },
552
+ riskManagement: {
553
+ targetEntry,
554
+ stopLoss,
555
+ profitTarget,
556
+ riskRewardRatio
557
+ }
558
+ };
559
+ }
560
+ };
561
+ var createTechnicalAnalysisHandler = (marketDataPrices) => {
562
+ return async (args) => {
563
+ try {
564
+ const symbol = args.symbol;
565
+ const priceHistory = marketDataPrices.get(symbol) || [];
566
+ if (priceHistory.length === 0) {
567
+ return {
568
+ content: [
569
+ {
570
+ type: "text",
571
+ text: `No price data available for ${symbol}. Please request market data first.`,
572
+ uri: "technicalAnalysis"
573
+ }
574
+ ]
575
+ };
576
+ }
577
+ const analyzer = new TechnicalAnalyzer(priceHistory);
578
+ const analysis = analyzer.generateJSONAnalysis(symbol);
579
+ return {
580
+ content: [
581
+ {
582
+ type: "text",
583
+ text: `Technical Analysis for ${symbol}:
584
+
585
+ ${JSON.stringify(analysis, null, 2)}`,
586
+ uri: "technicalAnalysis"
587
+ }
588
+ ]
589
+ };
590
+ } catch (error) {
591
+ return {
592
+ content: [
593
+ {
594
+ type: "text",
595
+ text: `Error performing technical analysis: ${error instanceof Error ? error.message : "Unknown error"}`,
596
+ uri: "technicalAnalysis"
597
+ }
598
+ ],
599
+ isError: true
600
+ };
601
+ }
602
+ };
603
+ };
604
+
282
605
  // src/tools/marketData.ts
283
606
  import { Field, Fields, MDEntryType, Messages } from "fixparser";
284
607
  import QuickChart from "quickchart-js";
285
608
  var createMarketDataRequestHandler = (parser, pendingRequests) => {
286
609
  return async (args) => {
287
610
  try {
611
+ parser.logger.log({
612
+ level: "info",
613
+ message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
614
+ });
288
615
  const response = new Promise((resolve) => {
289
616
  pendingRequests.set(args.mdReqID, resolve);
617
+ parser.logger.log({
618
+ level: "info",
619
+ message: `Registered callback for market data request ID: ${args.mdReqID}`
620
+ });
290
621
  });
291
622
  const entryTypes = args.mdEntryTypes || [
292
623
  MDEntryType.Bid,
@@ -355,6 +686,10 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
355
686
  });
356
687
  const mdr = parser.createMessage(...messageFields);
357
688
  if (!parser.connected) {
689
+ parser.logger.log({
690
+ level: "error",
691
+ message: "Not connected. Cannot send market data request."
692
+ });
358
693
  return {
359
694
  content: [
360
695
  {
@@ -366,8 +701,16 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
366
701
  isError: true
367
702
  };
368
703
  }
704
+ parser.logger.log({
705
+ level: "info",
706
+ message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
707
+ });
369
708
  parser.send(mdr);
370
709
  const fixData = await response;
710
+ parser.logger.log({
711
+ level: "info",
712
+ message: `Received market data response for request ID: ${args.mdReqID}`
713
+ });
371
714
  return {
372
715
  content: [
373
716
  {
@@ -416,6 +759,9 @@ var createGetStockGraphHandler = (marketDataPrices) => {
416
759
  const offerData = priceHistory.map((point) => point.offer);
417
760
  const spreadData = priceHistory.map((point) => point.spread);
418
761
  const volumeData = priceHistory.map((point) => point.volume);
762
+ const tradeData = priceHistory.map((point) => point.trade);
763
+ const vwapData = priceHistory.map((point) => point.vwap);
764
+ const twapData = priceHistory.map((point) => point.twap);
419
765
  const config = {
420
766
  type: "line",
421
767
  data: {
@@ -445,6 +791,30 @@ var createGetStockGraphHandler = (marketDataPrices) => {
445
791
  fill: false,
446
792
  tension: 0.4
447
793
  },
794
+ {
795
+ label: "Trade",
796
+ data: tradeData,
797
+ borderColor: "#ffc107",
798
+ backgroundColor: "rgba(255, 193, 7, 0.1)",
799
+ fill: false,
800
+ tension: 0.4
801
+ },
802
+ {
803
+ label: "VWAP",
804
+ data: vwapData,
805
+ borderColor: "#17a2b8",
806
+ backgroundColor: "rgba(23, 162, 184, 0.1)",
807
+ fill: false,
808
+ tension: 0.4
809
+ },
810
+ {
811
+ label: "TWAP",
812
+ data: twapData,
813
+ borderColor: "#6610f2",
814
+ backgroundColor: "rgba(102, 16, 242, 0.1)",
815
+ fill: false,
816
+ tension: 0.4
817
+ },
448
818
  {
449
819
  label: "Volume",
450
820
  data: volumeData,
@@ -490,7 +860,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
490
860
  content: [
491
861
  {
492
862
  type: "text",
493
- text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
863
+ text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
494
864
  uri: "getStockGraph"
495
865
  }
496
866
  ],
@@ -528,7 +898,48 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
528
898
  bid: point.bid,
529
899
  offer: point.offer,
530
900
  spread: point.spread,
531
- volume: point.volume
901
+ volume: point.volume,
902
+ trade: point.trade,
903
+ indexValue: point.indexValue,
904
+ openingPrice: point.openingPrice,
905
+ closingPrice: point.closingPrice,
906
+ settlementPrice: point.settlementPrice,
907
+ tradingSessionHighPrice: point.tradingSessionHighPrice,
908
+ tradingSessionLowPrice: point.tradingSessionLowPrice,
909
+ vwap: point.vwap,
910
+ imbalance: point.imbalance,
911
+ openInterest: point.openInterest,
912
+ compositeUnderlyingPrice: point.compositeUnderlyingPrice,
913
+ simulatedSellPrice: point.simulatedSellPrice,
914
+ simulatedBuyPrice: point.simulatedBuyPrice,
915
+ marginRate: point.marginRate,
916
+ midPrice: point.midPrice,
917
+ emptyBook: point.emptyBook,
918
+ settleHighPrice: point.settleHighPrice,
919
+ settleLowPrice: point.settleLowPrice,
920
+ priorSettlePrice: point.priorSettlePrice,
921
+ sessionHighBid: point.sessionHighBid,
922
+ sessionLowOffer: point.sessionLowOffer,
923
+ earlyPrices: point.earlyPrices,
924
+ auctionClearingPrice: point.auctionClearingPrice,
925
+ swapValueFactor: point.swapValueFactor,
926
+ dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
927
+ cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
928
+ dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
929
+ cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
930
+ fixingPrice: point.fixingPrice,
931
+ cashRate: point.cashRate,
932
+ recoveryRate: point.recoveryRate,
933
+ recoveryRateForLong: point.recoveryRateForLong,
934
+ recoveryRateForShort: point.recoveryRateForShort,
935
+ marketBid: point.marketBid,
936
+ marketOffer: point.marketOffer,
937
+ shortSaleMinPrice: point.shortSaleMinPrice,
938
+ previousClosingPrice: point.previousClosingPrice,
939
+ thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
940
+ dailyFinancingValue: point.dailyFinancingValue,
941
+ accruedFinancingValue: point.accruedFinancingValue,
942
+ twap: point.twap
532
943
  }))
533
944
  },
534
945
  null,
@@ -543,7 +954,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
543
954
  content: [
544
955
  {
545
956
  type: "text",
546
- text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
957
+ text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
547
958
  uri: "getStockPriceHistory"
548
959
  }
549
960
  ],
@@ -651,7 +1062,7 @@ Parameters verified:
651
1062
  - Symbol: ${args.symbol}
652
1063
  - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
653
1064
 
654
- To execute this order, call the executeOrder tool with these exact same parameters.`,
1065
+ To execute this order, call the executeOrder tool with these exact same parameters. Important: The user has to explicitly confirm before executeOrder is called!`,
655
1066
  uri: "verifyOrder"
656
1067
  }
657
1068
  ]
@@ -847,16 +1258,16 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
847
1258
  executeOrder: createExecuteOrderHandler(parser, verifiedOrders, pendingRequests),
848
1259
  marketDataRequest: createMarketDataRequestHandler(parser, pendingRequests),
849
1260
  getStockGraph: createGetStockGraphHandler(marketDataPrices),
850
- getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
1261
+ getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices),
1262
+ technicalAnalysis: createTechnicalAnalysisHandler(marketDataPrices)
851
1263
  });
852
1264
 
853
1265
  // src/utils/messageHandler.ts
854
1266
  import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
1267
+ function getEnumValue(enumObj, name) {
1268
+ return enumObj[name] || name;
1269
+ }
855
1270
  function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
856
- parser.logger.log({
857
- level: "info",
858
- message: `MCP Server received message: ${message.messageType}: ${message.description}`
859
- });
860
1271
  const msgType = message.messageType;
861
1272
  if (msgType === Messages3.MarketDataSnapshotFullRefresh || msgType === Messages3.MarketDataIncrementalRefresh) {
862
1273
  const symbol = message.getField(Fields3.Symbol)?.value;
@@ -914,7 +1325,8 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
914
1325
  const entryType = entry.MDEntryType;
915
1326
  const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
916
1327
  const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
917
- switch (entryType) {
1328
+ const enumValue = getEnumValue(MDEntryType2, entryType);
1329
+ switch (enumValue) {
918
1330
  case MDEntryType2.Bid:
919
1331
  data.bid = price;
920
1332
  break;
@@ -1181,25 +1593,13 @@ var MCPRemote = class extends MCPBase {
1181
1593
  }
1182
1594
  });
1183
1595
  this.httpServer = createServer(async (req, res) => {
1184
- this.logger?.log({
1185
- level: "info",
1186
- message: `Incoming request: ${req.method} ${req.url}`
1187
- });
1188
1596
  if (!req.url || !req.method) {
1189
- this.logger?.log({
1190
- level: "error",
1191
- message: "Invalid request: missing URL or method"
1192
- });
1193
1597
  res.writeHead(400);
1194
1598
  res.end("Bad Request");
1195
1599
  return;
1196
1600
  }
1197
1601
  if (req.url === "/mcp") {
1198
1602
  const sessionId = req.headers["mcp-session-id"];
1199
- this.logger?.log({
1200
- level: "info",
1201
- message: `MCP request received. Session ID: ${sessionId || "none"}, headers: ${req.headers}`
1202
- });
1203
1603
  if (req.method === "POST") {
1204
1604
  const bodyChunks = [];
1205
1605
  req.on("data", (chunk) => {
@@ -1210,47 +1610,23 @@ var MCPRemote = class extends MCPBase {
1210
1610
  const body = Buffer.concat(bodyChunks).toString();
1211
1611
  try {
1212
1612
  parsed = JSON.parse(body);
1213
- this.logger?.log({
1214
- level: "info",
1215
- message: `Parsed request body: ${JSON.stringify(parsed)}`
1216
- });
1217
1613
  } catch (err) {
1218
- this.logger?.log({
1219
- level: "error",
1220
- message: `Failed to parse JSON body: ${err}`
1221
- });
1222
1614
  res.writeHead(400);
1223
1615
  res.end(JSON.stringify({ error: "Invalid JSON" }));
1224
1616
  return;
1225
1617
  }
1226
1618
  let transport;
1227
1619
  if (sessionId && transports[sessionId]) {
1228
- this.logger?.log({
1229
- level: "info",
1230
- message: `Using existing transport for session: ${sessionId}`
1231
- });
1232
1620
  transport = transports[sessionId];
1233
1621
  } else if (!sessionId && req.method === "POST" && isInitializeRequest(parsed)) {
1234
- this.logger?.log({
1235
- level: "info",
1236
- message: "Creating new transport for initialization request"
1237
- });
1238
1622
  transport = new StreamableHTTPServerTransport({
1239
1623
  sessionIdGenerator: () => randomUUID(),
1240
1624
  onsessioninitialized: (sessionId2) => {
1241
- this.logger?.log({
1242
- level: "info",
1243
- message: `New session initialized: ${sessionId2}`
1244
- });
1245
1625
  transports[sessionId2] = transport;
1246
1626
  }
1247
1627
  });
1248
1628
  transport.onclose = () => {
1249
1629
  if (transport.sessionId) {
1250
- this.logger?.log({
1251
- level: "info",
1252
- message: `Session closed: ${transport.sessionId}`
1253
- });
1254
1630
  delete transports[transport.sessionId];
1255
1631
  }
1256
1632
  };
@@ -1261,10 +1637,6 @@ var MCPRemote = class extends MCPBase {
1261
1637
  this.setupTools();
1262
1638
  await this.mcpServer.connect(transport);
1263
1639
  } else {
1264
- this.logger?.log({
1265
- level: "error",
1266
- message: "Invalid request: No valid session ID provided"
1267
- });
1268
1640
  res.writeHead(400, { "Content-Type": "application/json" });
1269
1641
  res.end(
1270
1642
  JSON.stringify({
@@ -1280,10 +1652,6 @@ var MCPRemote = class extends MCPBase {
1280
1652
  }
1281
1653
  try {
1282
1654
  await transport.handleRequest(req, res, parsed);
1283
- this.logger?.log({
1284
- level: "info",
1285
- message: "Request handled successfully"
1286
- });
1287
1655
  } catch (error) {
1288
1656
  this.logger?.log({
1289
1657
  level: "error",
@@ -1294,10 +1662,6 @@ var MCPRemote = class extends MCPBase {
1294
1662
  });
1295
1663
  } else if (req.method === "GET" || req.method === "DELETE") {
1296
1664
  if (!sessionId || !transports[sessionId]) {
1297
- this.logger?.log({
1298
- level: "error",
1299
- message: `Invalid session ID for ${req.method} request: ${sessionId}`
1300
- });
1301
1665
  res.writeHead(400);
1302
1666
  res.end("Invalid or missing session ID");
1303
1667
  return;
@@ -1305,10 +1669,6 @@ var MCPRemote = class extends MCPBase {
1305
1669
  const transport = transports[sessionId];
1306
1670
  try {
1307
1671
  await transport.handleRequest(req, res);
1308
- this.logger?.log({
1309
- level: "info",
1310
- message: `${req.method} request handled successfully for session: ${sessionId}`
1311
- });
1312
1672
  } catch (error) {
1313
1673
  this.logger?.log({
1314
1674
  level: "error",
@@ -1325,10 +1685,6 @@ var MCPRemote = class extends MCPBase {
1325
1685
  res.end("Method Not Allowed");
1326
1686
  }
1327
1687
  } else {
1328
- this.logger?.log({
1329
- level: "error",
1330
- message: `Not found: ${req.url}`
1331
- });
1332
1688
  res.writeHead(404);
1333
1689
  res.end("Not Found");
1334
1690
  }