fixparser-plugin-mcp 9.1.7-eb1de32a → 9.1.7-edd9ee17
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 +528 -126
- package/build/cjs/MCPLocal.js.map +4 -4
- package/build/cjs/MCPRemote.js +1328 -435
- package/build/cjs/MCPRemote.js.map +4 -4
- package/build/cjs/index.js +1627 -0
- package/build/cjs/index.js.map +7 -0
- package/build/esm/MCPLocal.mjs +529 -127
- package/build/esm/MCPLocal.mjs.map +4 -4
- package/build/esm/MCPRemote.mjs +1318 -444
- package/build/esm/MCPRemote.mjs.map +4 -4
- package/build/esm/index.mjs +1589 -0
- package/build/esm/index.mjs.map +7 -0
- package/build-examples/cjs/example_mcp_local.js +7 -7
- package/build-examples/cjs/example_mcp_local.js.map +4 -4
- package/build-examples/cjs/example_mcp_remote.js +16 -0
- package/build-examples/cjs/example_mcp_remote.js.map +7 -0
- package/build-examples/esm/example_mcp_local.mjs +7 -7
- package/build-examples/esm/example_mcp_local.mjs.map +4 -4
- package/build-examples/esm/example_mcp_remote.mjs +16 -0
- package/build-examples/esm/example_mcp_remote.mjs.map +7 -0
- package/package.json +6 -6
- package/types/MCPBase.d.ts +49 -0
- package/types/MCPLocal.d.ts +25 -9
- package/types/MCPRemote.d.ts +25 -27
- package/types/schemas/index.d.ts +3 -17
- package/types/schemas/marketData.d.ts +48 -0
- package/types/schemas/schemas.d.ts +1 -1
- package/types/tools/index.d.ts +2 -8
- package/types/tools/marketData.d.ts +8 -23
- package/types/tools/order.d.ts +4 -3
- package/types/tools/parse.d.ts +2 -2
- package/types/tools/parseToJSON.d.ts +2 -2
- package/types/utils/messageHandler.d.ts +12 -0
package/build/esm/MCPLocal.mjs
CHANGED
|
@@ -1,9 +1,51 @@
|
|
|
1
1
|
// src/MCPLocal.ts
|
|
2
2
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import { Fields as Fields3, Messages as Messages3 } from "fixparser";
|
|
5
4
|
import { z } from "zod";
|
|
6
5
|
|
|
6
|
+
// src/MCPBase.ts
|
|
7
|
+
var MCPBase = class {
|
|
8
|
+
/**
|
|
9
|
+
* Optional logger instance for diagnostics and output.
|
|
10
|
+
* @protected
|
|
11
|
+
*/
|
|
12
|
+
logger;
|
|
13
|
+
/**
|
|
14
|
+
* FIXParser instance, set during plugin register().
|
|
15
|
+
* @protected
|
|
16
|
+
*/
|
|
17
|
+
parser;
|
|
18
|
+
/**
|
|
19
|
+
* Called when server is setup and listening.
|
|
20
|
+
* @protected
|
|
21
|
+
*/
|
|
22
|
+
onReady = void 0;
|
|
23
|
+
/**
|
|
24
|
+
* Map to store verified orders before execution
|
|
25
|
+
* @protected
|
|
26
|
+
*/
|
|
27
|
+
verifiedOrders = /* @__PURE__ */ new Map();
|
|
28
|
+
/**
|
|
29
|
+
* Map to store pending market data requests
|
|
30
|
+
* @protected
|
|
31
|
+
*/
|
|
32
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
33
|
+
/**
|
|
34
|
+
* Map to store market data prices
|
|
35
|
+
* @protected
|
|
36
|
+
*/
|
|
37
|
+
marketDataPrices = /* @__PURE__ */ new Map();
|
|
38
|
+
/**
|
|
39
|
+
* Maximum number of price history entries to keep per symbol
|
|
40
|
+
* @protected
|
|
41
|
+
*/
|
|
42
|
+
MAX_PRICE_HISTORY = 1e5;
|
|
43
|
+
constructor({ logger, onReady }) {
|
|
44
|
+
this.logger = logger;
|
|
45
|
+
this.onReady = onReady;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
7
49
|
// src/schemas/schemas.ts
|
|
8
50
|
var toolSchemas = {
|
|
9
51
|
parse: {
|
|
@@ -87,7 +129,7 @@ var toolSchemas = {
|
|
|
87
129
|
}
|
|
88
130
|
},
|
|
89
131
|
executeOrder: {
|
|
90
|
-
description: "Executes a verified order. verifyOrder must be called before executeOrder.
|
|
132
|
+
description: "Executes a verified order. verifyOrder must be called before executeOrder.",
|
|
91
133
|
schema: {
|
|
92
134
|
type: "object",
|
|
93
135
|
properties: {
|
|
@@ -204,12 +246,12 @@ var toolSchemas = {
|
|
|
204
246
|
"X",
|
|
205
247
|
"Y",
|
|
206
248
|
"Z"
|
|
207
|
-
]
|
|
208
|
-
|
|
209
|
-
|
|
249
|
+
]
|
|
250
|
+
},
|
|
251
|
+
description: "Market Data Entry Types: 0=Bid, 1=Offer, 2=Trade, 3=Index Value, 4=Opening Price, 5=Closing Price, 6=Settlement Price, 7=High Price, 8=Low Price, 9=Trade Volume, A=Open Interest, B=Simulated Sell Price, C=Simulated Buy Price, D=Empty Book, E=Session High Bid, F=Session Low Offer, G=Fixing Price, H=Electronic Volume, I=Threshold Limits and Price Band Variation, J=Clearing Price, K=Open Interest Change, L=Last Trade Price, M=Last Trade Volume, N=Last Trade Time, O=Last Trade Tick, P=Last Trade Exchange, Q=Last Trade ID, R=Last Trade Side, S=Last Trade Price Change, T=Last Trade Price Change Percent, U=Last Trade Price Change Basis Points, V=Last Trade Price Change Points, W=Last Trade Price Change Ticks, X=Last Trade Price Change Ticks Percent, Y=Last Trade Price Change Ticks Basis Points, Z=Last Trade Price Change Ticks Points"
|
|
210
252
|
}
|
|
211
253
|
},
|
|
212
|
-
required: ["mdUpdateType", "symbols", "mdReqID", "subscriptionRequestType"
|
|
254
|
+
required: ["mdUpdateType", "symbols", "mdReqID", "subscriptionRequestType"]
|
|
213
255
|
}
|
|
214
256
|
},
|
|
215
257
|
getStockGraph: {
|
|
@@ -235,14 +277,68 @@ var toolSchemas = {
|
|
|
235
277
|
};
|
|
236
278
|
|
|
237
279
|
// src/tools/marketData.ts
|
|
238
|
-
import { Field, Fields, Messages } from "fixparser";
|
|
280
|
+
import { Field, Fields, MDEntryType, Messages } from "fixparser";
|
|
239
281
|
import QuickChart from "quickchart-js";
|
|
240
282
|
var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
241
283
|
return async (args) => {
|
|
242
284
|
try {
|
|
285
|
+
parser.logger.log({
|
|
286
|
+
level: "info",
|
|
287
|
+
message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
|
|
288
|
+
});
|
|
243
289
|
const response = new Promise((resolve) => {
|
|
244
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
|
+
});
|
|
245
295
|
});
|
|
296
|
+
const entryTypes = args.mdEntryTypes || [
|
|
297
|
+
MDEntryType.Bid,
|
|
298
|
+
MDEntryType.Offer,
|
|
299
|
+
MDEntryType.Trade,
|
|
300
|
+
MDEntryType.IndexValue,
|
|
301
|
+
MDEntryType.OpeningPrice,
|
|
302
|
+
MDEntryType.ClosingPrice,
|
|
303
|
+
MDEntryType.SettlementPrice,
|
|
304
|
+
MDEntryType.TradingSessionHighPrice,
|
|
305
|
+
MDEntryType.TradingSessionLowPrice,
|
|
306
|
+
MDEntryType.VWAP,
|
|
307
|
+
MDEntryType.Imbalance,
|
|
308
|
+
MDEntryType.TradeVolume,
|
|
309
|
+
MDEntryType.OpenInterest,
|
|
310
|
+
MDEntryType.CompositeUnderlyingPrice,
|
|
311
|
+
MDEntryType.SimulatedSellPrice,
|
|
312
|
+
MDEntryType.SimulatedBuyPrice,
|
|
313
|
+
MDEntryType.MarginRate,
|
|
314
|
+
MDEntryType.MidPrice,
|
|
315
|
+
MDEntryType.EmptyBook,
|
|
316
|
+
MDEntryType.SettleHighPrice,
|
|
317
|
+
MDEntryType.SettleLowPrice,
|
|
318
|
+
MDEntryType.PriorSettlePrice,
|
|
319
|
+
MDEntryType.SessionHighBid,
|
|
320
|
+
MDEntryType.SessionLowOffer,
|
|
321
|
+
MDEntryType.EarlyPrices,
|
|
322
|
+
MDEntryType.AuctionClearingPrice,
|
|
323
|
+
MDEntryType.SwapValueFactor,
|
|
324
|
+
MDEntryType.DailyValueAdjustmentForLongPositions,
|
|
325
|
+
MDEntryType.CumulativeValueAdjustmentForLongPositions,
|
|
326
|
+
MDEntryType.DailyValueAdjustmentForShortPositions,
|
|
327
|
+
MDEntryType.CumulativeValueAdjustmentForShortPositions,
|
|
328
|
+
MDEntryType.FixingPrice,
|
|
329
|
+
MDEntryType.CashRate,
|
|
330
|
+
MDEntryType.RecoveryRate,
|
|
331
|
+
MDEntryType.RecoveryRateForLong,
|
|
332
|
+
MDEntryType.RecoveryRateForShort,
|
|
333
|
+
MDEntryType.MarketBid,
|
|
334
|
+
MDEntryType.MarketOffer,
|
|
335
|
+
MDEntryType.ShortSaleMinPrice,
|
|
336
|
+
MDEntryType.PreviousClosingPrice,
|
|
337
|
+
MDEntryType.ThresholdLimitPriceBanding,
|
|
338
|
+
MDEntryType.DailyFinancingValue,
|
|
339
|
+
MDEntryType.AccruedFinancingValue,
|
|
340
|
+
MDEntryType.TWAP
|
|
341
|
+
];
|
|
246
342
|
const messageFields = [
|
|
247
343
|
new Field(Fields.MsgType, Messages.MarketDataRequest),
|
|
248
344
|
new Field(Fields.SenderCompID, parser.sender),
|
|
@@ -258,12 +354,16 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
|
258
354
|
args.symbols.forEach((symbol) => {
|
|
259
355
|
messageFields.push(new Field(Fields.Symbol, symbol));
|
|
260
356
|
});
|
|
261
|
-
messageFields.push(new Field(Fields.NoMDEntryTypes,
|
|
262
|
-
|
|
357
|
+
messageFields.push(new Field(Fields.NoMDEntryTypes, entryTypes.length));
|
|
358
|
+
entryTypes.forEach((entryType) => {
|
|
263
359
|
messageFields.push(new Field(Fields.MDEntryType, entryType));
|
|
264
360
|
});
|
|
265
361
|
const mdr = parser.createMessage(...messageFields);
|
|
266
362
|
if (!parser.connected) {
|
|
363
|
+
parser.logger.log({
|
|
364
|
+
level: "error",
|
|
365
|
+
message: "Not connected. Cannot send market data request."
|
|
366
|
+
});
|
|
267
367
|
return {
|
|
268
368
|
content: [
|
|
269
369
|
{
|
|
@@ -275,8 +375,16 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
|
275
375
|
isError: true
|
|
276
376
|
};
|
|
277
377
|
}
|
|
378
|
+
parser.logger.log({
|
|
379
|
+
level: "info",
|
|
380
|
+
message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
|
|
381
|
+
});
|
|
278
382
|
parser.send(mdr);
|
|
279
383
|
const fixData = await response;
|
|
384
|
+
parser.logger.log({
|
|
385
|
+
level: "info",
|
|
386
|
+
message: `Received market data response for request ID: ${args.mdReqID}`
|
|
387
|
+
});
|
|
280
388
|
return {
|
|
281
389
|
content: [
|
|
282
390
|
{
|
|
@@ -317,18 +425,73 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
317
425
|
};
|
|
318
426
|
}
|
|
319
427
|
const chart = new QuickChart();
|
|
320
|
-
chart.setWidth(
|
|
321
|
-
chart.setHeight(
|
|
428
|
+
chart.setWidth(1200);
|
|
429
|
+
chart.setHeight(600);
|
|
430
|
+
chart.setBackgroundColor("transparent");
|
|
322
431
|
const labels = priceHistory.map((point) => new Date(point.timestamp).toLocaleTimeString());
|
|
323
|
-
const
|
|
324
|
-
|
|
432
|
+
const bidData = priceHistory.map((point) => point.bid);
|
|
433
|
+
const offerData = priceHistory.map((point) => point.offer);
|
|
434
|
+
const spreadData = priceHistory.map((point) => point.spread);
|
|
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);
|
|
439
|
+
const config = {
|
|
325
440
|
type: "line",
|
|
326
441
|
data: {
|
|
327
442
|
labels,
|
|
328
443
|
datasets: [
|
|
329
444
|
{
|
|
330
|
-
label:
|
|
331
|
-
data,
|
|
445
|
+
label: "Bid",
|
|
446
|
+
data: bidData,
|
|
447
|
+
borderColor: "#28a745",
|
|
448
|
+
backgroundColor: "rgba(40, 167, 69, 0.1)",
|
|
449
|
+
fill: false,
|
|
450
|
+
tension: 0.4
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
label: "Offer",
|
|
454
|
+
data: offerData,
|
|
455
|
+
borderColor: "#dc3545",
|
|
456
|
+
backgroundColor: "rgba(220, 53, 69, 0.1)",
|
|
457
|
+
fill: false,
|
|
458
|
+
tension: 0.4
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
label: "Spread",
|
|
462
|
+
data: spreadData,
|
|
463
|
+
borderColor: "#6c757d",
|
|
464
|
+
backgroundColor: "rgba(108, 117, 125, 0.1)",
|
|
465
|
+
fill: false,
|
|
466
|
+
tension: 0.4
|
|
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
|
+
},
|
|
492
|
+
{
|
|
493
|
+
label: "Volume",
|
|
494
|
+
data: volumeData,
|
|
332
495
|
borderColor: "#007bff",
|
|
333
496
|
backgroundColor: "rgba(0, 123, 255, 0.1)",
|
|
334
497
|
fill: true,
|
|
@@ -337,46 +500,32 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
337
500
|
]
|
|
338
501
|
},
|
|
339
502
|
options: {
|
|
503
|
+
responsive: true,
|
|
340
504
|
plugins: {
|
|
341
505
|
title: {
|
|
342
506
|
display: true,
|
|
343
|
-
text: `${symbol}
|
|
344
|
-
font: {
|
|
345
|
-
size: 16,
|
|
346
|
-
weight: "bold"
|
|
347
|
-
}
|
|
348
|
-
},
|
|
349
|
-
legend: {
|
|
350
|
-
display: true
|
|
507
|
+
text: `${symbol} Market Data`
|
|
351
508
|
}
|
|
352
509
|
},
|
|
353
510
|
scales: {
|
|
354
511
|
y: {
|
|
355
|
-
beginAtZero: false
|
|
356
|
-
grid: {
|
|
357
|
-
color: "#e9ecef"
|
|
358
|
-
}
|
|
359
|
-
},
|
|
360
|
-
x: {
|
|
361
|
-
grid: {
|
|
362
|
-
display: false
|
|
363
|
-
}
|
|
512
|
+
beginAtZero: false
|
|
364
513
|
}
|
|
365
514
|
}
|
|
366
515
|
}
|
|
367
|
-
}
|
|
516
|
+
};
|
|
517
|
+
chart.setConfig(config);
|
|
368
518
|
const imageBuffer = await chart.toBinary();
|
|
369
|
-
const
|
|
519
|
+
const base64 = imageBuffer.toString("base64");
|
|
370
520
|
return {
|
|
371
521
|
content: [
|
|
372
522
|
{
|
|
373
|
-
type: "
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
mimeType: "image/png"
|
|
523
|
+
type: "resource",
|
|
524
|
+
resource: {
|
|
525
|
+
uri: "resource://graph",
|
|
526
|
+
mimeType: "image/png",
|
|
527
|
+
blob: base64
|
|
528
|
+
}
|
|
380
529
|
}
|
|
381
530
|
]
|
|
382
531
|
};
|
|
@@ -385,7 +534,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
385
534
|
content: [
|
|
386
535
|
{
|
|
387
536
|
type: "text",
|
|
388
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to generate
|
|
537
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
|
|
389
538
|
uri: "getStockGraph"
|
|
390
539
|
}
|
|
391
540
|
],
|
|
@@ -418,9 +567,53 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
|
|
|
418
567
|
{
|
|
419
568
|
symbol,
|
|
420
569
|
count: priceHistory.length,
|
|
421
|
-
|
|
570
|
+
data: priceHistory.map((point) => ({
|
|
422
571
|
timestamp: new Date(point.timestamp).toISOString(),
|
|
423
|
-
|
|
572
|
+
bid: point.bid,
|
|
573
|
+
offer: point.offer,
|
|
574
|
+
spread: point.spread,
|
|
575
|
+
volume: point.volume,
|
|
576
|
+
trade: point.trade,
|
|
577
|
+
indexValue: point.indexValue,
|
|
578
|
+
openingPrice: point.openingPrice,
|
|
579
|
+
closingPrice: point.closingPrice,
|
|
580
|
+
settlementPrice: point.settlementPrice,
|
|
581
|
+
tradingSessionHighPrice: point.tradingSessionHighPrice,
|
|
582
|
+
tradingSessionLowPrice: point.tradingSessionLowPrice,
|
|
583
|
+
vwap: point.vwap,
|
|
584
|
+
imbalance: point.imbalance,
|
|
585
|
+
openInterest: point.openInterest,
|
|
586
|
+
compositeUnderlyingPrice: point.compositeUnderlyingPrice,
|
|
587
|
+
simulatedSellPrice: point.simulatedSellPrice,
|
|
588
|
+
simulatedBuyPrice: point.simulatedBuyPrice,
|
|
589
|
+
marginRate: point.marginRate,
|
|
590
|
+
midPrice: point.midPrice,
|
|
591
|
+
emptyBook: point.emptyBook,
|
|
592
|
+
settleHighPrice: point.settleHighPrice,
|
|
593
|
+
settleLowPrice: point.settleLowPrice,
|
|
594
|
+
priorSettlePrice: point.priorSettlePrice,
|
|
595
|
+
sessionHighBid: point.sessionHighBid,
|
|
596
|
+
sessionLowOffer: point.sessionLowOffer,
|
|
597
|
+
earlyPrices: point.earlyPrices,
|
|
598
|
+
auctionClearingPrice: point.auctionClearingPrice,
|
|
599
|
+
swapValueFactor: point.swapValueFactor,
|
|
600
|
+
dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
|
|
601
|
+
cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
|
|
602
|
+
dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
|
|
603
|
+
cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
|
|
604
|
+
fixingPrice: point.fixingPrice,
|
|
605
|
+
cashRate: point.cashRate,
|
|
606
|
+
recoveryRate: point.recoveryRate,
|
|
607
|
+
recoveryRateForLong: point.recoveryRateForLong,
|
|
608
|
+
recoveryRateForShort: point.recoveryRateForShort,
|
|
609
|
+
marketBid: point.marketBid,
|
|
610
|
+
marketOffer: point.marketOffer,
|
|
611
|
+
shortSaleMinPrice: point.shortSaleMinPrice,
|
|
612
|
+
previousClosingPrice: point.previousClosingPrice,
|
|
613
|
+
thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
|
|
614
|
+
dailyFinancingValue: point.dailyFinancingValue,
|
|
615
|
+
accruedFinancingValue: point.accruedFinancingValue,
|
|
616
|
+
twap: point.twap
|
|
424
617
|
}))
|
|
425
618
|
},
|
|
426
619
|
null,
|
|
@@ -435,7 +628,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
|
|
|
435
628
|
content: [
|
|
436
629
|
{
|
|
437
630
|
type: "text",
|
|
438
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to get
|
|
631
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
|
|
439
632
|
uri: "getStockPriceHistory"
|
|
440
633
|
}
|
|
441
634
|
],
|
|
@@ -543,7 +736,7 @@ Parameters verified:
|
|
|
543
736
|
- Symbol: ${args.symbol}
|
|
544
737
|
- TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
|
|
545
738
|
|
|
546
|
-
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!`,
|
|
547
740
|
uri: "verifyOrder"
|
|
548
741
|
}
|
|
549
742
|
]
|
|
@@ -742,9 +935,285 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
|
|
|
742
935
|
getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
|
|
743
936
|
});
|
|
744
937
|
|
|
938
|
+
// src/utils/messageHandler.ts
|
|
939
|
+
import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
|
|
940
|
+
function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
|
|
941
|
+
parser.logger.log({
|
|
942
|
+
level: "info",
|
|
943
|
+
message: `MCP Server received message: ${message.messageType}: ${message.description}`
|
|
944
|
+
});
|
|
945
|
+
const msgType = message.messageType;
|
|
946
|
+
if (msgType === Messages3.MarketDataSnapshotFullRefresh || msgType === Messages3.MarketDataIncrementalRefresh) {
|
|
947
|
+
const symbol = message.getField(Fields3.Symbol)?.value;
|
|
948
|
+
parser.logger.log({
|
|
949
|
+
level: "info",
|
|
950
|
+
message: `Processing market data for symbol: ${symbol}`
|
|
951
|
+
});
|
|
952
|
+
const fixJson = message.toFIXJSON();
|
|
953
|
+
const entries = fixJson.Body?.NoMDEntries || [];
|
|
954
|
+
parser.logger.log({
|
|
955
|
+
level: "info",
|
|
956
|
+
message: `Found ${entries.length} market data entries`
|
|
957
|
+
});
|
|
958
|
+
const data = {
|
|
959
|
+
timestamp: Date.now(),
|
|
960
|
+
bid: 0,
|
|
961
|
+
offer: 0,
|
|
962
|
+
spread: 0,
|
|
963
|
+
volume: 0,
|
|
964
|
+
trade: 0,
|
|
965
|
+
indexValue: 0,
|
|
966
|
+
openingPrice: 0,
|
|
967
|
+
closingPrice: 0,
|
|
968
|
+
settlementPrice: 0,
|
|
969
|
+
tradingSessionHighPrice: 0,
|
|
970
|
+
tradingSessionLowPrice: 0,
|
|
971
|
+
vwap: 0,
|
|
972
|
+
imbalance: 0,
|
|
973
|
+
openInterest: 0,
|
|
974
|
+
compositeUnderlyingPrice: 0,
|
|
975
|
+
simulatedSellPrice: 0,
|
|
976
|
+
simulatedBuyPrice: 0,
|
|
977
|
+
marginRate: 0,
|
|
978
|
+
midPrice: 0,
|
|
979
|
+
emptyBook: 0,
|
|
980
|
+
settleHighPrice: 0,
|
|
981
|
+
settleLowPrice: 0,
|
|
982
|
+
priorSettlePrice: 0,
|
|
983
|
+
sessionHighBid: 0,
|
|
984
|
+
sessionLowOffer: 0,
|
|
985
|
+
earlyPrices: 0,
|
|
986
|
+
auctionClearingPrice: 0,
|
|
987
|
+
swapValueFactor: 0,
|
|
988
|
+
dailyValueAdjustmentForLongPositions: 0,
|
|
989
|
+
cumulativeValueAdjustmentForLongPositions: 0,
|
|
990
|
+
dailyValueAdjustmentForShortPositions: 0,
|
|
991
|
+
cumulativeValueAdjustmentForShortPositions: 0,
|
|
992
|
+
fixingPrice: 0,
|
|
993
|
+
cashRate: 0,
|
|
994
|
+
recoveryRate: 0,
|
|
995
|
+
recoveryRateForLong: 0,
|
|
996
|
+
recoveryRateForShort: 0,
|
|
997
|
+
marketBid: 0,
|
|
998
|
+
marketOffer: 0,
|
|
999
|
+
shortSaleMinPrice: 0,
|
|
1000
|
+
previousClosingPrice: 0,
|
|
1001
|
+
thresholdLimitPriceBanding: 0,
|
|
1002
|
+
dailyFinancingValue: 0,
|
|
1003
|
+
accruedFinancingValue: 0,
|
|
1004
|
+
twap: 0
|
|
1005
|
+
};
|
|
1006
|
+
for (const entry of entries) {
|
|
1007
|
+
const entryType = entry.MDEntryType;
|
|
1008
|
+
const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
|
|
1009
|
+
const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
|
|
1010
|
+
if (entryType === MDEntryType2.Bid || entryType === MDEntryType2.Offer || entryType === MDEntryType2.TradeVolume) {
|
|
1011
|
+
parser.logger.log({
|
|
1012
|
+
level: "info",
|
|
1013
|
+
message: `Market Data Entry - Type: ${entryType}, Price: ${price}, Size: ${size}`
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
switch (entryType) {
|
|
1017
|
+
case MDEntryType2.Bid:
|
|
1018
|
+
data.bid = price;
|
|
1019
|
+
break;
|
|
1020
|
+
case MDEntryType2.Offer:
|
|
1021
|
+
data.offer = price;
|
|
1022
|
+
break;
|
|
1023
|
+
case MDEntryType2.Trade:
|
|
1024
|
+
data.trade = price;
|
|
1025
|
+
break;
|
|
1026
|
+
case MDEntryType2.IndexValue:
|
|
1027
|
+
data.indexValue = price;
|
|
1028
|
+
break;
|
|
1029
|
+
case MDEntryType2.OpeningPrice:
|
|
1030
|
+
data.openingPrice = price;
|
|
1031
|
+
break;
|
|
1032
|
+
case MDEntryType2.ClosingPrice:
|
|
1033
|
+
data.closingPrice = price;
|
|
1034
|
+
break;
|
|
1035
|
+
case MDEntryType2.SettlementPrice:
|
|
1036
|
+
data.settlementPrice = price;
|
|
1037
|
+
break;
|
|
1038
|
+
case MDEntryType2.TradingSessionHighPrice:
|
|
1039
|
+
data.tradingSessionHighPrice = price;
|
|
1040
|
+
break;
|
|
1041
|
+
case MDEntryType2.TradingSessionLowPrice:
|
|
1042
|
+
data.tradingSessionLowPrice = price;
|
|
1043
|
+
break;
|
|
1044
|
+
case MDEntryType2.VWAP:
|
|
1045
|
+
data.vwap = price;
|
|
1046
|
+
break;
|
|
1047
|
+
case MDEntryType2.Imbalance:
|
|
1048
|
+
data.imbalance = size;
|
|
1049
|
+
break;
|
|
1050
|
+
case MDEntryType2.TradeVolume:
|
|
1051
|
+
data.volume = size;
|
|
1052
|
+
break;
|
|
1053
|
+
case MDEntryType2.OpenInterest:
|
|
1054
|
+
data.openInterest = size;
|
|
1055
|
+
break;
|
|
1056
|
+
case MDEntryType2.CompositeUnderlyingPrice:
|
|
1057
|
+
data.compositeUnderlyingPrice = price;
|
|
1058
|
+
break;
|
|
1059
|
+
case MDEntryType2.SimulatedSellPrice:
|
|
1060
|
+
data.simulatedSellPrice = price;
|
|
1061
|
+
break;
|
|
1062
|
+
case MDEntryType2.SimulatedBuyPrice:
|
|
1063
|
+
data.simulatedBuyPrice = price;
|
|
1064
|
+
break;
|
|
1065
|
+
case MDEntryType2.MarginRate:
|
|
1066
|
+
data.marginRate = price;
|
|
1067
|
+
break;
|
|
1068
|
+
case MDEntryType2.MidPrice:
|
|
1069
|
+
data.midPrice = price;
|
|
1070
|
+
break;
|
|
1071
|
+
case MDEntryType2.EmptyBook:
|
|
1072
|
+
data.emptyBook = 1;
|
|
1073
|
+
break;
|
|
1074
|
+
case MDEntryType2.SettleHighPrice:
|
|
1075
|
+
data.settleHighPrice = price;
|
|
1076
|
+
break;
|
|
1077
|
+
case MDEntryType2.SettleLowPrice:
|
|
1078
|
+
data.settleLowPrice = price;
|
|
1079
|
+
break;
|
|
1080
|
+
case MDEntryType2.PriorSettlePrice:
|
|
1081
|
+
data.priorSettlePrice = price;
|
|
1082
|
+
break;
|
|
1083
|
+
case MDEntryType2.SessionHighBid:
|
|
1084
|
+
data.sessionHighBid = price;
|
|
1085
|
+
break;
|
|
1086
|
+
case MDEntryType2.SessionLowOffer:
|
|
1087
|
+
data.sessionLowOffer = price;
|
|
1088
|
+
break;
|
|
1089
|
+
case MDEntryType2.EarlyPrices:
|
|
1090
|
+
data.earlyPrices = price;
|
|
1091
|
+
break;
|
|
1092
|
+
case MDEntryType2.AuctionClearingPrice:
|
|
1093
|
+
data.auctionClearingPrice = price;
|
|
1094
|
+
break;
|
|
1095
|
+
case MDEntryType2.SwapValueFactor:
|
|
1096
|
+
data.swapValueFactor = price;
|
|
1097
|
+
break;
|
|
1098
|
+
case MDEntryType2.DailyValueAdjustmentForLongPositions:
|
|
1099
|
+
data.dailyValueAdjustmentForLongPositions = price;
|
|
1100
|
+
break;
|
|
1101
|
+
case MDEntryType2.CumulativeValueAdjustmentForLongPositions:
|
|
1102
|
+
data.cumulativeValueAdjustmentForLongPositions = price;
|
|
1103
|
+
break;
|
|
1104
|
+
case MDEntryType2.DailyValueAdjustmentForShortPositions:
|
|
1105
|
+
data.dailyValueAdjustmentForShortPositions = price;
|
|
1106
|
+
break;
|
|
1107
|
+
case MDEntryType2.CumulativeValueAdjustmentForShortPositions:
|
|
1108
|
+
data.cumulativeValueAdjustmentForShortPositions = price;
|
|
1109
|
+
break;
|
|
1110
|
+
case MDEntryType2.FixingPrice:
|
|
1111
|
+
data.fixingPrice = price;
|
|
1112
|
+
break;
|
|
1113
|
+
case MDEntryType2.CashRate:
|
|
1114
|
+
data.cashRate = price;
|
|
1115
|
+
break;
|
|
1116
|
+
case MDEntryType2.RecoveryRate:
|
|
1117
|
+
data.recoveryRate = price;
|
|
1118
|
+
break;
|
|
1119
|
+
case MDEntryType2.RecoveryRateForLong:
|
|
1120
|
+
data.recoveryRateForLong = price;
|
|
1121
|
+
break;
|
|
1122
|
+
case MDEntryType2.RecoveryRateForShort:
|
|
1123
|
+
data.recoveryRateForShort = price;
|
|
1124
|
+
break;
|
|
1125
|
+
case MDEntryType2.MarketBid:
|
|
1126
|
+
data.marketBid = price;
|
|
1127
|
+
break;
|
|
1128
|
+
case MDEntryType2.MarketOffer:
|
|
1129
|
+
data.marketOffer = price;
|
|
1130
|
+
break;
|
|
1131
|
+
case MDEntryType2.ShortSaleMinPrice:
|
|
1132
|
+
data.shortSaleMinPrice = price;
|
|
1133
|
+
break;
|
|
1134
|
+
case MDEntryType2.PreviousClosingPrice:
|
|
1135
|
+
data.previousClosingPrice = price;
|
|
1136
|
+
break;
|
|
1137
|
+
case MDEntryType2.ThresholdLimitPriceBanding:
|
|
1138
|
+
data.thresholdLimitPriceBanding = price;
|
|
1139
|
+
break;
|
|
1140
|
+
case MDEntryType2.DailyFinancingValue:
|
|
1141
|
+
data.dailyFinancingValue = price;
|
|
1142
|
+
break;
|
|
1143
|
+
case MDEntryType2.AccruedFinancingValue:
|
|
1144
|
+
data.accruedFinancingValue = price;
|
|
1145
|
+
break;
|
|
1146
|
+
case MDEntryType2.TWAP:
|
|
1147
|
+
data.twap = price;
|
|
1148
|
+
break;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
data.spread = data.offer - data.bid;
|
|
1152
|
+
if (!marketDataPrices.has(symbol)) {
|
|
1153
|
+
parser.logger.log({
|
|
1154
|
+
level: "info",
|
|
1155
|
+
message: `Creating new price history array for symbol: ${symbol}`
|
|
1156
|
+
});
|
|
1157
|
+
marketDataPrices.set(symbol, []);
|
|
1158
|
+
}
|
|
1159
|
+
const prices = marketDataPrices.get(symbol);
|
|
1160
|
+
prices.push(data);
|
|
1161
|
+
parser.logger.log({
|
|
1162
|
+
level: "info",
|
|
1163
|
+
message: `Updated price history for ${symbol}. Current size: ${prices.length}`
|
|
1164
|
+
});
|
|
1165
|
+
if (prices.length > maxPriceHistory) {
|
|
1166
|
+
prices.splice(0, prices.length - maxPriceHistory);
|
|
1167
|
+
parser.logger.log({
|
|
1168
|
+
level: "info",
|
|
1169
|
+
message: `Trimmed price history for ${symbol} to ${maxPriceHistory} entries`
|
|
1170
|
+
});
|
|
1171
|
+
}
|
|
1172
|
+
onPriceUpdate?.(symbol, data);
|
|
1173
|
+
const mdReqID = message.getField(Fields3.MDReqID)?.value;
|
|
1174
|
+
if (mdReqID) {
|
|
1175
|
+
const callback = pendingRequests.get(mdReqID);
|
|
1176
|
+
if (callback) {
|
|
1177
|
+
callback(message);
|
|
1178
|
+
pendingRequests.delete(mdReqID);
|
|
1179
|
+
parser.logger.log({
|
|
1180
|
+
level: "info",
|
|
1181
|
+
message: `Resolved market data request for ID: ${mdReqID}`
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
} else if (msgType === Messages3.ExecutionReport) {
|
|
1186
|
+
const reqId = message.getField(Fields3.ClOrdID)?.value;
|
|
1187
|
+
const callback = pendingRequests.get(reqId);
|
|
1188
|
+
if (callback) {
|
|
1189
|
+
callback(message);
|
|
1190
|
+
pendingRequests.delete(reqId);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
745
1195
|
// src/MCPLocal.ts
|
|
746
|
-
var MCPLocal = class {
|
|
747
|
-
|
|
1196
|
+
var MCPLocal = class extends MCPBase {
|
|
1197
|
+
/**
|
|
1198
|
+
* Map to store verified orders before execution
|
|
1199
|
+
* @private
|
|
1200
|
+
*/
|
|
1201
|
+
verifiedOrders = /* @__PURE__ */ new Map();
|
|
1202
|
+
/**
|
|
1203
|
+
* Map to store pending requests and their callbacks
|
|
1204
|
+
* @private
|
|
1205
|
+
*/
|
|
1206
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
1207
|
+
/**
|
|
1208
|
+
* Map to store market data prices for each symbol
|
|
1209
|
+
* @private
|
|
1210
|
+
*/
|
|
1211
|
+
marketDataPrices = /* @__PURE__ */ new Map();
|
|
1212
|
+
/**
|
|
1213
|
+
* Maximum number of price history entries to keep per symbol
|
|
1214
|
+
* @private
|
|
1215
|
+
*/
|
|
1216
|
+
MAX_PRICE_HISTORY = 1e5;
|
|
748
1217
|
server = new Server(
|
|
749
1218
|
{
|
|
750
1219
|
name: "fixparser",
|
|
@@ -766,77 +1235,13 @@ var MCPLocal = class {
|
|
|
766
1235
|
}
|
|
767
1236
|
);
|
|
768
1237
|
transport = new StdioServerTransport();
|
|
769
|
-
onReady = void 0;
|
|
770
|
-
pendingRequests = /* @__PURE__ */ new Map();
|
|
771
|
-
verifiedOrders = /* @__PURE__ */ new Map();
|
|
772
|
-
marketDataPrices = /* @__PURE__ */ new Map();
|
|
773
|
-
MAX_PRICE_HISTORY = 1e5;
|
|
774
|
-
// Maximum number of price points to store per symbol
|
|
775
1238
|
constructor({ logger, onReady }) {
|
|
776
|
-
|
|
1239
|
+
super({ logger, onReady });
|
|
777
1240
|
}
|
|
778
1241
|
async register(parser) {
|
|
779
1242
|
this.parser = parser;
|
|
780
1243
|
this.parser.addOnMessageCallback((message) => {
|
|
781
|
-
this.parser
|
|
782
|
-
level: "info",
|
|
783
|
-
message: `MCP Server received message: ${message.messageType}: ${message.description}`
|
|
784
|
-
});
|
|
785
|
-
const msgType = message.messageType;
|
|
786
|
-
if (msgType === Messages3.MarketDataSnapshotFullRefresh || msgType === Messages3.ExecutionReport || msgType === Messages3.Reject || msgType === Messages3.MarketDataIncrementalRefresh) {
|
|
787
|
-
this.parser?.logger.log({
|
|
788
|
-
level: "info",
|
|
789
|
-
message: `MCP Server handling message type: ${msgType}`
|
|
790
|
-
});
|
|
791
|
-
let id;
|
|
792
|
-
if (msgType === Messages3.MarketDataIncrementalRefresh || msgType === Messages3.MarketDataSnapshotFullRefresh) {
|
|
793
|
-
const symbol = message.getField(Fields3.Symbol);
|
|
794
|
-
const price = message.getField(Fields3.MDEntryPx);
|
|
795
|
-
const timestamp = message.getField(Fields3.MDEntryTime)?.value || Date.now();
|
|
796
|
-
if (symbol?.value && price?.value) {
|
|
797
|
-
const symbolStr = String(symbol.value);
|
|
798
|
-
const priceNum = Number(price.value);
|
|
799
|
-
const priceHistory = this.marketDataPrices.get(symbolStr) || [];
|
|
800
|
-
priceHistory.push({
|
|
801
|
-
timestamp: Number(timestamp),
|
|
802
|
-
price: priceNum
|
|
803
|
-
});
|
|
804
|
-
if (priceHistory.length > this.MAX_PRICE_HISTORY) {
|
|
805
|
-
priceHistory.shift();
|
|
806
|
-
}
|
|
807
|
-
this.marketDataPrices.set(symbolStr, priceHistory);
|
|
808
|
-
this.parser?.logger.log({
|
|
809
|
-
level: "info",
|
|
810
|
-
message: `MCP Server added ${symbol}: ${priceNum}`
|
|
811
|
-
});
|
|
812
|
-
this.server.notification({
|
|
813
|
-
method: "priceUpdate",
|
|
814
|
-
params: {
|
|
815
|
-
symbol: symbolStr,
|
|
816
|
-
price: priceNum,
|
|
817
|
-
timestamp: Number(timestamp)
|
|
818
|
-
}
|
|
819
|
-
});
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
if (msgType === Messages3.MarketDataSnapshotFullRefresh) {
|
|
823
|
-
const mdReqID = message.getField(Fields3.MDReqID);
|
|
824
|
-
if (mdReqID) id = String(mdReqID.value);
|
|
825
|
-
} else if (msgType === Messages3.ExecutionReport) {
|
|
826
|
-
const clOrdID = message.getField(Fields3.ClOrdID);
|
|
827
|
-
if (clOrdID) id = String(clOrdID.value);
|
|
828
|
-
} else if (msgType === Messages3.Reject) {
|
|
829
|
-
const refSeqNum = message.getField(Fields3.RefSeqNum);
|
|
830
|
-
if (refSeqNum) id = String(refSeqNum.value);
|
|
831
|
-
}
|
|
832
|
-
if (id) {
|
|
833
|
-
const callback = this.pendingRequests.get(id);
|
|
834
|
-
if (callback) {
|
|
835
|
-
callback(message);
|
|
836
|
-
this.pendingRequests.delete(id);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
}
|
|
1244
|
+
handleMessage(message, this.parser, this.pendingRequests, this.marketDataPrices, this.MAX_PRICE_HISTORY);
|
|
840
1245
|
});
|
|
841
1246
|
this.addWorkflows();
|
|
842
1247
|
await this.server.connect(this.transport);
|
|
@@ -851,18 +1256,15 @@ var MCPLocal = class {
|
|
|
851
1256
|
if (!this.server) {
|
|
852
1257
|
return;
|
|
853
1258
|
}
|
|
854
|
-
this.server.setRequestHandler(
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
};
|
|
864
|
-
}
|
|
865
|
-
);
|
|
1259
|
+
this.server.setRequestHandler(z.object({ method: z.literal("tools/list") }), async () => {
|
|
1260
|
+
return {
|
|
1261
|
+
tools: Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
|
|
1262
|
+
name,
|
|
1263
|
+
description,
|
|
1264
|
+
inputSchema: schema
|
|
1265
|
+
}))
|
|
1266
|
+
};
|
|
1267
|
+
});
|
|
866
1268
|
this.server.setRequestHandler(
|
|
867
1269
|
z.object({
|
|
868
1270
|
method: z.literal("tools/call"),
|
|
@@ -874,7 +1276,7 @@ var MCPLocal = class {
|
|
|
874
1276
|
}).optional()
|
|
875
1277
|
})
|
|
876
1278
|
}),
|
|
877
|
-
async (request
|
|
1279
|
+
async (request) => {
|
|
878
1280
|
const { name, arguments: args } = request.params;
|
|
879
1281
|
const toolHandlers = createToolHandlers(
|
|
880
1282
|
this.parser,
|