fixparser-plugin-mcp 9.1.7-67ba45e9 → 9.1.7-70682ed6

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.
@@ -1,51 +1,9 @@
1
1
  // src/MCPLocal.ts
2
2
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
4
5
  import { z } from "zod";
5
6
 
6
- // src/MCPBase.ts
7
- var MCPBase = class {
8
- /**
9
- * Optional logger instance for diagnostics and output.
10
- * @protected
11
- */
12
- logger;
13
- /**
14
- * FIXParser instance, set during plugin register().
15
- * @protected
16
- */
17
- parser;
18
- /**
19
- * Called when server is setup and listening.
20
- * @protected
21
- */
22
- onReady = void 0;
23
- /**
24
- * Map to store verified orders before execution
25
- * @protected
26
- */
27
- verifiedOrders = /* @__PURE__ */ new Map();
28
- /**
29
- * Map to store pending market data requests
30
- * @protected
31
- */
32
- pendingRequests = /* @__PURE__ */ new Map();
33
- /**
34
- * Map to store market data prices
35
- * @protected
36
- */
37
- marketDataPrices = /* @__PURE__ */ new Map();
38
- /**
39
- * Maximum number of price history entries to keep per symbol
40
- * @protected
41
- */
42
- MAX_PRICE_HISTORY = 1e5;
43
- constructor({ logger, onReady }) {
44
- this.logger = logger;
45
- this.onReady = onReady;
46
- }
47
- };
48
-
49
7
  // src/schemas/schemas.ts
