medusa-plugin-mcp 0.1.0

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.
Files changed (44) hide show
  1. package/.medusa/server/medusa-config.d.ts +1 -0
  2. package/.medusa/server/medusa-config.js +23 -0
  3. package/.medusa/server/src/admin/index.js +192 -0
  4. package/.medusa/server/src/admin/index.mjs +191 -0
  5. package/.medusa/server/src/api/admin/chat/route.d.ts +3 -0
  6. package/.medusa/server/src/api/admin/chat/route.js +102 -0
  7. package/.medusa/server/src/api/admin/mcp/route.d.ts +4 -0
  8. package/.medusa/server/src/api/admin/mcp/route.js +60 -0
  9. package/.medusa/server/src/api/middlewares.d.ts +2 -0
  10. package/.medusa/server/src/api/middlewares.js +24 -0
  11. package/.medusa/server/src/api/validators.d.ts +24 -0
  12. package/.medusa/server/src/api/validators.js +11 -0
  13. package/.medusa/server/src/lib/llm-provider.d.ts +32 -0
  14. package/.medusa/server/src/lib/llm-provider.js +22 -0
  15. package/.medusa/server/src/lib/providers/anthropic.d.ts +11 -0
  16. package/.medusa/server/src/lib/providers/anthropic.js +53 -0
  17. package/.medusa/server/src/lib/providers/ollama.d.ts +11 -0
  18. package/.medusa/server/src/lib/providers/ollama.js +39 -0
  19. package/.medusa/server/src/lib/providers/openai.d.ts +12 -0
  20. package/.medusa/server/src/lib/providers/openai.js +49 -0
  21. package/.medusa/server/src/mcp/server.d.ts +3 -0
  22. package/.medusa/server/src/mcp/server.js +42 -0
  23. package/.medusa/server/src/mcp/tools/automations.d.ts +3 -0
  24. package/.medusa/server/src/mcp/tools/automations.js +176 -0
  25. package/.medusa/server/src/mcp/tools/customers.d.ts +3 -0
  26. package/.medusa/server/src/mcp/tools/customers.js +72 -0
  27. package/.medusa/server/src/mcp/tools/inventory.d.ts +3 -0
  28. package/.medusa/server/src/mcp/tools/inventory.js +70 -0
  29. package/.medusa/server/src/mcp/tools/orders.d.ts +3 -0
  30. package/.medusa/server/src/mcp/tools/orders.js +80 -0
  31. package/.medusa/server/src/mcp/tools/products.d.ts +3 -0
  32. package/.medusa/server/src/mcp/tools/products.js +72 -0
  33. package/.medusa/server/src/mcp/tools/query.d.ts +3 -0
  34. package/.medusa/server/src/mcp/tools/query.js +42 -0
  35. package/.medusa/server/src/mcp/tools/statistics.d.ts +3 -0
  36. package/.medusa/server/src/mcp/tools/statistics.js +10 -0
  37. package/.medusa/server/src/modules/mcp/index.d.ts +7 -0
  38. package/.medusa/server/src/modules/mcp/index.js +25 -0
  39. package/.medusa/server/src/modules/mcp/service.d.ts +8 -0
  40. package/.medusa/server/src/modules/mcp/service.js +15 -0
  41. package/.medusa/server/src/types.d.ts +7 -0
  42. package/.medusa/server/src/types.js +3 -0
  43. package/LICENSE.md +73 -0
  44. package/package.json +98 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@medusajs/framework/utils");
