@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.
- package/LICENSE +674 -0
- package/README.md +1034 -0
- package/dist/abilities.d.ts +144 -0
- package/dist/abilities.d.ts.map +1 -0
- package/dist/abilities.js +529 -0
- package/dist/abilities.js.map +1 -0
- package/dist/config.d.ts +135 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +405 -0
- package/dist/config.js.map +1 -0
- package/dist/confirmation-responses.d.ts +44 -0
- package/dist/confirmation-responses.d.ts.map +1 -0
- package/dist/confirmation-responses.js +120 -0
- package/dist/confirmation-responses.js.map +1 -0
- package/dist/errors.d.ts +118 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +206 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +506 -0
- package/dist/index.js.map +1 -0
- package/dist/logging.d.ts +34 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +74 -0
- package/dist/logging.js.map +1 -0
- package/dist/naming.d.ts +23 -0
- package/dist/naming.d.ts.map +1 -0
- package/dist/naming.js +37 -0
- package/dist/naming.js.map +1 -0
- package/dist/prompts.d.ts +22 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +414 -0
- package/dist/prompts.js.map +1 -0
- package/dist/retry.d.ts +77 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +206 -0
- package/dist/retry.js.map +1 -0
- package/dist/security.d.ts +41 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +154 -0
- package/dist/security.js.map +1 -0
- package/dist/tools.d.ts +82 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +861 -0
- package/dist/tools.js.map +1 -0
- package/package.json +73 -0
- package/settings.example.json +30 -0
- package/settings.schema.json +129 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MainWP MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Model Context Protocol server that exposes MainWP Dashboard abilities
|
|
6
|
+
* as MCP tools for AI assistants like Claude.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* MAINWP_URL=https://dashboard.local MAINWP_TOKEN=xxx node dist/index.js
|
|
10
|
+
*
|
|
11
|
+
* Environment Variables:
|
|
12
|
+
* - MAINWP_URL: Base URL of MainWP Dashboard (required)
|
|
13
|
+
* - MAINWP_TOKEN: Bearer token for authentication (required)
|
|
14
|
+
* - MAINWP_SKIP_SSL_VERIFY: Set to "true" to skip SSL verification (optional)
|
|
15
|
+
*/
|
|
16
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
17
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
18
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, CompleteRequestSchema, ListResourceTemplatesRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
19
|
+
import { loadConfig, formatJson } from './config.js';
|
|
20
|
+
import { getTools, executeTool, toolNameToAbilityName, getSessionDataUsage } from './tools.js';
|
|
21
|
+
import { fetchAbilities, fetchCategories, clearCache, onCacheRefresh, executeAbility, initRateLimiter, getAbility, generateHelpDocument, generateToolHelp, } from './abilities.js';
|
|
22
|
+
import { getPromptList, getPrompt, getPromptArgumentCompletions } from './prompts.js';
|
|
23
|
+
import { createLogger, createStderrLogger } from './logging.js';
|
|
24
|
+
import { sanitizeError, isValidId, validateInput } from './security.js';
|
|
25
|
+
import { formatErrorResponse, McpErrorFactory, McpError } from './errors.js';
|
|
26
|
+
// Server metadata
|
|
27
|
+
const SERVER_NAME = 'mainwp-mcp';
|
|
28
|
+
const SERVER_VERSION = '1.0.0-beta.1';
|
|
29
|
+
// Completion limits
|
|
30
|
+
const MAX_COMPLETION_SUGGESTIONS = 20;
|
|
31
|
+
/**
|
|
32
|
+
* Validate and parse a resource URI.
|
|
33
|
+
* Only allows known URI patterns to prevent injection attacks.
|
|
34
|
+
* Decodes URL-encoded characters before validation.
|
|
35
|
+
*/
|
|
36
|
+
function validateResourceUri(uri) {
|
|
37
|
+
// Decode URI to handle URL-encoded characters (e.g., %20, %2F)
|
|
38
|
+
let decodedUri;
|
|
39
|
+
try {
|
|
40
|
+
decodedUri = decodeURIComponent(uri);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// Handle malformed URIs (invalid percent-encoding)
|
|
44
|
+
throw McpErrorFactory.invalidParams('Malformed URI: invalid percent-encoding', {
|
|
45
|
+
uri,
|
|
46
|
+
error: error instanceof Error ? error.message : String(error),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const staticUris = [
|
|
50
|
+
'mainwp://abilities',
|
|
51
|
+
'mainwp://categories',
|
|
52
|
+
'mainwp://status',
|
|
53
|
+
'mainwp://help',
|
|
54
|
+
];
|
|
55
|
+
if (staticUris.includes(decodedUri)) {
|
|
56
|
+
return { type: decodedUri.replace('mainwp://', '') };
|
|
57
|
+
}
|
|
58
|
+
// Match mainwp://site/{id} pattern with strict numeric ID
|
|
59
|
+
const siteMatch = decodedUri.match(/^mainwp:\/\/site\/(\d+)$/);
|
|
60
|
+
if (siteMatch) {
|
|
61
|
+
const siteId = parseInt(siteMatch[1], 10);
|
|
62
|
+
if (siteId < 1 || siteId > Number.MAX_SAFE_INTEGER) {
|
|
63
|
+
throw McpErrorFactory.invalidParams('Invalid site ID: must be between 1 and ' + Number.MAX_SAFE_INTEGER, { uri, siteId });
|
|
64
|
+
}
|
|
65
|
+
return { type: 'site', params: { site_id: siteId } };
|
|
66
|
+
}
|
|
67
|
+
// Match mainwp://help/tool/{tool_name} pattern (lowercase only, matches tool name format)
|
|
68
|
+
const toolHelpMatch = decodedUri.match(/^mainwp:\/\/help\/tool\/([a-z0-9_]+)$/);
|
|
69
|
+
if (toolHelpMatch) {
|
|
70
|
+
return { type: 'tool-help', params: { tool_name: toolHelpMatch[1] } };
|
|
71
|
+
}
|
|
72
|
+
throw McpErrorFactory.resourceNotFound(uri);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create and configure the MCP server
|
|
76
|
+
*/
|
|
77
|
+
async function createServer(config) {
|
|
78
|
+
const server = new Server({
|
|
79
|
+
name: SERVER_NAME,
|
|
80
|
+
version: SERVER_VERSION,
|
|
81
|
+
}, {
|
|
82
|
+
capabilities: {
|
|
83
|
+
tools: { listChanged: true },
|
|
84
|
+
resources: { listChanged: true },
|
|
85
|
+
prompts: { listChanged: true },
|
|
86
|
+
logging: {},
|
|
87
|
+
completions: {},
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
// Create structured logger
|
|
91
|
+
const logger = createLogger(server);
|
|
92
|
+
// Handler: List available tools (derived from abilities)
|
|
93
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
94
|
+
try {
|
|
95
|
+
const tools = await getTools(config, logger);
|
|
96
|
+
return { tools };
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
logger.error('Error listing tools', {
|
|
100
|
+
error: error instanceof Error ? error.message : String(error),
|
|
101
|
+
});
|
|
102
|
+
return { tools: [] };
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
// Handler: Execute a tool call
|
|
106
|
+
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
107
|
+
const { name, arguments: args } = request.params;
|
|
108
|
+
try {
|
|
109
|
+
// Pass abort signal for cancellation support
|
|
110
|
+
const content = await executeTool(config, name, args ?? {}, logger, { signal: extra.signal });
|
|
111
|
+
return { content };
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
return {
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
type: 'text',
|
|
118
|
+
text: formatErrorResponse(error, sanitizeError),
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
isError: true,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
// Handler: List available resources (abilities info, categories, help)
|
|
126
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
127
|
+
return {
|
|
128
|
+
resources: [
|
|
129
|
+
{
|
|
130
|
+
uri: 'mainwp://abilities',
|
|
131
|
+
name: 'MainWP Abilities',
|
|
132
|
+
description: 'List of all available MainWP abilities with their schemas',
|
|
133
|
+
mimeType: 'application/json',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
uri: 'mainwp://categories',
|
|
137
|
+
name: 'MainWP Categories',
|
|
138
|
+
description: 'List of ability categories',
|
|
139
|
+
mimeType: 'application/json',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
uri: 'mainwp://status',
|
|
143
|
+
name: 'Connection Status',
|
|
144
|
+
description: 'Current connection status to MainWP Dashboard',
|
|
145
|
+
mimeType: 'application/json',
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
uri: 'mainwp://help',
|
|
149
|
+
name: 'MainWP MCP Help',
|
|
150
|
+
description: 'Tool documentation, safety conventions (dry_run, confirm), and usage guides',
|
|
151
|
+
mimeType: 'application/json',
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
// Handler: Read a resource
|
|
157
|
+
// URI Handling Convention:
|
|
158
|
+
// - Static URIs (mainwp://abilities, mainwp://categories, mainwp://status, mainwp://help)
|
|
159
|
+
// use direct equality checks for performance.
|
|
160
|
+
// - Dynamic/parameterized URIs (mainwp://site/{id}, mainwp://help/tool/{name})
|
|
161
|
+
// MUST be routed through validateResourceUri() for security validation.
|
|
162
|
+
// - Do not introduce new dynamic URI patterns without using validateResourceUri().
|
|
163
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
164
|
+
const { uri } = request.params;
|
|
165
|
+
try {
|
|
166
|
+
// Static URI handlers (no validation needed - exact match)
|
|
167
|
+
if (uri === 'mainwp://abilities') {
|
|
168
|
+
const abilities = await fetchAbilities(config, false, logger);
|
|
169
|
+
return {
|
|
170
|
+
contents: [
|
|
171
|
+
{
|
|
172
|
+
uri,
|
|
173
|
+
mimeType: 'application/json',
|
|
174
|
+
text: formatJson(config, abilities),
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
if (uri === 'mainwp://categories') {
|
|
180
|
+
const categories = await fetchCategories(config, false, logger);
|
|
181
|
+
return {
|
|
182
|
+
contents: [
|
|
183
|
+
{
|
|
184
|
+
uri,
|
|
185
|
+
mimeType: 'application/json',
|
|
186
|
+
text: formatJson(config, categories),
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
if (uri === 'mainwp://status') {
|
|
192
|
+
// Test connection by fetching abilities
|
|
193
|
+
// Redact dashboardUrl to host-only to avoid leaking full URL path to untrusted MCP clients
|
|
194
|
+
let redactedHost;
|
|
195
|
+
try {
|
|
196
|
+
redactedHost = new URL(config.dashboardUrl).host;
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
redactedHost = '[invalid-url]';
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const abilities = await fetchAbilities(config, true, logger); // Force refresh
|
|
203
|
+
return {
|
|
204
|
+
contents: [
|
|
205
|
+
{
|
|
206
|
+
uri,
|
|
207
|
+
mimeType: 'application/json',
|
|
208
|
+
text: formatJson(config, {
|
|
209
|
+
connected: true,
|
|
210
|
+
dashboardHost: redactedHost,
|
|
211
|
+
abilitiesCount: abilities.length,
|
|
212
|
+
sessionData: getSessionDataUsage(config),
|
|
213
|
+
}),
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
220
|
+
return {
|
|
221
|
+
contents: [
|
|
222
|
+
{
|
|
223
|
+
uri,
|
|
224
|
+
mimeType: 'application/json',
|
|
225
|
+
text: formatJson(config, {
|
|
226
|
+
connected: false,
|
|
227
|
+
dashboardHost: redactedHost,
|
|
228
|
+
error: sanitizeError(errorMsg),
|
|
229
|
+
}),
|
|
230
|
+
},
|
|
231
|
+
],
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Handle help resource: comprehensive documentation
|
|
236
|
+
if (uri === 'mainwp://help') {
|
|
237
|
+
const abilities = await fetchAbilities(config, false, logger);
|
|
238
|
+
const helpDoc = generateHelpDocument(abilities);
|
|
239
|
+
return {
|
|
240
|
+
contents: [
|
|
241
|
+
{
|
|
242
|
+
uri,
|
|
243
|
+
mimeType: 'application/json',
|
|
244
|
+
text: formatJson(config, helpDoc),
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
// Validate and parse the resource URI (throws on invalid URIs)
|
|
250
|
+
const parsed = validateResourceUri(uri);
|
|
251
|
+
// Handle site resource template: mainwp://site/{id}
|
|
252
|
+
if (parsed.type === 'site' && parsed.params?.site_id) {
|
|
253
|
+
const result = await executeAbility(config, 'mainwp/get-site-v1', { site_id: parsed.params.site_id }, logger);
|
|
254
|
+
return {
|
|
255
|
+
contents: [
|
|
256
|
+
{
|
|
257
|
+
uri,
|
|
258
|
+
mimeType: 'application/json',
|
|
259
|
+
text: formatJson(config, result),
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
// Handle tool help resource template: mainwp://help/tool/{tool_name}
|
|
265
|
+
if (parsed.type === 'tool-help' && parsed.params?.tool_name) {
|
|
266
|
+
const toolName = parsed.params.tool_name;
|
|
267
|
+
// Hardcoded 'mainwp' namespace - this server only supports MainWP abilities
|
|
268
|
+
const abilityName = toolNameToAbilityName(toolName, 'mainwp');
|
|
269
|
+
const ability = await getAbility(config, abilityName, logger);
|
|
270
|
+
if (!ability) {
|
|
271
|
+
throw McpErrorFactory.resourceNotFound(uri);
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
contents: [
|
|
275
|
+
{
|
|
276
|
+
uri,
|
|
277
|
+
mimeType: 'application/json',
|
|
278
|
+
text: formatJson(config, generateToolHelp(ability)),
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
// If we get here, the URI was valid but not handled by the code above
|
|
284
|
+
throw new Error(`Unhandled resource type: ${parsed.type}`);
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
return {
|
|
288
|
+
contents: [
|
|
289
|
+
{
|
|
290
|
+
uri,
|
|
291
|
+
mimeType: 'application/json',
|
|
292
|
+
text: formatErrorResponse(error, sanitizeError),
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
// Handler: List available prompts
|
|
299
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
300
|
+
return { prompts: getPromptList() };
|
|
301
|
+
});
|
|
302
|
+
// Handler: Get a specific prompt
|
|
303
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
304
|
+
const { name, arguments: args } = request.params;
|
|
305
|
+
try {
|
|
306
|
+
// Validate prompt arguments before processing
|
|
307
|
+
if (args) {
|
|
308
|
+
validateInput(args);
|
|
309
|
+
}
|
|
310
|
+
return getPrompt(name, args);
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
// Preserve structured MCP errors (e.g., from validateInput)
|
|
314
|
+
if (error instanceof McpError) {
|
|
315
|
+
throw error;
|
|
316
|
+
}
|
|
317
|
+
// Sanitize unexpected errors
|
|
318
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
319
|
+
throw new Error(sanitizeError(errorMessage), { cause: error });
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
// Handler: Argument completions
|
|
323
|
+
server.setRequestHandler(CompleteRequestSchema, async (request) => {
|
|
324
|
+
const { ref, argument } = request.params;
|
|
325
|
+
// Handle prompt argument completions
|
|
326
|
+
if (ref.type === 'ref/prompt') {
|
|
327
|
+
const promptName = ref.name;
|
|
328
|
+
const argName = argument.name;
|
|
329
|
+
// Get static completions for known argument types
|
|
330
|
+
let values = getPromptArgumentCompletions(promptName, argName);
|
|
331
|
+
// For site_id arguments, try to fetch site list dynamically
|
|
332
|
+
if ((argName === 'site_id' || argName === 'site_ids') && values.length === 0) {
|
|
333
|
+
try {
|
|
334
|
+
const abilities = await fetchAbilities(config, false, logger);
|
|
335
|
+
const listSitesAbility = abilities.find(a => a.name === 'mainwp/list-sites-v1');
|
|
336
|
+
if (listSitesAbility) {
|
|
337
|
+
const result = await executeAbility(config, 'mainwp/list-sites-v1', {}, logger);
|
|
338
|
+
if (Array.isArray(result)) {
|
|
339
|
+
// Filter to only valid site IDs
|
|
340
|
+
values = result
|
|
341
|
+
.filter((site) => isValidId(site.id))
|
|
342
|
+
.map((site) => String(site.id));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
// Ignore errors, return empty completions
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Filter by current input value if provided
|
|
351
|
+
const currentValue = argument.value || '';
|
|
352
|
+
const filteredValues = values.filter(v => v.toLowerCase().startsWith(currentValue.toLowerCase()));
|
|
353
|
+
return {
|
|
354
|
+
completion: {
|
|
355
|
+
values: filteredValues.slice(0, MAX_COMPLETION_SUGGESTIONS),
|
|
356
|
+
hasMore: filteredValues.length > MAX_COMPLETION_SUGGESTIONS,
|
|
357
|
+
total: filteredValues.length,
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
// Default: no completions
|
|
362
|
+
return {
|
|
363
|
+
completion: {
|
|
364
|
+
values: [],
|
|
365
|
+
hasMore: false,
|
|
366
|
+
total: 0,
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
});
|
|
370
|
+
// Handler: List resource templates
|
|
371
|
+
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
|
|
372
|
+
return {
|
|
373
|
+
resourceTemplates: [
|
|
374
|
+
{
|
|
375
|
+
uriTemplate: 'mainwp://site/{site_id}',
|
|
376
|
+
name: 'Site Details',
|
|
377
|
+
description: 'Get detailed information about a specific site by ID',
|
|
378
|
+
mimeType: 'application/json',
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
uriTemplate: 'mainwp://help/tool/{tool_name}',
|
|
382
|
+
name: 'Tool Documentation',
|
|
383
|
+
description: 'Get detailed documentation for a specific tool including parameters and safety features',
|
|
384
|
+
mimeType: 'application/json',
|
|
385
|
+
},
|
|
386
|
+
],
|
|
387
|
+
};
|
|
388
|
+
});
|
|
389
|
+
// Register cache refresh callback for list_changed notifications
|
|
390
|
+
onCacheRefresh(() => {
|
|
391
|
+
server.sendToolListChanged().catch(() => {
|
|
392
|
+
// Ignore if not connected
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
return { server, logger };
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Validate credentials by attempting to fetch abilities from the MainWP Dashboard.
|
|
399
|
+
* Provides enhanced error messages for common failure scenarios.
|
|
400
|
+
*
|
|
401
|
+
* @param config - Server configuration
|
|
402
|
+
* @param logger - Logger for status messages
|
|
403
|
+
* @returns The fetched abilities array on success
|
|
404
|
+
* @throws Error with actionable message on failure
|
|
405
|
+
*/
|
|
406
|
+
async function validateCredentials(config, logger) {
|
|
407
|
+
try {
|
|
408
|
+
const abilities = await fetchAbilities(config, false, logger);
|
|
409
|
+
logger.info('Credential validation successful: Connected to MainWP Dashboard');
|
|
410
|
+
return abilities;
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
414
|
+
const lowerMessage = message.toLowerCase();
|
|
415
|
+
// Authentication failures (401/403) - provide auth-type specific guidance
|
|
416
|
+
if (lowerMessage.includes('401') ||
|
|
417
|
+
lowerMessage.includes('403') ||
|
|
418
|
+
lowerMessage.includes('unauthorized') ||
|
|
419
|
+
lowerMessage.includes('forbidden')) {
|
|
420
|
+
const authHint = config.authType === 'basic'
|
|
421
|
+
? 'Verify MAINWP_USER and MAINWP_APP_PASSWORD (or username/appPassword in settings.json) are correct and the user has REST API access.'
|
|
422
|
+
: 'Verify MAINWP_TOKEN (or apiToken in settings.json) is correct and has not expired.';
|
|
423
|
+
throw new Error(`Authentication failed: Invalid credentials. ${authHint}`, {
|
|
424
|
+
cause: error,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
// Endpoint not found (404) - likely missing Abilities API plugin
|
|
428
|
+
if (lowerMessage.includes('404') || lowerMessage.includes('not found')) {
|
|
429
|
+
throw new Error('Abilities API endpoint not found. Verify MAINWP_URL points to a MainWP Dashboard with the Abilities API plugin installed.', { cause: error });
|
|
430
|
+
}
|
|
431
|
+
// Connection timeout
|
|
432
|
+
if (lowerMessage.includes('timeout')) {
|
|
433
|
+
throw new Error('Connection timeout. Verify MAINWP_URL is reachable and the server is responding.', { cause: error });
|
|
434
|
+
}
|
|
435
|
+
// SSL/TLS certificate errors
|
|
436
|
+
if (lowerMessage.includes('certificate') ||
|
|
437
|
+
lowerMessage.includes('ssl') ||
|
|
438
|
+
lowerMessage.includes('tls') ||
|
|
439
|
+
lowerMessage.includes('self-signed') ||
|
|
440
|
+
lowerMessage.includes('unable to verify')) {
|
|
441
|
+
throw new Error('SSL certificate verification failed. For self-signed certificates, set MAINWP_SKIP_SSL_VERIFY=true (development only).', { cause: error });
|
|
442
|
+
}
|
|
443
|
+
// Network connectivity errors
|
|
444
|
+
if (lowerMessage.includes('enotfound') ||
|
|
445
|
+
lowerMessage.includes('econnrefused') ||
|
|
446
|
+
lowerMessage.includes('network') ||
|
|
447
|
+
lowerMessage.includes('getaddrinfo') ||
|
|
448
|
+
lowerMessage.includes('econnreset')) {
|
|
449
|
+
throw new Error('Network error: Cannot reach MAINWP_URL. Verify the URL is correct and the server is accessible.', { cause: error });
|
|
450
|
+
}
|
|
451
|
+
// Other errors - re-throw with prefix
|
|
452
|
+
throw new Error(`Credential validation failed: ${message}`, { cause: error });
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Main entry point
|
|
457
|
+
*/
|
|
458
|
+
async function main() {
|
|
459
|
+
// Use stderr logger before server is initialized
|
|
460
|
+
const startupLogger = createStderrLogger();
|
|
461
|
+
try {
|
|
462
|
+
// Load configuration from environment
|
|
463
|
+
const config = loadConfig();
|
|
464
|
+
// Initialize rate limiter
|
|
465
|
+
initRateLimiter(config.rateLimit);
|
|
466
|
+
startupLogger.info(`MainWP MCP Server v${SERVER_VERSION}`);
|
|
467
|
+
startupLogger.info(`Dashboard: ${config.dashboardUrl}`);
|
|
468
|
+
startupLogger.info(`Auth: ${config.authType === 'basic' ? 'Basic Auth' : 'Bearer Token'}`);
|
|
469
|
+
startupLogger.info(`Config source: ${config.configSource}`);
|
|
470
|
+
startupLogger.info(`Session data limit: ${(config.maxSessionData / 1048576).toFixed(1)}MB`);
|
|
471
|
+
if (config.skipSslVerify) {
|
|
472
|
+
startupLogger.error('╔══════════════════════════════════════════════════════════════╗');
|
|
473
|
+
startupLogger.error('║ WARNING: SSL verification disabled ║');
|
|
474
|
+
startupLogger.error('║ Connection is vulnerable to man-in-the-middle attacks ║');
|
|
475
|
+
startupLogger.error('║ Only use for local development with self-signed certs ║');
|
|
476
|
+
startupLogger.error('╚══════════════════════════════════════════════════════════════╝');
|
|
477
|
+
}
|
|
478
|
+
// Validate credentials with fail-fast behavior
|
|
479
|
+
startupLogger.info('Validating credentials...');
|
|
480
|
+
const abilities = await validateCredentials(config, startupLogger);
|
|
481
|
+
startupLogger.info(`Connected! Found ${abilities.length} abilities`);
|
|
482
|
+
abilities.forEach(a => startupLogger.debug(` - ${a.name}: ${a.label}`));
|
|
483
|
+
// Create server (returns server + structured logger)
|
|
484
|
+
const { server, logger } = await createServer(config);
|
|
485
|
+
// Connect via stdio transport
|
|
486
|
+
const transport = new StdioServerTransport();
|
|
487
|
+
await server.connect(transport);
|
|
488
|
+
logger.info('MCP server running on stdio');
|
|
489
|
+
// Handle graceful shutdown for both SIGINT and SIGTERM
|
|
490
|
+
const shutdown = async (signal) => {
|
|
491
|
+
logger.info(`Received ${signal}, shutting down...`);
|
|
492
|
+
clearCache();
|
|
493
|
+
await server.close();
|
|
494
|
+
process.exit(0);
|
|
495
|
+
};
|
|
496
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
497
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
498
|
+
}
|
|
499
|
+
catch (error) {
|
|
500
|
+
startupLogger.error(`Fatal error: ${error instanceof Error ? error.message : error}`);
|
|
501
|
+
process.exit(1);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
// Run the server
|
|
505
|
+
main();
|
|
506
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured Logging Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides MCP-compliant logging with severity levels.
|
|
5
|
+
* Uses server.sendLoggingMessage() when connected, falls back to stderr.
|
|
6
|
+
*/
|
|
7
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
8
|
+
export type LogLevel = 'debug' | 'info' | 'notice' | 'warning' | 'error' | 'critical' | 'alert' | 'emergency';
|
|
9
|
+
export interface Logger {
|
|
10
|
+
debug(message: string, data?: Record<string, unknown>): void;
|
|
11
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
12
|
+
notice(message: string, data?: Record<string, unknown>): void;
|
|
13
|
+
warning(message: string, data?: Record<string, unknown>): void;
|
|
14
|
+
error(message: string, data?: Record<string, unknown>): void;
|
|
15
|
+
critical(message: string, data?: Record<string, unknown>): void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a logger that sends structured messages to MCP clients.
|
|
19
|
+
*
|
|
20
|
+
* @param server - The MCP server instance (requires logging capability)
|
|
21
|
+
* @param loggerName - Name to identify the logging source (default: 'mainwp-mcp')
|
|
22
|
+
*/
|
|
23
|
+
export declare function createLogger(server: Server, loggerName?: string): Logger;
|
|
24
|
+
/**
|
|
25
|
+
* Create a child logger that automatically includes a request correlation ID
|
|
26
|
+
* in every log entry. Useful for tracing a tool call across log entries.
|
|
27
|
+
*/
|
|
28
|
+
export declare function withRequestId(logger: Logger, requestId: string): Logger;
|
|
29
|
+
/**
|
|
30
|
+
* Simple stderr logger for use before MCP server is initialized.
|
|
31
|
+
* Does not require a server instance.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createStderrLogger(loggerName?: string): Logger;
|
|
34
|
+
//# sourceMappingURL=logging.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE,MAAM,MAAM,QAAQ,GAChB,OAAO,GACP,MAAM,GACN,QAAQ,GACR,SAAS,GACT,OAAO,GACP,UAAU,GACV,OAAO,GACP,WAAW,CAAC;AAEhB,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACjE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,SAAe,GAAG,MAAM,CA8B9E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAavE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,SAAe,GAAG,MAAM,CAepE"}
|
package/dist/logging.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured Logging Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides MCP-compliant logging with severity levels.
|
|
5
|
+
* Uses server.sendLoggingMessage() when connected, falls back to stderr.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Create a logger that sends structured messages to MCP clients.
|
|
9
|
+
*
|
|
10
|
+
* @param server - The MCP server instance (requires logging capability)
|
|
11
|
+
* @param loggerName - Name to identify the logging source (default: 'mainwp-mcp')
|
|
12
|
+
*/
|
|
13
|
+
export function createLogger(server, loggerName = 'mainwp-mcp') {
|
|
14
|
+
const log = (level, message, data) => {
|
|
15
|
+
// Build the log data payload
|
|
16
|
+
const logData = data ? { message, ...data } : message;
|
|
17
|
+
// Try to send via MCP protocol
|
|
18
|
+
server
|
|
19
|
+
.sendLoggingMessage({
|
|
20
|
+
level,
|
|
21
|
+
logger: loggerName,
|
|
22
|
+
data: logData,
|
|
23
|
+
})
|
|
24
|
+
.catch(() => {
|
|
25
|
+
// Fall back to stderr if server not connected or logging not enabled
|
|
26
|
+
const timestamp = new Date().toISOString();
|
|
27
|
+
const dataStr = data ? ` ${JSON.stringify(data)}` : '';
|
|
28
|
+
console.error(`[${timestamp}] [${level.toUpperCase()}] [${loggerName}] ${message}${dataStr}`);
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
debug: (message, data) => log('debug', message, data),
|
|
33
|
+
info: (message, data) => log('info', message, data),
|
|
34
|
+
notice: (message, data) => log('notice', message, data),
|
|
35
|
+
warning: (message, data) => log('warning', message, data),
|
|
36
|
+
error: (message, data) => log('error', message, data),
|
|
37
|
+
critical: (message, data) => log('critical', message, data),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a child logger that automatically includes a request correlation ID
|
|
42
|
+
* in every log entry. Useful for tracing a tool call across log entries.
|
|
43
|
+
*/
|
|
44
|
+
export function withRequestId(logger, requestId) {
|
|
45
|
+
const wrap = (fn) => (message, data) => fn(message, { ...data, requestId });
|
|
46
|
+
return {
|
|
47
|
+
debug: wrap(logger.debug.bind(logger)),
|
|
48
|
+
info: wrap(logger.info.bind(logger)),
|
|
49
|
+
notice: wrap(logger.notice.bind(logger)),
|
|
50
|
+
warning: wrap(logger.warning.bind(logger)),
|
|
51
|
+
error: wrap(logger.error.bind(logger)),
|
|
52
|
+
critical: wrap(logger.critical.bind(logger)),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Simple stderr logger for use before MCP server is initialized.
|
|
57
|
+
* Does not require a server instance.
|
|
58
|
+
*/
|
|
59
|
+
export function createStderrLogger(loggerName = 'mainwp-mcp') {
|
|
60
|
+
const log = (level, message, data) => {
|
|
61
|
+
const timestamp = new Date().toISOString();
|
|
62
|
+
const dataStr = data ? ` ${JSON.stringify(data)}` : '';
|
|
63
|
+
console.error(`[${timestamp}] [${level.toUpperCase()}] [${loggerName}] ${message}${dataStr}`);
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
debug: (message, data) => log('debug', message, data),
|
|
67
|
+
info: (message, data) => log('info', message, data),
|
|
68
|
+
notice: (message, data) => log('notice', message, data),
|
|
69
|
+
warning: (message, data) => log('warning', message, data),
|
|
70
|
+
error: (message, data) => log('error', message, data),
|
|
71
|
+
critical: (message, data) => log('critical', message, data),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=logging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwBH;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,UAAU,GAAG,YAAY;IACpE,MAAM,GAAG,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,IAA8B,EAAQ,EAAE;QACrF,6BAA6B;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAEtD,+BAA+B;QAC/B,MAAM;aACH,kBAAkB,CAAC;YAClB,KAAK;YACL,MAAM,EAAE,UAAU;YAClB,IAAI,EAAE,OAAO;SACd,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,qEAAqE;YACrE,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,OAAO,CAAC,KAAK,CACX,IAAI,SAAS,MAAM,KAAK,CAAC,WAAW,EAAE,MAAM,UAAU,KAAK,OAAO,GAAG,OAAO,EAAE,CAC/E,CAAC;QACJ,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;QACrD,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;QACnD,MAAM,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;QACvD,OAAO,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC;QACzD,KAAK,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;QACrD,QAAQ,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,SAAiB;IAC7D,MAAM,IAAI,GACR,CAAC,EAAyD,EAAE,EAAE,CAC9D,CAAC,OAAe,EAAE,IAA8B,EAAE,EAAE,CAClD,EAAE,CAAC,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACxC,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;KAC7C,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAU,GAAG,YAAY;IAC1D,MAAM,GAAG,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,IAA8B,EAAQ,EAAE;QACrF,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,OAAO,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,KAAK,CAAC,WAAW,EAAE,MAAM,UAAU,KAAK,OAAO,GAAG,OAAO,EAAE,CAAC,CAAC;IAChG,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;QACrD,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;QACnD,MAAM,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;QACvD,OAAO,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC;QACzD,KAAK,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;QACrD,QAAQ,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC;KAC5D,CAAC;AACJ,CAAC"}
|