medusa-plugin-statistics 0.1.0 → 0.1.1

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.
@@ -389,220 +389,6 @@ const WIDGETS = [
389
389
  component: LowStockWidget
390
390
  }
391
391
  ];
392
- const baseUrl = "";
393
- let rpcId = 1;
394
- let mcpSessionId = null;
395
- async function mcpRequest(method, params) {
396
- const headers = {
397
- "Content-Type": "application/json",
398
- Accept: "application/json, text/event-stream"
399
- };
400
- if (mcpSessionId) {
401
- headers["mcp-session-id"] = mcpSessionId;
402
- }
403
- const res = await fetch(`${baseUrl}/admin/mcp`, {
404
- method: "POST",
405
- credentials: "include",
406
- headers,
407
- body: JSON.stringify({
408
- jsonrpc: "2.0",
409
- id: rpcId++,
410
- method,
411
- params
412
- })
413
- });
414
- const newSessionId = res.headers.get("mcp-session-id");
415
- if (newSessionId) {
416
- mcpSessionId = newSessionId;
417
- }
418
- if (!res.ok) {
419
- const text = await res.text();
420
- throw new Error(`MCP error ${res.status}: ${text}`);
421
- }
422
- return res.json();
423
- }
424
- async function mcpInitialize() {
425
- mcpSessionId = null;
426
- return mcpRequest("initialize", {
427
- protocolVersion: "2025-03-26",
428
- capabilities: {},
429
- clientInfo: { name: "medusa-admin-chat", version: "1.0.0" }
430
- });
431
- }
432
- async function mcpListTools() {
433
- var _a;
434
- const res = await mcpRequest("tools/list", {});
435
- return ((_a = res == null ? void 0 : res.result) == null ? void 0 : _a.tools) ?? (res == null ? void 0 : res.tools) ?? [];
436
- }
437
- async function mcpCallTool(name, args) {
438
- var _a;
439
- const res = await mcpRequest("tools/call", { name, arguments: args });
440
- const content = ((_a = res == null ? void 0 : res.result) == null ? void 0 : _a.content) ?? (res == null ? void 0 : res.content) ?? [];
441
- return content.map((c) => c.text ?? JSON.stringify(c)).join("\n");
442
- }
443
- const McpQuery = () => {
444
- var _a, _b;
445
- const [open, setOpen] = react.useState(false);
446
- const [tools, setTools] = react.useState([]);
447
- const [selectedToolName, setSelectedToolName] = react.useState("");
448
- const [paramValues, setParamValues] = react.useState({});
449
- const [messages, setMessages] = react.useState([]);
450
- const [loading, setLoading] = react.useState(false);
451
- const [initialized, setInitialized] = react.useState(false);
452
- const messagesEndRef = react.useRef(null);
453
- const selectedTool = tools.find((t) => t.name === selectedToolName) ?? null;
454
- react.useEffect(() => {
455
- var _a2;
456
- (_a2 = messagesEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth" });
457
- }, [messages]);
458
- const handleOpen = async (isOpen) => {
459
- setOpen(isOpen);
460
- if (isOpen && !initialized) {
461
- try {
462
- await mcpInitialize();
463
- const toolList = await mcpListTools();
464
- setTools(toolList);
465
- setInitialized(true);
466
- } catch (err) {
467
- console.error("[MCP] Connection error:", err);
468
- setMessages([{ role: "assistant", content: "Failed to connect to MCP server." }]);
469
- }
470
- }
471
- };
472
- const handleSelectTool = (value) => {
473
- setSelectedToolName(value);
474
- setParamValues({});
475
- };
476
- const handleExecute = async () => {
477
- var _a2;
478
- if (!selectedTool) return;
479
- setLoading(true);
480
- const args = {};
481
- const props = ((_a2 = selectedTool.inputSchema) == null ? void 0 : _a2.properties) ?? {};
482
- for (const [key, schema] of Object.entries(props)) {
483
- const raw = paramValues[key];
484
- if (raw === void 0 || raw === "") continue;
485
- if (schema.type === "number" || schema.type === "integer") {
486
- args[key] = Number(raw);
487
- } else if (schema.type === "array") {
488
- try {
489
- args[key] = JSON.parse(raw);
490
- } catch {
491
- args[key] = raw.split(",").map((s) => s.trim());
492
- }
493
- } else if (schema.type === "object") {
494
- try {
495
- args[key] = JSON.parse(raw);
496
- } catch {
497
- args[key] = raw;
498
- }
499
- } else {
500
- args[key] = raw;
501
- }
502
- }
503
- setMessages((prev) => [
504
- ...prev,
505
- { role: "user", content: `${selectedTool.name}(${JSON.stringify(args)})` }
506
- ]);
507
- try {
508
- const result = await mcpCallTool(selectedTool.name, args);
509
- setMessages((prev) => [...prev, { role: "assistant", content: result }]);
510
- } catch (err) {
511
- setMessages((prev) => [
512
- ...prev,
513
- { role: "assistant", content: `Error: ${err.message ?? "Unknown error"}` }
514
- ]);
515
- }
516
- setLoading(false);
517
- setSelectedToolName("");
518
- setParamValues({});
519
- };
520
- const allParams = selectedTool ? [
521
- ...Object.entries(((_a = selectedTool.inputSchema) == null ? void 0 : _a.properties) ?? {}).filter(
522
- ([key]) => {
523
- var _a2;
524
- return (((_a2 = selectedTool.inputSchema) == null ? void 0 : _a2.required) ?? []).includes(key);
525
- }
526
- ),
527
- ...Object.entries(((_b = selectedTool.inputSchema) == null ? void 0 : _b.properties) ?? {}).filter(
528
- ([key]) => {
529
- var _a2;
530
- return !(((_a2 = selectedTool.inputSchema) == null ? void 0 : _a2.required) ?? []).includes(key);
531
- }
532
- )
533
- ] : [];
534
- return /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer, { open, onOpenChange: handleOpen, children: [
535
- /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", children: [
536
- /* @__PURE__ */ jsxRuntime.jsx(icons.ChatBubbleLeftRight, { className: "mr-1" }),
537
- "Query Data"
538
- ] }) }),
539
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
540
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Header, { children: [
541
- /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: "Query Data" }),
542
- /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Description, { children: "Run queries against your store data using MCP tools." })
543
- ] }),
544
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Body, { className: "flex flex-col gap-4 overflow-hidden", children: [
545
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
546
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: selectedToolName, onValueChange: handleSelectTool, children: [
547
- /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Select a tool..." }) }),
548
- /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: tools.map((tool) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: tool.name, children: tool.name }, tool.name)) })
549
- ] }),
550
- selectedTool && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
551
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: selectedTool.description }),
552
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2 items-end", children: [
553
- allParams.map(([key, schema]) => {
554
- var _a2;
555
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
556
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-subtle", children: [
557
- key,
558
- (((_a2 = selectedTool.inputSchema) == null ? void 0 : _a2.required) ?? []).includes(key) ? " *" : ""
559
- ] }),
560
- /* @__PURE__ */ jsxRuntime.jsx(
561
- ui.Input,
562
- {
563
- size: "small",
564
- placeholder: schema.description ?? key,
565
- value: paramValues[key] ?? "",
566
- onChange: (e) => setParamValues((prev) => ({ ...prev, [key]: e.target.value }))
567
- }
568
- )
569
- ] }, key);
570
- }),
571
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", onClick: handleExecute, disabled: loading, children: "Run" })
572
- ] })
573
- ] })
574
- ] }),
575
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto flex flex-col gap-2 min-h-0", children: [
576
- messages.map(
577
- (msg, i) => msg.role === "user" ? /* @__PURE__ */ jsxRuntime.jsx(
578
- "div",
579
- {
580
- className: "max-w-[90%] self-end rounded-lg px-3 py-2 text-xs bg-ui-bg-subtle text-ui-fg-base",
581
- children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap font-mono break-all", children: msg.content })
582
- },
583
- i
584
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "self-start w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
585
- ui.CodeBlock,
586
- {
587
- snippets: [
588
- {
589
- label: "Result",
590
- language: "json",
591
- code: msg.content,
592
- hideLineNumbers: true
593
- }
594
- ],
595
- children: /* @__PURE__ */ jsxRuntime.jsx(ui.CodeBlock.Body, { className: "text-xs [&_code]:text-xs" })
596
- }
597
- ) }, i)
598
- ),
599
- loading && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Running..." }),
600
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
601
- ] })
602
- ] })
603
- ] })
604
- ] });
605
- };
606
392
  const config = adminSdk.defineRouteConfig({
607
393
  label: "Statistics",
608
394
  icon: icons.ChartBar,
@@ -722,8 +508,7 @@ const StatisticsPage = () => {
722
508
  editMode ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
723
509
  /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", onClick: () => setEditMode(false), children: "Cancel" }),
724
510
  /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", onClick: handleSaveLayout, children: "Save Layout" })
725
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", onClick: () => setEditMode(true), children: "Customize" }),
726
- /* @__PURE__ */ jsxRuntime.jsx(McpQuery, {})
511
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", onClick: () => setEditMode(true), children: "Customize" })
727
512
  ] })