4
+ (0, utils_1.loadEnv)(process.env.NODE_ENV || 'development', process.cwd());
5
+ module.exports = (0, utils_1.defineConfig)({
6
+ projectConfig: {
7
+ redisUrl: process.env.REDIS_URL,
8
+ databaseUrl: process.env.DATABASE_URL,
9
+ http: {
10
+ storeCors: process.env.STORE_CORS || 'http://localhost:5173',
11
+ adminCors: process.env.ADMIN_CORS || 'http://localhost:5173,http://localhost:9000',
12
+ authCors: process.env.AUTH_CORS || 'http://localhost:5173,http://localhost:9000',
13
+ jwtSecret: process.env.JWT_SECRET || 'supersecret',
14
+ cookieSecret: process.env.COOKIE_SECRET || 'supersecret'
15
+ }
16
+ },
17
+ modules: [
18
+ {
19
+ resolve: './src/modules/mcp'
20
+ }
21
+ ]
22
+ });
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVkdXNhLWNvbmZpZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL21lZHVzYS1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFBaUU7QUFFakUsSUFBQSxlQUFPLEVBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLElBQUksYUFBYSxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFBO0FBRTdELE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBQSxvQkFBWSxFQUFDO0lBQzdCLGFBQWEsRUFBRTtRQUNkLFFBQVEsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVM7UUFDL0IsV0FBVyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWTtRQUNyQyxJQUFJLEVBQUU7WUFDTCxTQUFTLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksdUJBQXVCO1lBQzVELFNBQVMsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSw2Q0FBNkM7WUFDbEYsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxJQUFJLDZDQUE2QztZQUNoRixTQUFTLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksYUFBYTtZQUNsRCxZQUFZLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLElBQUksYUFBYTtTQUN4RDtLQUNEO0lBQ0QsT0FBTyxFQUFFO1FBQ1I7WUFDQyxPQUFPLEVBQUUsbUJBQW1CO1NBQzVCO0tBQ0Q7Q0FDRCxDQUFDLENBQUEifQ==
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const react = require("react");
4
+ const adminSdk = require("@medusajs/admin-sdk");
5
+ const icons = require("@medusajs/icons");
6
+ const ui = require("@medusajs/ui");
7
+ const reactQuery = require("@tanstack/react-query");
8
+ const Medusa = require("@medusajs/js-sdk");
9
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
10
+ const Medusa__default = /* @__PURE__ */ _interopDefault(Medusa);
11
+ const sdk = new Medusa__default.default({
12
+ baseUrl: "",
13
+ auth: { type: "session" }
14
+ });
15
+ const useChat = () => {
16
+ return reactQuery.useMutation({
17
+ mutationFn: (messages) => sdk.client.fetch("/admin/chat", {
18
+ method: "POST",
19
+ body: { messages }
20
+ })
21
+ });
22
+ };
23
+ const ToolCallBlock = ({ toolCall }) => {
24
+ const [expanded, setExpanded] = react.useState(false);
25
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "my-1", children: [
26
+ /* @__PURE__ */ jsxRuntime.jsxs(
27
+ "button",
28
+ {
29
+ onClick: () => setExpanded(!expanded),
30
+ className: "flex items-center gap-1.5 text-xs text-ui-fg-subtle hover:text-ui-fg-base transition-colors",
31
+ children: [
32
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "grey", children: toolCall.name }),
33
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: expanded ? "▼" : "▶" })
34
+ ]
35
+ }
36
+ ),
37
+ expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 ml-2", children: /* @__PURE__ */ jsxRuntime.jsx(
38
+ ui.CodeBlock,
39
+ {
40
+ snippets: [
41
+ {
42
+ label: `${toolCall.name}(${JSON.stringify(toolCall.args)})`,
43
+ language: "json",
44
+ code: toolCall.result,
45
+ hideLineNumbers: true
46
+ }
47
+ ],
48
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.CodeBlock.Body, { className: "text-xs [&_code]:text-xs max-h-48 overflow-y-auto" })
49
+ }
50
+ ) })
51
+ ] });
52
+ };
53
+ const ChatMessage = ({ role, content, toolCalls }) => {
54
+ if (role === "user") {
55
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[80%] self-end rounded-lg px-4 py-2.5 bg-ui-bg-subtle text-ui-fg-base", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: content }) });
56
+ }
57
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-[90%] self-start flex flex-col gap-1", children: [
58
+ toolCalls && toolCalls.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-0.5", children: toolCalls.map((tc, i) => /* @__PURE__ */ jsxRuntime.jsx(ToolCallBlock, { toolCall: tc }, i)) }),
59
+ content && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg px-4 py-2.5 bg-ui-bg-base border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "whitespace-pre-wrap", children: content }) })
60
+ ] });
61
+ };
62
+ const config = adminSdk.defineRouteConfig({
63
+ label: "Chat",
64
+ icon: icons.Robot
65
+ });
66
+ const handle = { breadcrumb: () => "Chat" };
67
+ const ChatPage = () => {
68
+ const [messages, setMessages] = react.useState([]);
69
+ const [input, setInput] = react.useState("");
70
+ const messagesEndRef = react.useRef(null);
71
+ const inputRef = react.useRef(null);
72
+ const { mutate: sendChat, isPending } = useChat();
73
+ react.useEffect(() => {
74
+ var _a;
75
+ (_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
76
+ }, [messages]);
77
+ const handleSend = () => {
78
+ const text = input.trim();
79
+ if (!text || isPending) return;
80
+ const userMessage = { role: "user", content: text };
81
+ const updatedMessages = [...messages, userMessage];
82
+ setMessages(updatedMessages);
83
+ setInput("");
84
+ const apiMessages = updatedMessages.map(({ role, content }) => ({ role, content }));
85
+ sendChat(apiMessages, {
86
+ onSuccess: (data) => {
87
+ setMessages((prev) => [
88
+ ...prev,
89
+ {
90
+ role: "assistant",
91
+ content: data.content,
92
+ toolCalls: data.tool_calls
93
+ }
94
+ ]);
95
+ },
96
+ onError: (err) => {
97
+ setMessages((prev) => [
98
+ ...prev,
99
+ {
100
+ role: "assistant",
101
+ content: `Error: ${err instanceof Error ? err.message : "Something went wrong"}`
102
+ }
103
+ ]);
104
+ }
105
+ });
106
+ };
107
+ const handleKeyDown = (e) => {
108
+ if (e.key === "Enter" && !e.shiftKey) {
109
+ e.preventDefault();
110
+ handleSend();
111
+ }
112
+ };
113
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col h-[calc(100vh-120px)] p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "flex flex-col flex-1 p-0 overflow-hidden", children: [
114
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-4 border-b border-ui-border-base", children: [
115
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Chat" }),
116
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle mt-1", children: "Ask questions about your store data or manage automations using natural language." })
117
+ ] }),
118
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto px-6 py-4 flex flex-col gap-3", children: [
119
+ messages.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: 'Send a message to get started. Try "Show me recent orders" or "List my automations."' }) }),
120
+ messages.map((msg, i) => /* @__PURE__ */ jsxRuntime.jsx(
121
+ ChatMessage,
122
+ {
123
+ role: msg.role,
124
+ content: msg.content,
125
+ toolCalls: msg.toolCalls
126
+ },
127
+ i
128
+ )),
129
+ isPending && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "self-start", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted animate-pulse", children: "Thinking..." }) }),
130
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
131
+ ] }),
132
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4 border-t border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
133
+ /* @__PURE__ */ jsxRuntime.jsx(
134
+ ui.Input,
135
+ {
136
+ ref: inputRef,
137
+ value: input,
138
+ onChange: (e) => setInput(e.target.value),
139
+ onKeyDown: handleKeyDown,
140
+ placeholder: "Ask a question...",
141
+ disabled: isPending,
142
+ className: "flex-1"
143
+ }
144
+ ),
145
+ /* @__PURE__ */ jsxRuntime.jsx(
146
+ ui.Button,
147
+ {
148
+ onClick: handleSend,
149
+ disabled: !input.trim() || isPending,
150
+ isLoading: isPending,
151
+ children: "Send"
152
+ }
153
+ )
154
+ ] }) })
155
+ ] }) });
156
+ };
157
+ const widgetModule = { widgets: [] };
158
+ const routeModule = {
159
+ routes: [
160
+ {
161
+ Component: ChatPage,
162
+ path: "/chat",
163
+ handle
164
+ }
165
+ ]
166
+ };
167
+ const menuItemModule = {
168
+ menuItems: [
169
+ {
170
+ label: config.label,
171
+ icon: config.icon,
172
+ path: "/chat",
173
+ nested: void 0,
174
+ rank: void 0,
175
+ translationNs: void 0
176
+ }
177
+ ]
178
+ };
179
+ const formModule = { customFields: {} };
180
+ const displayModule = {
181
+ displays: {}
182
+ };
183
+ const i18nModule = { resources: {} };
184
+ const plugin = {
185
+ widgetModule,
186
+ routeModule,
187
+ menuItemModule,
188
+ formModule,
189
+ displayModule,
190
+ i18nModule
191
+ };
192
+ module.exports = plugin;
@@ -0,0 +1,191 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect } from "react";
3
+ import { defineRouteConfig } from "@medusajs/admin-sdk";
4
+ import { Robot } from "@medusajs/icons";
5
+ import { Text, Badge, CodeBlock, Container, Heading, Input, Button } from "@medusajs/ui";
6
+ import { useMutation } from "@tanstack/react-query";
7
+ import Medusa from "@medusajs/js-sdk";
8
+ const sdk = new Medusa({
9
+ baseUrl: "",
10
+ auth: { type: "session" }
11
+ });
12
+ const useChat = () => {
13
+ return useMutation({
14
+ mutationFn: (messages) => sdk.client.fetch("/admin/chat", {
15
+ method: "POST",
16
+ body: { messages }
17
+ })
18
+ });
19
+ };
20
+ const ToolCallBlock = ({ toolCall }) => {
21
+ const [expanded, setExpanded] = useState(false);
22
+ return /* @__PURE__ */ jsxs("div", { className: "my-1", children: [
23
+ /* @__PURE__ */ jsxs(
24
+ "button",
25
+ {
26
+ onClick: () => setExpanded(!expanded),
27
+ className: "flex items-center gap-1.5 text-xs text-ui-fg-subtle hover:text-ui-fg-base transition-colors",
28
+ children: [
29
+ /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "grey", children: toolCall.name }),
30
+ /* @__PURE__ */ jsx("span", { children: expanded ? "▼" : "▶" })
31
+ ]
32
+ }
33
+ ),
34
+ expanded && /* @__PURE__ */ jsx("div", { className: "mt-1 ml-2", children: /* @__PURE__ */ jsx(
35
+ CodeBlock,
36
+ {
37
+ snippets: [
38
+ {
39
+ label: `${toolCall.name}(${JSON.stringify(toolCall.args)})`,
40
+ language: "json",
41
+ code: toolCall.result,
42
+ hideLineNumbers: true
43
+ }
44
+ ],
45
+ children: /* @__PURE__ */ jsx(CodeBlock.Body, { className: "text-xs [&_code]:text-xs max-h-48 overflow-y-auto" })
46
+ }
47
+ ) })
48
+ ] });
49
+ };
50
+ const ChatMessage = ({ role, content, toolCalls }) => {
51
+ if (role === "user") {
52
+ return /* @__PURE__ */ jsx("div", { className: "max-w-[80%] self-end rounded-lg px-4 py-2.5 bg-ui-bg-subtle text-ui-fg-base", children: /* @__PURE__ */ jsx(Text, { size: "small", children: content }) });
53
+ }
54
+ return /* @__PURE__ */ jsxs("div", { className: "max-w-[90%] self-start flex flex-col gap-1", children: [
55
+ toolCalls && toolCalls.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: toolCalls.map((tc, i) => /* @__PURE__ */ jsx(ToolCallBlock, { toolCall: tc }, i)) }),
56
+ content && /* @__PURE__ */ jsx("div", { className: "rounded-lg px-4 py-2.5 bg-ui-bg-base border border-ui-border-base", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "whitespace-pre-wrap", children: content }) })
57
+ ] });
58
+ };
59
+ const config = defineRouteConfig({
60
+ label: "Chat",
61
+ icon: Robot
62
+ });
63
+ const handle = { breadcrumb: () => "Chat" };
64
+ const ChatPage = () => {
65
+ const [messages, setMessages] = useState([]);
66
+ const [input, setInput] = useState("");
67
+ const messagesEndRef = useRef(null);
68
+ const inputRef = useRef(null);
69
+ const { mutate: sendChat, isPending } = useChat();
70
+ useEffect(() => {
71
+ var _a;
72
+ (_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
73
+ }, [messages]);
74
+ const handleSend = () => {
75
+ const text = input.trim();
76
+ if (!text || isPending) return;
77
+ const userMessage = { role: "user", content: text };
78
+ const updatedMessages = [...messages, userMessage];
79
+ setMessages(updatedMessages);
80
+ setInput("");
81
+ const apiMessages = updatedMessages.map(({ role, content }) => ({ role, content }));
82
+ sendChat(apiMessages, {
83
+ onSuccess: (data) => {
84
+ setMessages((prev) => [
85
+ ...prev,
86
+ {
87
+ role: "assistant",
88
+ content: data.content,
89
+ toolCalls: data.tool_calls
90
+ }
91
+ ]);
92
+ },
93
+ onError: (err) => {
94
+ setMessages((prev) => [
95
+ ...prev,
96
+ {
97
+ role: "assistant",
98
+ content: `Error: ${err instanceof Error ? err.message : "Something went wrong"}`
99
+ }
100
+ ]);
101
+ }
102
+ });
103
+ };
104
+ const handleKeyDown = (e) => {
105
+ if (e.key === "Enter" && !e.shiftKey) {
106
+ e.preventDefault();
107
+ handleSend();
108
+ }
109
+ };
110
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col h-[calc(100vh-120px)] p-4", children: /* @__PURE__ */ jsxs(Container, { className: "flex flex-col flex-1 p-0 overflow-hidden", children: [
111
+ /* @__PURE__ */ jsxs("div", { className: "px-6 py-4 border-b border-ui-border-base", children: [
112
+ /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Chat" }),
113
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle mt-1", children: "Ask questions about your store data or manage automations using natural language." })
114
+ ] }),
115
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-6 py-4 flex flex-col gap-3", children: [
116
+ messages.length === 0 && /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted", children: 'Send a message to get started. Try "Show me recent orders" or "List my automations."' }) }),
117
+ messages.map((msg, i) => /* @__PURE__ */ jsx(
118
+ ChatMessage,
119
+ {
120
+ role: msg.role,
121
+ content: msg.content,
122
+ toolCalls: msg.toolCalls
123
+ },
124
+ i
125
+ )),
126
+ isPending && /* @__PURE__ */ jsx("div", { className: "self-start", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-muted animate-pulse", children: "Thinking..." }) }),
127
+ /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
128
+ ] }),
129
+ /* @__PURE__ */ jsx("div", { className: "px-6 py-4 border-t border-ui-border-base", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
130
+ /* @__PURE__ */ jsx(
131
+ Input,
132
+ {
133
+ ref: inputRef,
134
+ value: input,
135
+ onChange: (e) => setInput(e.target.value),
136
+ onKeyDown: handleKeyDown,
137
+ placeholder: "Ask a question...",
138
+ disabled: isPending,
139
+ className: "flex-1"
140
+ }
141
+ ),
142
+ /* @__PURE__ */ jsx(
143
+ Button,
144
+ {
145
+ onClick: handleSend,
146
+ disabled: !input.trim() || isPending,
147
+ isLoading: isPending,
148
+ children: "Send"
149
+ }
150
+ )
151
+ ] }) })
152
+ ] }) });
153
+ };
154
+ const widgetModule = { widgets: [] };
155
+ const routeModule = {
156
+ routes: [
157
+ {
158
+ Component: ChatPage,
159
+ path: "/chat",
160
+ handle
161
+ }
162
+ ]
163
+ };
164
+ const menuItemModule = {
165
+ menuItems: [
166
+ {
167
+ label: config.label,
168
+ icon: config.icon,
169
+ path: "/chat",
170
+ nested: void 0,
171
+ rank: void 0,
172
+ translationNs: void 0
173
+ }
174
+ ]
175
+ };
176
+ const formModule = { customFields: {} };
177
+ const displayModule = {
178
+ displays: {}
179
+ };
180
+ const i18nModule = { resources: {} };
181
+ const plugin = {
182
+ widgetModule,
183
+ routeModule,
184
+ menuItemModule,
185
+ formModule,
186
+ displayModule,
187
+ i18nModule
188
+ };
189
+ export {
190
+ plugin as default
191
+ };
@@ -0,0 +1,3 @@
1
+ import { AuthenticatedMedusaRequest, MedusaResponse } from '@medusajs/framework/http';
2
+ import { AdminPostChatType } from '../../validators';
3
+ export declare const POST: (req: AuthenticatedMedusaRequest<AdminPostChatType>, res: MedusaResponse) => Promise<MedusaResponse | undefined>;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const zod_to_json_schema_1 = require("zod-to-json-schema");
5
+ const server_1 = require("../../../mcp/server");
6
+ const llm_provider_1 = require("../../../lib/llm-provider");
7
+ const mcp_1 = require("../../../modules/mcp");
8
+ const DEFAULT_SYSTEM_PROMPT = `You are a helpful assistant for a Medusa commerce store admin. You have access to tools that let you query store data (orders, customers, products, inventory) and manage automations. Use the tools to answer questions with real data. Be concise and helpful. When displaying data, format it clearly.`;
9
+ const POST = async (req, res) => {
10
+ try {
11
+ const mcpService = req.scope.resolve(mcp_1.MCP_MODULE);
12
+ const options = mcpService.getOptions();
13
+ if (!options?.provider) {
14
+ return res.status(500).json({
15
+ error: 'MCP plugin options not configured. Set provider, model, and apiKey in medusa-config.ts.'
16
+ });
17
+ }
18
+ if (options.provider !== 'ollama' && !options.apiKey) {
19
+ return res.status(500).json({
20
+ error: `API key required for ${options.provider} provider. Set MCP_LLM_API_KEY in your environment.`
21
+ });
22
+ }
23
+ const provider = (0, llm_provider_1.createProvider)(options);
24
+ const mcpServer = await (0, server_1.createMcpServer)(req.scope);
25
+ // Extract tool definitions from MCP server internals
26
+ const registeredTools = mcpServer._registeredTools;
27
+ const toolDefs = [];
28
+ const toolHandlers = new Map();
29
+ for (const [name, tool] of Object.entries(registeredTools)) {
30
+ const jsonSchema = tool.inputSchema
31
+ ? (0, zod_to_json_schema_1.zodToJsonSchema)(tool.inputSchema)
32
+ : { type: 'object', properties: {} };
33
+ toolDefs.push({
34
+ name,
35
+ description: tool.description ?? '',
36
+ inputSchema: jsonSchema
37
+ });
38
+ toolHandlers.set(name, tool.handler);
39
+ }
40
+ const systemPrompt = options.systemPrompt
41
+ ? `${DEFAULT_SYSTEM_PROMPT}\n\n${options.systemPrompt}`
42
+ : DEFAULT_SYSTEM_PROMPT;
43
+ // Build conversation with tool-use loop
44
+ let messages = [...req.body.messages];
45
+ const allToolCalls = [];
46
+ const MAX_TOOL_ROUNDS = 10;
47
+ for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
48
+ const response = await provider.chat({
49
+ messages,
50
+ tools: toolDefs,
51
+ systemPrompt
52
+ });
53
+ if (response.toolCalls.length === 0) {
54
+ return res.json({
55
+ role: 'assistant',
56
+ content: response.content,
57
+ tool_calls: allToolCalls.length > 0 ? allToolCalls : undefined
58
+ });
59
+ }
60
+ // Execute each tool call via the handler directly
61
+ const toolResults = [];
62
+ for (const tc of response.toolCalls) {
63
+ let result;
64
+ try {
65
+ const handler = toolHandlers.get(tc.name);
66
+ if (!handler)
67
+ throw new Error(`Unknown tool: ${tc.name}`);
68
+ const mcpResult = await handler(tc.args);
69
+ result = mcpResult?.content?.map((c) => c.text ?? JSON.stringify(c)).join('\n') ?? 'No result';
70
+ }
71
+ catch (err) {
72
+ result = `Error: ${err instanceof Error ? err.message : String(err)}`;
73
+ }
74
+ toolResults.push(result);
75
+ allToolCalls.push({ name: tc.name, args: tc.args, result });
76
+ }
77
+ const toolSummary = response.toolCalls.map((tc, i) => `[Tool: ${tc.name}]\nArgs: ${JSON.stringify(tc.args)}\nResult: ${toolResults[i]}`).join('\n\n');
78
+ if (response.content) {
79
+ messages.push({ role: 'assistant', content: response.content });
80
+ }
81
+ messages.push({
82
+ role: 'user',
83
+ content: `[Tool results]\n${toolSummary}`
84
+ });
85
+ }
86
+ return res.json({
87
+ role: 'assistant',
88
+ content: 'I reached the maximum number of tool calls. Here is what I found so far.',
89
+ tool_calls: allToolCalls.length > 0 ? allToolCalls : undefined
90
+ });
91
+ }
92
+ catch (err) {
93
+ console.error('[Chat] Error:', err);
94
+ if (!res.headersSent) {
95
+ res.status(500).json({
96
+ error: err instanceof Error ? err.message : 'Internal server error'
97
+ });
98
+ }
99
+ }
100
+ };
101
+ exports.POST = POST;
102
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2NoYXQvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsMkRBQW9EO0FBRXBELGdEQUFxRDtBQUNyRCw0REFBaUc7QUFDakcsOENBQWlEO0FBR2pELE1BQU0scUJBQXFCLEdBQUcsMlNBQTJTLENBQUE7QUFFbFUsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUN4QixHQUFrRCxFQUNsRCxHQUFtQixFQUNsQixFQUFFO0lBQ0gsSUFBSSxDQUFDO1FBQ0osTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsZ0JBQVUsQ0FBZSxDQUFBO1FBQzlELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQTtRQUV2QyxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxDQUFDO1lBQ3hCLE9BQU8sR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQzNCLEtBQUssRUFBRSx5RkFBeUY7YUFDaEcsQ0FBQyxDQUFBO1FBQ0gsQ0FBQztRQUVELElBQUksT0FBTyxDQUFDLFFBQVEsS0FBSyxRQUFRLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdEQsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDM0IsS0FBSyxFQUFFLHdCQUF3QixPQUFPLENBQUMsUUFBUSxxREFBcUQ7YUFDcEcsQ0FBQyxDQUFBO1FBQ0gsQ0FBQztRQUVELE1BQU0sUUFBUSxHQUFHLElBQUEsNkJBQWMsRUFBQyxPQUFPLENBQUMsQ0FBQTtRQUN4QyxNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUEsd0JBQWUsRUFBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUE7UUFFbEQscURBQXFEO1FBQ3JELE1BQU0sZUFBZSxHQUFJLFNBQWlCLENBQUMsZ0JBQXVDLENBQUE7UUFDbEYsTUFBTSxRQUFRLEdBQXFCLEVBQUUsQ0FBQTtRQUNyQyxNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBMkQsQ0FBQTtRQUV2RixLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1lBQzVELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXO2dCQUNsQyxDQUFDLENBQUMsSUFBQSxvQ0FBZSxFQUFDLElBQUksQ0FBQyxXQUFXLENBQUM7Z0JBQ25DLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxDQUFBO1lBQ3JDLFFBQVEsQ0FBQyxJQUFJLENBQUM7Z0JBQ2IsSUFBSTtnQkFDSixXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVcsSUFBSSxFQUFFO2dCQUNuQyxXQUFXLEVBQUUsVUFBcUM7YUFDbEQsQ0FBQyxDQUFBO1lBQ0YsWUFBWSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQ3JDLENBQUM7UUFFRCxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsWUFBWTtZQUN4QyxDQUFDLENBQUMsR0FBRyxxQkFBcUIsT0FBTyxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ3ZELENBQUMsQ0FBQyxxQkFBcUIsQ0FBQTtRQUV4Qix3Q0FBd0M7UUFDeEMsSUFBSSxRQUFRLEdBQWtCLENBQUMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3BELE1BQU0sWUFBWSxHQUEyRSxFQUFFLENBQUE7UUFDL0YsTUFBTSxlQUFlLEdBQUcsRUFBRSxDQUFBO1FBRTFCLEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxlQUFlLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUN0RCxNQUFNLFFBQVEsR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLENBQUM7Z0JBQ3BDLFFBQVE7Z0JBQ1IsS0FBSyxFQUFFLFFBQVE7Z0JBQ2YsWUFBWTthQUNaLENBQUMsQ0FBQTtZQUVGLElBQUksUUFBUSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ3JDLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQztvQkFDZixJQUFJLEVBQUUsV0FBVztvQkFDakIsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPO29CQUN6QixVQUFVLEVBQUUsWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsU0FBUztpQkFDOUQsQ0FBQyxDQUFBO1lBQ0gsQ0FBQztZQUVELGtEQUFrRDtZQUNsRCxNQUFNLFdBQVcsR0FBYSxFQUFFLENBQUE7WUFDaEMsS0FBSyxNQUFNLEVBQUUsSUFBSSxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ3JDLElBQUksTUFBYyxDQUFBO2dCQUNsQixJQUFJLENBQUM7b0JBQ0osTUFBTSxPQUFPLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUE7b0JBQ3pDLElBQUksQ0FBQyxPQUFPO3dCQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFBO29CQUN6RCxNQUFNLFNBQVMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUE7b0JBQ3hDLE1BQU0sR0FBRyxTQUFTLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLFdBQVcsQ0FBQTtnQkFDcEcsQ0FBQztnQkFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO29CQUNkLE1BQU0sR0FBRyxVQUFVLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFBO2dCQUN0RSxDQUFDO2dCQUNELFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7Z0JBQ3hCLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO1lBQzVELENBQUM7WUFFRCxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUNwRCxVQUFVLEVBQUUsQ0FBQyxJQUFJLFlBQVksSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQ2pGLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBRWQsSUFBSSxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ3RCLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQTtZQUNoRSxDQUFDO1lBQ0QsUUFBUSxDQUFDLElBQUksQ0FBQztnQkFDYixJQUFJLEVBQUUsTUFBTTtnQkFDWixPQUFPLEVBQUUsbUJBQW1CLFdBQVcsRUFBRTthQUN6QyxDQUFDLENBQUE7UUFDSCxDQUFDO1FBRUQsT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDO1lBQ2YsSUFBSSxFQUFFLFdBQVc7WUFDakIsT0FBTyxFQUFFLDBFQUEwRTtZQUNuRixVQUFVLEVBQUUsWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsU0FBUztTQUM5RCxDQUFDLENBQUE7SUFDSCxDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNkLE9BQU8sQ0FBQyxLQUFLLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxDQUFBO1FBQ25DLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDdEIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQ3BCLEtBQUssRUFBRSxHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyx1QkFBdUI7YUFDbkUsQ0FBQyxDQUFBO1FBQ0gsQ0FBQztJQUNGLENBQUM7QUFDRixDQUFDLENBQUE7QUExR1ksUUFBQSxJQUFJLFFBMEdoQiJ9
@@ -0,0 +1,4 @@
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>;
@@ -0,0 +1,60 @@
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 = await (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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL21jcC9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBd0M7QUFFeEMsMEZBQWtHO0FBQ2xHLGlFQUF3RTtBQUN4RSxnREFBcUQ7QUFFckQsOERBQThEO0FBQzlELE1BQU0sUUFBUSxHQUFrRCxFQUFFLENBQUE7QUFFM0QsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLEdBQStCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ2xGLElBQUksQ0FBQztRQUNKLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQXVCLENBQUE7UUFDckUsSUFBSSxTQUF3QyxDQUFBO1FBRTVDLElBQUksU0FBUyxJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ3RDLG1DQUFtQztZQUNuQyxTQUFTLEdBQUcsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBQ2hDLENBQUM7YUFBTSxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUEsOEJBQW1CLEVBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDeEQsNkJBQTZCO1lBQzdCLFNBQVMsR0FBRyxJQUFJLGlEQUE2QixDQUFDO2dCQUM3QyxrQkFBa0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFBLHdCQUFVLEdBQUU7Z0JBQ3RDLGtCQUFrQixFQUFFLElBQUk7Z0JBQ3hCLG9CQUFvQixFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUU7b0JBQzVCLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUE7Z0JBQ3pCLENBQUM7YUFDRCxDQUFDLENBQUE7WUFFRixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEsd0JBQWUsRUFBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDL0MsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBQ2hDLENBQUM7YUFBTSxDQUFDO1lBQ1AsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQ3BCLE9BQU8sRUFBRSxLQUFLO2dCQUNkLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsdURBQXVELEVBQUU7Z0JBQ3pGLEVBQUUsRUFBRSxJQUFJO2FBQ1IsQ0FBQyxDQUFBO1lBQ0YsT0FBTTtRQUNQLENBQUM7UUFFRCxNQUFNLFNBQVMsQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDbEQsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDZCxPQUFPLENBQUMsS0FBSyxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsQ0FBQTtRQUNsQyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3RCLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNwQixPQUFPLEVBQUUsS0FBSztnQkFDZCxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLHVCQUF1QixFQUFFO2dCQUN6RCxFQUFFLEVBQUUsSUFBSTthQUNSLENBQUMsQ0FBQTtRQUNILENBQUM7SUFDRixDQUFDO0FBQ0YsQ0FBQyxDQUFBO0FBeENZLFFBQUEsSUFBSSxRQXdDaEI7QUFFTSxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQUUsSUFBZ0MsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDbEYsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEtBQUssRUFBRSxvQkFBb0IsRUFBRSxDQUFDLENBQUMsQ0FBQTtBQUN4RSxDQUFDLENBQUE7QUFGWSxRQUFBLEdBQUcsT0FFZjtBQUVNLE1BQU0sTUFBTSxHQUFHLEtBQUssRUFBRSxJQUFnQyxFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNyRixHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsS0FBSyxFQUFFLG9CQUFvQixFQUFFLENBQUMsQ0FBQyxDQUFBO0FBQ3hFLENBQUMsQ0FBQTtBQUZZLFFBQUEsTUFBTSxVQUVsQiJ9
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@medusajs/framework/http").MiddlewaresConfig;
2
+ export default _default;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const http_1 = require("@medusajs/framework/http");
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
+ exports.default = (0, http_1.defineMiddlewares)([
13
+ {
14
+ matcher: '/admin/mcp',
15
+ method: ['GET', 'POST', 'DELETE'],
16
+ middlewares: [exposeMcpHeaders]
17
+ },
18
+ {
19
+ matcher: '/admin/chat',
20
+ method: ['POST'],
21
+ middlewares: [(0, http_1.validateAndTransformBody)(validators_1.AdminPostChat)]
22
+ }
23
+ ]);
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXBpL21pZGRsZXdhcmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbURBS2lDO0FBRWpDLDZDQUE0QztBQUU1QyxTQUFTLGdCQUFnQixDQUN4QixHQUFrQixFQUNsQixHQUFtQixFQUNuQixJQUFrQjtJQUVsQixHQUFHLENBQUMsU0FBUyxDQUFDLCtCQUErQixFQUFFLGdCQUFnQixDQUFDLENBQUE7SUFDaEUsR0FBRyxDQUFDLFNBQVMsQ0FDWiw4QkFBOEIsRUFDOUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLDhCQUE4QixDQUFDLElBQUksRUFBRSxFQUFFLGdCQUFnQixDQUFDO1NBQ3JFLE1BQU0sQ0FBQyxPQUFPLENBQUM7U0FDZixJQUFJLENBQUMsSUFBSSxDQUFDLENBQ1osQ0FBQTtJQUNELElBQUksRUFBRSxDQUFBO0FBQ1AsQ0FBQztBQUVELGtCQUFlLElBQUEsd0JBQWlCLEVBQUM7SUFDaEM7UUFDQyxPQUFPLEVBQUUsWUFBWTtRQUNyQixNQUFNLEVBQUUsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQztRQUNqQyxXQUFXLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQztLQUMvQjtJQUNEO1FBQ0MsT0FBTyxFQUFFLGFBQWE7UUFDdEIsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDO1FBQ2hCLFdBQVcsRUFBRSxDQUFDLElBQUEsK0JBQXdCLEVBQUMsMEJBQWEsQ0FBQyxDQUFDO0tBQ3REO0NBQ0QsQ0FBQyxDQUFBIn0=
@@ -0,0 +1,24 @@
1
+ import { z } from '@medusajs/framework/zod';
2
+ export declare const AdminPostChat: z.ZodObject<{
3
+ messages: z.ZodArray<z.ZodObject<{
4
+ role: z.ZodEnum<["user", "assistant"]>;
5
+ content: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ role: "user" | "assistant";
8
+ content: string;
9
+ }, {
10
+ role: "user" | "assistant";
11
+ content: string;
12
+ }>, "many">;
13
+ }, "strip", z.ZodTypeAny, {
14
+ messages: {
15
+ role: "user" | "assistant";
16
+ content: string;
17
+ }[];
18
+ }, {
19
+ messages: {
20
+ role: "user" | "assistant";
21
+ content: string;
22
+ }[];
23
+ }>;
24
+ export type AdminPostChatType = z.infer<typeof AdminPostChat>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AdminPostChat = void 0;
4
+ const zod_1 = require("@medusajs/framework/zod");
5
+ exports.AdminPostChat = zod_1.z.object({
6
+ messages: zod_1.z.array(zod_1.z.object({
7
+ role: zod_1.z.enum(['user', 'assistant']),
8
+ content: zod_1.z.string()
9
+ })).min(1)
10
+ });
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcGkvdmFsaWRhdG9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxpREFBMkM7QUFFOUIsUUFBQSxhQUFhLEdBQUcsT0FBQyxDQUFDLE1BQU0sQ0FBQztJQUNyQyxRQUFRLEVBQUUsT0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFDLENBQUMsTUFBTSxDQUFDO1FBQzFCLElBQUksRUFBRSxPQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ25DLE9BQU8sRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFO0tBQ25CLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Q0FDVixDQUFDLENBQUEifQ==