fixparser-plugin-mcp 9.1.7-bfafe1e3 → 9.1.7-c213f7c6

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.
@@ -35,9 +35,51 @@ __export(MCPLocal_exports, {
35
35
  module.exports = __toCommonJS(MCPLocal_exports);
36
36
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
37
37
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
38
- var import_fixparser3 = require("fixparser");
39
38
  var import_zod = require("zod");
40
39
 
40
+ // src/MCPBase.ts
41
+ var MCPBase = class {
42
+ /**
43
+ * Optional logger instance for diagnostics and output.
44
+ * @protected
45
+ */
46
+ logger;
47
+ /**
48
+ * FIXParser instance, set during plugin register().
49
+ * @protected
50
+ */
51
+ parser;
52
+ /**
53
+ * Called when server is setup and listening.
54
+ * @protected
55
+ */
56
+ onReady = void 0;
57
+ /**
58
+ * Map to store verified orders before execution
59
+ * @protected
60
+ */
61
+ verifiedOrders = /* @__PURE__ */ new Map();
62
+ /**
63
+ * Map to store pending market data requests
64
+ * @protected
65
+ */
66
+ pendingRequests = /* @__PURE__ */ new Map();
67
+ /**
68
+ * Map to store market data prices
69
+ * @protected
70
+ */
71
+ marketDataPrices = /* @__PURE__ */ new Map();
72
+ /**
73
+ * Maximum number of price history entries to keep per symbol
74
+ * @protected
75
+ */
76
+ MAX_PRICE_HISTORY = 1e5;
77
+ constructor({ logger, onReady }) {
78
+ this.logger = logger;
79
+ this.onReady = onReady;
80
+ }
81
+ };
82
+
41
83
  // src/schemas/schemas.ts
42
84
  var toolSchemas = {
43
85
  parse: {
@@ -121,7 +163,7 @@ var toolSchemas = {
121
163
  }
122
164
  },
123
165
  executeOrder: {
124
- description: "Executes a verified order. verifyOrder must be called before executeOrder. user has to explicitly allow executeOrder.",
166
+ description: "Executes a verified order. verifyOrder must be called before executeOrder.",
125
167
  schema: {
126
168
  type: "object",
127
169
  properties: {
@@ -277,7 +319,52 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
277
319
  const response = new Promise((resolve) => {
278
320
  pendingRequests.set(args.mdReqID, resolve);
279
321
  });
280
- const entryTypes = args.mdEntryTypes || [import_fixparser.MDEntryType.Bid, import_fixparser.MDEntryType.Offer, import_fixparser.MDEntryType.TradeVolume];
322
+ const entryTypes = args.mdEntryTypes || [
323
+ import_fixparser.MDEntryType.Bid,
324
+ import_fixparser.MDEntryType.Offer,
325
+ import_fixparser.MDEntryType.Trade,
326
+ import_fixparser.MDEntryType.IndexValue,
327
+ import_fixparser.MDEntryType.OpeningPrice,
328
+ import_fixparser.MDEntryType.ClosingPrice,
329
+ import_fixparser.MDEntryType.SettlementPrice,
330
+ import_fixparser.MDEntryType.TradingSessionHighPrice,
331
+ import_fixparser.MDEntryType.TradingSessionLowPrice,
332
+ import_fixparser.MDEntryType.VWAP,
333
+ import_fixparser.MDEntryType.Imbalance,
334
+ import_fixparser.MDEntryType.TradeVolume,
335
+ import_fixparser.MDEntryType.OpenInterest,
336
+ import_fixparser.MDEntryType.CompositeUnderlyingPrice,
337
+ import_fixparser.MDEntryType.SimulatedSellPrice,
338
+ import_fixparser.MDEntryType.SimulatedBuyPrice,
339
+ import_fixparser.MDEntryType.MarginRate,
340
+ import_fixparser.MDEntryType.MidPrice,
341
+ import_fixparser.MDEntryType.EmptyBook,
342
+ import_fixparser.MDEntryType.SettleHighPrice,
343
+ import_fixparser.MDEntryType.SettleLowPrice,
344
+ import_fixparser.MDEntryType.PriorSettlePrice,
345
+ import_fixparser.MDEntryType.SessionHighBid,
346
+ import_fixparser.MDEntryType.SessionLowOffer,
347
+ import_fixparser.MDEntryType.EarlyPrices,
348
+ import_fixparser.MDEntryType.AuctionClearingPrice,
349
+ import_fixparser.MDEntryType.SwapValueFactor,
350
+ import_fixparser.MDEntryType.DailyValueAdjustmentForLongPositions,
351
+ import_fixparser.MDEntryType.CumulativeValueAdjustmentForLongPositions,
352
+ import_fixparser.MDEntryType.DailyValueAdjustmentForShortPositions,
353
+ import_fixparser.MDEntryType.CumulativeValueAdjustmentForShortPositions,
354
+ import_fixparser.MDEntryType.FixingPrice,
355
+ import_fixparser.MDEntryType.CashRate,
356
+ import_fixparser.MDEntryType.RecoveryRate,
357
+ import_fixparser.MDEntryType.RecoveryRateForLong,
358
+ import_fixparser.MDEntryType.RecoveryRateForShort,
359
+ import_fixparser.MDEntryType.MarketBid,
360
+ import_fixparser.MDEntryType.MarketOffer,
361
+ import_fixparser.MDEntryType.ShortSaleMinPrice,
362
+ import_fixparser.MDEntryType.PreviousClosingPrice,
363
+ import_fixparser.MDEntryType.ThresholdLimitPriceBanding,
364
+ import_fixparser.MDEntryType.DailyFinancingValue,
365
+ import_fixparser.MDEntryType.AccruedFinancingValue,
366
+ import_fixparser.MDEntryType.TWAP
367
+ ];
281
368
  const messageFields = [
282
369
  new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.MarketDataRequest),
283
370
  new import_fixparser.Field(import_fixparser.Fields.SenderCompID, parser.sender),
@@ -352,14 +439,18 @@ var createGetStockGraphHandler = (marketDataPrices) => {
352
439
  };
353
440
  }
354
441
  const chart = new import_quickchart_js.default();
355
- chart.setWidth(600);
356
- chart.setHeight(300);
442
+ chart.setWidth(1200);
443
+ chart.setHeight(600);
444
+ chart.setBackgroundColor("transparent");
357
445
  const labels = priceHistory.map((point) => new Date(point.timestamp).toLocaleTimeString());
358
446
  const bidData = priceHistory.map((point) => point.bid);
359
447
  const offerData = priceHistory.map((point) => point.offer);
360
448
  const spreadData = priceHistory.map((point) => point.spread);
361
449
  const volumeData = priceHistory.map((point) => point.volume);
362
- chart.setConfig({
450
+ const tradeData = priceHistory.map((point) => point.trade);
451
+ const vwapData = priceHistory.map((point) => point.vwap);
452
+ const twapData = priceHistory.map((point) => point.twap);
453
+ const config = {
363
454
  type: "line",
364
455
  data: {
365
456
  labels,
@@ -388,69 +479,67 @@ var createGetStockGraphHandler = (marketDataPrices) => {
388
479
  fill: false,
389
480
  tension: 0.4
390
481
  },
482
+ {
483
+ label: "Trade",
484
+ data: tradeData,
485
+ borderColor: "#ffc107",
486
+ backgroundColor: "rgba(255, 193, 7, 0.1)",
487
+ fill: false,
488
+ tension: 0.4
489
+ },
490
+ {
491
+ label: "VWAP",
492
+ data: vwapData,
493
+ borderColor: "#17a2b8",
494
+ backgroundColor: "rgba(23, 162, 184, 0.1)",
495
+ fill: false,
496
+ tension: 0.4
497
+ },
498
+ {
499
+ label: "TWAP",
500
+ data: twapData,
501
+ borderColor: "#6610f2",
502
+ backgroundColor: "rgba(102, 16, 242, 0.1)",
503
+ fill: false,
504
+ tension: 0.4
505
+ },
391
506
  {
392
507
  label: "Volume",
393
508
  data: volumeData,
394
509
  borderColor: "#007bff",
395
510
  backgroundColor: "rgba(0, 123, 255, 0.1)",
396
511
  fill: true,
397
- tension: 0.4,
398
- yAxisID: "volume"
512
+ tension: 0.4
399
513
  }
400
514
  ]
401
515
  },
402
516
  options: {
517
+ responsive: true,
403
518
  plugins: {
404
519
  title: {
405
520
  display: true,
406
- text: `${symbol} Market Data`,
407
- font: {
408
- size: 16,
409
- weight: "bold"
410
- }
411
- },
412
- legend: {
413
- display: true
521
+ text: `${symbol} Market Data`
414
522
  }
415
523
  },
416
524
  scales: {
417
525
  y: {
418
- beginAtZero: false,
419
- grid: {
420
- color: "#e9ecef"
421
- }
422
- },
423
- volume: {
424
- position: "right",
425
- beginAtZero: true,
426
- grid: {
427
- display: false
428
- }
429
- },
430
- x: {
431
- grid: {
432
- display: false
433
- }
526
+ beginAtZero: false
434
527
  }
435
528
  }
436
529
  }
437
- });
530
+ };
531
+ chart.setConfig(config);
438
532
  const imageBuffer = await chart.toBinary();
439
- const base64Image = imageBuffer.toString("base64");
440
- console.log("-------------------------------------------");
441
- console.log("b64", base64Image);
442
- console.log("-------------------------------------------");
533
+ const base64 = imageBuffer.toString("base64");
443
534
  return {
444
535
  content: [
445
536
  {
446
- type: "image",
447
- image: {
448
- source: {
449
- data: base64Image
450
- }
451
- },
452
- uri: "getStockGraph",
453
- mimeType: "image/png"
537
+ type: "resource",
538
+ resource: {
539
+ uri: "resource://graph",
540
+ mimeType: "image/png",
541
+ blob: base64
542
+ }
454
543
  }
455
544
  ]
456
545
  };
@@ -459,7 +548,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
459
548
  content: [
460
549
  {
461
550
  type: "text",
462
- text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
551
+ text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
463
552
  uri: "getStockGraph"
464
553
  }
465
554
  ],
@@ -497,7 +586,48 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
497
586
  bid: point.bid,
498
587
  offer: point.offer,
499
588
  spread: point.spread,
500
- volume: point.volume
589
+ volume: point.volume,
590
+ trade: point.trade,
591
+ indexValue: point.indexValue,
592
+ openingPrice: point.openingPrice,
593
+ closingPrice: point.closingPrice,
594
+ settlementPrice: point.settlementPrice,
595
+ tradingSessionHighPrice: point.tradingSessionHighPrice,
596
+ tradingSessionLowPrice: point.tradingSessionLowPrice,
597
+ vwap: point.vwap,
598
+ imbalance: point.imbalance,
599
+ openInterest: point.openInterest,
600
+ compositeUnderlyingPrice: point.compositeUnderlyingPrice,
601
+ simulatedSellPrice: point.simulatedSellPrice,
602
+ simulatedBuyPrice: point.simulatedBuyPrice,
603
+ marginRate: point.marginRate,
604
+ midPrice: point.midPrice,
605
+ emptyBook: point.emptyBook,
606
+ settleHighPrice: point.settleHighPrice,
607
+ settleLowPrice: point.settleLowPrice,
608
+ priorSettlePrice: point.priorSettlePrice,
609
+ sessionHighBid: point.sessionHighBid,
610
+ sessionLowOffer: point.sessionLowOffer,
611
+ earlyPrices: point.earlyPrices,
612
+ auctionClearingPrice: point.auctionClearingPrice,
613
+ swapValueFactor: point.swapValueFactor,
614
+ dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
615
+ cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
616
+ dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
617
+ cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
618
+ fixingPrice: point.fixingPrice,
619
+ cashRate: point.cashRate,
620
+ recoveryRate: point.recoveryRate,
621
+ recoveryRateForLong: point.recoveryRateForLong,
622
+ recoveryRateForShort: point.recoveryRateForShort,
623
+ marketBid: point.marketBid,
624
+ marketOffer: point.marketOffer,
625
+ shortSaleMinPrice: point.shortSaleMinPrice,
626
+ previousClosingPrice: point.previousClosingPrice,
627
+ thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
628
+ dailyFinancingValue: point.dailyFinancingValue,
629
+ accruedFinancingValue: point.accruedFinancingValue,
630
+ twap: point.twap
501
631
  }))
502
632
  },
503
633
  null,
@@ -512,7 +642,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
512
642
  content: [
513
643
  {
514
644
  type: "text",
515
- text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
645
+ text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
516
646
  uri: "getStockPriceHistory"
517
647
  }
518
648
  ],
@@ -620,7 +750,7 @@ Parameters verified:
620
750
  - Symbol: ${args.symbol}
621
751
  - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
622
752
 
623
- To execute this order, call the executeOrder tool with these exact same parameters.`,
753
+ To execute this order, call the executeOrder tool with these exact same parameters. Important: The user has to explicitly confirm before executeOrder is called!`,
624
754
  uri: "verifyOrder"
625
755
  }
626
756
  ]
@@ -819,9 +949,261 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
819
949
  getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
820
950
  });
821
951
 
952
+ // src/utils/messageHandler.ts
953
+ var import_fixparser3 = require("fixparser");
954
+ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
955
+ parser.logger.log({
956
+ level: "info",
957
+ message: `MCP Server received message: ${message.messageType}: ${message.description}`
958
+ });
959
+ const msgType = message.messageType;
960
+ if (msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh || msgType === import_fixparser3.Messages.MarketDataIncrementalRefresh) {
961
+ const symbol = message.getField(import_fixparser3.Fields.Symbol)?.value;
962
+ const fixJson = message.toFIXJSON();
963
+ const entries = fixJson.Body?.NoMDEntries || [];
964
+ const data = {
965
+ timestamp: Date.now(),
966
+ bid: 0,
967
+ offer: 0,
968
+ spread: 0,
969
+ volume: 0,
970
+ trade: 0,
971
+ indexValue: 0,
972
+ openingPrice: 0,
973
+ closingPrice: 0,
974
+ settlementPrice: 0,
975
+ tradingSessionHighPrice: 0,
976
+ tradingSessionLowPrice: 0,
977
+ vwap: 0,
978
+ imbalance: 0,
979
+ openInterest: 0,
980
+ compositeUnderlyingPrice: 0,
981
+ simulatedSellPrice: 0,
982
+ simulatedBuyPrice: 0,
983
+ marginRate: 0,
984
+ midPrice: 0,
985
+ emptyBook: 0,
986
+ settleHighPrice: 0,
987
+ settleLowPrice: 0,
988
+ priorSettlePrice: 0,
989
+ sessionHighBid: 0,
990
+ sessionLowOffer: 0,
991
+ earlyPrices: 0,
992
+ auctionClearingPrice: 0,
993
+ swapValueFactor: 0,
994
+ dailyValueAdjustmentForLongPositions: 0,
995
+ cumulativeValueAdjustmentForLongPositions: 0,
996
+ dailyValueAdjustmentForShortPositions: 0,
997
+ cumulativeValueAdjustmentForShortPositions: 0,
998
+ fixingPrice: 0,
999
+ cashRate: 0,
1000
+ recoveryRate: 0,
1001
+ recoveryRateForLong: 0,
1002
+ recoveryRateForShort: 0,
1003
+ marketBid: 0,
1004
+ marketOffer: 0,
1005
+ shortSaleMinPrice: 0,
1006
+ previousClosingPrice: 0,
1007
+ thresholdLimitPriceBanding: 0,
1008
+ dailyFinancingValue: 0,
1009
+ accruedFinancingValue: 0,
1010
+ twap: 0
1011
+ };
1012
+ for (const entry of entries) {
1013
+ const entryType = entry.MDEntryType;
1014
+ const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
1015
+ const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
1016
+ if (entryType === import_fixparser3.MDEntryType.Bid || entryType === import_fixparser3.MDEntryType.Offer || entryType === import_fixparser3.MDEntryType.TradeVolume) {
1017
+ parser.logger.log({
1018
+ level: "info",
1019
+ message: `Market Data Entry - Type: ${entryType}, Price: ${price}, Size: ${size}`
1020
+ });
1021
+ }
1022
+ switch (entryType) {
1023
+ case import_fixparser3.MDEntryType.Bid:
1024
+ data.bid = price;
1025
+ break;
1026
+ case import_fixparser3.MDEntryType.Offer:
1027
+ data.offer = price;
1028
+ break;
1029
+ case import_fixparser3.MDEntryType.Trade:
1030
+ data.trade = price;
1031
+ break;
1032
+ case import_fixparser3.MDEntryType.IndexValue:
1033
+ data.indexValue = price;
1034
+ break;
1035
+ case import_fixparser3.MDEntryType.OpeningPrice:
1036
+ data.openingPrice = price;
1037
+ break;
1038
+ case import_fixparser3.MDEntryType.ClosingPrice:
1039
+ data.closingPrice = price;
1040
+ break;
1041
+ case import_fixparser3.MDEntryType.SettlementPrice:
1042
+ data.settlementPrice = price;
1043
+ break;
1044
+ case import_fixparser3.MDEntryType.TradingSessionHighPrice:
1045
+ data.tradingSessionHighPrice = price;
1046
+ break;
1047
+ case import_fixparser3.MDEntryType.TradingSessionLowPrice:
1048
+ data.tradingSessionLowPrice = price;
1049
+ break;
1050
+ case import_fixparser3.MDEntryType.VWAP:
1051
+ data.vwap = price;
1052
+ break;
1053
+ case import_fixparser3.MDEntryType.Imbalance:
1054
+ data.imbalance = size;
1055
+ break;
1056
+ case import_fixparser3.MDEntryType.TradeVolume:
1057
+ data.volume = size;
1058
+ break;
1059
+ case import_fixparser3.MDEntryType.OpenInterest:
1060
+ data.openInterest = size;
1061
+ break;
1062
+ case import_fixparser3.MDEntryType.CompositeUnderlyingPrice:
1063
+ data.compositeUnderlyingPrice = price;
1064
+ break;
1065
+ case import_fixparser3.MDEntryType.SimulatedSellPrice:
1066
+ data.simulatedSellPrice = price;
1067
+ break;
1068
+ case import_fixparser3.MDEntryType.SimulatedBuyPrice:
1069
+ data.simulatedBuyPrice = price;
1070
+ break;
1071
+ case import_fixparser3.MDEntryType.MarginRate:
1072
+ data.marginRate = price;
1073
+ break;
1074
+ case import_fixparser3.MDEntryType.MidPrice:
1075
+ data.midPrice = price;
1076
+ break;
1077
+ case import_fixparser3.MDEntryType.EmptyBook:
1078
+ data.emptyBook = 1;
1079
+ break;
1080
+ case import_fixparser3.MDEntryType.SettleHighPrice:
1081
+ data.settleHighPrice = price;
1082
+ break;
1083
+ case import_fixparser3.MDEntryType.SettleLowPrice:
1084
+ data.settleLowPrice = price;
1085
+ break;
1086
+ case import_fixparser3.MDEntryType.PriorSettlePrice:
1087
+ data.priorSettlePrice = price;
1088
+ break;
1089
+ case import_fixparser3.MDEntryType.SessionHighBid:
1090
+ data.sessionHighBid = price;
1091
+ break;
1092
+ case import_fixparser3.MDEntryType.SessionLowOffer:
1093
+ data.sessionLowOffer = price;
1094
+ break;
1095
+ case import_fixparser3.MDEntryType.EarlyPrices:
1096
+ data.earlyPrices = price;
1097
+ break;
1098
+ case import_fixparser3.MDEntryType.AuctionClearingPrice:
1099
+ data.auctionClearingPrice = price;
1100
+ break;
1101
+ case import_fixparser3.MDEntryType.SwapValueFactor:
1102
+ data.swapValueFactor = price;
1103
+ break;
1104
+ case import_fixparser3.MDEntryType.DailyValueAdjustmentForLongPositions:
1105
+ data.dailyValueAdjustmentForLongPositions = price;
1106
+ break;
1107
+ case import_fixparser3.MDEntryType.CumulativeValueAdjustmentForLongPositions:
1108
+ data.cumulativeValueAdjustmentForLongPositions = price;
1109
+ break;
1110
+ case import_fixparser3.MDEntryType.DailyValueAdjustmentForShortPositions:
1111
+ data.dailyValueAdjustmentForShortPositions = price;
1112
+ break;
1113
+ case import_fixparser3.MDEntryType.CumulativeValueAdjustmentForShortPositions:
1114
+ data.cumulativeValueAdjustmentForShortPositions = price;
1115
+ break;
1116
+ case import_fixparser3.MDEntryType.FixingPrice:
1117
+ data.fixingPrice = price;
1118
+ break;
1119
+ case import_fixparser3.MDEntryType.CashRate:
1120
+ data.cashRate = price;
1121
+ break;
1122
+ case import_fixparser3.MDEntryType.RecoveryRate:
1123
+ data.recoveryRate = price;
1124
+ break;
1125
+ case import_fixparser3.MDEntryType.RecoveryRateForLong:
1126
+ data.recoveryRateForLong = price;
1127
+ break;
1128
+ case import_fixparser3.MDEntryType.RecoveryRateForShort:
1129
+ data.recoveryRateForShort = price;
1130
+ break;
1131
+ case import_fixparser3.MDEntryType.MarketBid:
1132
+ data.marketBid = price;
1133
+ break;
1134
+ case import_fixparser3.MDEntryType.MarketOffer:
1135
+ data.marketOffer = price;
1136
+ break;
1137
+ case import_fixparser3.MDEntryType.ShortSaleMinPrice:
1138
+ data.shortSaleMinPrice = price;
1139
+ break;
1140
+ case import_fixparser3.MDEntryType.PreviousClosingPrice:
1141
+ data.previousClosingPrice = price;
1142
+ break;
1143
+ case import_fixparser3.MDEntryType.ThresholdLimitPriceBanding:
1144
+ data.thresholdLimitPriceBanding = price;
1145
+ break;
1146
+ case import_fixparser3.MDEntryType.DailyFinancingValue:
1147
+ data.dailyFinancingValue = price;
1148
+ break;
1149
+ case import_fixparser3.MDEntryType.AccruedFinancingValue:
1150
+ data.accruedFinancingValue = price;
1151
+ break;
1152
+ case import_fixparser3.MDEntryType.TWAP:
1153
+ data.twap = price;
1154
+ break;
1155
+ }
1156
+ }
1157
+ data.spread = data.offer - data.bid;
1158
+ if (!marketDataPrices.has(symbol)) {
1159
+ marketDataPrices.set(symbol, []);
1160
+ }
1161
+ const prices = marketDataPrices.get(symbol);
1162
+ prices.push(data);
1163
+ if (prices.length > maxPriceHistory) {
1164
+ prices.splice(0, prices.length - maxPriceHistory);
1165
+ }
1166
+ onPriceUpdate?.(symbol, data);
1167
+ const mdReqID = message.getField(import_fixparser3.Fields.MDReqID)?.value;
1168
+ if (mdReqID) {
1169
+ const callback = pendingRequests.get(mdReqID);
1170
+ if (callback) {
1171
+ callback(message);
1172
+ pendingRequests.delete(mdReqID);
1173
+ }
1174
+ }
1175
+ } else if (msgType === import_fixparser3.Messages.ExecutionReport) {
1176
+ const reqId = message.getField(import_fixparser3.Fields.ClOrdID)?.value;
1177
+ const callback = pendingRequests.get(reqId);
1178
+ if (callback) {
1179
+ callback(message);
1180
+ pendingRequests.delete(reqId);
1181
+ }
1182
+ }
1183
+ }
1184
+
822
1185
  // src/MCPLocal.ts
