fixparser-plugin-mcp 9.1.7-620b3399 → 9.1.7-63c797c5

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.
@@ -166,7 +166,7 @@ var toolSchemas = {
166
166
  }
167
167
  },
168
168
  executeOrder: {
169
- description: "Executes a verified order. verifyOrder must be called before executeOrder.",
169
+ description: "Executes a verified order. verifyOrder must be called before executeOrder. user has to explicitly allow executeOrder.",
170
170
  schema: {
171
171
  type: "object",
172
172
  properties: {
@@ -319,63 +319,10 @@ var import_quickchart_js = __toESM(require("quickchart-js"), 1);
319
319
  var createMarketDataRequestHandler = (parser, pendingRequests) => {
320
320
  return async (args) => {
321
321
  try {
322
- parser.logger.log({
323
- level: "info",
324
- message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
325
- });
326
322
  const response = new Promise((resolve) => {
327
323
  pendingRequests.set(args.mdReqID, resolve);
328
- parser.logger.log({
329
- level: "info",
330
- message: `Registered callback for market data request ID: ${args.mdReqID}`
331
- });
332
324
  });
333
- const entryTypes = args.mdEntryTypes || [
334
- import_fixparser.MDEntryType.Bid,
335
- import_fixparser.MDEntryType.Offer,
336
- import_fixparser.MDEntryType.Trade,
337
- import_fixparser.MDEntryType.IndexValue,
338
- import_fixparser.MDEntryType.OpeningPrice,
339
- import_fixparser.MDEntryType.ClosingPrice,
340
- import_fixparser.MDEntryType.SettlementPrice,
341
- import_fixparser.MDEntryType.TradingSessionHighPrice,
342
- import_fixparser.MDEntryType.TradingSessionLowPrice,
343
- import_fixparser.MDEntryType.VWAP,
344
- import_fixparser.MDEntryType.Imbalance,
345
- import_fixparser.MDEntryType.TradeVolume,
346
- import_fixparser.MDEntryType.OpenInterest,
347
- import_fixparser.MDEntryType.CompositeUnderlyingPrice,
348
- import_fixparser.MDEntryType.SimulatedSellPrice,
349
- import_fixparser.MDEntryType.SimulatedBuyPrice,
350
- import_fixparser.MDEntryType.MarginRate,
351
- import_fixparser.MDEntryType.MidPrice,
352
- import_fixparser.MDEntryType.EmptyBook,
353
- import_fixparser.MDEntryType.SettleHighPrice,
354
- import_fixparser.MDEntryType.SettleLowPrice,
355
- import_fixparser.MDEntryType.PriorSettlePrice,
356
- import_fixparser.MDEntryType.SessionHighBid,
357
- import_fixparser.MDEntryType.SessionLowOffer,
358
- import_fixparser.MDEntryType.EarlyPrices,
359
- import_fixparser.MDEntryType.AuctionClearingPrice,
360
- import_fixparser.MDEntryType.SwapValueFactor,
361
- import_fixparser.MDEntryType.DailyValueAdjustmentForLongPositions,
362
- import_fixparser.MDEntryType.CumulativeValueAdjustmentForLongPositions,
363
- import_fixparser.MDEntryType.DailyValueAdjustmentForShortPositions,
364
- import_fixparser.MDEntryType.CumulativeValueAdjustmentForShortPositions,
365
- import_fixparser.MDEntryType.FixingPrice,
366
- import_fixparser.MDEntryType.CashRate,
367
- import_fixparser.MDEntryType.RecoveryRate,
368
- import_fixparser.MDEntryType.RecoveryRateForLong,
369
- import_fixparser.MDEntryType.RecoveryRateForShort,
370
- import_fixparser.MDEntryType.MarketBid,
371
- import_fixparser.MDEntryType.MarketOffer,
372
- import_fixparser.MDEntryType.ShortSaleMinPrice,
373
- import_fixparser.MDEntryType.PreviousClosingPrice,
374
- import_fixparser.MDEntryType.ThresholdLimitPriceBanding,
375
- import_fixparser.MDEntryType.DailyFinancingValue,
376
- import_fixparser.MDEntryType.AccruedFinancingValue,
377
- import_fixparser.MDEntryType.TWAP
378
- ];
325
+ const entryTypes = args.mdEntryTypes || [import_fixparser.MDEntryType.Bid, import_fixparser.MDEntryType.Offer, import_fixparser.MDEntryType.TradeVolume];
379
326
  const messageFields = [
380
327
  new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.MarketDataRequest),
381
328
  new import_fixparser.Field(import_fixparser.Fields.SenderCompID, parser.sender),
@@ -397,10 +344,6 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
397
344
  });
398
345
  const mdr = parser.createMessage(...messageFields);
399
346
  if (!parser.connected) {
400
- parser.logger.log({
401
- level: "error",
402
- message: "Not connected. Cannot send market data request."
403
- });
404
347
  return {
405
348
  content: [
406
349
  {
@@ -412,16 +355,8 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
412
355
  isError: true
413
356
  };
414
357
  }
415
- parser.logger.log({
416
- level: "info",
417
- message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
418
- });
419
358
  parser.send(mdr);
420
359
  const fixData = await response;
421
- parser.logger.log({
422
- level: "info",
423
- message: `Received market data response for request ID: ${args.mdReqID}`
424
- });
425
360
  return {
426
361
  content: [
427
362
  {
@@ -470,9 +405,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
470
405
  const offerData = priceHistory.map((point) => point.offer);
471
406
  const spreadData = priceHistory.map((point) => point.spread);
472
407
  const volumeData = priceHistory.map((point) => point.volume);
473
- const tradeData = priceHistory.map((point) => point.trade);
474
- const vwapData = priceHistory.map((point) => point.vwap);
475
- const twapData = priceHistory.map((point) => point.twap);
476
408
  const config = {
477
409
  type: "line",
478
410
  data: {
@@ -502,30 +434,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
502
434
  fill: false,
503
435
  tension: 0.4
504
436
  },
505
- {
506
- label: "Trade",
507
- data: tradeData,
508
- borderColor: "#ffc107",
509
- backgroundColor: "rgba(255, 193, 7, 0.1)",
510
- fill: false,
511
- tension: 0.4
512
- },
513
- {
514
- label: "VWAP",
515
- data: vwapData,
516
- borderColor: "#17a2b8",
517
- backgroundColor: "rgba(23, 162, 184, 0.1)",
518
- fill: false,
519
- tension: 0.4
520
- },
521
- {
522
- label: "TWAP",
523
- data: twapData,
524
- borderColor: "#6610f2",
525
- backgroundColor: "rgba(102, 16, 242, 0.1)",
526
- fill: false,
527
- tension: 0.4
528
- },
529
437
  {
530
438
  label: "Volume",
531
439
  data: volumeData,
@@ -571,7 +479,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
571
479
  content: [
572
480
  {
573
481
  type: "text",
574
- text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
482
+ text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
575
483
  uri: "getStockGraph"
576
484
  }
577
485
  ],
@@ -609,48 +517,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
609
517
  bid: point.bid,
610
518
  offer: point.offer,
611
519
  spread: point.spread,
612
- volume: point.volume,
613
- trade: point.trade,
614
- indexValue: point.indexValue,
615
- openingPrice: point.openingPrice,
616
- closingPrice: point.closingPrice,
617
- settlementPrice: point.settlementPrice,
618
- tradingSessionHighPrice: point.tradingSessionHighPrice,
619
- tradingSessionLowPrice: point.tradingSessionLowPrice,
620
- vwap: point.vwap,
621
- imbalance: point.imbalance,
622
- openInterest: point.openInterest,
623
- compositeUnderlyingPrice: point.compositeUnderlyingPrice,
624
- simulatedSellPrice: point.simulatedSellPrice,
625
- simulatedBuyPrice: point.simulatedBuyPrice,
626
- marginRate: point.marginRate,
627
- midPrice: point.midPrice,
628
- emptyBook: point.emptyBook,
629
- settleHighPrice: point.settleHighPrice,
630
- settleLowPrice: point.settleLowPrice,
631
- priorSettlePrice: point.priorSettlePrice,
632
- sessionHighBid: point.sessionHighBid,
633
- sessionLowOffer: point.sessionLowOffer,
634
- earlyPrices: point.earlyPrices,
635
- auctionClearingPrice: point.auctionClearingPrice,
636
- swapValueFactor: point.swapValueFactor,
637
- dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
638
- cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
639
- dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
640
- cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
641
- fixingPrice: point.fixingPrice,
642
- cashRate: point.cashRate,
643
- recoveryRate: point.recoveryRate,
644
- recoveryRateForLong: point.recoveryRateForLong,
645
- recoveryRateForShort: point.recoveryRateForShort,
646
- marketBid: point.marketBid,
647
- marketOffer: point.marketOffer,
648
- shortSaleMinPrice: point.shortSaleMinPrice,
649
- previousClosingPrice: point.previousClosingPrice,
650
- thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
651
- dailyFinancingValue: point.dailyFinancingValue,
652
- accruedFinancingValue: point.accruedFinancingValue,
653
- twap: point.twap
520
+ volume: point.volume
654
521
  }))
655
522
  },
656
523
  null,
@@ -665,7 +532,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
665
532
  content: [
666
533
  {
667
534
  type: "text",
668
- text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
535
+ text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
669
536
  uri: "getStockPriceHistory"
670
537
  }
671
538
  ],
@@ -773,7 +640,7 @@ Parameters verified:
773
640
  - Symbol: ${args.symbol}
774
641
  - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
775
642
 
776
- To execute this order, call the executeOrder tool with these exact same parameters. Important: The user has to explicitly confirm before executeOrder is called!`,
643
+ To execute this order, call the executeOrder tool with these exact same parameters.`,
777
644
  uri: "verifyOrder"
778
645
  }
779
646
  ]
@@ -980,245 +847,46 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
980
847
  message: `MCP Server received message: ${message.messageType}: ${message.description}`
981
848
  });
982
849
  const msgType = message.messageType;
983
- if (msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh || msgType === import_fixparser3.Messages.MarketDataIncrementalRefresh) {
850
+ if (msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh) {
984
851
  const symbol = message.getField(import_fixparser3.Fields.Symbol)?.value;
985
- parser.logger.log({
986
- level: "info",
987
- message: `Processing market data for symbol: ${symbol}`
988
- });
989
- const fixJson = message.toFIXJSON();
990
- const entries = fixJson.Body?.NoMDEntries || [];
991
- parser.logger.log({
992
- level: "info",
993
- message: `Found ${entries.length} market data entries`
994
- });
995
- const data = {
996
- timestamp: Date.now(),
997
- bid: 0,
998
- offer: 0,
999
- spread: 0,
1000
- volume: 0,
1001
- trade: 0,
1002
- indexValue: 0,
1003
- openingPrice: 0,
1004
- closingPrice: 0,
1005
- settlementPrice: 0,
1006
- tradingSessionHighPrice: 0,
1007
- tradingSessionLowPrice: 0,
1008
- vwap: 0,
1009
- imbalance: 0,
1010
- openInterest: 0,
1011
- compositeUnderlyingPrice: 0,
1012
- simulatedSellPrice: 0,
1013
- simulatedBuyPrice: 0,
1014
- marginRate: 0,
1015
- midPrice: 0,
1016
- emptyBook: 0,
1017
- settleHighPrice: 0,
1018
- settleLowPrice: 0,
1019
- priorSettlePrice: 0,
1020
- sessionHighBid: 0,
1021
- sessionLowOffer: 0,
1022
- earlyPrices: 0,
1023
- auctionClearingPrice: 0,
1024
- swapValueFactor: 0,
1025
- dailyValueAdjustmentForLongPositions: 0,
1026
- cumulativeValueAdjustmentForLongPositions: 0,
1027
- dailyValueAdjustmentForShortPositions: 0,
1028
- cumulativeValueAdjustmentForShortPositions: 0,
1029
- fixingPrice: 0,
1030
- cashRate: 0,
1031
- recoveryRate: 0,
1032
- recoveryRateForLong: 0,
1033
- recoveryRateForShort: 0,
1034
- marketBid: 0,
1035
- marketOffer: 0,
1036
- shortSaleMinPrice: 0,
1037
- previousClosingPrice: 0,
1038
- thresholdLimitPriceBanding: 0,
1039
- dailyFinancingValue: 0,
1040
- accruedFinancingValue: 0,
1041
- twap: 0
1042
- };
1043
- for (const entry of entries) {
1044
- const entryType = entry.MDEntryType;
1045
- const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
1046
- const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
1047
- if (entryType === import_fixparser3.MDEntryType.Bid || entryType === import_fixparser3.MDEntryType.Offer || entryType === import_fixparser3.MDEntryType.TradeVolume) {
1048
- parser.logger.log({
1049
- level: "info",
1050
- message: `Market Data Entry - Type: ${entryType}, Price: ${price}, Size: ${size}`
1051
- });
1052
- }
1053
- switch (entryType) {
1054
- case import_fixparser3.MDEntryType.Bid:
1055
- data.bid = price;
1056
- break;
1057
- case import_fixparser3.MDEntryType.Offer:
1058
- data.offer = price;
1059
- break;
1060
- case import_fixparser3.MDEntryType.Trade:
1061
- data.trade = price;
1062
- break;
1063
- case import_fixparser3.MDEntryType.IndexValue:
1064
- data.indexValue = price;
1065
- break;
1066
- case import_fixparser3.MDEntryType.OpeningPrice:
1067
- data.openingPrice = price;
1068
- break;
1069
- case import_fixparser3.MDEntryType.ClosingPrice:
1070
- data.closingPrice = price;
1071
- break;
1072
- case import_fixparser3.MDEntryType.SettlementPrice:
1073
- data.settlementPrice = price;
1074
- break;
1075
- case import_fixparser3.MDEntryType.TradingSessionHighPrice:
1076
- data.tradingSessionHighPrice = price;
1077
- break;
1078
- case import_fixparser3.MDEntryType.TradingSessionLowPrice:
1079
- data.tradingSessionLowPrice = price;
1080
- break;
1081
- case import_fixparser3.MDEntryType.VWAP:
1082
- data.vwap = price;
1083
- break;
1084
- case import_fixparser3.MDEntryType.Imbalance:
1085
- data.imbalance = size;
1086
- break;
1087
- case import_fixparser3.MDEntryType.TradeVolume:
1088
- data.volume = size;
1089
- break;
1090
- case import_fixparser3.MDEntryType.OpenInterest:
1091
- data.openInterest = size;
1092
- break;
1093
- case import_fixparser3.MDEntryType.CompositeUnderlyingPrice:
1094
- data.compositeUnderlyingPrice = price;
1095
- break;
1096
- case import_fixparser3.MDEntryType.SimulatedSellPrice:
1097
- data.simulatedSellPrice = price;
1098
- break;
1099
- case import_fixparser3.MDEntryType.SimulatedBuyPrice:
1100
- data.simulatedBuyPrice = price;
1101
- break;
1102
- case import_fixparser3.MDEntryType.MarginRate:
1103
- data.marginRate = price;
1104
- break;
1105
- case import_fixparser3.MDEntryType.MidPrice:
1106
- data.midPrice = price;
1107
- break;
1108
- case import_fixparser3.MDEntryType.EmptyBook:
1109
- data.emptyBook = 1;
1110
- break;
1111
- case import_fixparser3.MDEntryType.SettleHighPrice:
1112
- data.settleHighPrice = price;
1113
- break;
1114
- case import_fixparser3.MDEntryType.SettleLowPrice:
1115
- data.settleLowPrice = price;
1116
- break;
1117
- case import_fixparser3.MDEntryType.PriorSettlePrice:
1118
- data.priorSettlePrice = price;
1119
- break;
1120
- case import_fixparser3.MDEntryType.SessionHighBid:
1121
- data.sessionHighBid = price;
1122
- break;
1123
- case import_fixparser3.MDEntryType.SessionLowOffer:
1124
- data.sessionLowOffer = price;
1125
- break;
1126
- case import_fixparser3.MDEntryType.EarlyPrices:
1127
- data.earlyPrices = price;
1128
- break;
1129
- case import_fixparser3.MDEntryType.AuctionClearingPrice:
1130
- data.auctionClearingPrice = price;
1131
- break;
1132
- case import_fixparser3.MDEntryType.SwapValueFactor:
1133
- data.swapValueFactor = price;
1134
- break;
1135
- case import_fixparser3.MDEntryType.DailyValueAdjustmentForLongPositions:
1136
- data.dailyValueAdjustmentForLongPositions = price;
1137
- break;
1138
- case import_fixparser3.MDEntryType.CumulativeValueAdjustmentForLongPositions:
1139
- data.cumulativeValueAdjustmentForLongPositions = price;
1140
- break;
1141
- case import_fixparser3.MDEntryType.DailyValueAdjustmentForShortPositions:
1142
- data.dailyValueAdjustmentForShortPositions = price;
1143
- break;
1144
- case import_fixparser3.MDEntryType.CumulativeValueAdjustmentForShortPositions:
1145
- data.cumulativeValueAdjustmentForShortPositions = price;
1146
- break;
1147
- case import_fixparser3.MDEntryType.FixingPrice:
1148
- data.fixingPrice = price;
1149
- break;
1150
- case import_fixparser3.MDEntryType.CashRate:
1151
- data.cashRate = price;
1152
- break;
1153
- case import_fixparser3.MDEntryType.RecoveryRate:
1154
- data.recoveryRate = price;
1155
- break;
1156
- case import_fixparser3.MDEntryType.RecoveryRateForLong:
1157
- data.recoveryRateForLong = price;
1158
- break;
1159
- case import_fixparser3.MDEntryType.RecoveryRateForShort:
1160
- data.recoveryRateForShort = price;
1161
- break;
1162
- case import_fixparser3.MDEntryType.MarketBid:
1163
- data.marketBid = price;
1164
- break;
1165
- case import_fixparser3.MDEntryType.MarketOffer:
1166
- data.marketOffer = price;
1167
- break;
1168
- case import_fixparser3.MDEntryType.ShortSaleMinPrice:
1169
- data.shortSaleMinPrice = price;
1170
- break;
1171
- case import_fixparser3.MDEntryType.PreviousClosingPrice:
1172
- data.previousClosingPrice = price;
1173
- break;
1174
- case import_fixparser3.MDEntryType.ThresholdLimitPriceBanding:
1175
- data.thresholdLimitPriceBanding = price;
1176
- break;
1177
- case import_fixparser3.MDEntryType.DailyFinancingValue:
1178
- data.dailyFinancingValue = price;
1179
- break;
1180
- case import_fixparser3.MDEntryType.AccruedFinancingValue:
1181
- data.accruedFinancingValue = price;
1182
- break;
1183
- case import_fixparser3.MDEntryType.TWAP:
1184
- data.twap = price;
1185
- break;
852
+ const entries = message.getField(import_fixparser3.Fields.NoMDEntries)?.value;
853
+ let bid = 0;
854
+ let offer = 0;
855
+ let volume = 0;
856
+ const entryTypes = message.getFields(import_fixparser3.Fields.MDEntryType);
857
+ const entryPrices = message.getFields(import_fixparser3.Fields.MDEntryPx);
858
+ const entrySizes = message.getFields(import_fixparser3.Fields.MDEntrySize);
859
+ if (entryTypes && entryPrices && entrySizes) {
860
+ for (let i = 0; i < entries; i++) {
861
+ const entryType = entryTypes[i]?.value;
862
+ const entryPrice = Number.parseFloat(entryPrices[i]?.value);
863
+ const entrySize = Number.parseFloat(entrySizes[i]?.value);
864
+ if (entryType === import_fixparser3.MDEntryType.Bid) {
865
+ bid = entryPrice;
866
+ } else if (entryType === import_fixparser3.MDEntryType.Offer) {
867
+ offer = entryPrice;
868
+ }
869
+ volume += entrySize;
1186
870
  }
1187
871
  }
1188
- data.spread = data.offer - data.bid;
872
+ const spread = offer - bid;
873
+ const timestamp = Date.now();
874
+ const data = {
875
+ timestamp,
876
+ bid,
877
+ offer,
878
+ spread,
879
+ volume
880
+ };
1189
881
  if (!marketDataPrices.has(symbol)) {
1190
- parser.logger.log({
1191
- level: "info",
1192
- message: `Creating new price history array for symbol: ${symbol}`
1193
- });
1194
882
  marketDataPrices.set(symbol, []);
1195
883
  }
1196
884
  const prices = marketDataPrices.get(symbol);
1197
885
  prices.push(data);
1198
- parser.logger.log({
1199
- level: "info",
1200
- message: `Updated price history for ${symbol}. Current size: ${prices.length}`
1201
- });
1202
886
  if (prices.length > maxPriceHistory) {
1203
887
  prices.splice(0, prices.length - maxPriceHistory);
1204
- parser.logger.log({
1205
- level: "info",
1206
- message: `Trimmed price history for ${symbol} to ${maxPriceHistory} entries`
1207
- });
1208
888
  }
1209
889
  onPriceUpdate?.(symbol, data);
1210
- const mdReqID = message.getField(import_fixparser3.Fields.MDReqID)?.value;
1211
- if (mdReqID) {
1212
- const callback = pendingRequests.get(mdReqID);
1213
- if (callback) {
1214
- callback(message);
1215
- pendingRequests.delete(mdReqID);
1216
- parser.logger.log({
1217
- level: "info",
1218
- message: `Resolved market data request for ID: ${mdReqID}`
1219
- });
1220
- }
1221
- }
1222
890
  } else if (msgType === import_fixparser3.Messages.ExecutionReport) {
1223
891
  const reqId = message.getField(import_fixparser3.Fields.ClOrdID)?.value;
1224
892
  const callback = pendingRequests.get(reqId);
@@ -1247,7 +915,7 @@ var MCPLocal = class extends MCPBase {
1247
915
  */
1248
916
  marketDataPrices = /* @__PURE__ */ new Map();
1249
917
  /**
1250
- * Maximum number of price history entries to keep per symbol
918
+ * Maximum number of price points to store per symbol
1251
919
  * @private
1252
920
  */
1253
921
  MAX_PRICE_HISTORY = 1e5;
@@ -1356,39 +1024,6 @@ var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamable
1356
1024
  var import_types = require("@modelcontextprotocol/sdk/types.js");
1357
1025
  var import_zod2 = require("zod");
1358
1026
  var transports = {};
1359
- function jsonSchemaToZod(schema) {
1360
- if (schema.type === "object") {
1361
- const shape = {};
1362
- for (const [key, prop] of Object.entries(schema.properties || {})) {
1363
- const propSchema = prop;
1364
- if (propSchema.type === "string") {
1365
- if (propSchema.enum) {
1366
- shape[key] = import_zod2.z.enum(propSchema.enum);
1367
- } else {
1368
- shape[key] = import_zod2.z.string();
1369
- }
1370
- } else if (propSchema.type === "number") {
1371
- shape[key] = import_zod2.z.number();
1372
- } else if (propSchema.type === "boolean") {
1373
- shape[key] = import_zod2.z.boolean();
1374
- } else if (propSchema.type === "array") {
1375
- if (propSchema.items.type === "string") {
1376
- shape[key] = import_zod2.z.array(import_zod2.z.string());
1377
- } else if (propSchema.items.type === "number") {
1378
- shape[key] = import_zod2.z.array(import_zod2.z.number());
1379
- } else if (propSchema.items.type === "boolean") {
1380
- shape[key] = import_zod2.z.array(import_zod2.z.boolean());
1381
- } else {
1382
- shape[key] = import_zod2.z.array(import_zod2.z.any());
1383
- }
1384
- } else {
1385
- shape[key] = import_zod2.z.any();
1386
- }
1387
- }
1388
- return shape;
1389
- }
1390
- return {};
1391
- }
1392
1027
  var MCPRemote = class extends MCPBase {
1393
1028
  /**
1394
1029
  * Port number the server will listen on.
@@ -1431,7 +1066,7 @@ var MCPRemote = class extends MCPBase {
1431
1066
  */
1432
1067
  marketDataPrices = /* @__PURE__ */ new Map();
1433
1068
  /**
1434
- * Maximum number of price history entries to keep per symbol
1069
+ * Maximum number of price points to store per symbol
1435
1070
  * @private
1436
1071
  */
1437
1072
  MAX_PRICE_HISTORY = 1e5;
@@ -1453,22 +1088,55 @@ var MCPRemote = class extends MCPBase {
1453
1088
  this.parser,
1454
1089
  this.pendingRequests,
1455
1090
  this.marketDataPrices,
1456
- this.MAX_PRICE_HISTORY
1091
+ this.MAX_PRICE_HISTORY,
1092
+ (symbol, data) => {
1093
+ this.mcpServer?.tool(
1094
+ "priceUpdate",
1095
+ {
1096
+ description: "Price update notification",
1097
+ schema: import_zod2.z.object({
1098
+ symbol: import_zod2.z.string(),
1099
+ timestamp: import_zod2.z.number(),
1100
+ bid: import_zod2.z.number(),
1101
+ offer: import_zod2.z.number(),
1102
+ spread: import_zod2.z.number(),
1103
+ volume: import_zod2.z.number()
1104
+ })
1105
+ },
1106
+ () => ({
1107
+ content: [
1108
+ {
1109
+ type: "text",
1110
+ text: JSON.stringify({ symbol, ...data })
1111
+ }
1112
+ ]
1113
+ })
1114
+ );
1115
+ }
1457
1116
  );
1458
- this.logger?.log({
1459
- level: "info",
1460
- message: `Market Data Prices TEST: ${JSON.stringify(this.marketDataPrices)}`
1461
- });
1462
1117
  }
1463
1118
  });
1464
1119
  this.httpServer = (0, import_node_http.createServer)(async (req, res) => {
1120
+ console.log(req.headers);
1121
+ this.logger?.log({
1122
+ level: "info",
1123
+ message: `Incoming request: ${req.method} ${req.url}`
1124
+ });
1465
1125
  if (!req.url || !req.method) {
1126
+ this.logger?.log({
1127
+ level: "error",
1128
+ message: "Invalid request: missing URL or method"
1129
+ });
1466
1130
  res.writeHead(400);
1467
1131
  res.end("Bad Request");
1468
1132
  return;
1469
1133
  }
1470
1134
  if (req.url === "/mcp") {
1471
1135
  const sessionId = req.headers["mcp-session-id"];
1136
+ this.logger?.log({
1137
+ level: "info",
1138
+ message: `MCP request received. Session ID: ${sessionId || "none"}, headers: ${req.headers}`
1139
+ });
1472
1140
  if (req.method === "POST") {
1473
1141
  const bodyChunks = [];
1474
1142
  req.on("data", (chunk) => {
@@ -1479,23 +1147,47 @@ var MCPRemote = class extends MCPBase {
1479
1147
  const body = Buffer.concat(bodyChunks).toString();
1480
1148
  try {
1481
1149
  parsed = JSON.parse(body);
1150
+ this.logger?.log({
1151
+ level: "info",
1152
+ message: `Parsed request body: ${JSON.stringify(parsed)}`
1153
+ });
1482
1154
  } catch (err) {
1155
+ this.logger?.log({
1156
+ level: "error",
1157
+ message: `Failed to parse JSON body: ${err}`
1158
+ });
1483
1159
  res.writeHead(400);
1484
1160
  res.end(JSON.stringify({ error: "Invalid JSON" }));
1485
1161
  return;
1486
1162
  }
1487
1163
  let transport;
1488
1164
  if (sessionId && transports[sessionId]) {
1165
+ this.logger?.log({
1166
+ level: "info",
1167
+ message: `Using existing transport for session: ${sessionId}`
1168
+ });
1489
1169
  transport = transports[sessionId];
1490
1170
  } else if (!sessionId && req.method === "POST" && (0, import_types.isInitializeRequest)(parsed)) {
1171
+ this.logger?.log({
1172
+ level: "info",
1173
+ message: "Creating new transport for initialization request"
1174
+ });
1491
1175
  transport = new import_streamableHttp.StreamableHTTPServerTransport({
1492
1176
  sessionIdGenerator: () => (0, import_node_crypto.randomUUID)(),
1493
1177
  onsessioninitialized: (sessionId2) => {
1178
+ this.logger?.log({
1179
+ level: "info",
1180
+ message: `New session initialized: ${sessionId2}`
1181
+ });
1494
1182
  transports[sessionId2] = transport;
1495
1183
  }
1496
1184
  });
1497
1185
  transport.onclose = () => {
1498
1186
  if (transport.sessionId) {
1187
+ this.logger?.log({
1188
+ level: "info",
1189
+ message: `Session closed: ${transport.sessionId}`
1190
+ });
1499
1191
  delete transports[transport.sessionId];
1500
1192
  }
1501
1193
  };
@@ -1506,6 +1198,10 @@ var MCPRemote = class extends MCPBase {
1506
1198
  this.setupTools();
1507
1199
  await this.mcpServer.connect(transport);
1508
1200
  } else {
1201
+ this.logger?.log({
1202
+ level: "error",
1203
+ message: "Invalid request: No valid session ID provided"
1204
+ });
1509
1205
  res.writeHead(400, { "Content-Type": "application/json" });
1510
1206
  res.end(
1511
1207
  JSON.stringify({
@@ -1521,6 +1217,10 @@ var MCPRemote = class extends MCPBase {
1521
1217
  }
1522
1218
  try {
1523
1219
  await transport.handleRequest(req, res, parsed);
1220
+ this.logger?.log({
1221
+ level: "info",
1222
+ message: "Request handled successfully"
1223
+ });
1524
1224
  } catch (error) {
1525
1225
  this.logger?.log({
1526
1226
  level: "error",
@@ -1531,6 +1231,10 @@ var MCPRemote = class extends MCPBase {
1531
1231
  });
1532
1232
  } else if (req.method === "GET" || req.method === "DELETE") {
1533
1233
  if (!sessionId || !transports[sessionId]) {
1234
+ this.logger?.log({
1235
+ level: "error",
1236
+ message: `Invalid session ID for ${req.method} request: ${sessionId}`
1237
+ });
1534
1238
  res.writeHead(400);
1535
1239
  res.end("Invalid or missing session ID");
1536
1240
  return;
@@ -1538,6 +1242,10 @@ var MCPRemote = class extends MCPBase {
1538
1242
  const transport = transports[sessionId];
1539
1243
  try {
1540
1244
  await transport.handleRequest(req, res);
1245
+ this.logger?.log({
1246
+ level: "info",
1247
+ message: `${req.method} request handled successfully for session: ${sessionId}`
1248
+ });
1541
1249
  } catch (error) {
1542
1250
  this.logger?.log({
1543
1251
  level: "error",
@@ -1554,6 +1262,10 @@ var MCPRemote = class extends MCPBase {
1554
1262
  res.end("Method Not Allowed");
1555
1263
  }
1556
1264
  } else {
1265
+ this.logger?.log({
1266
+ level: "error",
1267
+ message: `Not found: ${req.url}`
1268
+ });
1557
1269
  res.writeHead(404);
1558
1270
  res.end("Not Found");
1559
1271
  }
@@ -1583,40 +1295,69 @@ var MCPRemote = class extends MCPBase {
1583
1295
  });
1584
1296
  return;
1585
1297
  }
1586
- const toolHandlers = createToolHandlers(
1587
- this.parser,
1588
- this.verifiedOrders,
1589
- this.pendingRequests,
1590
- this.marketDataPrices
1298
+ this.mcpServer.tool(
1299
+ "tools/list",
1300
+ {
1301
+ description: "List available tools",
1302
+ schema: import_zod2.z.object({})
1303
+ },
1304
+ async () => {
1305
+ return {
1306
+ content: [
1307
+ {
1308
+ type: "text",
1309
+ text: JSON.stringify(
1310
+ Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
1311
+ name,
1312
+ description,
1313
+ inputSchema: schema
1314
+ }))
1315
+ )
1316
+ }
1317
+ ]
1318
+ };
1319
+ }
1591
1320
  );
1592
- Object.entries(toolSchemas).forEach(([name, { description, schema }]) => {
1593
- this.mcpServer?.registerTool(
1594
- name,
1595
- {
1596
- description,
1597
- inputSchema: jsonSchemaToZod(schema)
1598
- },
1599
- async (args) => {
1600
- const handler = toolHandlers[name];
1601
- if (!handler) {
1602
- return {
1603
- content: [
1604
- {
1605
- type: "text",
1606
- text: `Tool not found: ${name}`
1607
- }
1608
- ],
1609
- isError: true
1610
- };
1611
- }
1612
- const result = await handler(args);
1321
+ this.mcpServer.tool(
1322
+ "tools/call",
1323
+ {
1324
+ description: "Call a tool",
1325
+ schema: import_zod2.z.object({
1326
+ name: import_zod2.z.string(),
1327
+ arguments: import_zod2.z.any(),
1328
+ _meta: import_zod2.z.object({
1329
+ progressToken: import_zod2.z.number()
1330
+ }).optional()
1331
+ })
1332
+ },
1333
+ async (request) => {
1334
+ const { name, arguments: args } = request;
1335
+ const toolHandlers = createToolHandlers(
1336
+ this.parser,
1337
+ this.verifiedOrders,
1338
+ this.pendingRequests,
1339
+ this.marketDataPrices
1340
+ );
1341
+ const handler = toolHandlers[name];
1342
+ if (!handler) {
1613
1343
  return {
1614
- content: result.content,
1615
- isError: result.isError
1344
+ content: [
1345
+ {
1346
+ type: "text",
1347
+ text: `Tool not found: ${name}`,
1348
+ uri: name
1349
+ }
1350
+ ],
1351
+ isError: true
1616
1352
  };
1617
1353
  }
1618
- );
1619
- });
1354
+ const result = await handler(args);
1355
+ return {
1356
+ content: result.content,
1357
+ isError: result.isError
1358
+ };
1359
+ }
1360
+ );
1620
1361
  }
1621
1362
  };
1622
1363
  // Annotate the CommonJS export names for ESM import in node: