fixparser-plugin-mcp 9.1.7-be52c470 → 9.1.7-bfafe1e3

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.
@@ -1,51 +1,9 @@
1
1
  // src/MCPLocal.ts
2
2
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
4
5
  import { z } from "zod";
5
6
 
6
- // src/MCPBase.ts
7
- var MCPBase = class {
8
- /**
9
- * Optional logger instance for diagnostics and output.
10
- * @protected
11
- */
12
- logger;
13
- /**
14
- * FIXParser instance, set during plugin register().
15
- * @protected
16
- */
17
- parser;
18
- /**
19
- * Called when server is setup and listening.
20
- * @protected
21
- */
22
- onReady = void 0;
23
- /**
24
- * Map to store verified orders before execution
25
- * @protected
26
- */
27
- verifiedOrders = /* @__PURE__ */ new Map();
28
- /**
29
- * Map to store pending market data requests
30
- * @protected
31
- */
32
- pendingRequests = /* @__PURE__ */ new Map();
33
- /**
34
- * Map to store market data prices
35
- * @protected
36
- */
37
- marketDataPrices = /* @__PURE__ */ new Map();
38
- /**
39
- * Maximum number of price history entries to keep per symbol
40
- * @protected
41
- */
42
- MAX_PRICE_HISTORY = 1e5;
43
- constructor({ logger, onReady }) {
44
- this.logger = logger;
45
- this.onReady = onReady;
46
- }
47
- };
48
-
49
7
  // src/schemas/schemas.ts
50
8
  var toolSchemas = {
51
9
  parse: {
@@ -129,7 +87,7 @@ var toolSchemas = {
129
87
  }
130
88
  },
131
89
  executeOrder: {
132
- description: "Executes a verified order. verifyOrder must be called before executeOrder.",
90
+ description: "Executes a verified order. verifyOrder must be called before executeOrder. user has to explicitly allow executeOrder.",
133
91
  schema: {
134
92
  type: "object",
135
93
  properties: {
@@ -360,15 +318,14 @@ var createGetStockGraphHandler = (marketDataPrices) => {
360
318
  };
361
319
  }
362
320
  const chart = new QuickChart();
363
- chart.setWidth(1200);
364
- chart.setHeight(600);
365
- chart.setBackgroundColor("transparent");
321
+ chart.setWidth(600);
322
+ chart.setHeight(300);
366
323
  const labels = priceHistory.map((point) => new Date(point.timestamp).toLocaleTimeString());
367
324
  const bidData = priceHistory.map((point) => point.bid);
368
325
  const offerData = priceHistory.map((point) => point.offer);
369
326
  const spreadData = priceHistory.map((point) => point.spread);
370
327
  const volumeData = priceHistory.map((point) => point.volume);
371
- const config = {
328
+ chart.setConfig({
372
329
  type: "line",
373
330
  data: {
374
331
  labels,
@@ -403,37 +360,63 @@ var createGetStockGraphHandler = (marketDataPrices) => {
403
360
  borderColor: "#007bff",
404
361
  backgroundColor: "rgba(0, 123, 255, 0.1)",
405
362
  fill: true,
406
- tension: 0.4
363
+ tension: 0.4,
364
+ yAxisID: "volume"
407
365
  }
408
366
  ]
409
367
  },
410
368
  options: {
411
- responsive: true,
412
369
  plugins: {
413
370
  title: {
414
371
  display: true,
415
- text: `${symbol} Market Data`
372
+ text: `${symbol} Market Data`,
373
+ font: {
374
+ size: 16,
375
+ weight: "bold"
376
+ }
377
+ },
378
+ legend: {
379
+ display: true
416
380
  }
417
381
  },
418
382
  scales: {
419
383
  y: {
420
- beginAtZero: false
384
+ beginAtZero: false,
385
+ grid: {
386
+ color: "#e9ecef"
387
+ }
388
+ },
389
+ volume: {
390
+ position: "right",
391
+ beginAtZero: true,
392
+ grid: {
393
+ display: false
394
+ }
395
+ },
396
+ x: {
397
+ grid: {
398
+ display: false
399
+ }
421
400
  }
422
401
  }
423
402
  }
424
- };
425
- chart.setConfig(config);
403
+ });
426
404
  const imageBuffer = await chart.toBinary();
427
- const base64 = imageBuffer.toString("base64");
405
+ const base64Image = imageBuffer.toString("base64");
406
+ console.log("-------------------------------------------");
407
+ console.log("b64", base64Image);
408
+ console.log("-------------------------------------------");
428
409
  return {
429
410
  content: [
430
411
  {
431
- type: "resource",
432
- resource: {
433
- uri: "resource://graph",
434
- mimeType: "image/png",
435
- blob: base64
436
- }
412
+ type: "image",
413
+ image: {
414
+ source: {
415
+ data: base64Image
416
+ }
417
+ },
418
+ uri: "getStockGraph",
419
+ mimeType: "image/png"
437
420
  }
438
421
  ]
439
422
  };
@@ -802,86 +785,9 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
802
785
  getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
803
786
  });
