@mainwp/mcp 1.0.0-beta.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.
Files changed (49) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +1034 -0
  3. package/dist/abilities.d.ts +144 -0
  4. package/dist/abilities.d.ts.map +1 -0
  5. package/dist/abilities.js +529 -0
  6. package/dist/abilities.js.map +1 -0
  7. package/dist/config.d.ts +135 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +405 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/confirmation-responses.d.ts +44 -0
  12. package/dist/confirmation-responses.d.ts.map +1 -0
  13. package/dist/confirmation-responses.js +120 -0
  14. package/dist/confirmation-responses.js.map +1 -0
  15. package/dist/errors.d.ts +118 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +206 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/index.d.ts +17 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +506 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/logging.d.ts +34 -0
  24. package/dist/logging.d.ts.map +1 -0
  25. package/dist/logging.js +74 -0
  26. package/dist/logging.js.map +1 -0
  27. package/dist/naming.d.ts +23 -0
  28. package/dist/naming.d.ts.map +1 -0
  29. package/dist/naming.js +37 -0
  30. package/dist/naming.js.map +1 -0
  31. package/dist/prompts.d.ts +22 -0
  32. package/dist/prompts.d.ts.map +1 -0
  33. package/dist/prompts.js +414 -0
  34. package/dist/prompts.js.map +1 -0
  35. package/dist/retry.d.ts +77 -0
  36. package/dist/retry.d.ts.map +1 -0
  37. package/dist/retry.js +206 -0
  38. package/dist/retry.js.map +1 -0
  39. package/dist/security.d.ts +41 -0
  40. package/dist/security.d.ts.map +1 -0
  41. package/dist/security.js +154 -0
  42. package/dist/security.js.map +1 -0
  43. package/dist/tools.d.ts +82 -0
  44. package/dist/tools.d.ts.map +1 -0
  45. package/dist/tools.js +861 -0
  46. package/dist/tools.js.map +1 -0
  47. package/package.json +73 -0
  48. package/settings.example.json +30 -0
  49. package/settings.schema.json +129 -0
