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/esm/MCPLocal.mjs
CHANGED
|
@@ -3,6 +3,9 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { Field, Fields, Messages } from "fixparser";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
+
var symbolSchema = z.object({
|
|
7
|
+
symbol: z.string()
|
|
8
|
+
});
|
|
6
9
|
var fixStringSchema = z.object({
|
|
7
10
|
fixString: z.string()
|
|
8
11
|
});
|
|
@@ -255,11 +258,25 @@ var MCPLocal = class {
|
|
|
255
258
|
},
|
|
256
259
|
stockGraph: {
|
|
257
260
|
description: "Generates a price chart for a given symbol",
|
|
258
|
-
uri: "stockGraph
|
|
261
|
+
uri: "stockGraph",
|
|
262
|
+
parameters: {
|
|
263
|
+
type: "object",
|
|
264
|
+
properties: {
|
|
265
|
+
symbol: { type: "string" }
|
|
266
|
+
},
|
|
267
|
+
required: ["symbol"]
|
|
268
|
+
}
|
|
259
269
|
},
|
|
260
270
|
stockPriceHistory: {
|
|
261
271
|
description: "Returns price history for a given symbol",
|
|
262
|
-
uri: "stockPriceHistory
|
|
272
|
+
uri: "stockPriceHistory",
|
|
273
|
+
parameters: {
|
|
274
|
+
type: "object",
|
|
275
|
+
properties: {
|
|
276
|
+
symbol: { type: "string" }
|
|
277
|
+
},
|
|
278
|
+
required: ["symbol"]
|
|
279
|
+
}
|
|
263
280
|
}
|
|
264
281
|
}
|
|
265
282
|
}
|
|
@@ -353,20 +370,11 @@ var MCPLocal = class {
|
|
|
353
370
|
name: "greeting",
|
|
354
371
|
description: "A simple greeting resource",
|
|
355
372
|
uri: "greeting-resource"
|
|
356
|
-
}
|
|
357
|
-
]
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
);
|
|
361
|
-
this.server.setRequestHandler(
|
|
362
|
-
z.object({ method: z.literal("resources/templates/list") }),
|
|
363
|
-
async (request, extra) => {
|
|
364
|
-
return {
|
|
365
|
-
templates: [
|
|
373
|
+
},
|
|
366
374
|
{
|
|
367
375
|
name: "stockGraph",
|
|
368
376
|
description: "Generates a price chart for a given symbol",
|
|
369
|
-
uri: "stockGraph
|
|
377
|
+
uri: "stockGraph",
|
|
370
378
|
parameters: {
|
|
371
379
|
type: "object",
|
|
372
380
|
properties: {
|
|
@@ -378,7 +386,7 @@ var MCPLocal = class {
|
|
|
378
386
|
{
|
|
379
387
|
name: "stockPriceHistory",
|
|
380
388
|
description: "Returns price history for a given symbol",
|
|
381
|
-
uri: "stockPriceHistory
|
|
389
|
+
uri: "stockPriceHistory",
|
|
382
390
|
parameters: {
|
|
383
391
|
type: "object",
|
|
384
392
|
properties: {
|
|
@@ -566,8 +574,7 @@ var MCPLocal = class {
|
|
|
566
574
|
contents: [
|
|
567
575
|
{
|
|
568
576
|
type: "text",
|
|
569
|
-
text: "Hello, world!"
|
|
570
|
-
uri: "greeting-resource"
|
|
577
|
+
text: "Hello, world!"
|
|
571
578
|
}
|
|
572
579
|
]
|
|
573
580
|
};
|
|
@@ -576,8 +583,7 @@ var MCPLocal = class {
|
|
|
576
583
|
contents: [
|
|
577
584
|
{
|
|
578
585
|
type: "text",
|
|
579
|
-
text: "This resource requires a symbol parameter. Please use the stockGraph
|
|
580
|
-
uri: "stockGraph"
|
|
586
|
+
text: "This resource requires a symbol parameter. Please use the stockGraph resource with a symbol parameter."
|
|
581
587
|
}
|
|
582
588
|
]
|
|
583
589
|
};
|
|
@@ -586,133 +592,16 @@ var MCPLocal = class {
|
|
|
586
592
|
contents: [
|
|
587
593
|
{
|
|
588
594
|
type: "text",
|
|
589
|
-
text: "This resource requires a symbol parameter. Please use the stockPriceHistory
|
|
590
|
-
uri: "stockPriceHistory"
|
|
595
|
+
text: "This resource requires a symbol parameter. Please use the stockPriceHistory resource with a symbol parameter."
|
|
591
596
|
}
|
|
592
597
|
]
|
|
593
598
|
};
|
|
594
599
|
default:
|
|
595
|
-
if (uri.startsWith("stockGraph/")) {
|
|
596
|
-
const symbol = uri.split("/")[1];
|
|
597
|
-
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
598
|
-
if (priceHistory.length === 0) {
|
|
599
|
-
return {
|
|
600
|
-
contents: [
|
|
601
|
-
{
|
|
602
|
-
type: "text",
|
|
603
|
-
text: `No price data available for ${symbol}`
|
|
604
|
-
}
|
|
605
|
-
]
|
|
606
|
-
};
|
|
607
|
-
}
|
|
608
|
-
const width = 600;
|
|
609
|
-
const height = 300;
|
|
610
|
-
const padding = 40;
|
|
611
|
-
const xScale = (width - 2 * padding) / (priceHistory.length - 1);
|
|
612
|
-
const yMin = Math.min(...priceHistory.map((d) => d.price));
|
|
613
|
-
const yMax = Math.max(...priceHistory.map((d) => d.price));
|
|
614
|
-
const yScale = (height - 2 * padding) / (yMax - yMin);
|
|
615
|
-
const points = priceHistory.map((d, i) => {
|
|
616
|
-
const x = padding + i * xScale;
|
|
617
|
-
const y = height - padding - (d.price - yMin) * yScale;
|
|
618
|
-
return `${x},${y}`;
|
|
619
|
-
}).join(" L ");
|
|
620
|
-
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
621
|
-
<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
|
|
622
|
-
<!-- Background -->
|
|
623
|
-
<rect width="100%" height="100%" fill="#f8f9fa"/>
|
|
624
|
-
|
|
625
|
-
<!-- Grid lines -->
|
|
626
|
-
<g stroke="#e9ecef" stroke-width="1">
|
|
627
|
-
${Array.from({ length: 5 }, (_, i) => {
|
|
628
|
-
const y = padding + (height - 2 * padding) * i / 4;
|
|
629
|
-
return `<line x1="${padding}" y1="${y}" x2="${width - padding}" y2="${y}"/>`;
|
|
630
|
-
}).join("\n")}
|
|
631
|
-
</g>
|
|
632
|
-
|
|
633
|
-
<!-- Price line -->
|
|
634
|
-
<path d="M ${points}"
|
|
635
|
-
fill="none"
|
|
636
|
-
stroke="#007bff"
|
|
637
|
-
stroke-width="2"/>
|
|
638
|
-
|
|
639
|
-
<!-- Data points -->
|
|
640
|
-
${priceHistory.map((d, i) => {
|
|
641
|
-
const x = padding + i * xScale;
|
|
642
|
-
const y = height - padding - (d.price - yMin) * yScale;
|
|
643
|
-
return `<circle cx="${x}" cy="${y}" r="3" fill="#007bff"/>`;
|
|
644
|
-
}).join("\n")}
|
|
645
|
-
|
|
646
|
-
<!-- Labels -->
|
|
647
|
-
<g font-family="Arial" font-size="12" fill="#495057">
|
|
648
|
-
${Array.from({ length: 5 }, (_, i) => {
|
|
649
|
-
const x = padding + (width - 2 * padding) * i / 4;
|
|
650
|
-
const index = Math.floor((priceHistory.length - 1) * i / 4);
|
|
651
|
-
const timestamp = new Date(priceHistory[index].timestamp).toLocaleTimeString();
|
|
652
|
-
return `<text x="${x + padding}" y="${height - padding + 20}" text-anchor="middle">${timestamp}</text>`;
|
|
653
|
-
}).join("\n")}
|
|
654
|
-
${Array.from({ length: 5 }, (_, i) => {
|
|
655
|
-
const y = padding + (height - 2 * padding) * i / 4;
|
|
656
|
-
const price = yMax - (yMax - yMin) * i / 4;
|
|
657
|
-
return `<text x="${padding - 5}" y="${y + 4}" text-anchor="end">$${price.toFixed(2)}</text>`;
|
|
658
|
-
}).join("\n")}
|
|
659
|
-
</g>
|
|
660
|
-
|
|
661
|
-
<!-- Title -->
|
|
662
|
-
<text x="${width / 2}" y="${padding / 2}"
|
|
663
|
-
font-family="Arial" font-size="16" font-weight="bold"
|
|
664
|
-
text-anchor="middle" fill="#212529">
|
|
665
|
-
${symbol} - Price Chart (${priceHistory.length} points)
|
|
666
|
-
</text>
|
|
667
|
-
</svg>`;
|
|
668
|
-
return {
|
|
669
|
-
contents: [
|
|
670
|
-
{
|
|
671
|
-
type: "text",
|
|
672
|
-
text: svg
|
|
673
|
-
}
|
|
674
|
-
]
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
if (uri.startsWith("stockPriceHistory/")) {
|
|
678
|
-
const symbol = uri.split("/")[1];
|
|
679
|
-
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
680
|
-
if (priceHistory.length === 0) {
|
|
681
|
-
return {
|
|
682
|
-
contents: [
|
|
683
|
-
{
|
|
684
|
-
type: "text",
|
|
685
|
-
text: `No price data available for ${symbol}`
|
|
686
|
-
}
|
|
687
|
-
]
|
|
688
|
-
};
|
|
689
|
-
}
|
|
690
|
-
return {
|
|
691
|
-
contents: [
|
|
692
|
-
{
|
|
693
|
-
type: "text",
|
|
694
|
-
text: JSON.stringify(
|
|
695
|
-
{
|
|
696
|
-
symbol,
|
|
697
|
-
count: priceHistory.length,
|
|
698
|
-
prices: priceHistory.map((point) => ({
|
|
699
|
-
timestamp: new Date(point.timestamp).toISOString(),
|
|
700
|
-
price: point.price
|
|
701
|
-
}))
|
|
702
|
-
},
|
|
703
|
-
null,
|
|
704
|
-
2
|
|
705
|
-
)
|
|
706
|
-
}
|
|
707
|
-
]
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
600
|
return {
|
|
711
601
|
contents: [
|
|
712
602
|
{
|
|
713
603
|
type: "text",
|
|
714
|
-
text: `Resource not found: ${uri}
|
|
715
|
-
uri
|
|
604
|
+
text: `Resource not found: ${uri}`
|
|
716
605
|
}
|
|
717
606
|
],
|
|
718
607
|
isError: true
|
|
@@ -731,12 +620,12 @@ var MCPLocal = class {
|
|
|
731
620
|
const parsedMessage = this.parser?.parse(args.fixString);
|
|
732
621
|
if (!parsedMessage || parsedMessage.length === 0) {
|
|
733
622
|
return {
|
|
734
|
-
|
|
623
|
+
content: [{ type: "text", text: "Error: Failed to parse FIX string" }],
|
|
735
624
|
isError: true
|
|
736
625
|
};
|
|
737
626
|
}
|
|
738
627
|
return {
|
|
739
|
-
|
|
628
|
+
content: [
|
|
740
629
|
{
|
|
741
630
|
type: "text",
|
|
742
631
|
text: `${parsedMessage[0].description}
|
|
@@ -746,7 +635,7 @@ ${parsedMessage[0].messageTypeDescription}`
|
|
|
746
635
|
};
|
|
747
636
|
} catch (error) {
|
|
748
637
|
return {
|
|
749
|
-
|
|
638
|
+
content: [
|
|
750
639
|
{
|
|
751
640
|
type: "text",
|
|
752
641
|
text: `Error: ${error instanceof Error ? error.message : "Failed to parse FIX string"}`
|
|
@@ -768,12 +657,12 @@ ${parsedMessage[0].messageTypeDescription}`
|
|
|
768
657
|
const parsedMessage = this.parser?.parse(args.fixString);
|
|
769
658
|
if (!parsedMessage || parsedMessage.length === 0) {
|
|
770
659
|
return {
|
|
771
|
-
|
|
660
|
+
content: [{ type: "text", text: "Error: Failed to parse FIX string" }],
|
|
772
661
|
isError: true
|
|
773
662
|
};
|
|
774
663
|
}
|
|
775
664
|
return {
|
|
776
|
-
|
|
665
|
+
content: [
|
|
777
666
|
{
|
|
778
667
|
type: "text",
|
|
779
668
|
text: `${parsedMessage[0].toFIXJSON()}`
|
|
@@ -782,7 +671,7 @@ ${parsedMessage[0].messageTypeDescription}`
|
|
|
782
671
|
};
|
|
783
672
|
} catch (error) {
|
|
784
673
|
return {
|
|
785
|
-
|
|
674
|
+
content: [
|
|
786
675
|
{
|
|
787
676
|
type: "text",
|
|
788
677
|
text: `Error: ${error instanceof Error ? error.message : "Failed to parse FIX string"}`
|
|
@@ -879,7 +768,7 @@ ${parsedMessage[0].messageTypeDescription}`
|
|
|
879
768
|
"3": "ManualOrder"
|
|
880
769
|
};
|
|
881
770
|
return {
|
|
882
|
-
|
|
771
|
+
content: [
|
|
883
772
|
{
|
|
884
773
|
type: "text",
|
|
885
774
|
text: `VERIFICATION: All parameters valid. Ready to proceed with order execution.
|
|
@@ -900,7 +789,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
900
789
|
};
|
|
901
790
|
} catch (error) {
|
|
902
791
|
return {
|
|
903
|
-
|
|
792
|
+
content: [
|
|
904
793
|
{
|
|
905
794
|
type: "text",
|
|
906
795
|
text: `Error: ${error instanceof Error ? error.message : "Failed to verify order parameters"}`
|
|
@@ -922,7 +811,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
922
811
|
const verifiedOrder = this.verifiedOrders.get(args.clOrdID);
|
|
923
812
|
if (!verifiedOrder) {
|
|
924
813
|
return {
|
|
925
|
-
|
|
814
|
+
content: [
|
|
926
815
|
{
|
|
927
816
|
type: "text",
|
|
928
817
|
text: `Error: Order ${args.clOrdID} has not been verified. Please call verifyOrder first.`
|
|
@@ -933,7 +822,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
933
822
|
}
|
|
934
823
|
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) {
|
|
935
824
|
return {
|
|
936
|
-
|
|
825
|
+
content: [
|
|
937
826
|
{
|
|
938
827
|
type: "text",
|
|
939
828
|
text: "Error: Order parameters do not match the verified order. Please use the exact same parameters that were verified."
|
|
@@ -963,7 +852,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
963
852
|
);
|
|
964
853
|
if (!this.parser?.connected) {
|
|
965
854
|
return {
|
|
966
|
-
|
|
855
|
+
content: [
|
|
967
856
|
{
|
|
968
857
|
type: "text",
|
|
969
858
|
text: "Error: Not connected. Ignoring message."
|
|
@@ -976,7 +865,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
976
865
|
const fixData = await response;
|
|
977
866
|
this.verifiedOrders.delete(args.clOrdID);
|
|
978
867
|
return {
|
|
979
|
-
|
|
868
|
+
content: [
|
|
980
869
|
{
|
|
981
870
|
type: "text",
|
|
982
871
|
text: fixData.messageType === Messages.Reject ? `Reject message for order ${args.clOrdID}: ${JSON.stringify(fixData.toFIXJSON())}` : `Execution Report for order ${args.clOrdID}: ${JSON.stringify(fixData.toFIXJSON())}`
|
|
@@ -985,7 +874,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
985
874
|
};
|
|
986
875
|
} catch (error) {
|
|
987
876
|
return {
|
|
988
|
-
|
|
877
|
+
content: [
|
|
989
878
|
{
|
|
990
879
|
type: "text",
|
|
991
880
|
text: `Error: ${error instanceof Error ? error.message : "Failed to execute order"}`
|
|
@@ -1029,7 +918,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
1029
918
|
const mdr = this.parser?.createMessage(...messageFields);
|
|
1030
919
|
if (!this.parser?.connected) {
|
|
1031
920
|
return {
|
|
1032
|
-
|
|
921
|
+
content: [
|
|
1033
922
|
{
|
|
1034
923
|
type: "text",
|
|
1035
924
|
text: "Error: Not connected. Ignoring message."
|
|
@@ -1041,7 +930,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
1041
930
|
this.parser?.send(mdr);
|
|
1042
931
|
const fixData = await response;
|
|
1043
932
|
return {
|
|
1044
|
-
|
|
933
|
+
content: [
|
|
1045
934
|
{
|
|
1046
935
|
type: "text",
|
|
1047
936
|
text: `Market data for ${args.symbols.join(", ")}: ${JSON.stringify(fixData.toFIXJSON())}`
|
|
@@ -1050,7 +939,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
1050
939
|
};
|
|
1051
940
|
} catch (error) {
|
|
1052
941
|
return {
|
|
1053
|
-
|
|
942
|
+
content: [
|
|
1054
943
|
{
|
|
1055
944
|
type: "text",
|
|
1056
945
|
text: `Error: ${error instanceof Error ? error.message : "Failed to request market data"}`
|
|
@@ -1061,6 +950,143 @@ To execute this order, call the executeOrder tool with these exact same paramete
|
|
|
1061
950
|
}
|
|
1062
951
|
}
|
|
1063
952
|
);
|
|
953
|
+
this.server.setRequestHandler(
|
|
954
|
+
z.object({
|
|
955
|
+
method: z.literal("stockGraph"),
|
|
956
|
+
params: symbolSchema
|
|
957
|
+
}),
|
|
958
|
+
async (request, extra) => {
|
|
959
|
+
this.parser?.logger.log({
|
|
960
|
+
level: "info",
|
|
961
|
+
message: "MCP Server Resource called: stockGraph"
|
|
962
|
+
});
|
|
963
|
+
const args = request.params;
|
|
964
|
+
const symbol = args.symbol;
|
|
965
|
+
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
966
|
+
if (priceHistory.length === 0) {
|
|
967
|
+
return {
|
|
968
|
+
content: [
|
|
969
|
+
{
|
|
970
|
+
type: "text",
|
|
971
|
+
text: `No price data available for ${symbol}`
|
|
972
|
+
}
|
|
973
|
+
]
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
const width = 600;
|
|
977
|
+
const height = 300;
|
|
978
|
+
const padding = 40;
|
|
979
|
+
const xScale = (width - 2 * padding) / (priceHistory.length - 1);
|
|
980
|
+
const yMin = Math.min(...priceHistory.map((d) => d.price));
|
|
981
|
+
const yMax = Math.max(...priceHistory.map((d) => d.price));
|
|
982
|
+
const yScale = (height - 2 * padding) / (yMax - yMin);
|
|
983
|
+
const points = priceHistory.map((d, i) => {
|
|
984
|
+
const x = padding + i * xScale;
|
|
985
|
+
const y = height - padding - (d.price - yMin) * yScale;
|
|
986
|
+
return `${x},${y}`;
|
|
987
|
+
}).join(" L ");
|
|
988
|
+
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
989
|
+
<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
|
|
990
|
+
<!-- Background -->
|
|
991
|
+
<rect width="100%" height="100%" fill="#f8f9fa"/>
|
|
992
|
+
|
|
993
|
+
<!-- Grid lines -->
|
|
994
|
+
<g stroke="#e9ecef" stroke-width="1">
|
|
995
|
+
${Array.from({ length: 5 }, (_, i) => {
|
|
996
|
+
const y = padding + (height - 2 * padding) * i / 4;
|
|
997
|
+
return `<line x1="${padding}" y1="${y}" x2="${width - padding}" y2="${y}"/>`;
|
|
998
|
+
}).join("\n")}
|
|
999
|
+
</g>
|
|
1000
|
+
|
|
1001
|
+
<!-- Price line -->
|
|
1002
|
+
<path d="M ${points}"
|
|
1003
|
+
fill="none"
|
|
1004
|
+
stroke="#007bff"
|
|
1005
|
+
stroke-width="2"/>
|
|
1006
|
+
|
|
1007
|
+
<!-- Data points -->
|
|
1008
|
+
${priceHistory.map((d, i) => {
|
|
1009
|
+
const x = padding + i * xScale;
|
|
1010
|
+
const y = height - padding - (d.price - yMin) * yScale;
|
|
1011
|
+
return `<circle cx="${x}" cy="${y}" r="3" fill="#007bff"/>`;
|
|
1012
|
+
}).join("\n")}
|
|
1013
|
+
|
|
1014
|
+
<!-- Labels -->
|
|
1015
|
+
<g font-family="Arial" font-size="12" fill="#495057">
|
|
1016
|
+
${Array.from({ length: 5 }, (_, i) => {
|
|
1017
|
+
const x = padding + (width - 2 * padding) * i / 4;
|
|
1018
|
+
const index = Math.floor((priceHistory.length - 1) * i / 4);
|
|
1019
|
+
const timestamp = new Date(priceHistory[index].timestamp).toLocaleTimeString();
|
|
1020
|
+
return `<text x="${x + padding}" y="${height - padding + 20}" text-anchor="middle">${timestamp}</text>`;
|
|
1021
|
+
}).join("\n")}
|
|
1022
|
+
${Array.from({ length: 5 }, (_, i) => {
|
|
1023
|
+
const y = padding + (height - 2 * padding) * i / 4;
|
|
1024
|
+
const price = yMax - (yMax - yMin) * i / 4;
|
|
1025
|
+
return `<text x="${padding - 5}" y="${y + 4}" text-anchor="end">$${price.toFixed(2)}</text>`;
|
|
1026
|
+
}).join("\n")}
|
|
1027
|
+
</g>
|
|
1028
|
+
|
|
1029
|
+
<!-- Title -->
|
|
1030
|
+
<text x="${width / 2}" y="${padding / 2}"
|
|
1031
|
+
font-family="Arial" font-size="16" font-weight="bold"
|
|
1032
|
+
text-anchor="middle" fill="#212529">
|
|
1033
|
+
${symbol} - Price Chart (${priceHistory.length} points)
|
|
1034
|
+
</text>
|
|
1035
|
+
</svg>`;
|
|
1036
|
+
return {
|
|
1037
|
+
content: [
|
|
1038
|
+
{
|
|
1039
|
+
type: "text",
|
|
1040
|
+
text: svg
|
|
1041
|
+
}
|
|
1042
|
+
]
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
);
|
|
1046
|
+
this.server.setRequestHandler(
|
|
1047
|
+
z.object({
|
|
1048
|
+
method: z.literal("stockPriceHistory"),
|
|
1049
|
+
params: symbolSchema
|
|
1050
|
+
}),
|
|
1051
|
+
async (request, extra) => {
|
|
1052
|
+
this.parser?.logger.log({
|
|
1053
|
+
level: "info",
|
|
1054
|
+
message: "MCP Server Resource called: stockPriceHistory"
|
|
1055
|
+
});
|
|
1056
|
+
const args = request.params;
|
|
1057
|
+
const symbol = args.symbol;
|
|
1058
|
+
const priceHistory = this.marketDataPrices.get(symbol) || [];
|
|
1059
|
+
if (priceHistory.length === 0) {
|
|
1060
|
+
return {
|
|
1061
|
+
content: [
|
|
1062
|
+
{
|
|
1063
|
+
type: "text",
|
|
1064
|
+
text: `No price data available for ${symbol}`
|
|
1065
|
+
}
|
|
1066
|
+
]
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
return {
|
|
1070
|
+
content: [
|
|
1071
|
+
{
|
|
1072
|
+
type: "text",
|
|
1073
|
+
text: JSON.stringify(
|
|
1074
|
+
{
|
|
1075
|
+
symbol,
|
|
1076
|
+
count: priceHistory.length,
|
|
1077
|
+
prices: priceHistory.map((point) => ({
|
|
1078
|
+
timestamp: new Date(point.timestamp).toISOString(),
|
|
1079
|
+
price: point.price
|
|
1080
|
+
}))
|
|
1081
|
+
},
|
|
1082
|
+
null,
|
|
1083
|
+
2
|
|
1084
|
+
)
|
|
1085
|
+
}
|
|
1086
|
+
]
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
);
|
|
1064
1090
|
process.on("SIGINT", async () => {
|
|
1065
1091
|
await this.server.close();
|
|
1066
1092
|
process.exit(0);
|