728
513
  ] }) }),
729
514
  /* @__PURE__ */ jsxRuntime.jsx("div", { ref: gridRef, className: editMode ? "ring-2 ring-ui-border-interactive ring-offset-2 rounded-lg" : "", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading statistics..." }) }) : gridMounted && /* @__PURE__ */ jsxRuntime.jsx(
@@ -1,8 +1,8 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { useState, useRef, useEffect, useCallback, useMemo } from "react";
2
+ import { useState, useEffect, useCallback, useMemo } from "react";
3
3
  import { defineRouteConfig } from "@medusajs/admin-sdk";
4
- import { XCircle, ExclamationCircle, ChatBubbleLeftRight, ChartBar } from "@medusajs/icons";
5
- import { Container, Heading, Text, Badge, Drawer, Button, Select, Input, CodeBlock, toast } from "@medusajs/ui";
4
+ import { XCircle, ExclamationCircle, ChartBar } from "@medusajs/icons";
5
+ import { Container, Heading, Text, Badge, Button, toast } from "@medusajs/ui";
6
6
  import { useContainerWidth, ResponsiveGridLayout, verticalCompactor } from "react-grid-layout";
7
7
  import "react-grid-layout/css/styles.css";
8
8
  import { useQuery, useQueryClient, useMutation } from "@tanstack/react-query";
@@ -386,220 +386,6 @@ const WIDGETS = [
386
386
  component: LowStockWidget
387
387
  }
388
388
  ];
389
- const baseUrl = "";
390
- let rpcId = 1;
391
- let mcpSessionId = null;
392
- async function mcpRequest(method, params) {
393
- const headers = {
394
- "Content-Type": "application/json",
395
- Accept: "application/json, text/event-stream"
396
- };
397
- if (mcpSessionId) {
398
- headers["mcp-session-id"] = mcpSessionId;
399
- }
400
- const res = await fetch(`${baseUrl}/admin/mcp`, {
401
- method: "POST",
402
- credentials: "include",
403
- headers,
404
- body: JSON.stringify({
405
- jsonrpc: "2.0",
406
- id: rpcId++,
407
- method,
408
- params
409
- })
410
- });
411
- const newSessionId = res.headers.get("mcp-session-id");
412
- if (newSessionId) {
413
- mcpSessionId = newSessionId;
414
- }
415
- if (!res.ok) {
416
- const text = await res.text();
417
- throw new Error(`MCP error ${res.status}: ${text}`);
418
- }
419
- return res.json();
420
- }
421
- async function mcpInitialize() {
422
- mcpSessionId = null;
423
- return mcpRequest("initialize", {
424
- protocolVersion: "2025-03-26",
425
- capabilities: {},
426
- clientInfo: { name: "medusa-admin-chat", version: "1.0.0" }
427
- });
428
- }
429
- async function mcpListTools() {
430
- var _a;
431
- const res = await mcpRequest("tools/list", {});
432
- return ((_a = res == null ? void 0 : res.result) == null ? void 0 : _a.tools) ?? (res == null ? void 0 : res.tools) ?? [];
433
- }
434
- async function mcpCallTool(name, args) {
435
- var _a;
436
- const res = await mcpRequest("tools/call", { name, arguments: args });
437
- const content = ((_a = res == null ? void 0 : res.result) == null ? void 0 : _a.content) ?? (res == null ? void 0 : res.content) ?? [];
438
- return content.map((c) => c.text ?? JSON.stringify(c)).join("\n");
439
- }
440
- const McpQuery = () => {
441
- var _a, _b;
442
- const [open, setOpen] = useState(false);
443
- const [tools, setTools] = useState([]);
444
- const [selectedToolName, setSelectedToolName] = useState("");
445
- const [paramValues, setParamValues] = useState({});
446
- const [messages, setMessages] = useState([]);
447
- const [loading, setLoading] = useState(false);
448
- const [initialized, setInitialized] = useState(false);
449
- const messagesEndRef = useRef(null);
450
- const selectedTool = tools.find((t) => t.name === selectedToolName) ?? null;
451
- useEffect(() => {
452
- var _a2;
453
- (_a2 = messagesEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth" });
454
- }, [messages]);
455
- const handleOpen = async (isOpen) => {
456
- setOpen(isOpen);
457
- if (isOpen && !initialized) {
458
- try {
459
- await mcpInitialize();
460
- const toolList = await mcpListTools();
461
- setTools(toolList);
462
- setInitialized(true);
463
- } catch (err) {
464
- console.error("[MCP] Connection error:", err);
465
- setMessages([{ role: "assistant", content: "Failed to connect to MCP server." }]);
466
- }
467
- }
468
- };
469
- const handleSelectTool = (value) => {
470
- setSelectedToolName(value);
471
- setParamValues({});
472
- };
473
- const handleExecute = async () => {
474
- var _a2;
475
- if (!selectedTool) return;
476
- setLoading(true);
477
- const args = {};
478
- const props = ((_a2 = selectedTool.inputSchema) == null ? void 0 : _a2.properties) ?? {};
479
- for (const [key, schema] of Object.entries(props)) {
480
- const raw = paramValues[key];
481
- if (raw === void 0 || raw === "") continue;
482
- if (schema.type === "number" || schema.type === "integer") {
483
- args[key] = Number(raw);
484
- } else if (schema.type === "array") {
485
- try {
486
- args[key] = JSON.parse(raw);
487
- } catch {
488
- args[key] = raw.split(",").map((s) => s.trim());
489
- }
490
- } else if (schema.type === "object") {
491
- try {
492
- args[key] = JSON.parse(raw);
493
- } catch {
494
- args[key] = raw;
495
- }
496
- } else {
497
- args[key] = raw;
498
- }
499
- }
500
- setMessages((prev) => [
501
- ...prev,
502
- { role: "user", content: `${selectedTool.name}(${JSON.stringify(args)})` }
503
- ]);
504
- try {
505
- const result = await mcpCallTool(selectedTool.name, args);
506
- setMessages((prev) => [...prev, { role: "assistant", content: result }]);
507
- } catch (err) {
508
- setMessages((prev) => [
509
- ...prev,
510
- { role: "assistant", content: `Error: ${err.message ?? "Unknown error"}` }
511
- ]);
512
- }
513
- setLoading(false);
514
- setSelectedToolName("");
515
- setParamValues({});
516
- };
517
- const allParams = selectedTool ? [
518
- ...Object.entries(((_a = selectedTool.inputSchema) == null ? void 0 : _a.properties) ?? {}).filter(
519
- ([key]) => {
520
- var _a2;
521
- return (((_a2 = selectedTool.inputSchema) == null ? void 0 : _a2.required) ?? []).includes(key);
522
- }
523
- ),
524
- ...Object.entries(((_b = selectedTool.inputSchema) == null ? void 0 : _b.properties) ?? {}).filter(
525
- ([key]) => {
526
- var _a2;
527
- return !(((_a2 = selectedTool.inputSchema) == null ? void 0 : _a2.required) ?? []).includes(key);
528
- }
529
- )
530
- ] : [];
531
- return /* @__PURE__ */ jsxs(Drawer, { open, onOpenChange: handleOpen, children: [
532
- /* @__PURE__ */ jsx(Drawer.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { size: "small", children: [
533
- /* @__PURE__ */ jsx(ChatBubbleLeftRight, { className: "mr-1" }),
534
- "Query Data"
535
- ] }) }),
536
- /* @__PURE__ */ jsxs(Drawer.Content, { children: [
537
- /* @__PURE__ */ jsxs(Drawer.Header, { children: [
538
- /* @__PURE__ */ jsx(Drawer.Title, { children: "Query Data" }),
539
- /* @__PURE__ */ jsx(Drawer.Description, { children: "Run queries against your store data using MCP tools." })
540
- ] }),
541
- /* @__PURE__ */ jsxs(Drawer.Body, { className: "flex flex-col gap-4 overflow-hidden", children: [
542
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
543
- /* @__PURE__ */ jsxs(Select, { value: selectedToolName, onValueChange: handleSelectTool, children: [
544
- /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Select a tool..." }) }),
545
- /* @__PURE__ */ jsx(Select.Content, { children: tools.map((tool) => /* @__PURE__ */ jsx(Select.Item, { value: tool.name, children: tool.name }, tool.name)) })
546
- ] }),
547
- selectedTool && /* @__PURE__ */ jsxs(Fragment, { children: [
548
- /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-subtle", children: selectedTool.description }),
549
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2 items-end", children: [
550
- allParams.map(([key, schema]) => {
551
- var _a2;
552
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
553
- /* @__PURE__ */ jsxs(Text, { size: "xsmall", className: "text-ui-fg-subtle", children: [
554
- key,
555
- (((_a2 = selectedTool.inputSchema) == null ? void 0 : _a2.required) ?? []).includes(key) ? " *" : ""
556
- ] }),
557
- /* @__PURE__ */ jsx(
558
- Input,
559
- {
560
- size: "small",
561
- placeholder: schema.description ?? key,
562
- value: paramValues[key] ?? "",
563
- onChange: (e) => setParamValues((prev) => ({ ...prev, [key]: e.target.value }))
564
- }
565
- )
566
- ] }, key);
567
- }),
568
- /* @__PURE__ */ jsx(Button, { size: "small", onClick: handleExecute, disabled: loading, children: "Run" })
569
- ] })
570
- ] })
571
- ] }),
572
- /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto flex flex-col gap-2 min-h-0", children: [
573
- messages.map(
574
- (msg, i) => msg.role === "user" ? /* @__PURE__ */ jsx(
575
- "div",
576
- {
577
- className: "max-w-[90%] self-end rounded-lg px-3 py-2 text-xs bg-ui-bg-subtle text-ui-fg-base",
578
- children: /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap font-mono break-all", children: msg.content })
579
- },
580
- i
581
- ) : /* @__PURE__ */ jsx("div", { className: "self-start w-full", children: /* @__PURE__ */ jsx(
582
- CodeBlock,
583
- {
584
- snippets: [
585
- {
586
- label: "Result",
587
- language: "json",
588
- code: msg.content,
589
- hideLineNumbers: true
590
- }
591
- ],
592
- children: /* @__PURE__ */ jsx(CodeBlock.Body, { className: "text-xs [&_code]:text-xs" })
593
- }
594
- ) }, i)
595
- ),
596
- loading && /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-muted", children: "Running..." }),
597
- /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
598
- ] })
599
- ] })
600
- ] })
601
- ] });
602
- };
603
389
  const config = defineRouteConfig({
604
390
  label: "Statistics",
605
391
  icon: ChartBar,
@@ -719,8 +505,7 @@ const StatisticsPage = () => {
719
505
  editMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
720
506
  /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", onClick: () => setEditMode(false), children: "Cancel" }),
721
507
  /* @__PURE__ */ jsx(Button, { size: "small", onClick: handleSaveLayout, children: "Save Layout" })
722
- ] }) : /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", onClick: () => setEditMode(true), children: "Customize" }),
723
- /* @__PURE__ */ jsx(McpQuery, {})
508
+ ] }) : /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", onClick: () => setEditMode(true), children: "Customize" })
724
509
  ] })