package/README.md ADDED
@@ -0,0 +1,1034 @@
1
+ <p align="center">
2
+ <img src="docs/images/mainwp-mcp-logo.png" alt="MainWP MCP" width="400">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <img src="https://img.shields.io/badge/status-beta-blue" alt="Beta">
7
+ <a href="https://www.npmjs.com/package/@mainwp/mcp"><img src="https://img.shields.io/npm/v/@mainwp/mcp" alt="npm version"></a>
8
+ <a href="https://github.com/mainwp/mainwp-mcp/actions/workflows/ci.yml"><img src="https://github.com/mainwp/mainwp-mcp/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
9
+ </p>
10
+
11
+ # MainWP MCP Server
12
+
13
+ **Beta Release** — This project is under active development. APIs may change between versions.
14
+
15
+ An MCP (Model Context Protocol) server that connects AI assistants to your MainWP Dashboard. This lets Cursor, Claude, OpenAI Codex, VS Code Copilot, and other AI tools manage your WordPress network through natural conversation.
16
+
17
+ ### What You Can Do
18
+
19
+ - **Site Management**: List sites, check connection status, sync data, add or remove child sites
20
+ - **Update Management**: See pending updates across all sites, apply core/plugin/theme updates
21
+ - **Plugin and Theme Control**: View installed plugins and themes, activate or deactivate them
22
+ - **Client Organization**: Manage client records, assign sites to clients, track costs
23
+ - **Bulk Operations**: Sync, reconnect, or check connectivity across dozens of sites at once
24
+
25
+ Built for WordPress agencies and site managers who want AI assistance with their MainWP workflows.
26
+
27
+ ---
28
+
29
+ ## Quick Start
30
+
31
+ **Requirements:** Node.js >=20.19.0 and MainWP Dashboard 6.0+
32
+
33
+ ### Option A: Run with npx (recommended)
34
+
35
+ No installation needed. Run the server directly:
36
+
37
+ ```bash
38
+ npx -y @mainwp/mcp
39
+ ```
40
+
41
+ Credentials are loaded from a `settings.json` file in either the current working directory or `~/.config/mainwp-mcp/settings.json`. See [Credential Configuration](#credential-configuration) for the file format.
42
+
43
+ ### Option B: Clone and build (for development)
44
+
45
+ ```bash
46
+ git clone https://github.com/mainwp/mainwp-mcp.git
47
+ cd mainwp-mcp
48
+ npm ci
49
+ npm run build
50
+ ```
51
+
52
+ ### Then:
53
+
54
+ 1. Create an Application Password (see [instructions below](#creating-an-application-password))
55
+
56
+ 2. Configure your AI tool (see [Installation](#installation))
57
+
58
+ 3. Start chatting: "What sites need updates?" or "Sync all my sites"
59
+
60
+ Need inspiration? See the [Example Prompts](docs/example-prompts.md) for more ideas.
61
+
62
+ ---
63
+
64
+ ## Credential Configuration
65
+
66
+ There are two ways to provide your MainWP credentials. Both store credentials in config files, so choose based on your workflow preference.
67
+
68
+ ### Option A: Per-Tool Configuration (Recommended)
69
+
70
+ Include credentials directly in each AI tool's MCP configuration using the `env` block. This is the standard approach you'll see in MCP server documentation.
71
+
72
+ ```json
73
+ {
74
+ "mcpServers": {
75
+ "mainwp": {
76
+ "command": "npx",
77
+ "args": ["-y", "@mainwp/mcp"],
78
+ "env": {
79
+ "MAINWP_URL": "https://your-dashboard.com",
80
+ "MAINWP_USER": "admin",
81
+ "MAINWP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
82
+ }
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ This is the standard approach. Each tool has its own self-contained config, and you can create a separate Application Password for each AI tool for better security.
89
+
90
+ ### Option B: Centralized Settings File
91
+
92
+ Store your credentials once in `~/.config/mainwp-mcp/settings.json`:
93
+
94
+ ```json
95
+ {
96
+ "dashboardUrl": "https://your-dashboard.com",
97
+ "username": "admin",
98
+ "appPassword": "xxxx xxxx xxxx xxxx xxxx xxxx"
99
+ }
100
+ ```
101
+
102
+ This keeps credentials in one place for all your AI tools. When you need to rotate passwords, you only update one file. You can also set restrictive permissions with `chmod 600` and safely share your MCP configs without exposing credentials.
103
+
104
+ If you manage multiple dashboards, this approach works well. The server checks the current working directory for `settings.json` first, so you can create separate folders for each dashboard and use the `cwd` option to point at them:
105
+
106
+ ```json
107
+ {
108
+ "mcpServers": {
109
+ "mainwp": {
110
+ "command": "npx",
111
+ "args": ["-y", "@mainwp/mcp"],
112
+ "cwd": "/path/to/dashboard-credentials"
113
+ }
114
+ }
115
+ }
116
+ ```
117
+
118
+ Each folder just needs its own `settings.json` with that dashboard's credentials. To switch dashboards, change the `cwd` path or create multiple server entries with different names.
119
+
120
+ The downside is you have an extra file to manage, and all tools share the same password.
121
+
122
+ ### Which Should I Use?
123
+
124
+ Use **Option A (per-tool configuration)** unless you have a specific reason not to. It's the standard approach, lets you use separate passwords per tool, and matches how other MCP servers work.
125
+
126
+ Use Option B if you use many AI tools and want to avoid duplicating credentials across configs.
127
+
128
+ > **Note:** Neither approach uses true system environment variables. For higher security options, see the [Security Guide](docs/security.md).
129
+
130
+ ---
131
+
132
+ ## Creating an Application Password
133
+
134
+ You'll need a [WordPress Application Password](https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/) to connect to your MainWP Dashboard. Follow these steps to generate a WordPress Application Password to authenticate with your MainWP Dashboard.
135
+
136
+ 1. Log into your MainWP Dashboard as an administrator
137
+ 2. Go to **Users > Profile** in the WordPress portion (click your username in the top right of the MainWP Dashboard)
138
+ 3. Scroll down to the **Application Passwords** section
139
+ 4. Enter a name like "MainWP MCP Server"
140
+ 5. Click **Add New Application Password**
141
+ 6. Copy the generated password immediately (it's only shown once)
142
+
143
+ WordPress displays the password with spaces for readability. You can use it with or without the spaces.
144
+
145
+ > **Tip:** Create a dedicated WordPress user for API access rather than using your main admin account. This makes it easier to revoke access later if needed.
146
+
147
+ ---
148
+
149
+ ## Installation
150
+
151
+ Click on your AI tool to see configuration instructions.
152
+
153
+ <details>
154
+ <summary>Claude Code</summary>
155
+
156
+ Anthropic's official CLI for Claude with built-in MCP support.
157
+
158
+ **Add via CLI:**
159
+
160
+ ```bash
161
+ claude mcp add --transport stdio mainwp \
162
+ --env MAINWP_URL=https://your-dashboard.com \
163
+ --env MAINWP_USER=admin \
164
+ --env MAINWP_APP_PASSWORD="xxxx xxxx xxxx xxxx xxxx xxxx" \
165
+ -- npx -y @mainwp/mcp
166
+ ```
167
+
168
+ **Or add to `~/.claude.json`:**
169
+
170
+ ```json
171
+ {
172
+ "mcpServers": {
173
+ "mainwp": {
174
+ "command": "npx",
175
+ "args": ["-y", "@mainwp/mcp"],
176
+ "env": {
177
+ "MAINWP_URL": "https://your-dashboard.com",
178
+ "MAINWP_USER": "admin",
179
+ "MAINWP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
180
+ }
181
+ }
182
+ }
183
+ }
184
+ ```
185
+
186
+ **Using settings.json instead:**
187
+
188
+ If you prefer centralized credentials, first create `~/.config/mainwp-mcp/settings.json` with your credentials, then simply run:
189
+
190
+ ```bash
191
+ claude mcp add --transport stdio mainwp -- npx -y @mainwp/mcp
192
+ ```
193
+
194
+ [Claude Code MCP Documentation](https://code.claude.com/docs/en/mcp)
195
+
196
+ </details>
197
+
198
+ <details>
199
+ <summary>Claude Desktop</summary>
200
+
201
+ The Claude desktop application for macOS and Windows.
202
+
203
+ Config file location:
204
+
205
+ - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
206
+ - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
207
+
208
+ ```json
209
+ {
210
+ "mcpServers": {
211
+ "mainwp": {
212
+ "command": "npx",
213
+ "args": ["-y", "@mainwp/mcp"],
214
+ "env": {
215
+ "MAINWP_URL": "https://your-dashboard.com",
216
+ "MAINWP_USER": "admin",
217
+ "MAINWP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
218
+ }
219
+ }
220
+ }
221
+ }
222
+ ```
223
+
224
+ **Using settings.json instead:**
225
+
226
+ If you prefer centralized credentials, create `~/.config/mainwp-mcp/settings.json` with your credentials, then omit the `env` block:
227
+
228
+ ```json
229
+ {
230
+ "mcpServers": {
231
+ "mainwp": {
232
+ "command": "npx",
233
+ "args": ["-y", "@mainwp/mcp"]
234
+ }
235
+ }
236
+ }
237
+ ```
238
+
239
+ [Claude Desktop MCP Documentation](https://modelcontextprotocol.io/quickstart/user)
240
+
241
+ </details>
242
+
243
+ <details>
244
+ <summary>VS Code (Copilot Agent Mode)</summary>
245
+
246
+ GitHub Copilot in VS Code with MCP server support.
247
+
248
+ Add to `.vscode/mcp.json` in your workspace:
249
+
250
+ ```json
251
+ {
252
+ "servers": {
253
+ "mainwp": {
254
+ "type": "stdio",
255
+ "command": "npx",
256
+ "args": ["-y", "@mainwp/mcp"],
257
+ "env": {
258
+ "MAINWP_URL": "https://your-dashboard.com",
259
+ "MAINWP_USER": "admin",
260
+ "MAINWP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
261
+ }
262
+ }
263
+ }
264
+ }
265
+ ```
266
+
267
+ **Using secure input prompts:**
268
+
269
+ VS Code can prompt for credentials at runtime so they aren't stored in the file:
270
+
271
+ ```json
272
+ {
273
+ "inputs": [
274
+ {
275
+ "type": "promptString",
276
+ "id": "mainwp_password",
277
+ "description": "MainWP Application Password",
278
+ "password": true
279
+ }
280
+ ],
281
+ "servers": {
282
+ "mainwp": {
283
+ "type": "stdio",
284
+ "command": "npx",
285
+ "args": ["-y", "@mainwp/mcp"],
286
+ "env": {
287
+ "MAINWP_URL": "https://your-dashboard.com",
288
+ "MAINWP_USER": "admin",
289
+ "MAINWP_APP_PASSWORD": "${input:mainwp_password}"
290
+ }
291
+ }
292
+ }
293
+ }
294
+ ```
295
+
296
+ **Using settings.json instead:**
297
+
298
+ Create `~/.config/mainwp-mcp/settings.json` with your credentials, then omit the `env` block from your config.
299
+
300
+ [VS Code MCP Documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers)
301
+
302
+ </details>
303
+
304
+ <details>
305
+ <summary>Cursor</summary>
306
+
307
+ The AI-first code editor with MCP support.
308
+
309
+ Config file: `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global)
310
+
311
+ ```json
312
+ {
313
+ "mcpServers": {
314
+ "mainwp": {
315
+ "command": "npx",
316
+ "args": ["-y", "@mainwp/mcp"],
317
+ "env": {
318
+ "MAINWP_URL": "https://your-dashboard.com",
319
+ "MAINWP_USER": "admin",
320
+ "MAINWP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
321
+ }
322
+ }
323
+ }
324
+ }
325
+ ```
326
+
327
+ Cursor also supports `${env:VAR_NAME}` to reference system environment variables.
328
+
329
+ **Using settings.json instead:**
330
+
331
+ Create `~/.config/mainwp-mcp/settings.json` with your credentials, then omit the `env` block from your config.
332
+
333
+ [Cursor MCP Documentation](https://cursor.com/docs/context/mcp)
334
+
335
+ </details>
336
+
337
+ <details>
338
+ <summary>OpenAI Codex</summary>
339
+
340
+ OpenAI's coding assistant with MCP support.
341
+
342
+ Config file: `~/.codex/config.toml` (uses TOML format, unlike the others)
343
+
344
+ ```toml
345
+ [mcp_servers.mainwp]
346
+ command = "npx"
347
+ args = ["-y", "@mainwp/mcp"]
348
+
349
+ [mcp_servers.mainwp.env]
350
+ MAINWP_URL = "https://your-dashboard.com"
351
+ MAINWP_USER = "admin"
352
+ MAINWP_APP_PASSWORD = "xxxx xxxx xxxx xxxx xxxx xxxx"
353
+ ```
354
+
355
+ **Using settings.json instead:**
356
+
357
+ Create `~/.config/mainwp-mcp/settings.json` with your credentials, then omit the `[mcp_servers.mainwp.env]` section from your config.
358
+
359
+ [OpenAI Codex MCP Documentation](https://developers.openai.com/codex/mcp)
360
+
361
+ </details>
362
+
363
+ <details>
364
+ <summary>ZenCoder</summary>
365
+
366
+ AI coding assistant for VS Code and JetBrains IDEs.
367
+
368
+ **VS Code:** Edit `zencoder.mcpServers` in VS Code settings.json:
369
+
370
+ ```json
371
+ "zencoder.mcpServers": {
372
+ "mainwp": {
373
+ "command": "npx",
374
+ "args": ["-y", "@mainwp/mcp"],
375
+ "env": {
376
+ "MAINWP_URL": "https://your-dashboard.com",
377
+ "MAINWP_USER": "admin",
378
+ "MAINWP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
379
+ }
380
+ }
381
+ }
382
+ ```
383
+
384
+ **JetBrains:** Go to Settings > Tools > Zencoder > MCP Servers and use the same JSON format.
385
+
386
+ **Using settings.json instead:**
387
+
388
+ Create `~/.config/mainwp-mcp/settings.json` with your credentials, then omit the `env` block from your config.
389
+
390
+ [ZenCoder MCP Documentation](https://docs.zencoder.ai/features/integrations-and-mcp)
391
+
392
+ </details>
393
+
394
+ For Windsurf and other hosts, use the same JSON configuration pattern shown above.
395
+
396
+ ---
397
+
398
+ ## Configuration
399
+
400
+ ### Environment Variables
401
+
402
+ | Variable | Required | Default | Description |
403
+ | ---------------------------------- | -------- | ---------- | -------------------------------------------------------- |
404
+ | `MAINWP_URL` | Yes | | Base URL of your MainWP Dashboard |
405
+ | `MAINWP_USER` | Yes | | WordPress admin username |
406
+ | `MAINWP_APP_PASSWORD` | Yes | | WordPress Application Password |
407
+ | `MAINWP_SKIP_SSL_VERIFY` | No | `false` | Skip SSL verification (dev only) |
408
+ | `MAINWP_ALLOW_HTTP` | No | `false` | Allow HTTP URLs (credentials sent in plain text) |
409
+ | `MAINWP_SAFE_MODE` | No | `false` | Block destructive operations |
410
+ | `MAINWP_REQUIRE_USER_CONFIRMATION` | No | `true` | Require two-step confirmation for destructive operations |
411
+ | `MAINWP_ALLOWED_TOOLS` | No | | Whitelist of tools to expose |
412
+ | `MAINWP_BLOCKED_TOOLS` | No | | Blacklist of tools to hide |
413
+ | `MAINWP_SCHEMA_VERBOSITY` | No | `standard` | `standard` or `compact` |
414
+ | `MAINWP_RETRY_ENABLED` | No | `true` | Enable automatic retry for transient errors |
415
+ | `MAINWP_MAX_RETRIES` | No | `2` | Total retry attempts including initial request |
416
+ | `MAINWP_RETRY_BASE_DELAY` | No | `1000` | Base delay between retries in milliseconds |
417
+ | `MAINWP_RETRY_MAX_DELAY` | No | `2000` | Maximum delay between retries in milliseconds |
418
+
419
+ > **⚠️ Security Warning: SSL Verification**
420
+ >
421
+ > Setting `MAINWP_SKIP_SSL_VERIFY=true` disables SSL certificate verification, making your connection vulnerable to man-in-the-middle (MITM) attacks.
422
+ >
423
+ > **Only use for:** Local development with self-signed certificates or isolated test environments.
424
+ >
425
+ > **Never use in production** or on untrusted networks.
426
+
427
+ For the complete list of variables and configuration file options, see the [Configuration Guide](docs/configuration.md).
428
+
429
+ ### Configuration File
430
+
431
+ Instead of environment variables, you can use a `settings.json` file:
432
+
433
+ ```json
434
+ {
435
+ "dashboardUrl": "https://your-dashboard.com",
436
+ "username": "admin",
437
+ "appPassword": "xxxx xxxx xxxx xxxx xxxx xxxx",
438
+ "retryEnabled": true,
439
+ "maxRetries": 2,
440
+ "retryBaseDelay": 1000,
441
+ "retryMaxDelay": 2000
442
+ }
443
+ ```
444
+
445
+ Configuration loads from `./settings.json` or `~/.config/mainwp-mcp/settings.json` (checked in that order). Environment variables override file settings.
446
+
447
+ ---
448
+
449
+ ## Optimizing Token Usage
450
+
451
+ You have access to 64 tools, which consume approximately 28,000 tokens in your AI's context window. Two settings help reduce this footprint.
452
+
453
+ ### Compact Schema Mode
454
+
455
+ A single setting reduces token usage by roughly 30%:
456
+
457
+ ```json
458
+ {
459
+ "schemaVerbosity": "compact"
460
+ }
461
+ ```
462
+
463
+ Or via environment variable:
464
+
465
+ ```bash
466
+ MAINWP_SCHEMA_VERBOSITY=compact
467
+ ```
468
+
469
+ Compact mode truncates descriptions to 60 characters and removes examples while leaving tool functionality unchanged.
470
+
471
+ ### Limiting Exposed Tools
472
+
473
+ You can expose only the tools you need. These configurations cover common scenarios:
474
+
475
+ **Read-only monitoring** (17 tools, ~73% reduction):
476
+
477
+ ```json
478
+ {
479
+ "allowedTools": [
480
+ "list_sites_v1",
481
+ "get_site_v1",
482
+ "get_site_plugins_v1",
483
+ "get_site_themes_v1",
484
+ "get_site_updates_v1",
485
+ "list_updates_v1",
486
+ "list_ignored_updates_v1",
487
+ "list_clients_v1",
488
+ "get_client_v1",
489
+ "count_clients_v1",
490
+ "count_client_sites_v1",
491
+ "get_client_sites_v1",
492
+ "get_client_costs_v1",
493
+ "list_tags_v1",
494
+ "get_tag_v1",
495
+ "get_tag_sites_v1",
496
+ "get_tag_clients_v1"
497
+ ]
498
+ }
499
+ ```
500
+
501
+ **Site management only** (30 tools, ~53% reduction):
502
+
503
+ ```json
504
+ {
505
+ "allowedTools": [
506
+ "list_sites_v1",
507
+ "get_site_v1",
508
+ "count_sites_v1",
509
+ "get_sites_basic_v1",
510
+ "add_site_v1",
511
+ "update_site_v1",
512
+ "delete_site_v1",
513
+ "sync_sites_v1",
514
+ "check_site_v1",
515
+ "check_sites_v1",
516
+ "reconnect_site_v1",
517
+ "reconnect_sites_v1",
518
+ "disconnect_site_v1",
519
+ "disconnect_sites_v1",
520
+ "suspend_site_v1",
521
+ "suspend_sites_v1",
522
+ "unsuspend_site_v1",
523
+ "get_site_plugins_v1",
524
+ "get_site_themes_v1",
525
+ "activate_site_plugins_v1",
526
+ "deactivate_site_plugins_v1",
527
+ "delete_site_plugins_v1",
528
+ "activate_site_theme_v1",
529
+ "delete_site_themes_v1",
530
+ "get_abandoned_plugins_v1",
531
+ "get_abandoned_themes_v1",
532
+ "get_site_security_v1",
533
+ "get_site_client_v1",
534
+ "get_site_costs_v1",
535
+ "get_site_changes_v1"
536
+ ]
537
+ }
538
+ ```
539
+
540
+ **Updates only** (13 tools, ~80% reduction):
541
+
542
+ ```json
543
+ {
544
+ "allowedTools": [
545
+ "list_updates_v1",
546
+ "run_updates_v1",
547
+ "update_all_v1",
548
+ "get_site_updates_v1",
549
+ "update_site_core_v1",
550
+ "update_site_plugins_v1",
551
+ "update_site_themes_v1",
552
+ "update_site_translations_v1",
553
+ "list_ignored_updates_v1",
554
+ "set_ignored_updates_v1",
555
+ "ignore_site_core_v1",
556
+ "ignore_site_plugins_v1",
557
+ "ignore_site_themes_v1"
558
+ ]
559
+ }
560
+ ```
561
+
562
+ **Hide destructive tools** (block deletions while keeping everything else):
563
+
564
+ ```json
565
+ {
566
+ "blockedTools": [
567
+ "delete_site_v1",
568
+ "delete_client_v1",
569
+ "delete_tag_v1",
570
+ "delete_site_plugins_v1",
571
+ "delete_site_themes_v1"
572
+ ]
573
+ }
574
+ ```
575
+
576
+ ### Combining Settings
577
+
578
+ Compact mode and tool filtering work together. This configuration exposes just four tools with minimal descriptions, well-suited for focused automation:
579
+
580
+ ```json
581
+ {
582
+ "schemaVerbosity": "compact",
583
+ "allowedTools": ["list_sites_v1", "get_site_v1", "list_updates_v1", "run_updates_v1"]
584
+ }
585
+ ```
586
+
587
+ For all configuration options, see the [Configuration Guide](docs/configuration.md).
588
+
589
+ ---
590
+
591
+ ## Two-Step Confirmation Flow
592
+
593
+ Destructive operations (deletions) require your explicit confirmation to prevent accidental data loss. When you ask the AI to delete something, it shows you a preview first and waits for your approval.
594
+
595
+ ### How It Works
596
+
597
+ ```mermaid
598
+ sequenceDiagram
599
+ participant User
600
+ participant AI
601
+ participant Server
602
+ participant MainWP
603
+
604
+ User->>AI: Delete site 3
605
+ AI->>Server: delete_site_v1(site_id: 3, confirm: true)
606
+ Server->>MainWP: dry_run preview request
607
+ MainWP-->>Server: site details
608
+ Server-->>AI: PREVIEW with site info
609
+ AI->>User: Shows: "Example Site (https://example.com)<br/>Confirm deletion?"
610
+ User->>AI: Yes, proceed
611
+ AI->>Server: delete_site_v1(site_id: 3, user_confirmed: true)
612
+ Server->>MainWP: execute deletion
613
+ MainWP-->>Server: success
614
+ Server-->>AI: deletion complete
615
+ AI->>User: Site deleted successfully
616
+ ```
617
+
618
+ **Example Conversation:**
619
+
620
+ ```
621
+ You: Delete site 3
622
+
623
+ AI: I found site 3: Example Site (https://example.com)
624
+ This will permanently remove it from your MainWP Dashboard.
625
+ Do you want me to proceed with deletion?
626
+
627
+ You: Yes
628
+
629
+ AI: Site 3 has been deleted successfully.
630
+ ```
631
+
632
+ ### Affected Operations
633
+
634
+ These destructive tools require two-step confirmation:
635
+
636
+ - `delete_site_v1` - Delete a child site
637
+ - `delete_client_v1` - Delete a client record
638
+ - `delete_tag_v1` - Delete a tag
639
+ - `delete_site_plugins_v1` - Delete plugins from a site
640
+ - `delete_site_themes_v1` - Delete themes from a site
641
+
642
+ ### Disabling for Automation
643
+
644
+ If you're running automated scripts that need to delete without interaction:
645
+
646
+ ```json
647
+ {
648
+ "requireUserConfirmation": false
649
+ }
650
+ ```
651
+
652
+ Or as an environment variable:
653
+
654
+ ```bash
655
+ MAINWP_REQUIRE_USER_CONFIRMATION=false
656
+ ```
657
+
658
+ See the [Security Guide](docs/security.md#confirmation-guardrails) for more details.
659
+
660
+ ---
661
+
662
+ ## Tools
663
+
664
+ Over 60 tools organized by category. Each tool shows parameters with type, requirement, and description.
665
+
666
+ > **Note:** Tool names omit the `mainwp` namespace. The ability `mainwp/list-sites-v1` becomes `list_sites_v1`.
667
+
668
+ <details>
669
+ <summary>Sites</summary>
670
+
671
+ - **list_sites_v1** - List MainWP child sites with pagination and filtering
672
+ - `page`: Page number, 1-based (number, optional)
673
+ - `per_page`: Items per page, max 100 (number, optional)
674
+ - `status`: Filter by status: any, connected, disconnected, suspended (string, optional)
675
+ - `search`: Search term for site name or URL (string, optional)
676
+ - `client_id`: Filter by client ID (number, optional)
677
+ - `tag_id`: Filter by tag ID (number, optional)
678
+
679
+ - **get_site_v1** - Get detailed information about a single site
680
+ - `site_id_or_domain`: Site ID or domain/URL (string|number, required)
681
+ - `include_stats`: Include update counts and health info (boolean, optional)
682
+
683
+ - **count_sites_v1** - Count total sites with optional filtering
684
+ - `status`: Filter by status (string, optional)
685
+ - `client_id`: Filter by client ID (number, optional)
686
+ - `tag_ids`: Filter by tag IDs (number[], optional)
687
+
688
+ - **get_sites_basic_v1** - Get basic site info (id, url, name) for fast bulk retrieval
689
+ - `page`: Page number (number, optional)
690
+ - `per_page`: Items per page, max 100 (number, optional)
691
+ - `status`: Filter by status (string, optional)
692
+ - `client_id`: Filter by client ID (number, optional)
693
+ - `tag_ids`: Filter by tag IDs (number[], optional)
694
+
695
+ - **sync_sites_v1** - Trigger synchronization for sites. Large operations queue automatically.
696
+ - `site_ids_or_domains`: Sites to sync, empty array means all (array, optional)
697
+
698
+ - **add_site_v1** - Add a new child site to MainWP
699
+ - `url`: Site URL (string, required)
700
+ - `name`: Site name (string, required)
701
+ - `admin_username`: Admin username on the child site (string, required)
702
+ - `verify_certificate`: SSL verification: 0=off, 1=on, 2=global (number, optional)
703
+ - `http_user`: HTTP auth username (string, optional)
704
+ - `http_pass`: HTTP auth password (string, optional)
705
+ - `tag_ids`: Tag IDs to assign (number[], optional)
706
+ - `client_id`: Client ID to assign (number, optional)
707
+
708
+ - **update_site_v1** - Update settings for a child site
709
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
710
+ - `name`: New site name (string, optional)
711
+ - `url`: New site URL (string, optional)
712
+ - `admin_username`: New admin username (string, optional)
713
+ - `verify_certificate`: SSL verification setting (number, optional)
714
+ - `suspended`: Suspended status: 0 or 1 (number, optional)
715
+ - `tag_ids`: Tag IDs to assign (number[], optional)
716
+ - `client_id`: Client ID to assign (number, optional)
717
+
718
+ - **delete_site_v1** - Delete a child site. Requires two-step confirmation: preview then user approval. [DESTRUCTIVE]
719
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
720
+ - `confirm`: Must be true to request preview (boolean, required)
721
+ - `dry_run`: Preview what would be deleted (boolean, optional)
722
+ - `user_confirmed`: Set to true only after showing preview to user and receiving approval (boolean, optional)
723
+
724
+ - **reconnect_site_v1** - Reconnect a disconnected site
725
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
726
+
727
+ - **disconnect_site_v1** - Disconnect a site
728
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
729
+
730
+ - **suspend_site_v1** - Suspend a site
731
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
732
+
733
+ - **unsuspend_site_v1** - Unsuspend a site
734
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
735
+
736
+ - **check_site_v1** - Check connectivity status of a site
737
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
738
+
739
+ - **reconnect_sites_v1** - Reconnect multiple sites. Large operations queue automatically.
740
+ - `site_ids_or_domains`: Sites to reconnect (array, required)
741
+
742
+ - **disconnect_sites_v1** - Disconnect multiple sites. Large operations queue automatically.
743
+ - `site_ids_or_domains`: Sites to disconnect (array, required)
744
+
745
+ - **check_sites_v1** - Check connectivity for multiple sites. Large operations queue automatically.
746
+ - `site_ids_or_domains`: Sites to check (array, required)
747
+
748
+ - **suspend_sites_v1** - Suspend multiple sites. Large operations queue automatically.
749
+ - `site_ids_or_domains`: Sites to suspend (array, required)
750
+
751
+ - **get_site_plugins_v1** - Get plugins installed on a site
752
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
753
+ - `status`: Filter: all, active, inactive (string, optional)
754
+ - `has_update`: Filter to plugins with updates (boolean, optional)
755
+
756
+ - **get_site_themes_v1** - Get themes installed on a site
757
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
758
+ - `status`: Filter: all, active, inactive (string, optional)
759
+ - `has_update`: Filter to themes with updates (boolean, optional)
760
+
761
+ - **activate_site_plugins_v1** - Activate plugins on a site
762
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
763
+ - `plugins`: Plugin slugs to activate (string[], required)
764
+
765
+ - **deactivate_site_plugins_v1** - Deactivate plugins on a site
766
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
767
+ - `plugins`: Plugin slugs to deactivate (string[], required)
768
+
769
+ - **delete_site_plugins_v1** - Delete plugins from a site. Requires two-step confirmation: preview then user approval. [DESTRUCTIVE]
770
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
771
+ - `plugins`: Plugin slugs to delete (string[], required)
772
+ - `confirm`: Must be true to request preview (boolean, required)
773
+ - `dry_run`: Preview what would be deleted (boolean, optional)
774
+ - `user_confirmed`: Set to true only after showing preview to user and receiving approval (boolean, optional)
775
+
776
+ - **activate_site_theme_v1** - Activate a theme on a site
777
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
778
+ - `theme`: Theme slug to activate (string, required)
779
+
780
+ - **delete_site_themes_v1** - Delete themes from a site. Requires two-step confirmation: preview then user approval. [DESTRUCTIVE]
781
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
782
+ - `themes`: Theme slugs to delete (string[], required)
783
+ - `confirm`: Must be true to request preview (boolean, required)
784
+ - `dry_run`: Preview what would be deleted (boolean, optional)
785
+ - `user_confirmed`: Set to true only after showing preview to user and receiving approval (boolean, optional)
786
+
787
+ - **get_abandoned_plugins_v1** - Get abandoned plugins on a site
788
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
789
+
790
+ - **get_abandoned_themes_v1** - Get abandoned themes on a site
791
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
792
+
793
+ - **get_site_security_v1** - Get security status for a site
794
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
795
+
796
+ - **get_site_changes_v1** - Get non-MainWP changes detected on a site (requires Logs module)
797
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
798
+ - `page`: Page number (number, optional)
799
+ - `per_page`: Items per page, max 100 (number, optional)
800
+ - `type`: Filter by change type (string, optional)
801
+
802
+ - **get_site_client_v1** - Get client assigned to a site
803
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
804
+
805
+ - **get_site_costs_v1** - Get costs for a site (requires Cost Tracker module)
806
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
807
+
808
+ </details>
809
+
810
+ <details>
811
+ <summary>Updates</summary>
812
+
813
+ - **list_updates_v1** - List available updates across sites
814
+ - `page`: Page number (number, optional)
815
+ - `per_page`: Items per page, max 200 (number, optional)
816
+ - `site_ids_or_domains`: Filter to specific sites (array, optional)
817
+ - `types`: Update types: core, plugins, themes, translations (string[], optional)
818
+
819
+ - **run_updates_v1** - Execute updates on sites. Large operations queue automatically.
820
+ - `site_ids_or_domains`: Sites to update, empty means all with updates (array, optional)
821
+ - `types`: Update types to apply (string[], optional)
822
+ - `specific_items`: Specific slugs to update (string[], optional)
823
+
824
+ - **update_all_v1** - Execute ALL available updates across sites. Use with caution.
825
+ - `site_ids_or_domains`: Sites to update, empty means all (array, optional)
826
+ - `types`: Update types: core, plugins, themes, translations (string[], optional)
827
+
828
+ - **get_site_updates_v1** - Get available updates for a single site
829
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
830
+ - `types`: Update types to retrieve (string[], optional)
831
+
832
+ - **update_site_core_v1** - Update WordPress core on a single site
833
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
834
+
835
+ - **update_site_plugins_v1** - Update plugins on a single site
836
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
837
+ - `slugs`: Specific plugin slugs to update, empty means all (string[], optional)
838
+
839
+ - **update_site_themes_v1** - Update themes on a single site
840
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
841
+ - `slugs`: Specific theme slugs to update, empty means all (string[], optional)
842
+
843
+ - **update_site_translations_v1** - Update translations on a single site
844
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
845
+ - `slugs`: Specific translation slugs to update, empty means all (string[], optional)
846
+
847
+ - **list_ignored_updates_v1** - List updates marked as ignored
848
+ - `site_ids_or_domains`: Filter to specific sites (array, optional)
849
+ - `types`: Filter by type: core, plugins, themes (string[], optional)
850
+
851
+ - **set_ignored_updates_v1** - Add or remove items from ignored updates list
852
+ - `action`: ignore or unignore (string, required)
853
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
854
+ - `type`: Update type: core, plugin, theme (string, required)
855
+ - `slug`: Item slug, use "wordpress" for core (string, required)
856
+
857
+ - **ignore_site_core_v1** - Ignore or unignore core updates for a site
858
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
859
+ - `action`: add or remove from ignored list (string, optional)
860
+
861
+ - **ignore_site_plugins_v1** - Ignore or unignore plugin updates for a site
862
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
863
+ - `slugs`: Plugin slugs to ignore/unignore (string[], required)
864
+ - `action`: add or remove from ignored list (string, optional)
865
+
866
+ - **ignore_site_themes_v1** - Ignore or unignore theme updates for a site
867
+ - `site_id_or_domain`: Site ID or domain (string|number, required)
868
+ - `slugs`: Theme slugs to ignore/unignore (string[], required)
869
+ - `action`: add or remove from ignored list (string, optional)
870
+
871
+ </details>
872
+
873
+ <details>
874
+ <summary>Clients</summary>
875
+
876
+ - **list_clients_v1** - List MainWP clients
877
+ - `page`: Page number (number, optional)
878
+ - `per_page`: Items per page, max 100 (number, optional)
879
+ - `status`: Filter: any, active, suspended (string, optional)
880
+ - `search`: Search term (string, optional)
881
+ - `include`: Client IDs to include (number[], optional)
882
+ - `exclude`: Client IDs to exclude (number[], optional)
883
+
884
+ - **count_clients_v1** - Count total clients
885
+ - No parameters
886
+
887
+ - **get_client_v1** - Get detailed information about a client
888
+ - `client_id_or_email`: Client ID or email (string|number, required)
889
+
890
+ - **add_client_v1** - Create a new client
891
+ - `name`: Client name (string, required)
892
+ - `client_email`: Email address (string, optional)
893
+ - `client_phone`: Phone number (string, optional)
894
+ - `address_1`: Address line 1 (string, optional)
895
+ - `address_2`: Address line 2 (string, optional)
896
+ - `city`: City (string, optional)
897
+ - `state`: State/province (string, optional)
898
+ - `zip`: Postal code (string, optional)
899
+ - `country`: Country (string, optional)
900
+ - `note`: Notes (string, optional)
901
+ - `selected_sites`: Site IDs to assign (number[], optional)
902
+ - `client_facebook`: Facebook URL (string, optional)
903
+ - `client_twitter`: Twitter URL (string, optional)
904
+ - `client_instagram`: Instagram URL (string, optional)
905
+ - `client_linkedin`: LinkedIn URL (string, optional)
906
+
907
+ - **update_client_v1** - Update an existing client
908
+ - `client_id_or_email`: Client ID or email (string|number, required)
909
+ - `name`: Client name (string, optional)
910
+ - `client_email`: Email address (string, optional)
911
+ - `client_phone`: Phone number (string, optional)
912
+ - `address_1`: Address line 1 (string, optional)
913
+ - `address_2`: Address line 2 (string, optional)
914
+ - `city`: City (string, optional)
915
+ - `state`: State/province (string, optional)
916
+ - `zip`: Postal code (string, optional)
917
+ - `country`: Country (string, optional)
918
+ - `note`: Notes (string, optional)
919
+ - `selected_sites`: Site IDs to assign (number[], optional)
920
+
921
+ - **delete_client_v1** - Delete a client. Requires two-step confirmation: preview then user approval. [DESTRUCTIVE]
922
+ - `client_id_or_email`: Client ID or email (string|number, required)
923
+ - `confirm`: Must be true to request preview (boolean, required)
924
+ - `dry_run`: Preview what would be deleted (boolean, optional)
925
+ - `user_confirmed`: Set to true only after showing preview to user and receiving approval (boolean, optional)
926
+
927
+ - **suspend_client_v1** - Suspend a client
928
+ - `client_id_or_email`: Client ID or email (string|number, required)
929
+
930
+ - **unsuspend_client_v1** - Unsuspend a client
931
+ - `client_id_or_email`: Client ID or email (string|number, required)
932
+
933
+ - **get_client_sites_v1** - Get sites associated with a client
934
+ - `client_id_or_email`: Client ID or email (string|number, required)
935
+
936
+ - **count_client_sites_v1** - Count sites for a client
937
+ - `client_id_or_email`: Client ID or email (string|number, required)
938
+
939
+ - **get_client_costs_v1** - Get costs for a client (requires Cost Tracker module)
940
+ - `client_id_or_email`: Client ID or email (string|number, required)
941
+
942
+ </details>
943
+
944
+ <details>
945
+ <summary>Tags</summary>
946
+
947
+ - **list_tags_v1** - List MainWP tags
948
+ - `page`: Page number (number, optional)
949
+ - `per_page`: Items per page, max 100 (number, optional)
950
+ - `search`: Search term (string, optional)
951
+ - `include`: Tag IDs to include (number[], optional)
952
+ - `exclude`: Tag IDs to exclude (number[], optional)
953
+
954
+ - **get_tag_v1** - Get detailed information about a tag
955
+ - `tag_id`: Tag ID (number, required)
956
+
957
+ - **add_tag_v1** - Create a new tag
958
+ - `name`: Tag name (string, required)
959
+ - `color`: Tag color in hex format, e.g., #3498db (string, optional)
960
+
961
+ - **update_tag_v1** - Update an existing tag
962
+ - `tag_id`: Tag ID (number, required)
963
+ - `name`: Tag name (string, optional)
964
+ - `color`: Tag color in hex format (string, optional)
965
+
966
+ - **delete_tag_v1** - Delete a tag. Requires two-step confirmation: preview then user approval. [DESTRUCTIVE]
967
+ - `tag_id`: Tag ID (number, required)
968
+ - `confirm`: Must be true to request preview (boolean, required)
969
+ - `dry_run`: Preview what would be deleted (boolean, optional)
970
+ - `user_confirmed`: Set to true only after showing preview to user and receiving approval (boolean, optional)
971
+
972
+ - **get_tag_sites_v1** - Get sites associated with a tag
973
+ - `tag_id`: Tag ID (number, required)
974
+ - `page`: Page number (number, optional)
975
+ - `per_page`: Items per page, max 100 (number, optional)
976
+
977
+ - **get_tag_clients_v1** - Get clients associated with a tag
978
+ - `tag_id`: Tag ID (number, required)
979
+ - `page`: Page number (number, optional)
980
+ - `per_page`: Items per page, max 100 (number, optional)
981
+
982
+ </details>
983
+
984
+ <details>
985
+ <summary>Batch Operations</summary>
986
+
987
+ - **get_batch_job_status_v1** - Get status of a queued batch operation
988
+ - `job_id`: Job ID from queued operation (string, required)
989
+
990
+ Operations with more than 50 sites are automatically queued for background processing. The response includes a `job_id` that you can use with this tool to check progress.
991
+
992
+ </details>
993
+
994
+ ---
995
+
996
+ ## Resources
997
+
998
+ These resources are available for inspection:
999
+
1000
+ | URI | Description |
1001
+ | --------------------- | --------------------------------------------- |
1002
+ | `mainwp://abilities` | Full list of available abilities with schemas |
1003
+ | `mainwp://categories` | List of ability categories |
1004
+ | `mainwp://status` | Current connection status |
1005
+ | `mainwp://help` | Tool documentation and safety conventions |
1006
+
1007
+ ---
1008
+
1009
+ ## Documentation
1010
+
1011
+ - **[Configuration Reference](docs/configuration.md)** - All settings, tool filtering, safe mode
1012
+ - **[Security Guide](docs/security.md)** - Trust model, credential management, best practices
1013
+ - **[Example Prompts](docs/example-prompts.md)** - Sample queries to get started
1014
+ - **[Troubleshooting](docs/troubleshooting.md)** - Common issues and solutions
1015
+
1016
+ ---
1017
+
1018
+ ## Contributing
1019
+
1020
+ ```bash
1021
+ npm run dev # Development mode with hot reload
1022
+ npm run inspect # Test with MCP Inspector
1023
+ npm test # Run tests
1024
+ npm run lint # Check code style
1025
+ npm run format # Format code
1026
+ ```
1027
+
1028
+ CI runs on all pull requests and pushes to main.
1029
+
1030
+ ---
1031
+
1032
+ ## License
1033
+
1034
+ GPL-3.0