From 1782612e6f855376e6f80d3438d7abc412f6e4ea Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 13 Jan 2026 02:44:36 +0000
Subject: [PATCH 1/7] Initial plan


From c57d2b5eb9a21a5b7cc6f37df0e356471f4b9e9a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 13 Jan 2026 02:55:52 +0000
Subject: [PATCH 2/7] Update Serena to use uvx with HTTP transport

- Modified MCP config rendering to use HTTP URL (http://localhost:9121)
- Added runtime dependency detection for Serena languages
- Created language-to-runtime mapping for supported languages
- Added uvx startup step with HTTP server
- Updated tests to reflect HTTP-based configuration
- All Serena tests passing

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
 pkg/workflow/importable_tools_test.go         |  39 +++---
 pkg/workflow/mcp-config.go                    |  49 +-------
 pkg/workflow/mcp_config_comprehensive_test.go |  36 +++---
 pkg/workflow/mcp_renderer.go                  |  34 +-----
 pkg/workflow/mcp_servers.go                   |  62 ++++++++++
 pkg/workflow/runtime_detection.go             | 115 +++++++++++++++++-
 6 files changed, 227 insertions(+), 108 deletions(-)

diff --git a/pkg/workflow/importable_tools_test.go b/pkg/workflow/importable_tools_test.go
index edf29a89034..c82ecd2eb89 100644
--- a/pkg/workflow/importable_tools_test.go
+++ b/pkg/workflow/importable_tools_test.go
@@ -153,13 +153,19 @@ Uses imported serena tool.
 		t.Error("Expected compiled workflow to contain serena tool")
 	}
 
-	// Verify serena container (now using Docker instead of uvx)
-	if !strings.Contains(workflowData, "ghcr.io/oraios/serena:latest") {
-		t.Error("Expected compiled workflow to contain serena Docker container")
+	// Verify serena HTTP server setup (now using uvx with HTTP transport)
+	if !strings.Contains(workflowData, "Start Serena MCP HTTP Server") {
+		t.Error("Expected compiled workflow to contain Serena HTTP server startup step")
+	}
+	if !strings.Contains(workflowData, "uvx --from git+https://github.com/oraios/serena") {
+		t.Error("Expected compiled workflow to use uvx to start Serena")
+	}
+	if !strings.Contains(workflowData, "http://localhost:9121") {
+		t.Error("Expected compiled workflow to contain Serena HTTP URL")
 	}
 
-	// Verify that language service setup steps are NOT present
-	// since Serena now runs in a container with language services included
+	// Verify that language service setup steps ARE present
+	// since Serena now runs with uvx on the host and needs language runtimes
 	if strings.Contains(workflowData, "Install Go language service") {
 		t.Error("Did not expect Go language service installation step (Serena runs in container)")
 	}
@@ -318,8 +324,8 @@ Uses all imported tools.
 	if !strings.Contains(workflowData, "mcr.microsoft.com/playwright/mcp") {
 		t.Error("Expected compiled workflow to contain playwright Docker image")
 	}
-	if !strings.Contains(workflowData, "ghcr.io/oraios/serena:latest") {
-		t.Error("Expected compiled workflow to contain serena Docker container")
+	if !strings.Contains(workflowData, "http://localhost:9121") {
+		t.Error("Expected compiled workflow to contain Serena HTTP URL")
 	}
 	if !strings.Contains(workflowData, "example.com") {
 		t.Error("Expected compiled workflow to contain example.com domain for playwright")
@@ -391,19 +397,18 @@ Uses imported serena with language config.
 		t.Error("Expected compiled workflow to contain serena tool")
 	}
 
-	// Verify that language runtime setup steps are NOT present
-	// since Serena now runs in a container with language services included
-	if strings.Contains(workflowData, "Setup Go") {
-		t.Error("Did not expect Go setup step (Serena runs in container)")
+	// Verify that runtime setup steps ARE present for Serena languages
+	// since Serena now runs with uvx on the host and needs language runtimes
+	if !strings.Contains(workflowData, "Setup Go") {
+		t.Error("Expected Go setup step (Serena needs Go runtime)")
 	}
-
-	if strings.Contains(workflowData, "Setup Node.js") {
-		t.Error("Did not expect Node.js setup step (Serena runs in container)")
+	if !strings.Contains(workflowData, "Setup Node.js") {
+		t.Error("Expected Node.js setup step (Serena needs Node for TypeScript)")
 	}
 
-	// Verify serena container is present
-	if !strings.Contains(workflowData, "ghcr.io/oraios/serena") {
-		t.Error("Expected serena to use Docker container")
+	// Verify serena HTTP server is started with uvx
+	if !strings.Contains(workflowData, "uvx --from git+https://github.com/oraios/serena") {
+		t.Error("Expected serena to use uvx for HTTP server")
 	}
 }
 
diff --git a/pkg/workflow/mcp-config.go b/pkg/workflow/mcp-config.go
index eb1851ef586..792826b06ad 100644
--- a/pkg/workflow/mcp-config.go
+++ b/pkg/workflow/mcp-config.go
@@ -146,55 +146,18 @@ func renderPlaywrightMCPConfigWithOptions(yaml *strings.Builder, playwrightTool
 }
 
 // renderSerenaMCPConfigWithOptions generates the Serena MCP server configuration with engine-specific options
-// Per MCP Gateway Specification v1.0.0 section 3.2.1, stdio-based MCP servers MUST be containerized.
-// Uses Docker container format as specified by Serena: ghcr.io/oraios/serena:latest
+// Serena now runs using uvx with HTTP transport in the agent job (not containerized)
+// The HTTP server is started in a background step and accessed via http://localhost:9121
 func renderSerenaMCPConfigWithOptions(yaml *strings.Builder, serenaTool any, isLast bool, includeCopilotFields bool, inlineArgs bool) {
-	customArgs := getSerenaCustomArgs(serenaTool)
-
 	yaml.WriteString("              \"serena\": {\n")
 
-	// Add type field for Copilot (per MCP Gateway Specification v1.0.0, use "stdio" for containerized servers)
+	// Add type field for Copilot (HTTP transport)
 	if includeCopilotFields {
-		yaml.WriteString("                \"type\": \"stdio\",\n")
-	}
-
-	// Use Serena's Docker container image
-	yaml.WriteString("                \"container\": \"ghcr.io/oraios/serena:latest\",\n")
-
-	// Docker runtime args (--network host for network access)
-	if inlineArgs {
-		yaml.WriteString("                \"args\": [\"--network\", \"host\"],\n")
-	} else {
-		yaml.WriteString("                \"args\": [\n")
-		yaml.WriteString("                  \"--network\",\n")
-		yaml.WriteString("                  \"host\"\n")
-		yaml.WriteString("                ],\n")
-	}
-
-	// Serena entrypoint
-	yaml.WriteString("                \"entrypoint\": \"serena\",\n")
-
-	// Entrypoint args for Serena MCP server
-	if inlineArgs {
-		yaml.WriteString("                \"entrypointArgs\": [\"start-mcp-server\", \"--context\", \"codex\", \"--project\", \"${{ github.workspace }}\"")
-		// Append custom args if present
-		writeArgsToYAMLInline(yaml, customArgs)
-		yaml.WriteString("],\n")
-	} else {
-		yaml.WriteString("                \"entrypointArgs\": [\n")
-		yaml.WriteString("                  \"start-mcp-server\",\n")
-		yaml.WriteString("                  \"--context\",\n")
-		yaml.WriteString("                  \"codex\",\n")
-		yaml.WriteString("                  \"--project\",\n")
-		yaml.WriteString("                  \"${{ github.workspace }}\"")
-		// Append custom args if present
-		writeArgsToYAML(yaml, customArgs, "                  ")
-		yaml.WriteString("\n")
-		yaml.WriteString("                ],\n")
+		yaml.WriteString("                \"type\": \"http\",\n")
 	}
 
-	// Add volume mount for workspace access
-	yaml.WriteString("                \"mounts\": [\"${{ github.workspace }}:${{ github.workspace }}:rw\"]\n")
+	// HTTP URL for Serena MCP server running on host
+	yaml.WriteString("                \"url\": \"http://localhost:9121\"\n")
 
 	// Note: tools field is NOT included here - the converter script adds it back
 	// for Copilot. This keeps the gateway config compatible with the schema.
diff --git a/pkg/workflow/mcp_config_comprehensive_test.go b/pkg/workflow/mcp_config_comprehensive_test.go
index 12c2aa8f57e..e896758fb5d 100644
--- a/pkg/workflow/mcp_config_comprehensive_test.go
+++ b/pkg/workflow/mcp_config_comprehensive_test.go
@@ -574,15 +574,15 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) {
 			inlineArgs:           false,
 			expectedContent: []string{
 				`"serena": {`,
-				`"container": "ghcr.io/oraios/serena:latest"`,
-				`"entrypoint": "serena"`,
-				`"entrypointArgs"`,
-				`"start-mcp-server"`,
+				`"url": "http://localhost:9121"`,
 				`              },`,
 			},
 			unexpectedContent: []string{
 				`"type"`,
 				`"tools"`,
+				`"container"`,
+				`"entrypoint"`,
+				`"entrypointArgs"`,
 			},
 		},
 		{
@@ -593,12 +593,13 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) {
 			inlineArgs:           false,
 			expectedContent: []string{
 				`"serena": {`,
-				`"container": "ghcr.io/oraios/serena:latest"`,
+				`"url": "http://localhost:9121"`,
 				`              }`,
 			},
 			unexpectedContent: []string{
 				`"type"`,
 				`"tools"`,
+				`"container"`,
 				`              },`,
 			},
 		},
@@ -610,10 +611,12 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) {
 			inlineArgs:           false,
 			expectedContent: []string{
 				`"serena": {`,
-				`"type": "stdio"`,
-				`"container": "ghcr.io/oraios/serena:latest"`,
+				`"type": "http"`,
+				`"url": "http://localhost:9121"`,
+			},
+			unexpectedContent: []string{
+				`"container"`,
 			},
-			unexpectedContent: []string{},
 		},
 		{
 			name:                 "Serena config with inline args format",
@@ -623,11 +626,13 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) {
 			inlineArgs:           true,
 			expectedContent: []string{
 				`"serena": {`,
-				`"type": "stdio"`,
-				`"container": "ghcr.io/oraios/serena:latest"`,
-				`"entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"]`,
+				`"type": "http"`,
+				`"url": "http://localhost:9121"`,
+			},
+			unexpectedContent: []string{
+				`"container"`,
+				`"entrypointArgs"`,
 			},
-			unexpectedContent: []string{},
 		},
 		{
 			name: "Serena config with custom args",
@@ -639,11 +644,14 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) {
 			inlineArgs:           false,
 			expectedContent: []string{
 				`"serena": {`,
-				`"container": "ghcr.io/oraios/serena:latest"`,
+				`"url": "http://localhost:9121"`,
+			},
+			unexpectedContent: []string{
+				`"container"`,
+				// Note: custom args are now used in the startup step, not in MCP config
 				`"--verbose"`,
 				`"--debug"`,
 			},
-			unexpectedContent: []string{},
 		},
 	}
 
diff --git a/pkg/workflow/mcp_renderer.go b/pkg/workflow/mcp_renderer.go
index e93f445dfb4..2cce44fb0e0 100644
--- a/pkg/workflow/mcp_renderer.go
+++ b/pkg/workflow/mcp_renderer.go
@@ -185,40 +185,12 @@ func (r *MCPConfigRendererUnified) RenderSerenaMCP(yaml *strings.Builder, serena
 }
 
 // renderSerenaTOML generates Serena MCP configuration in TOML format
-// Per MCP Gateway Specification v1.0.0 section 3.2.1, stdio-based MCP servers MUST be containerized.
-// Uses Docker container format as specified by Serena: ghcr.io/oraios/serena:latest
+// Serena now runs using uvx with HTTP transport in the agent job (not containerized)
+// The HTTP server is started in a background step and accessed via http://localhost:9121
 func (r *MCPConfigRendererUnified) renderSerenaTOML(yaml *strings.Builder, serenaTool any) {
-	customArgs := getSerenaCustomArgs(serenaTool)
-
 	yaml.WriteString("          \n")
 	yaml.WriteString("          [mcp_servers.serena]\n")
-	yaml.WriteString("          container = \"ghcr.io/oraios/serena:latest\"\n")
-
-	// Docker runtime args (--network host for network access)
-	yaml.WriteString("          args = [\n")
-	yaml.WriteString("            \"--network\",\n")
-	yaml.WriteString("            \"host\",\n")
-	yaml.WriteString("          ]\n")
-
-	// Serena entrypoint
-	yaml.WriteString("          entrypoint = \"serena\"\n")
-
-	// Entrypoint args for Serena MCP server
-	yaml.WriteString("          entrypointArgs = [\n")
-	yaml.WriteString("            \"start-mcp-server\",\n")
-	yaml.WriteString("            \"--context\",\n")
-	yaml.WriteString("            \"codex\",\n")
-	yaml.WriteString("            \"--project\",\n")
-	yaml.WriteString("            \"${{ github.workspace }}\"")
-
-	// Append custom args if present
-	writeArgsToYAML(yaml, customArgs, "            ")
-
-	yaml.WriteString("\n")
-	yaml.WriteString("          ]\n")
-
-	// Add volume mount for workspace access
-	yaml.WriteString("          mounts = [\"${{ github.workspace }}:${{ github.workspace }}:rw\"]\n")
+	yaml.WriteString("          url = \"http://localhost:9121\"\n")
 }
 
 // RenderSafeOutputsMCP generates the Safe Outputs MCP server configuration
diff --git a/pkg/workflow/mcp_servers.go b/pkg/workflow/mcp_servers.go
index 1cb84a42e9b..a49d3828777 100644
--- a/pkg/workflow/mcp_servers.go
+++ b/pkg/workflow/mcp_servers.go
@@ -442,6 +442,68 @@ func (c *Compiler) generateMCPSetup(yaml *strings.Builder, tools map[string]any,
 		yaml.WriteString("          \n")
 	}
 
+	// Start Serena MCP HTTP server if serena tool is enabled
+	hasSerena := false
+	for _, toolName := range mcpTools {
+		if toolName == "serena" {
+			hasSerena = true
+			break
+		}
+	}
+	if hasSerena {
+		// Get Serena tool configuration for custom args
+		serenaTool := tools["serena"]
+		customArgs := getSerenaCustomArgs(serenaTool)
+
+		yaml.WriteString("      - name: Start Serena MCP HTTP Server\n")
+		yaml.WriteString("        id: serena-start\n")
+		yaml.WriteString("        run: |\n")
+		yaml.WriteString("          set -eo pipefail\n")
+		yaml.WriteString("          mkdir -p /tmp/gh-aw/mcp-logs/serena\n")
+		yaml.WriteString("          \n")
+		yaml.WriteString("          echo \"Starting Serena MCP HTTP server on port 9121...\"\n")
+		yaml.WriteString("          \n")
+		yaml.WriteString("          # Start Serena MCP server in background with uvx\n")
+		yaml.WriteString("          uvx --from git+https://github.com/oraios/serena \\\n")
+		yaml.WriteString("            serena start-mcp-server \\\n")
+		yaml.WriteString("            --transport streamable-http \\\n")
+		yaml.WriteString("            --port 9121 \\\n")
+		yaml.WriteString("            --project \"${{ github.workspace }}\"")
+
+		// Append custom args if present
+		if len(customArgs) > 0 {
+			yaml.WriteString(" \\\n")
+			for i, arg := range customArgs {
+				yaml.WriteString("            " + arg)
+				if i < len(customArgs)-1 {
+					yaml.WriteString(" \\\n")
+				}
+			}
+		}
+		yaml.WriteString(" \\\n")
+		yaml.WriteString("            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &\n")
+		yaml.WriteString("          \n")
+		yaml.WriteString("          # Save PID for potential cleanup\n")
+		yaml.WriteString("          echo $! > /tmp/gh-aw/serena-mcp-server.pid\n")
+		yaml.WriteString("          \n")
+		yaml.WriteString("          # Wait for server to start (max 30 seconds)\n")
+		yaml.WriteString("          echo \"Waiting for Serena MCP server to start...\"\n")
+		yaml.WriteString("          for i in {1..30}; do\n")
+		yaml.WriteString("            if curl -s http://localhost:9121/health > /dev/null 2>&1; then\n")
+		yaml.WriteString("              echo \"Serena MCP server is ready\"\n")
+		yaml.WriteString("              break\n")
+		yaml.WriteString("            fi\n")
+		yaml.WriteString("            if [ $i -eq 30 ]; then\n")
+		yaml.WriteString("              echo \"ERROR: Serena MCP server failed to start within 30 seconds\"\n")
+		yaml.WriteString("              echo \"Server logs:\"\n")
+		yaml.WriteString("              cat /tmp/gh-aw/mcp-logs/serena/server.log || true\n")
+		yaml.WriteString("              exit 1\n")
+		yaml.WriteString("            fi\n")
+		yaml.WriteString("            sleep 1\n")
+		yaml.WriteString("          done\n")
+		yaml.WriteString("          \n")
+	}
+
 	// Skip gateway setup if sandbox is disabled
 	// When sandbox: false, MCP servers are configured without the gateway
 	if !isSandboxDisabled(workflowData) {
diff --git a/pkg/workflow/runtime_detection.go b/pkg/workflow/runtime_detection.go
index a45fb6cd02e..b4384d4ad12 100644
--- a/pkg/workflow/runtime_detection.go
+++ b/pkg/workflow/runtime_detection.go
@@ -24,6 +24,11 @@ func DetectRuntimeRequirements(workflowData *WorkflowData) []RuntimeRequirement
 		detectFromMCPConfigs(workflowData.ParsedTools, requirements)
 	}
 
+	// Detect from Serena language configuration
+	if workflowData.ParsedTools != nil && workflowData.ParsedTools.Serena != nil {
+		detectFromSerenaLanguages(workflowData.ParsedTools.Serena, requirements)
+	}
+
 	// Detect from engine requirements
 	if workflowData.EngineConfig != nil && len(workflowData.EngineConfig.Steps) > 0 {
 		detectFromEngineSteps(workflowData.EngineConfig.Steps, requirements)
@@ -129,9 +134,6 @@ func detectFromMCPConfigs(tools *ToolsConfig, requirements map[string]*RuntimeRe
 	allTools := tools.ToMap()
 	log.Printf("Scanning %d MCP configurations for runtime commands", len(allTools))
 
-	// Note: Serena and other built-in MCP servers now run in containers and do not
-	// require runtime detection. Language services are provided inside the containers.
-
 	// Scan custom MCP tools for runtime commands
 	// Skip containerized MCP servers as they don't need host runtime setup
 	for _, tool := range tools.Custom {
@@ -150,6 +152,113 @@ func detectFromMCPConfigs(tools *ToolsConfig, requirements map[string]*RuntimeRe
 	}
 }
 
+// detectFromSerenaLanguages detects runtime requirements based on Serena language configuration
+// Serena now runs using uvx with HTTP transport in the agent job, requiring language runtimes
+// to be installed on the host system
+func detectFromSerenaLanguages(serenaConfig *SerenaToolConfig, requirements map[string]*RuntimeRequirement) {
+	if serenaConfig == nil {
+		return
+	}
+
+	// uvx is always required to run Serena
+	uvRuntime := findRuntimeByID("uv")
+	if uvRuntime != nil {
+		runtimeSetupLog.Print("Serena detected, adding uv runtime requirement")
+		updateRequiredRuntime(uvRuntime, "", requirements)
+	}
+
+	// Map to track which languages we need to process
+	languagesToProcess := make(map[string]string) // language name -> version
+
+	// Check short syntax (array of language names)
+	if len(serenaConfig.ShortSyntax) > 0 {
+		runtimeSetupLog.Printf("Detecting runtimes from Serena short syntax: %v", serenaConfig.ShortSyntax)
+		for _, lang := range serenaConfig.ShortSyntax {
+			languagesToProcess[lang] = "" // No version specified in short syntax
+		}
+	}
+
+	// Check long syntax (detailed language configuration)
+	if len(serenaConfig.Languages) > 0 {
+		runtimeSetupLog.Printf("Detecting runtimes from Serena long syntax: %d languages", len(serenaConfig.Languages))
+		for lang, langConfig := range serenaConfig.Languages {
+			version := ""
+			if langConfig != nil && langConfig.Version != "" {
+				version = langConfig.Version
+			}
+			languagesToProcess[lang] = version
+		}
+	}
+
+	// Map Serena languages to runtime IDs and add requirements
+	for lang, version := range languagesToProcess {
+		runtimeID := mapSerenaLanguageToRuntime(lang)
+		if runtimeID == "" {
+			// Language doesn't map to a known runtime (e.g., bash, markdown, yaml)
+			runtimeSetupLog.Printf("Skipping Serena language '%s' - no runtime mapping", lang)
+			continue
+		}
+
+		runtime := findRuntimeByID(runtimeID)
+		if runtime != nil {
+			runtimeSetupLog.Printf("Adding runtime requirement for Serena language '%s' -> %s (version=%s)", lang, runtimeID, version)
+			updateRequiredRuntime(runtime, version, requirements)
+		}
+	}
+}
+
+// mapSerenaLanguageToRuntime maps a Serena language identifier to a runtime ID
+// Returns empty string if the language doesn't require a runtime setup
+func mapSerenaLanguageToRuntime(serenaLang string) string {
+	// Mapping based on .serena/project.yml language list and available runtimes
+	languageMap := map[string]string{
+		// Direct mappings
+		"go":         "go",
+		"typescript": "node", // JavaScript/TypeScript use Node.js
+		"python":     "python",
+		"java":       "java",
+		"ruby":       "ruby",
+		"haskell":    "haskell",
+		"elixir":     "elixir",
+		"rust":       "rust",
+
+		// Alternative names or variants
+		"python_jedi":       "python",
+		"typescript_vts":    "node",
+		"ruby_solargraph":   "ruby",
+		"kotlin":            "java", // Kotlin runs on JVM
+		"scala":             "java", // Scala runs on JVM
+		"csharp":            "dotnet",
+		"csharp_omnisharp":  "dotnet",
+		"erlang":            "elixir", // Erlang uses same runtime setup
+
+		// Languages that don't need runtime setup (return empty string)
+		"bash":     "",
+		"markdown": "",
+		"yaml":     "",
+
+		// Languages not in our runtime definitions (return empty string)
+		"cpp":       "",
+		"clojure":   "",
+		"dart":      "",
+		"elm":       "",
+		"fortran":   "",
+		"julia":     "",
+		"lua":       "",
+		"nix":       "",
+		"perl":      "",
+		"php":       "",
+		"r":         "",
+		"rego":      "",
+		"swift":     "",
+		"terraform": "",
+		"zig":       "",
+		"al":        "",
+	}
+
+	return languageMap[serenaLang]
+}
+
 // detectFromEngineSteps scans engine steps for runtime commands
 func detectFromEngineSteps(steps []map[string]any, requirements map[string]*RuntimeRequirement) {
 	for _, step := range steps {

From 4450186f6cb77262c053f685a1fd02a8af238673 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 13 Jan 2026 02:59:42 +0000
Subject: [PATCH 3/7] Recompile all workflows with Serena HTTP transport
 changes

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
 .github/workflows/archie.lock.yml             | 53 +++++++++++--
 .github/workflows/cloclo.lock.yml             | 65 +++++++++++-----
 .github/workflows/daily-file-diet.lock.yml    | 53 +++++++++++--
 .../developer-docs-consolidator.lock.yml      | 60 +++++++++++----
 .../duplicate-code-detector.lock.yml          | 75 ++++++++++++-------
 .../workflows/glossary-maintainer.lock.yml    | 53 +++++++++++--
 .github/workflows/go-fan.lock.yml             | 60 +++++++++++----
 .github/workflows/jsweep.lock.yml             | 49 ++++++++++--
 .github/workflows/mcp-inspector.lock.yml      | 52 ++++++++++---
 .github/workflows/q.lock.yml                  | 58 +++++++++++---
 .../repository-quality-improver.lock.yml      | 53 +++++++++++--
 .github/workflows/smoke-claude.lock.yml       | 60 +++++++++++----
 .github/workflows/smoke-codex.lock.yml        | 75 ++++++++++++-------
 .github/workflows/smoke-copilot.lock.yml      | 53 +++++++++++--
 .github/workflows/terminal-stylist.lock.yml   | 53 +++++++++++--
 .github/workflows/typist.lock.yml             | 60 +++++++++++----
 16 files changed, 737 insertions(+), 195 deletions(-)

diff --git a/.github/workflows/archie.lock.yml b/.github/workflows/archie.lock.yml
index addce637fa0..e270fea9063 100644
--- a/.github/workflows/archie.lock.yml
+++ b/.github/workflows/archie.lock.yml
@@ -153,6 +153,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Configure Git credentials
@@ -370,6 +380,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -426,12 +471,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml
index 9c8226e6bde..f0092cccb37 100644
--- a/.github/workflows/cloclo.lock.yml
+++ b/.github/workflows/cloclo.lock.yml
@@ -181,13 +181,18 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
-      - name: Create gh-aw temp directory
-        run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
-      - name: Set up Go
+      - name: Setup Go
         uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
         with:
-          cache: true
-          go-version-file: go.mod
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
+      - name: Create gh-aw temp directory
+        run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Install dependencies
         run: make deps-dev
       - env:
@@ -485,6 +490,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -559,20 +599,7 @@ jobs:
                 }
               },
               "serena": {
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": [
-                  "--network",
-                  "host"
-                ],
-                "entrypoint": "serena",
-                "entrypointArgs": [
-                  "start-mcp-server",
-                  "--context",
-                  "codex",
-                  "--project",
-                  "${{ github.workspace }}"
-                ],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/daily-file-diet.lock.yml b/.github/workflows/daily-file-diet.lock.yml
index 79a0c1dbade..1ff7104cfe7 100644
--- a/.github/workflows/daily-file-diet.lock.yml
+++ b/.github/workflows/daily-file-diet.lock.yml
@@ -113,6 +113,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Configure Git credentials
@@ -368,6 +378,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -424,12 +469,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml
index 3fa5a9c990d..6fb984d9785 100644
--- a/.github/workflows/developer-docs-consolidator.lock.yml
+++ b/.github/workflows/developer-docs-consolidator.lock.yml
@@ -112,6 +112,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       # Cache memory file share configuration from frontmatter processed below
@@ -415,6 +425,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -468,20 +513,7 @@ jobs:
                 }
               },
               "serena": {
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": [
-                  "--network",
-                  "host"
-                ],
-                "entrypoint": "serena",
-                "entrypointArgs": [
-                  "start-mcp-server",
-                  "--context",
-                  "codex",
-                  "--project",
-                  "${{ github.workspace }}"
-                ],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/duplicate-code-detector.lock.yml b/.github/workflows/duplicate-code-detector.lock.yml
index 57a925b7812..49c5451becd 100644
--- a/.github/workflows/duplicate-code-detector.lock.yml
+++ b/.github/workflows/duplicate-code-detector.lock.yml
@@ -106,6 +106,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Configure Git credentials
@@ -356,6 +366,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -400,20 +445,7 @@ jobs:
           env_vars = ["GH_AW_MCP_LOG_DIR", "GH_AW_SAFE_OUTPUTS", "GH_AW_SAFE_OUTPUTS_CONFIG_PATH", "GH_AW_SAFE_OUTPUTS_TOOLS_PATH", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "GITHUB_SHA", "GITHUB_WORKSPACE", "DEFAULT_BRANCH"]
           
           [mcp_servers.serena]
-          container = "ghcr.io/oraios/serena:latest"
-          args = [
-            "--network",
-            "host",
-          ]
-          entrypoint = "serena"
-          entrypointArgs = [
-            "start-mcp-server",
-            "--context",
-            "codex",
-            "--project",
-            "${{ github.workspace }}"
-          ]
-          mounts = ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+          url = "http://localhost:9121"
           EOF
           
           # Generate JSON config for MCP gateway
@@ -450,20 +482,7 @@ jobs:
                 }
               },
               "serena": {
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": [
-                  "--network",
-                  "host"
-                ],
-                "entrypoint": "serena",
-                "entrypointArgs": [
-                  "start-mcp-server",
-                  "--context",
-                  "codex",
-                  "--project",
-                  "${{ github.workspace }}"
-                ],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml
index 3e2bc00d5a1..8000cb0a729 100644
--- a/.github/workflows/glossary-maintainer.lock.yml
+++ b/.github/workflows/glossary-maintainer.lock.yml
@@ -112,6 +112,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       # Cache memory file share configuration from frontmatter processed below
@@ -367,6 +377,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -423,12 +468,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/go-fan.lock.yml b/.github/workflows/go-fan.lock.yml
index 2e92b7109d5..e2f2e1ee79b 100644
--- a/.github/workflows/go-fan.lock.yml
+++ b/.github/workflows/go-fan.lock.yml
@@ -111,6 +111,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       # Cache memory file share configuration from frontmatter processed below
@@ -351,6 +361,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -404,20 +449,7 @@ jobs:
                 }
               },
               "serena": {
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": [
-                  "--network",
-                  "host"
-                ],
-                "entrypoint": "serena",
-                "entrypointArgs": [
-                  "start-mcp-server",
-                  "--context",
-                  "codex",
-                  "--project",
-                  "${{ github.workspace }}"
-                ],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/jsweep.lock.yml b/.github/workflows/jsweep.lock.yml
index 17d81e2a915..610a759ed53 100644
--- a/.github/workflows/jsweep.lock.yml
+++ b/.github/workflows/jsweep.lock.yml
@@ -113,6 +113,12 @@ jobs:
         with:
           node-version: '20'
           package-manager-cache: false
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Install Node.js dependencies
@@ -372,6 +378,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -428,12 +469,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml
index 4c88d041636..f8fb3b18c0c 100644
--- a/.github/workflows/mcp-inspector.lock.yml
+++ b/.github/workflows/mcp-inspector.lock.yml
@@ -127,6 +127,10 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
       - name: Setup Node.js
         uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
         with:
@@ -140,11 +144,6 @@ jobs:
         uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
-      - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
-        with:
-          cache: true
-          go-version-file: go.mod
       - name: Install dependencies
         run: make deps-dev
       - env:
@@ -435,6 +434,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -726,12 +760,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               },
               "tavily": {
                 "type": "http",
diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml
index 833a85b5d4d..8351976f553 100644
--- a/.github/workflows/q.lock.yml
+++ b/.github/workflows/q.lock.yml
@@ -176,13 +176,18 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
-      - name: Create gh-aw temp directory
-        run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
-      - name: Set up Go
+      - name: Setup Go
         uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
         with:
-          cache: true
-          go-version-file: go.mod
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
+      - name: Create gh-aw temp directory
+        run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Install dependencies
         run: make deps-dev
       - env:
@@ -482,6 +487,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -545,12 +585,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               },
               "tavily": {
                 "type": "http",
diff --git a/.github/workflows/repository-quality-improver.lock.yml b/.github/workflows/repository-quality-improver.lock.yml
index ec464cc1dc8..3918d29b9d9 100644
--- a/.github/workflows/repository-quality-improver.lock.yml
+++ b/.github/workflows/repository-quality-improver.lock.yml
@@ -111,6 +111,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       # Cache memory file share configuration from frontmatter processed below
@@ -358,6 +368,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -414,12 +459,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml
index 4b0e3038b99..40e911933ec 100644
--- a/.github/workflows/smoke-claude.lock.yml
+++ b/.github/workflows/smoke-claude.lock.yml
@@ -138,6 +138,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       # Cache memory file share configuration from frontmatter processed below
@@ -572,6 +582,41 @@ jobs:
           
           bash /opt/gh-aw/actions/start_safe_inputs_server.sh
           
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -653,20 +698,7 @@ jobs:
                 }
               },
               "serena": {
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": [
-                  "--network",
-                  "host"
-                ],
-                "entrypoint": "serena",
-                "entrypointArgs": [
-                  "start-mcp-server",
-                  "--context",
-                  "codex",
-                  "--project",
-                  "${{ github.workspace }}"
-                ],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "url": "http://localhost:9121"
               },
               "tavily": {
                 "type": "http",
diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml
index 76f57c2f770..d54648acc41 100644
--- a/.github/workflows/smoke-codex.lock.yml
+++ b/.github/workflows/smoke-codex.lock.yml
@@ -137,6 +137,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       # Cache memory file share configuration from frontmatter processed below
@@ -599,6 +609,41 @@ jobs:
           
           bash /opt/gh-aw/actions/start_safe_inputs_server.sh
           
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -669,20 +714,7 @@ jobs:
           env_vars = ["GH_AW_MCP_LOG_DIR", "GH_AW_SAFE_OUTPUTS", "GH_AW_SAFE_OUTPUTS_CONFIG_PATH", "GH_AW_SAFE_OUTPUTS_TOOLS_PATH", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "GITHUB_SHA", "GITHUB_WORKSPACE", "DEFAULT_BRANCH"]
           
           [mcp_servers.serena]
-          container = "ghcr.io/oraios/serena:latest"
-          args = [
-            "--network",
-            "host",
-          ]
-          entrypoint = "serena"
-          entrypointArgs = [
-            "start-mcp-server",
-            "--context",
-            "codex",
-            "--project",
-            "${{ github.workspace }}"
-          ]
-          mounts = ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+          url = "http://localhost:9121"
           
           [mcp_servers.tavily]
           url = "https://mcp.tavily.com/mcp/"
@@ -747,20 +779,7 @@ jobs:
                 }
               },
               "serena": {
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": [
-                  "--network",
-                  "host"
-                ],
-                "entrypoint": "serena",
-                "entrypointArgs": [
-                  "start-mcp-server",
-                  "--context",
-                  "codex",
-                  "--project",
-                  "${{ github.workspace }}"
-                ],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "url": "http://localhost:9121"
               },
               "tavily": {
               "type": "http",
diff --git a/.github/workflows/smoke-copilot.lock.yml b/.github/workflows/smoke-copilot.lock.yml
index 494be2fcebe..76293d69588 100644
--- a/.github/workflows/smoke-copilot.lock.yml
+++ b/.github/workflows/smoke-copilot.lock.yml
@@ -132,6 +132,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       # Cache memory file share configuration from frontmatter processed below
@@ -472,6 +482,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -535,12 +580,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/terminal-stylist.lock.yml b/.github/workflows/terminal-stylist.lock.yml
index 96de1f3d874..ae3c8b52771 100644
--- a/.github/workflows/terminal-stylist.lock.yml
+++ b/.github/workflows/terminal-stylist.lock.yml
@@ -102,6 +102,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Configure Git credentials
@@ -336,6 +346,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -392,12 +437,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/typist.lock.yml b/.github/workflows/typist.lock.yml
index 8f7f167f995..409750c4be7 100644
--- a/.github/workflows/typist.lock.yml
+++ b/.github/workflows/typist.lock.yml
@@ -109,6 +109,16 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Configure Git credentials
@@ -338,6 +348,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -391,20 +436,7 @@ jobs:
                 }
               },
               "serena": {
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": [
-                  "--network",
-                  "host"
-                ],
-                "entrypoint": "serena",
-                "entrypointArgs": [
-                  "start-mcp-server",
-                  "--context",
-                  "codex",
-                  "--project",
-                  "${{ github.workspace }}"
-                ],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {

From be9ca85b3a193db4568dbc2e29c2b4f06e8dd218 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 13 Jan 2026 06:48:41 +0000
Subject: [PATCH 4/7] Fix Copilot MCP config converter to handle stdio to local
 conversion

The converter script now properly converts type: "stdio" to type: "local"
for Copilot CLI compatibility. HTTP servers remain unchanged as type: "http".

This fixes the Serena configuration for Copilot where Serena MCP server
runs with HTTP transport and should keep type: "http" in the output.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
 .github/aw/actions-lock.json                     |  5 +++++
 .github/workflows/audit-workflows.lock.yml       |  2 +-
 .github/workflows/ci-coach.lock.yml              |  2 +-
 .../daily-copilot-token-report.lock.yml          |  2 +-
 .github/workflows/daily-firewall-report.lock.yml |  2 +-
 .github/workflows/deep-report.lock.yml           |  2 +-
 .github/workflows/dev-hawk.lock.yml              |  2 +-
 .github/workflows/go-logger.lock.yml             |  2 +-
 .github/workflows/hourly-ci-cleaner.lock.yml     |  2 +-
 .github/workflows/portfolio-analyst.lock.yml     |  2 +-
 .../prompt-clustering-analysis.lock.yml          |  2 +-
 .github/workflows/release.lock.yml               |  2 +-
 .github/workflows/safe-output-health.lock.yml    |  2 +-
 .../workflows/static-analysis-report.lock.yml    |  2 +-
 .github/workflows/tidy.lock.yml                  |  2 +-
 .../setup/sh/convert_gateway_config_copilot.sh   | 13 +++++++++----
 pkg/workflow/runtime_detection.go                | 16 ++++++++--------
 17 files changed, 36 insertions(+), 26 deletions(-)

diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json
index 0ef7d9d9063..705bdeb0b60 100644
--- a/.github/aw/actions-lock.json
+++ b/.github/aw/actions-lock.json
@@ -60,6 +60,11 @@
       "version": "v4.3.1",
       "sha": "67a3573c9a986a3f9c594539f4ab511d57bb3ce9"
     },