804
787
 
805
- // src/utils/messageHandler.ts
806
- import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
807
- function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
808
- parser.logger.log({
809
- level: "info",
810
- message: `MCP Server received message: ${message.messageType}: ${message.description}`
811
- });
812
- const msgType = message.messageType;
813
- if (msgType === Messages3.MarketDataSnapshotFullRefresh) {
814
- const symbol = message.getField(Fields3.Symbol)?.value;
815
- const entries = message.getField(Fields3.NoMDEntries)?.value;
816
- let bid = 0;
817
- let offer = 0;
818
- let volume = 0;
819
- const entryTypes = message.getFields(Fields3.MDEntryType);
820
- const entryPrices = message.getFields(Fields3.MDEntryPx);
821
- const entrySizes = message.getFields(Fields3.MDEntrySize);
822
- if (entryTypes && entryPrices && entrySizes) {
823
- for (let i = 0; i < entries; i++) {
824
- const entryType = entryTypes[i]?.value;
825
- const entryPrice = Number.parseFloat(entryPrices[i]?.value);
826
- const entrySize = Number.parseFloat(entrySizes[i]?.value);
827
- if (entryType === MDEntryType2.Bid) {
828
- bid = entryPrice;
829
- } else if (entryType === MDEntryType2.Offer) {
830
- offer = entryPrice;
831
- }
832
- volume += entrySize;
833
- }
834
- }
835
- const spread = offer - bid;
836
- const timestamp = Date.now();
837
- const data = {
838
- timestamp,
839
- bid,
840
- offer,
841
- spread,
842
- volume
843
- };
844
- if (!marketDataPrices.has(symbol)) {
845
- marketDataPrices.set(symbol, []);
846
- }
847
- const prices = marketDataPrices.get(symbol);
848
- prices.push(data);
849
- if (prices.length > maxPriceHistory) {
850
- prices.splice(0, prices.length - maxPriceHistory);
851
- }
852
- onPriceUpdate?.(symbol, data);
853
- } else if (msgType === Messages3.ExecutionReport) {
854
- const reqId = message.getField(Fields3.ClOrdID)?.value;
855
- const callback = pendingRequests.get(reqId);
856
- if (callback) {
857
- callback(message);
858
- pendingRequests.delete(reqId);
859
- }
860
- }
861
- }
862
-
863
788
  // src/MCPLocal.ts
