vendure-mcp-graphql 1.0.0 → 1.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.
- package/README.md +52 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +89 -5
- package/dist/src/tools/graphql-operations.d.ts +21 -0
- package/dist/src/tools/graphql-operations.js +40 -0
- package/package.json +4 -1
- package/CHANGELOG.md +0 -5
- package/index.ts +0 -275
- package/src/client.ts +0 -70
- package/src/tools/graphql-operations.ts +0 -190
- package/src/tools/index.ts +0 -1
- package/tsconfig.json +0 -21
package/README.md
CHANGED
|
@@ -27,11 +27,59 @@ Configure as an MCP server in your IDE (like Claude Desktop):
|
|
|
27
27
|
}
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
##
|
|
30
|
+
## Tools
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
### Admin API
|
|
33
|
+
| Tool | Description |
|
|
34
|
+
|------|-------------|
|
|
35
|
+
| `admin_query` | Execute a GraphQL query on the Admin API |
|
|
36
|
+
| `admin_mutation` | Execute a GraphQL mutation on the Admin API |
|
|
37
|
+
| `admin_batch_mutation` | Execute a mutation in bulk for multiple IDs (concurrent) |
|
|
38
|
+
| `get_admin_schema` | Fetch the full Admin API schema introspection |
|
|
39
|
+
| `list_admin_operations` | List all available Admin API queries and mutations |
|
|
40
|
+
|
|
41
|
+
### Shop API
|
|
42
|
+
| Tool | Description |
|
|
43
|
+
|------|-------------|
|
|
44
|
+
| `shop_query` | Execute a GraphQL query on the Shop API |
|
|
45
|
+
| `shop_mutation` | Execute a GraphQL mutation on the Shop API |
|
|
46
|
+
| `shop_batch_mutation` | Execute a mutation in bulk for multiple IDs (concurrent) |
|
|
47
|
+
| `get_shop_schema` | Fetch the full Shop API schema introspection |
|
|
48
|
+
| `list_shop_operations` | List all available Shop API queries and mutations |
|
|
49
|
+
|
|
50
|
+
### Batch Mutations
|
|
51
|
+
|
|
52
|
+
The batch mutation tools allow you to run a single mutation across multiple IDs concurrently. Useful for bulk operations like deleting or updating many records at once.
|
|
53
|
+
|
|
54
|
+
**Parameters:**
|
|
55
|
+
- `mutation` (required) — GraphQL mutation string with an ID variable (e.g. `$id: ID!`)
|
|
56
|
+
- `ids` (required) — Array of IDs to run the mutation for
|
|
57
|
+
- `variableName` — Name of the ID variable in the mutation (default: `"id"`)
|
|
58
|
+
- `extraVariables` — Additional variables to pass alongside each ID
|
|
59
|
+
- `concurrency` — Max concurrent mutations (default: `5`)
|
|
60
|
+
|
|
61
|
+
**Example — bulk delete products:**
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"mutation": "mutation DeleteProduct($id: ID!) { deleteProduct(id: $id) { result } }",
|
|
65
|
+
"ids": ["1", "2", "3"],
|
|
66
|
+
"concurrency": 3
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Returns per-ID results:**
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"total": 3,
|
|
74
|
+
"succeeded": 2,
|
|
75
|
+
"failed": 1,
|
|
76
|
+
"results": [
|
|
77
|
+
{ "id": "1", "success": true, "data": { "deleteProduct": { "result": "DELETED" } } },
|
|
78
|
+
{ "id": "2", "success": true, "data": { "deleteProduct": { "result": "DELETED" } } },
|
|
79
|
+
{ "id": "3", "success": false, "error": "Product not found" }
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
```
|
|
35
83
|
|
|
36
84
|
## License
|
|
37
85
|
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Vendure GraphQL MCP Server
|
|
4
4
|
* Consolidated version for both Vendure Admin and Shop APIs
|
|
5
5
|
*/
|
|
6
6
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -22,10 +22,10 @@ if (existsSync(apiKeyPath)) {
|
|
|
22
22
|
process.env.VENDURE_API_KEY = envConfig.parsed.VENDURE_API_KEY;
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
import { adminQuery, adminMutation, getAdminSchema, getAdminOperations, shopQuery, shopMutation, getShopSchema, getShopOperations, } from "./src/tools/index.js";
|
|
25
|
+
import { adminQuery, adminMutation, adminBatchMutation, getAdminSchema, getAdminOperations, shopQuery, shopMutation, shopBatchMutation, getShopSchema, getShopOperations, } from "./src/tools/index.js";
|
|
26
26
|
const server = new Server({
|
|
27
|
-
name: "
|
|
28
|
-
version: "
|
|
27
|
+
name: "vendure-mcp-graphql",
|
|
28
|
+
version: "1.0.0",
|
|
29
29
|
}, {
|
|
30
30
|
capabilities: {
|
|
31
31
|
tools: {},
|
|
@@ -61,6 +61,39 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
61
61
|
required: ["mutation"],
|
|
62
62
|
},
|
|
63
63
|
},
|
|
64
|
+
{
|
|
65
|
+
name: "admin_batch_mutation",
|
|
66
|
+
description: "Execute a GraphQL mutation in batch for multiple IDs on the Vendure Admin API. " +
|
|
67
|
+
"Runs mutations concurrently and returns aggregated success/failure results per ID. " +
|
|
68
|
+
"Use this for bulk delete, update, or any mutation that takes an ID input.",
|
|
69
|
+
inputSchema: {
|
|
70
|
+
type: "object",
|
|
71
|
+
properties: {
|
|
72
|
+
mutation: {
|
|
73
|
+
type: "string",
|
|
74
|
+
description: "The GraphQL mutation string. Must accept a variable for the ID (e.g. $id: ID!).",
|
|
75
|
+
},
|
|
76
|
+
ids: {
|
|
77
|
+
type: "array",
|
|
78
|
+
items: { type: "string" },
|
|
79
|
+
description: "Array of IDs to execute the mutation for.",
|
|
80
|
+
},
|
|
81
|
+
variableName: {
|
|
82
|
+
type: "string",
|
|
83
|
+
description: 'Name of the variable holding the ID in the mutation. Default: "id".',
|
|
84
|
+
},
|
|
85
|
+
extraVariables: {
|
|
86
|
+
type: "object",
|
|
87
|
+
description: "Additional variables to pass alongside each ID (e.g. { enabled: false }).",
|
|
88
|
+
},
|
|
89
|
+
concurrency: {
|
|
90
|
+
type: "number",
|
|
91
|
+
description: "Max number of concurrent mutations. Default: 5.",
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
required: ["mutation", "ids"],
|
|
95
|
+
},
|
|
96
|
+
},
|
|
64
97
|
{
|
|
65
98
|
name: "get_admin_schema",
|
|
66
99
|
description: "Fetch the full Admin API GraphQL schema introspection. (Warning: Large output)",
|
|
@@ -98,6 +131,39 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
98
131
|
required: ["mutation"],
|
|
99
132
|
},
|
|
100
133
|
},
|
|
134
|
+
{
|
|
135
|
+
name: "shop_batch_mutation",
|
|
136
|
+
description: "Execute a GraphQL mutation in batch for multiple IDs on the Vendure Shop API. " +
|
|
137
|
+
"Runs mutations concurrently and returns aggregated success/failure results per ID. " +
|
|
138
|
+
"Use this for bulk delete, update, or any mutation that takes an ID input.",
|
|
139
|
+
inputSchema: {
|
|
140
|
+
type: "object",
|
|
141
|
+
properties: {
|
|
142
|
+
mutation: {
|
|
143
|
+
type: "string",
|
|
144
|
+
description: "The GraphQL mutation string. Must accept a variable for the ID (e.g. $id: ID!).",
|
|
145
|
+
},
|
|
146
|
+
ids: {
|
|
147
|
+
type: "array",
|
|
148
|
+
items: { type: "string" },
|
|
149
|
+
description: "Array of IDs to execute the mutation for.",
|
|
150
|
+
},
|
|
151
|
+
variableName: {
|
|
152
|
+
type: "string",
|
|
153
|
+
description: 'Name of the variable holding the ID in the mutation. Default: "id".',
|
|
154
|
+
},
|
|
155
|
+
extraVariables: {
|
|
156
|
+
type: "object",
|
|
157
|
+
description: "Additional variables to pass alongside each ID.",
|
|
158
|
+
},
|
|
159
|
+
concurrency: {
|
|
160
|
+
type: "number",
|
|
161
|
+
description: "Max number of concurrent mutations. Default: 5.",
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
required: ["mutation", "ids"],
|
|
165
|
+
},
|
|
166
|
+
},
|
|
101
167
|
{
|
|
102
168
|
name: "get_shop_schema",
|
|
103
169
|
description: "Fetch the full Shop API GraphQL schema introspection. (Warning: Large output)",
|
|
@@ -133,6 +199,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
133
199
|
},
|
|
134
200
|
],
|
|
135
201
|
};
|
|
202
|
+
case "admin_batch_mutation":
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: "text",
|
|
207
|
+
text: JSON.stringify(await adminBatchMutation(args?.mutation, args?.ids, args?.variableName || "id", args?.extraVariables, args?.concurrency || 5), null, 2),
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
};
|
|
136
211
|
case "get_admin_schema":
|
|
137
212
|
return {
|
|
138
213
|
content: [
|
|
@@ -169,6 +244,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
169
244
|
},
|
|
170
245
|
],
|
|
171
246
|
};
|
|
247
|
+
case "shop_batch_mutation":
|
|
248
|
+
return {
|
|
249
|
+
content: [
|
|
250
|
+
{
|
|
251
|
+
type: "text",
|
|
252
|
+
text: JSON.stringify(await shopBatchMutation(args?.mutation, args?.ids, args?.variableName || "id", args?.extraVariables, args?.concurrency || 5), null, 2),
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
};
|
|
172
256
|
case "get_shop_schema":
|
|
173
257
|
return {
|
|
174
258
|
content: [
|
|
@@ -203,7 +287,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
203
287
|
async function main() {
|
|
204
288
|
const transport = new StdioServerTransport();
|
|
205
289
|
await server.connect(transport);
|
|
206
|
-
console.error("
|
|
290
|
+
console.error("Vendure GraphQL MCP server running on stdio");
|
|
207
291
|
console.error(`API Key: ${process.env.VENDURE_API_KEY ? "Present" : "Missing"}`);
|
|
208
292
|
console.error(`Admin URL: ${process.env.ADMIN_API_URL || "default"}`);
|
|
209
293
|
console.error(`Shop URL: ${process.env.SHOP_API_URL || "default"}`);
|
|
@@ -30,3 +30,24 @@ export declare function getAdminOperations(): Promise<any>;
|
|
|
30
30
|
* Fetch a summary of available queries and mutations for the Shop API
|
|
31
31
|
*/
|
|
32
32
|
export declare function getShopOperations(): Promise<any>;
|
|
33
|
+
export interface BatchResult {
|
|
34
|
+
total: number;
|
|
35
|
+
succeeded: number;
|
|
36
|
+
failed: number;
|
|
37
|
+
results: Array<{
|
|
38
|
+
id: string;
|
|
39
|
+
success: boolean;
|
|
40
|
+
data?: any;
|
|
41
|
+
error?: string;
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Execute a GraphQL mutation in batch for multiple IDs on the Admin API.
|
|
46
|
+
* Runs mutations concurrently with configurable concurrency.
|
|
47
|
+
*/
|
|
48
|
+
export declare function adminBatchMutation(mutationString: string, ids: string[], variableName?: string, extraVariables?: Record<string, any>, concurrency?: number): Promise<BatchResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Execute a GraphQL mutation in batch for multiple IDs on the Shop API.
|
|
51
|
+
* Runs mutations concurrently with configurable concurrency.
|
|
52
|
+
*/
|
|
53
|
+
export declare function shopBatchMutation(mutationString: string, ids: string[], variableName?: string, extraVariables?: Record<string, any>, concurrency?: number): Promise<BatchResult>;
|
|
@@ -166,3 +166,43 @@ export async function getShopOperations() {
|
|
|
166
166
|
const client = getClient();
|
|
167
167
|
return client.request(getShopUrl(), operationsSummaryQuery);
|
|
168
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Execute a GraphQL mutation in batch for multiple IDs on the Admin API.
|
|
171
|
+
* Runs mutations concurrently with configurable concurrency.
|
|
172
|
+
*/
|
|
173
|
+
export async function adminBatchMutation(mutationString, ids, variableName = "id", extraVariables, concurrency = 5) {
|
|
174
|
+
return executeBatch(getAdminUrl(), mutationString, ids, variableName, extraVariables, concurrency);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Execute a GraphQL mutation in batch for multiple IDs on the Shop API.
|
|
178
|
+
* Runs mutations concurrently with configurable concurrency.
|
|
179
|
+
*/
|
|
180
|
+
export async function shopBatchMutation(mutationString, ids, variableName = "id", extraVariables, concurrency = 5) {
|
|
181
|
+
return executeBatch(getShopUrl(), mutationString, ids, variableName, extraVariables, concurrency);
|
|
182
|
+
}
|
|
183
|
+
async function executeBatch(url, mutationString, ids, variableName, extraVariables, concurrency) {
|
|
184
|
+
const client = getClient();
|
|
185
|
+
const results = [];
|
|
186
|
+
const queue = [...ids];
|
|
187
|
+
let succeeded = 0;
|
|
188
|
+
let failed = 0;
|
|
189
|
+
async function worker() {
|
|
190
|
+
while (queue.length > 0) {
|
|
191
|
+
const id = queue.shift();
|
|
192
|
+
const variables = { ...extraVariables, [variableName]: id };
|
|
193
|
+
try {
|
|
194
|
+
const data = await client.request(url, mutationString, variables);
|
|
195
|
+
succeeded++;
|
|
196
|
+
results.push({ id, success: true, data });
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
failed++;
|
|
200
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
201
|
+
results.push({ id, success: false, error: message });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const workers = Array.from({ length: Math.min(concurrency, ids.length) }, () => worker());
|
|
206
|
+
await Promise.all(workers);
|
|
207
|
+
return { total: ids.length, succeeded, failed, results };
|
|
208
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vendure-mcp-graphql",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "MCP server for Vendure Admin and Shop GraphQL APIs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"vendure-mcp-graphql": "./dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"main": "dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
10
13
|
"scripts": {
|
|
11
14
|
"build": "tsc",
|
|
12
15
|
"start": "node dist/index.js",
|
package/CHANGELOG.md
DELETED
package/index.ts
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Vendure GraphQL MCP Server
|
|
4
|
-
* Consolidated version for both Vendure Admin and Shop APIs
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
8
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
|
-
import {
|
|
10
|
-
CallToolRequestSchema,
|
|
11
|
-
ListToolsRequestSchema,
|
|
12
|
-
ErrorCode,
|
|
13
|
-
McpError,
|
|
14
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
15
|
-
import { config } from "dotenv";
|
|
16
|
-
import { resolve, dirname } from "path";
|
|
17
|
-
import { fileURLToPath } from "url";
|
|
18
|
-
import { existsSync } from "fs";
|
|
19
|
-
|
|
20
|
-
// Load environment variables
|
|
21
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
22
|
-
|
|
23
|
-
// 1. Try to load from project root .env.local
|
|
24
|
-
config({ path: resolve(__dirname, "../../.env.local") });
|
|
25
|
-
|
|
26
|
-
// 2. Also try to load from specific vendure-api-key.env if it exists
|
|
27
|
-
const apiKeyPath = resolve(__dirname, "../../vendure-api-key.env");
|
|
28
|
-
if (existsSync(apiKeyPath)) {
|
|
29
|
-
const envConfig = config({ path: apiKeyPath });
|
|
30
|
-
if (envConfig.parsed?.VENDURE_API_KEY) {
|
|
31
|
-
process.env.VENDURE_API_KEY = envConfig.parsed.VENDURE_API_KEY;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
import {
|
|
36
|
-
adminQuery,
|
|
37
|
-
adminMutation,
|
|
38
|
-
getAdminSchema,
|
|
39
|
-
getAdminOperations,
|
|
40
|
-
shopQuery,
|
|
41
|
-
shopMutation,
|
|
42
|
-
getShopSchema,
|
|
43
|
-
getShopOperations,
|
|
44
|
-
} from "./src/tools/index.js";
|
|
45
|
-
|
|
46
|
-
const server = new Server(
|
|
47
|
-
{
|
|
48
|
-
name: "vendure-mcp-graphql",
|
|
49
|
-
version: "1.0.0",
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
capabilities: {
|
|
53
|
-
tools: {},
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
// Define available tools
|
|
59
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
60
|
-
tools: [
|
|
61
|
-
{
|
|
62
|
-
name: "admin_query",
|
|
63
|
-
description: "Execute a GraphQL query on the Vendure Admin API.",
|
|
64
|
-
inputSchema: {
|
|
65
|
-
type: "object",
|
|
66
|
-
properties: {
|
|
67
|
-
query: { type: "string", description: "The GraphQL query string" },
|
|
68
|
-
variables: { type: "object", description: "Optional variables" },
|
|
69
|
-
},
|
|
70
|
-
required: ["query"],
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
name: "admin_mutation",
|
|
75
|
-
description: "Execute a GraphQL mutation on the Vendure Admin API.",
|
|
76
|
-
inputSchema: {
|
|
77
|
-
type: "object",
|
|
78
|
-
properties: {
|
|
79
|
-
mutation: {
|
|
80
|
-
type: "string",
|
|
81
|
-
description: "The GraphQL mutation string",
|
|
82
|
-
},
|
|
83
|
-
variables: { type: "object", description: "Optional variables" },
|
|
84
|
-
},
|
|
85
|
-
required: ["mutation"],
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
name: "get_admin_schema",
|
|
90
|
-
description:
|
|
91
|
-
"Fetch the full Admin API GraphQL schema introspection. (Warning: Large output)",
|
|
92
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
name: "list_admin_operations",
|
|
96
|
-
description:
|
|
97
|
-
"List all available queries and mutations for the Admin API with descriptions.",
|
|
98
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
name: "shop_query",
|
|
102
|
-
description: "Execute a GraphQL query on the Vendure Shop API.",
|
|
103
|
-
inputSchema: {
|
|
104
|
-
type: "object",
|
|
105
|
-
properties: {
|
|
106
|
-
query: { type: "string", description: "The GraphQL query string" },
|
|
107
|
-
variables: { type: "object", description: "Optional variables" },
|
|
108
|
-
},
|
|
109
|
-
required: ["query"],
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
name: "shop_mutation",
|
|
114
|
-
description: "Execute a GraphQL mutation on the Vendure Shop API.",
|
|
115
|
-
inputSchema: {
|
|
116
|
-
type: "object",
|
|
117
|
-
properties: {
|
|
118
|
-
mutation: {
|
|
119
|
-
type: "string",
|
|
120
|
-
description: "The GraphQL mutation string",
|
|
121
|
-
},
|
|
122
|
-
variables: { type: "object", description: "Optional variables" },
|
|
123
|
-
},
|
|
124
|
-
required: ["mutation"],
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
name: "get_shop_schema",
|
|
129
|
-
description:
|
|
130
|
-
"Fetch the full Shop API GraphQL schema introspection. (Warning: Large output)",
|
|
131
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
name: "list_shop_operations",
|
|
135
|
-
description:
|
|
136
|
-
"List all available queries and mutations for the Shop API with descriptions.",
|
|
137
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
138
|
-
},
|
|
139
|
-
],
|
|
140
|
-
}));
|
|
141
|
-
|
|
142
|
-
// Handle tool calls
|
|
143
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
144
|
-
const { name, arguments: args } = request.params;
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
switch (name) {
|
|
148
|
-
case "admin_query":
|
|
149
|
-
return {
|
|
150
|
-
content: [
|
|
151
|
-
{
|
|
152
|
-
type: "text",
|
|
153
|
-
text: JSON.stringify(
|
|
154
|
-
await adminQuery(
|
|
155
|
-
args?.query as string,
|
|
156
|
-
args?.variables as Record<string, any>,
|
|
157
|
-
),
|
|
158
|
-
null,
|
|
159
|
-
2,
|
|
160
|
-
),
|
|
161
|
-
},
|
|
162
|
-
],
|
|
163
|
-
};
|
|
164
|
-
case "admin_mutation":
|
|
165
|
-
return {
|
|
166
|
-
content: [
|
|
167
|
-
{
|
|
168
|
-
type: "text",
|
|
169
|
-
text: JSON.stringify(
|
|
170
|
-
await adminMutation(
|
|
171
|
-
args?.mutation as string,
|
|
172
|
-
args?.variables as Record<string, any>,
|
|
173
|
-
),
|
|
174
|
-
null,
|
|
175
|
-
2,
|
|
176
|
-
),
|
|
177
|
-
},
|
|
178
|
-
],
|
|
179
|
-
};
|
|
180
|
-
case "get_admin_schema":
|
|
181
|
-
return {
|
|
182
|
-
content: [
|
|
183
|
-
{
|
|
184
|
-
type: "text",
|
|
185
|
-
text: JSON.stringify(await getAdminSchema(), null, 2),
|
|
186
|
-
},
|
|
187
|
-
],
|
|
188
|
-
};
|
|
189
|
-
case "list_admin_operations":
|
|
190
|
-
return {
|
|
191
|
-
content: [
|
|
192
|
-
{
|
|
193
|
-
type: "text",
|
|
194
|
-
text: JSON.stringify(await getAdminOperations(), null, 2),
|
|
195
|
-
},
|
|
196
|
-
],
|
|
197
|
-
};
|
|
198
|
-
case "shop_query":
|
|
199
|
-
return {
|
|
200
|
-
content: [
|
|
201
|
-
{
|
|
202
|
-
type: "text",
|
|
203
|
-
text: JSON.stringify(
|
|
204
|
-
await shopQuery(
|
|
205
|
-
args?.query as string,
|
|
206
|
-
args?.variables as Record<string, any>,
|
|
207
|
-
),
|
|
208
|
-
null,
|
|
209
|
-
2,
|
|
210
|
-
),
|
|
211
|
-
},
|
|
212
|
-
],
|
|
213
|
-
};
|
|
214
|
-
case "shop_mutation":
|
|
215
|
-
return {
|
|
216
|
-
content: [
|
|
217
|
-
{
|
|
218
|
-
type: "text",
|
|
219
|
-
text: JSON.stringify(
|
|
220
|
-
await shopMutation(
|
|
221
|
-
args?.mutation as string,
|
|
222
|
-
args?.variables as Record<string, any>,
|
|
223
|
-
),
|
|
224
|
-
null,
|
|
225
|
-
2,
|
|
226
|
-
),
|
|
227
|
-
},
|
|
228
|
-
],
|
|
229
|
-
};
|
|
230
|
-
case "get_shop_schema":
|
|
231
|
-
return {
|
|
232
|
-
content: [
|
|
233
|
-
{
|
|
234
|
-
type: "text",
|
|
235
|
-
text: JSON.stringify(await getShopSchema(), null, 2),
|
|
236
|
-
},
|
|
237
|
-
],
|
|
238
|
-
};
|
|
239
|
-
case "list_shop_operations":
|
|
240
|
-
return {
|
|
241
|
-
content: [
|
|
242
|
-
{
|
|
243
|
-
type: "text",
|
|
244
|
-
text: JSON.stringify(await getShopOperations(), null, 2),
|
|
245
|
-
},
|
|
246
|
-
],
|
|
247
|
-
};
|
|
248
|
-
default:
|
|
249
|
-
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
250
|
-
}
|
|
251
|
-
} catch (error) {
|
|
252
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
253
|
-
return {
|
|
254
|
-
content: [{ type: "text", text: `Error: ${message}` }],
|
|
255
|
-
isError: true,
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
// Start the server
|
|
261
|
-
async function main() {
|
|
262
|
-
const transport = new StdioServerTransport();
|
|
263
|
-
await server.connect(transport);
|
|
264
|
-
console.error("Vendure GraphQL MCP server running on stdio");
|
|
265
|
-
console.error(
|
|
266
|
-
`API Key: ${process.env.VENDURE_API_KEY ? "Present" : "Missing"}`,
|
|
267
|
-
);
|
|
268
|
-
console.error(`Admin URL: ${process.env.ADMIN_API_URL || "default"}`);
|
|
269
|
-
console.error(`Shop URL: ${process.env.SHOP_API_URL || "default"}`);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
main().catch((error) => {
|
|
273
|
-
console.error("Server error:", error);
|
|
274
|
-
process.exit(1);
|
|
275
|
-
});
|
package/src/client.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GraphQL Client for Vendure API
|
|
3
|
-
* Handles authentication via API Key for both Admin and Shop APIs
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export interface GraphQLResponse<T = any> {
|
|
7
|
-
data?: T;
|
|
8
|
-
errors?: Array<{ message: string; path?: string[] }>;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export class GraphQLClient {
|
|
12
|
-
constructor(private apiKey: string | null = null) {}
|
|
13
|
-
|
|
14
|
-
async request<T = any>(
|
|
15
|
-
url: string,
|
|
16
|
-
queryString: string,
|
|
17
|
-
variables?: Record<string, any>,
|
|
18
|
-
): Promise<T> {
|
|
19
|
-
const headers: Record<string, string> = {
|
|
20
|
-
"Content-Type": "application/json",
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
if (this.apiKey) {
|
|
24
|
-
headers["vendure-api-key"] = this.apiKey;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const response = await fetch(url, {
|
|
28
|
-
method: "POST",
|
|
29
|
-
headers,
|
|
30
|
-
body: JSON.stringify({
|
|
31
|
-
query: queryString,
|
|
32
|
-
variables,
|
|
33
|
-
}),
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
if (!response.ok) {
|
|
37
|
-
const text = await response.text();
|
|
38
|
-
throw new Error(`HTTP Error ${response.status}: ${text}`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const result = (await response.json()) as GraphQLResponse<T>;
|
|
42
|
-
|
|
43
|
-
if (result.errors && result.errors.length > 0) {
|
|
44
|
-
throw new Error(result.errors.map((e) => e.message).join(", "));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return result.data as T;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Singleton instance
|
|
52
|
-
let clientInstance: GraphQLClient | null = null;
|
|
53
|
-
|
|
54
|
-
export function getClient(): GraphQLClient {
|
|
55
|
-
if (clientInstance) {
|
|
56
|
-
return clientInstance;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const apiKey = process.env.VENDURE_API_KEY || null;
|
|
60
|
-
clientInstance = new GraphQLClient(apiKey);
|
|
61
|
-
return clientInstance;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function getAdminUrl(): string {
|
|
65
|
-
return process.env.ADMIN_API_URL || "http://localhost:3000/admin-api";
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function getShopUrl(): string {
|
|
69
|
-
return process.env.SHOP_API_URL || "http://localhost:3000/shop-api";
|
|
70
|
-
}
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { getClient, getAdminUrl, getShopUrl } from "../client.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Execute a GraphQL query on the Admin API
|
|
5
|
-
*/
|
|
6
|
-
export async function adminQuery(
|
|
7
|
-
queryString: string,
|
|
8
|
-
variables?: Record<string, any>,
|
|
9
|
-
): Promise<any> {
|
|
10
|
-
const client = getClient();
|
|
11
|
-
return client.request(getAdminUrl(), queryString, variables);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Execute a GraphQL mutation on the Admin API
|
|
16
|
-
*/
|
|
17
|
-
export async function adminMutation(
|
|
18
|
-
mutationString: string,
|
|
19
|
-
variables?: Record<string, any>,
|
|
20
|
-
): Promise<any> {
|
|
21
|
-
const client = getClient();
|
|
22
|
-
return client.request(getAdminUrl(), mutationString, variables);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Execute a GraphQL query on the Shop API
|
|
27
|
-
*/
|
|
28
|
-
export async function shopQuery(
|
|
29
|
-
queryString: string,
|
|
30
|
-
variables?: Record<string, any>,
|
|
31
|
-
): Promise<any> {
|
|
32
|
-
const client = getClient();
|
|
33
|
-
return client.request(getShopUrl(), queryString, variables);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Execute a GraphQL mutation on the Shop API
|
|
38
|
-
*/
|
|
39
|
-
export async function shopMutation(
|
|
40
|
-
mutationString: string,
|
|
41
|
-
variables?: Record<string, any>,
|
|
42
|
-
): Promise<any> {
|
|
43
|
-
const client = getClient();
|
|
44
|
-
return client.request(getShopUrl(), mutationString, variables);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const introspectionQuery = `
|
|
48
|
-
query IntrospectionQuery {
|
|
49
|
-
__schema {
|
|
50
|
-
queryType { name }
|
|
51
|
-
mutationType { name }
|
|
52
|
-
subscriptionType { name }
|
|
53
|
-
types {
|
|
54
|
-
...FullType
|
|
55
|
-
}
|
|
56
|
-
directives {
|
|
57
|
-
name
|
|
58
|
-
description
|
|
59
|
-
locations
|
|
60
|
-
args {
|
|
61
|
-
...InputValue
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
fragment FullType on __Type {
|
|
68
|
-
kind
|
|
69
|
-
name
|
|
70
|
-
description
|
|
71
|
-
fields(includeDeprecated: true) {
|
|
72
|
-
name
|
|
73
|
-
description
|
|
74
|
-
args {
|
|
75
|
-
...InputValue
|
|
76
|
-
}
|
|
77
|
-
type {
|
|
78
|
-
...TypeRef
|
|
79
|
-
}
|
|
80
|
-
isDeprecated
|
|
81
|
-
deprecationReason
|
|
82
|
-
}
|
|
83
|
-
inputFields {
|
|
84
|
-
...InputValue
|
|
85
|
-
}
|
|
86
|
-
interfaces {
|
|
87
|
-
...TypeRef
|
|
88
|
-
}
|
|
89
|
-
enums {
|
|
90
|
-
name
|
|
91
|
-
description
|
|
92
|
-
isDeprecated
|
|
93
|
-
deprecationReason
|
|
94
|
-
}
|
|
95
|
-
possibleTypes {
|
|
96
|
-
...TypeRef
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
fragment InputValue on __InputValue {
|
|
101
|
-
name
|
|
102
|
-
description
|
|
103
|
-
type { ...TypeRef }
|
|
104
|
-
defaultValue
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
fragment TypeRef on __Type {
|
|
108
|
-
kind
|
|
109
|
-
name
|
|
110
|
-
ofType {
|
|
111
|
-
kind
|
|
112
|
-
name
|
|
113
|
-
ofType {
|
|
114
|
-
kind
|
|
115
|
-
name
|
|
116
|
-
ofType {
|
|
117
|
-
kind
|
|
118
|
-
name
|
|
119
|
-
ofType {
|
|
120
|
-
kind
|
|
121
|
-
name
|
|
122
|
-
ofType {
|
|
123
|
-
kind
|
|
124
|
-
name
|
|
125
|
-
ofType {
|
|
126
|
-
kind
|
|
127
|
-
name
|
|
128
|
-
ofType {
|
|
129
|
-
kind
|
|
130
|
-
name
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
`;
|
|
140
|
-
|
|
141
|
-
const operationsSummaryQuery = `
|
|
142
|
-
query OperationsSummary {
|
|
143
|
-
__schema {
|
|
144
|
-
queryType {
|
|
145
|
-
fields {
|
|
146
|
-
name
|
|
147
|
-
description
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
mutationType {
|
|
151
|
-
fields {
|
|
152
|
-
name
|
|
153
|
-
description
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
`;
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Fetch the Admin GraphQL schema introspection
|
|
162
|
-
*/
|
|
163
|
-
export async function getAdminSchema(): Promise<any> {
|
|
164
|
-
const client = getClient();
|
|
165
|
-
return client.request(getAdminUrl(), introspectionQuery);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Fetch the Shop GraphQL schema introspection
|
|
170
|
-
*/
|
|
171
|
-
export async function getShopSchema(): Promise<any> {
|
|
172
|
-
const client = getClient();
|
|
173
|
-
return client.request(getShopUrl(), introspectionQuery);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Fetch a summary of available queries and mutations for the Admin API
|
|
178
|
-
*/
|
|
179
|
-
export async function getAdminOperations(): Promise<any> {
|
|
180
|
-
const client = getClient();
|
|
181
|
-
return client.request(getAdminUrl(), operationsSummaryQuery);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Fetch a summary of available queries and mutations for the Shop API
|
|
186
|
-
*/
|
|
187
|
-
export async function getShopOperations(): Promise<any> {
|
|
188
|
-
const client = getClient();
|
|
189
|
-
return client.request(getShopUrl(), operationsSummaryQuery);
|
|
190
|
-
}
|
package/src/tools/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./graphql-operations.js";
|
package/tsconfig.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "node",
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"strict": true,
|
|
8
|
-
"outDir": "./dist",
|
|
9
|
-
"rootDir": ".",
|
|
10
|
-
"declaration": true,
|
|
11
|
-
"skipLibCheck": true
|
|
12
|
-
},
|
|
13
|
-
"include": [
|
|
14
|
-
"*.ts",
|
|
15
|
-
"src/**/*.ts"
|
|
16
|
-
],
|
|
17
|
-
"exclude": [
|
|
18
|
-
"node_modules",
|
|
19
|
-
"dist"
|
|
20
|
-
]
|
|
21
|
-
}
|