diff --git a/ai-code-mcp-agent.el b/ai-code-mcp-agent.el index 2b7b90e9..ab597f60 100644 --- a/ai-code-mcp-agent.el +++ b/ai-code-mcp-agent.el @@ -81,7 +81,7 @@ (let* ((port (ai-code-mcp-http-server-ensure)) (session-id (ai-code-mcp-agent--make-session-id backend)) (token (ai-code-mcp--random-secret)) - (url (ai-code-mcp-agent--make-server-url port session-id)) + (url (ai-code-mcp-agent--make-server-url port)) (launch-metadata (ai-code-mcp-agent--inject-argv backend argv url ai-code-mcp-agent--token-environment-variable)) @@ -142,11 +142,10 @@ Failed file removals are retried; session unregistration occurs at most once." (format-time-string "%Y%m%d%H%M%S") (random 1000000))) -(defun ai-code-mcp-agent--make-server-url (port &optional session-id) - "Build the MCP server URL for PORT, optionally scoped by SESSION-ID." - (if session-id - (format "http://127.0.0.1:%d/mcp/%s" port session-id) - (format "http://127.0.0.1:%d/mcp" port))) +(defun ai-code-mcp-agent--make-server-url (port) + "Build the shared MCP server endpoint for PORT. +The bearer token selects the registered agent session." + (format "http://127.0.0.1:%d/mcp" port)) (defun ai-code-mcp-agent--record-buffer-session (buffer backend session-id url) "Record BUFFER session for BACKEND, SESSION-ID, and URL." diff --git a/test/test_ai-code-codex-cli.el b/test/test_ai-code-codex-cli.el index 1fc5028d..8cdcf3fd 100644 --- a/test/test_ai-code-codex-cli.el +++ b/test/test_ai-code-codex-cli.el @@ -245,8 +245,7 @@ (should (fboundp 'ai-code-mcp-agent-buffer-status)) (let ((status (ai-code-mcp-agent-buffer-status))) (should (eq 'codex (plist-get status :backend))) - (should (equal (format "http://127.0.0.1:8765/mcp/%s" - (car registered)) + (should (equal "http://127.0.0.1:8765/mcp" (plist-get status :server-url))))) (funcall captured-cleanup-fn) (should (equal (car registered) unregistered))) diff --git a/test/test_ai-code-github-copilot-cli.el b/test/test_ai-code-github-copilot-cli.el index 517fb643..dfb9e746 100644 --- a/test/test_ai-code-github-copilot-cli.el +++ b/test/test_ai-code-github-copilot-cli.el @@ -151,7 +151,7 @@ (should (string-match-p "127\\.0\\.0\\.1" (cadr config-args))) (should (string-match-p - "mcp/github-copilot-cli-" + "\\\"url\\\":\\\"http://127\\.0\\.0\\.1:8765/mcp\\\"" (cadr config-args))) (should (string-match-p "AI_CODE_MCP_BEARER_TOKEN" (cadr config-args))) @@ -173,8 +173,7 @@ (should (fboundp 'ai-code-mcp-agent-buffer-status)) (let ((status (ai-code-mcp-agent-buffer-status))) (should (eq 'github-copilot-cli (plist-get status :backend))) - (should (equal (format "http://127.0.0.1:8765/mcp/%s" - (car registered)) + (should (equal "http://127.0.0.1:8765/mcp" (plist-get status :server-url))))) (funcall captured-cleanup-fn) (should (equal (car registered) unregistered)))) diff --git a/test/test_ai-code-mcp-agent.el b/test/test_ai-code-mcp-agent.el index c0d9308b..d7408d9e 100644 --- a/test/test_ai-code-mcp-agent.el +++ b/test/test_ai-code-mcp-agent.el @@ -17,6 +17,30 @@ (provide 'magit)) (require 'ai-code-mcp-agent) +(ert-deftest ai-code-test-mcp-agent-launch-url-matches-http-endpoint () + "Launch metadata should use the exact path accepted by the HTTP server." + (let ((ai-code-mcp-agent-enabled-backends '(codex)) + (ai-code-mcp--sessions (make-hash-table :test 'equal)) + launch) + (cl-letf (((symbol-function 'ai-code-mcp-builtins-setup) #'ignore) + ((symbol-function 'ai-code-mcp-http-server-ensure) + (lambda () 8765)) + ((symbol-function 'ai-code-mcp-http-server-stop) #'ignore) + ((symbol-function 'ai-code-mcp-agent--make-session-id) + (lambda (_backend) "codex-test-session"))) + (unwind-protect + (progn + (setq launch + (ai-code-mcp-agent-prepare-launch + 'codex default-directory '("codex"))) + (should (equal "http://127.0.0.1:8765/mcp" + (plist-get launch :mcp-server-url))) + (should (equal + "mcp_servers.emacs_tools={ url = \"http://127.0.0.1:8765/mcp\", bearer_token_env_var = \"AI_CODE_MCP_BEARER_TOKEN\" }" + (car (last (plist-get launch :argv)))))) + (when-let ((cleanup-fn (plist-get launch :cleanup-fn))) + (funcall cleanup-fn)))))) + (ert-deftest ai-code-test-mcp-agent-prepare-launch-registers-source-before-process-start () "Preparing a launch should register its source before the CLI starts." (let ((ai-code-mcp-agent-enabled-backends '(codex)) @@ -45,7 +69,7 @@ (should (equal (file-name-as-directory project-dir) (file-name-as-directory (plist-get context :project-dir)))) - (should (string-prefix-p + (should (equal (format "http://127.0.0.1:%d/mcp" ai-code-mcp-http-server--port) (plist-get launch :mcp-server-url))))) @@ -157,8 +181,8 @@ "Bearer ${AI_CODE_MCP_BEARER_TOKEN}" (alist-get 'Authorization (alist-get 'headers server))))))) - (should (string-prefix-p "http://127.0.0.1:8765/mcp" - (plist-get launch :mcp-server-url)))) + (should (equal "http://127.0.0.1:8765/mcp" + (plist-get launch :mcp-server-url)))) (funcall (plist-get launch :cleanup-fn)))))) (when (buffer-live-p source-buffer) (kill-buffer source-buffer))))) @@ -252,7 +276,7 @@ "--banner" "value with spaces" "--additional-mcp-config" - "{\"mcpServers\":{\"emacs_tools\":{\"type\":\"http\",\"url\":\"http://127.0.0.1:8765/mcp/github-copilot-cli-20260730223000-42\",\"headers\":{\"Authorization\":\"Bearer ${AI_CODE_MCP_BEARER_TOKEN}\"},\"tools\":[\"*\"]}}}"))) + "{\"mcpServers\":{\"emacs_tools\":{\"type\":\"http\",\"url\":\"http://127.0.0.1:8765/mcp\",\"headers\":{\"Authorization\":\"Bearer ${AI_CODE_MCP_BEARER_TOKEN}\"},\"tools\":[\"*\"]}}}"))) (funcall (plist-get launch :cleanup-fn))))))) (ert-deftest ai-code-test-mcp-agent-codex-launch-preserves-config-override-argument () @@ -279,7 +303,7 @@ "--profile" "work profile" "-c" - "mcp_servers.emacs_tools={ url = \"http://127.0.0.1:8765/mcp/codex-20260730223000-42\", bearer_token_env_var = \"AI_CODE_MCP_BEARER_TOKEN\" }"))) + "mcp_servers.emacs_tools={ url = \"http://127.0.0.1:8765/mcp\", bearer_token_env_var = \"AI_CODE_MCP_BEARER_TOKEN\" }"))) (funcall (plist-get launch :cleanup-fn))))))) (ert-deftest ai-code-test-mcp-agent-open-interpreter-preserves-config-override-argument () @@ -306,7 +330,7 @@ "--model" "provider/model name" "-c" - "mcp_servers.emacs_tools={ url = \"http://127.0.0.1:8765/mcp/open-interpreter-20260730223000-42\", bearer_token_env_var = \"AI_CODE_MCP_BEARER_TOKEN\" }"))) + "mcp_servers.emacs_tools={ url = \"http://127.0.0.1:8765/mcp\", bearer_token_env_var = \"AI_CODE_MCP_BEARER_TOKEN\" }"))) (funcall (plist-get launch :cleanup-fn))))))) (ert-deftest ai-code-test-mcp-agent-claude-cleanup-removes-temp-config () diff --git a/test/test_ai-code-open-interpreter-cli.el b/test/test_ai-code-open-interpreter-cli.el index 6e4bda36..f1179cfe 100644 --- a/test/test_ai-code-open-interpreter-cli.el +++ b/test/test_ai-code-open-interpreter-cli.el @@ -128,7 +128,7 @@ (cadr config-args))) (should (string-match-p - "mcp/open-interpreter-" + "url = \\\"http://127\\.0\\.0\\.1:8765/mcp\\\"" (cadr config-args)))) (should-not (string-match-p "test-interpreter-token" (cadr (member "-c" captured-command)))) @@ -147,8 +147,7 @@ (with-current-buffer session-buffer (let ((status (ai-code-mcp-agent-buffer-status))) (should (eq 'open-interpreter (plist-get status :backend))) - (should (equal (format "http://127.0.0.1:8765/mcp/%s" - (car registered)) + (should (equal "http://127.0.0.1:8765/mcp" (plist-get status :server-url))))) (funcall captured-cleanup-fn) (should (equal (car registered) unregistered)))