PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.22
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.22
2.7.1 2.7.2 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 All 141 releases
metasync / wp-mcp-server / class-mcp-json-rpc-handler.php

class-mcp-json-rpc-handler.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.22, at wp-mcp-server/class-mcp-json-rpc-handler.php

209 lines 5.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MCP JSON-RPC 2.0 Handler
4 *
5 * Handles parsing, validation, and routing of JSON-RPC 2.0 requests
6 * according to the Model Context Protocol specification.
7 *
8 * @package MetaSync
9 * @subpackage MCP_Server
10 */
11
12 if (!defined('ABSPATH')) {
13 exit;
14 }
15
16 class MCP_JSON_RPC_Handler {
17
18 /**
19 * JSON-RPC version
20 */
21 const JSONRPC_VERSION = '2.0';
22
23 /**
24 * Error codes (JSON-RPC 2.0 standard + custom)
25 */
26 const ERROR_PARSE_ERROR = -32700;
27 const ERROR_INVALID_REQUEST = -32600;
28 const ERROR_METHOD_NOT_FOUND = -32601;
29 const ERROR_INVALID_PARAMS = -32602;
30 const ERROR_INTERNAL_ERROR = -32603;
31 const ERROR_SERVER_ERROR = -32000;
32 const ERROR_RATE_LIMITED = -32029;
33
34 /**
35 * Method handlers
36 *
37 * @var array
38 */
39 private $handlers = [];
40
41 /**
42 * Constructor
43 */
44 public function __construct() {
45 // Register default handlers
46 $this->register_handler('initialize', [$this, 'handle_initialize']);
47 $this->register_handler('ping', [$this, 'handle_ping']);
48 }
49
50 /**
51 * Register a method handler
52 *
53 * @param string $method Method name
54 * @param callable $callback Handler callback
55 */
56 public function register_handler($method, $callback) {
57 if (!is_callable($callback)) {
58 throw new InvalidArgumentException("Handler for method '{$method}' must be callable");
59 }
60 $this->handlers[$method] = $callback;
61 }
62
63 /**
64 * Handle incoming JSON-RPC request
65 *
66 * @param string $request_body Raw request body
67 * @return array Response array
68 */
69 public function handle_request($request_body) {
70 // Parse JSON
71 $request = json_decode($request_body, true);
72
73 if (json_last_error() !== JSON_ERROR_NONE) {
74 return $this->error_response(null, self::ERROR_PARSE_ERROR, 'Parse error');
75 }
76
77 // Validate request structure
78 if (!$this->validate_request($request)) {
79 return $this->error_response(
80 isset($request['id']) ? $request['id'] : null,
81 self::ERROR_INVALID_REQUEST,
82 'Invalid Request'
83 );
84 }
85
86 $method = $request['method'];
87 $params = isset($request['params']) ? $request['params'] : [];
88 $id = isset($request['id']) ? $request['id'] : null;
89
90 // Check if handler exists
91 if (!isset($this->handlers[$method])) {
92 return $this->error_response($id, self::ERROR_METHOD_NOT_FOUND, "Method not found: {$method}");
93 }
94
95 try {
96 // Call handler
97 $result = call_user_func($this->handlers[$method], $params);
98 return $this->success_response($id, $result);
99 } catch (InvalidArgumentException $e) {
100 return $this->error_response($id, self::ERROR_INVALID_PARAMS, $e->getMessage());
101 } catch (Exception $e) {
102 // Log error
103 error_log('MCP JSON-RPC Error: ' . $e->getMessage());
104 return $this->error_response($id, self::ERROR_INTERNAL_ERROR, $e->getMessage());
105 }
106 }
107
108 /**
109 * Validate JSON-RPC request structure
110 *
111 * @param mixed $request Request data
112 * @return bool
113 */
114 private function validate_request($request) {
115 if (!is_array($request)) {
116 return false;
117 }
118
119 // Must have jsonrpc, method
120 if (!isset($request['jsonrpc']) || $request['jsonrpc'] !== self::JSONRPC_VERSION) {
121 return false;
122 }
123
124 if (!isset($request['method']) || !is_string($request['method'])) {
125 return false;
126 }
127
128 // Params are optional but must be array or object if present
129 if (isset($request['params']) && !is_array($request['params'])) {
130 return false;
131 }
132
133 return true;
134 }
135
136 /**
137 * Create success response
138 *
139 * @param mixed $id Request ID
140 * @param mixed $result Result data
141 * @return array
142 */
143 public function success_response($id, $result) {
144 return [
145 'jsonrpc' => self::JSONRPC_VERSION,
146 'id' => $id,
147 'result' => $result
148 ];
149 }
150
151 /**
152 * Create error response
153 *
154 * @param mixed $id Request ID
155 * @param int $code Error code
156 * @param string $message Error message
157 * @param mixed $data Optional error data
158 * @return array
159 */
160 public function error_response($id, $code, $message, $data = null) {
161 $error = [
162 'code' => $code,
163 'message' => $message
164 ];
165
166 if ($data !== null) {
167 $error['data'] = $data;
168 }
169
170 return [
171 'jsonrpc' => self::JSONRPC_VERSION,
172 'id' => $id,
173 'error' => $error
174 ];
175 }
176
177 /**
178 * Handle initialize method
179 *
180 * @param array $params Request parameters
181 * @return array
182 */
183 private function handle_initialize($params) {
184 return [
185 'protocolVersion' => '2024-11-05',
186 'capabilities' => [
187 'tools' => [
188 'list' => true,
189 'call' => true
190 ]
191 ],
192 'serverInfo' => [
193 'name' => 'metasync-wordpress-mcp',
194 'version' => METASYNC_VERSION
195 ]
196 ];
197 }
198
199 /**
200 * Handle ping method
201 *
202 * @param array $params Request parameters
203 * @return array
204 */
205 private function handle_ping($params) {
206 return ['status' => 'ok'];
207 }
208 }
209