PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.14
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.14
2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 All 139 releases
metasync / wp-mcp-server / tools / class-mcp-tool-search.php

class-mcp-tool-search.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.14, at wp-mcp-server/tools/class-mcp-tool-search.php

333 lines 10.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MCP Tool: Search Operations
4 *
5 * Provides tools for searching WordPress content.
6 *
7 * @package MetaSync
8 * @subpackage MCP_Server/Tools
9 */
10
11 if (!defined('ABSPATH')) {
12 exit;
13 }
14
15 /**
16 * Search Posts Tool
17 */
18 class MCP_Tool_Search_Posts extends MCP_Tool_Base {
19
20 public function get_name() {
21 return 'wordpress_search_posts';
22 }
23
24 public function get_description() {
25 return 'Search WordPress posts and pages by title or content';
26 }
27
28 public function get_input_schema() {
29 return [
30 'type' => 'object',
31 'properties' => [
32 'search' => [
33 'type' => 'string',
34 'description' => 'Search term to find in post titles and content'
35 ],
36 'post_type' => [
37 'type' => 'string',
38 'description' => 'Post type to search',
39 'enum' => ['post', 'page', 'any'],
40 'default' => 'any'
41 ],
42 'post_status' => [
43 'type' => 'string',
44 'description' => 'Post status filter',
45 'enum' => ['publish', 'draft', 'pending', 'any'],
46 'default' => 'publish'
47 ],
48 'limit' => [
49 'type' => 'integer',
50 'description' => 'Maximum number of results',
51 'default' => 10,
52 'minimum' => 1,
53 'maximum' => 100
54 ]
55 ],
56 'required' => ['search']
57 ];
58 }
59
60 public function execute($params) {
61 $this->validate_params($params);
62 $this->require_capability('read');
63
64 $search_term = $this->sanitize_string($params['search']);
65
66 if (empty($search_term)) {
67 throw new InvalidArgumentException('Search term cannot be empty');
68 }
69
70 // Build query args
71 $args = [
72 's' => $search_term,
73 'post_type' => isset($params['post_type']) ? $params['post_type'] : 'any',
74 'post_status' => isset($params['post_status']) ? $params['post_status'] : 'publish',
75 'posts_per_page' => isset($params['limit']) ? $this->sanitize_integer($params['limit']) : 10,
76 'orderby' => 'relevance',
77 'order' => 'DESC'
78 ];
79
80 // Execute search
81 $query = new WP_Query($args);
82 $results = [];
83
84 if ($query->have_posts()) {
85 while ($query->have_posts()) {
86 $query->the_post();
87 $post_id = get_the_ID();
88
89 // Get excerpt with search term highlighted
90 $excerpt = get_the_excerpt();
91 if (empty($excerpt)) {
92 $excerpt = wp_trim_words(get_the_content(), 30);
93 }
94
95 $results[] = [
96 'id' => $post_id,
97 'title' => get_the_title(),
98 'excerpt' => $excerpt,
99 'type' => get_post_type(),
100 'status' => get_post_status(),
101 'date' => get_the_date('c'),
102 'url' => get_permalink(),
103 'edit_url' => get_edit_post_link($post_id, 'raw')
104 ];
105 }
106 wp_reset_postdata();
107 }
108
109 return $this->success([
110 'results' => $results,
111 'total_found' => $query->found_posts,
112 'search_term' => $search_term,
113 'query' => [
114 'post_type' => $args['post_type'],
115 'post_status' => $args['post_status'],
116 'limit' => $args['posts_per_page']
117 ]
118 ]);
119 }
120 }
121
122 /**
123 * Search by Keyword Tool
124 */
125 class MCP_Tool_Search_By_Keyword extends MCP_Tool_Base {
126
127 public function get_name() {
128 return 'wordpress_search_by_keyword';
129 }
130
131 public function get_description() {
132 return 'Find posts that have a specific focus keyword set';
133 }
134
135 public function get_input_schema() {
136 return [
137 'type' => 'object',
138 'properties' => [
139 'keyword' => [
140 'type' => 'string',
141 'description' => 'Focus keyword to search for'
142 ],
143 'limit' => [
144 'type' => 'integer',
145 'description' => 'Maximum number of results',
146 'default' => 10,
147 'minimum' => 1,
148 'maximum' => 100
149 ]
150 ],
151 'required' => ['keyword']
152 ];
153 }
154
155 public function execute($params) {
156 $this->validate_params($params);
157 $this->require_capability('read');
158
159 $keyword = $this->sanitize_string($params['keyword']);
160 $limit = isset($params['limit']) ? $this->sanitize_integer($params['limit']) : 10;
161
162 if (empty($keyword)) {
163 throw new InvalidArgumentException('Keyword cannot be empty');
164 }
165
166 // Query posts with this focus keyword
167 $args = [
168 'post_type' => 'any',
169 'post_status' => 'any',
170 'posts_per_page' => $limit,
171 'meta_query' => [
172 [
173 'key' => '_metasync_focus_keyword',
174 'value' => $keyword,
175 'compare' => 'LIKE'
176 ]
177 ]
178 ];
179
180 $query = new WP_Query($args);
181 $results = [];
182
183 if ($query->have_posts()) {
184 while ($query->have_posts()) {
185 $query->the_post();
186 $post_id = get_the_ID();
187
188 $results[] = [
189 'id' => $post_id,
190 'title' => get_the_title(),
191 'type' => get_post_type(),
192 'status' => get_post_status(),
193 'url' => get_permalink(),
194 'focus_keyword' => get_post_meta($post_id, '_metasync_focus_keyword', true),
195 'meta_title' => get_post_meta($post_id, '_metasync_metatitle', true)
196 ];
197 }
198 wp_reset_postdata();
199 }
200
201 return $this->success([
202 'results' => $results,
203 'total_found' => $query->found_posts,
204 'keyword' => $keyword
205 ]);
206 }
207 }
208
209 /**
210 * Find Missing Meta Tool
211 */
212 class MCP_Tool_Find_Missing_Meta extends MCP_Tool_Base {
213
214 public function get_name() {
215 return 'wordpress_find_missing_meta';
216 }
217
218 public function get_description() {
219 return 'Find posts that are missing meta descriptions, titles, or focus keywords';
220 }
221
222 public function get_input_schema() {
223 return [
224 'type' => 'object',
225 'properties' => [
226 'missing_field' => [
227 'type' => 'string',
228 'description' => 'Which meta field to check for',
229 'enum' => ['meta_title', 'meta_description', 'focus_keyword', 'any'],
230 'default' => 'meta_description'
231 ],
232 'post_type' => [
233 'type' => 'string',
234 'description' => 'Post type to check',
235 'enum' => ['post', 'page', 'any'],
236 'default' => 'post'
237 ],
238 'limit' => [
239 'type' => 'integer',
240 'description' => 'Maximum number of results',
241 'default' => 10,
242 'minimum' => 1,
243 'maximum' => 100
244 ]
245 ],
246 'required' => []
247 ];
248 }
249
250 public function execute($params) {
251 $this->validate_params($params);
252 $this->require_capability('read');
253
254 $missing_field = isset($params['missing_field']) ? $params['missing_field'] : 'meta_description';
255 $post_type = isset($params['post_type']) ? $params['post_type'] : 'post';
256 $limit = isset($params['limit']) ? $this->sanitize_integer($params['limit']) : 10;
257
258 // Map field names to meta keys
259 $meta_key_map = [
260 'meta_title' => '_metasync_metatitle',
261 'meta_description' => '_metasync_metadesc',
262 'focus_keyword' => '_metasync_focus_keyword'
263 ];
264
265 // Build query
266 $args = [
267 'post_type' => $post_type,
268 'post_status' => 'publish',
269 'posts_per_page' => $limit,
270 'orderby' => 'date',
271 'order' => 'DESC'
272 ];
273
274 if ($missing_field !== 'any') {
275 $meta_key = $meta_key_map[$missing_field];
276 $args['meta_query'] = [
277 'relation' => 'OR',
278 [
279 'key' => $meta_key,
280 'compare' => 'NOT EXISTS'
281 ],
282 [
283 'key' => $meta_key,
284 'value' => '',
285 'compare' => '='
286 ]
287 ];
288 }
289
290 $query = new WP_Query($args);
291 $results = [];
292
293 if ($query->have_posts()) {
294 while ($query->have_posts()) {
295 $query->the_post();
296 $post_id = get_the_ID();
297
298 $meta_title = get_post_meta($post_id, '_metasync_metatitle', true);
299 $meta_desc = get_post_meta($post_id, '_metasync_metadesc', true);
300 $focus_kw = get_post_meta($post_id, '_metasync_focus_keyword', true);
301
302 // For 'any', check if at least one field is missing
303 if ($missing_field === 'any') {
304 if (!empty($meta_title) && !empty($meta_desc) && !empty($focus_kw)) {
305 continue; // Skip if all fields are present
306 }
307 }
308
309 $results[] = [
310 'id' => $post_id,
311 'title' => get_the_title(),
312 'type' => get_post_type(),
313 'url' => get_permalink(),
314 'edit_url' => get_edit_post_link($post_id, 'raw'),
315 'missing' => [
316 'meta_title' => empty($meta_title),
317 'meta_description' => empty($meta_desc),
318 'focus_keyword' => empty($focus_kw)
319 ]
320 ];
321 }
322 wp_reset_postdata();
323 }
324
325 return $this->success([
326 'results' => $results,
327 'total_found' => count($results),
328 'checked_field' => $missing_field,
329 'post_type' => $post_type
330 ]);
331 }
332 }
333