823
- var MCPLocal = class {
824
- parser;
1186
+ var MCPLocal = class extends MCPBase {
1187
+ /**
1188
+ * Map to store verified orders before execution
1189
+ * @private
1190
+ */
1191
+ verifiedOrders = /* @__PURE__ */ new Map();
1192
+ /**
1193
+ * Map to store pending requests and their callbacks
1194
+ * @private
1195
+ */
1196
+ pendingRequests = /* @__PURE__ */ new Map();
1197
+ /**
1198
+ * Map to store market data prices for each symbol
1199
+ * @private
1200
+ */
1201
+ marketDataPrices = /* @__PURE__ */ new Map();
1202
+ /**
1203
+ * Maximum number of price history entries to keep per symbol
1204
+ * @private
1205
+ */
1206
+ MAX_PRICE_HISTORY = 1e5;
825
1207
  server = new import_server.Server(
826
1208
  {
827
1209
  name: "fixparser",
@@ -843,90 +1225,13 @@ var MCPLocal = class {
843
1225
  }
844
1226
  );
845
1227
  transport = new import_stdio.StdioServerTransport();
846
- onReady = void 0;
847
- pendingRequests = /* @__PURE__ */ new Map();
848
- verifiedOrders = /* @__PURE__ */ new Map();
849
- marketDataPrices = /* @__PURE__ */ new Map();
850
- MAX_PRICE_HISTORY = 1e5;
851
- // Maximum number of price points to store per symbol
852
1228
  constructor({ logger, onReady }) {
853
- if (onReady) this.onReady = onReady;
1229
+ super({ logger, onReady });
854
1230
  }
855
1231
  async register(parser) {
856
1232
  this.parser = parser;
857
1233
  this.parser.addOnMessageCallback((message) => {
858
- this.parser?.logger.log({
859
- level: "info",
860
- message: `MCP Server received message: ${message.messageType}: ${message.description}`
861
- });
862
- const msgType = message.messageType;
863
- if (msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh || msgType === import_fixparser3.Messages.ExecutionReport || msgType === import_fixparser3.Messages.Reject || msgType === import_fixparser3.Messages.MarketDataIncrementalRefresh) {
864
- this.parser?.logger.log({
865
- level: "info",
866
- message: `MCP Server handling message type: ${msgType}`
867
- });
868
- let id;
869
- if (msgType === import_fixparser3.Messages.MarketDataIncrementalRefresh || msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh) {
870
- const symbol = message.getField(import_fixparser3.Fields.Symbol);
871
- const entryType = message.getField(import_fixparser3.Fields.MDEntryType);
872
- const price = message.getField(import_fixparser3.Fields.MDEntryPx);
873
- const size = message.getField(import_fixparser3.Fields.MDEntrySize);
874
- const timestamp = message.getField(import_fixparser3.Fields.MDEntryTime)?.value || Date.now();
875
- if (symbol?.value && price?.value) {
876
- const symbolStr = String(symbol.value);
877
- const priceNum = Number(price.value);
878
- const sizeNum = size?.value ? Number(size.value) : 0;
879
- const priceHistory = this.marketDataPrices.get(symbolStr) || [];
880
- const lastEntry = priceHistory[priceHistory.length - 1] || {
881
- timestamp: 0,
882
- bid: 0,
883
- offer: 0,
884
- spread: 0,
885
- volume: 0
886
- };
887
- const newEntry = {
888
- timestamp: Number(timestamp),
889
- bid: entryType?.value === import_fixparser3.MDEntryType.Bid ? priceNum : lastEntry.bid,
890
- offer: entryType?.value === import_fixparser3.MDEntryType.Offer ? priceNum : lastEntry.offer,
891
- spread: entryType?.value === import_fixparser3.MDEntryType.Offer ? priceNum - lastEntry.bid : entryType?.value === import_fixparser3.MDEntryType.Bid ? lastEntry.offer - priceNum : lastEntry.spread,
892
- volume: entryType?.value === import_fixparser3.MDEntryType.TradeVolume ? sizeNum : lastEntry.volume
893
- };
894
- priceHistory.push(newEntry);
895
- if (priceHistory.length > this.MAX_PRICE_HISTORY) {
896
- priceHistory.shift();
897
- }
898
- this.marketDataPrices.set(symbolStr, priceHistory);
899
- this.parser?.logger.log({
900
- level: "info",
901
- message: `MCP Server added ${symbol}: ${JSON.stringify(newEntry)}`
902
- });
903
- this.server.notification({
904
- method: "priceUpdate",
905
- params: {
906
- symbol: symbolStr,
907
- ...newEntry
908
- }
909
- });
910
- }
911
- }
912
- if (msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh) {
913
- const mdReqID = message.getField(import_fixparser3.Fields.MDReqID);
914
- if (mdReqID) id = String(mdReqID.value);
915
- } else if (msgType === import_fixparser3.Messages.ExecutionReport) {
916
- const clOrdID = message.getField(import_fixparser3.Fields.ClOrdID);
917
- if (clOrdID) id = String(clOrdID.value);
918
- } else if (msgType === import_fixparser3.Messages.Reject) {
919
- const refSeqNum = message.getField(import_fixparser3.Fields.RefSeqNum);
920
- if (refSeqNum) id = String(refSeqNum.value);
921
- }
922
- if (id) {
923
- const callback = this.pendingRequests.get(id);
924
- if (callback) {
925
- callback(message);
926
- this.pendingRequests.delete(id);
927
- }
928
- }
929
- }
1234
+ handleMessage(message, this.parser, this.pendingRequests, this.marketDataPrices, this.MAX_PRICE_HISTORY);
930
1235
  });
931
1236
  this.addWorkflows();
932
1237
  await this.server.connect(this.transport);
@@ -941,18 +1246,15 @@ var MCPLocal = class {
941
1246
  if (!this.server) {
942
1247
  return;
943
1248
  }
944
- this.server.setRequestHandler(
945
- import_zod.z.object({ method: import_zod.z.literal("tools/list") }),
946
- async (request, extra) => {
947
- return {
948
- tools: Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
949
- name,
950
- description,
951
- inputSchema: schema
952
- }))
953
- };
954
- }
955
- );
1249
+ this.server.setRequestHandler(import_zod.z.object({ method: import_zod.z.literal("tools/list") }), async () => {
1250
+ return {
1251
+ tools: Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
1252
+ name,
1253
+ description,
1254
+ inputSchema: schema
1255
+ }))
1256
+ };
1257
+ });
956
1258
  this.server.setRequestHandler(
957
1259
  import_zod.z.object({
958
1260
  method: import_zod.z.literal("tools/call"),
@@ -964,7 +1266,7 @@ var MCPLocal = class {
964
1266
  }).optional()
965
1267
  })
966
1268
  }),
967
- async (request, extra) => {
1269
+ async (request) => {
968
1270
  const { name, arguments: args } = request.params;
969
1271
  const toolHandlers = createToolHandlers(
970
1272
  this.parser,