725
510
  ] }) }),
726
511
  /* @__PURE__ */ jsx("div", { ref: gridRef, className: editMode ? "ring-2 ring-ui-border-interactive ring-offset-2 rounded-lg" : "", children: isLoading ? /* @__PURE__ */ jsx(Container, { className: "p-6", children: /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-muted", children: "Loading statistics..." }) }) : gridMounted && /* @__PURE__ */ jsx(
@@ -2,19 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const http_1 = require("@medusajs/framework/http");
4
4
  const validators_1 = require("./validators");
5
- function exposeMcpHeaders(req, res, next) {
6
- res.setHeader('Access-Control-Expose-Headers', 'mcp-session-id');
7
- res.setHeader('Access-Control-Allow-Headers', [res.getHeader('Access-Control-Allow-Headers') ?? '', 'mcp-session-id']
8
- .filter(Boolean)
9
- .join(', '));
10
- next();
11
- }
12
5
  exports.default = (0, http_1.defineMiddlewares)([
13
- {
14
- matcher: '/admin/mcp',
15
- method: ['GET', 'POST', 'DELETE'],
16
- middlewares: [exposeMcpHeaders]
17
- },
18
6
  {
19
7
  matcher: '/admin/statistics',
20
8
  method: ['GET'],
@@ -41,4 +29,4 @@ exports.default = (0, http_1.defineMiddlewares)([
41
29
  middlewares: [(0, http_1.validateAndTransformBody)(validators_1.AdminSaveStatisticsLayout)]
42
30
  }
43
31
  ]);
44
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXBpL21pZGRsZXdhcmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbURBTWlDO0FBRWpDLDZDQU1xQjtBQUVyQixTQUFTLGdCQUFnQixDQUN4QixHQUFrQixFQUNsQixHQUFtQixFQUNuQixJQUFrQjtJQUVsQixHQUFHLENBQUMsU0FBUyxDQUFDLCtCQUErQixFQUFFLGdCQUFnQixDQUFDLENBQUE7SUFDaEUsR0FBRyxDQUFDLFNBQVMsQ0FDWiw4QkFBOEIsRUFDOUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLDhCQUE4QixDQUFDLElBQUksRUFBRSxFQUFFLGdCQUFnQixDQUFDO1NBQ3JFLE1BQU0sQ0FBQyxPQUFPLENBQUM7U0FDZixJQUFJLENBQUMsSUFBSSxDQUFDLENBQ1osQ0FBQTtJQUNELElBQUksRUFBRSxDQUFBO0FBQ1AsQ0FBQztBQUVELGtCQUFlLElBQUEsd0JBQWlCLEVBQUM7SUFDaEM7UUFDQyxPQUFPLEVBQUUsWUFBWTtRQUNyQixNQUFNLEVBQUUsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQztRQUNqQyxXQUFXLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQztLQUMvQjtJQUNEO1FBQ0MsT0FBTyxFQUFFLG1CQUFtQjtRQUM1QixNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDZixXQUFXLEVBQUUsQ0FBQyxJQUFBLGdDQUF5QixFQUFDLCtCQUFrQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7S0FDL0U7SUFDRDtRQUNDLE9BQU8sRUFBRSwrQkFBK0I7UUFDeEMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDO1FBQ2hCLFdBQVcsRUFBRSxDQUFDLElBQUEsK0JBQXdCLEVBQUMsdUNBQTBCLENBQUMsQ0FBQztLQUNuRTtJQUNEO1FBQ0MsT0FBTyxFQUFFLGlDQUFpQztRQUMxQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDZixXQUFXLEVBQUUsQ0FBQyxJQUFBLGdDQUF5QixFQUFDLGlDQUFvQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7S0FDakY7SUFDRDtRQUNDLE9BQU8sRUFBRSw2QkFBNkI7UUFDdEMsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDO1FBQ2YsV0FBVyxFQUFFLENBQUMsSUFBQSxnQ0FBeUIsRUFBQyw2QkFBZ0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0tBQzdFO0lBQ0Q7UUFDQyxPQUFPLEVBQUUsMEJBQTBCO1FBQ25DLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQztRQUNoQixXQUFXLEVBQUUsQ0FBQyxJQUFBLCtCQUF3QixFQUFDLHNDQUF5QixDQUFDLENBQUM7S0FDbEU7Q0FDRCxDQUFDLENBQUEifQ==
32
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXBpL21pZGRsZXdhcmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbURBSWlDO0FBQ2pDLDZDQU1xQjtBQUVyQixrQkFBZSxJQUFBLHdCQUFpQixFQUFDO0lBQ2hDO1FBQ0MsT0FBTyxFQUFFLG1CQUFtQjtRQUM1QixNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDZixXQUFXLEVBQUUsQ0FBQyxJQUFBLGdDQUF5QixFQUFDLCtCQUFrQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7S0FDL0U7SUFDRDtRQUNDLE9BQU8sRUFBRSwrQkFBK0I7UUFDeEMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDO1FBQ2hCLFdBQVcsRUFBRSxDQUFDLElBQUEsK0JBQXdCLEVBQUMsdUNBQTBCLENBQUMsQ0FBQztLQUNuRTtJQUNEO1FBQ0MsT0FBTyxFQUFFLGlDQUFpQztRQUMxQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDZixXQUFXLEVBQUUsQ0FBQyxJQUFBLGdDQUF5QixFQUFDLGlDQUFvQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7S0FDakY7SUFDRDtRQUNDLE9BQU8sRUFBRSw2QkFBNkI7UUFDdEMsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDO1FBQ2YsV0FBVyxFQUFFLENBQUMsSUFBQSxnQ0FBeUIsRUFBQyw2QkFBZ0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0tBQzdFO0lBQ0Q7UUFDQyxPQUFPLEVBQUUsMEJBQTBCO1FBQ25DLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQztRQUNoQixXQUFXLEVBQUUsQ0FBQyxJQUFBLCtCQUF3QixFQUFDLHNDQUF5QixDQUFDLENBQUM7S0FDbEU7Q0FDRCxDQUFDLENBQUEifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "medusa-plugin-statistics",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Dashboard statistics plugin for Medusa v2 with daily aggregation and customizable widgets",
5
5
  "author": "Lacey Pevey",
6
6
  "license": "MIT",
@@ -57,7 +57,6 @@
57
57
  "test:integration:http": "TEST_TYPE=integration:http NODE_OPTIONS=--experimental-vm-modules jest --silent=false --runInBand --detectOpenHandles --forceExit"
58
58
  },
59
59
  "dependencies": {
60
- "@modelcontextprotocol/sdk": "^1.29.0",
61
60
  "react-grid-layout": "^2.2.3",
62
61
  "recharts": "^2.15.3"
63
62
  },
@@ -94,4 +93,4 @@
94
93
  "engines": {
95
94
  "node": ">=20"
96
95
  }
97
- }
96
+ }
@@ -1,4 +0,0 @@
1
- import { AuthenticatedMedusaRequest, MedusaResponse } from '@medusajs/framework/http';
2
- export declare const POST: (req: AuthenticatedMedusaRequest, res: MedusaResponse) => Promise<void>;
3
- export declare const GET: (_req: AuthenticatedMedusaRequest, res: MedusaResponse) => Promise<void>;
4
- export declare const DELETE: (_req: AuthenticatedMedusaRequest, res: MedusaResponse) => Promise<void>;
@@ -1,60 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DELETE = exports.GET = exports.POST = void 0;
4
- const node_crypto_1 = require("node:crypto");
5
- const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
6
- const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
7
- const server_1 = require("../../../mcp/server");
8
- // Store transports by session ID for stateful MCP connections
9
- const sessions = {};
10
- const POST = async (req, res) => {
11
- try {
12
- const sessionId = req.headers['mcp-session-id'];
13
- let transport;
14
- if (sessionId && sessions[sessionId]) {
15
- // Reuse existing session transport
16
- transport = sessions[sessionId];
17
- }
18
- else if (!sessionId && (0, types_js_1.isInitializeRequest)(req.body)) {
19
- // New initialization request
20
- transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
21
- sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
22
- enableJsonResponse: true,
23
- onsessioninitialized: (id) => {
24
- sessions[id] = transport;
25
- }
26
- });
27
- const server = (0, server_1.createMcpServer)(req.scope);
28
- await server.connect(transport);
29
- }
30
- else {
31
- res.status(400).json({
32
- jsonrpc: '2.0',
33
- error: { code: -32000, message: 'Bad Request: No valid session. Send initialize first.' },
34
- id: null
35
- });
36
- return;
37
- }
38
- await transport.handleRequest(req, res, req.body);
39
- }
40
- catch (err) {
41
- console.error('[MCP] Error:', err);
42
- if (!res.headersSent) {
43
- res.status(500).json({
44
- jsonrpc: '2.0',
45
- error: { code: -32603, message: 'Internal server error' },
46
- id: null
47
- });
48
- }
49
- }
50
- };
51
- exports.POST = POST;
52
- const GET = async (_req, res) => {
53
- res.writeHead(405).end(JSON.stringify({ error: 'Method not allowed' }));
54
- };
55
- exports.GET = GET;
56
- const DELETE = async (_req, res) => {
57
- res.writeHead(405).end(JSON.stringify({ error: 'Method not allowed' }));
58
- };
59
- exports.DELETE = DELETE;
60
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL21jcC9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBd0M7QUFFeEMsMEZBQWtHO0FBQ2xHLGlFQUF3RTtBQUN4RSxnREFBcUQ7QUFFckQsOERBQThEO0FBQzlELE1BQU0sUUFBUSxHQUFrRCxFQUFFLENBQUE7QUFFM0QsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLEdBQStCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ2xGLElBQUksQ0FBQztRQUNKLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQXVCLENBQUE7UUFDckUsSUFBSSxTQUF3QyxDQUFBO1FBRTVDLElBQUksU0FBUyxJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ3RDLG1DQUFtQztZQUNuQyxTQUFTLEdBQUcsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBQ2hDLENBQUM7YUFBTSxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUEsOEJBQW1CLEVBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDeEQsNkJBQTZCO1lBQzdCLFNBQVMsR0FBRyxJQUFJLGlEQUE2QixDQUFDO2dCQUM3QyxrQkFBa0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFBLHdCQUFVLEdBQUU7Z0JBQ3RDLGtCQUFrQixFQUFFLElBQUk7Z0JBQ3hCLG9CQUFvQixFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUU7b0JBQzVCLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUE7Z0JBQ3pCLENBQUM7YUFDRCxDQUFDLENBQUE7WUFFRixNQUFNLE1BQU0sR0FBRyxJQUFBLHdCQUFlLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQ3pDLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQTtRQUNoQyxDQUFDO2FBQU0sQ0FBQztZQUNQLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNwQixPQUFPLEVBQUUsS0FBSztnQkFDZCxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLHVEQUF1RCxFQUFFO2dCQUN6RixFQUFFLEVBQUUsSUFBSTthQUNSLENBQUMsQ0FBQTtZQUNGLE9BQU07UUFDUCxDQUFDO1FBRUQsTUFBTSxTQUFTLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ2xELENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2QsT0FBTyxDQUFDLEtBQUssQ0FBQyxjQUFjLEVBQUUsR0FBRyxDQUFDLENBQUE7UUFDbEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN0QixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDcEIsT0FBTyxFQUFFLEtBQUs7Z0JBQ2QsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRTtnQkFDekQsRUFBRSxFQUFFLElBQUk7YUFDUixDQUFDLENBQUE7UUFDSCxDQUFDO0lBQ0YsQ0FBQztBQUNGLENBQUMsQ0FBQTtBQXhDWSxRQUFBLElBQUksUUF3Q2hCO0FBRU0sTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUFFLElBQWdDLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ2xGLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxLQUFLLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDLENBQUE7QUFDeEUsQ0FBQyxDQUFBO0FBRlksUUFBQSxHQUFHLE9BRWY7QUFFTSxNQUFNLE1BQU0sR0FBRyxLQUFLLEVBQUUsSUFBZ0MsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDckYsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEtBQUssRUFBRSxvQkFBb0IsRUFBRSxDQUFDLENBQUMsQ0FBQTtBQUN4RSxDQUFDLENBQUE7QUFGWSxRQUFBLE1BQU0sVUFFbEIifQ==
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { MedusaContainer } from '@medusajs/framework/types';
3
- export declare const createMcpServer: (scope: MedusaContainer) => McpServer;
@@ -1,23 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createMcpServer = void 0;
4
- const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
5
- const query_1 = require("./tools/query");
6
- const orders_1 = require("./tools/orders");
7
- const customers_1 = require("./tools/customers");
8
- const products_1 = require("./tools/products");
9
- const inventory_1 = require("./tools/inventory");
10
- const createMcpServer = (scope) => {
11
- const server = new mcp_js_1.McpServer({
12
- name: 'medusa-admin',
13
- version: '1.0.0'
14
- });
15
- (0, query_1.registerQueryTool)(server, scope);
16
- (0, orders_1.registerOrderTools)(server, scope);
17
- (0, customers_1.registerCustomerTools)(server, scope);
18
- (0, products_1.registerProductTools)(server, scope);
19
- (0, inventory_1.registerInventoryTools)(server, scope);
20
- return server;
21
- };
22
- exports.createMcpServer = createMcpServer;
23
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL21jcC9zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsb0VBQW1FO0FBRW5FLHlDQUFpRDtBQUNqRCwyQ0FBbUQ7QUFDbkQsaURBQXlEO0FBQ3pELCtDQUF1RDtBQUN2RCxpREFBMEQ7QUFFbkQsTUFBTSxlQUFlLEdBQUcsQ0FBQyxLQUFzQixFQUFhLEVBQUU7SUFDcEUsTUFBTSxNQUFNLEdBQUcsSUFBSSxrQkFBUyxDQUFDO1FBQzVCLElBQUksRUFBRSxjQUFjO1FBQ3BCLE9BQU8sRUFBRSxPQUFPO0tBQ2hCLENBQUMsQ0FBQTtJQUVGLElBQUEseUJBQWlCLEVBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQ2hDLElBQUEsMkJBQWtCLEVBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQ2pDLElBQUEsaUNBQXFCLEVBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQ3BDLElBQUEsK0JBQW9CLEVBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQ25DLElBQUEsa0NBQXNCLEVBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBRXJDLE9BQU8sTUFBTSxDQUFBO0FBQ2QsQ0FBQyxDQUFBO0FBYlksUUFBQSxlQUFlLG1CQWEzQiJ9
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { MedusaContainer } from '@medusajs/framework/types';
3
- export declare function registerCustomerTools(server: McpServer, scope: MedusaContainer): void;
@@ -1,72 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerCustomerTools = registerCustomerTools;
4
- const utils_1 = require("@medusajs/framework/utils");
5
- const zod_1 = require("zod");
6
- function registerCustomerTools(server, scope) {
7
- const query = scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
8
- server.registerTool('search_customers', {
9
- description: 'Search customers by email or name.',
10
- inputSchema: {
11
- q: zod_1.z.string().describe('Search term (matches email, first_name, or last_name)'),
12
- limit: zod_1.z.coerce.number().int().min(1).max(50).optional().default(10)
13
- }
14
- }, async ({ q, limit }) => {
15
- const { data } = await query.graph({
16
- entity: 'customer',
17
- fields: [
18
- 'id',
19
- 'email',
20
- 'first_name',
21
- 'last_name',
22
- 'phone',
23
- 'has_account',
24
- 'created_at'
25
- ],
26
- filters: {
27
- $or: [
28
- { email: { $ilike: `%${q}%` } },
29
- { first_name: { $ilike: `%${q}%` } },
30
- { last_name: { $ilike: `%${q}%` } }
31
- ]
32
- },
33
- pagination: { take: limit }
34
- });
35
- return {
36
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
37
- };
38
- });
39
- server.registerTool('get_customer', {
40
- description: 'Fetch a single customer by ID with their order history.',
41
- inputSchema: {
42
- customer_id: zod_1.z.string().describe('The customer ID')
43
- }
44
- }, async ({ customer_id }) => {
45
- const { data: [customer] } = await query.graph({
46
- entity: 'customer',
47
- fields: [
48
- 'id',
49
- 'email',
50
- 'first_name',
51
- 'last_name',
52
- 'phone',
53
- 'has_account',
54
- 'orders.id',
55
- 'orders.display_id',
56
- 'orders.status',
57
- 'orders.total',
58
- 'orders.created_at',
59
- 'created_at',
60
- 'updated_at'
61
- ],
62
- filters: { id: customer_id }
63
- });
64
- if (!customer) {
65
- return { content: [{ type: 'text', text: 'Customer not found.' }] };
66
- }
67
- return {
68
- content: [{ type: 'text', text: JSON.stringify(customer, null, 2) }]
69
- };
70
- });
71
- }
72
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL21jcC90b29scy9jdXN0b21lcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFLQSxzREFnRkM7QUFuRkQscURBQXFFO0FBQ3JFLDZCQUF1QjtBQUV2QixTQUFnQixxQkFBcUIsQ0FBQyxNQUFpQixFQUFFLEtBQXNCO0lBQzlFLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFFNUQsTUFBTSxDQUFDLFlBQVksQ0FDbEIsa0JBQWtCLEVBQ2xCO1FBQ0MsV0FBVyxFQUFFLG9DQUFvQztRQUNqRCxXQUFXLEVBQUU7WUFDWixDQUFDLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyx1REFBdUQsQ0FBQztZQUMvRSxLQUFLLEVBQUUsT0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7U0FDcEU7S0FDRCxFQUNELEtBQUssRUFBRSxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFO1FBQ3RCLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFDbEMsTUFBTSxFQUFFLFVBQVU7WUFDbEIsTUFBTSxFQUFFO2dCQUNQLElBQUk7Z0JBQ0osT0FBTztnQkFDUCxZQUFZO2dCQUNaLFdBQVc7Z0JBQ1gsT0FBTztnQkFDUCxhQUFhO2dCQUNiLFlBQVk7YUFDWjtZQUNELE9BQU8sRUFBRTtnQkFDUixHQUFHLEVBQUU7b0JBQ0osRUFBRSxLQUFLLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFO29CQUMvQixFQUFFLFVBQVUsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLEVBQUU7b0JBQ3BDLEVBQUUsU0FBUyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsRUFBRTtpQkFDbkM7YUFDRDtZQUNELFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUU7U0FDM0IsQ0FBQyxDQUFBO1FBRUYsT0FBTztZQUNOLE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQWUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUM7U0FDekUsQ0FBQTtJQUNGLENBQUMsQ0FDRCxDQUFBO0lBRUQsTUFBTSxDQUFDLFlBQVksQ0FDbEIsY0FBYyxFQUNkO1FBQ0MsV0FBVyxFQUFFLHlEQUF5RDtRQUN0RSxXQUFXLEVBQUU7WUFDWixXQUFXLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQztTQUNuRDtLQUNELEVBQ0QsS0FBSyxFQUFFLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRTtRQUN6QixNQUFNLEVBQ0wsSUFBSSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQ2hCLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDO1lBQ3JCLE1BQU0sRUFBRSxVQUFVO1lBQ2xCLE1BQU0sRUFBRTtnQkFDUCxJQUFJO2dCQUNKLE9BQU87Z0JBQ1AsWUFBWTtnQkFDWixXQUFXO2dCQUNYLE9BQU87Z0JBQ1AsYUFBYTtnQkFDYixXQUFXO2dCQUNYLG1CQUFtQjtnQkFDbkIsZUFBZTtnQkFDZixjQUFjO2dCQUNkLG1CQUFtQjtnQkFDbkIsWUFBWTtnQkFDWixZQUFZO2FBQ1o7WUFDRCxPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFO1NBQzVCLENBQUMsQ0FBQTtRQUVGLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNmLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFlLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixFQUFFLENBQUMsRUFBRSxDQUFBO1FBQzdFLENBQUM7UUFFRCxPQUFPO1lBQ04sT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBZSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUM3RSxDQUFBO0lBQ0YsQ0FBQyxDQUNELENBQUE7QUFDRixDQUFDIn0=
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { MedusaContainer } from '@medusajs/framework/types';
3
- export declare function registerInventoryTools(server: McpServer, scope: MedusaContainer): void;
@@ -1,70 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerInventoryTools = registerInventoryTools;
4
- const utils_1 = require("@medusajs/framework/utils");
5
- const zod_1 = require("zod");
6
- function registerInventoryTools(server, scope) {
7
- const query = scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
8
- server.registerTool('low_stock_items', {
9
- description: 'Find inventory items with stock levels at or below a threshold.',
10
- inputSchema: {
11
- threshold: zod_1.z.coerce.number().int().min(0).optional().default(10),
12
- limit: zod_1.z.coerce.number().int().min(1).max(100).optional().default(20)
13
- }
14
- }, async ({ threshold, limit }) => {
15
- const { data } = await query.graph({
16
- entity: 'inventory_item',
17
- fields: [
18
- 'id',
19
- 'sku',
20
- 'title',
21
- 'location_levels.id',
22
- 'location_levels.stocked_quantity',
23
- 'location_levels.reserved_quantity',
24
- 'location_levels.stock_location.id',
25
- 'location_levels.stock_location.name'
26
- ],
27
- filters: {
28
- location_levels: {
29
- stocked_quantity: { $lte: threshold }
30
- }
31
- },
32
- pagination: { take: limit }
33
- });
34
- return {
35
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
36
- };
37
- });
38
- server.registerTool('get_inventory_item', {
39
- description: 'Fetch a single inventory item by ID with stock levels across locations.',
40
- inputSchema: {
41
- inventory_item_id: zod_1.z.string().describe('The inventory item ID')
42
- }
43
- }, async ({ inventory_item_id }) => {
44
- const { data: [item] } = await query.graph({
45
- entity: 'inventory_item',
46
- fields: [
47
- 'id',
48
- 'sku',
49
- 'title',
50
- 'requires_shipping',
51
- 'location_levels.id',
52
- 'location_levels.stocked_quantity',
53
- 'location_levels.reserved_quantity',
54
- 'location_levels.incoming_quantity',
55
- 'location_levels.stock_location.id',
56
- 'location_levels.stock_location.name',
57
- 'created_at',
58
- 'updated_at'
59
- ],
60
- filters: { id: inventory_item_id }
61
- });
62
- if (!item) {
63
- return { content: [{ type: 'text', text: 'Inventory item not found.' }] };
64
- }
65
- return {
66
- content: [{ type: 'text', text: JSON.stringify(item, null, 2) }]
67
- };
68
- });
69
- }
70
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW52ZW50b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL21jcC90b29scy9pbnZlbnRvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFLQSx3REE4RUM7QUFqRkQscURBQXFFO0FBQ3JFLDZCQUF1QjtBQUV2QixTQUFnQixzQkFBc0IsQ0FBQyxNQUFpQixFQUFFLEtBQXNCO0lBQy9FLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFFNUQsTUFBTSxDQUFDLFlBQVksQ0FDbEIsaUJBQWlCLEVBQ2pCO1FBQ0MsV0FBVyxFQUFFLGlFQUFpRTtRQUM5RSxXQUFXLEVBQUU7WUFDWixTQUFTLEVBQUUsT0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNoRSxLQUFLLEVBQUUsT0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7U0FDckU7S0FDRCxFQUNELEtBQUssRUFBRSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFO1FBQzlCLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFDbEMsTUFBTSxFQUFFLGdCQUFnQjtZQUN4QixNQUFNLEVBQUU7Z0JBQ1AsSUFBSTtnQkFDSixLQUFLO2dCQUNMLE9BQU87Z0JBQ1Asb0JBQW9CO2dCQUNwQixrQ0FBa0M7Z0JBQ2xDLG1DQUFtQztnQkFDbkMsbUNBQW1DO2dCQUNuQyxxQ0FBcUM7YUFDckM7WUFDRCxPQUFPLEVBQUU7Z0JBQ1IsZUFBZSxFQUFFO29CQUNoQixnQkFBZ0IsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUU7aUJBQ3JDO2FBQ007WUFDUixVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFO1NBQzNCLENBQUMsQ0FBQTtRQUVGLE9BQU87WUFDTixPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFlLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQ3pFLENBQUE7SUFDRixDQUFDLENBQ0QsQ0FBQTtJQUVELE1BQU0sQ0FBQyxZQUFZLENBQ2xCLG9CQUFvQixFQUNwQjtRQUNDLFdBQVcsRUFBRSx5RUFBeUU7UUFDdEYsV0FBVyxFQUFFO1lBQ1osaUJBQWlCLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsQ0FBQztTQUMvRDtLQUNELEVBQ0QsS0FBSyxFQUFFLEVBQUUsaUJBQWlCLEVBQUUsRUFBRSxFQUFFO1FBQy9CLE1BQU0sRUFDTCxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFDWixHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQztZQUNyQixNQUFNLEVBQUUsZ0JBQWdCO1lBQ3hCLE1BQU0sRUFBRTtnQkFDUCxJQUFJO2dCQUNKLEtBQUs7Z0JBQ0wsT0FBTztnQkFDUCxtQkFBbUI7Z0JBQ25CLG9CQUFvQjtnQkFDcEIsa0NBQWtDO2dCQUNsQyxtQ0FBbUM7Z0JBQ25DLG1DQUFtQztnQkFDbkMsbUNBQW1DO2dCQUNuQyxxQ0FBcUM7Z0JBQ3JDLFlBQVk7Z0JBQ1osWUFBWTthQUNaO1lBQ0QsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLGlCQUFpQixFQUFFO1NBQ2xDLENBQUMsQ0FBQTtRQUVGLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNYLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFlLEVBQUUsSUFBSSxFQUFFLDJCQUEyQixFQUFFLENBQUMsRUFBRSxDQUFBO1FBQ25GLENBQUM7UUFFRCxPQUFPO1lBQ04sT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBZSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUN6RSxDQUFBO0lBQ0YsQ0FBQyxDQUNELENBQUE7QUFDRixDQUFDIn0=
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { MedusaContainer } from '@medusajs/framework/types';
3
- export declare function registerOrderTools(server: McpServer, scope: MedusaContainer): void;
@@ -1,80 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerOrderTools = registerOrderTools;
4
- const utils_1 = require("@medusajs/framework/utils");
5
- const zod_1 = require("zod");
6
- function registerOrderTools(server, scope) {
7
- const query = scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
8
- server.registerTool('recent_orders', {
9
- description: 'Fetch recent orders with status, totals, and customer info.',
10
- inputSchema: {
11
- limit: zod_1.z.coerce.number().int().min(1).max(50).optional().default(10),
12
- status: zod_1.z.string().optional().describe('Filter by order status')
13
- }
14
- }, async ({ limit, status }) => {
15
- const { data } = await query.graph({
16
- entity: 'order',
17
- fields: [
18
- 'id',
19
- 'display_id',
20
- 'status',
21
- 'email',
22
- 'total',
23
- 'subtotal',
24
- 'tax_total',
25
- 'shipping_total',
26
- 'customer.first_name',
27
- 'customer.last_name',
28
- 'created_at'
29
- ],
30
- filters: (status ? { status } : {}),
31
- pagination: { take: limit, order: { created_at: 'DESC' } }
32
- });
33
- return {
34
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
35
- };
36
- });
37
- server.registerTool('get_order', {
38
- description: 'Fetch a single order by ID with full details including items, fulfillments, and customer.',
39
- inputSchema: {
40
- order_id: zod_1.z.string().describe('The order ID')
41
- }
42
- }, async ({ order_id }) => {
43
- const { data: [order] } = await query.graph({
44
- entity: 'order',
45
- fields: [
46
- 'id',
47
- 'display_id',
48
- 'status',
49
- 'email',
50
- 'total',
51
- 'subtotal',
52
- 'tax_total',
53
- 'shipping_total',
54
- 'discount_total',
55
- 'customer.id',
56
- 'customer.first_name',
57
- 'customer.last_name',
58
- 'customer.email',
59
- 'items.id',
60
- 'items.title',
61
- 'items.quantity',
62
- 'items.unit_price',
63
- 'shipping_address.*',
64
- 'billing_address.*',
65
- 'fulfillments.id',
66
- 'fulfillments.status',
67
- 'created_at',
68
- 'updated_at'
69
- ],
70
- filters: { id: order_id }
71
- });
72
- if (!order) {
73
- return { content: [{ type: 'text', text: 'Order not found.' }] };
74
- }
75
- return {
76
- content: [{ type: 'text', text: JSON.stringify(order, null, 2) }]
77
- };
78
- });
79
- }
80
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JkZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL21jcC90b29scy9vcmRlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFLQSxnREF3RkM7QUEzRkQscURBQXFFO0FBQ3JFLDZCQUF1QjtBQUV2QixTQUFnQixrQkFBa0IsQ0FBQyxNQUFpQixFQUFFLEtBQXNCO0lBQzNFLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFFNUQsTUFBTSxDQUFDLFlBQVksQ0FDbEIsZUFBZSxFQUNmO1FBQ0MsV0FBVyxFQUFFLDZEQUE2RDtRQUMxRSxXQUFXLEVBQUU7WUFDWixLQUFLLEVBQUUsT0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDcEUsTUFBTSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsd0JBQXdCLENBQUM7U0FDaEU7S0FDRCxFQUNELEtBQUssRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFO1FBQzNCLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFDbEMsTUFBTSxFQUFFLE9BQU87WUFDZixNQUFNLEVBQUU7Z0JBQ1AsSUFBSTtnQkFDSixZQUFZO2dCQUNaLFFBQVE7Z0JBQ1IsT0FBTztnQkFDUCxPQUFPO2dCQUNQLFVBQVU7Z0JBQ1YsV0FBVztnQkFDWCxnQkFBZ0I7Z0JBQ2hCLHFCQUFxQjtnQkFDckIsb0JBQW9CO2dCQUNwQixZQUFZO2FBQ1o7WUFDRCxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBUTtZQUMxQyxVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsRUFBRTtTQUMxRCxDQUFDLENBQUE7UUFFRixPQUFPO1lBQ04sT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBZSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUN6RSxDQUFBO0lBQ0YsQ0FBQyxDQUNELENBQUE7SUFFRCxNQUFNLENBQUMsWUFBWSxDQUNsQixXQUFXLEVBQ1g7UUFDQyxXQUFXLEVBQUUsMkZBQTJGO1FBQ3hHLFdBQVcsRUFBRTtZQUNaLFFBQVEsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQztTQUM3QztLQUNELEVBQ0QsS0FBSyxFQUFFLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRTtRQUN0QixNQUFNLEVBQ0wsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQ2IsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFDckIsTUFBTSxFQUFFLE9BQU87WUFDZixNQUFNLEVBQUU7Z0JBQ1AsSUFBSTtnQkFDSixZQUFZO2dCQUNaLFFBQVE7Z0JBQ1IsT0FBTztnQkFDUCxPQUFPO2dCQUNQLFVBQVU7Z0JBQ1YsV0FBVztnQkFDWCxnQkFBZ0I7Z0JBQ2hCLGdCQUFnQjtnQkFDaEIsYUFBYTtnQkFDYixxQkFBcUI7Z0JBQ3JCLG9CQUFvQjtnQkFDcEIsZ0JBQWdCO2dCQUNoQixVQUFVO2dCQUNWLGFBQWE7Z0JBQ2IsZ0JBQWdCO2dCQUNoQixrQkFBa0I7Z0JBQ2xCLG9CQUFvQjtnQkFDcEIsbUJBQW1CO2dCQUNuQixpQkFBaUI7Z0JBQ2pCLHFCQUFxQjtnQkFDckIsWUFBWTtnQkFDWixZQUFZO2FBQ1o7WUFDRCxPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFO1NBQ3pCLENBQUMsQ0FBQTtRQUVGLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNaLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFlLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLENBQUMsRUFBRSxDQUFBO1FBQzFFLENBQUM7UUFFRCxPQUFPO1lBQ04sT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBZSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUMxRSxDQUFBO0lBQ0YsQ0FBQyxDQUNELENBQUE7QUFDRixDQUFDIn0=
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { MedusaContainer } from '@medusajs/framework/types';
3
- export declare function registerProductTools(server: McpServer, scope: MedusaContainer): void;
@@ -1,72 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerProductTools = registerProductTools;
4
- const utils_1 = require("@medusajs/framework/utils");
5
- const zod_1 = require("zod");
6
- function registerProductTools(server, scope) {
7
- const query = scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
8
- server.registerTool('search_products', {
9
- description: 'Search products by title.',
10
- inputSchema: {
11
- q: zod_1.z.string().describe('Search term (matches title)'),
12
- limit: zod_1.z.coerce.number().int().min(1).max(50).optional().default(10)
13
- }
14
- }, async ({ q, limit }) => {
15
- const { data } = await query.graph({
16
- entity: 'product',
17
- fields: [
18
- 'id',
19
- 'title',
20
- 'handle',
21
- 'status',
22
- 'variants.id',
23
- 'variants.title',
24
- 'variants.sku',
25
- 'created_at'
26
- ],
27
- filters: { title: { $ilike: `%${q}%` } },
28
- pagination: { take: limit }
29
- });
30
- return {
31
- content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
32
- };
33
- });
34
- server.registerTool('get_product', {
35
- description: 'Fetch a single product by ID with variants and pricing.',
36
- inputSchema: {
37
- product_id: zod_1.z.string().describe('The product ID')
38
- }
39
- }, async ({ product_id }) => {
40
- const { data: [product] } = await query.graph({
41
- entity: 'product',
42
- fields: [
43
- 'id',
44
- 'title',
45
- 'handle',
46
- 'subtitle',
47
- 'description',
48
- 'status',
49
- 'variants.id',
50
- 'variants.title',
51
- 'variants.sku',
52
- 'variants.prices.amount',
53
- 'variants.prices.currency_code',
54
- 'options.id',
55
- 'options.title',
56
- 'options.values.value',
57
- 'tags.id',
58
- 'tags.value',
59
- 'created_at',
60
- 'updated_at'
61
- ],
62
- filters: { id: product_id }
63
- });
64
- if (!product) {
65
- return { content: [{ type: 'text', text: 'Product not found.' }] };
66
- }
67
- return {
68
- content: [{ type: 'text', text: JSON.stringify(product, null, 2) }]
69
- };
70
- });
71
- }
72
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZHVjdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbWNwL3Rvb2xzL3Byb2R1Y3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBS0Esb0RBZ0ZDO0FBbkZELHFEQUFxRTtBQUNyRSw2QkFBdUI7QUFFdkIsU0FBZ0Isb0JBQW9CLENBQUMsTUFBaUIsRUFBRSxLQUFzQjtJQUM3RSxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBRTVELE1BQU0sQ0FBQyxZQUFZLENBQ2xCLGlCQUFpQixFQUNqQjtRQUNDLFdBQVcsRUFBRSwyQkFBMkI7UUFDeEMsV0FBVyxFQUFFO1lBQ1osQ0FBQyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsNkJBQTZCLENBQUM7WUFDckQsS0FBSyxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1NBQ3BFO0tBQ0QsRUFDRCxLQUFLLEVBQUUsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRTtRQUN0QixNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDO1lBQ2xDLE1BQU0sRUFBRSxTQUFTO1lBQ2pCLE1BQU0sRUFBRTtnQkFDUCxJQUFJO2dCQUNKLE9BQU87Z0JBQ1AsUUFBUTtnQkFDUixRQUFRO2dCQUNSLGFBQWE7Z0JBQ2IsZ0JBQWdCO2dCQUNoQixjQUFjO2dCQUNkLFlBQVk7YUFDWjtZQUNELE9BQU8sRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLEVBQUU7WUFDeEMsVUFBVSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRTtTQUMzQixDQUFDLENBQUE7UUFFRixPQUFPO1lBQ04sT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBZSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUN6RSxDQUFBO0lBQ0YsQ0FBQyxDQUNELENBQUE7SUFFRCxNQUFNLENBQUMsWUFBWSxDQUNsQixhQUFhLEVBQ2I7UUFDQyxXQUFXLEVBQUUseURBQXlEO1FBQ3RFLFdBQVcsRUFBRTtZQUNaLFVBQVUsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDO1NBQ2pEO0tBQ0QsRUFDRCxLQUFLLEVBQUUsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFO1FBQ3hCLE1BQU0sRUFDTCxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFDZixHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQztZQUNyQixNQUFNLEVBQUUsU0FBUztZQUNqQixNQUFNLEVBQUU7Z0JBQ1AsSUFBSTtnQkFDSixPQUFPO2dCQUNQLFFBQVE7Z0JBQ1IsVUFBVTtnQkFDVixhQUFhO2dCQUNiLFFBQVE7Z0JBQ1IsYUFBYTtnQkFDYixnQkFBZ0I7Z0JBQ2hCLGNBQWM7Z0JBQ2Qsd0JBQXdCO2dCQUN4QiwrQkFBK0I7Z0JBQy9CLFlBQVk7Z0JBQ1osZUFBZTtnQkFDZixzQkFBc0I7Z0JBQ3RCLFNBQVM7Z0JBQ1QsWUFBWTtnQkFDWixZQUFZO2dCQUNaLFlBQVk7YUFDWjtZQUNELE9BQU8sRUFBRSxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUU7U0FDM0IsQ0FBQyxDQUFBO1FBRUYsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2QsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQWUsRUFBRSxJQUFJLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxFQUFFLENBQUE7UUFDNUUsQ0FBQztRQUVELE9BQU87WUFDTixPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFlLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQzVFLENBQUE7SUFDRixDQUFDLENBQ0QsQ0FBQTtBQUNGLENBQUMifQ==
@@ -1,3 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { MedusaContainer } from '@medusajs/framework/types';
3
- export declare function registerQueryTool(server: McpServer, scope: MedusaContainer): void;
@@ -1,42 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerQueryTool = registerQueryTool;
4
- const utils_1 = require("@medusajs/framework/utils");
5
- const zod_1 = require("zod");
6
- const ALLOWED_ENTITIES = [
7
- 'order', 'product', 'product_variant', 'customer', 'inventory_item',
8
- 'fulfillment', 'cart', 'shipping_option', 'sales_channel', 'store',
9
- 'form', 'form_submission', 'review', 'complaint', 'complaint_tag',
10
- 'content_item', 'content_collection', 'stock_lot', 'serial_number',
11
- 'veeqo_order', 'veeqo_shipment', 'webhook_trigger', 'webhook_action',
12
- 'barcode', 'order_note', 'customer_tag'
13
- ];
14
- function registerQueryTool(server, scope) {
15
- server.registerTool('query', {
16
- description: `Run a query against any Medusa entity using query.graph(). Allowed entities: ${ALLOWED_ENTITIES.join(', ')}. ` +
17
- 'Use dot notation for relations (e.g. "customer.first_name"). ' +
18
- 'Filters support operators: $eq, $ne, $in, $nin, $like, $ilike, $gt, $gte, $lt, $lte.',
19
- inputSchema: {
20
- entity: zod_1.z.enum(ALLOWED_ENTITIES),
21
- fields: zod_1.z.array(zod_1.z.string()).min(1).describe('Fields to return, e.g. ["id", "email", "orders.id"]'),
22
- filters: zod_1.z.record(zod_1.z.unknown()).optional().describe('Filter conditions, e.g. { status: "completed" }'),
23
- limit: zod_1.z.coerce.number().int().min(1).max(100).optional().default(20),
24
- offset: zod_1.z.coerce.number().int().min(0).optional().default(0)
25
- }
26
- }, async ({ entity, fields, filters, limit, offset }) => {
27
- const query = scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
28
- const { data, metadata } = await query.graph({
29
- entity,
30
- fields,
31
- filters: filters ?? {},
32
- pagination: { take: limit, skip: offset }
33
- });
34
- return {
35
- content: [{
36
- type: 'text',
37
- text: JSON.stringify({ data, count: metadata?.count ?? data.length, limit, offset }, null, 2)
38
- }]
39
- };
40
- });
41
- }
42
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbWNwL3Rvb2xzL3F1ZXJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBY0EsOENBa0NDO0FBOUNELHFEQUFxRTtBQUNyRSw2QkFBdUI7QUFFdkIsTUFBTSxnQkFBZ0IsR0FBRztJQUN4QixPQUFPLEVBQUUsU0FBUyxFQUFFLGlCQUFpQixFQUFFLFVBQVUsRUFBRSxnQkFBZ0I7SUFDbkUsYUFBYSxFQUFFLE1BQU0sRUFBRSxpQkFBaUIsRUFBRSxlQUFlLEVBQUUsT0FBTztJQUNsRSxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxlQUFlO0lBQ2pFLGNBQWMsRUFBRSxvQkFBb0IsRUFBRSxXQUFXLEVBQUUsZUFBZTtJQUNsRSxhQUFhLEVBQUUsZ0JBQWdCLEVBQUUsaUJBQWlCLEVBQUUsZ0JBQWdCO0lBQ3BFLFNBQVMsRUFBRSxZQUFZLEVBQUUsY0FBYztDQUN2QyxDQUFBO0FBRUQsU0FBZ0IsaUJBQWlCLENBQUMsTUFBaUIsRUFBRSxLQUFzQjtJQUMxRSxNQUFNLENBQUMsWUFBWSxDQUNsQixPQUFPLEVBQ1A7UUFDQyxXQUFXLEVBQ1YsZ0ZBQWdGLGdCQUFnQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSTtZQUMvRywrREFBK0Q7WUFDL0Qsc0ZBQXNGO1FBQ3ZGLFdBQVcsRUFBRTtZQUNaLE1BQU0sRUFBRSxPQUFDLENBQUMsSUFBSSxDQUFDLGdCQUF5QyxDQUFDO1lBQ3pELE1BQU0sRUFBRSxPQUFDLENBQUMsS0FBSyxDQUFDLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMscURBQXFELENBQUM7WUFDbEcsT0FBTyxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQUMsT0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLGlEQUFpRCxDQUFDO1lBQ3JHLEtBQUssRUFBRSxPQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNyRSxNQUFNLEVBQUUsT0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztTQUM1RDtLQUNELEVBQ0QsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7UUFDcEQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUU1RCxNQUFNLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQztZQUM1QyxNQUFNO1lBQ04sTUFBTTtZQUNOLE9BQU8sRUFBRSxPQUFPLElBQUksRUFBRTtZQUN0QixVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUU7U0FDekMsQ0FBQyxDQUFBO1FBRUYsT0FBTztZQUNOLE9BQU8sRUFBRSxDQUFDO29CQUNULElBQUksRUFBRSxNQUFlO29CQUNyQixJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2lCQUM3RixDQUFDO1NBQ0YsQ0FBQTtJQUNGLENBQUMsQ0FDRCxDQUFBO0FBQ0YsQ0FBQyJ9