PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 3.1.7
AI Engine – The Chatbot, AI Framework & MCP for WordPress v3.1.7
3.5.9 3.5.8 3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / labs / mcp-rest.php
ai-engine / labs Last commit date
mcp-core.php 8 months ago mcp-rest.php 1 year ago mcp.conf 1 year ago mcp.js 8 months ago mcp.md 8 months ago mcp.php 8 months ago oauth.php 9 months ago realtime.php 1 year ago
mcp-rest.php
238 lines
1 <?php
2
3 class Meow_MWAI_Labs_MCP_Rest {
4 private $cache_key = 'mwai_mcp_tools_cache';
5 private $allowed = [ 'posts', 'pages', 'media' ];
6
7 public function __construct() {
8 add_action( 'rest_api_init', [ $this, 'rest_api_init' ] );
9 }
10
11 public function rest_api_init() {
12 add_filter( 'mwai_mcp_tools', [ $this, 'register_rest_tools' ] );
13 add_filter( 'mwai_mcp_callback', [ $this, 'handle_call' ], 10, 4 );
14 }
15
16 public function register_rest_tools( $prevTools ) {
17 $cached = get_transient( $this->cache_key );
18
19 if ( !$cached ) {
20 $tools = [];
21 $server = rest_get_server();
22 $routes = $server->get_routes();
23
24 foreach ( $this->allowed as $resource ) {
25 $base = "/wp/v2/{$resource}";
26 $item = "{$base}/(?P<id>[\d]+)";
27
28 if ( isset( $routes[ $base ] ) ) {
29 foreach ( $routes[ $base ] as $endpoint ) {
30 if ( !empty( $endpoint['methods']['GET'] ) ) {
31 $tools[ "list_{$resource}" ] = [
32 'name' => "list_{$resource}",
33 'description' => "List {$resource}",
34 'category' => 'Dynamic REST',
35 'inputSchema' => $this->build_schema_from_args( $endpoint['args'] ),
36 'outputSchema' => $this->build_output_schema(),
37 ];
38 break;
39 }
40 }
41 }
42
43 if ( isset( $routes[ $item ] ) ) {
44 foreach ( $routes[ $item ] as $endpoint ) {
45 if ( !empty( $endpoint['methods']['GET'] ) ) {
46 $tools[ "get_{$resource}" ] = [
47 'name' => "get_{$resource}",
48 'description' => "Get single {$resource} by ID",
49 'category' => 'Dynamic REST',
50 'inputSchema' => $this->build_schema_from_args( $endpoint['args'] ),
51 'outputSchema' => $this->build_output_schema(),
52 ];
53 break;
54 }
55 }
56 }
57
58 if ( isset( $routes[ $base ] ) ) {
59 foreach ( $routes[ $base ] as $endpoint ) {
60 if ( !empty( $endpoint['methods']['POST'] ) ) {
61 $tools[ "create_{$resource}" ] = [
62 'name' => "create_{$resource}",
63 'description' => "Create {$resource}",
64 'category' => 'Dynamic REST',
65 'inputSchema' => $this->build_schema_from_args( $endpoint['args'] ),
66 'outputSchema' => $this->build_output_schema(),
67 ];
68 break;
69 }
70 }
71 }
72
73 if ( isset( $routes[ $item ] ) ) {
74 foreach ( $routes[ $item ] as $endpoint ) {
75 $methods = array_keys( $endpoint['methods'] );
76 if ( array_intersect( [ 'POST', 'PUT', 'PATCH' ], $methods ) ) {
77 $tools[ "update_{$resource}" ] = [
78 'name' => "update_{$resource}",
79 'description' => "Update {$resource}",
80 'category' => 'Dynamic REST',
81 'inputSchema' => $this->build_schema_from_args( $endpoint['args'] ),
82 'outputSchema' => $this->build_output_schema(),
83 ];
84 break;
85 }
86 }
87 }
88
89 if ( isset( $routes[ $item ] ) ) {
90 foreach ( $routes[ $item ] as $endpoint ) {
91 if ( !empty( $endpoint['methods']['DELETE'] ) ) {
92 $tools[ "delete_{$resource}" ] = [
93 'name' => "delete_{$resource}",
94 'description' => "Delete {$resource}",
95 'category' => 'Dynamic REST',
96 'inputSchema' => $this->build_schema_from_args( $endpoint['args'] ),
97 'outputSchema' => $this->build_output_schema(),
98 ];
99 break;
100 }
101 }
102 }
103 }
104
105 set_transient( $this->cache_key, $tools, DAY_IN_SECONDS );
106 $cached = $tools;
107 }
108
109 return array_merge( array_values( $cached ), $prevTools );
110 }
111
112 private function build_schema_from_args( $args ) {
113 $schema = [
114 'type' => 'object',
115 'properties' => [],
116 'required' => [],
117 ];
118
119 foreach ( $args as $name => $def ) {
120 $schema['properties'][ $name ] = [
121 'type' => $def['type'] ?? 'string',
122 'description' => $def['description'] ?? '',
123 ];
124
125 if ( !empty( $def['required'] ) ) {
126 $schema['required'][] = $name;
127 }
128 }
129
130 return $schema;
131 }
132
133 private function build_output_schema() {
134 return [
135 'type' => 'object',
136 'properties' => [
137 'content' => [
138 'type' => 'array',
139 'items' => [
140 'type' => 'object',
141 'properties' => [
142 'type' => [
143 'type' => 'string',
144 'description' => 'Block type, e.g. text or image',
145 ],
146 'text' => [
147 'type' => 'string',
148 'description' => 'Human-readable content',
149 ],
150 ],
151 'required' => [ 'type', 'text' ],
152 ],
153 ],
154 ],
155 'required' => [ 'content' ],
156 ];
157 }
158
159 public function handle_call( $existing, $tool, $args, $id ) {
160 if ( !empty( $existing ) ) {
161 return $existing;
162 }
163
164 $tools = get_transient( $this->cache_key );
165 if ( !isset( $tools[ $tool ] ) ) {
166 return $existing;
167 }
168
169 // Security check is already done in the MCP auth layer
170 // If we reach here, the user is authorized to use MCP
171
172 list( $action, $resource ) = explode( '_', $tool, 2 );
173 $path = "/wp/v2/{$resource}";
174 $method = 'GET';
175
176 if ( in_array( $action, [ 'get', 'update', 'delete' ], true ) ) {
177 if ( empty( $args['id'] ) ) {
178 return [
179 'jsonrpc' => '2.0',
180 'id' => $id,
181 'error' => [
182 'code' => -32602,
183 'message' => 'Missing parameter: id',
184 ],
185 ];
186 }
187 $path .= '/' . intval( $args['id'] );
188 }
189
190 switch ( $action ) {
191 case 'create':
192 case 'update':
193 $method = 'POST';
194 break;
195 case 'delete':
196 $method = 'DELETE';
197 break;
198 default:
199 $method = 'GET';
200 break;
201 }
202
203 $request = new WP_REST_Request( $method, $path );
204
205 if ( $method === 'GET' ) {
206 foreach ( $args as $key => $value ) {
207 $request->set_param( $key, $value );
208 }
209 }
210 else {
211 $request->set_body_params( $args );
212 }
213
214 $response = rest_do_request( $request );
215
216 if ( is_wp_error( $response ) || $response->get_status() >= 400 ) {
217 $error_obj = is_wp_error( $response ) ? $response : $response->as_error();
218
219 // Return error in old format for backward compatibility
220 // The execute_tool method will detect this and not re-wrap it
221 return [
222 'jsonrpc' => '2.0',
223 'id' => $id,
224 'error' => [
225 'code' => (int) ( $error_obj->get_error_code() ?: $response->get_status() ),
226 'message' => $error_obj->get_error_message(),
227 'data' => $error_obj->get_error_data() ?: null,
228 ],
229 ];
230 }
231
232 $data = $response->get_data();
233
234 // Return just the data - execute_tool will wrap it properly
235 return $data;
236 }
237 }
238