+    "actions/setup-go@v6": {
+      "repo": "actions/setup-go",
+      "version": "v6",
+      "sha": "7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5"
+    },
     "actions/setup-go@v6.1.0": {
       "repo": "actions/setup-go",
       "version": "v6.1.0",
diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml
index bc313fc5085..c2957c53a5b 100644
--- a/.github/workflows/audit-workflows.lock.yml
+++ b/.github/workflows/audit-workflows.lock.yml
@@ -118,7 +118,7 @@ jobs:
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/ci-coach.lock.yml b/.github/workflows/ci-coach.lock.yml
index 2df155ace86..5a0a95e9c1b 100644
--- a/.github/workflows/ci-coach.lock.yml
+++ b/.github/workflows/ci-coach.lock.yml
@@ -128,7 +128,7 @@ jobs:
         name: Download CI workflow runs from last 7 days
         run: "# Download workflow runs for the ci workflow\ngh run list --repo ${{ github.repository }} --workflow=ci.yml --limit 100 --json databaseId,status,conclusion,createdAt,updatedAt,displayTitle,headBranch,event,url,workflowDatabaseId,number > /tmp/ci-runs.json\n\n# Create directory for artifacts\nmkdir -p /tmp/ci-artifacts\n\n# Download artifacts from recent runs (last 5 successful runs)\necho \"Downloading artifacts from recent CI runs...\"\ngh run list --repo ${{ github.repository }} --workflow=ci.yml --status success --limit 5 --json databaseId | jq -r '.[].databaseId' | while read -r run_id; do\n  echo \"Processing run $run_id\"\n  gh run download \"$run_id\" --repo ${{ github.repository }} --dir \"/tmp/ci-artifacts/$run_id\" 2>/dev/null || echo \"No artifacts for run $run_id\"\ndone\n\necho \"CI runs data saved to /tmp/ci-runs.json\"\necho \"Artifacts saved to /tmp/ci-artifacts/\"\n\n# Summarize downloaded artifacts\necho \"## Downloaded Artifacts\" >> $GITHUB_STEP_SUMMARY\nfind /tmp/ci-artifacts -type f -name \"*.txt\" -o -name \"*.html\" -o -name \"*.json\" | head -20 | while read -r f; do\n  echo \"- $(basename $f)\" >> $GITHUB_STEP_SUMMARY\ndone\n"
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/daily-copilot-token-report.lock.yml b/.github/workflows/daily-copilot-token-report.lock.yml
index 92563113eeb..c1d477006c1 100644
--- a/.github/workflows/daily-copilot-token-report.lock.yml
+++ b/.github/workflows/daily-copilot-token-report.lock.yml
@@ -137,7 +137,7 @@ jobs:
             /tmp/gh-aw/python/data/*
           retention-days: 30
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/daily-firewall-report.lock.yml b/.github/workflows/daily-firewall-report.lock.yml
index fef351b14bd..85052f8a746 100644
--- a/.github/workflows/daily-firewall-report.lock.yml
+++ b/.github/workflows/daily-firewall-report.lock.yml
@@ -117,7 +117,7 @@ jobs:
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/deep-report.lock.yml b/.github/workflows/deep-report.lock.yml
index 9de01df6c7b..73cbe12c501 100644
--- a/.github/workflows/deep-report.lock.yml
+++ b/.github/workflows/deep-report.lock.yml
@@ -128,7 +128,7 @@ jobs:
         name: Fetch weekly issues data
         run: "# Create output directories\nmkdir -p /tmp/gh-aw/weekly-issues-data\nmkdir -p /tmp/gh-aw/cache-memory\n\n# Get today's date for cache identification\nTODAY=$(date '+%Y-%m-%d')\nCACHE_DIR=\"/tmp/gh-aw/cache-memory\"\n\n# Check if cached data exists from today\nif [ -f \"$CACHE_DIR/weekly-issues-${TODAY}.json\" ] && [ -s \"$CACHE_DIR/weekly-issues-${TODAY}.json\" ]; then\n  echo \"✓ Found cached weekly issues data from ${TODAY}\"\n  cp \"$CACHE_DIR/weekly-issues-${TODAY}.json\" /tmp/gh-aw/weekly-issues-data/issues.json\n  \n  # Regenerate schema if missing\n  if [ ! -f \"$CACHE_DIR/weekly-issues-${TODAY}-schema.json\" ]; then\n    /tmp/gh-aw/jqschema.sh < /tmp/gh-aw/weekly-issues-data/issues.json > \"$CACHE_DIR/weekly-issues-${TODAY}-schema.json\"\n  fi\n  cp \"$CACHE_DIR/weekly-issues-${TODAY}-schema.json\" /tmp/gh-aw/weekly-issues-data/issues-schema.json\n  \n  echo \"Using cached data from ${TODAY}\"\n  echo \"Total issues in cache: $(jq 'length' /tmp/gh-aw/weekly-issues-data/issues.json)\"\nelse\n  echo \"⬇ Downloading fresh weekly issues data...\"\n  \n  # Calculate date 7 days ago (cross-platform: GNU date first, BSD fallback)\n  DATE_7_DAYS_AGO=$(date -d '7 days ago' '+%Y-%m-%d' 2>/dev/null || date -v-7d '+%Y-%m-%d')\n  \n  echo \"Fetching issues created or updated since ${DATE_7_DAYS_AGO}...\"\n  \n  # Fetch issues from the last 7 days using gh CLI\n  # Using --search with updated filter to get recent activity\n  gh issue list --repo ${{ github.repository }} \\\n    --search \"updated:>=${DATE_7_DAYS_AGO}\" \\\n    --state all \\\n    --json number,title,author,createdAt,state,url,body,labels,updatedAt,closedAt,milestone,assignees,comments \\\n    --limit 500 \\\n    > /tmp/gh-aw/weekly-issues-data/issues.json\n\n  # Generate schema for reference\n  /tmp/gh-aw/jqschema.sh < /tmp/gh-aw/weekly-issues-data/issues.json > /tmp/gh-aw/weekly-issues-data/issues-schema.json\n\n  # Store in cache with today's date\n  cp /tmp/gh-aw/weekly-issues-data/issues.json \"$CACHE_DIR/weekly-issues-${TODAY}.json\"\n  cp /tmp/gh-aw/weekly-issues-data/issues-schema.json \"$CACHE_DIR/weekly-issues-${TODAY}-schema.json\"\n\n  echo \"✓ Weekly issues data saved to cache: weekly-issues-${TODAY}.json\"\n  echo \"Total issues found: $(jq 'length' /tmp/gh-aw/weekly-issues-data/issues.json)\"\nfi\n\n# Always ensure data is available at expected locations for backward compatibility\necho \"Weekly issues data available at: /tmp/gh-aw/weekly-issues-data/issues.json\"\necho \"Schema available at: /tmp/gh-aw/weekly-issues-data/issues-schema.json\""
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/dev-hawk.lock.yml b/.github/workflows/dev-hawk.lock.yml
index 2ec4a572759..129f4f0bfaa 100644
--- a/.github/workflows/dev-hawk.lock.yml
+++ b/.github/workflows/dev-hawk.lock.yml
@@ -123,7 +123,7 @@ jobs:
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/go-logger.lock.yml b/.github/workflows/go-logger.lock.yml
index cb6822cd018..5d5bcfe33d0 100644
--- a/.github/workflows/go-logger.lock.yml
+++ b/.github/workflows/go-logger.lock.yml
@@ -116,7 +116,7 @@ jobs:
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/hourly-ci-cleaner.lock.yml b/.github/workflows/hourly-ci-cleaner.lock.yml
index 776490b07e5..1dc345f9218 100644
--- a/.github/workflows/hourly-ci-cleaner.lock.yml
+++ b/.github/workflows/hourly-ci-cleaner.lock.yml
@@ -128,7 +128,7 @@ jobs:
           sudo apt-get update
           sudo apt-get install -y make
       - name: Setup Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/portfolio-analyst.lock.yml b/.github/workflows/portfolio-analyst.lock.yml
index c6ee1e01791..58128114049 100644
--- a/.github/workflows/portfolio-analyst.lock.yml
+++ b/.github/workflows/portfolio-analyst.lock.yml
@@ -118,7 +118,7 @@ jobs:
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/prompt-clustering-analysis.lock.yml b/.github/workflows/prompt-clustering-analysis.lock.yml
index 6f8f4b1c922..fdbc22a0e67 100644
--- a/.github/workflows/prompt-clustering-analysis.lock.yml
+++ b/.github/workflows/prompt-clustering-analysis.lock.yml
@@ -123,7 +123,7 @@ jobs:
       - name: Set up jq utilities directory
         run: "mkdir -p /tmp/gh-aw\ncat > /tmp/gh-aw/jqschema.sh << 'EOF'\n#!/usr/bin/env bash\n# jqschema.sh\njq -c '\ndef walk(f):\n  . as $in |\n  if type == \"object\" then\n    reduce keys[] as $k ({}; . + {($k): ($in[$k] | walk(f))})\n  elif type == \"array\" then\n    if length == 0 then [] else [.[0] | walk(f)] end\n  else\n    type\n  end;\nwalk(.)\n'\nEOF\nchmod +x /tmp/gh-aw/jqschema.sh"
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/release.lock.yml b/.github/workflows/release.lock.yml
index ce8d4a55d9c..b66b59cb120 100644
--- a/.github/workflows/release.lock.yml
+++ b/.github/workflows/release.lock.yml
@@ -1225,7 +1225,7 @@ jobs:
       - name: Checkout repository
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: false
           go-version-file: go.mod
diff --git a/.github/workflows/safe-output-health.lock.yml b/.github/workflows/safe-output-health.lock.yml
index 120464489f0..df7a8c5f86c 100644
--- a/.github/workflows/safe-output-health.lock.yml
+++ b/.github/workflows/safe-output-health.lock.yml
@@ -117,7 +117,7 @@ jobs:
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/static-analysis-report.lock.yml b/.github/workflows/static-analysis-report.lock.yml
index 99bd6115f91..9deb84b0871 100644
--- a/.github/workflows/static-analysis-report.lock.yml
+++ b/.github/workflows/static-analysis-report.lock.yml
@@ -116,7 +116,7 @@ jobs:
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml
index 27d69710830..5d7ef7ddf8f 100644
--- a/.github/workflows/tidy.lock.yml
+++ b/.github/workflows/tidy.lock.yml
@@ -149,7 +149,7 @@ jobs:
           cache-dependency-path: actions/setup/js/package-lock.json
           node-version: "24"
       - name: Set up Go
-        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
         with:
           cache: true
           go-version-file: go.mod
diff --git a/actions/setup/sh/convert_gateway_config_copilot.sh b/actions/setup/sh/convert_gateway_config_copilot.sh
index d3721ba55d0..73c7ca9244c 100755
--- a/actions/setup/sh/convert_gateway_config_copilot.sh
+++ b/actions/setup/sh/convert_gateway_config_copilot.sh
@@ -26,7 +26,7 @@ echo "Input: $MCP_GATEWAY_OUTPUT"
 # {
 #   "mcpServers": {
 #     "server-name": {
-#       "type": "http",
+#       "type": "http" or "stdio",
 #       "url": "http://domain:port/mcp/server-name",
 #       "headers": {
 #         "Authorization": "apiKey"
@@ -39,7 +39,7 @@ echo "Input: $MCP_GATEWAY_OUTPUT"
 # {
 #   "mcpServers": {
 #     "server-name": {
-#       "type": "http",
+#       "type": "http" or "local",
 #       "url": "http://domain:port/mcp/server-name",
 #       "headers": {
 #         "Authorization": "apiKey"
@@ -49,12 +49,17 @@ echo "Input: $MCP_GATEWAY_OUTPUT"
 #   }
 # }
 #
-# The main difference is that Copilot requires the "tools" field.
-# We also need to ensure headers use the actual API key value, not a placeholder.
+# The main differences for Copilot:
+# 1. Copilot requires the "tools" field
+# 2. Copilot uses "local" instead of "stdio" for containerized servers
+# 3. HTTP servers keep "type": "http" and don't need conversion
 
 jq '
   .mcpServers |= with_entries(
     .value |= (
+      # Convert stdio to local for Copilot compatibility
+      if .type == "stdio" then .type = "local" else . end |
+      # Add tools field if not present
       if .tools then . else . + {"tools": ["*"]} end
     )
   )
diff --git a/pkg/workflow/runtime_detection.go b/pkg/workflow/runtime_detection.go
index b4384d4ad12..e290fa80ac2 100644
--- a/pkg/workflow/runtime_detection.go
+++ b/pkg/workflow/runtime_detection.go
@@ -223,14 +223,14 @@ func mapSerenaLanguageToRuntime(serenaLang string) string {
 		"rust":       "rust",
 
 		// Alternative names or variants
-		"python_jedi":       "python",
-		"typescript_vts":    "node",
-		"ruby_solargraph":   "ruby",
-		"kotlin":            "java", // Kotlin runs on JVM
-		"scala":             "java", // Scala runs on JVM
-		"csharp":            "dotnet",
-		"csharp_omnisharp":  "dotnet",
-		"erlang":            "elixir", // Erlang uses same runtime setup
+		"python_jedi":      "python",
+		"typescript_vts":   "node",
+		"ruby_solargraph":  "ruby",
+		"kotlin":           "java", // Kotlin runs on JVM
+		"scala":            "java", // Scala runs on JVM
+		"csharp":           "dotnet",
+		"csharp_omnisharp": "dotnet",
+		"erlang":           "elixir", // Erlang uses same runtime setup
 
 		// Languages that don't need runtime setup (return empty string)
 		"bash":     "",

From ba137a94f6f643f8ae20f45f3a0bd6e12b45e631 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 13 Jan 2026 06:50:57 +0000
Subject: [PATCH 5/7] Merge main and recompile all workflows

- Merged main branch with conflict resolution
- Combined stdio-to-local conversion with URL rewriting in converter
- Recompiled all 119 workflows successfully

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
 .github/workflows/cloclo.lock.yml        | 65 +++++++++++++++++-------
 .github/workflows/mcp-inspector.lock.yml | 52 +++++++++++++++----
 .github/workflows/q.lock.yml             | 58 +++++++++++++++++----
 3 files changed, 134 insertions(+), 41 deletions(-)

diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml
index 5a31212caf4..687f69b9c03 100644
--- a/.github/workflows/cloclo.lock.yml
+++ b/.github/workflows/cloclo.lock.yml
@@ -181,13 +181,18 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
-      - name: Set up Go
-        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
-        with:
-          cache: true
-          go-version-file: go.mod
       - name: Install dependencies
         run: make deps-dev
       - env:
@@ -485,6 +490,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -559,20 +599,7 @@ jobs:
                 }
               },
               "serena": {
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": [
-                  "--network",
-                  "host"
-                ],
-                "entrypoint": "serena",
-                "entrypointArgs": [
-                  "start-mcp-server",
-                  "--context",
-                  "codex",
-                  "--project",
-                  "${{ github.workspace }}"
-                ],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "url": "http://localhost:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml
index b78d5ed5621..70b94395543 100644
--- a/.github/workflows/mcp-inspector.lock.yml
+++ b/.github/workflows/mcp-inspector.lock.yml
@@ -127,6 +127,10 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
       - name: Setup Node.js
         uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
         with:
@@ -140,11 +144,6 @@ jobs:
         uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
-      - name: Set up Go
-        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
-        with:
-          cache: true
-          go-version-file: go.mod
       - name: Install dependencies
         run: make deps-dev
       - env:
@@ -435,6 +434,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -726,12 +760,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               },
               "tavily": {
                 "type": "http",
diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml
index 420c2c52d2e..c00427aa87b 100644
--- a/.github/workflows/q.lock.yml
+++ b/.github/workflows/q.lock.yml
@@ -176,13 +176,18 @@ jobs:
         uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
         with:
           persist-credentials: false
+      - name: Setup Go
+        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
+        with:
+          go-version: '1.25'
+      - name: Setup Python
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+        with:
+          python-version: '3.12'
+      - name: Setup uv
+        uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
       - name: Create gh-aw temp directory
         run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh
-      - name: Set up Go
-        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
-        with:
-          cache: true
-          go-version-file: go.mod
       - name: Install dependencies
         run: make deps-dev
       - env:
@@ -482,6 +487,41 @@ jobs:
             }
           }
           EOF
+      - name: Start Serena MCP HTTP Server
+        id: serena-start
+        run: |
+          set -eo pipefail
+          mkdir -p /tmp/gh-aw/mcp-logs/serena
+          
+          echo "Starting Serena MCP HTTP server on port 9121..."
+          
+          # Start Serena MCP server in background with uvx
+          uvx --from git+https://github.com/oraios/serena \
+            serena start-mcp-server \
+            --transport streamable-http \
+            --port 9121 \
+            --project "${{ github.workspace }}" \
+            > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &
+          
+          # Save PID for potential cleanup
+          echo $! > /tmp/gh-aw/serena-mcp-server.pid
+          
+          # Wait for server to start (max 30 seconds)
+          echo "Waiting for Serena MCP server to start..."
+          for i in {1..30}; do
+            if curl -s http://localhost:9121/health > /dev/null 2>&1; then
+              echo "Serena MCP server is ready"
+              break
+            fi
+            if [ $i -eq 30 ]; then
+              echo "ERROR: Serena MCP server failed to start within 30 seconds"
+              echo "Server logs:"
+              cat /tmp/gh-aw/mcp-logs/serena/server.log || true
+              exit 1
+            fi
+            sleep 1
+          done
+          
       - name: Start MCP gateway
         id: start-mcp-gateway
         env:
@@ -545,12 +585,8 @@ jobs:
                 }
               },
               "serena": {
-                "type": "stdio",
-                "container": "ghcr.io/oraios/serena:latest",
-                "args": ["--network", "host"],
-                "entrypoint": "serena",
-                "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"],
-                "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"]
+                "type": "http",
+                "url": "http://localhost:9121"
               },
               "tavily": {
                 "type": "http",

From a332056e316331ccf736fe28bf3b274b66f6925c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 13 Jan 2026 07:00:55 +0000
Subject: [PATCH 6/7] Fix gateway converters to preserve direct HTTP server
 URLs

Updated all three MCP gateway converters (Copilot, Claude, Codex) to properly
handle direct HTTP servers like Serena:

- Copilot: Added clearer comments about URL rewriting logic
- Claude: Added comments clarifying gateway-proxied vs direct HTTP servers
- Codex: Fixed URL construction to preserve original URL for direct HTTP servers
  (previously always rewrote URLs to gateway format)

The regex pattern ^http://[^/]+/mcp/ only matches gateway-proxied URLs, so
Serena's http://localhost:9121 passes through unchanged. Codex converter now
uses conditional logic instead of always constructing gateway URLs.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
 actions/setup/sh/convert_gateway_config_claude.sh  |  4 +++-
 actions/setup/sh/convert_gateway_config_codex.sh   | 10 +++++++++-
 actions/setup/sh/convert_gateway_config_copilot.sh |  5 +++--
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/actions/setup/sh/convert_gateway_config_claude.sh b/actions/setup/sh/convert_gateway_config_claude.sh
index 639147cafe1..8ad92e3d935 100755
--- a/actions/setup/sh/convert_gateway_config_claude.sh
+++ b/actions/setup/sh/convert_gateway_config_claude.sh
@@ -74,7 +74,9 @@ jq --arg urlPrefix "$URL_PREFIX" '
     .value |= (
       (.type = "http") |
       (del(.tools)) |
-      # Fix the URL to use the correct domain
+      # Fix the URL to use the correct domain for gateway-proxied servers only
+      # URLs with /mcp/ prefix are gateway-proxied and need rewriting
+      # Direct HTTP servers (like Serena on localhost) should pass through unchanged
       .url |= (. | sub("^http://[^/]+/mcp/"; $urlPrefix + "/mcp/"))
     )
   )
diff --git a/actions/setup/sh/convert_gateway_config_codex.sh b/actions/setup/sh/convert_gateway_config_codex.sh
index 14c8107340a..833058e6b06 100755
--- a/actions/setup/sh/convert_gateway_config_codex.sh
+++ b/actions/setup/sh/convert_gateway_config_codex.sh
@@ -73,7 +73,15 @@ TOML_EOF
 jq -r --arg urlPrefix "$URL_PREFIX" '
   .mcpServers | to_entries[] |
   "[mcp_servers.\(.key)]\n" +
-  "url = \"" + ($urlPrefix + "/mcp/" + .key) + "\"\n" +
+  # Use original URL if it doesn'\''t contain /mcp/ (direct HTTP servers like Serena)
+  # Otherwise construct gateway URL
+  "url = \"" + (
+    if (.value.url | contains("/mcp/")) then
+      $urlPrefix + "/mcp/" + .key
+    else
+      .value.url
+    end
+  ) + "\"\n" +
   "http_headers = { Authorization = \"\(.value.headers.Authorization)\" }\n"
 ' "$MCP_GATEWAY_OUTPUT" >> /tmp/gh-aw/mcp-config/config.toml
 
diff --git a/actions/setup/sh/convert_gateway_config_copilot.sh b/actions/setup/sh/convert_gateway_config_copilot.sh
index bc8dd942285..b601581b19a 100755
--- a/actions/setup/sh/convert_gateway_config_copilot.sh
+++ b/actions/setup/sh/convert_gateway_config_copilot.sh
@@ -79,8 +79,9 @@ jq --arg urlPrefix "$URL_PREFIX" '
       (if .type == "stdio" then .type = "local" else . end) |
       # Add tools field if not present
       (if .tools then . else . + {"tools": ["*"]} end) |
-      # Fix the URL to use the correct domain
-      # Replace http://anything:port/mcp/ with http://domain:port/mcp/
+      # Fix the URL to use the correct domain for gateway-proxied servers only
+      # URLs with /mcp/ prefix are gateway-proxied and need rewriting
+      # Direct HTTP servers (like Serena on localhost) should pass through unchanged
       .url |= (. | sub("^http://[^/]+/mcp/"; $urlPrefix + "/mcp/"))
     )
   )

From dbab4959389e83e3a2891d6b3ba2d55552716a2d Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Tue, 13 Jan 2026 04:25:07 -0800
Subject: [PATCH 7/7] Fix Serena MCP server URL to use host.docker.internal
 (#9817)

---
 .github/workflows/archie.lock.yml                      |  2 +-
 .github/workflows/cloclo.lock.yml                      |  2 +-
 .github/workflows/daily-file-diet.lock.yml             |  2 +-
 .github/workflows/developer-docs-consolidator.lock.yml |  2 +-
 .github/workflows/duplicate-code-detector.lock.yml     |  4 ++--
 .github/workflows/glossary-maintainer.lock.yml         |  2 +-
 .github/workflows/go-fan.lock.yml                      |  2 +-
 .github/workflows/jsweep.lock.yml                      |  2 +-
 .github/workflows/mcp-inspector.lock.yml               |  2 +-
 .github/workflows/q.lock.yml                           |  2 +-
 .github/workflows/repository-quality-improver.lock.yml |  2 +-
 .github/workflows/smoke-claude.lock.yml                |  2 +-
 .github/workflows/smoke-codex.lock.yml                 |  4 ++--
 .github/workflows/smoke-copilot.lock.yml               |  2 +-
 .github/workflows/terminal-stylist.lock.yml            |  2 +-
 .github/workflows/typist.lock.yml                      |  2 +-
 pkg/workflow/importable_tools_test.go                  |  8 ++++----
 pkg/workflow/mcp-config.go                             |  6 ++++--
 pkg/workflow/mcp_config_comprehensive_test.go          | 10 +++++-----
 pkg/workflow/mcp_renderer.go                           |  5 +++--
 20 files changed, 34 insertions(+), 31 deletions(-)

diff --git a/.github/workflows/archie.lock.yml b/.github/workflows/archie.lock.yml
index 374c889b955..b88d79f9b10 100644
--- a/.github/workflows/archie.lock.yml
+++ b/.github/workflows/archie.lock.yml
@@ -472,7 +472,7 @@ jobs:
               },
               "serena": {
                 "type": "http",
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml
index 687f69b9c03..f6cafa6558e 100644
--- a/.github/workflows/cloclo.lock.yml
+++ b/.github/workflows/cloclo.lock.yml
@@ -599,7 +599,7 @@ jobs:
                 }
               },
               "serena": {
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/daily-file-diet.lock.yml b/.github/workflows/daily-file-diet.lock.yml
index 6c75554cdf0..c18e31c79e9 100644
--- a/.github/workflows/daily-file-diet.lock.yml
+++ b/.github/workflows/daily-file-diet.lock.yml
@@ -470,7 +470,7 @@ jobs:
               },
               "serena": {
                 "type": "http",
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml
index 53546f3604a..141cb77b520 100644
--- a/.github/workflows/developer-docs-consolidator.lock.yml
+++ b/.github/workflows/developer-docs-consolidator.lock.yml
@@ -513,7 +513,7 @@ jobs:
                 }
               },
               "serena": {
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/duplicate-code-detector.lock.yml b/.github/workflows/duplicate-code-detector.lock.yml
index 423edbc18f4..82a54e65942 100644
--- a/.github/workflows/duplicate-code-detector.lock.yml
+++ b/.github/workflows/duplicate-code-detector.lock.yml
@@ -445,7 +445,7 @@ jobs:
           env_vars = ["GH_AW_MCP_LOG_DIR", "GH_AW_SAFE_OUTPUTS", "GH_AW_SAFE_OUTPUTS_CONFIG_PATH", "GH_AW_SAFE_OUTPUTS_TOOLS_PATH", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "GITHUB_SHA", "GITHUB_WORKSPACE", "DEFAULT_BRANCH"]
           
           [mcp_servers.serena]
-          url = "http://localhost:9121"
+          url = "http://host.docker.internal:9121"
           EOF
           
           # Generate JSON config for MCP gateway
@@ -482,7 +482,7 @@ jobs:
                 }
               },
               "serena": {
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml
index 6e67d32bc2d..3f3cb4ccf62 100644
--- a/.github/workflows/glossary-maintainer.lock.yml
+++ b/.github/workflows/glossary-maintainer.lock.yml
@@ -469,7 +469,7 @@ jobs:
               },
               "serena": {
                 "type": "http",
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/go-fan.lock.yml b/.github/workflows/go-fan.lock.yml
index de8a398d2b5..81dd77f5212 100644
--- a/.github/workflows/go-fan.lock.yml
+++ b/.github/workflows/go-fan.lock.yml
@@ -449,7 +449,7 @@ jobs:
                 }
               },
               "serena": {
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/jsweep.lock.yml b/.github/workflows/jsweep.lock.yml
index b60db5a2cbd..ddc1c0fd58a 100644
--- a/.github/workflows/jsweep.lock.yml
+++ b/.github/workflows/jsweep.lock.yml
@@ -470,7 +470,7 @@ jobs:
               },
               "serena": {
                 "type": "http",
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml
index 70b94395543..59b8b854166 100644
--- a/.github/workflows/mcp-inspector.lock.yml
+++ b/.github/workflows/mcp-inspector.lock.yml
@@ -761,7 +761,7 @@ jobs:
               },
               "serena": {
                 "type": "http",
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               },
               "tavily": {
                 "type": "http",
diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml
index c00427aa87b..0e9138ff724 100644
--- a/.github/workflows/q.lock.yml
+++ b/.github/workflows/q.lock.yml
@@ -586,7 +586,7 @@ jobs:
               },
               "serena": {
                 "type": "http",
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               },
               "tavily": {
                 "type": "http",
diff --git a/.github/workflows/repository-quality-improver.lock.yml b/.github/workflows/repository-quality-improver.lock.yml
index 77b2f0073f1..e47b9daec25 100644
--- a/.github/workflows/repository-quality-improver.lock.yml
+++ b/.github/workflows/repository-quality-improver.lock.yml
@@ -460,7 +460,7 @@ jobs:
               },
               "serena": {
                 "type": "http",
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml
index b157c7c59a8..8fe18650ea5 100644
--- a/.github/workflows/smoke-claude.lock.yml
+++ b/.github/workflows/smoke-claude.lock.yml
@@ -698,7 +698,7 @@ jobs:
                 }
               },
               "serena": {
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               },
               "tavily": {
                 "type": "http",
diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml
index 6de1b324a25..a30243631fb 100644
--- a/.github/workflows/smoke-codex.lock.yml
+++ b/.github/workflows/smoke-codex.lock.yml
@@ -714,7 +714,7 @@ jobs:
           env_vars = ["GH_AW_MCP_LOG_DIR", "GH_AW_SAFE_OUTPUTS", "GH_AW_SAFE_OUTPUTS_CONFIG_PATH", "GH_AW_SAFE_OUTPUTS_TOOLS_PATH", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "GITHUB_SHA", "GITHUB_WORKSPACE", "DEFAULT_BRANCH"]
           
           [mcp_servers.serena]
-          url = "http://localhost:9121"
+          url = "http://host.docker.internal:9121"
           
           [mcp_servers.tavily]
           url = "https://mcp.tavily.com/mcp/"
@@ -779,7 +779,7 @@ jobs:
                 }
               },
               "serena": {
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               },
               "tavily": {
               "type": "http",
diff --git a/.github/workflows/smoke-copilot.lock.yml b/.github/workflows/smoke-copilot.lock.yml
index c53808edc37..0dd374c97ff 100644
--- a/.github/workflows/smoke-copilot.lock.yml
+++ b/.github/workflows/smoke-copilot.lock.yml
@@ -581,7 +581,7 @@ jobs:
               },
               "serena": {
                 "type": "http",
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/terminal-stylist.lock.yml b/.github/workflows/terminal-stylist.lock.yml
index 24022f4fcd0..db0ffb1230b 100644
--- a/.github/workflows/terminal-stylist.lock.yml
+++ b/.github/workflows/terminal-stylist.lock.yml
@@ -438,7 +438,7 @@ jobs:
               },
               "serena": {
                 "type": "http",
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/.github/workflows/typist.lock.yml b/.github/workflows/typist.lock.yml
index a9196d96bee..0b7b8a9c5a2 100644
--- a/.github/workflows/typist.lock.yml
+++ b/.github/workflows/typist.lock.yml
@@ -436,7 +436,7 @@ jobs:
                 }
               },
               "serena": {
-                "url": "http://localhost:9121"
+                "url": "http://host.docker.internal:9121"
               }
             },
             "gateway": {
diff --git a/pkg/workflow/importable_tools_test.go b/pkg/workflow/importable_tools_test.go
index c82ecd2eb89..932fe922f0a 100644
--- a/pkg/workflow/importable_tools_test.go
+++ b/pkg/workflow/importable_tools_test.go
@@ -160,8 +160,8 @@ Uses imported serena tool.
 	if !strings.Contains(workflowData, "uvx --from git+https://github.com/oraios/serena") {
 		t.Error("Expected compiled workflow to use uvx to start Serena")
 	}
-	if !strings.Contains(workflowData, "http://localhost:9121") {
-		t.Error("Expected compiled workflow to contain Serena HTTP URL")
+	if !strings.Contains(workflowData, "http://host.docker.internal:9121") {
+		t.Error("Expected compiled workflow to contain Serena HTTP URL with host.docker.internal")
 	}
 
 	// Verify that language service setup steps ARE present
@@ -324,8 +324,8 @@ Uses all imported tools.
 	if !strings.Contains(workflowData, "mcr.microsoft.com/playwright/mcp") {
 		t.Error("Expected compiled workflow to contain playwright Docker image")
 	}
-	if !strings.Contains(workflowData, "http://localhost:9121") {
-		t.Error("Expected compiled workflow to contain Serena HTTP URL")
+	if !strings.Contains(workflowData, "http://host.docker.internal:9121") {
+		t.Error("Expected compiled workflow to contain Serena HTTP URL with host.docker.internal")
 	}
 	if !strings.Contains(workflowData, "example.com") {
 		t.Error("Expected compiled workflow to contain example.com domain for playwright")
diff --git a/pkg/workflow/mcp-config.go b/pkg/workflow/mcp-config.go
index 792826b06ad..cf81b5c8d8e 100644
--- a/pkg/workflow/mcp-config.go
+++ b/pkg/workflow/mcp-config.go
@@ -147,7 +147,8 @@ func renderPlaywrightMCPConfigWithOptions(yaml *strings.Builder, playwrightTool
 
 // renderSerenaMCPConfigWithOptions generates the Serena MCP server configuration with engine-specific options
 // Serena now runs using uvx with HTTP transport in the agent job (not containerized)
-// The HTTP server is started in a background step and accessed via http://localhost:9121
+// The HTTP server is started in a background step and accessed via http://host.docker.internal:9121
+// Note: host.docker.internal is used because the MCP gateway runs in a container and needs to reach the host
 func renderSerenaMCPConfigWithOptions(yaml *strings.Builder, serenaTool any, isLast bool, includeCopilotFields bool, inlineArgs bool) {
 	yaml.WriteString("              \"serena\": {\n")
 
@@ -157,7 +158,8 @@ func renderSerenaMCPConfigWithOptions(yaml *strings.Builder, serenaTool any, isL
 	}
 
 	// HTTP URL for Serena MCP server running on host
-	yaml.WriteString("                \"url\": \"http://localhost:9121\"\n")
+	// Use host.docker.internal so the gateway container can reach the host
+	yaml.WriteString("                \"url\": \"http://host.docker.internal:9121\"\n")
 
 	// Note: tools field is NOT included here - the converter script adds it back
 	// for Copilot. This keeps the gateway config compatible with the schema.
diff --git a/pkg/workflow/mcp_config_comprehensive_test.go b/pkg/workflow/mcp_config_comprehensive_test.go
index e896758fb5d..4dba3060fd0 100644
--- a/pkg/workflow/mcp_config_comprehensive_test.go
+++ b/pkg/workflow/mcp_config_comprehensive_test.go
@@ -574,7 +574,7 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) {
 			inlineArgs:           false,
 			expectedContent: []string{
 				`"serena": {`,
-				`"url": "http://localhost:9121"`,
+				`"url": "http://host.docker.internal:9121"`,
 				`              },`,
 			},
 			unexpectedContent: []string{
@@ -593,7 +593,7 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) {
 			inlineArgs:           false,
 			expectedContent: []string{
 				`"serena": {`,
-				`"url": "http://localhost:9121"`,
+				`"url": "http://host.docker.internal:9121"`,
 				`              }`,
 			},
 			unexpectedContent: []string{
@@ -612,7 +612,7 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) {
 			expectedContent: []string{
 				`"serena": {`,
 				`"type": "http"`,
-				`"url": "http://localhost:9121"`,
+				`"url": "http://host.docker.internal:9121"`,
 			},
 			unexpectedContent: []string{
 				`"container"`,
@@ -627,7 +627,7 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) {
 			expectedContent: []string{
 				`"serena": {`,
 				`"type": "http"`,
-				`"url": "http://localhost:9121"`,
+				`"url": "http://host.docker.internal:9121"`,
 			},
 			unexpectedContent: []string{
 				`"container"`,
@@ -644,7 +644,7 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) {
 			inlineArgs:           false,
 			expectedContent: []string{
 				`"serena": {`,
-				`"url": "http://localhost:9121"`,
+				`"url": "http://host.docker.internal:9121"`,
 			},
 			unexpectedContent: []string{
 				`"container"`,
diff --git a/pkg/workflow/mcp_renderer.go b/pkg/workflow/mcp_renderer.go
index 2cce44fb0e0..d3d6663654a 100644
--- a/pkg/workflow/mcp_renderer.go
+++ b/pkg/workflow/mcp_renderer.go
@@ -186,11 +186,12 @@ func (r *MCPConfigRendererUnified) RenderSerenaMCP(yaml *strings.Builder, serena
 
 // renderSerenaTOML generates Serena MCP configuration in TOML format
 // Serena now runs using uvx with HTTP transport in the agent job (not containerized)
-// The HTTP server is started in a background step and accessed via http://localhost:9121
+// The HTTP server is started in a background step and accessed via http://host.docker.internal:9121
+// Note: host.docker.internal is used because the MCP gateway runs in a container and needs to reach the host
 func (r *MCPConfigRendererUnified) renderSerenaTOML(yaml *strings.Builder, serenaTool any) {
 	yaml.WriteString("          \n")
 	yaml.WriteString("          [mcp_servers.serena]\n")
-	yaml.WriteString("          url = \"http://localhost:9121\"\n")
+	yaml.WriteString("          url = \"http://host.docker.internal:9121\"\n")
 }
 
 // RenderSafeOutputsMCP generates the Safe Outputs MCP server configuration
