fixparser-plugin-mcp 9.1.7-75ded9c1 → 9.1.7-81ea0211

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,100 @@ 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 fixStringSchema = import_zod.z.object({
31
+ fixString: import_zod.z.string()
32
+ });
33
+ var orderSchema = import_zod.z.object({
34
+ clOrdID: import_zod.z.string(),
35
+ handlInst: import_zod.z.enum(["1", "2", "3"]),
36
+ quantity: import_zod.z.string(),
37
+ price: import_zod.z.string(),
38
+ ordType: import_zod.z.enum([
39
+ "1",
40
+ "2",
41
+ "3",
42
+ "4",
43
+ "5",
44
+ "6",
45
+ "7",
46
+ "8",
47
+ "9",
48
+ "A",
49
+ "B",
50
+ "C",
51
+ "D",
52
+ "E",
53
+ "F",
54
+ "G",
55
+ "H",
56
+ "I",
57
+ "J",
58
+ "K",
59
+ "L",
60
+ "M",
61
+ "P",
62
+ "Q",
63
+ "R",
64
+ "S"
65
+ ]),
66
+ side: import_zod.z.enum(["1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H"]),
67
+ symbol: import_zod.z.string(),
68
+ timeInForce: import_zod.z.enum(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C"])
69
+ });
70
+ var marketDataRequestSchema = import_zod.z.object({
71
+ mdUpdateType: import_zod.z.enum(["0", "1"]),
72
+ symbols: import_zod.z.array(import_zod.z.string()),
73
+ mdReqID: import_zod.z.string(),
74
+ subscriptionRequestType: import_zod.z.enum(["0", "1", "2"]),
75
+ mdEntryTypes: import_zod.z.array(
76
+ import_zod.z.enum([
77
+ "0",
78
+ "1",
79
+ "2",
80
+ "3",
81
+ "4",
82
+ "5",
83
+ "6",
84
+ "7",
85
+ "8",
86
+ "9",
87
+ "A",
88
+ "B",
89
+ "C",
90
+ "D",
91
+ "E",
92
+ "F",
93
+ "G",
94
+ "H",
95
+ "J",
96
+ "K",
97
+ "L",
98
+ "M",
99
+ "N",
100
+ "O",
101
+ "P",
102
+ "Q",
103
+ "R",
104
+ "S",
105
+ "T",
106
+ "U",
107
+ "V",
108
+ "W",
109
+ "X",
110
+ "Y",
111
+ "Z",
112
+ "a",
113
+ "b",
114
+ "c",
115
+ "d",
116
+ "e",
117
+ "g",
118
+ "h",
119
+ "i",
120
+ "t"
121
+ ])
122
+ )
123
+ });
30
124
  var MCPLocal = class {
31
125
  parser;
32
126
  server = new import_server.Server(
@@ -240,14 +334,6 @@ var MCPLocal = class {
240
334
  level: "info",
241
335
  message: `MCP Server added ${symbol}: ${priceNum}`
242
336
  });
243
- this.server.notification({
244
- method: "priceUpdate",
245
- params: {
246
- symbol: symbolStr,
247
- price: priceNum,
248
- timestamp: Number(timestamp)
249
- }
250
- });
251
337
  }
252
338
  }
