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.
@@ -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/{symbol}"
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/{symbol}"
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/{symbol}",
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/{symbol}",
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/{symbol} resource.",
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/{symbol} resource.",
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
- contents: [{ type: "text", text: "Error: Failed to parse FIX string" }],
647
+ content: [{ type: "text", text: "Error: Failed to parse FIX string" }],
759
648
  isError: true
760
649
  };
761
650
  }
762
651
  return {
763
- contents: [
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
- contents: [
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
- contents: [{ type: "text", text: "Error: Failed to parse FIX string" }],
684
+ content: [{ type: "text", text: "Error: Failed to parse FIX string" }],
796
685
  isError: true
797
686
  };
798
687
  }
799
688
  return {
800
- contents: [
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
- contents: [
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
- contents: [
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
- contents: [
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
- contents: [
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
- contents: [
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
- contents: [
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
- contents: [
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
- contents: [
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
- contents: [
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
- contents: [
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
- contents: [
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);