fixparser-plugin-mcp 9.1.7-3f807208 → 9.1.7-400318ef
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 +402 -660
- package/build/cjs/MCPLocal.js.map +2 -2
- package/build/esm/MCPLocal.mjs +402 -660
- package/build/esm/MCPLocal.mjs.map +2 -2
- package/build-examples/cjs/example_mcp_local.js +21 -21
- package/build-examples/cjs/example_mcp_local.js.map +3 -3
- package/build-examples/esm/example_mcp_local.mjs +20 -20
- package/build-examples/esm/example_mcp_local.mjs.map +3 -3
- package/package.json +2 -2
package/build/cjs/MCPLocal.js
CHANGED
|
@@ -176,9 +176,16 @@ var MCPLocal = class {
|
|
|
176
176
|
},
|
|
177
177
|
required: ["mdUpdateType", "symbols", "mdReqID", "subscriptionRequestType", "mdEntryTypes"]
|
|
178
178
|
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
resources: {
|
|
182
|
+
greeting: {
|
|
183
|
+
description: "A simple greeting resource",
|
|
184
|
+
uri: "greeting-resource"
|
|
179
185
|
},
|
|
180
|
-
|
|
186
|
+
stockGraph: {
|
|
181
187
|
description: "Generates a price chart for a given symbol",
|
|
188
|
+
uri: "stockGraph",
|
|
182
189
|
parameters: {
|
|
183
190
|
type: "object",
|
|
184
191
|
properties: {
|
|
@@ -187,8 +194,9 @@ var MCPLocal = class {
|
|
|
187
194
|
required: ["symbol"]
|
|
188
195
|
}
|
|
189
196
|
},
|
|
190
|
-
|
|
197
|
+
stockPriceHistory: {
|
|
191
198
|
description: "Returns price history for a given symbol",
|
|
199
|
+
uri: "stockPriceHistory",
|
|
192
200
|
parameters: {
|
|
193
201
|
type: "object",
|
|
194
202
|
properties: {
|
|
@@ -197,20 +205,6 @@ var MCPLocal = class {
|
|
|
197
205
|
required: ["symbol"]
|
|
198
206
|
}
|
|
199
207
|
}
|
|
200
|
-
},
|
|
201
|
-
resources: {
|
|
202
|
-
greeting: {
|
|
203
|
-
description: "A simple greeting resource",
|
|
204
|
-
uri: "greeting-resource"
|
|
205
|
-
},
|
|
206
|
-
stockGraph: {
|
|
207
|
-
description: "Generates a price chart for a given symbol",
|
|
208
|
-
uri: "stockGraph/{symbol}"
|
|
209
|
-
},
|
|
210
|
-
stockPriceHistory: {
|
|
211
|
-
description: "Returns price history for a given symbol",
|
|
212
|
-
uri: "stockPriceHistory/{symbol}"
|
|
213
|
-
}
|
|
214
208
|
}
|
|
215
209
|
}
|
|
216
210
|
}
|
|
@@ -260,14 +254,6 @@ var MCPLocal = class {
|
|
|
260
254
|
level: "info",
|
|
261
255
|
message: `MCP Server added ${symbol}: ${priceNum}`
|
|
262
256
|
});
|
|
263
|
-
this.server.notification({
|
|
264
|
-
method: "priceUpdate",
|
|
265
|
-
params: {
|
|
266
|
-
symbol: symbolStr,
|
|
267
|
-
price: priceNum,
|
|
268
|
-
timestamp: Number(timestamp)
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
257
|
}
|
|
272
258
|
}
|
|
273
259
|
if (msgType === import_fixparser.Messages.MarketDataSnapshotFullRefresh) {
|
|
@@ -302,385 +288,158 @@ var MCPLocal = class {
|
|
|
302
288
|
if (!this.server) {
|
|
303
289
|
return;
|
|
304
290
|
}
|
|
305
|
-
this.server.setRequestHandler(
|
|
306
|
-
|
|
307
|
-
|
|
291
|
+
this.server.setRequestHandler(import_zod.z.object({ method: import_zod.z.literal("parse") }), async (request, extra) => {
|
|
292
|
+
try {
|
|
293
|
+
const args = request.params;
|
|
294
|
+
const parsedMessage = this.parser?.parse(args.fixString);
|
|
295
|
+
if (!parsedMessage || parsedMessage.length === 0) {
|
|
296
|
+
return {
|
|
297
|
+
content: [{ type: "text", text: "Error: Failed to parse FIX string" }],
|
|
298
|
+
isError: true
|
|
299
|
+
};
|
|
300
|
+
}
|
|
308
301
|
return {
|
|
309
|
-
|
|
302
|
+
content: [
|
|
310
303
|
{
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
304
|
+
type: "text",
|
|
305
|
+
text: `${parsedMessage[0].description}
|
|
306
|
+
${parsedMessage[0].messageTypeDescription}`
|
|
314
307
|
}
|
|
315
308
|
]
|
|
316
309
|
};
|
|
317
|
-
}
|
|
318
|
-
);
|
|
319
|
-
this.server.setRequestHandler(
|
|
320
|
-
import_zod.z.object({ method: import_zod.z.literal("resources/templates/list") }),
|
|
321
|
-
async (request, extra) => {
|
|
310
|
+
} catch (error) {
|
|
322
311
|
return {
|
|
323
|
-
|
|
324
|
-
{
|
|
325
|
-
name: "stockGraph",
|
|
326
|
-
description: "Generates a price chart for a given symbol",
|
|
327
|
-
uriTemplate: "stockGraph/{symbol}",
|
|
328
|
-
parameters: {
|
|
329
|
-
type: "object",
|
|
330
|
-
properties: {
|
|
331
|
-
symbol: { type: "string" }
|
|
332
|
-
},
|
|
333
|
-
required: ["symbol"]
|
|
334
|
-
}
|
|
335
|
-
},
|
|
312
|
+
content: [
|
|
336
313
|
{
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
uriTemplate: "stockPriceHistory/{symbol}",
|
|
340
|
-
parameters: {
|
|
341
|
-
type: "object",
|
|
342
|
-
properties: {
|
|
343
|
-
symbol: { type: "string" }
|
|
344
|
-
},
|
|
345
|
-
required: ["symbol"]
|
|
346
|
-
}
|
|
314
|
+
type: "text",
|
|
315
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to parse FIX string"}`
|
|
347
316
|
}
|
|
348
|
-
]
|
|
317
|
+
],
|
|
318
|
+
isError: true
|
|
349
319
|
};
|
|
350
320
|
}
|
|
351
|
-
);
|
|
321
|
+
});
|
|
352
322
|
this.server.setRequestHandler(
|
|
353
|
-
import_zod.z.object({ method: import_zod.z.literal("
|
|
323
|
+
import_zod.z.object({ method: import_zod.z.literal("parseToJSON") }),
|
|
354
324
|
async (request, extra) => {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
name: "parseToJSON",
|
|
370
|
-
description: "Parses a FIX message into JSON",
|
|
371
|
-
inputSchema: {
|
|
372
|
-
type: "object",
|
|
373
|
-
properties: {
|
|
374
|
-
fixString: { type: "string" }
|
|
375
|
-
},
|
|
376
|
-
required: ["fixString"]
|
|
377
|
-
}
|
|
378
|
-
},
|
|
379
|
-
{
|
|
380
|
-
name: "verifyOrder",
|
|
381
|
-
description: "Verifies order parameters before execution",
|
|
382
|
-
inputSchema: {
|
|
383
|
-
type: "object",
|
|
384
|
-
properties: {
|
|
385
|
-
clOrdID: { type: "string" },
|
|
386
|
-
handlInst: { type: "string", enum: ["1", "2", "3"] },
|
|
387
|
-
quantity: { type: "string" },
|
|
388
|
-
price: { type: "string" },
|
|
389
|
-
ordType: {
|
|
390
|
-
type: "string",
|
|
391
|
-
enum: [
|
|
392
|
-
"1",
|
|
393
|
-
"2",
|
|
394
|
-
"3",
|
|
395
|
-
"4",
|
|
396
|
-
"5",
|
|
397
|
-
"6",
|
|
398
|
-
"7",
|
|
399
|
-
"8",
|
|
400
|
-
"9",
|
|
401
|
-
"A",
|
|
402
|
-
"B",
|
|
403
|
-
"C",
|
|
404
|
-
"D",
|
|
405
|
-
"E",
|
|
406
|
-
"F",
|
|
407
|
-
"G",
|
|
408
|
-
"H",
|
|
409
|
-
"I",
|
|
410
|
-
"J",
|
|
411
|
-
"K",
|
|
412
|
-
"L",
|
|
413
|
-
"M",
|
|
414
|
-
"P",
|
|
415
|
-
"Q",
|
|
416
|
-
"R",
|
|
417
|
-
"S"
|
|
418
|
-
]
|
|
419
|
-
},
|
|
420
|
-
side: {
|
|
421
|
-
type: "string",
|
|
422
|
-
enum: [
|
|
423
|
-
"1",
|
|
424
|
-
"2",
|
|
425
|
-
"3",
|
|
426
|
-
"4",
|
|
427
|
-
"5",
|
|
428
|
-
"6",
|
|
429
|
-
"7",
|
|
430
|
-
"8",
|
|
431
|
-
"9",
|
|
432
|
-
"A",
|
|
433
|
-
"B",
|
|
434
|
-
"C",
|
|
435
|
-
"D",
|
|
436
|
-
"E",
|
|
437
|
-
"F",
|
|
438
|
-
"G",
|
|
439
|
-
"H"
|
|
440
|
-
]
|
|
441
|
-
},
|
|
442
|
-
symbol: { type: "string" },
|
|
443
|
-
timeInForce: {
|
|
444
|
-
type: "string",
|
|
445
|
-
enum: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C"]
|
|
446
|
-
}
|
|
447
|
-
},
|
|
448
|
-
required: [
|
|
449
|
-
"clOrdID",
|
|
450
|
-
"handlInst",
|
|
451
|
-
"quantity",
|
|
452
|
-
"price",
|
|
453
|
-
"ordType",
|
|
454
|
-
"side",
|
|
455
|
-
"symbol",
|
|
456
|
-
"timeInForce"
|
|
457
|
-
]
|
|
458
|
-
}
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
name: "executeOrder",
|
|
462
|
-
description: "Executes a verified order",
|
|
463
|
-
inputSchema: {
|
|
464
|
-
type: "object",
|
|
465
|
-
properties: {
|
|
466
|
-
clOrdID: { type: "string" },
|
|
467
|
-
handlInst: { type: "string", enum: ["1", "2", "3"] },
|
|
468
|
-
quantity: { type: "string" },
|
|
469
|
-
price: { type: "string" },
|
|
470
|
-
ordType: { type: "string" },
|
|
471
|
-
side: { type: "string" },
|
|
472
|
-
symbol: { type: "string" },
|
|
473
|
-
timeInForce: { type: "string" }
|
|
474
|
-
},
|
|
475
|
-
required: [
|
|
476
|
-
"clOrdID",
|
|
477
|
-
"handlInst",
|
|
478
|
-
"quantity",
|
|
479
|
-
"price",
|
|
480
|
-
"ordType",
|
|
481
|
-
"side",
|
|
482
|
-
"symbol",
|
|
483
|
-
"timeInForce"
|
|
484
|
-
]
|
|
325
|
+
try {
|
|
326
|
+
const args = request.params;
|
|
327
|
+
const parsedMessage = this.parser?.parse(args.fixString);
|
|
328
|
+
if (!parsedMessage || parsedMessage.length === 0) {
|
|
329
|
+
return {
|
|
330
|
+
content: [{ type: "text", text: "Error: Failed to parse FIX string" }],
|
|
331
|
+
isError: true
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
content: [
|
|
336
|
+
{
|
|
337
|
+
type: "text",
|
|
338
|
+
text: `${parsedMessage[0].toFIXJSON()}`
|
|
485
339
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
symbols: { type: "array", items: { type: "string" } },
|
|
495
|
-
mdReqID: { type: "string" },
|
|
496
|
-
subscriptionRequestType: { type: "string", enum: ["0", "1", "2"] },
|
|
497
|
-
mdEntryTypes: { type: "array", items: { type: "string" } }
|
|
498
|
-
},
|
|
499
|
-
required: [
|
|
500
|
-
"mdUpdateType",
|
|
501
|
-
"symbols",
|
|
502
|
-
"mdReqID",
|
|
503
|
-
"subscriptionRequestType",
|
|
504
|
-
"mdEntryTypes"
|
|
505
|
-
]
|
|
340
|
+
]
|
|
341
|
+
};
|
|
342
|
+
} catch (error) {
|
|
343
|
+
return {
|
|
344
|
+
content: [
|
|
345
|
+
{
|
|
346
|
+
type: "text",
|
|
347
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to parse FIX string"}`
|
|
506
348
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
349
|
+
],
|
|
350
|
+
isError: true
|
|
351
|
+
};
|
|
352
|
+
}
|
|
510
353
|
}
|
|
511
354
|
);
|
|
512
355
|
this.server.setRequestHandler(
|
|
513
|
-
import_zod.z.object({
|
|
514
|
-
method: import_zod.z.literal("tools/call"),
|
|
515
|
-
params: import_zod.z.object({
|
|
516
|
-
name: import_zod.z.string(),
|
|
517
|
-
arguments: import_zod.z.any(),
|
|
518
|
-
_meta: import_zod.z.object({
|
|
519
|
-
progressToken: import_zod.z.number()
|
|
520
|
-
}).optional()
|
|
521
|
-
})
|
|
522
|
-
}),
|
|
356
|
+
import_zod.z.object({ method: import_zod.z.literal("verifyOrder") }),
|
|
523
357
|
async (request, extra) => {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
timeInForce: args.timeInForce
|
|
610
|
-
});
|
|
611
|
-
const ordTypeNames = {
|
|
612
|
-
"1": "Market",
|
|
613
|
-
"2": "Limit",
|
|
614
|
-
"3": "Stop",
|
|
615
|
-
"4": "StopLimit",
|
|
616
|
-
"5": "MarketOnClose",
|
|
617
|
-
"6": "WithOrWithout",
|
|
618
|
-
"7": "LimitOrBetter",
|
|
619
|
-
"8": "LimitWithOrWithout",
|
|
620
|
-
"9": "OnBasis",
|
|
621
|
-
A: "OnClose",
|
|
622
|
-
B: "LimitOnClose",
|
|
623
|
-
C: "ForexMarket",
|
|
624
|
-
D: "PreviouslyQuoted",
|
|
625
|
-
E: "PreviouslyIndicated",
|
|
626
|
-
F: "ForexLimit",
|
|
627
|
-
G: "ForexSwap",
|
|
628
|
-
H: "ForexPreviouslyQuoted",
|
|
629
|
-
I: "Funari",
|
|
630
|
-
J: "MarketIfTouched",
|
|
631
|
-
K: "MarketWithLeftOverAsLimit",
|
|
632
|
-
L: "PreviousFundValuationPoint",
|
|
633
|
-
M: "NextFundValuationPoint",
|
|
634
|
-
P: "Pegged",
|
|
635
|
-
Q: "CounterOrderSelection",
|
|
636
|
-
R: "StopOnBidOrOffer",
|
|
637
|
-
S: "StopLimitOnBidOrOffer"
|
|
638
|
-
};
|
|
639
|
-
const sideNames = {
|
|
640
|
-
"1": "Buy",
|
|
641
|
-
"2": "Sell",
|
|
642
|
-
"3": "BuyMinus",
|
|
643
|
-
"4": "SellPlus",
|
|
644
|
-
"5": "SellShort",
|
|
645
|
-
"6": "SellShortExempt",
|
|
646
|
-
"7": "Undisclosed",
|
|
647
|
-
"8": "Cross",
|
|
648
|
-
"9": "CrossShort",
|
|
649
|
-
A: "CrossShortExempt",
|
|
650
|
-
B: "AsDefined",
|
|
651
|
-
C: "Opposite",
|
|
652
|
-
D: "Subscribe",
|
|
653
|
-
E: "Redeem",
|
|
654
|
-
F: "Lend",
|
|
655
|
-
G: "Borrow",
|
|
656
|
-
H: "SellUndisclosed"
|
|
657
|
-
};
|
|
658
|
-
const timeInForceNames = {
|
|
659
|
-
"0": "Day",
|
|
660
|
-
"1": "GoodTillCancel",
|
|
661
|
-
"2": "AtTheOpening",
|
|
662
|
-
"3": "ImmediateOrCancel",
|
|
663
|
-
"4": "FillOrKill",
|
|
664
|
-
"5": "GoodTillCrossing",
|
|
665
|
-
"6": "GoodTillDate",
|
|
666
|
-
"7": "AtTheClose",
|
|
667
|
-
"8": "GoodThroughCrossing",
|
|
668
|
-
"9": "AtCrossing",
|
|
669
|
-
A: "GoodForTime",
|
|
670
|
-
B: "GoodForAuction",
|
|
671
|
-
C: "GoodForMonth"
|
|
672
|
-
};
|
|
673
|
-
const handlInstNames = {
|
|
674
|
-
"1": "AutomatedExecutionNoIntervention",
|
|
675
|
-
"2": "AutomatedExecutionInterventionOK",
|
|
676
|
-
"3": "ManualOrder"
|
|
677
|
-
};
|
|
678
|
-
return {
|
|
679
|
-
contents: [
|
|
680
|
-
{
|
|
681
|
-
type: "text",
|
|
682
|
-
text: `VERIFICATION: All parameters valid. Ready to proceed with order execution.
|
|
683
|
-
|
|
358
|
+
try {
|
|
359
|
+
const args = request.params;
|
|
360
|
+
this.verifiedOrders.set(args.clOrdID, {
|
|
361
|
+
clOrdID: args.clOrdID,
|
|
362
|
+
handlInst: args.handlInst,
|
|
363
|
+
quantity: Number.parseFloat(args.quantity),
|
|
364
|
+
price: Number.parseFloat(args.price),
|
|
365
|
+
ordType: args.ordType,
|
|
366
|
+
side: args.side,
|
|
367
|
+
symbol: args.symbol,
|
|
368
|
+
timeInForce: args.timeInForce
|
|
369
|
+
});
|
|
370
|
+
const ordTypeNames = {
|
|
371
|
+
"1": "Market",
|
|
372
|
+
"2": "Limit",
|
|
373
|
+
"3": "Stop",
|
|
374
|
+
"4": "StopLimit",
|
|
375
|
+
"5": "MarketOnClose",
|
|
376
|
+
"6": "WithOrWithout",
|
|
377
|
+
"7": "LimitOrBetter",
|
|
378
|
+
"8": "LimitWithOrWithout",
|
|
379
|
+
"9": "OnBasis",
|
|
380
|
+
A: "OnClose",
|
|
381
|
+
B: "LimitOnClose",
|
|
382
|
+
C: "ForexMarket",
|
|
383
|
+
D: "PreviouslyQuoted",
|
|
384
|
+
E: "PreviouslyIndicated",
|
|
385
|
+
F: "ForexLimit",
|
|
386
|
+
G: "ForexSwap",
|
|
387
|
+
H: "ForexPreviouslyQuoted",
|
|
388
|
+
I: "Funari",
|
|
389
|
+
J: "MarketIfTouched",
|
|
390
|
+
K: "MarketWithLeftOverAsLimit",
|
|
391
|
+
L: "PreviousFundValuationPoint",
|
|
392
|
+
M: "NextFundValuationPoint",
|
|
393
|
+
P: "Pegged",
|
|
394
|
+
Q: "CounterOrderSelection",
|
|
395
|
+
R: "StopOnBidOrOffer",
|
|
396
|
+
S: "StopLimitOnBidOrOffer"
|
|
397
|
+
};
|
|
398
|
+
const sideNames = {
|
|
399
|
+
"1": "Buy",
|
|
400
|
+
"2": "Sell",
|
|
401
|
+
"3": "BuyMinus",
|
|
402
|
+
"4": "SellPlus",
|
|
403
|
+
"5": "SellShort",
|
|
404
|
+
"6": "SellShortExempt",
|
|
405
|
+
"7": "Undisclosed",
|
|
406
|
+
"8": "Cross",
|
|
407
|
+
"9": "CrossShort",
|
|
408
|
+
A: "CrossShortExempt",
|
|
409
|
+
B: "AsDefined",
|
|
410
|
+
C: "Opposite",
|
|
411
|
+
D: "Subscribe",
|
|
412
|
+
E: "Redeem",
|
|
413
|
+
F: "Lend",
|
|
414
|
+
G: "Borrow",
|
|
415
|
+
H: "SellUndisclosed"
|
|
416
|
+
};
|
|
417
|
+
const timeInForceNames = {
|
|
418
|
+
"0": "Day",
|
|
419
|
+
"1": "GoodTillCancel",
|
|
420
|
+
"2": "AtTheOpening",
|
|
421
|
+
"3": "ImmediateOrCancel",
|
|
422
|
+
"4": "FillOrKill",
|
|
423
|
+
"5": "GoodTillCrossing",
|
|
424
|
+
"6": "GoodTillDate",
|
|
425
|
+
"7": "AtTheClose",
|
|
426
|
+
"8": "GoodThroughCrossing",
|
|
427
|
+
"9": "AtCrossing",
|
|
428
|
+
A: "GoodForTime",
|
|
429
|
+
B: "GoodForAuction",
|
|
430
|
+
C: "GoodForMonth"
|
|
431
|
+
};
|
|
432
|
+
const handlInstNames = {
|
|
433
|
+
"1": "AutomatedExecutionNoIntervention",
|
|
434
|
+
"2": "AutomatedExecutionInterventionOK",
|
|
435
|
+
"3": "ManualOrder"
|
|
436
|
+
};
|
|
437
|
+
return {
|
|
438
|
+
content: [
|
|
439
|
+
{
|
|
440
|
+
type: "text",
|
|
441
|
+
text: `VERIFICATION: All parameters valid. Ready to proceed with order execution.
|
|
442
|
+
|
|
684
443
|
Parameters verified:
|
|
685
444
|
- ClOrdID: ${args.clOrdID}
|
|
686
445
|
- HandlInst: ${args.handlInst} (${handlInstNames[args.handlInst]})
|
|
@@ -691,193 +450,217 @@ Parameters verified:
|
|
|
691
450
|
- Symbol: ${args.symbol}
|
|
692
451
|
- TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
|
|
693
452
|
|
|
694
|
-
To execute this order, call the executeOrder tool with these exact same parameters
|
|
695
|
-
uri: "verifyOrder"
|
|
696
|
-
}
|
|
697
|
-
]
|
|
698
|
-
};
|
|
699
|
-
} catch (error) {
|
|
700
|
-
return {
|
|
701
|
-
contents: [
|
|
702
|
-
{
|
|
703
|
-
type: "text",
|
|
704
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to verify order parameters"}`,
|
|
705
|
-
uri: "verifyOrder"
|
|
706
|
-
}
|
|
707
|
-
],
|
|
708
|
-
isError: true
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
case "executeOrder":
|
|
712
|
-
try {
|
|
713
|
-
const verifiedOrder = this.verifiedOrders.get(args.clOrdID);
|
|
714
|
-
if (!verifiedOrder) {
|
|
715
|
-
return {
|
|
716
|
-
contents: [
|
|
717
|
-
{
|
|
718
|
-
type: "text",
|
|
719
|
-
text: `Error: Order ${args.clOrdID} has not been verified. Please call verifyOrder first.`,
|
|
720
|
-
uri: "executeOrder"
|
|
721
|
-
}
|
|
722
|
-
],
|
|
723
|
-
isError: true
|
|
724
|
-
};
|
|
453
|
+
To execute this order, call the executeOrder tool with these exact same parameters.`
|
|
725
454
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
],
|
|
735
|
-
isError: true
|
|
736
|
-
};
|
|
455
|
+
]
|
|
456
|
+
};
|
|
457
|
+
} catch (error) {
|
|
458
|
+
return {
|
|
459
|
+
content: [
|
|
460
|
+
{
|
|
461
|
+
type: "text",
|
|
462
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to verify order parameters"}`
|
|
737
463
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
}
|
|
464
|
+
],
|
|
465
|
+
isError: true
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
);
|
|
470
|
+
this.server.setRequestHandler(
|
|
471
|
+
import_zod.z.object({ method: import_zod.z.literal("executeOrder") }),
|
|
472
|
+
async (request, extra) => {
|
|
473
|
+
try {
|
|
474
|
+
const args = request.params;
|
|
475
|
+
const verifiedOrder = this.verifiedOrders.get(args.clOrdID);
|
|
476
|
+
if (!verifiedOrder) {
|
|
477
|
+
return {
|
|
478
|
+
content: [
|
|
479
|
+
{
|
|
480
|
+
type: "text",
|
|
481
|
+
text: `Error: Order ${args.clOrdID} has not been verified. Please call verifyOrder first.`
|
|
482
|
+
}
|
|
483
|
+
],
|
|
484
|
+
isError: true
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
if (verifiedOrder.handlInst !== args.handlInst || verifiedOrder.quantity !== Number.parseFloat(args.quantity) || verifiedOrder.price !== Number.parseFloat(args.price) || verifiedOrder.ordType !== args.ordType || verifiedOrder.side !== args.side || verifiedOrder.symbol !== args.symbol || verifiedOrder.timeInForce !== args.timeInForce) {
|
|
488
|
+
return {
|
|
489
|
+
content: [
|
|
490
|
+
{
|
|
491
|
+
type: "text",
|
|
492
|
+
text: "Error: Order parameters do not match the verified order. Please use the exact same parameters that were verified."
|
|
493
|
+
}
|
|
494
|
+
],
|
|
495
|
+
isError: true
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
const response = new Promise((resolve) => {
|
|
499
|
+
this.pendingRequests.set(args.clOrdID, resolve);
|
|
500
|
+
});
|
|
501
|
+
const order = this.parser?.createMessage(
|
|
502
|
+
new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.NewOrderSingle),
|
|
503
|
+
new import_fixparser.Field(import_fixparser.Fields.MsgSeqNum, this.parser?.getNextTargetMsgSeqNum()),
|
|
504
|
+
new import_fixparser.Field(import_fixparser.Fields.SenderCompID, this.parser?.sender),
|
|
505
|
+
new import_fixparser.Field(import_fixparser.Fields.TargetCompID, this.parser?.target),
|
|
506
|
+
new import_fixparser.Field(import_fixparser.Fields.SendingTime, this.parser?.getTimestamp()),
|
|
507
|
+
new import_fixparser.Field(import_fixparser.Fields.ClOrdID, args.clOrdID),
|
|
508
|
+
new import_fixparser.Field(import_fixparser.Fields.Side, args.side),
|
|
509
|
+
new import_fixparser.Field(import_fixparser.Fields.Symbol, args.symbol),
|
|
510
|
+
new import_fixparser.Field(import_fixparser.Fields.OrderQty, Number.parseFloat(args.quantity)),
|
|
511
|
+
new import_fixparser.Field(import_fixparser.Fields.Price, Number.parseFloat(args.price)),
|
|
512
|
+
new import_fixparser.Field(import_fixparser.Fields.OrdType, args.ordType),
|
|
513
|
+
new import_fixparser.Field(import_fixparser.Fields.HandlInst, args.handlInst),
|
|
514
|
+
new import_fixparser.Field(import_fixparser.Fields.TimeInForce, args.timeInForce),
|
|
515
|
+
new import_fixparser.Field(import_fixparser.Fields.TransactTime, this.parser?.getTimestamp())
|
|
516
|
+
);
|
|
517
|
+
if (!this.parser?.connected) {
|
|
518
|
+
return {
|
|
519
|
+
content: [
|
|
520
|
+
{
|
|
521
|
+
type: "text",
|
|
522
|
+
text: "Error: Not connected. Ignoring message."
|
|
523
|
+
}
|
|
524
|
+
],
|
|
525
|
+
isError: true
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
this.parser?.send(order);
|
|
529
|
+
const fixData = await response;
|
|
530
|
+
this.verifiedOrders.delete(args.clOrdID);
|
|
531
|
+
return {
|
|
532
|
+
content: [
|
|
533
|
+
{
|
|
534
|
+
type: "text",
|
|
535
|
+
text: fixData.messageType === import_fixparser.Messages.Reject ? `Reject message for order ${args.clOrdID}: ${JSON.stringify(fixData.toFIXJSON())}` : `Execution Report for order ${args.clOrdID}: ${JSON.stringify(fixData.toFIXJSON())}`
|
|
768
536
|
}
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
uri: "executeOrder"
|
|
778
|
-
}
|
|
779
|
-
]
|
|
780
|
-
};
|
|
781
|
-
} catch (error) {
|
|
782
|
-
return {
|
|
783
|
-
contents: [
|
|
784
|
-
{
|
|
785
|
-
type: "text",
|
|
786
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to execute order"}`,
|
|
787
|
-
uri: "executeOrder"
|
|
788
|
-
}
|
|
789
|
-
],
|
|
790
|
-
isError: true
|
|
791
|
-
};
|
|
792
|
-
}
|
|
793
|
-
case "marketDataRequest":
|
|
794
|
-
try {
|
|
795
|
-
const response = new Promise((resolve) => {
|
|
796
|
-
this.pendingRequests.set(args.mdReqID, resolve);
|
|
797
|
-
});
|
|
798
|
-
const messageFields = [
|
|
799
|
-
new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.MarketDataRequest),
|
|
800
|
-
new import_fixparser.Field(import_fixparser.Fields.SenderCompID, this.parser?.sender),
|
|
801
|
-
new import_fixparser.Field(import_fixparser.Fields.MsgSeqNum, this.parser?.getNextTargetMsgSeqNum()),
|
|
802
|
-
new import_fixparser.Field(import_fixparser.Fields.TargetCompID, this.parser?.target),
|
|
803
|
-
new import_fixparser.Field(import_fixparser.Fields.SendingTime, this.parser?.getTimestamp()),
|
|
804
|
-
new import_fixparser.Field(import_fixparser.Fields.MDReqID, args.mdReqID),
|
|
805
|
-
new import_fixparser.Field(import_fixparser.Fields.SubscriptionRequestType, args.subscriptionRequestType),
|
|
806
|
-
new import_fixparser.Field(import_fixparser.Fields.MarketDepth, 0),
|
|
807
|
-
new import_fixparser.Field(import_fixparser.Fields.MDUpdateType, args.mdUpdateType)
|
|
808
|
-
];
|
|
809
|
-
messageFields.push(new import_fixparser.Field(import_fixparser.Fields.NoRelatedSym, args.symbols.length));
|
|
810
|
-
args.symbols.forEach((symbol) => {
|
|
811
|
-
messageFields.push(new import_fixparser.Field(import_fixparser.Fields.Symbol, symbol));
|
|
812
|
-
});
|
|
813
|
-
messageFields.push(new import_fixparser.Field(import_fixparser.Fields.NoMDEntryTypes, args.mdEntryTypes.length));
|
|
814
|
-
args.mdEntryTypes.forEach((entryType) => {
|
|
815
|
-
messageFields.push(new import_fixparser.Field(import_fixparser.Fields.MDEntryType, entryType));
|
|
816
|
-
});
|
|
817
|
-
const mdr = this.parser?.createMessage(...messageFields);
|
|
818
|
-
if (!this.parser?.connected) {
|
|
819
|
-
return {
|
|
820
|
-
contents: [
|
|
821
|
-
{
|
|
822
|
-
type: "text",
|
|
823
|
-
text: "Error: Not connected. Ignoring message.",
|
|
824
|
-
uri: "marketDataRequest"
|
|
825
|
-
}
|
|
826
|
-
],
|
|
827
|
-
isError: true
|
|
828
|
-
};
|
|
537
|
+
]
|
|
538
|
+
};
|
|
539
|
+
} catch (error) {
|
|
540
|
+
return {
|
|
541
|
+
content: [
|
|
542
|
+
{
|
|
543
|
+
type: "text",
|
|
544
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to execute order"}`
|
|
829
545
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
546
|
+
],
|
|
547
|
+
isError: true
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
);
|
|
552
|
+
this.server.setRequestHandler(
|
|
553
|
+
import_zod.z.object({ method: import_zod.z.literal("marketDataRequest") }),
|
|
554
|
+
async (request, extra) => {
|
|
555
|
+
try {
|
|
556
|
+
const args = request.params;
|
|
557
|
+
const response = new Promise((resolve) => {
|
|
558
|
+
this.pendingRequests.set(args.mdReqID, resolve);
|
|
559
|
+
});
|
|
560
|
+
const messageFields = [
|
|
561
|
+
new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.MarketDataRequest),
|
|
562
|
+
new import_fixparser.Field(import_fixparser.Fields.SenderCompID, this.parser?.sender),
|
|
563
|
+
new import_fixparser.Field(import_fixparser.Fields.MsgSeqNum, this.parser?.getNextTargetMsgSeqNum()),
|
|
564
|
+
new import_fixparser.Field(import_fixparser.Fields.TargetCompID, this.parser?.target),
|
|
565
|
+
new import_fixparser.Field(import_fixparser.Fields.SendingTime, this.parser?.getTimestamp()),
|
|
566
|
+
new import_fixparser.Field(import_fixparser.Fields.MDReqID, args.mdReqID),
|
|
567
|
+
new import_fixparser.Field(import_fixparser.Fields.SubscriptionRequestType, args.subscriptionRequestType),
|
|
568
|
+
new import_fixparser.Field(import_fixparser.Fields.MarketDepth, 0),
|
|
569
|
+
new import_fixparser.Field(import_fixparser.Fields.MDUpdateType, args.mdUpdateType)
|
|
570
|
+
];
|
|
571
|
+
messageFields.push(new import_fixparser.Field(import_fixparser.Fields.NoRelatedSym, args.symbols.length));
|
|
572
|
+
args.symbols.forEach((symbol) => {
|
|
573
|
+
messageFields.push(new import_fixparser.Field(import_fixparser.Fields.Symbol, symbol));
|
|
574
|
+
});
|
|
575
|
+
messageFields.push(new import_fixparser.Field(import_fixparser.Fields.NoMDEntryTypes, args.mdEntryTypes.length));
|
|
576
|
+
args.mdEntryTypes.forEach((entryType) => {
|
|
577
|
+
messageFields.push(new import_fixparser.Field(import_fixparser.Fields.MDEntryType, entryType));
|
|
578
|
+
});
|
|
579
|
+
const mdr = this.parser?.createMessage(...messageFields);
|
|
580
|
+
if (!this.parser?.connected) {
|
|
581
|
+
return {
|
|
582
|
+
content: [
|
|
583
|
+
{
|
|
584
|
+
type: "text",
|
|
585
|
+
text: "Error: Not connected. Ignoring message."
|
|
586
|
+
}
|
|
587
|
+
],
|
|
588
|
+
isError: true
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
this.parser?.send(mdr);
|
|
592
|
+
const fixData = await response;
|
|
593
|
+
return {
|
|
594
|
+
content: [
|
|
595
|
+
{
|
|
596
|
+
type: "text",
|
|
597
|
+
text: `Market data for ${args.symbols.join(", ")}: ${JSON.stringify(fixData.toFIXJSON())}`
|
|
598
|
+
}
|
|
599
|
+
]
|
|
600
|
+
};
|
|
601
|
+
} catch (error) {
|
|
602
|
+
return {
|
|
603
|
+
content: [
|
|
604
|
+
{
|
|
605
|
+
type: "text",
|
|
606
|
+
text: `Error: ${error instanceof Error ? error.message : "Failed to request market data"}`
|
|
607
|
+
}
|
|
608
|
+
],
|
|
609
|
+
isError: true
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
);
|
|
614
|
+
this.server.setRequestHandler(
|
|
615
|
+
import_zod.z.object({ method: import_zod.z.literal("greeting-resource") }),
|
|
616
|
+
async (request, extra) => {
|
|
617
|
+
this.parser?.logger.log({
|
|
618
|
+
level: "info",
|
|
619
|
+
message: "MCP Server Resource called: greeting-resource"
|
|
620
|
+
});
|
|
621
|
+
return {
|
|
622
|
+
content: [
|
|
623
|
+
{
|
|
624
|
+
type: "text",
|
|
625
|
+
text: "Hello, world!"
|
|
852
626
|
}
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
627
|
+
]
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
);
|
|
631
|
+
this.server.setRequestHandler(
|
|
632
|
+
import_zod.z.object({ method: import_zod.z.literal("stockGraph") }),
|
|
633
|
+
async (request, extra) => {
|
|
634
|
+
this.parser?.logger.log({
|
|
635
|
+
level: "info",
|
|
636
|
+
message: "MCP Server Resource called: stockGraph"
|
|
637
|
+
});
|
|
638
|
+
const args = request.params;
|
|
639
|
+
const symbol = args.symbol;
|
|
640
|
+
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
641
|
+
if (priceHistory.length === 0) {
|
|
642
|
+
return {
|
|
643
|
+
content: [
|
|
644
|
+
{
|
|
645
|
+
type: "text",
|
|
646
|
+
text: `No price data available for ${symbol}`
|
|
867
647
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
648
|
+
]
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
const width = 600;
|
|
652
|
+
const height = 300;
|
|
653
|
+
const padding = 40;
|
|
654
|
+
const xScale = (width - 2 * padding) / (priceHistory.length - 1);
|
|
655
|
+
const yMin = Math.min(...priceHistory.map((d) => d.price));
|
|
656
|
+
const yMax = Math.max(...priceHistory.map((d) => d.price));
|
|
657
|
+
const yScale = (height - 2 * padding) / (yMax - yMin);
|
|
658
|
+
const points = priceHistory.map((d, i) => {
|
|
659
|
+
const x = padding + i * xScale;
|
|
660
|
+
const y = height - padding - (d.price - yMin) * yScale;
|
|
661
|
+
return `${x},${y}`;
|
|
662
|
+
}).join(" L ");
|
|
663
|
+
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
881
664
|
<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
|
|
882
665
|
<!-- Background -->
|
|
883
666
|
<rect width="100%" height="100%" fill="#f8f9fa"/>
|
|
@@ -885,9 +668,9 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
885
668
|
<!-- Grid lines -->
|
|
886
669
|
<g stroke="#e9ecef" stroke-width="1">
|
|
887
670
|
${Array.from({ length: 5 }, (_, i) => {
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
671
|
+
const y = padding + (height - 2 * padding) * i / 4;
|
|
672
|
+
return `<line x1="${padding}" y1="${y}" x2="${width - padding}" y2="${y}"/>`;
|
|
673
|
+
}).join("\n")}
|
|
891
674
|
</g>
|
|
892
675
|
|
|
893
676
|
<!-- Price line -->
|
|
@@ -898,24 +681,24 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
898
681
|
|
|
899
682
|
<!-- Data points -->
|
|
900
683
|
${priceHistory.map((d, i) => {
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
684
|
+
const x = padding + i * xScale;
|
|
685
|
+
const y = height - padding - (d.price - yMin) * yScale;
|
|
686
|
+
return `<circle cx="${x}" cy="${y}" r="3" fill="#007bff"/>`;
|
|
687
|
+
}).join("\n")}
|
|
905
688
|
|
|
906
689
|
<!-- Labels -->
|
|
907
690
|
<g font-family="Arial" font-size="12" fill="#495057">
|
|
908
691
|
${Array.from({ length: 5 }, (_, i) => {
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
692
|
+
const x = padding + (width - 2 * padding) * i / 4;
|
|
693
|
+
const index = Math.floor((priceHistory.length - 1) * i / 4);
|
|
694
|
+
const timestamp = new Date(priceHistory[index].timestamp).toLocaleTimeString();
|
|
695
|
+
return `<text x="${x + padding}" y="${height - padding + 20}" text-anchor="middle">${timestamp}</text>`;
|
|
696
|
+
}).join("\n")}
|
|
914
697
|
${Array.from({ length: 5 }, (_, i) => {
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
698
|
+
const y = padding + (height - 2 * padding) * i / 4;
|
|
699
|
+
const price = yMax - (yMax - yMin) * i / 4;
|
|
700
|
+
return `<text x="${padding - 5}" y="${y + 4}" text-anchor="end">$${price.toFixed(2)}</text>`;
|
|
701
|
+
}).join("\n")}
|
|
919
702
|
</g>
|
|
920
703
|
|
|
921
704
|
<!-- Title -->
|
|
@@ -925,86 +708,45 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
925
708
|
${symbol} - Price Chart (${priceHistory.length} points)
|
|
926
709
|
</text>
|
|
927
710
|
</svg>`;
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
uri: "getStockGraph"
|
|
934
|
-
}
|
|
935
|
-
]
|
|
936
|
-
};
|
|
937
|
-
} catch (error) {
|
|
938
|
-
return {
|
|
939
|
-
contents: [
|
|
940
|
-
{
|
|
941
|
-
type: "text",
|
|
942
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to generate stock graph"}`,
|
|
943
|
-
uri: "getStockGraph"
|
|
944
|
-
}
|
|
945
|
-
],
|
|
946
|
-
isError: true
|
|
947
|
-
};
|
|
948
|
-
}
|
|
949
|
-
case "getStockPriceHistory":
|
|
950
|
-
try {
|
|
951
|
-
const symbol = args.symbol;
|
|
952
|
-
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
953
|
-
if (priceHistory.length === 0) {
|
|
954
|
-
return {
|
|
955
|
-
contents: [
|
|
956
|
-
{
|
|
957
|
-
type: "text",
|
|
958
|
-
text: `No price data available for ${symbol}`,
|
|
959
|
-
uri: "getStockPriceHistory"
|
|
960
|
-
}
|
|
961
|
-
]
|
|
962
|
-
};
|
|
963
|
-
}
|
|
964
|
-
return {
|
|
965
|
-
contents: [
|
|
966
|
-
{
|
|
967
|
-
type: "text",
|
|
968
|
-
text: JSON.stringify(
|
|
969
|
-
{
|
|
970
|
-
symbol,
|
|
971
|
-
count: priceHistory.length,
|
|
972
|
-
prices: priceHistory.map((point) => ({
|
|
973
|
-
timestamp: new Date(point.timestamp).toISOString(),
|
|
974
|
-
price: point.price
|
|
975
|
-
}))
|
|
976
|
-
},
|
|
977
|
-
null,
|
|
978
|
-
2
|
|
979
|
-
),
|
|
980
|
-
uri: "getStockPriceHistory"
|
|
981
|
-
}
|
|
982
|
-
]
|
|
983
|
-
};
|
|
984
|
-
} catch (error) {
|
|
985
|
-
return {
|
|
986
|
-
contents: [
|
|
987
|
-
{
|
|
988
|
-
type: "text",
|
|
989
|
-
text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
|
|
990
|
-
uri: "getStockPriceHistory"
|
|
991
|
-
}
|
|
992
|
-
],
|
|
993
|
-
isError: true
|
|
994
|
-
};
|
|
711
|
+
return {
|
|
712
|
+
content: [
|
|
713
|
+
{
|
|
714
|
+
type: "text",
|
|
715
|
+
text: svg
|
|
995
716
|
}
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
717
|
+
]
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
);
|
|
721
|
+
this.server.setRequestHandler(
|
|
722
|
+
import_zod.z.object({ method: import_zod.z.literal("stockPriceHistory") }),
|
|
723
|
+
async (request, extra) => {
|
|
724
|
+
this.parser?.logger.log({
|
|
725
|
+
level: "info",
|
|
726
|
+
message: "MCP Server Resource called: stockPriceHistory"
|
|
727
|
+
});
|
|
728
|
+
const args = request.params;
|
|
729
|
+
const symbol = args.symbol;
|
|
730
|
+
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
731
|
+
return {
|
|
732
|
+
content: [
|
|
733
|
+
{
|
|
734
|
+
type: "text",
|
|
735
|
+
text: JSON.stringify(
|
|
999
736
|
{
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
737
|
+
symbol,
|
|
738
|
+
count: priceHistory.length,
|
|
739
|
+
prices: priceHistory.map((point) => ({
|
|
740
|
+
timestamp: new Date(point.timestamp).toISOString(),
|
|
741
|
+
price: point.price
|
|
742
|
+
}))
|
|
743
|
+
},
|
|
744
|
+
null,
|
|
745
|
+
2
|
|
746
|
+
)
|
|
747
|
+
}
|
|
748
|
+
]
|
|
749
|
+
};
|
|
1008
750
|
}
|
|
1009
751
|
);
|
|
1010
752
|
process.on("SIGINT", async () => {
|