mage-remote-run 0.15.0 → 0.16.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.
package/README.md CHANGED
@@ -11,6 +11,8 @@ This tool is in an early stage and not yet stable. Expect breaking changes as th
11
11
  - **Connection Management**: Easily switch between multiple Magento instances (SaaS/PaaS).
12
12
  - **Interactive Prompts**: User-friendly wizard for configuration and command inputs.
13
13
  - **Rich Output**: Formatted tables and structured data display.
14
+ - **Interactive Console (REPL)**: Run CLI commands or JavaScript in a live session.
15
+ - **MCP Server**: Expose commands as MCP tools over stdio or HTTP (SSE).
14
16
  - **Comprehensive API Support**:
15
17
  - **Stores**: Manage websites, stores, and store views.
16
18
  - **Customers**: List, search, show, and delete customers.
@@ -83,6 +85,27 @@ The CLI supports multiple profiles. You can configure them interactively.
83
85
  node bin/mage-remote-run.js order show <increment_id>
84
86
  ```
85
87
 
88
+ ### Interactive Console (REPL)
89
+
90
+ ```bash
91
+ node bin/mage-remote-run.js console
92
+ # or
93
+ node bin/mage-remote-run.js repl
94
+ ```
95
+
96
+ Inside the console, you can run commands directly (for example, `website list`) or evaluate JavaScript with top-level `await`.
97
+
98
+ ### MCP Server
99
+
100
+ Expose the CLI as an MCP server:
101
+
102
+ ```bash
103
+ node bin/mage-remote-run.js mcp --transport stdio
104
+ node bin/mage-remote-run.js mcp --transport http --host 127.0.0.1 --port 18098
105
+ ```
106
+
107
+ Commands are registered as tools (for example, `website list` becomes `website_list`), and tool inputs map to the same CLI arguments and options.
108
+
86
109
  ## Development
87
110
 
88
111
  ### Testing
@@ -178,6 +178,13 @@ export function registerConsoleCommand(program) {
178
178
  }
179
179
 
180
180
  const firstWord = expandedArgs[0];
181
+ const blockedCommands = new Set(['console', 'mcp']);
182
+ if (blockedCommands.has(firstWord)) {
183
+ const blockedLabel = firstWord === 'console' ? 'console/repl' : firstWord;
184
+ console.error(chalk.red(`Command "${blockedLabel}" is not available inside the console.`));
185
+ callback(null);
186
+ return;
187
+ }
181
188
  const knownCommands = localProgram.commands.map(c => c.name());
182
189
 
183
190
  if (knownCommands.includes(firstWord)) {
@@ -73,6 +73,39 @@ Examples:
73
73
  } catch (e) { handleError(e); }
74
74
  });
75
75
 
76
+ //-------------------------------------------------------
77
+ // "customer create" Command
78
+ //-------------------------------------------------------
79
+ customers.command('create')
80
+ .description('Create a new customer')
81
+ .addHelpText('after', `
82
+ Examples:
83
+ $ mage-remote-run customer create
84
+ `)
85
+ .action(async () => {
86
+ try {
87
+ const client = await createClient();
88
+ const answers = await inquirer.prompt([
89
+ { name: 'firstname', message: 'First Name:' },
90
+ { name: 'lastname', message: 'Last Name:' },
91
+ { name: 'email', message: 'Email:' },
92
+ { name: 'password', message: 'Password:', type: 'password' }
93
+ ]);
94
+
95
+ const payload = {
96
+ customer: {
97
+ email: answers.email,
98
+ firstname: answers.firstname,
99
+ lastname: answers.lastname
100
+ },
101
+ password: answers.password
102
+ };
103
+
104
+ const data = await client.post('V1/customers', payload);
105
+ console.log(chalk.green(`✅ Customer created with ID: ${data.id}`));
106
+ } catch (e) { handleError(e); }
107
+ });
108
+
76
109
 
77
110
  //-------------------------------------------------------
78
111
  // "customer edit" Command
@@ -241,12 +274,8 @@ Examples:
241
274
  websiteId = answers.websiteId;
242
275
  }
243
276
 
244
- if (!customerId && !options.redirectUrl) {
245
- const { redirectUrl } = await inquirer.prompt([
246
- { name: 'redirectUrl', message: 'Redirect URL (optional):' }
247
- ]);
248
- options.redirectUrl = redirectUrl;
249
- }
277
+ // Redirect URL is optional and only used if provided via flag
278
+ // User requested to remove usage of interactive prompt for it.
250
279
 
251
280
  const payload = {
252
281
  email: email,
@@ -105,6 +105,57 @@ Examples:
105
105
  } catch (e) { handleError(e); }
106
106
  });
107
107
 
108
+ //-------------------------------------------------------
109
+ // "order cancel" Command
110
+ //-------------------------------------------------------
111
+ orders.command('cancel <id>')
112
+ .description('Cancel an order')
113
+ .addHelpText('after', `
114
+ Examples:
115
+ $ mage-remote-run order cancel 123
116
+ `)
117
+ .action(async (id) => {
118
+ try {
119
+ const client = await createClient();
120
+ await client.post(`V1/orders/${id}/cancel`);
121
+ console.log(chalk.green(`Order ${id} cancelled.`));
122
+ } catch (e) { handleError(e); }
123
+ });
124
+
125
+ //-------------------------------------------------------
126
+ // "order hold" Command
127
+ //-------------------------------------------------------
128
+ orders.command('hold <id>')
129
+ .description('Hold an order')
130
+ .addHelpText('after', `
131
+ Examples:
132
+ $ mage-remote-run order hold 123
133
+ `)
134
+ .action(async (id) => {
135
+ try {
136
+ const client = await createClient();
137
+ await client.post(`V1/orders/${id}/hold`);
138
+ console.log(chalk.green(`Order ${id} put on hold.`));
139
+ } catch (e) { handleError(e); }
140
+ });
141
+
142
+ //-------------------------------------------------------
143
+ // "order unhold" Command
144
+ //-------------------------------------------------------
145
+ orders.command('unhold <id>')
146
+ .description('Unhold an order')
147
+ .addHelpText('after', `
148
+ Examples:
149
+ $ mage-remote-run order unhold 123
150
+ `)
151
+ .action(async (id) => {
152
+ try {
153
+ const client = await createClient();
154
+ await client.post(`V1/orders/${id}/unhold`);
155
+ console.log(chalk.green(`Order ${id} released from hold.`));
156
+ } catch (e) { handleError(e); }
157
+ });
158
+
108
159
  //-------------------------------------------------------
109
160
  // "order show" Command
110
161
  //-------------------------------------------------------
@@ -171,6 +171,32 @@ Examples:
171
171
  } catch (e) { handleError(e); }
172
172
  });
173
173
 
174
+ const media = products.command('media').description('Manage product media');
175
+
176
+ //-------------------------------------------------------
177
+ // "product media list" Command
178
+ //-------------------------------------------------------
179
+ media.command('list <sku>')
180
+ .description('List media for a product')
181
+ .addHelpText('after', `
182
+ Examples:
183
+ $ mage-remote-run product media list SKU123
184
+ `)
185
+ .action(async (sku) => {
186
+ try {
187
+ const client = await createClient();
188
+ const data = await client.get(`V1/products/${encodeURIComponent(sku)}/media`);
189
+
190
+ if (!data || data.length === 0) {
191
+ console.log('No media found.');
192
+ return;
193
+ }
194
+
195
+ const rows = data.map(m => [m.id, m.media_type, m.file, m.label || '', m.position, m.disabled ? 'Yes' : 'No']);
196
+ printTable(['ID', 'Type', 'File', 'Label', 'Pos', 'Disabled'], rows);
197
+ } catch (e) { handleError(e); }
198
+ });
199
+
174
200
  const types = products.command('type').description('Manage product types');
175
201
 
176
202
 
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "mage-remote-run",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "The remote swiss army knife for Magento Open Source, Mage-OS, Adobe Commerce",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "NODE_OPTIONS=\"--experimental-vm-modules --localstorage-file=./.localstorage\" jest",
8
8
  "start": "node bin/mage-remote-run.js",
9
+ "dev:api-discover": "node scripts/parse_swagger.cjs",
9
10
  "release": "release-it"
10
11
  },
11
12
  "keywords": [],