88
99; ;; Code:
1010
11- (require 'cl-lib )
1211(require 'json )
1312(require 'ai-code-mcp-common )
1413(require 'nadvice )
3130 :type 'boolean
3231 :group 'ai-code-mcp-debug-tools )
3332
34- (defcustom ai-code-mcp-debug-tools-allow-effect-eval nil
35- " When non-nil, allow `eval_elisp' to run in effect mode."
36- :type 'boolean
37- :group 'ai-code-mcp-debug-tools )
38-
3933(defvar ai-code-mcp--last-error-record nil
4034 " Most recent Emacs error snapshot recorded for MCP diagnostics tools." )
4135
9185 :args ((:name " code"
9286 :type string
9387 :description " Single Emacs Lisp form to evaluate." )
94- (:name " mode"
95- :type string
96- :description " Evaluation mode."
97- :optional t )
9888 (:name " buffer_name"
9989 :type string
10090 :description " Optional buffer context."
117107 :optional t )))
118108 " Optional MCP eval tool specification." )
119109
120- (defconst ai-code-mcp-debug-tools--always-denied-symbols
121- '(append-to-file async-shell-command call-interactively call-process
122- command-execute compile copy-file delete-file delete-frame
123- delete-window eval funcall kill-buffer load load-file
124- make-directory make-network-process make-process rename-file
125- recompile require save-buffer save-buffers-kill-emacs shell-command
126- start-process url-retrieve write-file write-region)
127- " Symbols that `eval_elisp' rejects in every mode." )
128-
129- (defconst ai-code-mcp-debug-tools--query-denied-symbols
130- '(add-hook delete-region erase-buffer indent-region insert kill-region
131- newline put remove-hook replace-buffer-contents set setf setq
132- setq-local switch-to-buffer yank)
133- " Additional symbols that `eval_elisp' rejects in query mode." )
134-
135110(defun ai-code-mcp-debug-tools-setup ()
136111 " Register optional MCP debugging tools when enabled."
137112 (when ai-code-mcp-debug-tools-enabled
224199 (line . ,(alist-get 'line position))
225200 (column . ,(alist-get 'column position)))))
226201
227- (defun ai-code-mcp-debug-tools--symbol-denied-p (form denied-symbols )
228- " Return the first symbol in FORM that appears in DENIED-SYMBOLS."
229- (cond
230- ((symbolp form)
231- (and (memq form denied-symbols) form))
232- ((consp form)
233- (let ((head (car form)))
234- (cond
235- ((and (symbolp head)
236- (memq head denied-symbols))
237- head)
238- (t
239- (or (ai-code-mcp-debug-tools--symbol-denied-p head denied-symbols)
240- (cl-some
241- (lambda (item )
242- (ai-code-mcp-debug-tools--symbol-denied-p
243- item denied-symbols))
244- (cdr form)))))))
245- ((vectorp form)
246- (cl-some
247- (lambda (item )
248- (ai-code-mcp-debug-tools--symbol-denied-p item denied-symbols))
249- (append form nil )))
250- (t nil )))
251-
252202(defun ai-code-mcp-debug-tools--parse-single-form (code )
253203 " Parse CODE and return exactly one top-level Emacs Lisp form."
254204 (let* ((read-result (read-from-string code))
278228 (buffer-string )))
279229
280230(defun ai-code-mcp-debug-tools--encode-eval-result
281- (mode target-buffer before-messages capture-messages timed-out
231+ (target-buffer before-messages capture-messages timed-out
282232 value changed-buffers &optional error-object backtrace)
283- " Return a JSON response for MODE in TARGET-BUFFER.
233+ " Return a JSON eval response for TARGET-BUFFER.
284234BEFORE-MESSAGES and CAPTURE-MESSAGES control message collection.
285235TIMED-OUT records timeout state, VALUE carries the result,
286236CHANGED-BUFFERS lists modified buffers, and ERROR-OBJECT or BACKTRACE
287237describe failures."
288238 (json-encode
289239 `((ok . ,(ai-code-mcp--json-bool (null error-object)))
290- (mode . , mode )
291240 (value_repr . ,(and (null error-object) (prin1-to-string value)))
292241 (value_type . ,(and (null error-object)
293242 (symbol-name (type-of value))))
@@ -302,10 +251,10 @@ describe failures."
302251 target-buffer))
303252 (timed_out . ,(ai-code-mcp--json-bool timed-out)))))
304253
305- (defun ai-code-mcp-debug-tools--run-eval (form mode target-buffer timeout-ms
254+ (defun ai-code-mcp-debug-tools--run-eval (form target-buffer timeout-ms
306255 capture-messages
307256 include-backtrace )
308- " Evaluate FORM in MODE within TARGET-BUFFER using TIMEOUT-MS.
257+ " Evaluate FORM within TARGET-BUFFER using TIMEOUT-MS.
309258CAPTURE-MESSAGES controls message collection, and INCLUDE-BACKTRACE
310259keeps the backtrace on failures."
311260 (let ((before-messages (ai-code-mcp--message-lines))
@@ -320,16 +269,9 @@ keeps the backtrace on failures."
320269 (setq timed-out t )
321270 (throw 'ai-code-mcp-debug-tools-timeout nil ))
322271 (setq value
323- (if (string= mode " query" )
324- (save-current-buffer
325- (with-current-buffer target-buffer
326- (save-excursion
327- (save-match-data
328- (save-restriction
329- (eval form t ))))))
330- (save-current-buffer
331- (with-current-buffer target-buffer
332- (eval form t )))))))
272+ (save-current-buffer
273+ (with-current-buffer target-buffer
274+ (eval form t ))))))
333275 (error
334276 (setq error-object
335277 (ai-code-mcp-debug-tools--error-alist
@@ -343,7 +285,6 @@ keeps the backtrace on failures."
343285 " timeout"
344286 " Evaluation exceeded the configured timeout" )))
345287 (ai-code-mcp-debug-tools--encode-eval-result
346- mode
347288 target-buffer
348289 before-messages
349290 capture-messages
@@ -606,14 +547,14 @@ existing bound variable."
606547 (limit . , limit )
607548 (messages . ,(vconcat messages))))))
608549
609- (defun ai-code-mcp-eval-elisp (code &optional mode buffer-name file-path
550+ (defun ai-code-mcp-eval-elisp (code &optional buffer-name file-path
610551 capture-messages include-backtrace
611552 timeout-ms )
612- " Evaluate CODE as a single form using MODE and BUFFER-NAME .
613- Return a JSON payload for BUFFER-NAME, FILE-PATH,
614- CAPTURE-MESSAGES, INCLUDE-BACKTRACE, and TIMEOUT-MS. "
615- ( let* ((mode ( or mode " query " ))
616- (capture-messages (ai-code-mcp-debug-tools--bool-arg
553+ " Evaluate CODE as a single Emacs Lisp form .
554+ Return a JSON payload. BUFFER-NAME or FILE-PATH select the evaluation
555+ context. CAPTURE-MESSAGES, INCLUDE-BACKTRACE, and TIMEOUT-MS control
556+ diagnostics. "
557+ ( let* ( (capture-messages (ai-code-mcp-debug-tools--bool-arg
617558 capture-messages
618559 t ))
619560 (include-backtrace (ai-code-mcp-debug-tools--bool-arg
@@ -624,93 +565,32 @@ CAPTURE-MESSAGES, INCLUDE-BACKTRACE, and TIMEOUT-MS."
624565 buffer-name
625566 file-path))
626567 (parse-error nil )
627- form
628- always-denied
629- query-denied)
630- (unless (member mode '(" query" " effect" ))
631- (error " Argument mode must be either query or effect " ))
568+ form)
632569 (unless (and (integerp timeout-ms) (> timeout-ms 0 ))
633570 (error " Argument timeout_ms must be a positive integer " ))
634571 (condition-case err
635572 (setq form (ai-code-mcp-debug-tools--parse-single-form code))
636573 (error
637574 (setq parse-error err)))
638- (cond
639- (parse-error
640- (ai-code-mcp-debug-tools--encode-eval-result
641- mode
642- target-buffer
643- (ai-code-mcp--message-lines)
644- capture-messages
645- nil
646- nil
647- '()
648- (ai-code-mcp-debug-tools--error-alist
649- (symbol-name (car parse-error))
650- (error-message-string parse-error))
651- (and include-backtrace
652- (ai-code-mcp-debug-tools--backtrace-string))))
653- (t
654- (setq always-denied
655- (ai-code-mcp-debug-tools--symbol-denied-p
656- form
657- ai-code-mcp-debug-tools--always-denied-symbols))
658- (setq query-denied
659- (and (string= mode " query" )
660- (ai-code-mcp-debug-tools--symbol-denied-p
661- form
662- ai-code-mcp-debug-tools--query-denied-symbols)))
663- (cond
664- (always-denied
665- (ai-code-mcp-debug-tools--encode-eval-result
666- mode
667- target-buffer
668- (ai-code-mcp--message-lines)
669- capture-messages
670- nil
671- nil
672- '()
673- (ai-code-mcp-debug-tools--error-alist
674- " symbol_denied"
675- (format " Symbol `%s' is not allowed in eval_elisp "
676- always-denied))
677- nil ))
678- (query-denied
575+ (if parse-error
679576 (ai-code-mcp-debug-tools--encode-eval-result
680- mode
681577 target-buffer
682578 (ai-code-mcp--message-lines)
683579 capture-messages
684580 nil
685581 nil
686582 '()
687583 (ai-code-mcp-debug-tools--error-alist
688- " query_symbol_denied"
689- (format " Symbol `%s' is not allowed in query mode "
690- query-denied))
691- nil ))
692- ((and (string= mode " effect" )
693- (not ai-code-mcp-debug-tools-allow-effect-eval))
694- (ai-code-mcp-debug-tools--encode-eval-result
695- mode
696- target-buffer
697- (ai-code-mcp--message-lines)
698- capture-messages
699- nil
700- nil
701- '()
702- (ai-code-mcp-debug-tools--error-alist
703- " effect_mode_disabled"
704- " Effect mode is disabled by configuration" )
705- nil ))
706- (t
707- (ai-code-mcp-debug-tools--run-eval
708- form
709- mode
710- target-buffer
711- timeout-ms
712- capture-messages
713- include-backtrace)))))))
584+ (symbol-name (car parse-error))
585+ (error-message-string parse-error))
586+ (and include-backtrace
587+ (ai-code-mcp-debug-tools--backtrace-string)))
588+ (ai-code-mcp-debug-tools--run-eval
589+ form
590+ target-buffer
591+ timeout-ms
592+ capture-messages
593+ include-backtrace))))
714594
715595(add-to-list 'ai-code-mcp-server-tool-setup-functions
716596 #'ai-code-mcp-debug-tools-setup )
0 commit comments