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/MCPRemote.mjs
CHANGED
|
@@ -132,7 +132,7 @@ var toolSchemas = {
|
|
|
132
132
|
}
|
|
133
133
|
},
|
|
134
134
|
executeOrder: {
|
|
135
|
-
description: "Executes a verified order. verifyOrder must be called before executeOrder.
|
|
135
|
+
description: "Executes a verified order. verifyOrder must be called before executeOrder.",
|
|
136
136
|
schema: {
|
|
137
137
|
type: "object",
|
|
138
138
|
properties: {
|
|
@@ -285,10 +285,63 @@ import QuickChart from "quickchart-js";
|
|
|
285
285
|
var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
286
286
|
return async (args) => {
|
|
287
287
|
try {
|
|
288
|
+
parser.logger.log({
|
|
289
|
+
level: "info",
|
|
290
|
+
message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
|
|
291
|
+
});
|
|
288
292
|
const response = new Promise((resolve) => {
|
|
289
293
|
pendingRequests.set(args.mdReqID, resolve);
|
|
294
|
+
parser.logger.log({
|
|
295
|
+
level: "info",
|
|
296
|
+
message: `Registered callback for market data request ID: ${args.mdReqID}`
|
|
297
|
+
});
|
|
290
298
|
});
|
|
291
|
-
const entryTypes = args.mdEntryTypes || [
|
|
299
|
+
const entryTypes = args.mdEntryTypes || [
|
|
300
|
+
MDEntryType.Bid,
|
|
301
|
+
MDEntryType.Offer,
|
|
302
|
+
MDEntryType.Trade,
|
|
303
|
+
MDEntryType.IndexValue,
|
|
304
|
+
MDEntryType.OpeningPrice,
|
|
305
|
+
MDEntryType.ClosingPrice,
|
|
306
|
+
MDEntryType.SettlementPrice,
|
|
307
|
+
MDEntryType.TradingSessionHighPrice,
|
|
308
|
+
MDEntryType.TradingSessionLowPrice,
|
|
309
|
+
MDEntryType.VWAP,
|
|
310
|
+
MDEntryType.Imbalance,
|
|
311
|
+
MDEntryType.TradeVolume,
|
|
312
|
+
MDEntryType.OpenInterest,
|
|
313
|
+
MDEntryType.CompositeUnderlyingPrice,
|
|
314
|
+
MDEntryType.SimulatedSellPrice,
|
|
315
|
+
MDEntryType.SimulatedBuyPrice,
|
|
316
|
+
MDEntryType.MarginRate,
|
|
317
|
+
MDEntryType.MidPrice,
|
|
318
|
+
MDEntryType.EmptyBook,
|
|
319
|
+
MDEntryType.SettleHighPrice,
|
|
320
|
+
MDEntryType.SettleLowPrice,
|
|
321
|
+
MDEntryType.PriorSettlePrice,
|
|
322
|
+
MDEntryType.SessionHighBid,
|
|
323
|
+
MDEntryType.SessionLowOffer,
|
|
324
|
+
MDEntryType.EarlyPrices,
|
|
325
|
+
MDEntryType.AuctionClearingPrice,
|
|
326
|
+
MDEntryType.SwapValueFactor,
|
|
327
|
+
MDEntryType.DailyValueAdjustmentForLongPositions,
|
|
328
|
+
MDEntryType.CumulativeValueAdjustmentForLongPositions,
|
|
329
|
+
MDEntryType.DailyValueAdjustmentForShortPositions,
|
|
330
|
+
MDEntryType.CumulativeValueAdjustmentForShortPositions,
|
|
331
|
+
MDEntryType.FixingPrice,
|
|
332
|
+
MDEntryType.CashRate,
|
|
333
|
+
MDEntryType.RecoveryRate,
|
|
334
|
+
MDEntryType.RecoveryRateForLong,
|
|
335
|
+
MDEntryType.RecoveryRateForShort,
|
|
336
|
+
MDEntryType.MarketBid,
|
|
337
|
+
MDEntryType.MarketOffer,
|
|
338
|
+
MDEntryType.ShortSaleMinPrice,
|
|
339
|
+
MDEntryType.PreviousClosingPrice,
|
|
340
|
+
MDEntryType.ThresholdLimitPriceBanding,
|
|
341
|
+
MDEntryType.DailyFinancingValue,
|
|
342
|
+
MDEntryType.AccruedFinancingValue,
|
|
343
|
+
MDEntryType.TWAP
|
|
344
|
+
];
|
|
292
345
|
const messageFields = [
|
|
293
346
|
new Field(Fields.MsgType, Messages.MarketDataRequest),
|
|
294
347
|
new Field(Fields.SenderCompID, parser.sender),
|
|
@@ -310,6 +363,10 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
|
310
363
|
});
|
|
311
364
|
const mdr = parser.createMessage(...messageFields);
|
|
312
365
|
if (!parser.connected) {
|
|
366
|
+
parser.logger.log({
|
|
367
|
+
level: "error",
|
|
368
|
+
message: "Not connected. Cannot send market data request."
|
|
369
|
+
});
|
|
313
370
|
return {
|
|
314
371
|
content: [
|
|
315
372
|
{
|
|
@@ -321,8 +378,16 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
|
321
378
|
isError: true
|
|
322
379
|
};
|
|
323
380
|
}
|
|
381
|
+
parser.logger.log({
|
|
382
|
+
level: "info",
|
|
383
|
+
message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
|
|
384
|
+
});
|
|
324
385
|
parser.send(mdr);
|
|
325
386
|
const fixData = await response;
|
|
387
|
+
parser.logger.log({
|
|
388
|
+
level: "info",
|
|
389
|
+
message: `Received market data response for request ID: ${args.mdReqID}`
|
|
390
|
+
});
|
|
326
391
|
return {
|
|
327
392
|
content: [
|
|
328
393
|
{
|
|
@@ -371,6 +436,9 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
371
436
|
const offerData = priceHistory.map((point) => point.offer);
|
|
372
437
|
const spreadData = priceHistory.map((point) => point.spread);
|
|
373
438
|
const volumeData = priceHistory.map((point) => point.volume);
|
|
439
|
+
const tradeData = priceHistory.map((point) => point.trade);
|
|
440
|
+
const vwapData = priceHistory.map((point) => point.vwap);
|
|
441
|
+
const twapData = priceHistory.map((point) => point.twap);
|
|
374
442
|
const config = {
|
|
375
443
|
type: "line",
|
|
376
444
|
data: {
|
|
@@ -400,6 +468,30 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
400
468
|
fill: false,
|
|
401
469
|
tension: 0.4
|
|
402
470
|
},
|
|
471
|
+
{
|
|
472
|
+
label: "Trade",
|
|
473
|
+
data: tradeData,
|
|
474
|
+
borderColor: "#ffc107",
|
|
475
|
+
backgroundColor: "rgba(255, 193, 7, 0.1)",
|
|
476
|
+
fill: false,
|
|
477
|
+
tension: 0.4
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
label: "VWAP",
|
|
481
|
+
data: vwapData,
|
|
482
|
+
borderColor: "#17a2b8",
|
|
483
|
+
backgroundColor: "rgba(23, 162, 184, 0.1)",
|
|
484
|
+
fill: false,
|
|
485
|
+
tension: 0.4
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
label: "TWAP",
|
|
489
|
+
data: twapData,
|
|
490
|
+
borderColor: "#6610f2",
|
|
491
|
+
backgroundColor: "rgba(102, 16, 242, 0.1)",
|
|
492
|
+
fill: false,
|
|
493
|
+
tension: 0.4
|
|
494
|
+
},
|
|
403
495
|
{
|
|
404
496
|
label: "Volume",
|
|
405
497
|
data: volumeData,
|
|
@@ -445,7 +537,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
445
537
|
content: [
|
|
446
538
|
{
|
|
447
539
|
type: "text",
|
|
448
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to generate
|
|
540
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
|
|
449
541
|
uri: "getStockGraph"
|
|
450
542
|
}
|
|
451
543
|
],
|
|
@@ -483,7 +575,48 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
|
|
|
483
575
|
bid: point.bid,
|
|
484
576
|
offer: point.offer,
|
|
485
577
|
spread: point.spread,
|
|
486
|
-
volume: point.volume
|
|
578
|
+
volume: point.volume,
|
|
579
|
+
trade: point.trade,
|
|
580
|
+
indexValue: point.indexValue,
|
|
581
|
+
openingPrice: point.openingPrice,
|
|
582
|
+
closingPrice: point.closingPrice,
|
|
583
|
+
settlementPrice: point.settlementPrice,
|
|
584
|
+
tradingSessionHighPrice: point.tradingSessionHighPrice,
|
|
585
|
+
tradingSessionLowPrice: point.tradingSessionLowPrice,
|
|
586
|
+
vwap: point.vwap,
|
|
587
|
+
imbalance: point.imbalance,
|
|
588
|
+
openInterest: point.openInterest,
|
|
589
|
+
compositeUnderlyingPrice: point.compositeUnderlyingPrice,
|
|
590
|
+
simulatedSellPrice: point.simulatedSellPrice,
|
|
591
|
+
simulatedBuyPrice: point.simulatedBuyPrice,
|
|
592
|
+
marginRate: point.marginRate,
|
|
593
|
+
midPrice: point.midPrice,
|
|
594
|
+
emptyBook: point.emptyBook,
|
|
595
|
+
settleHighPrice: point.settleHighPrice,
|
|
596
|
+
settleLowPrice: point.settleLowPrice,
|
|
597
|
+
priorSettlePrice: point.priorSettlePrice,
|
|
598
|
+
sessionHighBid: point.sessionHighBid,
|
|
599
|
+
sessionLowOffer: point.sessionLowOffer,
|
|
600
|
+
earlyPrices: point.earlyPrices,
|
|
601
|
+
auctionClearingPrice: point.auctionClearingPrice,
|
|
602
|
+
swapValueFactor: point.swapValueFactor,
|
|
603
|
+
dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
|
|
604
|
+
cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
|
|
605
|
+
dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
|
|
606
|
+
cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
|
|
607
|
+
fixingPrice: point.fixingPrice,
|
|
608
|
+
cashRate: point.cashRate,
|
|
609
|
+
recoveryRate: point.recoveryRate,
|
|
610
|
+
recoveryRateForLong: point.recoveryRateForLong,
|
|
611
|
+
recoveryRateForShort: point.recoveryRateForShort,
|
|
612
|
+
marketBid: point.marketBid,
|
|
613
|
+
marketOffer: point.marketOffer,
|
|
614
|
+
shortSaleMinPrice: point.shortSaleMinPrice,
|
|
615
|
+
previousClosingPrice: point.previousClosingPrice,
|
|
616
|
+
thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
|
|
617
|
+
dailyFinancingValue: point.dailyFinancingValue,
|
|
618
|
+
accruedFinancingValue: point.accruedFinancingValue,
|
|
619
|
+
twap: point.twap
|
|
487
620
|
}))
|
|
488
621
|
},
|
|
489
622
|
null,
|
|
@@ -498,7 +631,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
|
|
|
498
631
|
content: [
|
|
499
632
|
{
|
|
500
633
|
type: "text",
|
|
501
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to get
|
|
634
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
|
|
502
635
|
uri: "getStockPriceHistory"
|
|
503
636
|
}
|
|
504
637
|
],
|
|
@@ -606,7 +739,7 @@ Parameters verified:
|
|
|
606
739
|
- Symbol: ${args.symbol}
|
|
607
740
|
- TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
|
|
608
741
|
|
|
609
|
-
To execute this order, call the executeOrder tool with these exact same parameters
|
|
742
|
+
To execute this order, call the executeOrder tool with these exact same parameters. Important: The user has to explicitly confirm before executeOrder is called!`,
|
|
610
743
|
uri: "verifyOrder"
|
|
611
744
|
}
|
|
612
745
|
]
|
|
@@ -807,52 +940,256 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
|
|
|
807
940
|
|
|
808
941
|
// src/utils/messageHandler.ts
|
|
809
942
|
import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
|
|
943
|
+
function getEnumValue(enumObj, name) {
|
|
944
|
+
return enumObj[name] || name;
|
|
945
|
+
}
|
|
810
946
|
function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
|
|
811
947
|
parser.logger.log({
|
|
812
948
|
level: "info",
|
|
813
949
|
message: `MCP Server received message: ${message.messageType}: ${message.description}`
|
|
814
950
|
});
|
|
815
951
|
const msgType = message.messageType;
|
|
816
|
-
if (msgType === Messages3.MarketDataSnapshotFullRefresh) {
|
|
952
|
+
if (msgType === Messages3.MarketDataSnapshotFullRefresh || msgType === Messages3.MarketDataIncrementalRefresh) {
|
|
817
953
|
const symbol = message.getField(Fields3.Symbol)?.value;
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
const
|
|
823
|
-
const
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
const entryPrice = Number.parseFloat(entryPrices[i]?.value);
|
|
829
|
-
const entrySize = Number.parseFloat(entrySizes[i]?.value);
|
|
830
|
-
if (entryType === MDEntryType2.Bid) {
|
|
831
|
-
bid = entryPrice;
|
|
832
|
-
} else if (entryType === MDEntryType2.Offer) {
|
|
833
|
-
offer = entryPrice;
|
|
834
|
-
}
|
|
835
|
-
volume += entrySize;
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
const spread = offer - bid;
|
|
839
|
-
const timestamp = Date.now();
|
|
954
|
+
parser.logger.log({
|
|
955
|
+
level: "info",
|
|
956
|
+
message: `Processing market data for symbol: ${symbol}`
|
|
957
|
+
});
|
|
958
|
+
const fixJson = message.toFIXJSON();
|
|
959
|
+
const entries = fixJson.Body?.NoMDEntries || [];
|
|
960
|
+
parser.logger.log({
|
|
961
|
+
level: "info",
|
|
962
|
+
message: `Found ${entries.length} market data entries`
|
|
963
|
+
});
|
|
840
964
|
const data = {
|
|
841
|
-
timestamp,
|
|
842
|
-
bid,
|
|
843
|
-
offer,
|
|
844
|
-
spread,
|
|
845
|
-
volume
|
|
965
|
+
timestamp: Date.now(),
|
|
966
|
+
bid: 0,
|
|
967
|
+
offer: 0,
|
|
968
|
+
spread: 0,
|
|
969
|
+
volume: 0,
|
|
970
|
+
trade: 0,
|
|
971
|
+
indexValue: 0,
|
|
972
|
+
openingPrice: 0,
|
|
973
|
+
closingPrice: 0,
|
|
974
|
+
settlementPrice: 0,
|
|
975
|
+
tradingSessionHighPrice: 0,
|
|
976
|
+
tradingSessionLowPrice: 0,
|
|
977
|
+
vwap: 0,
|
|
978
|
+
imbalance: 0,
|
|
979
|
+
openInterest: 0,
|
|
980
|
+
compositeUnderlyingPrice: 0,
|
|
981
|
+
simulatedSellPrice: 0,
|
|
982
|
+
simulatedBuyPrice: 0,
|
|
983
|
+
marginRate: 0,
|
|
984
|
+
midPrice: 0,
|
|
985
|
+
emptyBook: 0,
|
|
986
|
+
settleHighPrice: 0,
|
|
987
|
+
settleLowPrice: 0,
|
|
988
|
+
priorSettlePrice: 0,
|
|
989
|
+
sessionHighBid: 0,
|
|
990
|
+
sessionLowOffer: 0,
|
|
991
|
+
earlyPrices: 0,
|
|
992
|
+
auctionClearingPrice: 0,
|
|
993
|
+
swapValueFactor: 0,
|
|
994
|
+
dailyValueAdjustmentForLongPositions: 0,
|
|
995
|
+
cumulativeValueAdjustmentForLongPositions: 0,
|
|
996
|
+
dailyValueAdjustmentForShortPositions: 0,
|
|
997
|
+
cumulativeValueAdjustmentForShortPositions: 0,
|
|
998
|
+
fixingPrice: 0,
|
|
999
|
+
cashRate: 0,
|
|
1000
|
+
recoveryRate: 0,
|
|
1001
|
+
recoveryRateForLong: 0,
|
|
1002
|
+
recoveryRateForShort: 0,
|
|
1003
|
+
marketBid: 0,
|
|
1004
|
+
marketOffer: 0,
|
|
1005
|
+
shortSaleMinPrice: 0,
|
|
1006
|
+
previousClosingPrice: 0,
|
|
1007
|
+
thresholdLimitPriceBanding: 0,
|
|
1008
|
+
dailyFinancingValue: 0,
|
|
1009
|
+
accruedFinancingValue: 0,
|
|
1010
|
+
twap: 0
|
|
846
1011
|
};
|
|
1012
|
+
for (const entry of entries) {
|
|
1013
|
+
const entryType = entry.MDEntryType;
|
|
1014
|
+
const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
|
|
1015
|
+
const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
|
|
1016
|
+
if (entryType === MDEntryType2.Bid || entryType === MDEntryType2.Offer || entryType === MDEntryType2.TradeVolume) {
|
|
1017
|
+
parser.logger.log({
|
|
1018
|
+
level: "info",
|
|
1019
|
+
message: `Market Data Entry - Type: ${entryType}, Price: ${price}, Size: ${size}`
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
const enumValue = getEnumValue(MDEntryType2, entryType);
|
|
1023
|
+
switch (enumValue) {
|
|
1024
|
+
case MDEntryType2.Bid:
|
|
1025
|
+
data.bid = price;
|
|
1026
|
+
break;
|
|
1027
|
+
case MDEntryType2.Offer:
|
|
1028
|
+
data.offer = price;
|
|
1029
|
+
break;
|
|
1030
|
+
case MDEntryType2.Trade:
|
|
1031
|
+
data.trade = price;
|
|
1032
|
+
break;
|
|
1033
|
+
case MDEntryType2.IndexValue:
|
|
1034
|
+
data.indexValue = price;
|
|
1035
|
+
break;
|
|
1036
|
+
case MDEntryType2.OpeningPrice:
|
|
1037
|
+
data.openingPrice = price;
|
|
1038
|
+
break;
|
|
1039
|
+
case MDEntryType2.ClosingPrice:
|
|
1040
|
+
data.closingPrice = price;
|
|
1041
|
+
break;
|
|
1042
|
+
case MDEntryType2.SettlementPrice:
|
|
1043
|
+
data.settlementPrice = price;
|
|
1044
|
+
break;
|
|
1045
|
+
case MDEntryType2.TradingSessionHighPrice:
|
|
1046
|
+
data.tradingSessionHighPrice = price;
|
|
1047
|
+
break;
|
|
1048
|
+
case MDEntryType2.TradingSessionLowPrice:
|
|
1049
|
+
data.tradingSessionLowPrice = price;
|
|
1050
|
+
break;
|
|
1051
|
+
case MDEntryType2.VWAP:
|
|
1052
|
+
data.vwap = price;
|
|
1053
|
+
break;
|
|
1054
|
+
case MDEntryType2.Imbalance:
|
|
1055
|
+
data.imbalance = size;
|
|
1056
|
+
break;
|
|
1057
|
+
case MDEntryType2.TradeVolume:
|
|
1058
|
+
data.volume = size;
|
|
1059
|
+
break;
|
|
1060
|
+
case MDEntryType2.OpenInterest:
|
|
1061
|
+
data.openInterest = size;
|
|
1062
|
+
break;
|
|
1063
|
+
case MDEntryType2.CompositeUnderlyingPrice:
|
|
1064
|
+
data.compositeUnderlyingPrice = price;
|
|
1065
|
+
break;
|
|
1066
|
+
case MDEntryType2.SimulatedSellPrice:
|
|
1067
|
+
data.simulatedSellPrice = price;
|
|
1068
|
+
break;
|
|
1069
|
+
case MDEntryType2.SimulatedBuyPrice:
|
|
1070
|
+
data.simulatedBuyPrice = price;
|
|
1071
|
+
break;
|
|
1072
|
+
case MDEntryType2.MarginRate:
|
|
1073
|
+
data.marginRate = price;
|
|
1074
|
+
break;
|
|
1075
|
+
case MDEntryType2.MidPrice:
|
|
1076
|
+
data.midPrice = price;
|
|
1077
|
+
break;
|
|
1078
|
+
case MDEntryType2.EmptyBook:
|
|
1079
|
+
data.emptyBook = 1;
|
|
1080
|
+
break;
|
|
1081
|
+
case MDEntryType2.SettleHighPrice:
|
|
1082
|
+
data.settleHighPrice = price;
|
|
1083
|
+
break;
|
|
1084
|
+
case MDEntryType2.SettleLowPrice:
|
|
1085
|
+
data.settleLowPrice = price;
|
|
1086
|
+
break;
|
|
1087
|
+
case MDEntryType2.PriorSettlePrice:
|
|
1088
|
+
data.priorSettlePrice = price;
|
|
1089
|
+
break;
|
|
1090
|
+
case MDEntryType2.SessionHighBid:
|
|
1091
|
+
data.sessionHighBid = price;
|
|
1092
|
+
break;
|
|
1093
|
+
case MDEntryType2.SessionLowOffer:
|
|
1094
|
+
data.sessionLowOffer = price;
|
|
1095
|
+
break;
|
|
1096
|
+
case MDEntryType2.EarlyPrices:
|
|
1097
|
+
data.earlyPrices = price;
|
|
1098
|
+
break;
|
|
1099
|
+
case MDEntryType2.AuctionClearingPrice:
|
|
1100
|
+
data.auctionClearingPrice = price;
|
|
1101
|
+
break;
|
|
1102
|
+
case MDEntryType2.SwapValueFactor:
|
|
1103
|
+
data.swapValueFactor = price;
|
|
1104
|
+
break;
|
|
1105
|
+
case MDEntryType2.DailyValueAdjustmentForLongPositions:
|
|
1106
|
+
data.dailyValueAdjustmentForLongPositions = price;
|
|
1107
|
+
break;
|
|
1108
|
+
case MDEntryType2.CumulativeValueAdjustmentForLongPositions:
|
|
1109
|
+
data.cumulativeValueAdjustmentForLongPositions = price;
|
|
1110
|
+
break;
|
|
1111
|
+
case MDEntryType2.DailyValueAdjustmentForShortPositions:
|
|
1112
|
+
data.dailyValueAdjustmentForShortPositions = price;
|
|
1113
|
+
break;
|
|
1114
|
+
case MDEntryType2.CumulativeValueAdjustmentForShortPositions:
|
|
1115
|
+
data.cumulativeValueAdjustmentForShortPositions = price;
|
|
1116
|
+
break;
|
|
1117
|
+
case MDEntryType2.FixingPrice:
|
|
1118
|
+
data.fixingPrice = price;
|
|
1119
|
+
break;
|
|
1120
|
+
case MDEntryType2.CashRate:
|
|
1121
|
+
data.cashRate = price;
|
|
1122
|
+
break;
|
|
1123
|
+
case MDEntryType2.RecoveryRate:
|
|
1124
|
+
data.recoveryRate = price;
|
|
1125
|
+
break;
|
|
1126
|
+
case MDEntryType2.RecoveryRateForLong:
|
|
1127
|
+
data.recoveryRateForLong = price;
|
|
1128
|
+
break;
|
|
1129
|
+
case MDEntryType2.RecoveryRateForShort:
|
|
1130
|
+
data.recoveryRateForShort = price;
|
|
1131
|
+
break;
|
|
1132
|
+
case MDEntryType2.MarketBid:
|
|
1133
|
+
data.marketBid = price;
|
|
1134
|
+
break;
|
|
1135
|
+
case MDEntryType2.MarketOffer:
|
|
1136
|
+
data.marketOffer = price;
|
|
1137
|
+
break;
|
|
1138
|
+
case MDEntryType2.ShortSaleMinPrice:
|
|
1139
|
+
data.shortSaleMinPrice = price;
|
|
1140
|
+
break;
|
|
1141
|
+
case MDEntryType2.PreviousClosingPrice:
|
|
1142
|
+
data.previousClosingPrice = price;
|
|
1143
|
+
break;
|
|
1144
|
+
case MDEntryType2.ThresholdLimitPriceBanding:
|
|
1145
|
+
data.thresholdLimitPriceBanding = price;
|
|
1146
|
+
break;
|
|
1147
|
+
case MDEntryType2.DailyFinancingValue:
|
|
1148
|
+
data.dailyFinancingValue = price;
|
|
1149
|
+
break;
|
|
1150
|
+
case MDEntryType2.AccruedFinancingValue:
|
|
1151
|
+
data.accruedFinancingValue = price;
|
|
1152
|
+
break;
|
|
1153
|
+
case MDEntryType2.TWAP:
|
|
1154
|
+
data.twap = price;
|
|
1155
|
+
break;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
data.spread = data.offer - data.bid;
|
|
1159
|
+
console.log(">>>>>>>>>>>>>>>>>>>>", data);
|
|
847
1160
|
if (!marketDataPrices.has(symbol)) {
|
|
1161
|
+
parser.logger.log({
|
|
1162
|
+
level: "info",
|
|
1163
|
+
message: `Creating new price history array for symbol: ${symbol}`
|
|
1164
|
+
});
|
|
848
1165
|
marketDataPrices.set(symbol, []);
|
|
849
1166
|
}
|
|
850
1167
|
const prices = marketDataPrices.get(symbol);
|
|
851
1168
|
prices.push(data);
|
|
1169
|
+
parser.logger.log({
|
|
1170
|
+
level: "info",
|
|
1171
|
+
message: `Updated price history for ${symbol}. Current size: ${prices.length}`
|
|
1172
|
+
});
|
|
852
1173
|
if (prices.length > maxPriceHistory) {
|
|
853
1174
|
prices.splice(0, prices.length - maxPriceHistory);
|
|
1175
|
+
parser.logger.log({
|
|
1176
|
+
level: "info",
|
|
1177
|
+
message: `Trimmed price history for ${symbol} to ${maxPriceHistory} entries`
|
|
1178
|
+
});
|
|
854
1179
|
}
|
|
855
1180
|
onPriceUpdate?.(symbol, data);
|
|
1181
|
+
const mdReqID = message.getField(Fields3.MDReqID)?.value;
|
|
1182
|
+
if (mdReqID) {
|
|
1183
|
+
const callback = pendingRequests.get(mdReqID);
|
|
1184
|
+
if (callback) {
|
|
1185
|
+
callback(message);
|
|
1186
|
+
pendingRequests.delete(mdReqID);
|
|
1187
|
+
parser.logger.log({
|
|
1188
|
+
level: "info",
|
|
1189
|
+
message: `Resolved market data request for ID: ${mdReqID}`
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
856
1193
|
} else if (msgType === Messages3.ExecutionReport) {
|
|
857
1194
|
const reqId = message.getField(Fields3.ClOrdID)?.value;
|
|
858
1195
|
const callback = pendingRequests.get(reqId);
|
|
@@ -865,6 +1202,39 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
|
|
|
865
1202
|
|
|
866
1203
|
// src/MCPRemote.ts
|
|
867
1204
|
var transports = {};
|
|
1205
|
+
function jsonSchemaToZod(schema) {
|
|
1206
|
+
if (schema.type === "object") {
|
|
1207
|
+
const shape = {};
|
|
1208
|
+
for (const [key, prop] of Object.entries(schema.properties || {})) {
|
|
1209
|
+
const propSchema = prop;
|
|
1210
|
+
if (propSchema.type === "string") {
|
|
1211
|
+
if (propSchema.enum) {
|
|
1212
|
+
shape[key] = z.enum(propSchema.enum);
|
|
1213
|
+
} else {
|
|
1214
|
+
shape[key] = z.string();
|
|
1215
|
+
}
|
|
1216
|
+
} else if (propSchema.type === "number") {
|
|
1217
|
+
shape[key] = z.number();
|
|
1218
|
+
} else if (propSchema.type === "boolean") {
|
|
1219
|
+
shape[key] = z.boolean();
|
|
1220
|
+
} else if (propSchema.type === "array") {
|
|
1221
|
+
if (propSchema.items.type === "string") {
|
|
1222
|
+
shape[key] = z.array(z.string());
|
|
1223
|
+
} else if (propSchema.items.type === "number") {
|
|
1224
|
+
shape[key] = z.array(z.number());
|
|
1225
|
+
} else if (propSchema.items.type === "boolean") {
|
|
1226
|
+
shape[key] = z.array(z.boolean());
|
|
1227
|
+
} else {
|
|
1228
|
+
shape[key] = z.array(z.any());
|
|
1229
|
+
}
|
|
1230
|
+
} else {
|
|
1231
|
+
shape[key] = z.any();
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
return shape;
|
|
1235
|
+
}
|
|
1236
|
+
return {};
|
|
1237
|
+
}
|
|
868
1238
|
var MCPRemote = class extends MCPBase {
|
|
869
1239
|
/**
|
|
870
1240
|
* Port number the server will listen on.
|
|
@@ -907,7 +1277,7 @@ var MCPRemote = class extends MCPBase {
|
|
|
907
1277
|
*/
|
|
908
1278
|
marketDataPrices = /* @__PURE__ */ new Map();
|
|
909
1279
|
/**
|
|
910
|
-
* Maximum number of price
|
|
1280
|
+
* Maximum number of price history entries to keep per symbol
|
|
911
1281
|
* @private
|
|
912
1282
|
*/
|
|
913
1283
|
MAX_PRICE_HISTORY = 1e5;
|
|
@@ -929,55 +1299,22 @@ var MCPRemote = class extends MCPBase {
|
|
|
929
1299
|
this.parser,
|
|
930
1300
|
this.pendingRequests,
|
|
931
1301
|
this.marketDataPrices,
|
|
932
|
-
this.MAX_PRICE_HISTORY
|
|
933
|
-
(symbol, data) => {
|
|
934
|
-
this.mcpServer?.tool(
|
|
935
|
-
"priceUpdate",
|
|
936
|
-
{
|
|
937
|
-
description: "Price update notification",
|
|
938
|
-
schema: z.object({
|
|
939
|
-
symbol: z.string(),
|
|
940
|
-
timestamp: z.number(),
|
|
941
|
-
bid: z.number(),
|
|
942
|
-
offer: z.number(),
|
|
943
|
-
spread: z.number(),
|
|
944
|
-
volume: z.number()
|
|
945
|
-
})
|
|
946
|
-
},
|
|
947
|
-
() => ({
|
|
948
|
-
content: [
|
|
949
|
-
{
|
|
950
|
-
type: "text",
|
|
951
|
-
text: JSON.stringify({ symbol, ...data })
|
|
952
|
-
}
|
|
953
|
-
]
|
|
954
|
-
})
|
|
955
|
-
);
|
|
956
|
-
}
|
|
1302
|
+
this.MAX_PRICE_HISTORY
|
|
957
1303
|
);
|
|
1304
|
+
this.logger?.log({
|
|
1305
|
+
level: "info",
|
|
1306
|
+
message: `Market Data Prices TEST: ${JSON.stringify(this.marketDataPrices)}`
|
|
1307
|
+
});
|
|
958
1308
|
}
|
|
959
1309
|
});
|
|
960
1310
|
this.httpServer = createServer(async (req, res) => {
|
|
961
|
-
console.log(req.headers);
|
|
962
|
-
this.logger?.log({
|
|
963
|
-
level: "info",
|
|
964
|
-
message: `Incoming request: ${req.method} ${req.url}`
|
|
965
|
-
});
|
|
966
1311
|
if (!req.url || !req.method) {
|
|
967
|
-
this.logger?.log({
|
|
968
|
-
level: "error",
|
|
969
|
-
message: "Invalid request: missing URL or method"
|
|
970
|
-
});
|
|
971
1312
|
res.writeHead(400);
|
|
972
1313
|
res.end("Bad Request");
|
|
973
1314
|
return;
|
|
974
1315
|
}
|
|
975
1316
|
if (req.url === "/mcp") {
|
|
976
1317
|
const sessionId = req.headers["mcp-session-id"];
|
|
977
|
-
this.logger?.log({
|
|
978
|
-
level: "info",
|
|
979
|
-
message: `MCP request received. Session ID: ${sessionId || "none"}, headers: ${req.headers}`
|
|
980
|
-
});
|
|
981
1318
|
if (req.method === "POST") {
|
|
982
1319
|
const bodyChunks = [];
|
|
983
1320
|
req.on("data", (chunk) => {
|
|
@@ -988,47 +1325,23 @@ var MCPRemote = class extends MCPBase {
|
|
|
988
1325
|
const body = Buffer.concat(bodyChunks).toString();
|
|
989
1326
|
try {
|
|
990
1327
|
parsed = JSON.parse(body);
|
|
991
|
-
this.logger?.log({
|
|
992
|
-
level: "info",
|
|
993
|
-
message: `Parsed request body: ${JSON.stringify(parsed)}`
|
|
994
|
-
});
|
|
995
1328
|
} catch (err) {
|
|
996
|
-
this.logger?.log({
|
|
997
|
-
level: "error",
|
|
998
|
-
message: `Failed to parse JSON body: ${err}`
|
|
999
|
-
});
|
|
1000
1329
|
res.writeHead(400);
|
|
1001
1330
|
res.end(JSON.stringify({ error: "Invalid JSON" }));
|
|
1002
1331
|
return;
|
|
1003
1332
|
}
|
|
1004
1333
|
let transport;
|
|
1005
1334
|
if (sessionId && transports[sessionId]) {
|
|
1006
|
-
this.logger?.log({
|
|
1007
|
-
level: "info",
|
|
1008
|
-
message: `Using existing transport for session: ${sessionId}`
|
|
1009
|
-
});
|
|
1010
1335
|
transport = transports[sessionId];
|
|
1011
1336
|
} else if (!sessionId && req.method === "POST" && isInitializeRequest(parsed)) {
|
|
1012
|
-
this.logger?.log({
|
|
1013
|
-
level: "info",
|
|
1014
|
-
message: "Creating new transport for initialization request"
|
|
1015
|
-
});
|
|
1016
1337
|
transport = new StreamableHTTPServerTransport({
|
|
1017
1338
|
sessionIdGenerator: () => randomUUID(),
|
|
1018
1339
|
onsessioninitialized: (sessionId2) => {
|
|
1019
|
-
this.logger?.log({
|
|
1020
|
-
level: "info",
|
|
1021
|
-
message: `New session initialized: ${sessionId2}`
|
|
1022
|
-
});
|
|
1023
1340
|
transports[sessionId2] = transport;
|
|
1024
1341
|
}
|
|
1025
1342
|
});
|
|
1026
1343
|
transport.onclose = () => {
|
|
1027
1344
|
if (transport.sessionId) {
|
|
1028
|
-
this.logger?.log({
|
|
1029
|
-
level: "info",
|
|
1030
|
-
message: `Session closed: ${transport.sessionId}`
|
|
1031
|
-
});
|
|
1032
1345
|
delete transports[transport.sessionId];
|
|
1033
1346
|
}
|
|
1034
1347
|
};
|
|
@@ -1039,10 +1352,6 @@ var MCPRemote = class extends MCPBase {
|
|
|
1039
1352
|
this.setupTools();
|
|
1040
1353
|
await this.mcpServer.connect(transport);
|
|
1041
1354
|
} else {
|
|
1042
|
-
this.logger?.log({
|
|
1043
|
-
level: "error",
|
|
1044
|
-
message: "Invalid request: No valid session ID provided"
|
|
1045
|
-
});
|
|
1046
1355
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1047
1356
|
res.end(
|
|
1048
1357
|
JSON.stringify({
|
|
@@ -1058,10 +1367,6 @@ var MCPRemote = class extends MCPBase {
|
|
|
1058
1367
|
}
|
|
1059
1368
|
try {
|
|
1060
1369
|
await transport.handleRequest(req, res, parsed);
|
|
1061
|
-
this.logger?.log({
|
|
1062
|
-
level: "info",
|
|
1063
|
-
message: "Request handled successfully"
|
|
1064
|
-
});
|
|
1065
1370
|
} catch (error) {
|
|
1066
1371
|
this.logger?.log({
|
|
1067
1372
|
level: "error",
|
|
@@ -1072,10 +1377,6 @@ var MCPRemote = class extends MCPBase {
|
|
|
1072
1377
|
});
|
|
1073
1378
|
} else if (req.method === "GET" || req.method === "DELETE") {
|
|
1074
1379
|
if (!sessionId || !transports[sessionId]) {
|
|
1075
|
-
this.logger?.log({
|
|
1076
|
-
level: "error",
|
|
1077
|
-
message: `Invalid session ID for ${req.method} request: ${sessionId}`
|
|
1078
|
-
});
|
|
1079
1380
|
res.writeHead(400);
|
|
1080
1381
|
res.end("Invalid or missing session ID");
|
|
1081
1382
|
return;
|
|
@@ -1083,10 +1384,6 @@ var MCPRemote = class extends MCPBase {
|
|
|
1083
1384
|
const transport = transports[sessionId];
|
|
1084
1385
|
try {
|
|
1085
1386
|
await transport.handleRequest(req, res);
|
|
1086
|
-
this.logger?.log({
|
|
1087
|
-
level: "info",
|
|
1088
|
-
message: `${req.method} request handled successfully for session: ${sessionId}`
|
|
1089
|
-
});
|
|
1090
1387
|
} catch (error) {
|
|
1091
1388
|
this.logger?.log({
|
|
1092
1389
|
level: "error",
|
|
@@ -1103,10 +1400,6 @@ var MCPRemote = class extends MCPBase {
|
|
|
1103
1400
|
res.end("Method Not Allowed");
|
|
1104
1401
|
}
|
|
1105
1402
|
} else {
|
|
1106
|
-
this.logger?.log({
|
|
1107
|
-
level: "error",
|
|
1108
|
-
message: `Not found: ${req.url}`
|
|
1109
|
-
});
|
|
1110
1403
|
res.writeHead(404);
|
|
1111
1404
|
res.end("Not Found");
|
|
1112
1405
|
}
|
|
@@ -1136,69 +1429,40 @@ var MCPRemote = class extends MCPBase {
|
|
|
1136
1429
|
});
|
|
1137
1430
|
return;
|
|
1138
1431
|
}
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
},
|
|
1145
|
-
async () => {
|
|
1146
|
-
return {
|
|
1147
|
-
content: [
|
|
1148
|
-
{
|
|
1149
|
-
type: "text",
|
|
1150
|
-
text: JSON.stringify(
|
|
1151
|
-
Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
|
|
1152
|
-
name,
|
|
1153
|
-
description,
|
|
1154
|
-
inputSchema: schema
|
|
1155
|
-
}))
|
|
1156
|
-
)
|
|
1157
|
-
}
|
|
1158
|
-
]
|
|
1159
|
-
};
|
|
1160
|
-
}
|
|
1432
|
+
const toolHandlers = createToolHandlers(
|
|
1433
|
+
this.parser,
|
|
1434
|
+
this.verifiedOrders,
|
|
1435
|
+
this.pendingRequests,
|
|
1436
|
+
this.marketDataPrices
|
|
1161
1437
|
);
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
if (!handler) {
|
|
1438
|
+
Object.entries(toolSchemas).forEach(([name, { description, schema }]) => {
|
|
1439
|
+
this.mcpServer?.registerTool(
|
|
1440
|
+
name,
|
|
1441
|
+
{
|
|
1442
|
+
description,
|
|
1443
|
+
inputSchema: jsonSchemaToZod(schema)
|
|
1444
|
+
},
|
|
1445
|
+
async (args) => {
|
|
1446
|
+
const handler = toolHandlers[name];
|
|
1447
|
+
if (!handler) {
|
|
1448
|
+
return {
|
|
1449
|
+
content: [
|
|
1450
|
+
{
|
|
1451
|
+
type: "text",
|
|
1452
|
+
text: `Tool not found: ${name}`
|
|
1453
|
+
}
|
|
1454
|
+
],
|
|
1455
|
+
isError: true
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
const result = await handler(args);
|
|
1184
1459
|
return {
|
|
1185
|
-
content:
|
|
1186
|
-
|
|
1187
|
-
type: "text",
|
|
1188
|
-
text: `Tool not found: ${name}`,
|
|
1189
|
-
uri: name
|
|
1190
|
-
}
|
|
1191
|
-
],
|
|
1192
|
-
isError: true
|
|
1460
|
+
content: result.content,
|
|
1461
|
+
isError: result.isError
|
|
1193
1462
|
};
|
|
1194
1463
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
content: result.content,
|
|
1198
|
-
isError: result.isError
|
|
1199
|
-
};
|
|
1200
|
-
}
|
|
1201
|
-
);
|
|
1464
|
+
);
|
|
1465
|
+
});
|
|
1202
1466
|
}
|
|
1203
1467
|
};
|
|
1204
1468
|
export {
|