Skip to content

Commit b58c533

Browse files
yroblataskbot
andauthored
return the proxy mode in the server type for stdio (#1975)
* return the proxy mode in the server type for stdio when we run a server via stdio, we wrap it into a proxy, exposing via sse or streamable-http. So show this as the server type, instead of the stdio type Closes: #1717 * changes from review * fix ci --------- Co-authored-by: taskbot <[email protected]>
1 parent 7705e77 commit b58c533

File tree

8 files changed

+103
-7
lines changed

8 files changed

+103
-7
lines changed

cmd/thv/app/list.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func printMCPServersOutput(workloadList []core.Workload) error {
111111
// Add the MCP server to the map
112112
mcpServers[c.Name] = map[string]string{
113113
"url": c.URL,
114-
"type": c.TransportType.String(),
114+
"type": c.ProxyMode,
115115
}
116116
}
117117

docs/server/docs.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/server/swagger.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/server/swagger.yaml

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/core/workload.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ type Workload struct {
2727
ToolType string `json:"tool_type"`
2828
// TransportType is the type of transport used for this workload.
2929
TransportType types.TransportType `json:"transport_type"`
30-
// ProxyMode is the proxy mode for stdio transport (sse or streamable-http).
30+
// ProxyMode is the proxy mode that clients should use to connect.
31+
// For stdio transports, this will be the proxy mode (sse or streamable-http).
32+
// For direct transports (sse/streamable-http), this will be the same as TransportType.
3133
ProxyMode string `json:"proxy_mode,omitempty"`
3234
// Status is the current status of the workload.
3335
Status runtime.WorkloadStatus `json:"status"`

pkg/workloads/manager.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,9 @@ func (d *defaultManager) getRemoteWorkloadsFromState(
11541154
)
11551155
}
11561156

1157+
// Calculate the effective proxy mode that clients should use
1158+
effectiveProxyMode := types.GetEffectiveProxyMode(transportType, string(runConfig.ProxyMode))
1159+
11571160
// Create a workload from the run configuration
11581161
workload := core.Workload{
11591162
Name: name,
@@ -1162,7 +1165,7 @@ func (d *defaultManager) getRemoteWorkloadsFromState(
11621165
URL: proxyURL,
11631166
Port: runConfig.Port,
11641167
TransportType: transportType,
1165-
ProxyMode: string(runConfig.ProxyMode),
1168+
ProxyMode: effectiveProxyMode,
11661169
ToolType: "remote",
11671170
Group: runConfig.Group,
11681171
CreatedAt: workloadStatus.CreatedAt,
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package types
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
"github.com/stacklok/toolhive/pkg/transport/types"
9+
)
10+
11+
func TestGetEffectiveProxyMode(t *testing.T) {
12+
t.Parallel()
13+
14+
tests := []struct {
15+
name string
16+
transportType types.TransportType
17+
proxyMode string
18+
expectedProxyMode string
19+
}{
20+
{
21+
name: "stdio transport with sse proxy mode should return sse",
22+
transportType: types.TransportTypeStdio,
23+
proxyMode: "sse",
24+
expectedProxyMode: "sse",
25+
},
26+
{
27+
name: "stdio transport with streamable-http proxy mode should return streamable-http",
28+
transportType: types.TransportTypeStdio,
29+
proxyMode: "streamable-http",
30+
expectedProxyMode: "streamable-http",
31+
},
32+
{
33+
name: "stdio transport with empty proxy mode should return empty",
34+
transportType: types.TransportTypeStdio,
35+
proxyMode: "",
36+
expectedProxyMode: "",
37+
},
38+
{
39+
name: "sse transport should return sse",
40+
transportType: types.TransportTypeSSE,
41+
proxyMode: "",
42+
expectedProxyMode: "sse",
43+
},
44+
{
45+
name: "streamable-http transport should return streamable-http",
46+
transportType: types.TransportTypeStreamableHTTP,
47+
proxyMode: "",
48+
expectedProxyMode: "streamable-http",
49+
},
50+
{
51+
name: "sse transport ignores provided proxy mode",
52+
transportType: types.TransportTypeSSE,
53+
proxyMode: "some-value",
54+
expectedProxyMode: "sse",
55+
},
56+
{
57+
name: "stdio transport with invalid proxy mode should return the invalid mode",
58+
transportType: types.TransportTypeStdio,
59+
proxyMode: "invalid-mode",
60+
expectedProxyMode: "invalid-mode",
61+
},
62+
}
63+
64+
for _, tt := range tests {
65+
t.Run(tt.name, func(t *testing.T) {
66+
t.Parallel()
67+
68+
result := GetEffectiveProxyMode(tt.transportType, tt.proxyMode)
69+
assert.Equal(t, tt.expectedProxyMode, result, "Effective proxy mode should match expected")
70+
})
71+
}
72+
}

pkg/workloads/types/types.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,17 @@ func WorkloadFromContainerInfo(container *runtime.ContainerInfo) (core.Workload,
9595
return core.Workload{}, err
9696
}
9797

98+
// Calculate the effective proxy mode that clients should use
99+
effectiveProxyMode := GetEffectiveProxyMode(tType, runConfig.ProxyMode)
100+
98101
// Translate to the domain model.
99102
return core.Workload{
100103
Name: name, // Use the calculated workload name (base name), not container name
101104
Package: container.Image,
102105
URL: url,
103106
ToolType: toolType,
104107
TransportType: tType,
105-
ProxyMode: runConfig.ProxyMode,
108+
ProxyMode: effectiveProxyMode,
106109
Status: container.State,
107110
StatusContext: container.Status,
108111
CreatedAt: container.Created,
@@ -111,3 +114,16 @@ func WorkloadFromContainerInfo(container *runtime.ContainerInfo) (core.Workload,
111114
Group: runConfig.Group,
112115
}, nil
113116
}
117+
118+
// GetEffectiveProxyMode determines the effective proxy mode that clients should use
119+
// For stdio transports, this returns the proxy mode (sse or streamable-http)
120+
// For direct transports (sse/streamable-http), this returns the transport type as the proxy mode
121+
func GetEffectiveProxyMode(transportType types.TransportType, proxyMode string) string {
122+
// If the underlying transport is stdio, return the proxy mode (could be empty)
123+
if transportType == types.TransportTypeStdio {
124+
return proxyMode
125+
}
126+
127+
// For direct transports (sse, streamable-http), return the transport type as the proxy mode
128+
return transportType.String()
129+
}

0 commit comments

Comments
 (0)