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.
- package/build/cjs/MCPLocal.js +372 -35
- package/build/cjs/MCPLocal.js.map +2 -2
- package/build/cjs/MCPRemote.js +440 -176
- package/build/cjs/MCPRemote.js.map +2 -2
- package/build/cjs/index.js +441 -177
- package/build/cjs/index.js.map +2 -2
- package/build/esm/MCPLocal.mjs +372 -35
- package/build/esm/MCPLocal.mjs.map +2 -2
- package/build/esm/MCPRemote.mjs +440 -176
- package/build/esm/MCPRemote.mjs.map +2 -2
- package/build/esm/index.mjs +441 -177
- package/build/esm/index.mjs.map +2 -2
- package/build-examples/cjs/example_mcp_local.js +7 -7
- package/build-examples/cjs/example_mcp_local.js.map +3 -3
- package/build-examples/cjs/example_mcp_remote.js +7 -7
- package/build-examples/cjs/example_mcp_remote.js.map +3 -3
- package/build-examples/esm/example_mcp_local.mjs +7 -7
- package/build-examples/esm/example_mcp_local.mjs.map +3 -3
- package/build-examples/esm/example_mcp_remote.mjs +7 -7
- package/build-examples/esm/example_mcp_remote.mjs.map +3 -3
- package/package.json +1 -1
- package/types/MCPBase.d.ts +0 -49
- package/types/MCPLocal.d.ts +0 -40
- package/types/MCPRemote.d.ts +0 -66
- package/types/PluginOptions.d.ts +0 -6
- package/types/index.d.ts +0 -3
- package/types/schemas/index.d.ts +0 -15
- package/types/schemas/schemas.d.ts +0 -168
- package/types/tools/index.d.ts +0 -17
- package/types/tools/marketData.d.ts +0 -40
- package/types/tools/order.d.ts +0 -12
- package/types/tools/parse.d.ts +0 -5
- package/types/tools/parseToJSON.d.ts +0 -5
- package/types/utils/messageHandler.d.ts +0 -18
package/build/esm/index.mjs
CHANGED
|
@@ -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.
|
|
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 || [
|
|
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
|
|
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
|
|
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
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
const
|
|
820
|
-
const
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
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
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
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
|
-
|
|
1318
|
-
|
|
1319
|
-
content: result.content,
|
|
1320
|
-
isError: result.isError
|
|
1321
|
-
};
|
|
1322
|
-
}
|
|
1323
|
-
);
|
|
1586
|
+
);
|
|
1587
|
+
});
|
|
1324
1588
|
}
|
|
1325
1589
|
};
|
|
1326
1590
|
export {
|