From 5d38b45008a1a1db281ab0d43d364df64399b0b1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 21 Mar 2026 00:44:37 +0000
Subject: [PATCH 1/3] chore: start implementing session expiry removal from
 safe output mcp server

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/6253a4d6-5bdc-4886-8c02-12f7da3cc06d
---
 .github/workflows/smoke-codex.lock.yml | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml
index 72012049156..2b9da5373fb 100644
--- a/.github/workflows/smoke-codex.lock.yml
+++ b/.github/workflows/smoke-codex.lock.yml
@@ -455,13 +455,20 @@ jobs:
               {
                 "description": "Add the 'smoked' label to the current pull request (can only be called once)",
                 "inputSchema": {
-                  "additionalProperties": true,
+                  "additionalProperties": false,
                   "properties": {
-                    "payload": {
-                      "description": "JSON-encoded payload to pass to the action",
+                    "labels": {
+                      "description": "The labels' name to be added. Must be separated with line breaks if there're multiple labels.",
+                      "type": "string"
+                    },
+                    "number": {
+                      "description": "The number of the issue or pull request.",
                       "type": "string"
                     }
                   },
+                  "required": [
+                    "labels"
+                  ],
                   "type": "object"
                 },
                 "name": "add_smoked_label"
@@ -1566,7 +1573,8 @@ jobs:
         env:
           GITHUB_TOKEN: ${{ github.token }}
         with:
-          payload: ${{ steps.process_safe_outputs.outputs.action_add_smoked_label_payload }}
+          labels: ${{ fromJSON(steps.process_safe_outputs.outputs.action_add_smoked_label_payload).labels }}
+          number: ${{ fromJSON(steps.process_safe_outputs.outputs.action_add_smoked_label_payload).number }}
       - name: Upload safe output items
         if: always()
         uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0

From 3893cf9a75a35b1679e2d067663a97a7c33dd27f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 21 Mar 2026 00:49:14 +0000
Subject: [PATCH 2/3] feat: remove session expiry from safe output MCP server

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/6253a4d6-5bdc-4886-8c02-12f7da3cc06d
---
 actions/setup/js/safe-outputs-mcp-server.cjs  |  8 ++-----
 .../setup/js/safe_outputs_mcp_server_http.cjs | 22 +++++++------------
 2 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/actions/setup/js/safe-outputs-mcp-server.cjs b/actions/setup/js/safe-outputs-mcp-server.cjs
index 73e41bf1c96..7602bf77326 100644
--- a/actions/setup/js/safe-outputs-mcp-server.cjs
+++ b/actions/setup/js/safe-outputs-mcp-server.cjs
@@ -19,16 +19,12 @@ const { startHttpServer } = require("./safe_outputs_mcp_server_http.cjs");
 
 logger.debug("Successfully required safe_outputs_mcp_server_http.cjs");
 
-// Start the HTTP server
+// If run directly, start the HTTP server
 // The server reads configuration from ${RUNNER_TEMP}/gh-aw/safeoutputs/config.json
 // Port and API key are configured via environment variables:
 // - GH_AW_SAFE_OUTPUTS_PORT
 // - GH_AW_SAFE_OUTPUTS_API_KEY
 // Log directory is configured via GH_AW_MCP_LOG_DIR environment variable
-//
-// NOTE: The server runs in stateless mode (no session management) because
-// the MCP gateway doesn't perform the MCP protocol initialization handshake.
-// It directly calls methods like tools/list without the Mcp-Session-Id header.
 if (require.main === module) {
   logger.debug("In require.main === module block");
   const port = parseInt(process.env.GH_AW_SAFE_OUTPUTS_PORT || "3001", 10);
@@ -36,7 +32,7 @@ if (require.main === module) {
   logger.debug(`Port: ${port}, LogDir: ${logDir}`);
   logger.debug("Calling startHttpServer...");
 
-  startHttpServer({ port, logDir, stateless: true }).catch(error => {
+  startHttpServer({ port, logDir }).catch(error => {
     logger.debugError("Failed to start safe-outputs HTTP server: ", error);
     process.exit(1);
   });
diff --git a/actions/setup/js/safe_outputs_mcp_server_http.cjs b/actions/setup/js/safe_outputs_mcp_server_http.cjs
index 2d04b0bd382..fa18349cdee 100644
--- a/actions/setup/js/safe_outputs_mcp_server_http.cjs
+++ b/actions/setup/js/safe_outputs_mcp_server_http.cjs
@@ -19,21 +19,20 @@ moduleLogger.debug("Module is being loaded");
  * This module extends the safe-outputs MCP server to support HTTP transport
  * using the StreamableHTTPServerTransport from the MCP SDK.
  *
- * It provides both stateful and stateless HTTP modes, as well as SSE streaming.
+ * The server runs in stateless mode (no session management) because the MCP
+ * gateway does not perform the MCP protocol initialization handshake and
+ * directly calls methods like tools/list without an Mcp-Session-Id header.
  *
  * Usage:
- *   node safe_outputs_mcp_server_http.cjs [--port 3000] [--stateless]
+ *   node safe_outputs_mcp_server_http.cjs [--port 3000]
  *
  * Options:
  *   --port <number>    Port to listen on (default: 3000)
- *   --stateless        Run in stateless mode (no session management)
  *   --log-dir <path>   Directory for log files
  */
 
 const http = require("http");
 moduleLogger.debug("Loaded http");
-const { randomUUID } = require("crypto");
-moduleLogger.debug("Loaded crypto");
 const { MCPServer, MCPHTTPTransport } = require("./mcp_http_transport.cjs");
 moduleLogger.debug("Loaded mcp_http_transport.cjs");
 const { createLogger: createMCPLogger } = require("./mcp_logger.cjs");
@@ -222,19 +221,17 @@ function createMCPServer(options = {}) {
  * Start the HTTP server with MCP protocol support
  * @param {Object} options - Server options
  * @param {number} [options.port] - Port to listen on (default: 3000)
- * @param {boolean} [options.stateless] - Run in stateless mode (default: false)
  * @param {string} [options.logDir] - Override log directory from config
  */
 async function startHttpServer(options = {}) {
   const port = options.port || 3000;
-  const stateless = options.stateless || false;
 
   const logger = createMCPLogger("safe-outputs-startup");
 
-  logger.debug(`startHttpServer called with port=${port}, stateless=${stateless}`);
+  logger.debug(`startHttpServer called with port=${port}`);
   logger.debug(`=== Starting Safe Outputs MCP HTTP Server ===`);
   logger.debug(`Port: ${port}`);
-  logger.debug(`Mode: ${stateless ? "stateless" : "stateful"}`);
+  logger.debug(`Mode: stateless`);
   logger.debug(`Environment: NODE_VERSION=${process.version}, PLATFORM=${process.platform}`);
 
   // Create the MCP server
@@ -251,9 +248,9 @@ async function startHttpServer(options = {}) {
     logger.debug(`Tools configured: ${Object.keys(config).filter(k => config[k]).length}`);
 
     logger.debug(`Creating HTTP transport...`);
-    // Create the HTTP transport
+    // Create the HTTP transport in stateless mode (no session management)
     const transport = new MCPHTTPTransport({
-      sessionIdGenerator: stateless ? undefined : () => randomUUID(),
+      sessionIdGenerator: undefined,
       enableJsonResponse: true,
       enableDnsRebindingProtection: false, // Disable for local development
     });
@@ -433,7 +430,6 @@ if (require.main === module) {
 
   const options = {
     port: 3000,
-    stateless: false,
     /** @type {string | undefined} */
     logDir: undefined,
   };
@@ -443,8 +439,6 @@ if (require.main === module) {
     if (args[i] === "--port" && args[i + 1]) {
       options.port = parseInt(args[i + 1], 10);
       i++;
-    } else if (args[i] === "--stateless") {
-      options.stateless = true;
     } else if (args[i] === "--log-dir" && args[i + 1]) {
       options.logDir = args[i + 1];
       i++;

From 2e70d4d6875143daed6827f6ac08873a84ab297e Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Sat, 21 Mar 2026 01:01:47 +0000
Subject: [PATCH 3/3] Add changeset [skip-ci]

---
 .changeset/patch-remove-safe-outputs-session-management.md | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 .changeset/patch-remove-safe-outputs-session-management.md

diff --git a/.changeset/patch-remove-safe-outputs-session-management.md b/.changeset/patch-remove-safe-outputs-session-management.md
new file mode 100644
index 00000000000..db6e487226a
--- /dev/null
+++ b/.changeset/patch-remove-safe-outputs-session-management.md
@@ -0,0 +1,5 @@
+---
+"gh-aw": patch
+---
+
+Remove session management from the safe outputs MCP HTTP server and make it stateless-only so MCP gateway `tools/list` works without requiring `Mcp-Session-Id` or `--stateless` workarounds.