50
8
  var toolSchemas = {
51
9
  parse: {
@@ -129,7 +87,7 @@ var toolSchemas = {
129
87
  }
130
88
  },
131
89
  executeOrder: {
132
- description: "Executes a verified order. verifyOrder must be called before executeOrder.",
90
+ description: "Executes a verified order. verifyOrder must be called before executeOrder. user has to explicitly allow executeOrder.",
133
91
  schema: {
134
92
  type: "object",
135
93
  properties: {
@@ -282,63 +240,10 @@ import QuickChart from "quickchart-js";
282
240
  var createMarketDataRequestHandler = (parser, pendingRequests) => {
283
241
  return async (args) => {
284
242
  try {
285
- parser.logger.log({
286
- level: "info",
287
- message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
288
- });
289
243
  const response = new Promise((resolve) => {
290
244
  pendingRequests.set(args.mdReqID, resolve);
291
- parser.logger.log({
292
- level: "info",
293
- message: `Registered callback for market data request ID: ${args.mdReqID}`
294
- });
295
245
  });
296
- const entryTypes = args.mdEntryTypes || [
297
- MDEntryType.Bid,
298
- MDEntryType.Offer,
299
- MDEntryType.Trade,
300
- MDEntryType.IndexValue,
301
- MDEntryType.OpeningPrice,
302
- MDEntryType.ClosingPrice,
303
- MDEntryType.SettlementPrice,
304
- MDEntryType.TradingSessionHighPrice,
305
- MDEntryType.TradingSessionLowPrice,
306
- MDEntryType.VWAP,
307
- MDEntryType.Imbalance,
308
- MDEntryType.TradeVolume,
309
- MDEntryType.OpenInterest,
310
- MDEntryType.CompositeUnderlyingPrice,
311
- MDEntryType.SimulatedSellPrice,
312
- MDEntryType.SimulatedBuyPrice,
313
- MDEntryType.MarginRate,
314
- MDEntryType.MidPrice,
315
- MDEntryType.EmptyBook,
316
- MDEntryType.SettleHighPrice,
317
- MDEntryType.SettleLowPrice,
318
- MDEntryType.PriorSettlePrice,
319
- MDEntryType.SessionHighBid,
320
- MDEntryType.SessionLowOffer,
321
- MDEntryType.EarlyPrices,
322
- MDEntryType.AuctionClearingPrice,
323
- MDEntryType.SwapValueFactor,
324
- MDEntryType.DailyValueAdjustmentForLongPositions,
325
- MDEntryType.CumulativeValueAdjustmentForLongPositions,
326
- MDEntryType.DailyValueAdjustmentForShortPositions,
327
- MDEntryType.CumulativeValueAdjustmentForShortPositions,
328
- MDEntryType.FixingPrice,
329
- MDEntryType.CashRate,
330
- MDEntryType.RecoveryRate,
331
- MDEntryType.RecoveryRateForLong,
332
- MDEntryType.RecoveryRateForShort,
333
- MDEntryType.MarketBid,
334
- MDEntryType.MarketOffer,
335
- MDEntryType.ShortSaleMinPrice,
336
- MDEntryType.PreviousClosingPrice,
337
- MDEntryType.ThresholdLimitPriceBanding,
338
- MDEntryType.DailyFinancingValue,
339
- MDEntryType.AccruedFinancingValue,
340
- MDEntryType.TWAP
341
- ];
246
+ const entryTypes = args.mdEntryTypes || [MDEntryType.Bid, MDEntryType.Offer, MDEntryType.TradeVolume];
342
247
  const messageFields = [
343
248
  new Field(Fields.MsgType, Messages.MarketDataRequest),
344
249
  new Field(Fields.SenderCompID, parser.sender),
@@ -360,10 +265,6 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
360
265
  });
361
266
  const mdr = parser.createMessage(...messageFields);
362
267
  if (!parser.connected) {
363
- parser.logger.log({
364
- level: "error",
365
- message: "Not connected. Cannot send market data request."
366
- });
367
268
  return {
368
269
  content: [
369
270
  {
@@ -375,16 +276,8 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
375
276
  isError: true
376
277
  };
377
278
  }
378
- parser.logger.log({
379
- level: "info",
380
- message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
381
- });
382
279
  parser.send(mdr);
383
280
  const fixData = await response;
384
- parser.logger.log({
385
- level: "info",
386
- message: `Received market data response for request ID: ${args.mdReqID}`
387
- });
388
281
  return {
389
282
  content: [
390
283
  {
@@ -425,17 +318,13 @@ var createGetStockGraphHandler = (marketDataPrices) => {
425
318
  };
426
319
  }
427
320
  const chart = new QuickChart();
428
- chart.setWidth(1200);
429
- chart.setHeight(600);
430
- chart.setBackgroundColor("transparent");
321
+ chart.setWidth(600);
322
+ chart.setHeight(300);
431
323
  const labels = priceHistory.map((point) => new Date(point.timestamp).toLocaleTimeString());
432
324
  const bidData = priceHistory.map((point) => point.bid);
433
325
  const offerData = priceHistory.map((point) => point.offer);
434
326
  const spreadData = priceHistory.map((point) => point.spread);
435
327
  const volumeData = priceHistory.map((point) => point.volume);
436
- const tradeData = priceHistory.map((point) => point.trade);
437
- const vwapData = priceHistory.map((point) => point.vwap);
438
- const twapData = priceHistory.map((point) => point.twap);
439
328
  const config = {
440
329
  type: "line",
441
330
  data: {
@@ -465,30 +354,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
465
354
  fill: false,
466
355
  tension: 0.4
467
356
  },
468
- {
469
- label: "Trade",
470
- data: tradeData,
471
- borderColor: "#ffc107",
472
- backgroundColor: "rgba(255, 193, 7, 0.1)",
473
- fill: false,
474
- tension: 0.4
475
- },
476
- {
477
- label: "VWAP",
478
- data: vwapData,
479
- borderColor: "#17a2b8",
480
- backgroundColor: "rgba(23, 162, 184, 0.1)",
481
- fill: false,
482
- tension: 0.4
483
- },
484
- {
485
- label: "TWAP",
486
- data: twapData,
487
- borderColor: "#6610f2",
488
- backgroundColor: "rgba(102, 16, 242, 0.1)",
489
- fill: false,
490
- tension: 0.4
491
- },
492
357
  {
493
358
  label: "Volume",
494
359
  data: volumeData,
@@ -516,16 +381,18 @@ var createGetStockGraphHandler = (marketDataPrices) => {
516
381
  };
517
382
  chart.setConfig(config);
518
383
  const imageBuffer = await chart.toBinary();
519
- const base64 = imageBuffer.toString("base64");
384
+ const base64Image = imageBuffer.toString("base64");
520
385
  return {
521
386
  content: [
522
387
  {
523
- type: "resource",
524
- resource: {
525
- uri: "resource://graph",
526
- mimeType: "image/png",
527
- blob: base64
528
- }
388
+ type: "image",
389
+ image: {
390
+ source: {
391
+ data: `data:image/png;base64,${base64Image}`
392
+ }
393
+ },
394
+ uri: "getStockGraph",
395
+ mimeType: "image/png"
529
396
  }
530
397
  ]
531
398
  };
@@ -534,7 +401,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
534
401
  content: [
535
402
  {
536
403
  type: "text",
537
- text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
404
+ text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
538
405
  uri: "getStockGraph"
539
406
  }
540
407
  ],
@@ -572,48 +439,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
572
439
  bid: point.bid,
573
440
  offer: point.offer,
574
441
  spread: point.spread,
575
- volume: point.volume,
576
- trade: point.trade,
577
- indexValue: point.indexValue,
578
- openingPrice: point.openingPrice,
579
- closingPrice: point.closingPrice,
580
- settlementPrice: point.settlementPrice,
581
- tradingSessionHighPrice: point.tradingSessionHighPrice,
582
- tradingSessionLowPrice: point.tradingSessionLowPrice,
583
- vwap: point.vwap,
584
- imbalance: point.imbalance,
585
- openInterest: point.openInterest,
586
- compositeUnderlyingPrice: point.compositeUnderlyingPrice,
587
- simulatedSellPrice: point.simulatedSellPrice,
588
- simulatedBuyPrice: point.simulatedBuyPrice,
589
- marginRate: point.marginRate,
590
- midPrice: point.midPrice,
591
- emptyBook: point.emptyBook,
592
- settleHighPrice: point.settleHighPrice,
593
- settleLowPrice: point.settleLowPrice,
594
- priorSettlePrice: point.priorSettlePrice,
595
- sessionHighBid: point.sessionHighBid,
596
- sessionLowOffer: point.sessionLowOffer,
597
- earlyPrices: point.earlyPrices,
598
- auctionClearingPrice: point.auctionClearingPrice,
599
- swapValueFactor: point.swapValueFactor,
600
- dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
601
- cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
602
- dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
603
- cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
604
- fixingPrice: point.fixingPrice,
605
- cashRate: point.cashRate,
606
- recoveryRate: point.recoveryRate,
607
- recoveryRateForLong: point.recoveryRateForLong,
608
- recoveryRateForShort: point.recoveryRateForShort,
609
- marketBid: point.marketBid,
610
- marketOffer: point.marketOffer,
611
- shortSaleMinPrice: point.shortSaleMinPrice,
612
- previousClosingPrice: point.previousClosingPrice,
613
- thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
614
- dailyFinancingValue: point.dailyFinancingValue,
615
- accruedFinancingValue: point.accruedFinancingValue,
616
- twap: point.twap
442
+ volume: point.volume
617
443
  }))
618
444
  },
619
445
  null,
@@ -628,7 +454,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
628
454
  content: [
629
455
  {
630
456
  type: "text",
631
- text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
457
+ text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
632
458
  uri: "getStockPriceHistory"
633
459
  }
634
460
  ],
@@ -736,7 +562,7 @@ Parameters verified:
736
562
  - Symbol: ${args.symbol}
737
563
  - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
738
564
 
739
- To execute this order, call the executeOrder tool with these exact same parameters. Important: The user has to explicitly confirm before executeOrder is called!`,
565
+ To execute this order, call the executeOrder tool with these exact same parameters.`,
740
566
  uri: "verifyOrder"
741
567
  }
742
568
  ]
@@ -935,290 +761,9 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
935
761
  getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
936
762
  });
937
763
 
938
- // src/utils/messageHandler.ts
939
- import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
940
- function getEnumValue(enumObj, name) {
941
- return enumObj[name] || name;
942
- }
943
- function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
944
- parser.logger.log({
945
- level: "info",
946
- message: `MCP Server received message: ${message.messageType}: ${message.description}`
947
- });
948
- const msgType = message.messageType;
949
- if (msgType === Messages3.MarketDataSnapshotFullRefresh || msgType === Messages3.MarketDataIncrementalRefresh) {
950
- const symbol = message.getField(Fields3.Symbol)?.value;
951
- parser.logger.log({
952
- level: "info",
953
- message: `Processing market data for symbol: ${symbol}`
954
- });
955
- const fixJson = message.toFIXJSON();
956
- const entries = fixJson.Body?.NoMDEntries || [];
957
- parser.logger.log({
958
- level: "info",
959
- message: `Found ${entries.length} market data entries`
960
- });
961
- const data = {
962
- timestamp: Date.now(),
963
- bid: 0,
964
- offer: 0,
965
- spread: 0,
966
- volume: 0,
967
- trade: 0,
968
- indexValue: 0,
969
- openingPrice: 0,
970
- closingPrice: 0,
971
- settlementPrice: 0,
972
- tradingSessionHighPrice: 0,
973
- tradingSessionLowPrice: 0,
974
- vwap: 0,
975
- imbalance: 0,
976
- openInterest: 0,
977
- compositeUnderlyingPrice: 0,
978
- simulatedSellPrice: 0,
979
- simulatedBuyPrice: 0,
980
- marginRate: 0,
981
- midPrice: 0,
982
- emptyBook: 0,
983
- settleHighPrice: 0,
984
- settleLowPrice: 0,
985
- priorSettlePrice: 0,
986
- sessionHighBid: 0,
987
- sessionLowOffer: 0,
988
- earlyPrices: 0,
989
- auctionClearingPrice: 0,
990
- swapValueFactor: 0,
991
- dailyValueAdjustmentForLongPositions: 0,
992
- cumulativeValueAdjustmentForLongPositions: 0,
993
- dailyValueAdjustmentForShortPositions: 0,
994
- cumulativeValueAdjustmentForShortPositions: 0,
995
- fixingPrice: 0,
996
- cashRate: 0,
997
- recoveryRate: 0,
998
- recoveryRateForLong: 0,
999
- recoveryRateForShort: 0,
1000
- marketBid: 0,
1001
- marketOffer: 0,
1002
- shortSaleMinPrice: 0,
1003
- previousClosingPrice: 0,
1004
- thresholdLimitPriceBanding: 0,
1005
- dailyFinancingValue: 0,
1006
- accruedFinancingValue: 0,
1007
- twap: 0
1008
- };
1009
- for (const entry of entries) {
1010
- const entryType = entry.MDEntryType;
1011
- const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
1012
- const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
1013
- if (entryType === MDEntryType2.Bid || entryType === MDEntryType2.Offer || entryType === MDEntryType2.TradeVolume) {
1014
- parser.logger.log({
1015
- level: "info",
1016
- message: `Market Data Entry - Type: ${entryType}, Price: ${price}, Size: ${size}`
1017
- });
1018
- }
1019
- const enumValue = getEnumValue(MDEntryType2, entryType);
1020
- switch (enumValue) {
1021
- case MDEntryType2.Bid:
1022
- data.bid = price;
1023
- break;
1024
- case MDEntryType2.Offer:
1025
- data.offer = price;
1026
- break;
1027
- case MDEntryType2.Trade:
1028
- data.trade = price;
1029
- break;
1030
- case MDEntryType2.IndexValue:
1031
- data.indexValue = price;
1032
- break;
1033
- case MDEntryType2.OpeningPrice:
1034
- data.openingPrice = price;
1035
- break;
1036
- case MDEntryType2.ClosingPrice:
1037
- data.closingPrice = price;
1038
- break;
1039
- case MDEntryType2.SettlementPrice:
1040
- data.settlementPrice = price;
1041
- break;
1042
- case MDEntryType2.TradingSessionHighPrice:
1043
- data.tradingSessionHighPrice = price;
1044
- break;
1045
- case MDEntryType2.TradingSessionLowPrice:
1046
- data.tradingSessionLowPrice = price;
1047
- break;
1048
- case MDEntryType2.VWAP:
1049
- data.vwap = price;
1050
- break;
1051
- case MDEntryType2.Imbalance:
1052
- data.imbalance = size;
1053
- break;
1054
- case MDEntryType2.TradeVolume:
1055
- data.volume = size;
1056
- break;
1057
- case MDEntryType2.OpenInterest:
1058
- data.openInterest = size;
1059
- break;
1060
- case MDEntryType2.CompositeUnderlyingPrice:
1061
- data.compositeUnderlyingPrice = price;
1062
- break;
1063
- case MDEntryType2.SimulatedSellPrice:
1064
- data.simulatedSellPrice = price;
1065
- break;
1066
- case MDEntryType2.SimulatedBuyPrice:
1067
- data.simulatedBuyPrice = price;
1068
- break;
1069
- case MDEntryType2.MarginRate:
1070
- data.marginRate = price;
1071
- break;
1072
- case MDEntryType2.MidPrice:
1073
- data.midPrice = price;
1074
- break;
1075
- case MDEntryType2.EmptyBook:
1076
- data.emptyBook = 1;
1077
- break;
1078
- case MDEntryType2.SettleHighPrice:
1079
- data.settleHighPrice = price;
1080
- break;
1081
- case MDEntryType2.SettleLowPrice:
1082
- data.settleLowPrice = price;
1083
- break;
1084
- case MDEntryType2.PriorSettlePrice:
1085
- data.priorSettlePrice = price;
1086
- break;
1087
- case MDEntryType2.SessionHighBid:
1088
- data.sessionHighBid = price;
1089
- break;
1090
- case MDEntryType2.SessionLowOffer:
1091
- data.sessionLowOffer = price;
1092
- break;
1093
- case MDEntryType2.EarlyPrices:
1094
- data.earlyPrices = price;
1095
- break;
1096
- case MDEntryType2.AuctionClearingPrice:
1097
- data.auctionClearingPrice = price;
1098
- break;
1099
- case MDEntryType2.SwapValueFactor:
1100
- data.swapValueFactor = price;
1101
- break;
1102
- case MDEntryType2.DailyValueAdjustmentForLongPositions:
1103
- data.dailyValueAdjustmentForLongPositions = price;
1104
- break;
1105
- case MDEntryType2.CumulativeValueAdjustmentForLongPositions:
1106
- data.cumulativeValueAdjustmentForLongPositions = price;
1107
- break;
1108
- case MDEntryType2.DailyValueAdjustmentForShortPositions:
1109
- data.dailyValueAdjustmentForShortPositions = price;
1110
- break;
1111
- case MDEntryType2.CumulativeValueAdjustmentForShortPositions:
1112
- data.cumulativeValueAdjustmentForShortPositions = price;
1113
- break;
1114
- case MDEntryType2.FixingPrice:
1115
- data.fixingPrice = price;
1116
- break;
1117
- case MDEntryType2.CashRate:
1118
- data.cashRate = price;
1119
- break;
1120
- case MDEntryType2.RecoveryRate:
1121
- data.recoveryRate = price;
1122
- break;
1123
- case MDEntryType2.RecoveryRateForLong:
1124
- data.recoveryRateForLong = price;
1125
- break;
1126
- case MDEntryType2.RecoveryRateForShort:
1127
- data.recoveryRateForShort = price;
1128
- break;
1129
- case MDEntryType2.MarketBid:
1130
- data.marketBid = price;
1131
- break;
1132
- case MDEntryType2.MarketOffer:
1133
- data.marketOffer = price;
1134
- break;
1135
- case MDEntryType2.ShortSaleMinPrice:
1136
- data.shortSaleMinPrice = price;
1137
- break;
1138
- case MDEntryType2.PreviousClosingPrice:
1139
- data.previousClosingPrice = price;
1140
- break;
1141
- case MDEntryType2.ThresholdLimitPriceBanding:
1142
- data.thresholdLimitPriceBanding = price;
1143
- break;
1144
- case MDEntryType2.DailyFinancingValue:
1145
- data.dailyFinancingValue = price;
1146
- break;
1147
- case MDEntryType2.AccruedFinancingValue:
1148
- data.accruedFinancingValue = price;
1149
- break;
1150
- case MDEntryType2.TWAP:
1151
- data.twap = price;
1152
- break;
1153
- }
1154
- }
1155
- data.spread = data.offer - data.bid;
1156
- console.log(">>>>>>>>>>>>>>>>>>>>", data);
1157
- if (!marketDataPrices.has(symbol)) {
1158
- parser.logger.log({
1159
- level: "info",
1160
- message: `Creating new price history array for symbol: ${symbol}`
1161
- });
1162
- marketDataPrices.set(symbol, []);
1163
- }
1164
- const prices = marketDataPrices.get(symbol);
1165
- prices.push(data);
1166
- parser.logger.log({
1167
- level: "info",
1168
- message: `Updated price history for ${symbol}. Current size: ${prices.length}`
1169
- });
1170
- if (prices.length > maxPriceHistory) {
1171
- prices.splice(0, prices.length - maxPriceHistory);
1172
- parser.logger.log({
1173
- level: "info",
1174
- message: `Trimmed price history for ${symbol} to ${maxPriceHistory} entries`
1175
- });
1176
- }
1177
- onPriceUpdate?.(symbol, data);
1178
- const mdReqID = message.getField(Fields3.MDReqID)?.value;
1179
- if (mdReqID) {
1180
- const callback = pendingRequests.get(mdReqID);
1181
- if (callback) {
1182
- callback(message);
1183
- pendingRequests.delete(mdReqID);
1184
- parser.logger.log({
1185
- level: "info",
1186
- message: `Resolved market data request for ID: ${mdReqID}`
1187
- });
1188
- }
1189
- }
1190
- } else if (msgType === Messages3.ExecutionReport) {
1191
- const reqId = message.getField(Fields3.ClOrdID)?.value;
1192
- const callback = pendingRequests.get(reqId);
1193
- if (callback) {
1194
- callback(message);
1195
- pendingRequests.delete(reqId);
1196
- }
1197
- }
1198
- }
1199
-
1200
764
  // src/MCPLocal.ts
1201
- var MCPLocal = class extends MCPBase {
1202
- /**
1203
- * Map to store verified orders before execution
1204
- * @private
1205
- */
1206
- verifiedOrders = /* @__PURE__ */ new Map();
1207
- /**
1208
- * Map to store pending requests and their callbacks
1209
- * @private
1210
- */
1211
- pendingRequests = /* @__PURE__ */ new Map();
1212
- /**
1213
- * Map to store market data prices for each symbol
1214
- * @private
1215
- */
1216
- marketDataPrices = /* @__PURE__ */ new Map();
1217
- /**
1218
- * Maximum number of price history entries to keep per symbol
1219
- * @private
1220
- */
1221
- MAX_PRICE_HISTORY = 1e5;
765
+ var MCPLocal = class {
766
+ parser;
1222
767
  server = new Server(
1223
768
  {
1224
769
  name: "fixparser",
@@ -1240,13 +785,90 @@ var MCPLocal = class extends MCPBase {
1240
785
  }
1241
786
  );
1242
787
  transport = new StdioServerTransport();
788
+ onReady = void 0;
789
+ pendingRequests = /* @__PURE__ */ new Map();
790
+ verifiedOrders = /* @__PURE__ */ new Map();
791
+ marketDataPrices = /* @__PURE__ */ new Map();
792
+ MAX_PRICE_HISTORY = 1e5;
793
+ // Maximum number of price points to store per symbol
1243
794
  constructor({ logger, onReady }) {
1244
- super({ logger, onReady });
795
+ if (onReady) this.onReady = onReady;
1245
796
  }
1246
797
  async register(parser) {
1247
798
  this.parser = parser;
1248
799
  this.parser.addOnMessageCallback((message) => {
1249
- handleMessage(message, this.parser, this.pendingRequests, this.marketDataPrices, this.MAX_PRICE_HISTORY);
800
+ this.parser?.logger.log({
801
+ level: "info",
802
+ message: `MCP Server received message: ${message.messageType}: ${message.description}`
803
+ });
804
+ const msgType = message.messageType;
805
+ if (msgType === Messages3.MarketDataSnapshotFullRefresh || msgType === Messages3.ExecutionReport || msgType === Messages3.Reject || msgType === Messages3.MarketDataIncrementalRefresh) {
806
+ this.parser?.logger.log({
807
+ level: "info",
808
+ message: `MCP Server handling message type: ${msgType}`
809
+ });
810
+ let id;
811
+ if (msgType === Messages3.MarketDataIncrementalRefresh || msgType === Messages3.MarketDataSnapshotFullRefresh) {
812
+ const symbol = message.getField(Fields3.Symbol);
813
+ const entryType = message.getField(Fields3.MDEntryType);
814
+ const price = message.getField(Fields3.MDEntryPx);
815
+ const size = message.getField(Fields3.MDEntrySize);
816
+ const timestamp = message.getField(Fields3.MDEntryTime)?.value || Date.now();
817
+ if (symbol?.value && price?.value) {
818
+ const symbolStr = String(symbol.value);
819
+ const priceNum = Number(price.value);
820
+ const sizeNum = size?.value ? Number(size.value) : 0;
821
+ const priceHistory = this.marketDataPrices.get(symbolStr) || [];
822
+ const lastEntry = priceHistory[priceHistory.length - 1] || {
823
+ timestamp: 0,
824
+ bid: 0,
825
+ offer: 0,
826
+ spread: 0,
827
+ volume: 0
828
+ };
829
+ const newEntry = {
830
+ timestamp: Number(timestamp),
831
+ bid: entryType?.value === MDEntryType2.Bid ? priceNum : lastEntry.bid,
832
+ offer: entryType?.value === MDEntryType2.Offer ? priceNum : lastEntry.offer,
833
+ spread: entryType?.value === MDEntryType2.Offer ? priceNum - lastEntry.bid : entryType?.value === MDEntryType2.Bid ? lastEntry.offer - priceNum : lastEntry.spread,
834
+ volume: entryType?.value === MDEntryType2.TradeVolume ? sizeNum : lastEntry.volume
835
+ };
836
+ priceHistory.push(newEntry);
837
+ if (priceHistory.length > this.MAX_PRICE_HISTORY) {
838
+ priceHistory.shift();
839
+ }
840
+ this.marketDataPrices.set(symbolStr, priceHistory);
841
+ this.parser?.logger.log({
842
+ level: "info",
843
+ message: `MCP Server added ${symbol}: ${JSON.stringify(newEntry)}`
844
+ });
845
+ this.server.notification({
846
+ method: "priceUpdate",
847
+ params: {
848
+ symbol: symbolStr,
849
+ ...newEntry
850
+ }
851
+ });
852
+ }
853
+ }
854
+ if (msgType === Messages3.MarketDataSnapshotFullRefresh) {
855
+ const mdReqID = message.getField(Fields3.MDReqID);
856
+ if (mdReqID) id = String(mdReqID.value);
857
+ } else if (msgType === Messages3.ExecutionReport) {
858
+ const clOrdID = message.getField(Fields3.ClOrdID);
859
+ if (clOrdID) id = String(clOrdID.value);
860
+ } else if (msgType === Messages3.Reject) {
861
+ const refSeqNum = message.getField(Fields3.RefSeqNum);
862
+ if (refSeqNum) id = String(refSeqNum.value);
863
+ }
864
+ if (id) {
865
+ const callback = this.pendingRequests.get(id);
866
+ if (callback) {
867
+ callback(message);
868
+ this.pendingRequests.delete(id);
869
+ }
870
+ }
871
+ }
1250
872
  });
1251
873
  this.addWorkflows();
1252
874
  await this.server.connect(this.transport);
@@ -1261,15 +883,18 @@ var MCPLocal = class extends MCPBase {
1261
883
  if (!this.server) {
1262
884
  return;
1263
885
  }
1264
- this.server.setRequestHandler(z.object({ method: z.literal("tools/list") }), async () => {
1265
- return {
1266
- tools: Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
1267
- name,
1268
- description,
1269
- inputSchema: schema
1270
- }))
1271
- };
1272
- });
886
+ this.server.setRequestHandler(
887
+ z.object({ method: z.literal("tools/list") }),
888
+ async (request, extra) => {
889
+ return {
890
+ tools: Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
891
+ name,
892
+ description,
893
+ inputSchema: schema
894
+ }))
895
+ };
896
+ }
897
+ );
1273
898
  this.server.setRequestHandler(
1274
899
  z.object({
1275
900
  method: z.literal("tools/call"),
@@ -1281,7 +906,7 @@ var MCPLocal = class extends MCPBase {
1281
906
  }).optional()
1282
907
  })
1283
908
  }),
1284
- async (request) => {
909
+ async (request, extra) => {
1285
910
  const { name, arguments: args } = request.params;
1286
911
  const toolHandlers = createToolHandlers(
1287
912
  this.parser,