253
339
  if (msgType === import_fixparser.Messages.MarketDataSnapshotFullRefresh) {
@@ -300,11 +386,11 @@ var MCPLocal = class {
300
386
  import_zod.z.object({ method: import_zod.z.literal("resources/templates/list") }),
301
387
  async (request, extra) => {
302
388
  return {
303
- resourceTemplates: [
389
+ templates: [
304
390
  {
305
391
  name: "stockGraph",
306
392
  description: "Generates a price chart for a given symbol",
307
- uriTemplate: "stockGraph/{symbol}",
393
+ uri: "stockGraph/{symbol}",
308
394
  parameters: {
309
395
  type: "object",
310
396
  properties: {
@@ -316,7 +402,7 @@ var MCPLocal = class {
316
402
  {
317
403
  name: "stockPriceHistory",
318
404
  description: "Returns price history for a given symbol",
319
- uriTemplate: "stockPriceHistory/{symbol}",
405
+ uri: "stockPriceHistory/{symbol}",
320
406
  parameters: {
321
407
  type: "object",
322
408
  properties: {
@@ -489,361 +575,6 @@ var MCPLocal = class {
489
575
  };
490
576
  }
491
577
  );
492
- this.server.setRequestHandler(
493
- import_zod.z.object({
494
- method: import_zod.z.literal("tools/call"),
495
- params: import_zod.z.object({
496
- name: import_zod.z.string(),
497
- arguments: import_zod.z.any(),
498
- _meta: import_zod.z.object({
499
- progressToken: import_zod.z.number()
500
- }).optional()
501
- })
502
- }),
503
- async (request, extra) => {
504
- const { name, arguments: args } = request.params;
505
- switch (name) {
506
- case "parse":
507
- try {
508
- const parsedMessage = this.parser?.parse(args.fixString);
509
- if (!parsedMessage || parsedMessage.length === 0) {
510
- return {
511
- contents: [
512
- {
513
- type: "text",
514
- text: "Error: Failed to parse FIX string",
515
- uri: "parse"
516
- }
517
- ],
518
- isError: true
519
- };
520
- }
521
- return {
522
- contents: [
523
- {
524
- type: "text",
525
- text: `${parsedMessage[0].description}
526
- ${parsedMessage[0].messageTypeDescription}`,
527
- uri: "parse"
528
- }
529
- ]
530
- };
531
- } catch (error) {
532
- return {
533
- contents: [
534
- {
535
- type: "text",
536
- text: `Error: ${error instanceof Error ? error.message : "Failed to parse FIX string"}`,
537
- uri: "parse"
538
- }
539
- ],
540
- isError: true
541
- };
542
- }
543
- case "parseToJSON":
544
- try {
545
- const parsedMessage = this.parser?.parse(args.fixString);
546
- if (!parsedMessage || parsedMessage.length === 0) {
547
- return {
548
- contents: [
549
- {
550
- type: "text",
551
- text: "Error: Failed to parse FIX string",
552
- uri: "parseToJSON"
553
- }
554
- ],
555
- isError: true
556
- };
557
- }
558
- return {
559
- contents: [
560
- {
561
- type: "text",
562
- text: `${parsedMessage[0].toFIXJSON()}`,
563
- uri: "parseToJSON"
564
- }
565
- ]
566
- };
567
- } catch (error) {
568
- return {
569
- contents: [
570
- {
571
- type: "text",
572
- text: `Error: ${error instanceof Error ? error.message : "Failed to parse FIX string"}`,
573
- uri: "parseToJSON"
574
- }
575
- ],
576
- isError: true
577
- };
578
- }
579
- case "verifyOrder":
580
- try {
581
- this.verifiedOrders.set(args.clOrdID, {
582
- clOrdID: args.clOrdID,
583
- handlInst: args.handlInst,
584
- quantity: Number.parseFloat(args.quantity),
585
- price: Number.parseFloat(args.price),
586
- ordType: args.ordType,
587
- side: args.side,
588
- symbol: args.symbol,
589
- timeInForce: args.timeInForce
590
- });
591
- const ordTypeNames = {
592
- "1": "Market",
593
- "2": "Limit",
594
- "3": "Stop",
595
- "4": "StopLimit",
596
- "5": "MarketOnClose",
597
- "6": "WithOrWithout",
598
- "7": "LimitOrBetter",
599
- "8": "LimitWithOrWithout",
600
- "9": "OnBasis",
601
- A: "OnClose",
602
- B: "LimitOnClose",
603
- C: "ForexMarket",
604
- D: "PreviouslyQuoted",
605
- E: "PreviouslyIndicated",
606
- F: "ForexLimit",
607
- G: "ForexSwap",
608
- H: "ForexPreviouslyQuoted",
609
- I: "Funari",
610
- J: "MarketIfTouched",
611
- K: "MarketWithLeftOverAsLimit",
612
- L: "PreviousFundValuationPoint",
613
- M: "NextFundValuationPoint",
614
- P: "Pegged",
615
- Q: "CounterOrderSelection",
616
- R: "StopOnBidOrOffer",
617
- S: "StopLimitOnBidOrOffer"
618
- };
619
- const sideNames = {
620
- "1": "Buy",
621
- "2": "Sell",
622
- "3": "BuyMinus",
623
- "4": "SellPlus",
624
- "5": "SellShort",
625
- "6": "SellShortExempt",
626
- "7": "Undisclosed",
627
- "8": "Cross",
628
- "9": "CrossShort",
629
- A: "CrossShortExempt",
630
- B: "AsDefined",
631
- C: "Opposite",
632
- D: "Subscribe",
633
- E: "Redeem",
634
- F: "Lend",
635
- G: "Borrow",
636
- H: "SellUndisclosed"
637
- };
638
- const timeInForceNames = {
639
- "0": "Day",
640
- "1": "GoodTillCancel",
641
- "2": "AtTheOpening",
642
- "3": "ImmediateOrCancel",
643
- "4": "FillOrKill",
644
- "5": "GoodTillCrossing",
645
- "6": "GoodTillDate",
646
- "7": "AtTheClose",
647
- "8": "GoodThroughCrossing",
648
- "9": "AtCrossing",
649
- A: "GoodForTime",
650
- B: "GoodForAuction",
651
- C: "GoodForMonth"
652
- };
653
- const handlInstNames = {
654
- "1": "AutomatedExecutionNoIntervention",
655
- "2": "AutomatedExecutionInterventionOK",
656
- "3": "ManualOrder"
657
- };
658
- return {
659
- contents: [
660
- {
661
- type: "text",
662
- text: `VERIFICATION: All parameters valid. Ready to proceed with order execution.
663
-
664
- Parameters verified:
665
- - ClOrdID: ${args.clOrdID}
666
- - HandlInst: ${args.handlInst} (${handlInstNames[args.handlInst]})
667
- - Quantity: ${args.quantity}
668
- - Price: ${args.price}
669
- - OrdType: ${args.ordType} (${ordTypeNames[args.ordType]})
670
- - Side: ${args.side} (${sideNames[args.side]})
671
- - Symbol: ${args.symbol}
672
- - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
673
-
674
- To execute this order, call the executeOrder tool with these exact same parameters.`,
675
- uri: "verifyOrder"
676
- }
677
- ]
678
- };
679
- } catch (error) {
680
- return {
681
- contents: [
682
- {
683
- type: "text",
684
- text: `Error: ${error instanceof Error ? error.message : "Failed to verify order parameters"}`,
685
- uri: "verifyOrder"
686
- }
687
- ],
688
- isError: true
689
- };
690
- }
691
- case "executeOrder":
692
- try {
693
- const verifiedOrder = this.verifiedOrders.get(args.clOrdID);
694
- if (!verifiedOrder) {
695
- return {
696
- contents: [
697
- {
698
- type: "text",
699
- text: `Error: Order ${args.clOrdID} has not been verified. Please call verifyOrder first.`,
700
- uri: "executeOrder"
701
- }
702
- ],
703
- isError: true
704
- };
705
- }
706
- 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) {
707
- return {
708
- contents: [
709
- {
710
- type: "text",
711
- text: "Error: Order parameters do not match the verified order. Please use the exact same parameters that were verified.",
712
- uri: "executeOrder"
713
- }
714
- ],
715
- isError: true
716
- };
717
- }
718
- const response = new Promise((resolve) => {
719
- this.pendingRequests.set(args.clOrdID, resolve);
720
- });
721
- const order = this.parser?.createMessage(
722
- new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.NewOrderSingle),
723
- new import_fixparser.Field(import_fixparser.Fields.MsgSeqNum, this.parser?.getNextTargetMsgSeqNum()),
724
- new import_fixparser.Field(import_fixparser.Fields.SenderCompID, this.parser?.sender),
725
- new import_fixparser.Field(import_fixparser.Fields.TargetCompID, this.parser?.target),
726
- new import_fixparser.Field(import_fixparser.Fields.SendingTime, this.parser?.getTimestamp()),
727
- new import_fixparser.Field(import_fixparser.Fields.ClOrdID, args.clOrdID),
728
- new import_fixparser.Field(import_fixparser.Fields.Side, args.side),
729
- new import_fixparser.Field(import_fixparser.Fields.Symbol, args.symbol),
730
- new import_fixparser.Field(import_fixparser.Fields.OrderQty, Number.parseFloat(args.quantity)),
731
- new import_fixparser.Field(import_fixparser.Fields.Price, Number.parseFloat(args.price)),
732
- new import_fixparser.Field(import_fixparser.Fields.OrdType, args.ordType),
733
- new import_fixparser.Field(import_fixparser.Fields.HandlInst, args.handlInst),
734
- new import_fixparser.Field(import_fixparser.Fields.TimeInForce, args.timeInForce),
735
- new import_fixparser.Field(import_fixparser.Fields.TransactTime, this.parser?.getTimestamp())
736
- );
737
- if (!this.parser?.connected) {
738
- return {
739
- contents: [
740
- {
741
- type: "text",
742
- text: "Error: Not connected. Ignoring message.",
743
- uri: "executeOrder"
744
- }
745
- ],
746
- isError: true
747
- };
748
- }
749
- this.parser?.send(order);
750
- const fixData = await response;
751
- this.verifiedOrders.delete(args.clOrdID);
752
- return {
753
- contents: [
754
- {
755
- type: "text",
756
- 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())}`,
757
- uri: "executeOrder"
758
- }
759
- ]
760
- };
761
- } catch (error) {
762
- return {
763
- contents: [
764
- {
765
- type: "text",
766
- text: `Error: ${error instanceof Error ? error.message : "Failed to execute order"}`,
767
- uri: "executeOrder"
768
- }
769
- ],
770
- isError: true
771
- };
772
- }
773
- case "marketDataRequest":
774
- try {
775
- const response = new Promise((resolve) => {
776
- this.pendingRequests.set(args.mdReqID, resolve);
777
- });
778
- const messageFields = [
779
- new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.MarketDataRequest),
780
- new import_fixparser.Field(import_fixparser.Fields.SenderCompID, this.parser?.sender),
781
- new import_fixparser.Field(import_fixparser.Fields.MsgSeqNum, this.parser?.getNextTargetMsgSeqNum()),
782
- new import_fixparser.Field(import_fixparser.Fields.TargetCompID, this.parser?.target),
783
- new import_fixparser.Field(import_fixparser.Fields.SendingTime, this.parser?.getTimestamp()),
784
- new import_fixparser.Field(import_fixparser.Fields.MDReqID, args.mdReqID),
785
- new import_fixparser.Field(import_fixparser.Fields.SubscriptionRequestType, args.subscriptionRequestType),
786
- new import_fixparser.Field(import_fixparser.Fields.MarketDepth, 0),
787
- new import_fixparser.Field(import_fixparser.Fields.MDUpdateType, args.mdUpdateType)
788
- ];
789
- messageFields.push(new import_fixparser.Field(import_fixparser.Fields.NoRelatedSym, args.symbols.length));
790
- args.symbols.forEach((symbol) => {
791
- messageFields.push(new import_fixparser.Field(import_fixparser.Fields.Symbol, symbol));
792
- });
793
- messageFields.push(new import_fixparser.Field(import_fixparser.Fields.NoMDEntryTypes, args.mdEntryTypes.length));
794
- args.mdEntryTypes.forEach((entryType) => {
795
- messageFields.push(new import_fixparser.Field(import_fixparser.Fields.MDEntryType, entryType));
796
- });
797
- const mdr = this.parser?.createMessage(...messageFields);
798
- if (!this.parser?.connected) {
799
- return {
800
- contents: [
801
- {
802
- type: "text",
803
- text: "Error: Not connected. Ignoring message.",
804
- uri: "marketDataRequest"
805
- }
806
- ],
807
- isError: true
808
- };
809
- }
810
- this.parser?.send(mdr);
811
- const fixData = await response;
812
- return {
813
- contents: [
814
- {
815
- type: "text",
816
- text: `Market data for ${args.symbols.join(", ")}: ${JSON.stringify(fixData.toFIXJSON())}`,
817
- uri: "marketDataRequest"
818
- }
819
- ]
820
- };
821
- } catch (error) {
822
- return {
823
- contents: [
824
- {
825
- type: "text",
826
- text: `Error: ${error instanceof Error ? error.message : "Failed to request market data"}`,
827
- uri: "marketDataRequest"
828
- }
829
- ],
830
- isError: true
831
- };
832
- }
833
- default:
834
- return {
835
- contents: [
836
- {
837
- type: "text",
838
- text: `Tool not found: ${name}`,
839
- uri: name
840
- }
841
- ],
842
- isError: true
843
- };
844
- }
845
- }
846
- );
847
578
  this.server.setRequestHandler(
848
579
  import_zod.z.object({
849
580
  method: import_zod.z.literal("resources/read"),
@@ -893,8 +624,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
893
624
  contents: [
894
625
  {
895
626
  type: "text",
896
- text: `No price data available for ${symbol}`,
897
- uri
627
+ text: `No price data available for ${symbol}`
898
628
  }
899
629
  ]
900
630
  };
@@ -963,8 +693,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
963
693
  contents: [
964
694
  {
965
695
  type: "text",
966
- text: svg,
967
- uri
696
+ text: svg
968
697
  }
969
698
  ]
970
699
  };
@@ -977,8 +706,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
977
706
  contents: [
978
707
  {
979
708
  type: "text",
980
- text: `No price data available for ${symbol}`,
981
- uri
709
+ text: `No price data available for ${symbol}`
982
710
  }
983
711
  ]
984
712
  };
@@ -998,8 +726,7 @@ To execute this order, call the executeOrder tool with these exact same paramete
998
726
  },
999
727
  null,
1000
728
  2
1001
- ),
1002
- uri
729
+ )
1003
730
  }
1004
731
  ]
1005
732
  };
@@ -1017,6 +744,347 @@ To execute this order, call the executeOrder tool with these exact same paramete
1017
744
  }
1018
745
  }
1019
746
  );
747
+ this.server.setRequestHandler(
748
+ import_zod.z.object({
749
+ method: import_zod.z.literal("parse"),
750
+ params: fixStringSchema
751
+ }),
752
+ async (request, extra) => {
753
+ try {
754
+ const args = request.params;
755
+ const parsedMessage = this.parser?.parse(args.fixString);
756
+ if (!parsedMessage || parsedMessage.length === 0) {
757
+ return {
758
+ contents: [{ type: "text", text: "Error: Failed to parse FIX string" }],
759
+ isError: true
760
+ };
761
+ }
762
+ return {
763
+ contents: [
764
+ {
765
+ type: "text",
766
+ text: `${parsedMessage[0].description}
767
+ ${parsedMessage[0].messageTypeDescription}`
768
+ }
769
+ ]
770
+ };
771
+ } catch (error) {
772
+ return {
773
+ contents: [
774
+ {
775
+ type: "text",
776
+ text: `Error: ${error instanceof Error ? error.message : "Failed to parse FIX string"}`
777
+ }
778
+ ],
779
+ isError: true
780
+ };
781
+ }
782
+ }
783
+ );
784
+ this.server.setRequestHandler(
785
+ import_zod.z.object({
786
+ method: import_zod.z.literal("parseToJSON"),
787
+ params: fixStringSchema
788
+ }),
789
+ async (request, extra) => {
790
+ try {
791
+ const args = request.params;
792
+ const parsedMessage = this.parser?.parse(args.fixString);
793
+ if (!parsedMessage || parsedMessage.length === 0) {
794
+ return {
795
+ contents: [{ type: "text", text: "Error: Failed to parse FIX string" }],
796
+ isError: true
797
+ };
798
+ }
799
+ return {
800
+ contents: [
801
+ {
802
+ type: "text",
803
+ text: `${parsedMessage[0].toFIXJSON()}`
804
+ }
805
+ ]
806
+ };
807
+ } catch (error) {
808
+ return {
809
+ contents: [
810
+ {
811
+ type: "text",
812
+ text: `Error: ${error instanceof Error ? error.message : "Failed to parse FIX string"}`
813
+ }
814
+ ],
815
+ isError: true
816
+ };
817
+ }
818
+ }
819
+ );
820
+ this.server.setRequestHandler(
821
+ import_zod.z.object({
822
+ method: import_zod.z.literal("verifyOrder"),
823
+ params: orderSchema
824
+ }),
825
+ async (request, extra) => {
826
+ try {
827
+ const args = request.params;
828
+ this.verifiedOrders.set(args.clOrdID, {
829
+ clOrdID: args.clOrdID,
830
+ handlInst: args.handlInst,
831
+ quantity: Number.parseFloat(args.quantity),
832
+ price: Number.parseFloat(args.price),
833
+ ordType: args.ordType,
834
+ side: args.side,
835
+ symbol: args.symbol,
836
+ timeInForce: args.timeInForce
837
+ });
838
+ const ordTypeNames = {
839
+ "1": "Market",
840
+ "2": "Limit",
841
+ "3": "Stop",
842
+ "4": "StopLimit",
843
+ "5": "MarketOnClose",
844
+ "6": "WithOrWithout",
845
+ "7": "LimitOrBetter",
846
+ "8": "LimitWithOrWithout",
847
+ "9": "OnBasis",
848
+ A: "OnClose",
849
+ B: "LimitOnClose",
850
+ C: "ForexMarket",
851
+ D: "PreviouslyQuoted",
852
+ E: "PreviouslyIndicated",
853
+ F: "ForexLimit",
854
+ G: "ForexSwap",
855
+ H: "ForexPreviouslyQuoted",
856
+ I: "Funari",
857
+ J: "MarketIfTouched",
858
+ K: "MarketWithLeftOverAsLimit",
859
+ L: "PreviousFundValuationPoint",
860
+ M: "NextFundValuationPoint",
861
+ P: "Pegged",
862
+ Q: "CounterOrderSelection",
863
+ R: "StopOnBidOrOffer",
864
+ S: "StopLimitOnBidOrOffer"
865
+ };
866
+ const sideNames = {
867
+ "1": "Buy",
868
+ "2": "Sell",
869
+ "3": "BuyMinus",
870
+ "4": "SellPlus",
871
+ "5": "SellShort",
872
+ "6": "SellShortExempt",
873
+ "7": "Undisclosed",
874
+ "8": "Cross",
875
+ "9": "CrossShort",
876
+ A: "CrossShortExempt",
877
+ B: "AsDefined",
878
+ C: "Opposite",
879
+ D: "Subscribe",
880
+ E: "Redeem",
881
+ F: "Lend",
882
+ G: "Borrow",
883
+ H: "SellUndisclosed"
884
+ };
885
+ const timeInForceNames = {
886
+ "0": "Day",
887
+ "1": "GoodTillCancel",
888
+ "2": "AtTheOpening",
889
+ "3": "ImmediateOrCancel",
890
+ "4": "FillOrKill",
891
+ "5": "GoodTillCrossing",
892
+ "6": "GoodTillDate",
893
+ "7": "AtTheClose",
894
+ "8": "GoodThroughCrossing",
895
+ "9": "AtCrossing",
896
+ A: "GoodForTime",
897
+ B: "GoodForAuction",
898
+ C: "GoodForMonth"
899
+ };
900
+ const handlInstNames = {
901
+ "1": "AutomatedExecutionNoIntervention",
902
+ "2": "AutomatedExecutionInterventionOK",
903
+ "3": "ManualOrder"
904
+ };
905
+ return {
906
+ contents: [
907
+ {
908
+ type: "text",
909
+ text: `VERIFICATION: All parameters valid. Ready to proceed with order execution.
910
+
911
+ Parameters verified:
912
+ - ClOrdID: ${args.clOrdID}
913
+ - HandlInst: ${args.handlInst} (${handlInstNames[args.handlInst]})
914
+ - Quantity: ${args.quantity}
915
+ - Price: ${args.price}
916
+ - OrdType: ${args.ordType} (${ordTypeNames[args.ordType]})
917
+ - Side: ${args.side} (${sideNames[args.side]})
918
+ - Symbol: ${args.symbol}
919
+ - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
920
+
921
+ To execute this order, call the executeOrder tool with these exact same parameters.`
922
+ }
923
+ ]
924
+ };
925
+ } catch (error) {
926
+ return {
927
+ contents: [
928
+ {
929
+ type: "text",
930
+ text: `Error: ${error instanceof Error ? error.message : "Failed to verify order parameters"}`
931
+ }
932
+ ],
933
+ isError: true
934
+ };
935
+ }
936
+ }
937
+ );
938
+ this.server.setRequestHandler(
939
+ import_zod.z.object({
940
+ method: import_zod.z.literal("executeOrder"),
941
+ params: orderSchema
942
+ }),
943
+ async (request, extra) => {
944
+ try {
945
+ const args = request.params;
946
+ const verifiedOrder = this.verifiedOrders.get(args.clOrdID);
947
+ if (!verifiedOrder) {
948
+ return {
949
+ contents: [
950
+ {
951
+ type: "text",
952
+ text: `Error: Order ${args.clOrdID} has not been verified. Please call verifyOrder first.`
953
+ }
954
+ ],
955
+ isError: true
956
+ };
957
+ }
958
+ 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
+ return {
960
+ contents: [
961
+ {
962
+ type: "text",
963
+ text: "Error: Order parameters do not match the verified order. Please use the exact same parameters that were verified."
964
+ }
965
+ ],
966
+ isError: true
967
+ };
968
+ }
969
+ const response = new Promise((resolve) => {
970
+ this.pendingRequests.set(args.clOrdID, resolve);
971
+ });
972
+ const order = this.parser?.createMessage(
973
+ new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.NewOrderSingle),
974
+ new import_fixparser.Field(import_fixparser.Fields.MsgSeqNum, this.parser?.getNextTargetMsgSeqNum()),
975
+ new import_fixparser.Field(import_fixparser.Fields.SenderCompID, this.parser?.sender),
976
+ new import_fixparser.Field(import_fixparser.Fields.TargetCompID, this.parser?.target),
977
+ new import_fixparser.Field(import_fixparser.Fields.SendingTime, this.parser?.getTimestamp()),
978
+ new import_fixparser.Field(import_fixparser.Fields.ClOrdID, args.clOrdID),
979
+ new import_fixparser.Field(import_fixparser.Fields.Side, args.side),
980
+ new import_fixparser.Field(import_fixparser.Fields.Symbol, args.symbol),
981
+ new import_fixparser.Field(import_fixparser.Fields.OrderQty, Number.parseFloat(args.quantity)),
982
+ new import_fixparser.Field(import_fixparser.Fields.Price, Number.parseFloat(args.price)),
983
+ new import_fixparser.Field(import_fixparser.Fields.OrdType, args.ordType),
984
+ new import_fixparser.Field(import_fixparser.Fields.HandlInst, args.handlInst),
985
+ new import_fixparser.Field(import_fixparser.Fields.TimeInForce, args.timeInForce),
986
+ new import_fixparser.Field(import_fixparser.Fields.TransactTime, this.parser?.getTimestamp())
987
+ );
988
+ if (!this.parser?.connected) {
989
+ return {
990
+ contents: [
991
+ {
992
+ type: "text",
993
+ text: "Error: Not connected. Ignoring message."
994
+ }
995
+ ],
996
+ isError: true
997
+ };
998
+ }
999
+ this.parser?.send(order);
1000
+ const fixData = await response;
1001
+ this.verifiedOrders.delete(args.clOrdID);
1002
+ return {
1003
+ contents: [
1004
+ {
1005
+ type: "text",
1006
+ 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())}`
1007
+ }
1008
+ ]
1009
+ };
1010
+ } catch (error) {
1011
+ return {
1012
+ contents: [
1013
+ {
1014
+ type: "text",
1015
+ text: `Error: ${error instanceof Error ? error.message : "Failed to execute order"}`
1016
+ }
1017
+ ],
1018
+ isError: true
1019
+ };
1020
+ }
1021
+ }
1022
+ );
1023
+ this.server.setRequestHandler(
1024
+ import_zod.z.object({
1025
+ method: import_zod.z.literal("marketDataRequest"),
1026
+ params: marketDataRequestSchema
1027
+ }),
1028
+ async (request, extra) => {
1029
+ try {
1030
+ const args = request.params;
1031
+ const response = new Promise((resolve) => {
1032
+ this.pendingRequests.set(args.mdReqID, resolve);
1033
+ });
1034
+ const messageFields = [
1035
+ new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.MarketDataRequest),
1036
+ new import_fixparser.Field(import_fixparser.Fields.SenderCompID, this.parser?.sender),
1037
+ new import_fixparser.Field(import_fixparser.Fields.MsgSeqNum, this.parser?.getNextTargetMsgSeqNum()),
1038
+ new import_fixparser.Field(import_fixparser.Fields.TargetCompID, this.parser?.target),
1039
+ new import_fixparser.Field(import_fixparser.Fields.SendingTime, this.parser?.getTimestamp()),
1040
+ new import_fixparser.Field(import_fixparser.Fields.MDReqID, args.mdReqID),
1041
+ new import_fixparser.Field(import_fixparser.Fields.SubscriptionRequestType, args.subscriptionRequestType),
1042
+ new import_fixparser.Field(import_fixparser.Fields.MarketDepth, 0),
1043
+ new import_fixparser.Field(import_fixparser.Fields.MDUpdateType, args.mdUpdateType)
1044
+ ];
1045
+ messageFields.push(new import_fixparser.Field(import_fixparser.Fields.NoRelatedSym, args.symbols.length));
1046
+ args.symbols.forEach((symbol) => {
1047
+ messageFields.push(new import_fixparser.Field(import_fixparser.Fields.Symbol, symbol));
1048
+ });
1049
+ messageFields.push(new import_fixparser.Field(import_fixparser.Fields.NoMDEntryTypes, args.mdEntryTypes.length));
1050
+ args.mdEntryTypes.forEach((entryType) => {
1051
+ messageFields.push(new import_fixparser.Field(import_fixparser.Fields.MDEntryType, entryType));
1052
+ });
1053
+ const mdr = this.parser?.createMessage(...messageFields);
1054
+ if (!this.parser?.connected) {
1055
+ return {
1056
+ contents: [
1057
+ {
1058
+ type: "text",
1059
+ text: "Error: Not connected. Ignoring message."
1060
+ }
1061
+ ],
1062
+ isError: true
1063
+ };
1064
+ }
1065
+ this.parser?.send(mdr);
1066
+ const fixData = await response;
1067
+ return {
1068
+ contents: [
1069
+ {
1070
+ type: "text",
1071
+ text: `Market data for ${args.symbols.join(", ")}: ${JSON.stringify(fixData.toFIXJSON())}`
1072
+ }
1073
+ ]
1074
+ };
1075
+ } catch (error) {
1076
+ return {
1077
+ contents: [
1078
+ {
1079
+ type: "text",
1080
+ text: `Error: ${error instanceof Error ? error.message : "Failed to request market data"}`
1081
+ }
1082
+ ],
1083
+ isError: true
1084
+ };
1085
+ }
1086
+ }
1087
+ );
1020
1088
  process.on("SIGINT", async () => {
1021
1089
  await this.server.close();
1022
1090
  process.exit(0);