mcp-wordpress 1.1.2

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 (134) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +568 -0
  3. package/bin/mcp-wordpress.js +12 -0
  4. package/bin/setup.js +302 -0
  5. package/bin/status.js +359 -0
  6. package/dist/client/WordPressClient.d.ts +81 -0
  7. package/dist/client/WordPressClient.d.ts.map +1 -0
  8. package/dist/client/WordPressClient.js +354 -0
  9. package/dist/client/WordPressClient.js.map +1 -0
  10. package/dist/client/api.d.ts +140 -0
  11. package/dist/client/api.d.ts.map +1 -0
  12. package/dist/client/api.js +727 -0
  13. package/dist/client/api.js.map +1 -0
  14. package/dist/client/auth.d.ts +121 -0
  15. package/dist/client/auth.d.ts.map +1 -0
  16. package/dist/client/auth.js +430 -0
  17. package/dist/client/auth.js.map +1 -0
  18. package/dist/client/managers/AuthenticationManager.d.ts +39 -0
  19. package/dist/client/managers/AuthenticationManager.d.ts.map +1 -0
  20. package/dist/client/managers/AuthenticationManager.js +159 -0
  21. package/dist/client/managers/AuthenticationManager.js.map +1 -0
  22. package/dist/client/managers/BaseManager.d.ts +22 -0
  23. package/dist/client/managers/BaseManager.d.ts.map +1 -0
  24. package/dist/client/managers/BaseManager.js +47 -0
  25. package/dist/client/managers/BaseManager.js.map +1 -0
  26. package/dist/client/managers/RequestManager.d.ts +45 -0
  27. package/dist/client/managers/RequestManager.d.ts.map +1 -0
  28. package/dist/client/managers/RequestManager.js +161 -0
  29. package/dist/client/managers/RequestManager.js.map +1 -0
  30. package/dist/client/managers/index.d.ts +8 -0
  31. package/dist/client/managers/index.d.ts.map +1 -0
  32. package/dist/client/managers/index.js +8 -0
  33. package/dist/client/managers/index.js.map +1 -0
  34. package/dist/index.d.ts +19 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +264 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/server.d.ts +7 -0
  39. package/dist/server.d.ts.map +1 -0
  40. package/dist/server.js +7 -0
  41. package/dist/server.js.map +1 -0
  42. package/dist/tools/auth.d.ts +44 -0
  43. package/dist/tools/auth.d.ts.map +1 -0
  44. package/dist/tools/auth.js +126 -0
  45. package/dist/tools/auth.js.map +1 -0
  46. package/dist/tools/base.d.ts +37 -0
  47. package/dist/tools/base.d.ts.map +1 -0
  48. package/dist/tools/base.js +60 -0
  49. package/dist/tools/base.js.map +1 -0
  50. package/dist/tools/comments.d.ts +33 -0
  51. package/dist/tools/comments.d.ts.map +1 -0
  52. package/dist/tools/comments.js +228 -0
  53. package/dist/tools/comments.js.map +1 -0
  54. package/dist/tools/index.d.ts +9 -0
  55. package/dist/tools/index.d.ts.map +1 -0
  56. package/dist/tools/index.js +9 -0
  57. package/dist/tools/index.js.map +1 -0
  58. package/dist/tools/media.d.ts +29 -0
  59. package/dist/tools/media.d.ts.map +1 -0
  60. package/dist/tools/media.js +208 -0
  61. package/dist/tools/media.js.map +1 -0
  62. package/dist/tools/pages.d.ts +30 -0
  63. package/dist/tools/pages.d.ts.map +1 -0
  64. package/dist/tools/pages.js +211 -0
  65. package/dist/tools/pages.js.map +1 -0
  66. package/dist/tools/posts.d.ts +30 -0
  67. package/dist/tools/posts.d.ts.map +1 -0
  68. package/dist/tools/posts.js +240 -0
  69. package/dist/tools/posts.js.map +1 -0
  70. package/dist/tools/site.d.ts +31 -0
  71. package/dist/tools/site.d.ts.map +1 -0
  72. package/dist/tools/site.js +192 -0
  73. package/dist/tools/site.js.map +1 -0
  74. package/dist/tools/taxonomies.d.ts +37 -0
  75. package/dist/tools/taxonomies.d.ts.map +1 -0
  76. package/dist/tools/taxonomies.js +280 -0
  77. package/dist/tools/taxonomies.js.map +1 -0
  78. package/dist/tools/users.d.ts +28 -0
  79. package/dist/tools/users.d.ts.map +1 -0
  80. package/dist/tools/users.js +201 -0
  81. package/dist/tools/users.js.map +1 -0
  82. package/dist/types/client.d.ts +215 -0
  83. package/dist/types/client.d.ts.map +1 -0
  84. package/dist/types/client.js +72 -0
  85. package/dist/types/client.js.map +1 -0
  86. package/dist/types/index.d.ts +157 -0
  87. package/dist/types/index.d.ts.map +1 -0
  88. package/dist/types/index.js +12 -0
  89. package/dist/types/index.js.map +1 -0
  90. package/dist/types/mcp.d.ts +178 -0
  91. package/dist/types/mcp.d.ts.map +1 -0
  92. package/dist/types/mcp.js +7 -0
  93. package/dist/types/mcp.js.map +1 -0
  94. package/dist/types/wordpress.d.ts +443 -0
  95. package/dist/types/wordpress.d.ts.map +1 -0
  96. package/dist/types/wordpress.js +7 -0
  97. package/dist/types/wordpress.js.map +1 -0
  98. package/dist/utils/debug.d.ts +63 -0
  99. package/dist/utils/debug.d.ts.map +1 -0
  100. package/dist/utils/debug.js +195 -0
  101. package/dist/utils/debug.js.map +1 -0
  102. package/dist/utils/error.d.ts +19 -0
  103. package/dist/utils/error.d.ts.map +1 -0
  104. package/dist/utils/error.js +71 -0
  105. package/dist/utils/error.js.map +1 -0
  106. package/dist/utils/toolWrapper.d.ts +36 -0
  107. package/dist/utils/toolWrapper.d.ts.map +1 -0
  108. package/dist/utils/toolWrapper.js +90 -0
  109. package/dist/utils/toolWrapper.js.map +1 -0
  110. package/package.json +115 -0
  111. package/src/client/api.ts +1043 -0
  112. package/src/client/auth.ts +527 -0
  113. package/src/client/managers/AuthenticationManager.ts +190 -0
  114. package/src/client/managers/BaseManager.ts +73 -0
  115. package/src/client/managers/RequestManager.ts +214 -0
  116. package/src/client/managers/index.ts +8 -0
  117. package/src/index.ts +337 -0
  118. package/src/server.ts +7 -0
  119. package/src/tools/auth.ts +153 -0
  120. package/src/tools/comments.ts +263 -0
  121. package/src/tools/index.ts +8 -0
  122. package/src/tools/media.ts +240 -0
  123. package/src/tools/pages.ts +246 -0
  124. package/src/tools/posts.ts +277 -0
  125. package/src/tools/site.ts +227 -0
  126. package/src/tools/taxonomies.ts +322 -0
  127. package/src/tools/users.ts +233 -0
  128. package/src/types/client.ts +304 -0
  129. package/src/types/index.ts +207 -0
  130. package/src/types/mcp.ts +247 -0
  131. package/src/types/wordpress.ts +491 -0
  132. package/src/utils/debug.ts +258 -0
  133. package/src/utils/error.ts +88 -0
  134. package/src/utils/toolWrapper.ts +105 -0