864
- var MCPLocal = class extends MCPBase {
865
- /**
866
- * Map to store verified orders before execution
867
- * @private
868
- */
869
- verifiedOrders = /* @__PURE__ */ new Map();
870
- /**
871
- * Map to store pending requests and their callbacks
872
- * @private
873
- */
874
- pendingRequests = /* @__PURE__ */ new Map();
875
- /**
876
- * Map to store market data prices for each symbol
877
- * @private
878
- */
879
- marketDataPrices = /* @__PURE__ */ new Map();
880
- /**
881
- * Maximum number of price points to store per symbol
882
- * @private
883
- */
884
- MAX_PRICE_HISTORY = 1e5;
789
+ var MCPLocal = class {
790
+ parser;
885
791
  server = new Server(
886
792
  {
887
793
  name: "fixparser",
@@ -903,13 +809,90 @@ var MCPLocal = class extends MCPBase {
903
809
  }
904
810
  );
905
811
  transport = new StdioServerTransport();
812
+ onReady = void 0;
813
+ pendingRequests = /* @__PURE__ */ new Map();
814
+ verifiedOrders = /* @__PURE__ */ new Map();
815
+ marketDataPrices = /* @__PURE__ */ new Map();
816
+ MAX_PRICE_HISTORY = 1e5;
817
+ // Maximum number of price points to store per symbol
906
818
  constructor({ logger, onReady }) {
907
- super({ logger, onReady });
819
+ if (onReady) this.onReady = onReady;
908
820
  }
909
821
  async register(parser) {
910
822
  this.parser = parser;
911
823
  this.parser.addOnMessageCallback((message) => {
912
- handleMessage(message, this.parser, this.pendingRequests, this.marketDataPrices, this.MAX_PRICE_HISTORY);
824
+ this.parser?.logger.log({
825
+ level: "info",
826
+ message: `MCP Server received message: ${message.messageType}: ${message.description}`
827
+ });
828
+ const msgType = message.messageType;
829
+ if (msgType === Messages3.MarketDataSnapshotFullRefresh || msgType === Messages3.ExecutionReport || msgType === Messages3.Reject || msgType === Messages3.MarketDataIncrementalRefresh) {
830
+ this.parser?.logger.log({
831
+ level: "info",
832
+ message: `MCP Server handling message type: ${msgType}`
833
+ });
834
+ let id;
835
+ if (msgType === Messages3.MarketDataIncrementalRefresh || msgType === Messages3.MarketDataSnapshotFullRefresh) {
836
+ const symbol = message.getField(Fields3.Symbol);
837
+ const entryType = message.getField(Fields3.MDEntryType);
838
+ const price = message.getField(Fields3.MDEntryPx);
839
+ const size = message.getField(Fields3.MDEntrySize);
840
+ const timestamp = message.getField(Fields3.MDEntryTime)?.value || Date.now();
841
+ if (symbol?.value && price?.value) {
842
+ const symbolStr = String(symbol.value);
843
+ const priceNum = Number(price.value);
844
+ const sizeNum = size?.value ? Number(size.value) : 0;
845
+ const priceHistory = this.marketDataPrices.get(symbolStr) || [];
846
+ const lastEntry = priceHistory[priceHistory.length - 1] || {
847
+ timestamp: 0,
848
+ bid: 0,
849
+ offer: 0,
850
+ spread: 0,
851
+ volume: 0
852
+ };
853
+ const newEntry = {
854
+ timestamp: Number(timestamp),
855
+ bid: entryType?.value === MDEntryType2.Bid ? priceNum : lastEntry.bid,
856
+ offer: entryType?.value === MDEntryType2.Offer ? priceNum : lastEntry.offer,
857
+ spread: entryType?.value === MDEntryType2.Offer ? priceNum - lastEntry.bid : entryType?.value === MDEntryType2.Bid ? lastEntry.offer - priceNum : lastEntry.spread,
858
+ volume: entryType?.value === MDEntryType2.TradeVolume ? sizeNum : lastEntry.volume
859
+ };
860
+ priceHistory.push(newEntry);
861
+ if (priceHistory.length > this.MAX_PRICE_HISTORY) {
862
+ priceHistory.shift();
863
+ }
864
+ this.marketDataPrices.set(symbolStr, priceHistory);
865
+ this.parser?.logger.log({
866
+ level: "info",
867
+ message: `MCP Server added ${symbol}: ${JSON.stringify(newEntry)}`
868
+ });
869
+ this.server.notification({
870
+ method: "priceUpdate",
871
+ params: {
872
+ symbol: symbolStr,
873
+ ...newEntry
874
+ }
875
+ });
876
+ }
877
+ }
878
+ if (msgType === Messages3.MarketDataSnapshotFullRefresh) {
879
+ const mdReqID = message.getField(Fields3.MDReqID);
880
+ if (mdReqID) id = String(mdReqID.value);
881
+ } else if (msgType === Messages3.ExecutionReport) {
882
+ const clOrdID = message.getField(Fields3.ClOrdID);
883
+ if (clOrdID) id = String(clOrdID.value);
884
+ } else if (msgType === Messages3.Reject) {
885
+ const refSeqNum = message.getField(Fields3.RefSeqNum);
886
+ if (refSeqNum) id = String(refSeqNum.value);
887
+ }
888
+ if (id) {
889
+ const callback = this.pendingRequests.get(id);
890
+ if (callback) {
891
+ callback(message);
892
+ this.pendingRequests.delete(id);
893
+ }
894
+ }
895
+ }
913
896
  });
914
897
  this.addWorkflows();
915
898
  await this.server.connect(this.transport);
@@ -924,15 +907,18 @@ var MCPLocal = class extends MCPBase {
924
907
  if (!this.server) {
925
908
  return;
926
909
  }
927
- this.server.setRequestHandler(z.object({ method: z.literal("tools/list") }), async () => {
928
- return {
929
- tools: Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
930
- name,
931
- description,
932
- inputSchema: schema
933
- }))
934
- };
935
- });
910
+ this.server.setRequestHandler(
911
+ z.object({ method: z.literal("tools/list") }),
912
+ async (request, extra) => {
913
+ return {
914
+ tools: Object.entries(toolSchemas).map(([name, { description, schema }]) => ({
915
+ name,
916
+ description,
917
+ inputSchema: schema
918
+ }))
919
+ };
920
+ }
921
+ );
936
922
  this.server.setRequestHandler(
937
923
  z.object({
938
924
  method: z.literal("tools/call"),
@@ -944,7 +930,7 @@ var MCPLocal = class extends MCPBase {
944
930
  }).optional()
945
931
  })
946
932
  }),
947
- async (request) => {
933
+ async (request, extra) => {
948
934
  const { name, arguments: args } = request.params;
949
935
  const toolHandlers = createToolHandlers(
950
936
  this.parser,