fixparser-plugin-mcp 9.1.7-38cee007 → 9.1.7-3c6fd297
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 +40 -666
- package/build/cjs/MCPLocal.js.map +4 -4
- package/build/cjs/MCPRemote.js +126 -752
- package/build/cjs/MCPRemote.js.map +4 -4
- package/build/cjs/index.js +127 -753
- package/build/cjs/index.js.map +4 -4
- package/build/esm/MCPLocal.mjs +40 -666
- package/build/esm/MCPLocal.mjs.map +4 -4
- package/build/esm/MCPRemote.mjs +126 -752
- package/build/esm/MCPRemote.mjs.map +4 -4
- package/build/esm/index.mjs +127 -753
- package/build/esm/index.mjs.map +4 -4
- package/build-examples/cjs/example_mcp_local.js +7 -9
- package/build-examples/cjs/example_mcp_local.js.map +4 -4
- package/build-examples/cjs/example_mcp_remote.js +7 -9
- package/build-examples/cjs/example_mcp_remote.js.map +4 -4
- package/build-examples/esm/example_mcp_local.mjs +7 -9
- package/build-examples/esm/example_mcp_local.mjs.map +4 -4
- package/build-examples/esm/example_mcp_remote.mjs +6 -8
- package/build-examples/esm/example_mcp_remote.mjs.map +4 -4
- package/package.json +2 -2
- package/types/MCPBase.d.ts +49 -0
- package/types/MCPLocal.d.ts +40 -0
- package/types/MCPRemote.d.ts +66 -0
- package/types/PluginOptions.d.ts +6 -0
- package/types/index.d.ts +3 -0
- package/types/schemas/index.d.ts +15 -0
- package/types/schemas/schemas.d.ts +168 -0
- package/types/tools/index.d.ts +17 -0
- package/types/tools/marketData.d.ts +40 -0
- package/types/tools/order.d.ts +12 -0
- package/types/tools/parse.d.ts +5 -0
- package/types/tools/parseToJSON.d.ts +5 -0
- package/types/utils/messageHandler.d.ts +18 -0
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. user has to explicitly allow executeOrder.",
|
|
133
133
|
schema: {
|
|
134
134
|
type: "object",
|
|
135
135
|
properties: {
|
|
@@ -273,395 +273,19 @@ var toolSchemas = {
|
|
|
273
273
|
},
|
|
274
274
|
required: ["symbol"]
|
|
275
275
|
}
|
|
276
|
-
},
|
|
277
|
-
technicalAnalysis: {
|
|
278
|
-
description: "Performs comprehensive technical analysis on market data for a given symbol, including indicators like SMA, EMA, RSI, Bollinger Bands, and trading signals",
|
|
279
|
-
schema: {
|
|
280
|
-
type: "object",
|
|
281
|
-
properties: {
|
|
282
|
-
symbol: {
|
|
283
|
-
type: "string",
|
|
284
|
-
description: "The trading symbol to analyze (e.g., AAPL, MSFT, EURUSD)"
|
|
285
|
-
}
|
|
286
|
-
},
|
|
287
|
-
required: ["symbol"]
|
|
288
|
-
}
|
|
289
276
|
}
|
|
290
277
|
};
|
|
291
278
|
|
|
292
|
-
// src/tools/analytics.ts
|
|
293
|
-
function sum(numbers) {
|
|
294
|
-
return numbers.reduce((acc, val) => acc + val, 0);
|
|
295
|
-
}
|
|
296
|
-
var TechnicalAnalyzer = class {
|
|
297
|
-
prices;
|
|
298
|
-
volumes;
|
|
299
|
-
highs;
|
|
300
|
-
lows;
|
|
301
|
-
constructor(data) {
|
|
302
|
-
this.prices = data.map((d) => d.trade > 0 ? d.trade : d.midPrice);
|
|
303
|
-
this.volumes = data.map((d) => d.volume);
|
|
304
|
-
this.highs = data.map((d) => d.tradingSessionHighPrice > 0 ? d.tradingSessionHighPrice : d.trade);
|
|
305
|
-
this.lows = data.map((d) => d.tradingSessionLowPrice > 0 ? d.tradingSessionLowPrice : d.trade);
|
|
306
|
-
}
|
|
307
|
-
// Calculate Simple Moving Average
|
|
308
|
-
calculateSMA(data, period) {
|
|
309
|
-
const sma = [];
|
|
310
|
-
for (let i = period - 1; i < data.length; i++) {
|
|
311
|
-
const sum2 = data.slice(i - period + 1, i + 1).reduce((a, b) => a + b, 0);
|
|
312
|
-
sma.push(sum2 / period);
|
|
313
|
-
}
|
|
314
|
-
return sma;
|
|
315
|
-
}
|
|
316
|
-
// Calculate Exponential Moving Average
|
|
317
|
-
calculateEMA(data, period) {
|
|
318
|
-
const multiplier = 2 / (period + 1);
|
|
319
|
-
const ema = [data[0]];
|
|
320
|
-
for (let i = 1; i < data.length; i++) {
|
|
321
|
-
ema.push(data[i] * multiplier + ema[i - 1] * (1 - multiplier));
|
|
322
|
-
}
|
|
323
|
-
return ema;
|
|
324
|
-
}
|
|
325
|
-
// Calculate RSI
|
|
326
|
-
calculateRSI(data, period = 14) {
|
|
327
|
-
if (data.length < period + 1) return [];
|
|
328
|
-
const changes = [];
|
|
329
|
-
for (let i = 1; i < data.length; i++) {
|
|
330
|
-
changes.push(data[i] - data[i - 1]);
|
|
331
|
-
}
|
|
332
|
-
const gains = changes.map((change) => change > 0 ? change : 0);
|
|
333
|
-
const losses = changes.map((change) => change < 0 ? Math.abs(change) : 0);
|
|
334
|
-
let avgGain = gains.slice(0, period).reduce((a, b) => a + b, 0) / period;
|
|
335
|
-
let avgLoss = losses.slice(0, period).reduce((a, b) => a + b, 0) / period;
|
|
336
|
-
const rsi = [];
|
|
337
|
-
for (let i = period; i < changes.length; i++) {
|
|
338
|
-
const rs = avgGain / avgLoss;
|
|
339
|
-
rsi.push(100 - 100 / (1 + rs));
|
|
340
|
-
avgGain = (avgGain * (period - 1) + gains[i]) / period;
|
|
341
|
-
avgLoss = (avgLoss * (period - 1) + losses[i]) / period;
|
|
342
|
-
}
|
|
343
|
-
return rsi;
|
|
344
|
-
}
|
|
345
|
-
// Calculate Bollinger Bands
|
|
346
|
-
calculateBollingerBands(data, period = 20, stdDev = 2) {
|
|
347
|
-
if (data.length < period) return [];
|
|
348
|
-
const sma = this.calculateSMA(data, period);
|
|
349
|
-
const bands = [];
|
|
350
|
-
for (let i = 0; i < sma.length; i++) {
|
|
351
|
-
const dataSlice = data.slice(i, i + period);
|
|
352
|
-
const mean = sma[i];
|
|
353
|
-
const variance = dataSlice.reduce((sum2, price) => sum2 + (price - mean) ** 2, 0) / period;
|
|
354
|
-
const standardDeviation = Math.sqrt(variance);
|
|
355
|
-
bands.push({
|
|
356
|
-
upper: mean + standardDeviation * stdDev,
|
|
357
|
-
middle: mean,
|
|
358
|
-
lower: mean - standardDeviation * stdDev
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
return bands;
|
|
362
|
-
}
|
|
363
|
-
// Calculate maximum drawdown
|
|
364
|
-
calculateMaxDrawdown(prices) {
|
|
365
|
-
let maxPrice = prices[0];
|
|
366
|
-
let maxDrawdown = 0;
|
|
367
|
-
for (let i = 1; i < prices.length; i++) {
|
|
368
|
-
if (prices[i] > maxPrice) {
|
|
369
|
-
maxPrice = prices[i];
|
|
370
|
-
}
|
|
371
|
-
const drawdown = (maxPrice - prices[i]) / maxPrice;
|
|
372
|
-
if (drawdown > maxDrawdown) {
|
|
373
|
-
maxDrawdown = drawdown;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
return maxDrawdown;
|
|
377
|
-
}
|
|
378
|
-
// Calculate price changes for volatility
|
|
379
|
-
calculatePriceChanges() {
|
|
380
|
-
const changes = [];
|
|
381
|
-
for (let i = 1; i < this.prices.length; i++) {
|
|
382
|
-
changes.push((this.prices[i] - this.prices[i - 1]) / this.prices[i - 1]);
|
|
383
|
-
}
|
|
384
|
-
return changes;
|
|
385
|
-
}
|
|
386
|
-
// Generate comprehensive market analysis
|
|
387
|
-
analyze() {
|
|
388
|
-
const currentPrice = this.prices[this.prices.length - 1];
|
|
389
|
-
const startPrice = this.prices[0];
|
|
390
|
-
const sessionHigh = Math.max(...this.highs);
|
|
391
|
-
const sessionLow = Math.min(...this.lows);
|
|
392
|
-
const totalVolume = sum(this.volumes);
|
|
393
|
-
const avgVolume = totalVolume / this.volumes.length;
|
|
394
|
-
const priceChanges = this.calculatePriceChanges();
|
|
395
|
-
const volatility = priceChanges.length > 0 ? Math.sqrt(
|
|
396
|
-
priceChanges.reduce((sum2, change) => sum2 + change ** 2, 0) / priceChanges.length
|
|
397
|
-
) * Math.sqrt(252) * 100 : 0;
|
|
398
|
-
const sessionReturn = (currentPrice - startPrice) / startPrice * 100;
|
|
399
|
-
const pricePosition = (currentPrice - sessionLow) / (sessionHigh - sessionLow) * 100;
|
|
400
|
-
const trueVWAP = this.prices.reduce((sum2, price, i) => sum2 + price * this.volumes[i], 0) / totalVolume;
|
|
401
|
-
const momentum5 = this.prices.length > 5 ? (currentPrice - this.prices[Math.max(0, this.prices.length - 6)]) / this.prices[Math.max(0, this.prices.length - 6)] * 100 : 0;
|
|
402
|
-
const momentum10 = this.prices.length > 10 ? (currentPrice - this.prices[Math.max(0, this.prices.length - 11)]) / this.prices[Math.max(0, this.prices.length - 11)] * 100 : 0;
|
|
403
|
-
const maxDrawdown = this.calculateMaxDrawdown(this.prices);
|
|
404
|
-
return {
|
|
405
|
-
currentPrice,
|
|
406
|
-
startPrice,
|
|
407
|
-
sessionHigh,
|
|
408
|
-
sessionLow,
|
|
409
|
-
totalVolume,
|
|
410
|
-
avgVolume,
|
|
411
|
-
volatility,
|
|
412
|
-
sessionReturn,
|
|
413
|
-
pricePosition,
|
|
414
|
-
trueVWAP,
|
|
415
|
-
momentum5,
|
|
416
|
-
momentum10,
|
|
417
|
-
maxDrawdown
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
// Generate technical indicators
|
|
421
|
-
getTechnicalIndicators() {
|
|
422
|
-
return {
|
|
423
|
-
sma5: this.calculateSMA(this.prices, 5),
|
|
424
|
-
sma10: this.calculateSMA(this.prices, 10),
|
|
425
|
-
ema8: this.calculateEMA(this.prices, 8),
|
|
426
|
-
ema21: this.calculateEMA(this.prices, 21),
|
|
427
|
-
rsi: this.calculateRSI(this.prices, 14),
|
|
428
|
-
bollinger: this.calculateBollingerBands(this.prices, 20, 2)
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
// Generate trading signals
|
|
432
|
-
generateSignals() {
|
|
433
|
-
const analysis = this.analyze();
|
|
434
|
-
let bullishSignals = 0;
|
|
435
|
-
let bearishSignals = 0;
|
|
436
|
-
const signals = [];
|
|
437
|
-
if (analysis.currentPrice > analysis.trueVWAP) {
|
|
438
|
-
signals.push(
|
|
439
|
-
`\u2713 BULLISH: Price above VWAP (+${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
|
|
440
|
-
);
|
|
441
|
-
bullishSignals++;
|
|
442
|
-
} else {
|
|
443
|
-
signals.push(
|
|
444
|
-
`\u2717 BEARISH: Price below VWAP (${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
|
|
445
|
-
);
|
|
446
|
-
bearishSignals++;
|
|
447
|
-
}
|
|
448
|
-
if (analysis.momentum5 > 0 && analysis.momentum10 > 0) {
|
|
449
|
-
signals.push("\u2713 BULLISH: Positive momentum on both timeframes");
|
|
450
|
-
bullishSignals++;
|
|
451
|
-
} else if (analysis.momentum5 < 0 && analysis.momentum10 < 0) {
|
|
452
|
-
signals.push("\u2717 BEARISH: Negative momentum on both timeframes");
|
|
453
|
-
bearishSignals++;
|
|
454
|
-
} else {
|
|
455
|
-
signals.push("\u25D0 MIXED: Conflicting momentum signals");
|
|
456
|
-
}
|
|
457
|
-
const currentVolume = this.volumes[this.volumes.length - 1];
|
|
458
|
-
const volumeRatio = currentVolume / analysis.avgVolume;
|
|
459
|
-
if (volumeRatio > 1.2 && analysis.sessionReturn > 0) {
|
|
460
|
-
signals.push("\u2713 BULLISH: Above-average volume supporting upward move");
|
|
461
|
-
bullishSignals++;
|
|
462
|
-
} else if (volumeRatio > 1.2 && analysis.sessionReturn < 0) {
|
|
463
|
-
signals.push("\u2717 BEARISH: Above-average volume supporting downward move");
|
|
464
|
-
bearishSignals++;
|
|
465
|
-
} else {
|
|
466
|
-
signals.push("\u25D0 NEUTRAL: Volume not providing clear direction");
|
|
467
|
-
}
|
|
468
|
-
if (analysis.pricePosition > 65 && analysis.volatility > 30) {
|
|
469
|
-
signals.push("\u2717 BEARISH: High in range with elevated volatility - reversal risk");
|
|
470
|
-
bearishSignals++;
|
|
471
|
-
} else if (analysis.pricePosition < 35 && analysis.volatility > 30) {
|
|
472
|
-
signals.push("\u2713 BULLISH: Low in range with volatility - potential bounce");
|
|
473
|
-
bullishSignals++;
|
|
474
|
-
} else {
|
|
475
|
-
signals.push("\u25D0 NEUTRAL: Price position and volatility not extreme");
|
|
476
|
-
}
|
|
477
|
-
return { bullishSignals, bearishSignals, signals };
|
|
478
|
-
}
|
|
479
|
-
// Generate comprehensive JSON analysis
|
|
480
|
-
generateJSONAnalysis(symbol) {
|
|
481
|
-
const analysis = this.analyze();
|
|
482
|
-
const indicators = this.getTechnicalIndicators();
|
|
483
|
-
const signals = this.generateSignals();
|
|
484
|
-
const currentSMA5 = indicators.sma5.length > 0 ? indicators.sma5[indicators.sma5.length - 1] : null;
|
|
485
|
-
const currentSMA10 = indicators.sma10.length > 0 ? indicators.sma10[indicators.sma10.length - 1] : null;
|
|
486
|
-
const currentEMA8 = indicators.ema8[indicators.ema8.length - 1];
|
|
487
|
-
const currentEMA21 = indicators.ema21[indicators.ema21.length - 1];
|
|
488
|
-
const currentRSI = indicators.rsi.length > 0 ? indicators.rsi[indicators.rsi.length - 1] : null;
|
|
489
|
-
const currentBB = indicators.bollinger.length > 0 ? indicators.bollinger[indicators.bollinger.length - 1] : null;
|
|
490
|
-
const currentVolume = this.volumes[this.volumes.length - 1];
|
|
491
|
-
const volumeRatio = currentVolume / analysis.avgVolume;
|
|
492
|
-
const currentDrawdown = (analysis.sessionHigh - analysis.currentPrice) / analysis.sessionHigh * 100;
|
|
493
|
-
const rangeWidth = (analysis.sessionHigh - analysis.sessionLow) / analysis.sessionLow * 100;
|
|
494
|
-
const priceVsVWAP = (analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100;
|
|
495
|
-
const totalScore = signals.bullishSignals - signals.bearishSignals;
|
|
496
|
-
const overallSignal = totalScore > 0 ? "BULLISH_BIAS" : totalScore < 0 ? "BEARISH_BIAS" : "NEUTRAL";
|
|
497
|
-
const targetEntry = Math.max(analysis.sessionLow * 1.005, analysis.trueVWAP * 0.998);
|
|
498
|
-
const stopLoss = analysis.sessionLow * 0.995;
|
|
499
|
-
const profitTarget = analysis.sessionHigh * 0.995;
|
|
500
|
-
const riskRewardRatio = (profitTarget - analysis.currentPrice) / (analysis.currentPrice - stopLoss);
|
|
501
|
-
return {
|
|
502
|
-
symbol,
|
|
503
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
504
|
-
marketStructure: {
|
|
505
|
-
currentPrice: analysis.currentPrice,
|
|
506
|
-
startPrice: analysis.startPrice,
|
|
507
|
-
sessionHigh: analysis.sessionHigh,
|
|
508
|
-
sessionLow: analysis.sessionLow,
|
|
509
|
-
rangeWidth,
|
|
510
|
-
totalVolume: analysis.totalVolume,
|
|
511
|
-
sessionPerformance: analysis.sessionReturn,
|
|
512
|
-
positionInRange: analysis.pricePosition
|
|
513
|
-
},
|
|
514
|
-
volatility: {
|
|
515
|
-
impliedVolatility: analysis.volatility,
|
|
516
|
-
maxDrawdown: analysis.maxDrawdown * 100,
|
|
517
|
-
currentDrawdown
|
|
518
|
-
},
|
|
519
|
-
technicalIndicators: {
|
|
520
|
-
sma5: currentSMA5,
|
|
521
|
-
sma10: currentSMA10,
|
|
522
|
-
ema8: currentEMA8,
|
|
523
|
-
ema21: currentEMA21,
|
|
524
|
-
rsi: currentRSI,
|
|
525
|
-
bollingerBands: currentBB ? {
|
|
526
|
-
upper: currentBB.upper,
|
|
527
|
-
middle: currentBB.middle,
|
|
528
|
-
lower: currentBB.lower,
|
|
529
|
-
position: (analysis.currentPrice - currentBB.lower) / (currentBB.upper - currentBB.lower) * 100
|
|
530
|
-
} : null
|
|
531
|
-
},
|
|
532
|
-
volumeAnalysis: {
|
|
533
|
-
currentVolume,
|
|
534
|
-
averageVolume: Math.round(analysis.avgVolume),
|
|
535
|
-
volumeRatio,
|
|
536
|
-
trueVWAP: analysis.trueVWAP,
|
|
537
|
-
priceVsVWAP
|
|
538
|
-
},
|
|
539
|
-
momentum: {
|
|
540
|
-
momentum5: analysis.momentum5,
|
|
541
|
-
momentum10: analysis.momentum10,
|
|
542
|
-
sessionROC: analysis.sessionReturn
|
|
543
|
-
},
|
|
544
|
-
tradingSignals: {
|
|
545
|
-
...signals,
|
|
546
|
-
overallSignal,
|
|
547
|
-
signalScore: totalScore
|
|
548
|
-
},
|
|
549
|
-
riskManagement: {
|
|
550
|
-
targetEntry,
|
|
551
|
-
stopLoss,
|
|
552
|
-
profitTarget,
|
|
553
|
-
riskRewardRatio
|
|
554
|
-
}
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
};
|
|
558
|
-
var createTechnicalAnalysisHandler = (marketDataPrices) => {
|
|
559
|
-
return async (args) => {
|
|
560
|
-
try {
|
|
561
|
-
const symbol = args.symbol;
|
|
562
|
-
const priceHistory = marketDataPrices.get(symbol) || [];
|
|
563
|
-
if (priceHistory.length === 0) {
|
|
564
|
-
return {
|
|
565
|
-
content: [
|
|
566
|
-
{
|
|
567
|
-
type: "text",
|
|
568
|
-
text: `No price data available for ${symbol}. Please request market data first.`,
|
|
569
|
-
uri: "technicalAnalysis"
|
|
570
|
-
}
|
|
571
|
-
]
|
|
572
|
-
};
|
|
573
|
-
}
|
|
574
|
-
const analyzer = new TechnicalAnalyzer(priceHistory);
|
|
575
|
-
const analysis = analyzer.generateJSONAnalysis(symbol);
|
|
576
|
-
return {
|
|
577
|
-
content: [
|
|
578
|
-
{
|
|
579
|
-
type: "text",
|
|
580
|
-
text: `Technical Analysis for ${symbol}:
|
|
581
|
-
|
|
582
|
-
${JSON.stringify(analysis, null, 2)}`,
|
|
583
|
-
uri: "technicalAnalysis"
|
|
584
|
-
}
|
|
585
|
-
]
|
|
586
|
-
};
|
|
587
|
-
} catch (error) {
|
|
588
|
-
return {
|
|
589
|
-
content: [
|
|
590
|
-
{
|
|
591
|
-
type: "text",
|
|
592
|
-
text: `Error performing technical analysis: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
593
|
-
uri: "technicalAnalysis"
|
|
594
|
-
}
|
|
595
|
-
],
|
|
596
|
-
isError: true
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
};
|
|
600
|
-
};
|
|
601
|
-
|
|
602
279
|
// src/tools/marketData.ts
|
|
603
280
|
import { Field, Fields, MDEntryType, Messages } from "fixparser";
|
|
604
281
|
import QuickChart from "quickchart-js";
|
|
605
282
|
var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
606
283
|
return async (args) => {
|
|
607
284
|
try {
|
|
608
|
-
parser.logger.log({
|
|
609
|
-
level: "info",
|
|
610
|
-
message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
|
|
611
|
-
});
|
|
612
285
|
const response = new Promise((resolve) => {
|
|
613
286
|
pendingRequests.set(args.mdReqID, resolve);
|
|
614
|
-
parser.logger.log({
|
|
615
|
-
level: "info",
|
|
616
|
-
message: `Registered callback for market data request ID: ${args.mdReqID}`
|
|
617
|
-
});
|
|
618
287
|
});
|
|
619
|
-
const entryTypes = args.mdEntryTypes || [
|
|
620
|
-
MDEntryType.Bid,
|
|
621
|
-
MDEntryType.Offer,
|
|
622
|
-
MDEntryType.Trade,
|
|
623
|
-
MDEntryType.IndexValue,
|
|
624
|
-
MDEntryType.OpeningPrice,
|
|
625
|
-
MDEntryType.ClosingPrice,
|
|
626
|
-
MDEntryType.SettlementPrice,
|
|
627
|
-
MDEntryType.TradingSessionHighPrice,
|
|
628
|
-
MDEntryType.TradingSessionLowPrice,
|
|
629
|
-
MDEntryType.VWAP,
|
|
630
|
-
MDEntryType.Imbalance,
|
|
631
|
-
MDEntryType.TradeVolume,
|
|
632
|
-
MDEntryType.OpenInterest,
|
|
633
|
-
MDEntryType.CompositeUnderlyingPrice,
|
|
634
|
-
MDEntryType.SimulatedSellPrice,
|
|
635
|
-
MDEntryType.SimulatedBuyPrice,
|
|
636
|
-
MDEntryType.MarginRate,
|
|
637
|
-
MDEntryType.MidPrice,
|
|
638
|
-
MDEntryType.EmptyBook,
|
|
639
|
-
MDEntryType.SettleHighPrice,
|
|
640
|
-
MDEntryType.SettleLowPrice,
|
|
641
|
-
MDEntryType.PriorSettlePrice,
|
|
642
|
-
MDEntryType.SessionHighBid,
|
|
643
|
-
MDEntryType.SessionLowOffer,
|
|
644
|
-
MDEntryType.EarlyPrices,
|
|
645
|
-
MDEntryType.AuctionClearingPrice,
|
|
646
|
-
MDEntryType.SwapValueFactor,
|
|
647
|
-
MDEntryType.DailyValueAdjustmentForLongPositions,
|
|
648
|
-
MDEntryType.CumulativeValueAdjustmentForLongPositions,
|
|
649
|
-
MDEntryType.DailyValueAdjustmentForShortPositions,
|
|
650
|
-
MDEntryType.CumulativeValueAdjustmentForShortPositions,
|
|
651
|
-
MDEntryType.FixingPrice,
|
|
652
|
-
MDEntryType.CashRate,
|
|
653
|
-
MDEntryType.RecoveryRate,
|
|
654
|
-
MDEntryType.RecoveryRateForLong,
|
|
655
|
-
MDEntryType.RecoveryRateForShort,
|
|
656
|
-
MDEntryType.MarketBid,
|
|
657
|
-
MDEntryType.MarketOffer,
|
|
658
|
-
MDEntryType.ShortSaleMinPrice,
|
|
659
|
-
MDEntryType.PreviousClosingPrice,
|
|
660
|
-
MDEntryType.ThresholdLimitPriceBanding,
|
|
661
|
-
MDEntryType.DailyFinancingValue,
|
|
662
|
-
MDEntryType.AccruedFinancingValue,
|
|
663
|
-
MDEntryType.TWAP
|
|
664
|
-
];
|
|
288
|
+
const entryTypes = args.mdEntryTypes || [MDEntryType.Bid, MDEntryType.Offer, MDEntryType.TradeVolume];
|
|
665
289
|
const messageFields = [
|
|
666
290
|
new Field(Fields.MsgType, Messages.MarketDataRequest),
|
|
667
291
|
new Field(Fields.SenderCompID, parser.sender),
|
|
@@ -683,10 +307,6 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
|
683
307
|
});
|
|
684
308
|
const mdr = parser.createMessage(...messageFields);
|
|
685
309
|
if (!parser.connected) {
|
|
686
|
-
parser.logger.log({
|
|
687
|
-
level: "error",
|
|
688
|
-
message: "Not connected. Cannot send market data request."
|
|
689
|
-
});
|
|
690
310
|
return {
|
|
691
311
|
content: [
|
|
692
312
|
{
|
|
@@ -698,16 +318,8 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
|
|
|
698
318
|
isError: true
|
|
699
319
|
};
|
|
700
320
|
}
|
|
701
|
-
parser.logger.log({
|
|
702
|
-
level: "info",
|
|
703
|
-
message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
|
|
704
|
-
});
|
|
705
321
|
parser.send(mdr);
|
|
706
322
|
const fixData = await response;
|
|
707
|
-
parser.logger.log({
|
|
708
|
-
level: "info",
|
|
709
|
-
message: `Received market data response for request ID: ${args.mdReqID}`
|
|
710
|
-
});
|
|
711
323
|
return {
|
|
712
324
|
content: [
|
|
713
325
|
{
|
|
@@ -756,9 +368,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
756
368
|
const offerData = priceHistory.map((point) => point.offer);
|
|
757
369
|
const spreadData = priceHistory.map((point) => point.spread);
|
|
758
370
|
const volumeData = priceHistory.map((point) => point.volume);
|
|
759
|
-
const tradeData = priceHistory.map((point) => point.trade);
|
|
760
|
-
const vwapData = priceHistory.map((point) => point.vwap);
|
|
761
|
-
const twapData = priceHistory.map((point) => point.twap);
|
|
762
371
|
const config = {
|
|
763
372
|
type: "line",
|
|
764
373
|
data: {
|
|
@@ -788,30 +397,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
788
397
|
fill: false,
|
|
789
398
|
tension: 0.4
|
|
790
399
|
},
|
|
791
|
-
{
|
|
792
|
-
label: "Trade",
|
|
793
|
-
data: tradeData,
|
|
794
|
-
borderColor: "#ffc107",
|
|
795
|
-
backgroundColor: "rgba(255, 193, 7, 0.1)",
|
|
796
|
-
fill: false,
|
|
797
|
-
tension: 0.4
|
|
798
|
-
},
|
|
799
|
-
{
|
|
800
|
-
label: "VWAP",
|
|
801
|
-
data: vwapData,
|
|
802
|
-
borderColor: "#17a2b8",
|
|
803
|
-
backgroundColor: "rgba(23, 162, 184, 0.1)",
|
|
804
|
-
fill: false,
|
|
805
|
-
tension: 0.4
|
|
806
|
-
},
|
|
807
|
-
{
|
|
808
|
-
label: "TWAP",
|
|
809
|
-
data: twapData,
|
|
810
|
-
borderColor: "#6610f2",
|
|
811
|
-
backgroundColor: "rgba(102, 16, 242, 0.1)",
|
|
812
|
-
fill: false,
|
|
813
|
-
tension: 0.4
|
|
814
|
-
},
|
|
815
400
|
{
|
|
816
401
|
label: "Volume",
|
|
817
402
|
data: volumeData,
|
|
@@ -857,7 +442,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
|
|
|
857
442
|
content: [
|
|
858
443
|
{
|
|
859
444
|
type: "text",
|
|
860
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to generate
|
|
445
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
|
|
861
446
|
uri: "getStockGraph"
|
|
862
447
|
}
|
|
863
448
|
],
|
|
@@ -895,48 +480,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
|
|
|
895
480
|
bid: point.bid,
|
|
896
481
|
offer: point.offer,
|
|
897
482
|
spread: point.spread,
|
|
898
|
-
volume: point.volume
|
|
899
|
-
trade: point.trade,
|
|
900
|
-
indexValue: point.indexValue,
|
|
901
|
-
openingPrice: point.openingPrice,
|
|
902
|
-
closingPrice: point.closingPrice,
|
|
903
|
-
settlementPrice: point.settlementPrice,
|
|
904
|
-
tradingSessionHighPrice: point.tradingSessionHighPrice,
|
|
905
|
-
tradingSessionLowPrice: point.tradingSessionLowPrice,
|
|
906
|
-
vwap: point.vwap,
|
|
907
|
-
imbalance: point.imbalance,
|
|
908
|
-
openInterest: point.openInterest,
|
|
909
|
-
compositeUnderlyingPrice: point.compositeUnderlyingPrice,
|
|
910
|
-
simulatedSellPrice: point.simulatedSellPrice,
|
|
911
|
-
simulatedBuyPrice: point.simulatedBuyPrice,
|
|
912
|
-
marginRate: point.marginRate,
|
|
913
|
-
midPrice: point.midPrice,
|
|
914
|
-
emptyBook: point.emptyBook,
|
|
915
|
-
settleHighPrice: point.settleHighPrice,
|
|
916
|
-
settleLowPrice: point.settleLowPrice,
|
|
917
|
-
priorSettlePrice: point.priorSettlePrice,
|
|
918
|
-
sessionHighBid: point.sessionHighBid,
|
|
919
|
-
sessionLowOffer: point.sessionLowOffer,
|
|
920
|
-
earlyPrices: point.earlyPrices,
|
|
921
|
-
auctionClearingPrice: point.auctionClearingPrice,
|
|
922
|
-
swapValueFactor: point.swapValueFactor,
|
|
923
|
-
dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
|
|
924
|
-
cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
|
|
925
|
-
dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
|
|
926
|
-
cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
|
|
927
|
-
fixingPrice: point.fixingPrice,
|
|
928
|
-
cashRate: point.cashRate,
|
|
929
|
-
recoveryRate: point.recoveryRate,
|
|
930
|
-
recoveryRateForLong: point.recoveryRateForLong,
|
|
931
|
-
recoveryRateForShort: point.recoveryRateForShort,
|
|
932
|
-
marketBid: point.marketBid,
|
|
933
|
-
marketOffer: point.marketOffer,
|
|
934
|
-
shortSaleMinPrice: point.shortSaleMinPrice,
|
|
935
|
-
previousClosingPrice: point.previousClosingPrice,
|
|
936
|
-
thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
|
|
937
|
-
dailyFinancingValue: point.dailyFinancingValue,
|
|
938
|
-
accruedFinancingValue: point.accruedFinancingValue,
|
|
939
|
-
twap: point.twap
|
|
483
|
+
volume: point.volume
|
|
940
484
|
}))
|
|
941
485
|
},
|
|
942
486
|
null,
|
|
@@ -951,7 +495,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
|
|
|
951
495
|
content: [
|
|
952
496
|
{
|
|
953
497
|
type: "text",
|
|
954
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
|
|
498
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
|
|
955
499
|
uri: "getStockPriceHistory"
|
|
956
500
|
}
|
|
957
501
|
],
|
|
@@ -1059,7 +603,7 @@ Parameters verified:
|
|
|
1059
603
|
- Symbol: ${args.symbol}
|
|
1060
604
|
- TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
|
|
1061
605
|
|
|
1062
|
-
To execute this order, call the executeOrder tool with these exact same parameters
|
|
606
|
+
To execute this order, call the executeOrder tool with these exact same parameters.`,
|
|
1063
607
|
uri: "verifyOrder"
|
|
1064
608
|
}
|
|
1065
609
|
]
|
|
@@ -1255,210 +799,48 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
|
|
|
1255
799
|
executeOrder: createExecuteOrderHandler(parser, verifiedOrders, pendingRequests),
|
|
1256
800
|
marketDataRequest: createMarketDataRequestHandler(parser, pendingRequests),
|
|
1257
801
|
getStockGraph: createGetStockGraphHandler(marketDataPrices),
|
|
1258
|
-
getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
|
|
1259
|
-
technicalAnalysis: createTechnicalAnalysisHandler(marketDataPrices)
|
|
802
|
+
getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
|
|
1260
803
|
});
|
|
1261
804
|
|
|
1262
805
|
// src/utils/messageHandler.ts
|
|
1263
806
|
import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
|
|
1264
|
-
function getEnumValue(enumObj, name) {
|
|
1265
|
-
return enumObj[name] || name;
|
|
1266
|
-
}
|
|
1267
807
|
function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
|
|
808
|
+
parser.logger.log({
|
|
809
|
+
level: "info",
|
|
810
|
+
message: `MCP Server received message: ${message.messageType}: ${message.description}`
|
|
811
|
+
});
|
|
1268
812
|
const msgType = message.messageType;
|
|
1269
|
-
if (msgType === Messages3.MarketDataSnapshotFullRefresh
|
|
813
|
+
if (msgType === Messages3.MarketDataSnapshotFullRefresh) {
|
|
1270
814
|
const symbol = message.getField(Fields3.Symbol)?.value;
|
|
1271
|
-
const
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
compositeUnderlyingPrice: 0,
|
|
1290
|
-
simulatedSellPrice: 0,
|
|
1291
|
-
simulatedBuyPrice: 0,
|
|
1292
|
-
marginRate: 0,
|
|
1293
|
-
midPrice: 0,
|
|
1294
|
-
emptyBook: 0,
|
|
1295
|
-
settleHighPrice: 0,
|
|
1296
|
-
settleLowPrice: 0,
|
|
1297
|
-
priorSettlePrice: 0,
|
|
1298
|
-
sessionHighBid: 0,
|
|
1299
|
-
sessionLowOffer: 0,
|
|
1300
|
-
earlyPrices: 0,
|
|
1301
|
-
auctionClearingPrice: 0,
|
|
1302
|
-
swapValueFactor: 0,
|
|
1303
|
-
dailyValueAdjustmentForLongPositions: 0,
|
|
1304
|
-
cumulativeValueAdjustmentForLongPositions: 0,
|
|
1305
|
-
dailyValueAdjustmentForShortPositions: 0,
|
|
1306
|
-
cumulativeValueAdjustmentForShortPositions: 0,
|
|
1307
|
-
fixingPrice: 0,
|
|
1308
|
-
cashRate: 0,
|
|
1309
|
-
recoveryRate: 0,
|
|
1310
|
-
recoveryRateForLong: 0,
|
|
1311
|
-
recoveryRateForShort: 0,
|
|
1312
|
-
marketBid: 0,
|
|
1313
|
-
marketOffer: 0,
|
|
1314
|
-
shortSaleMinPrice: 0,
|
|
1315
|
-
previousClosingPrice: 0,
|
|
1316
|
-
thresholdLimitPriceBanding: 0,
|
|
1317
|
-
dailyFinancingValue: 0,
|
|
1318
|
-
accruedFinancingValue: 0,
|
|
1319
|
-
twap: 0
|
|
1320
|
-
};
|
|
1321
|
-
for (const entry of entries) {
|
|
1322
|
-
const entryType = entry.MDEntryType;
|
|
1323
|
-
const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
|
|
1324
|
-
const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
|
|
1325
|
-
const enumValue = getEnumValue(MDEntryType2, entryType);
|
|
1326
|
-
switch (enumValue) {
|
|
1327
|
-
case MDEntryType2.Bid:
|
|
1328
|
-
data.bid = price;
|
|
1329
|
-
break;
|
|
1330
|
-
case MDEntryType2.Offer:
|
|
1331
|
-
data.offer = price;
|
|
1332
|
-
break;
|
|
1333
|
-
case MDEntryType2.Trade:
|
|
1334
|
-
data.trade = price;
|
|
1335
|
-
break;
|
|
1336
|
-
case MDEntryType2.IndexValue:
|
|
1337
|
-
data.indexValue = price;
|
|
1338
|
-
break;
|
|
1339
|
-
case MDEntryType2.OpeningPrice:
|
|
1340
|
-
data.openingPrice = price;
|
|
1341
|
-
break;
|
|
1342
|
-
case MDEntryType2.ClosingPrice:
|
|
1343
|
-
data.closingPrice = price;
|
|
1344
|
-
break;
|
|
1345
|
-
case MDEntryType2.SettlementPrice:
|
|
1346
|
-
data.settlementPrice = price;
|
|
1347
|
-
break;
|
|
1348
|
-
case MDEntryType2.TradingSessionHighPrice:
|
|
1349
|
-
data.tradingSessionHighPrice = price;
|
|
1350
|
-
break;
|
|
1351
|
-
case MDEntryType2.TradingSessionLowPrice:
|
|
1352
|
-
data.tradingSessionLowPrice = price;
|
|
1353
|
-
break;
|
|
1354
|
-
case MDEntryType2.VWAP:
|
|
1355
|
-
data.vwap = price;
|
|
1356
|
-
break;
|
|
1357
|
-
case MDEntryType2.Imbalance:
|
|
1358
|
-
data.imbalance = size;
|
|
1359
|
-
break;
|
|
1360
|
-
case MDEntryType2.TradeVolume:
|
|
1361
|
-
data.volume = size;
|
|
1362
|
-
break;
|
|
1363
|
-
case MDEntryType2.OpenInterest:
|
|
1364
|
-
data.openInterest = size;
|
|
1365
|
-
break;
|
|
1366
|
-
case MDEntryType2.CompositeUnderlyingPrice:
|
|
1367
|
-
data.compositeUnderlyingPrice = price;
|
|
1368
|
-
break;
|
|
1369
|
-
case MDEntryType2.SimulatedSellPrice:
|
|
1370
|
-
data.simulatedSellPrice = price;
|
|
1371
|
-
break;
|
|
1372
|
-
case MDEntryType2.SimulatedBuyPrice:
|
|
1373
|
-
data.simulatedBuyPrice = price;
|
|
1374
|
-
break;
|
|
1375
|
-
case MDEntryType2.MarginRate:
|
|
1376
|
-
data.marginRate = price;
|
|
1377
|
-
break;
|
|
1378
|
-
case MDEntryType2.MidPrice:
|
|
1379
|
-
data.midPrice = price;
|
|
1380
|
-
break;
|
|
1381
|
-
case MDEntryType2.EmptyBook:
|
|
1382
|
-
data.emptyBook = 1;
|
|
1383
|
-
break;
|
|
1384
|
-
case MDEntryType2.SettleHighPrice:
|
|
1385
|
-
data.settleHighPrice = price;
|
|
1386
|
-
break;
|
|
1387
|
-
case MDEntryType2.SettleLowPrice:
|
|
1388
|
-
data.settleLowPrice = price;
|
|
1389
|
-
break;
|
|
1390
|
-
case MDEntryType2.PriorSettlePrice:
|
|
1391
|
-
data.priorSettlePrice = price;
|
|
1392
|
-
break;
|
|
1393
|
-
case MDEntryType2.SessionHighBid:
|
|
1394
|
-
data.sessionHighBid = price;
|
|
1395
|
-
break;
|
|
1396
|
-
case MDEntryType2.SessionLowOffer:
|
|
1397
|
-
data.sessionLowOffer = price;
|
|
1398
|
-
break;
|
|
1399
|
-
case MDEntryType2.EarlyPrices:
|
|
1400
|
-
data.earlyPrices = price;
|
|
1401
|
-
break;
|
|
1402
|
-
case MDEntryType2.AuctionClearingPrice:
|
|
1403
|
-
data.auctionClearingPrice = price;
|
|
1404
|
-
break;
|
|
1405
|
-
case MDEntryType2.SwapValueFactor:
|
|
1406
|
-
data.swapValueFactor = price;
|
|
1407
|
-
break;
|
|
1408
|
-
case MDEntryType2.DailyValueAdjustmentForLongPositions:
|
|
1409
|
-
data.dailyValueAdjustmentForLongPositions = price;
|
|
1410
|
-
break;
|
|
1411
|
-
case MDEntryType2.CumulativeValueAdjustmentForLongPositions:
|
|
1412
|
-
data.cumulativeValueAdjustmentForLongPositions = price;
|
|
1413
|
-
break;
|
|
1414
|
-
case MDEntryType2.DailyValueAdjustmentForShortPositions:
|
|
1415
|
-
data.dailyValueAdjustmentForShortPositions = price;
|
|
1416
|
-
break;
|
|
1417
|
-
case MDEntryType2.CumulativeValueAdjustmentForShortPositions:
|
|
1418
|
-
data.cumulativeValueAdjustmentForShortPositions = price;
|
|
1419
|
-
break;
|
|
1420
|
-
case MDEntryType2.FixingPrice:
|
|
1421
|
-
data.fixingPrice = price;
|
|
1422
|
-
break;
|
|
1423
|
-
case MDEntryType2.CashRate:
|
|
1424
|
-
data.cashRate = price;
|
|
1425
|
-
break;
|
|
1426
|
-
case MDEntryType2.RecoveryRate:
|
|
1427
|
-
data.recoveryRate = price;
|
|
1428
|
-
break;
|
|
1429
|
-
case MDEntryType2.RecoveryRateForLong:
|
|
1430
|
-
data.recoveryRateForLong = price;
|
|
1431
|
-
break;
|
|
1432
|
-
case MDEntryType2.RecoveryRateForShort:
|
|
1433
|
-
data.recoveryRateForShort = price;
|
|
1434
|
-
break;
|
|
1435
|
-
case MDEntryType2.MarketBid:
|
|
1436
|
-
data.marketBid = price;
|
|
1437
|
-
break;
|
|
1438
|
-
case MDEntryType2.MarketOffer:
|
|
1439
|
-
data.marketOffer = price;
|
|
1440
|
-
break;
|
|
1441
|
-
case MDEntryType2.ShortSaleMinPrice:
|
|
1442
|
-
data.shortSaleMinPrice = price;
|
|
1443
|
-
break;
|
|
1444
|
-
case MDEntryType2.PreviousClosingPrice:
|
|
1445
|
-
data.previousClosingPrice = price;
|
|
1446
|
-
break;
|
|
1447
|
-
case MDEntryType2.ThresholdLimitPriceBanding:
|
|
1448
|
-
data.thresholdLimitPriceBanding = price;
|
|
1449
|
-
break;
|
|
1450
|
-
case MDEntryType2.DailyFinancingValue:
|
|
1451
|
-
data.dailyFinancingValue = price;
|
|
1452
|
-
break;
|
|
1453
|
-
case MDEntryType2.AccruedFinancingValue:
|
|
1454
|
-
data.accruedFinancingValue = price;
|
|
1455
|
-
break;
|
|
1456
|
-
case MDEntryType2.TWAP:
|
|
1457
|
-
data.twap = price;
|
|
1458
|
-
break;
|
|
815
|
+
const entries = message.getField(Fields3.NoMDEntries)?.value;
|
|
816
|
+
let bid = 0;
|
|
817
|
+
let offer = 0;
|
|
818
|
+
let volume = 0;
|
|
819
|
+
const entryTypes = message.getFields(Fields3.MDEntryType);
|
|
820
|
+
const entryPrices = message.getFields(Fields3.MDEntryPx);
|
|
821
|
+
const entrySizes = message.getFields(Fields3.MDEntrySize);
|
|
822
|
+
if (entryTypes && entryPrices && entrySizes) {
|
|
823
|
+
for (let i = 0; i < entries; i++) {
|
|
824
|
+
const entryType = entryTypes[i]?.value;
|
|
825
|
+
const entryPrice = Number.parseFloat(entryPrices[i]?.value);
|
|
826
|
+
const entrySize = Number.parseFloat(entrySizes[i]?.value);
|
|
827
|
+
if (entryType === MDEntryType2.Bid) {
|
|
828
|
+
bid = entryPrice;
|
|
829
|
+
} else if (entryType === MDEntryType2.Offer) {
|
|
830
|
+
offer = entryPrice;
|
|
831
|
+
}
|
|
832
|
+
volume += entrySize;
|
|
1459
833
|
}
|
|
1460
834
|
}
|
|
1461
|
-
|
|
835
|
+
const spread = offer - bid;
|
|
836
|
+
const timestamp = Date.now();
|
|
837
|
+
const data = {
|
|
838
|
+
timestamp,
|
|
839
|
+
bid,
|
|
840
|
+
offer,
|
|
841
|
+
spread,
|
|
842
|
+
volume
|
|
843
|
+
};
|
|
1462
844
|
if (!marketDataPrices.has(symbol)) {
|
|
1463
845
|
marketDataPrices.set(symbol, []);
|
|
1464
846
|
}
|
|
@@ -1468,14 +850,6 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
|
|
|
1468
850
|
prices.splice(0, prices.length - maxPriceHistory);
|
|
1469
851
|
}
|
|
1470
852
|
onPriceUpdate?.(symbol, data);
|
|
1471
|
-
const mdReqID = message.getField(Fields3.MDReqID)?.value;
|
|
1472
|
-
if (mdReqID) {
|
|
1473
|
-
const callback = pendingRequests.get(mdReqID);
|
|
1474
|
-
if (callback) {
|
|
1475
|
-
callback(message);
|
|
1476
|
-
pendingRequests.delete(mdReqID);
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
853
|
} else if (msgType === Messages3.ExecutionReport) {
|
|
1480
854
|
const reqId = message.getField(Fields3.ClOrdID)?.value;
|
|
1481
855
|
const callback = pendingRequests.get(reqId);
|
|
@@ -1504,7 +878,7 @@ var MCPLocal = class extends MCPBase {
|
|
|
1504
878
|
*/
|
|
1505
879
|
marketDataPrices = /* @__PURE__ */ new Map();
|
|
1506
880
|
/**
|
|
1507
|
-
* Maximum number of price
|
|
881
|
+
* Maximum number of price points to store per symbol
|
|
1508
882
|
* @private
|
|
1509
883
|
*/
|
|
1510
884
|
MAX_PRICE_HISTORY = 1e5;
|
|
@@ -1613,39 +987,6 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
|
|
|
1613
987
|
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
1614
988
|
import { z as z2 } from "zod";
|
|
1615
989
|
var transports = {};
|
|
1616
|
-
function jsonSchemaToZod(schema) {
|
|
1617
|
-
if (schema.type === "object") {
|
|
1618
|
-
const shape = {};
|
|
1619
|
-
for (const [key, prop] of Object.entries(schema.properties || {})) {
|
|
1620
|
-
const propSchema = prop;
|
|
1621
|
-
if (propSchema.type === "string") {
|
|
1622
|
-
if (propSchema.enum) {
|
|
1623
|
-
shape[key] = z2.enum(propSchema.enum);
|
|
1624
|
-
} else {
|
|
1625
|
-
shape[key] = z2.string();
|
|
1626
|
-
}
|
|
1627
|
-
} else if (propSchema.type === "number") {
|
|
1628
|
-
shape[key] = z2.number();
|
|
1629
|
-
} else if (propSchema.type === "boolean") {
|
|
1630
|
-
shape[key] = z2.boolean();
|
|
1631
|
-
} else if (propSchema.type === "array") {
|
|
1632
|
-
if (propSchema.items.type === "string") {
|
|
1633
|
-
shape[key] = z2.array(z2.string());
|
|
1634
|
-
} else if (propSchema.items.type === "number") {
|
|
1635
|
-
shape[key] = z2.array(z2.number());
|
|
1636
|
-
} else if (propSchema.items.type === "boolean") {
|
|
1637
|
-
shape[key] = z2.array(z2.boolean());
|
|
1638
|
-
} else {
|
|
1639
|
-
shape[key] = z2.array(z2.any());
|
|
1640
|
-
}
|
|
1641
|
-
} else {
|
|
1642
|
-
shape[key] = z2.any();
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
return shape;
|
|
1646
|
-
}
|
|
1647
|
-
return {};
|
|
1648
|
-
}
|
|
1649
990
|
var MCPRemote = class extends MCPBase {
|
|
1650
991
|
/**
|
|
1651
992
|
* Port number the server will listen on.
|
|
@@ -1688,7 +1029,7 @@ var MCPRemote = class extends MCPBase {
|
|
|
1688
1029
|
*/
|
|
1689
1030
|
marketDataPrices = /* @__PURE__ */ new Map();
|
|
1690
1031
|
/**
|
|
1691
|
-
* Maximum number of price
|
|
1032
|
+
* Maximum number of price points to store per symbol
|
|
1692
1033
|
* @private
|
|
1693
1034
|
*/
|
|
1694
1035
|
MAX_PRICE_HISTORY = 1e5;
|
|
@@ -1710,7 +1051,31 @@ var MCPRemote = class extends MCPBase {
|
|
|
1710
1051
|
this.parser,
|
|
1711
1052
|
this.pendingRequests,
|
|
1712
1053
|
this.marketDataPrices,
|
|
1713
|
-
this.MAX_PRICE_HISTORY
|
|
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
|
+
}
|
|
1714
1079
|
);
|
|
1715
1080
|
}
|
|
1716
1081
|
});
|
|
@@ -1772,15 +1137,7 @@ var MCPRemote = class extends MCPBase {
|
|
|
1772
1137
|
);
|
|
1773
1138
|
return;
|
|
1774
1139
|
}
|
|
1775
|
-
|
|
1776
|
-
await transport.handleRequest(req, res, parsed);
|
|
1777
|
-
} catch (error) {
|
|
1778
|
-
this.logger?.log({
|
|
1779
|
-
level: "error",
|
|
1780
|
-
message: `Error handling request: ${error}`
|
|
1781
|
-
});
|
|
1782
|
-
throw error;
|
|
1783
|
-
}
|
|
1140
|
+
await transport.handleRequest(req, res, parsed);
|
|
1784
1141
|
});
|
|
1785
1142
|
} else if (req.method === "GET" || req.method === "DELETE") {
|
|
1786
1143
|
if (!sessionId || !transports[sessionId]) {
|
|
@@ -1789,20 +1146,8 @@ var MCPRemote = class extends MCPBase {
|
|
|
1789
1146
|
return;
|
|
1790
1147
|
}
|
|
1791
1148
|
const transport = transports[sessionId];
|
|
1792
|
-
|
|
1793
|
-
await transport.handleRequest(req, res);
|
|
1794
|
-
} catch (error) {
|
|
1795
|
-
this.logger?.log({
|
|
1796
|
-
level: "error",
|
|
1797
|
-
message: `Error handling ${req.method} request: ${error}`
|
|
1798
|
-
});
|
|
1799
|
-
throw error;
|
|
1800
|
-
}
|
|
1149
|
+
await transport.handleRequest(req, res);
|
|
1801
1150
|
} else {
|
|
1802
|
-
this.logger?.log({
|
|
1803
|
-
level: "error",
|
|
1804
|
-
message: `Method not allowed: ${req.method}`
|
|
1805
|
-
});
|
|
1806
1151
|
res.writeHead(405);
|
|
1807
1152
|
res.end("Method Not Allowed");
|
|
1808
1153
|
}
|
|
@@ -1836,40 +1181,69 @@ var MCPRemote = class extends MCPBase {
|
|
|
1836
1181
|
});
|
|
1837
1182
|
return;
|
|
1838
1183
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1184
|
+
this.mcpServer.tool(
|
|
1185
|
+
"tools/list",
|
|
1186
|
+
{
|
|
1187
|
+
description: "List available tools",
|
|
1188
|
+
schema: z2.object({})
|
|
1189
|
+
},
|
|
1190
|
+
async () => {
|
|
1191
|
+
return {
|
|
1192
|
+
content: [
|
|
1193
|
+
{
|
|
1194
|
+
type: "text",
|
|
1195
|
+
text: JSON.stringify(
|
|
1196
|
+
Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
|
|
1197
|
+
name,
|
|
1198
|
+
description,
|
|
1199
|
+
inputSchema: schema
|
|
1200
|
+
}))
|
|
1201
|
+
)
|
|
1202
|
+
}
|
|
1203
|
+
]
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1844
1206
|
);
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1207
|
+
this.mcpServer.tool(
|
|
1208
|
+
"tools/call",
|
|
1209
|
+
{
|
|
1210
|
+
description: "Call a tool",
|
|
1211
|
+
schema: z2.object({
|
|
1212
|
+
name: z2.string(),
|
|
1213
|
+
arguments: z2.any(),
|
|
1214
|
+
_meta: z2.object({
|
|
1215
|
+
progressToken: z2.number()
|
|
1216
|
+
}).optional()
|
|
1217
|
+
})
|
|
1218
|
+
},
|
|
1219
|
+
async (request) => {
|
|
1220
|
+
const { name, arguments: args } = request;
|
|
1221
|
+
const toolHandlers = createToolHandlers(
|
|
1222
|
+
this.parser,
|
|
1223
|
+
this.verifiedOrders,
|
|
1224
|
+
this.pendingRequests,
|
|
1225
|
+
this.marketDataPrices
|
|
1226
|
+
);
|
|
1227
|
+
const handler = toolHandlers[name];
|
|
1228
|
+
if (!handler) {
|
|
1866
1229
|
return {
|
|
1867
|
-
content:
|
|
1868
|
-
|
|
1230
|
+
content: [
|
|
1231
|
+
{
|
|
1232
|
+
type: "text",
|
|
1233
|
+
text: `Tool not found: ${name}`,
|
|
1234
|
+
uri: name
|
|
1235
|
+
}
|
|
1236
|
+
],
|
|
1237
|
+
isError: true
|
|
1869
1238
|
};
|
|
1870
1239
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
1240
|
+
const result = await handler(args);
|
|
1241
|
+
return {
|
|
1242
|
+
content: result.content,
|
|
1243
|
+
isError: result.isError
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
);
|
|
1873
1247
|
}
|
|
1874
1248
|
};
|
|
1875
1249
|
export {
|