fixparser-plugin-mcp 9.1.7-81ea0211 → 9.1.7-89ae1451
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 +179 -153
- package/build/cjs/MCPLocal.js.map +2 -2
- package/build/esm/MCPLocal.mjs +179 -153
- package/build/esm/MCPLocal.mjs.map +2 -2
- package/build-examples/cjs/example_mcp_local.js +22 -22
- package/build-examples/cjs/example_mcp_local.js.map +3 -3
- package/build-examples/esm/example_mcp_local.mjs +21 -21
- package/build-examples/esm/example_mcp_local.mjs.map +3 -3
- package/package.json +2 -2
package/build/cjs/MCPLocal.js
CHANGED
|
@@ -27,6 +27,9 @@ var import_server = require("@modelcontextprotocol/sdk/server/index.js");
|
|
|
27
27
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
28
28
|
var import_fixparser = require("fixparser");
|
|
29
29
|
var import_zod = require("zod");
|
|
30
|
+
var symbolSchema = import_zod.z.object({
|
|
31
|
+
symbol: import_zod.z.string()
|
|
32
|
+
});
|
|
30
33
|
var fixStringSchema = import_zod.z.object({
|
|
31
34
|
fixString: import_zod.z.string()
|
|
32
35
|
});
|
|
@@ -279,11 +282,25 @@ var MCPLocal = class {
|
|
|
279
282
|
},
|
|
280
283
|
stockGraph: {
|
|
281
284
|
description: "Generates a price chart for a given symbol",
|
|
282
|
-
uri: "stockGraph
|
|
285
|
+
uri: "stockGraph",
|
|
286
|
+
parameters: {
|
|
287
|
+
type: "object",
|
|
288
|
+
properties: {
|
|
289
|
+
symbol: { type: "string" }
|
|
290
|
+
},
|
|
291
|
+
required: ["symbol"]
|
|
292
|
+
}
|
|
283
293
|
},
|
|
284
294
|
stockPriceHistory: {
|
|
285
295
|
description: "Returns price history for a given symbol",
|
|
286
|
-
uri: "stockPriceHistory
|
|
296
|
+
uri: "stockPriceHistory",
|
|
297
|
+
parameters: {
|
|
298
|
+
type: "object",
|
|
299
|
+
properties: {
|
|
300
|
+
symbol: { type: "string" }
|
|
301
|
+
},
|
|
302
|
+
required: ["symbol"]
|
|
303
|
+
}
|
|
287
304
|
}
|
|
288
305
|
}
|
|
289
306
|
}
|
|
@@ -377,20 +394,11 @@ var MCPLocal = class {
|
|
|
377
394
|
name: "greeting",
|
|
378
395
|
description: "A simple greeting resource",
|
|
379
396
|
uri: "greeting-resource"
|
|
380
|
-
}
|
|
381
|
-
]
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
);
|
|
385
|
-
this.server.setRequestHandler(
|
|
386
|
-
import_zod.z.object({ method: import_zod.z.literal("resources/templates/list") }),
|
|
387
|
-
async (request, extra) => {
|
|
388
|
-
return {
|
|
389
|
-
templates: [
|
|
397
|
+
},
|
|
390
398
|
{
|
|
391
399
|
name: "stockGraph",
|
|
392
400
|
description: "Generates a price chart for a given symbol",
|
|
393
|
-
uri: "stockGraph
|
|
401
|
+
uri: "stockGraph",
|
|
394
402
|
parameters: {
|
|
395
403
|
type: "object",
|
|
396
404
|
properties: {
|
|
@@ -402,7 +410,7 @@ var MCPLocal = class {
|
|
|
402
410
|
{
|
|
403
411
|
name: "stockPriceHistory",
|
|
404
412
|
description: "Returns price history for a given symbol",
|
|
405
|
-
uri: "stockPriceHistory
|
|
413
|
+
uri: "stockPriceHistory",
|
|
406
414
|
parameters: {
|
|
407
415
|
type: "object",
|
|
408
416
|
properties: {
|
|
@@ -590,8 +598,7 @@ var MCPLocal = class {
|
|
|
590
598
|
contents: [
|
|
591
599
|
{
|
|
592
600
|
type: "text",
|
|
593
|
-
text: "Hello, world!"
|
|
594
|
-
uri: "greeting-resource"
|
|
601
|
+
text: "Hello, world!"
|
|
595
602
|
}
|
|
596
603
|
]
|
|
597
604
|
};
|
|
@@ -600,8 +607,7 @@ var MCPLocal = class {
|
|
|
600
607
|
contents: [
|
|
601
608
|
{
|
|
602
609
|
type: "text",
|
|
603
|
-
text: "This resource requires a symbol parameter. Please use the stockGraph
|
|
604
|
-
uri: "stockGraph"
|
|
610
|
+
text: "This resource requires a symbol parameter. Please use the stockGraph resource with a symbol parameter."
|
|
605
611
|
}
|
|
606
612
|
]
|
|
607
613
|
};
|
|
@@ -610,133 +616,16 @@ var MCPLocal = class {
|
|
|
610
616
|
contents: [
|
|
611
617
|
{
|
|
612
618
|
type: "text",
|
|
613
|
-
text: "This resource requires a symbol parameter. Please use the stockPriceHistory
|
|
614
|
-
uri: "stockPriceHistory"
|
|
619
|
+
text: "This resource requires a symbol parameter. Please use the stockPriceHistory resource with a symbol parameter."
|
|
615
620
|
}
|
|
616
621
|
]
|
|
617
622
|
};
|
|
618
623
|
default:
|
|
619
|
-
if (uri.startsWith("stockGraph/")) {
|
|
620
|
-
const symbol = uri.split("/")[1];
|
|
621
|
-
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
622
|
-
if (priceHistory.length === 0) {
|
|
623
|
-
return {
|
|
624
|
-
contents: [
|
|
625
|
-
{
|
|
626
|
-
type: "text",
|
|
627
|
-
text: `No price data available for ${symbol}`
|
|
628
|
-
}
|
|
629
|
-
]
|
|
630
|
-
};
|
|
631
|
-
}
|
|
632
|
-
const width = 600;
|
|
633
|
-
const height = 300;
|
|
634
|
-
const padding = 40;
|
|
635
|
-
const xScale = (width - 2 * padding) / (priceHistory.length - 1);
|
|
636
|
-
const yMin = Math.min(...priceHistory.map((d) => d.price));
|
|
637
|
-
const yMax = Math.max(...priceHistory.map((d) => d.price));
|
|
638
|
-
const yScale = (height - 2 * padding) / (yMax - yMin);
|
|
639
|
-
const points = priceHistory.map((d, i) => {
|
|
640
|
-
const x = padding + i * xScale;
|
|
641
|
-
const y = height - padding - (d.price - yMin) * yScale;
|
|
642
|
-
return `${x},${y}`;
|
|
643
|
-
}).join(" L ");
|
|
644
|
-
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
645
|
-
<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
|
|
646
|
-
<!-- Background -->
|
|
647
|
-
<rect width="100%" height="100%" fill="#f8f9fa"/>
|
|
648
|
-
|
|
649
|
-
<!-- Grid lines -->
|
|
650
|
-
<g stroke="#e9ecef" stroke-width="1">
|
|
651
|
-
${Array.from({ length: 5 }, (_, i) => {
|
|
652
|
-
const y = padding + (height - 2 * padding) * i / 4;
|
|
653
|
-
return `<line x1="${padding}" y1="${y}" x2="${width - padding}" y2="${y}"/>`;
|
|
654
|
-
}).join("\n")}
|
|
655
|
-
</g>
|
|
656
|
-
|
|
657
|
-
<!-- Price line -->
|
|
658
|
-
<path d="M ${points}"
|
|
659
|
-
fill="none"
|
|
660
|
-
stroke="#007bff"
|
|
661
|
-
stroke-width="2"/>
|
|
662
|
-
|
|
663
|
-
<!-- Data points -->
|
|
664
|
-
${priceHistory.map((d, i) => {
|
|
665
|
-
const x = padding + i * xScale;
|
|
666
|
-
const y = height - padding - (d.price - yMin) * yScale;
|
|
667
|
-
return `<circle cx="${x}" cy="${y}" r="3" fill="#007bff"/>`;
|
|
668
|
-
}).join("\n")}
|
|
669
|
-
|
|
670
|
-
<!-- Labels -->
|
|
671
|
-
<g font-family="Arial" font-size="12" fill="#495057">
|
|
672
|
-
${Array.from({ length: 5 }, (_, i) => {
|
|
673
|
-
const x = padding + (width - 2 * padding) * i / 4;
|
|
674
|
-
const index = Math.floor((priceHistory.length - 1) * i / 4);
|
|
675
|
-
const timestamp = new Date(priceHistory[index].timestamp).toLocaleTimeString();
|
|
676
|
-
return `<text x="${x + padding}" y="${height - padding + 20}" text-anchor="middle">${timestamp}</text>`;
|
|
677
|
-
}).join("\n")}
|
|
678
|
-
${Array.from({ length: 5 }, (_, i) => {
|
|
679
|
-
const y = padding + (height - 2 * padding) * i / 4;
|
|
680
|
-
const price = yMax - (yMax - yMin) * i / 4;
|
|
681
|
-
return `<text x="${padding - 5}" y="${y + 4}" text-anchor="end">$${price.toFixed(2)}</text>`;
|
|
682
|
-
}).join("\n")}
|
|
683
|
-
</g>
|
|
684
|
-
|
|
685
|
-
<!-- Title -->
|
|
686
|
-
<text x="${width / 2}" y="${padding / 2}"
|
|
687
|
-
font-family="Arial" font-size="16" font-weight="bold"
|
|
688
|
-
text-anchor="middle" fill="#212529">
|
|
689
|
-
${symbol} - Price Chart (${priceHistory.length} points)
|
|
690
|
-
</text>
|
|
691
|
-
</svg>`;
|
|
692
|
-
return {
|
|
693
|
-
contents: [
|
|
694
|
-
{
|
|
695
|
-
type: "text",
|
|
696
|
-
text: svg
|
|
697
|
-
}
|
|
698
|
-
]
|
|
699
|
-
};
|
|
700
|
-
}
|
|
701
|
-
if (uri.startsWith("stockPriceHistory/")) {
|
|
702
|
-
const symbol = uri.split("/")[1];
|
|
703
|
-
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
704
|
-
if (priceHistory.length === 0) {
|
|
705
|
-
return {
|
|
706
|
-
contents: [
|
|
707
|
-
{
|
|
708
|
-
type: "text",
|
|
709
|
-
text: `No price data available for ${symbol}`
|
|
710
|
-
}
|
|
711
|
-
]
|
|
712
|
-
};
|
|
713
|
-
}
|
|
714
|
-
return {
|
|
715
|
-
contents: [
|
|
716
|
-
{
|
|
717
|
-
type: "text",
|
|
718
|
-
text: JSON.stringify(
|
|
719
|
-
{
|
|
720
|
-
symbol,
|
|
721
|
-
count: priceHistory.length,
|
|
722
|
-
prices: priceHistory.map((point) => ({
|
|
723
|
-
timestamp: new Date(point.timestamp).toISOString(),
|
|
724
|
-
price: point.price
|
|
725
|
-
}))
|
|
726
|
-
},
|
|
727
|
-
null,
|
|
728
|
-
2
|
|
729
|
-
)
|
|
730
|
-
}
|
|
731
|
-
]
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
624
|
return {
|
|
735
625
|
contents: [
|
|
736
626
|
{
|
|
737
627
|
type: "text",
|
|
738
|
-
text: `Resource not found: ${uri}
|
|
739
|
-
uri
|
|
628
|
+
text: `Resource not found: ${uri}`
|
|
740
629
|
}
|
|
741
630
|
],
|
|
742
631
|
isError: true
|
|
@@ -755,12 +644,12 @@ var MCPLocal = class {
|
|
|
755
644
|
const parsedMessage = this.parser?.parse(args.fixString);
|
|
756
645
|
if (!parsedMessage || parsedMessage.length === 0) {
|
|
757
646
|
return {
|
|
758
|
-
|
|
647
|
+
content: [{ type: "text", text: "Error: Failed to parse FIX string" }],
|
|
759
648
|
isError: true
|
|
760
649
|
};
|
|
761
650
|
}
|
|
762
651
|
return {
|
|
763
|
-
|
|
652
|
+
content: [
|
|
764
653
|
{
|
|
765
654
|
type: "text",
|
|
766
655
|
text: `${parsedMessage[0].description}
|
|
@@ -770,7 +659,7 @@ ${parsedMessage[0].messageTypeDescription}`
|
|
|
770
659
|
};
|
|
771
660
|
} catch (error) {
|
|
772
661
|
return {
|
|
773
|
-
|
|
662
|
+
content: [
|
|
774
663
|
{
|
|
775
664
|
type: "text",
|
|
776
665
|
text: `Error: ${error instanceof Error ? error.message : "Failed to parse FIX string"}`
|
|
@@ -792,12 +681,12 @@ ${parsedMessage[0].messageTypeDescription}`
|
|
|
792
681
|
const parsedMessage = this.parser?.parse(args.fixString);
|
|
793
682
|
if (!parsedMessage || parsedMessage.length === 0) {
|
|
794
683
|
return {
|
|
795
|
-
|
|
684
|
+
content: [{ type: "text", text: "Error: Failed to parse FIX string" }],
|
|
796
685
|
isError: true
|
|
797
686
|
};
|
|
798
687
|
}
|
|
799
688
|
return {
|
|
800
|
-
|
|
689
|
+
content: [
|
|
801
690
|
{
|
|
802
691
|
type: "text",
|
|
803
692
|
text: `${parsedMessage[0].toFIXJSON()}`
|
|
@@ -806,7 +695,7 @@ ${parsedMessage[0].messageTypeDescription}`
|
|
|
806
695
|
};
|
|
807
696
|
} catch (error) {
|
|
808
697
|
return {
|
|
809
|
-
|
|
698
|
+
content: [
|
|
810
699
|
{
|
|
811
700
|
type: "text",
|
|
812
701
|
text: `Error: ${error instanceof Error ? error.message : "Failed to parse FIX string"}`
|
|
@@ -903,7 +792,7 @@ ${parsedMessage[0].messageTypeDescription}`
|
|
|
903
792
|
"3": "ManualOrder"
|
|
904
793
|
};
|
|
905
794
|
return {
|
|
906
|
-
|
|
795
|
+
content: [
|
|
907
796
|
{
|
|
908
797
|
type: "text",
|
|
909
798
|
text: `VERIFICATION: All parameters valid. Ready to proceed with order execution.
|
|
@@ -924,7 +813,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
924
813
|
};
|
|
925
814
|
} catch (error) {
|
|
926
815
|
return {
|
|
927
|
-
|
|
816
|
+
content: [
|
|
928
817
|
{
|
|
929
818
|
type: "text",
|
|
930
819
|
text: `Error: ${error instanceof Error ? error.message : "Failed to verify order parameters"}`
|
|
@@ -946,7 +835,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
946
835
|
const verifiedOrder = this.verifiedOrders.get(args.clOrdID);
|
|
947
836
|
if (!verifiedOrder) {
|
|
948
837
|
return {
|
|
949
|
-
|
|
838
|
+
content: [
|
|
950
839
|
{
|
|
951
840
|
type: "text",
|
|
952
841
|
text: `Error: Order ${args.clOrdID} has not been verified. Please call verifyOrder first.`
|
|
@@ -957,7 +846,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
957
846
|
}
|
|
958
847
|
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) {
|
|
959
848
|
return {
|
|
960
|
-
|
|
849
|
+
content: [
|
|
961
850
|
{
|
|
962
851
|
type: "text",
|
|
963
852
|
text: "Error: Order parameters do not match the verified order. Please use the exact same parameters that were verified."
|
|
@@ -987,7 +876,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
987
876
|
);
|
|
988
877
|
if (!this.parser?.connected) {
|
|
989
878
|
return {
|
|
990
|
-
|
|
879
|
+
content: [
|
|
991
880
|
{
|
|
992
881
|
type: "text",
|
|
993
882
|
text: "Error: Not connected. Ignoring message."
|
|
@@ -1000,7 +889,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
1000
889
|
const fixData = await response;
|
|
1001
890
|
this.verifiedOrders.delete(args.clOrdID);
|
|
1002
891
|
return {
|
|
1003
|
-
|
|
892
|
+
content: [
|
|
1004
893
|
{
|
|
1005
894
|
type: "text",
|
|
1006
895
|
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())}`
|
|
@@ -1009,7 +898,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
1009
898
|
};
|
|
1010
899
|
} catch (error) {
|
|
1011
900
|
return {
|
|
1012
|
-
|
|
901
|
+
content: [
|
|
1013
902
|
{
|
|
1014
903
|
type: "text",
|
|
1015
904
|
text: `Error: ${error instanceof Error ? error.message : "Failed to execute order"}`
|
|
@@ -1053,7 +942,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
1053
942
|
const mdr = this.parser?.createMessage(...messageFields);
|
|
1054
943
|
if (!this.parser?.connected) {
|
|
1055
944
|
return {
|
|
1056
|
-
|
|
945
|
+
content: [
|
|
1057
946
|
{
|
|
1058
947
|
type: "text",
|
|
1059
948
|
text: "Error: Not connected. Ignoring message."
|
|
@@ -1065,7 +954,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
1065
954
|
this.parser?.send(mdr);
|
|
1066
955
|
const fixData = await response;
|
|
1067
956
|
return {
|
|
1068
|
-
|
|
957
|
+
content: [
|
|
1069
958
|
{
|
|
1070
959
|
type: "text",
|
|
1071
960
|
text: `Market data for ${args.symbols.join(", ")}: ${JSON.stringify(fixData.toFIXJSON())}`
|
|
@@ -1074,7 +963,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
1074
963
|
};
|
|
1075
964
|
} catch (error) {
|
|
1076
965
|
return {
|
|
1077
|
-
|
|
966
|
+
content: [
|
|
1078
967
|
{
|
|
1079
968
|
type: "text",
|
|
1080
969
|
text: `Error: ${error instanceof Error ? error.message : "Failed to request market data"}`
|
|
@@ -1085,6 +974,143 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
1085
974
|
}
|
|
1086
975
|
}
|
|
1087
976
|
);
|
|
977
|
+
this.server.setRequestHandler(
|
|
978
|
+
import_zod.z.object({
|
|
979
|
+
method: import_zod.z.literal("stockGraph"),
|
|
980
|
+
params: symbolSchema
|
|
981
|
+
}),
|
|
982
|
+
async (request, extra) => {
|
|
983
|
+
this.parser?.logger.log({
|
|
984
|
+
level: "info",
|
|
985
|
+
message: "MCP Server Resource called: stockGraph"
|
|
986
|
+
});
|
|
987
|
+
const args = request.params;
|
|
988
|
+
const symbol = args.symbol;
|
|
989
|
+
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
990
|
+
if (priceHistory.length === 0) {
|
|
991
|
+
return {
|
|
992
|
+
content: [
|
|
993
|
+
{
|
|
994
|
+
type: "text",
|
|
995
|
+
text: `No price data available for ${symbol}`
|
|
996
|
+
}
|
|
997
|
+
]
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
const width = 600;
|
|
1001
|
+
const height = 300;
|
|
1002
|
+
const padding = 40;
|
|
1003
|
+
const xScale = (width - 2 * padding) / (priceHistory.length - 1);
|
|
1004
|
+
const yMin = Math.min(...priceHistory.map((d) => d.price));
|
|
1005
|
+
const yMax = Math.max(...priceHistory.map((d) => d.price));
|
|
1006
|
+
const yScale = (height - 2 * padding) / (yMax - yMin);
|
|
1007
|
+
const points = priceHistory.map((d, i) => {
|
|
1008
|
+
const x = padding + i * xScale;
|
|
1009
|
+
const y = height - padding - (d.price - yMin) * yScale;
|
|
1010
|
+
return `${x},${y}`;
|
|
1011
|
+
}).join(" L ");
|
|
1012
|
+
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
1013
|
+
<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
|
|
1014
|
+
<!-- Background -->
|
|
1015
|
+
<rect width="100%" height="100%" fill="#f8f9fa"/>
|
|
1016
|
+
|
|
1017
|
+
<!-- Grid lines -->
|
|
1018
|
+
<g stroke="#e9ecef" stroke-width="1">
|
|
1019
|
+
${Array.from({ length: 5 }, (_, i) => {
|
|
1020
|
+
const y = padding + (height - 2 * padding) * i / 4;
|
|
1021
|
+
return `<line x1="${padding}" y1="${y}" x2="${width - padding}" y2="${y}"/>`;
|
|
1022
|
+
}).join("\n")}
|
|
1023
|
+
</g>
|
|
1024
|
+
|
|
1025
|
+
<!-- Price line -->
|
|
1026
|
+
<path d="M ${points}"
|
|
1027
|
+
fill="none"
|
|
1028
|
+
stroke="#007bff"
|
|
1029
|
+
stroke-width="2"/>
|
|
1030
|
+
|
|
1031
|
+
<!-- Data points -->
|
|
1032
|
+
${priceHistory.map((d, i) => {
|
|
1033
|
+
const x = padding + i * xScale;
|
|
1034
|
+
const y = height - padding - (d.price - yMin) * yScale;
|
|
1035
|
+
return `<circle cx="${x}" cy="${y}" r="3" fill="#007bff"/>`;
|
|
1036
|
+
}).join("\n")}
|
|
1037
|
+
|
|
1038
|
+
<!-- Labels -->
|
|
1039
|
+
<g font-family="Arial" font-size="12" fill="#495057">
|
|
1040
|
+
${Array.from({ length: 5 }, (_, i) => {
|
|
1041
|
+
const x = padding + (width - 2 * padding) * i / 4;
|
|
1042
|
+
const index = Math.floor((priceHistory.length - 1) * i / 4);
|
|
1043
|
+
const timestamp = new Date(priceHistory[index].timestamp).toLocaleTimeString();
|
|
1044
|
+
return `<text x="${x + padding}" y="${height - padding + 20}" text-anchor="middle">${timestamp}</text>`;
|
|
1045
|
+
}).join("\n")}
|
|
1046
|
+
${Array.from({ length: 5 }, (_, i) => {
|
|
1047
|
+
const y = padding + (height - 2 * padding) * i / 4;
|
|
1048
|
+
const price = yMax - (yMax - yMin) * i / 4;
|
|
1049
|
+
return `<text x="${padding - 5}" y="${y + 4}" text-anchor="end">$${price.toFixed(2)}</text>`;
|
|
1050
|
+
}).join("\n")}
|
|
1051
|
+
</g>
|
|
1052
|
+
|
|
1053
|
+
<!-- Title -->
|
|
1054
|
+
<text x="${width / 2}" y="${padding / 2}"
|
|
1055
|
+
font-family="Arial" font-size="16" font-weight="bold"
|
|
1056
|
+
text-anchor="middle" fill="#212529">
|
|
1057
|
+
${symbol} - Price Chart (${priceHistory.length} points)
|
|
1058
|
+
</text>
|
|
1059
|
+
</svg>`;
|
|
1060
|
+
return {
|
|
1061
|
+
content: [
|
|
1062
|
+
{
|
|
1063
|
+
type: "text",
|
|
1064
|
+
text: svg
|
|
1065
|
+
}
|
|
1066
|
+
]
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
);
|
|
1070
|
+
this.server.setRequestHandler(
|
|
1071
|
+
import_zod.z.object({
|
|
1072
|
+
method: import_zod.z.literal("stockPriceHistory"),
|
|
1073
|
+
params: symbolSchema
|
|
1074
|
+
}),
|
|
1075
|
+
async (request, extra) => {
|
|
1076
|
+
this.parser?.logger.log({
|
|
1077
|
+
level: "info",
|
|
1078
|
+
message: "MCP Server Resource called: stockPriceHistory"
|
|
1079
|
+
});
|
|
1080
|
+
const args = request.params;
|
|
1081
|
+
const symbol = args.symbol;
|
|
1082
|
+
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
1083
|
+
if (priceHistory.length === 0) {
|
|
1084
|
+
return {
|
|
1085
|
+
content: [
|
|
1086
|
+
{
|
|
1087
|
+
type: "text",
|
|
1088
|
+
text: `No price data available for ${symbol}`
|
|
1089
|
+
}
|
|
1090
|
+
]
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
return {
|
|
1094
|
+
content: [
|
|
1095
|
+
{
|
|
1096
|
+
type: "text",
|
|
1097
|
+
text: JSON.stringify(
|
|
1098
|
+
{
|
|
1099
|
+
symbol,
|
|
1100
|
+
count: priceHistory.length,
|
|
1101
|
+
prices: priceHistory.map((point) => ({
|
|
1102
|
+
timestamp: new Date(point.timestamp).toISOString(),
|
|
1103
|
+
price: point.price
|
|
1104
|
+
}))
|
|
1105
|
+
},
|
|
1106
|
+
null,
|
|
1107
|
+
2
|
|
1108
|
+
)
|
|
1109
|
+
}
|
|
1110
|
+
]
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
);
|
|
1088
1114
|
process.on("SIGINT", async () => {
|
|
1089
1115
|
await this.server.close();
|
|
1090
1116
|
process.exit(0);
|