@@ -0,0 +1,258 @@
1
+ /**
2
+ * Debug Utility for MCP Server
3
+ *
4
+ * This module provides debug logging that only outputs when DEBUG mode is enabled.
5
+ * This prevents console.log from interfering with MCP STDIO communication.
6
+ */
7
+
8
+ import type { DebugInfo } from '../types/index.js';
9
+
10
+ // Log levels
11
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
12
+
13
+ // Logger interface
14
+ export interface Logger {
15
+ log(...args: any[]): void;
16
+ info(...args: any[]): void;
17
+ warn(...args: any[]): void;
18
+ error(...args: any[]): void;
19
+ }
20
+
21
+ // Enhanced logger with structured logging
22
+ export interface StructuredLogger extends Logger {
23
+ logStructured(info: DebugInfo): void;
24
+ child(context: Record<string, any>): StructuredLogger;
25
+ }
26
+
27
+ // Check if debug mode is enabled
28
+ const isDebugMode = (): boolean =>
29
+ process.env.DEBUG === 'true' ||
30
+ process.env.NODE_ENV === 'development';
31
+
32
+ // Get current timestamp
33
+ const getTimestamp = (): string => new Date().toISOString();
34
+
35
+ // Format log message with timestamp and level
36
+ const formatMessage = (level: LogLevel, args: any[]): string => {
37
+ const timestamp = getTimestamp();
38
+ const prefix = `[${timestamp}] [${level.toUpperCase()}]`;
39
+ return `${prefix} ${args.map(arg =>
40
+ typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
41
+ ).join(' ')}`;
42
+ };
43
+
44
+ // Handle circular references in objects
45
+ const safeStringify = (obj: any): string => {
46
+ try {
47
+ return JSON.stringify(obj, (key, value) => {
48
+ if (value instanceof Error) {
49
+ return {
50
+ name: value.name,
51
+ message: value.message,
52
+ stack: value.stack
53
+ };
54
+ }
55
+ return value;
56
+ }, 2);
57
+ } catch (error) {
58
+ return '[Object with circular reference]';
59
+ }
60
+ };
61
+
62
+ /**
63
+ * Debug logger that only outputs in debug mode
64
+ */
65
+ export const debug: Logger = {
66
+ log: (...args: any[]): void => {
67
+ if (isDebugMode()) {
68
+ console.error(formatMessage('debug', args)); // Use stderr for debug to avoid STDIO interference
69
+ }
70
+ },
71
+
72
+ info: (...args: any[]): void => {
73
+ if (isDebugMode()) {
74
+ console.error(formatMessage('info', args));
75
+ }
76
+ },
77
+
78
+ warn: (...args: any[]): void => {
79
+ if (isDebugMode()) {
80
+ console.error(formatMessage('warn', args));
81
+ }
82
+ },
83
+
84
+ error: (...args: any[]): void => {
85
+ if (isDebugMode()) {
86
+ console.error(formatMessage('error', args));
87
+ }
88
+ }
89
+ };
90
+
91
+ /**
92
+ * Silent logger for production use
93
+ */
94
+ export const silent: Logger = {
95
+ log: (): void => {},
96
+ warn: (): void => {},
97
+ error: (): void => {},
98
+ info: (): void => {}
99
+ };
100
+
101
+ /**
102
+ * Enhanced structured logger
103
+ */
104
+ class StructuredLoggerImpl implements StructuredLogger {
105
+ private context: Record<string, any>;
106
+ private enabled: boolean;
107
+
108
+ constructor(context: Record<string, any> = {}, enabled = isDebugMode()) {
109
+ this.context = context;
110
+ this.enabled = enabled;
111
+ }
112
+
113
+ private output(level: LogLevel, args: any[]): void {
114
+ if (!this.enabled) return;
115
+
116
+ const debugInfo: DebugInfo = {
117
+ timestamp: Date.now(),
118
+ level,
119
+ message: args.map(arg =>
120
+ typeof arg === 'object' ? safeStringify(arg) : String(arg)
121
+ ).join(' '),
122
+ ...(Object.keys(this.context).length > 0 && { context: this.context })
123
+ };
124
+
125
+ console.error(safeStringify(debugInfo));
126
+ }
127
+
128
+ log(...args: any[]): void {
129
+ this.output('debug', args);
130
+ }
131
+
132
+ info(...args: any[]): void {
133
+ this.output('info', args);
134
+ }
135
+
136
+ warn(...args: any[]): void {
137
+ this.output('warn', args);
138
+ }
139
+
140
+ error(...args: any[]): void {
141
+ this.output('error', args);
142
+ }
143
+
144
+ logStructured(info: DebugInfo): void {
145
+ if (!this.enabled) return;
146
+
147
+ const enhancedInfo: DebugInfo = {
148
+ ...info,
149
+ context: { ...this.context, ...info.context }
150
+ };
151
+
152
+ console.error(safeStringify(enhancedInfo));
153
+ }
154
+
155
+ child(context: Record<string, any>): StructuredLogger {
156
+ return new StructuredLoggerImpl(
157
+ { ...this.context, ...context },
158
+ this.enabled
159
+ );
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Create a structured logger instance
165
+ */
166
+ export const createStructuredLogger = (context: Record<string, any> = {}): StructuredLogger => {
167
+ return new StructuredLoggerImpl(context);
168
+ };
169
+
170
+ /**
171
+ * Default logger instance
172
+ */
173
+ export const logger: Logger = debug;
174
+
175
+ /**
176
+ * Create a logger with context
177
+ */
178
+ export const createLogger = (context: Record<string, any> = {}): StructuredLogger => {
179
+ return createStructuredLogger(context);
180
+ };
181
+
182
+ /**
183
+ * Performance measurement utility
184
+ */
185
+ export interface PerformanceTimer {
186
+ end(): number;
187
+ endWithLog(message?: string): number;
188
+ }
189
+
190
+ export const startTimer = (label?: string): PerformanceTimer => {
191
+ const start = Date.now();
192
+
193
+ return {
194
+ end(): number {
195
+ return Date.now() - start;
196
+ },
197
+
198
+ endWithLog(message = 'Operation'): number {
199
+ const duration = Date.now() - start;
200
+ debug.info(`${message} completed in ${duration}ms${label ? ` [${label}]` : ''}`);
201
+ return duration;
202
+ }
203
+ };
204
+ };
205
+
206
+ /**
207
+ * Log error with stack trace
208
+ */
209
+ export const logError = (error: Error | string, context?: Record<string, any>): void => {
210
+ if (typeof error === 'string') {
211
+ debug.error(error, context);
212
+ } else {
213
+ debug.error(`${error.name}: ${error.message}`, {
214
+ stack: error.stack,
215
+ ...context
216
+ });
217
+ }
218
+ };
219
+
220
+ /**
221
+ * Conditional logging
222
+ */
223
+ export const logIf = (condition: boolean, level: LogLevel = 'debug') => {
224
+ if (!condition) return silent;
225
+
226
+ const loggers = {
227
+ log: debug.log,
228
+ info: debug.info,
229
+ warn: debug.warn,
230
+ error: debug.error
231
+ };
232
+
233
+ return loggers[level as keyof typeof loggers] || debug.log;
234
+ };
235
+
236
+ /**
237
+ * Type-safe environment variable getter
238
+ */
239
+ export const getEnvVar = (key: string, defaultValue?: string): string | undefined => {
240
+ const value = process.env[key];
241
+ if (value === undefined && defaultValue !== undefined) {
242
+ debug.warn(`Environment variable ${key} not found, using default: ${defaultValue}`);
243
+ return defaultValue;
244
+ }
245
+ return value;
246
+ };
247
+
248
+ /**
249
+ * Validate required environment variables
250
+ */
251
+ export const validateEnvVars = (required: string[]): void => {
252
+ const missing = required.filter(key => !process.env[key]);
253
+ if (missing.length > 0) {
254
+ const error = new Error(`Missing required environment variables: ${missing.join(', ')}`);
255
+ logError(error);
256
+ throw error;
257
+ }
258
+ };
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Error handling utilities
3
+ */
4
+
5
+ export function getErrorMessage(error: unknown): string {
6
+ if (error instanceof Error) {
7
+ return error.message;
8
+ }
9
+
10
+ if (typeof error === 'string') {
11
+ return error;
12
+ }
13
+
14
+ if (error && typeof error === 'object' && 'message' in error) {
15
+ return String(error.message);
16
+ }
17
+
18
+ return 'Unknown error occurred';
19
+ }
20
+
21
+ export function isError(error: unknown): error is Error {
22
+ return error instanceof Error;
23
+ }
24
+
25
+ export function logAndReturn<T>(error: unknown, defaultValue: T): T {
26
+ console.error('Error occurred:', getErrorMessage(error));
27
+ return defaultValue;
28
+ }
29
+
30
+ /**
31
+ * Enhanced error handler for consistent tool error handling
32
+ */
33
+ export function handleToolError(error: unknown, operation: string, context?: Record<string, unknown>): never {
34
+ console.error(`Error in ${operation}:`, error);
35
+
36
+ if (context) {
37
+ console.error('Context:', context);
38
+ }
39
+
40
+ const message = getErrorMessage(error);
41
+
42
+ // Provide more specific error messages based on error content
43
+ if (message.includes('ECONNREFUSED') || message.includes('ENOTFOUND')) {
44
+ throw new Error(`Connection failed during ${operation}. Please check your WordPress site URL and network connection.`);
45
+ }
46
+
47
+ if (message.includes('401') || message.includes('Unauthorized')) {
48
+ throw new Error(`Authentication failed during ${operation}. Please check your WordPress credentials.`);
49
+ }
50
+
51
+ if (message.includes('403') || message.includes('Forbidden')) {
52
+ throw new Error(`Permission denied during ${operation}. Please check your user permissions.`);
53
+ }
54
+
55
+ if (message.includes('429') || message.includes('Too Many Requests')) {
56
+ throw new Error(`Rate limit exceeded during ${operation}. Please try again later.`);
57
+ }
58
+
59
+ throw new Error(`Failed to ${operation}: ${message}`);
60
+ }
61
+
62
+ /**
63
+ * Validates required parameters
64
+ */
65
+ export function validateRequired(params: Record<string, unknown>, required: string[]): void {
66
+ const missing = required.filter(key => !params[key]);
67
+ if (missing.length > 0) {
68
+ throw new Error(`Missing required parameters: ${missing.join(', ')}`);
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Validates site parameter for multi-site configurations
74
+ */
75
+ export function validateSite(site: string | undefined, availableSites: string[]): string {
76
+ if (!site) {
77
+ if (availableSites.length === 1) {
78
+ return availableSites[0];
79
+ }
80
+ throw new Error(`Site parameter is required when multiple sites are configured. Available sites: ${availableSites.join(', ')}`);
81
+ }
82
+
83
+ if (!availableSites.includes(site)) {
84
+ throw new Error(`Site '${site}' not found. Available sites: ${availableSites.join(', ')}`);
85
+ }
86
+
87
+ return site;
88
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Tool Wrapper Utility
3
+ * Standardizes error handling and reduces repetitive try-catch blocks
4
+ */
5
+
6
+ import { getErrorMessage } from "./error.js";
7
+
8
+ /**
9
+ * Wrapper for tool methods that standardizes error handling
10
+ */
11
+ export function withErrorHandling<T extends any[], R>(
12
+ operation: string,
13
+ fn: (...args: T) => Promise<R>
14
+ ): (...args: T) => Promise<R> {
15
+ return async (...args: T): Promise<R> => {
16
+ try {
17
+ return await fn(...args);
18
+ } catch (error) {
19
+ throw new Error(`${operation}: ${getErrorMessage(error)}`);
20
+ }
21
+ };
22
+ }
23
+
24
+ /**
25
+ * Wrapper for tool methods with validation
26
+ */
27
+ export function withValidation<T extends any[], R>(
28
+ operation: string,
29
+ validator: (...args: T) => void,
30
+ fn: (...args: T) => Promise<R>
31
+ ): (...args: T) => Promise<R> {
32
+ return async (...args: T): Promise<R> => {
33
+ try {
34
+ validator(...args);
35
+ return await fn(...args);
36
+ } catch (error) {
37
+ throw new Error(`${operation}: ${getErrorMessage(error)}`);
38
+ }
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Common validation functions
44
+ */
45
+ export const validators = {
46
+ requireSite: (client: any, params: any) => {
47
+ if (!client) {
48
+ throw new Error("WordPress client is required");
49
+ }
50
+ },
51
+
52
+ requireId: (params: { id?: number | string }) => {
53
+ if (!params.id) {
54
+ throw new Error("ID parameter is required");
55
+ }
56
+ },
57
+
58
+ requireNonEmpty: (value: any, fieldName: string) => {
59
+ if (!value || (typeof value === 'string' && value.trim() === '')) {
60
+ throw new Error(`${fieldName} cannot be empty`);
61
+ }
62
+ },
63
+
64
+ requireFields: (params: any, fields: string[]) => {
65
+ for (const field of fields) {
66
+ if (params[field] === undefined || params[field] === null) {
67
+ throw new Error(`${field} is required`);
68
+ }
69
+ }
70
+ }
71
+ };
72
+
73
+ /**
74
+ * Decorator for class methods to add error handling
75
+ */
76
+ export function errorHandler(operation: string) {
77
+ return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
78
+ const originalMethod = descriptor.value;
79
+
80
+ descriptor.value = async function (...args: any[]) {
81
+ try {
82
+ return await originalMethod.apply(this, args);
83
+ } catch (error) {
84
+ throw new Error(`${operation}: ${getErrorMessage(error)}`);
85
+ }
86
+ };
87
+
88
+ return descriptor;
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Helper to format success responses consistently
94
+ */
95
+ export function formatSuccessResponse(content: string): string {
96
+ return content;
97
+ }
98
+
99
+ /**
100
+ * Helper to format error responses consistently
101
+ */
102
+ export function formatErrorResponse(operation: string, error: any): never {
103
+ const message = getErrorMessage(error);
104
+ throw new Error(`${operation}: ${message}`);
105
+ }