fixparser-plugin-mcp 9.1.7-63c797c5 → 9.1.7-67ba45e9

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.
@@ -129,7 +129,7 @@ var toolSchemas = {
129
129
  }
130
130
  },
131
131
  executeOrder: {
132
- description: "Executes a verified order. verifyOrder must be called before executeOrder. user has to explicitly allow executeOrder.",
132
+ description: "Executes a verified order. verifyOrder must be called before executeOrder.",
133
133
  schema: {
134
134
  type: "object",
135
135
  properties: {
@@ -282,10 +282,63 @@ import QuickChart from "quickchart-js";
282
282
  var createMarketDataRequestHandler = (parser, pendingRequests) => {
283
283
  return async (args) => {
284
284
  try {
285
+ parser.logger.log({
286
+ level: "info",
287
+ message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
288
+ });
285
289
  const response = new Promise((resolve) => {
286
290
  pendingRequests.set(args.mdReqID, resolve);
291
+ parser.logger.log({
292
+ level: "info",
293
+ message: `Registered callback for market data request ID: ${args.mdReqID}`
294
+ });
287
295
  });
288
- const entryTypes = args.mdEntryTypes || [MDEntryType.Bid, MDEntryType.Offer, MDEntryType.TradeVolume];
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
+ ];
289
342
  const messageFields = [
290
343
  new Field(Fields.MsgType, Messages.MarketDataRequest),
291
344
  new Field(Fields.SenderCompID, parser.sender),
@@ -307,6 +360,10 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
307
360
  });
308
361
  const mdr = parser.createMessage(...messageFields);
309
362
  if (!parser.connected) {
363
+ parser.logger.log({
364
+ level: "error",
365
+ message: "Not connected. Cannot send market data request."
366
+ });
310
367
  return {
311
368
  content: [
312
369
  {
@@ -318,8 +375,16 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
318
375
  isError: true
319
376
  };
320
377
  }
378
+ parser.logger.log({
379
+ level: "info",
380
+ message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
381
+ });
321
382
  parser.send(mdr);
322
383
  const fixData = await response;
384
+ parser.logger.log({
385
+ level: "info",
386
+ message: `Received market data response for request ID: ${args.mdReqID}`
387
+ });
323
388
  return {
324
389
  content: [
325
390
  {
@@ -368,6 +433,9 @@ var createGetStockGraphHandler = (marketDataPrices) => {
368
433
  const offerData = priceHistory.map((point) => point.offer);
369
434
  const spreadData = priceHistory.map((point) => point.spread);
370
435
  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);
371
439
  const config = {
372
440
  type: "line",
373
441
  data: {
@@ -397,6 +465,30 @@ var createGetStockGraphHandler = (marketDataPrices) => {
397
465
  fill: false,
398
466
  tension: 0.4
399
467
  },
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
+ },
400
492
  {
401
493
  label: "Volume",
402
494
  data: volumeData,
@@ -442,7 +534,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
442
534
  content: [
443
535
  {
444
536
  type: "text",
445
- text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
537
+ text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
446
538
  uri: "getStockGraph"
447
539
  }
448
540
  ],
@@ -480,7 +572,48 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
480
572
  bid: point.bid,
481
573
  offer: point.offer,
482
574
  spread: point.spread,
483
- volume: point.volume
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
484
617
  }))
485
618
  },
486
619
  null,
@@ -495,7 +628,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
495
628
  content: [
496
629
  {
497
630
  type: "text",
498
- text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
631
+ text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
499
632
  uri: "getStockPriceHistory"
500
633
  }
501
634
  ],
@@ -603,7 +736,7 @@ Parameters verified:
603
736
  - Symbol: ${args.symbol}
604
737
  - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
605
738
 
606
- To execute this order, call the executeOrder tool with these exact same parameters.`,
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!`,
607
740
  uri: "verifyOrder"
608
741
  }
609
742
  ]
@@ -804,52 +937,256 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
804
937
 
805
938
  // src/utils/messageHandler.ts
806
939
  import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
940
+ function getEnumValue(enumObj, name) {
941
+ return enumObj[name] || name;
942
+ }
807
943
  function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
808
944
  parser.logger.log({
809
945
  level: "info",
810
946
  message: `MCP Server received message: ${message.messageType}: ${message.description}`
811
947
  });
812
948
  const msgType = message.messageType;
813
- if (msgType === Messages3.MarketDataSnapshotFullRefresh) {
949
+ if (msgType === Messages3.MarketDataSnapshotFullRefresh || msgType === Messages3.MarketDataIncrementalRefresh) {
814
950
  const symbol = message.getField(Fields3.Symbol)?.value;
815
- const entries = message.getField(Fields3.NoMDEntries)?.value;
816
- let bid = 0;
817
- let offer = 0;
818
- let volume = 0;
819
- const entryTypes = message.getFields(Fields3.MDEntryType);
820
- const entryPrices = message.getFields(Fields3.MDEntryPx);
821
- const entrySizes = message.getFields(Fields3.MDEntrySize);
822
- if (entryTypes && entryPrices && entrySizes) {
823
- for (let i = 0; i < entries; i++) {
824
- const entryType = entryTypes[i]?.value;
825
- const entryPrice = Number.parseFloat(entryPrices[i]?.value);
826
- const entrySize = Number.parseFloat(entrySizes[i]?.value);
827
- if (entryType === MDEntryType2.Bid) {
828
- bid = entryPrice;
829
- } else if (entryType === MDEntryType2.Offer) {
830
- offer = entryPrice;
831
- }
832
- volume += entrySize;
833
- }
834
- }
835
- const spread = offer - bid;
836
- const timestamp = Date.now();
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
+ });
837
961
  const data = {
838
- timestamp,
839
- bid,
840
- offer,
841
- spread,
842
- volume
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
843
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);
844
1157
  if (!marketDataPrices.has(symbol)) {
1158
+ parser.logger.log({
1159
+ level: "info",
1160
+ message: `Creating new price history array for symbol: ${symbol}`
1161
+ });
845
1162
  marketDataPrices.set(symbol, []);
846
1163
  }
847
1164
  const prices = marketDataPrices.get(symbol);
848
1165
  prices.push(data);
1166
+ parser.logger.log({
1167
+ level: "info",
1168
+ message: `Updated price history for ${symbol}. Current size: ${prices.length}`
1169
+ });
849
1170
  if (prices.length > maxPriceHistory) {
850
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
+ });
851
1176
  }
852
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
+ }
853
1190
  } else if (msgType === Messages3.ExecutionReport) {
854
1191
  const reqId = message.getField(Fields3.ClOrdID)?.value;
855
1192
  const callback = pendingRequests.get(reqId);
@@ -878,7 +1215,7 @@ var MCPLocal = class extends MCPBase {
878
1215
  */
879
1216
  marketDataPrices = /* @__PURE__ */ new Map();
880
1217
  /**
881
- * Maximum number of price points to store per symbol
1218
+ * Maximum number of price history entries to keep per symbol
882
1219
  * @private
883
1220
  */
884
1221
  MAX_PRICE_HISTORY = 1e5;
@@ -987,6 +1324,39 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
987
1324
  import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
988
1325
  import { z as z2 } from "zod";
989
1326
  var transports = {};
1327
+ function jsonSchemaToZod(schema) {
1328
+ if (schema.type === "object") {
1329
+ const shape = {};
1330
+ for (const [key, prop] of Object.entries(schema.properties || {})) {
1331
+ const propSchema = prop;
1332
+ if (propSchema.type === "string") {
1333
+ if (propSchema.enum) {
1334
+ shape[key] = z2.enum(propSchema.enum);
1335
+ } else {
1336
+ shape[key] = z2.string();
1337
+ }
1338
+ } else if (propSchema.type === "number") {
1339
+ shape[key] = z2.number();
1340
+ } else if (propSchema.type === "boolean") {
1341
+ shape[key] = z2.boolean();
1342
+ } else if (propSchema.type === "array") {
1343
+ if (propSchema.items.type === "string") {
1344
+ shape[key] = z2.array(z2.string());
1345
+ } else if (propSchema.items.type === "number") {
1346
+ shape[key] = z2.array(z2.number());
1347
+ } else if (propSchema.items.type === "boolean") {
1348
+ shape[key] = z2.array(z2.boolean());
1349
+ } else {
1350
+ shape[key] = z2.array(z2.any());
1351
+ }
1352
+ } else {
1353
+ shape[key] = z2.any();
1354
+ }
1355
+ }
1356
+ return shape;
1357
+ }
1358
+ return {};
1359
+ }
990
1360
  var MCPRemote = class extends MCPBase {
991
1361
  /**
992
1362
  * Port number the server will listen on.
@@ -1029,7 +1399,7 @@ var MCPRemote = class extends MCPBase {
1029
1399
  */
1030
1400
  marketDataPrices = /* @__PURE__ */ new Map();
1031
1401
  /**
1032
- * Maximum number of price points to store per symbol
1402
+ * Maximum number of price history entries to keep per symbol
1033
1403
  * @private
1034
1404
  */
1035
1405
  MAX_PRICE_HISTORY = 1e5;
@@ -1051,55 +1421,22 @@ var MCPRemote = class extends MCPBase {
1051
1421
  this.parser,
1052
1422
  this.pendingRequests,
1053
1423
  this.marketDataPrices,
1054
- this.MAX_PRICE_HISTORY,
1055
- (symbol, data) => {
1056
- this.mcpServer?.tool(
1057
- "priceUpdate",
1058
- {
1059
- description: "Price update notification",
1060
- schema: z2.object({
1061
- symbol: z2.string(),
1062
- timestamp: z2.number(),
1063
- bid: z2.number(),
1064
- offer: z2.number(),
1065
- spread: z2.number(),
1066
- volume: z2.number()
1067
- })
1068
- },
1069
- () => ({
1070
- content: [
1071
- {
1072
- type: "text",
1073
- text: JSON.stringify({ symbol, ...data })
1074
- }
1075
- ]
1076
- })
1077
- );
1078
- }
1424
+ this.MAX_PRICE_HISTORY
1079
1425
  );
1426
+ this.logger?.log({
1427
+ level: "info",
1428
+ message: `Market Data Prices TEST: ${JSON.stringify(this.marketDataPrices)}`
1429
+ });
1080
1430
  }
1081
1431
  });
1082
1432
  this.httpServer = createServer(async (req, res) => {
1083
- console.log(req.headers);
1084
- this.logger?.log({
1085
- level: "info",
1086
- message: `Incoming request: ${req.method} ${req.url}`
1087
- });
1088
1433
  if (!req.url || !req.method) {
1089
- this.logger?.log({
1090
- level: "error",
1091
- message: "Invalid request: missing URL or method"
1092
- });
1093
1434
  res.writeHead(400);
1094
1435
  res.end("Bad Request");
1095
1436
  return;
1096
1437
  }
1097
1438
  if (req.url === "/mcp") {
1098
1439
  const sessionId = req.headers["mcp-session-id"];
1099
- this.logger?.log({
1100
- level: "info",
1101
- message: `MCP request received. Session ID: ${sessionId || "none"}, headers: ${req.headers}`
1102
- });
1103
1440
  if (req.method === "POST") {
1104
1441
  const bodyChunks = [];
1105
1442
  req.on("data", (chunk) => {
@@ -1110,47 +1447,23 @@ var MCPRemote = class extends MCPBase {
1110
1447
  const body = Buffer.concat(bodyChunks).toString();
1111
1448
  try {
1112
1449
  parsed = JSON.parse(body);
1113
- this.logger?.log({
1114
- level: "info",
1115
- message: `Parsed request body: ${JSON.stringify(parsed)}`
1116
- });
1117
1450
  } catch (err) {
1118
- this.logger?.log({
1119
- level: "error",
1120
- message: `Failed to parse JSON body: ${err}`
1121
- });
1122
1451
  res.writeHead(400);
1123
1452
  res.end(JSON.stringify({ error: "Invalid JSON" }));
1124
1453
  return;
1125
1454
  }
1126
1455
  let transport;
1127
1456
  if (sessionId && transports[sessionId]) {
1128
- this.logger?.log({
1129
- level: "info",
1130
- message: `Using existing transport for session: ${sessionId}`
1131
- });
1132
1457
  transport = transports[sessionId];
1133
1458
  } else if (!sessionId && req.method === "POST" && isInitializeRequest(parsed)) {
1134
- this.logger?.log({
1135
- level: "info",
1136
- message: "Creating new transport for initialization request"
1137
- });
1138
1459
  transport = new StreamableHTTPServerTransport({
1139
1460
  sessionIdGenerator: () => randomUUID(),
1140
1461
  onsessioninitialized: (sessionId2) => {
1141
- this.logger?.log({
1142
- level: "info",
1143
- message: `New session initialized: ${sessionId2}`
1144
- });
1145
1462
  transports[sessionId2] = transport;
1146
1463
  }
1147
1464
  });
1148
1465
  transport.onclose = () => {
1149
1466
  if (transport.sessionId) {
1150
- this.logger?.log({
1151
- level: "info",
1152
- message: `Session closed: ${transport.sessionId}`
1153
- });
1154
1467
  delete transports[transport.sessionId];
1155
1468
  }
1156
1469
  };
@@ -1161,10 +1474,6 @@ var MCPRemote = class extends MCPBase {
1161
1474
  this.setupTools();
1162
1475
  await this.mcpServer.connect(transport);
1163
1476
  } else {
1164
- this.logger?.log({
1165
- level: "error",
1166
- message: "Invalid request: No valid session ID provided"
1167
- });
1168
1477
  res.writeHead(400, { "Content-Type": "application/json" });
1169
1478
  res.end(
1170
1479
  JSON.stringify({
@@ -1180,10 +1489,6 @@ var MCPRemote = class extends MCPBase {
1180
1489
  }
1181
1490
  try {
1182
1491
  await transport.handleRequest(req, res, parsed);
1183
- this.logger?.log({
1184
- level: "info",
1185
- message: "Request handled successfully"
1186
- });
1187
1492
  } catch (error) {
1188
1493
  this.logger?.log({
1189
1494
  level: "error",
@@ -1194,10 +1499,6 @@ var MCPRemote = class extends MCPBase {
1194
1499
  });
1195
1500
  } else if (req.method === "GET" || req.method === "DELETE") {
1196
1501
  if (!sessionId || !transports[sessionId]) {
1197
- this.logger?.log({
1198
- level: "error",
1199
- message: `Invalid session ID for ${req.method} request: ${sessionId}`
1200
- });
1201
1502
  res.writeHead(400);
1202
1503
  res.end("Invalid or missing session ID");
1203
1504
  return;
@@ -1205,10 +1506,6 @@ var MCPRemote = class extends MCPBase {
1205
1506
  const transport = transports[sessionId];
1206
1507
  try {
1207
1508
  await transport.handleRequest(req, res);
1208
- this.logger?.log({
1209
- level: "info",
1210
- message: `${req.method} request handled successfully for session: ${sessionId}`
1211
- });
1212
1509
  } catch (error) {
1213
1510
  this.logger?.log({
1214
1511
  level: "error",
@@ -1225,10 +1522,6 @@ var MCPRemote = class extends MCPBase {
1225
1522
  res.end("Method Not Allowed");
1226
1523
  }
1227
1524
  } else {
1228
- this.logger?.log({
1229
- level: "error",
1230
- message: `Not found: ${req.url}`
1231
- });
1232
1525
  res.writeHead(404);
1233
1526
  res.end("Not Found");
1234
1527
  }
@@ -1258,69 +1551,40 @@ var MCPRemote = class extends MCPBase {
1258
1551
  });
1259
1552
  return;
1260
1553
  }
1261
- this.mcpServer.tool(
1262
- "tools/list",
1263
- {
1264
- description: "List available tools",
1265
- schema: z2.object({})
1266
- },
1267
- async () => {
1268
- return {
1269
- content: [
1270
- {
1271
- type: "text",
1272
- text: JSON.stringify(
1273
- Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
1274
- name,
1275
- description,
1276
- inputSchema: schema
1277
- }))
1278
- )
1279
- }
1280
- ]
1281
- };
1282
- }
1554
+ const toolHandlers = createToolHandlers(
1555
+ this.parser,
1556
+ this.verifiedOrders,
1557
+ this.pendingRequests,
1558
+ this.marketDataPrices
1283
1559
  );
1284
- this.mcpServer.tool(
1285
- "tools/call",
1286
- {
1287
- description: "Call a tool",
1288
- schema: z2.object({
1289
- name: z2.string(),
1290
- arguments: z2.any(),
1291
- _meta: z2.object({
1292
- progressToken: z2.number()
1293
- }).optional()
1294
- })
1295
- },
1296
- async (request) => {
1297
- const { name, arguments: args } = request;
1298
- const toolHandlers = createToolHandlers(
1299
- this.parser,
1300
- this.verifiedOrders,
1301
- this.pendingRequests,
1302
- this.marketDataPrices
1303
- );
1304
- const handler = toolHandlers[name];
1305
- if (!handler) {
1560
+ Object.entries(toolSchemas).forEach(([name, { description, schema }]) => {
1561
+ this.mcpServer?.registerTool(
1562
+ name,
1563
+ {
1564
+ description,
1565
+ inputSchema: jsonSchemaToZod(schema)
1566
+ },
1567
+ async (args) => {
1568
+ const handler = toolHandlers[name];
1569
+ if (!handler) {
1570
+ return {
1571
+ content: [
1572
+ {
1573
+ type: "text",
1574
+ text: `Tool not found: ${name}`
1575
+ }
1576
+ ],
1577
+ isError: true
1578
+ };
1579
+ }
1580
+ const result = await handler(args);
1306
1581
  return {
1307
- content: [
1308
- {
1309
- type: "text",
1310
- text: `Tool not found: ${name}`,
1311
- uri: name
1312
- }
1313
- ],
1314
- isError: true
1582
+ content: result.content,
1583
+ isError: result.isError
1315
1584
  };
1316
1585
  }
1317
- const result = await handler(args);
1318
- return {
1319
- content: result.content,
1320
- isError: result.isError
1321
- };
1322
- }
1323
- );
1586
+ );
1587
+ });
1324
1588
  }
1325
1589
  };
1326
1590
  export {