Repository: mark3labs/mcp-go

Issue:
bug: v0.39.0 does not work at all
Hi, I have an MCP server that works fine through `stdio` and streamable HTTP in `v0.38.0`, then if I bump to `v0.39.0` it simply stops working in both transports, neither Claude Web nor Claude Desktop work with it, they can't even query the available tools, and no logs are printed anywhere (I guess for obvious reasons in the case of `stdio`).

Discussion:
@fatemehpourghaemi: Faced the same issue. Downgraded to v0.38.0.@matheuscscp: The last good commit is https://github.com/mark3labs/mcp-go/commit/4e353ac80e0e18a017988b43c3b1ffd3be1fb732

The first bad commit is https://github.com/mark3labs/mcp-go/commit/b9243915a8c31a0865d52a6df70c05bffe9ac170, from https://github.com/mark3labs/mcp-go/pull/571@alex210501: 👋 Hey

Really sorry for this, the issue is coming from the fact that you cannot return an empty `outputSchema`. I'm working on a fix and will post it here. 
@alex210501: By looking at the code, I believe that the same issue might also happen with an empty `inputSchema` so it might be interesting to keep this in view.@alex210501: There is [the fix](https://github.com/mark3labs/mcp-go/pull/573)@matheuscscp: The fix in `v0.39.1` works for me, thanks very much!!@alex210501: Thank you for the feedback @matheuscscp, and sorry again @ezynda3: Thanks @matheuscscp and @alex210501 for helping with this so quickly!

Solution patch:
diff --git a/mcp/tools.go b/mcp/tools.go
index 185aefa..493e8c7 100644
--- a/mcp/tools.go
+++ b/mcp/tools.go
@@ -607,7 +607,7 @@ func (t Tool) MarshalJSON() ([]byte, error) {
 			return nil, fmt.Errorf("tool %s has both OutputSchema and RawOutputSchema set: %w", t.Name, errToolSchemaConflict)
 		}
 		m["outputSchema"] = t.RawOutputSchema
-	} else {
+	} else if t.OutputSchema.Type != "" { // If no output schema is specified, do not return anything
 		m["outputSchema"] = t.OutputSchema
 	}
 



Test patch:
diff --git a/mcp/tools_test.go b/mcp/tools_test.go
index 270bf64..4bb07aa 100644
--- a/mcp/tools_test.go
+++ b/mcp/tools_test.go
@@ -586,27 +586,51 @@ func TestToolWithOutputSchema(t *testing.T) {
 		Email string `json:"email,omitempty" jsonschema_description:"Email address"`
 	}
 
-	tool := NewTool("test_tool",
-		WithDescription("Test tool with output schema"),
-		WithOutputSchema[TestOutput](),
-		WithString("input", Required()),
-	)
-
-	// Check that RawOutputSchema was set
-	assert.NotNil(t, tool.OutputSchema)
+	tests := []struct {
+		name                 string
+		tool                 Tool
+		expectedOutputSchema bool
+	}{
+		{
+			name: "default behavior",
+			tool: NewTool("test_tool",
+				WithDescription("Test tool with output schema"),
+				WithOutputSchema[TestOutput](),
+				WithString("input", Required()),
+			),
+			expectedOutputSchema: true,
+		},
+		{
+			name: "no output schema is set",
+			tool: NewTool("test_tool",
+				WithDescription("Test tool with no output schema"),
+				WithString("input", Required()),
+			),
+			expectedOutputSchema: false,
+		},
+	}
 
-	// Marshal and verify structure
-	data, err := json.Marshal(tool)
-	assert.NoError(t, err)
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			// Marshal and verify structure
+			data, err := json.Marshal(tt.tool)
+			assert.NoError(t, err)
 
-	var toolData map[string]any
-	err = json.Unmarshal(data, &toolData)
-	assert.NoError(t, err)
+			var toolData map[string]any
+			err = json.Unmarshal(data, &toolData)
+			assert.NoError(t, err)
 
-	// Verify outputSchema exists
-	outputSchema, exists := toolData["outputSchema"]
-	assert.True(t, exists)
-	assert.NotNil(t, outputSchema)
+			// Verify outputSchema exists
+			outputSchema, exists := toolData["outputSchema"]
+			if tt.expectedOutputSchema {
+				assert.True(t, exists)
+				assert.NotNil(t, outputSchema)
+			} else {
+				assert.False(t, exists)
+				assert.Nil(t, outputSchema)
+			}
+		})
+	}
 }
 
 // TestNewToolResultStructured tests that the NewToolResultStructured function