Skip to content

Commit e36ea33

Browse files
committed
Add transport type selector to inspector UI and comprehensive transport testing
- Add transport type dropdown to inspector UI (auto, HTTP, SSE) with session storage persistence - Update test framework to support transport type selection in test scenarios - Add comprehensive test cases covering: * Working /mcp endpoints with auto and HTTP transports * SSE endpoint with SSE transport (expected to pass) * SSE endpoint with auto transport (expected to fail - demonstrates current fallback issue) - Test structure now provides clear visibility into transport-specific behavior - All tests properly named and categorized for easy identification of failing scenarios
1 parent b2e7a0d commit e36ea33

File tree

2 files changed

+96
-27
lines changed

2 files changed

+96
-27
lines changed

examples/inspector/src/components/McpServers.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,22 @@ import { useMcp, type Tool } from 'use-mcp/react'
33
import { Info, X, ChevronRight, ChevronDown } from 'lucide-react'
44

55
// MCP Connection wrapper that only renders when active
6-
function McpConnection({ serverUrl, onConnectionUpdate }: { serverUrl: string; onConnectionUpdate: (data: any) => void }) {
6+
function McpConnection({
7+
serverUrl,
8+
transportType,
9+
onConnectionUpdate,
10+
}: {
11+
serverUrl: string
12+
transportType: 'auto' | 'http' | 'sse'
13+
onConnectionUpdate: (data: any) => void
14+
}) {
715
// Use the MCP hook with the server URL
816
const connection = useMcp({
917
url: serverUrl,
1018
debug: true,
1119
autoRetry: false,
1220
popupFeatures: 'width=500,height=600,resizable=yes,scrollbars=yes',
13-
transportType: 'auto',
21+
transportType,
1422
})
1523

1624
// Update parent component with connection data
@@ -26,6 +34,9 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[])
2634
const [serverUrl, setServerUrl] = useState(() => {
2735
return sessionStorage.getItem('mcpServerUrl') || ''
2836
})
37+
const [transportType, setTransportType] = useState<'auto' | 'http' | 'sse'>(() => {
38+
return (sessionStorage.getItem('mcpTransportType') as 'auto' | 'http' | 'sse') || 'auto'
39+
})
2940
const [isActive, setIsActive] = useState(false)
3041

3142
const [connectionData, setConnectionData] = useState<any>({
@@ -293,6 +304,20 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[])
293304
}}
294305
disabled={isActive && state !== 'failed'}
295306
/>
307+
<select
308+
className="p-2 border border-gray-200 rounded text-sm focus:outline-none focus:ring-1 focus:ring-blue-300"
309+
value={transportType}
310+
onChange={(e) => {
311+
const newValue = e.target.value as 'auto' | 'http' | 'sse'
312+
setTransportType(newValue)
313+
sessionStorage.setItem('mcpTransportType', newValue)
314+
}}
315+
disabled={isActive && state !== 'failed'}
316+
>
317+
<option value="auto">Auto</option>
318+
<option value="http">HTTP</option>
319+
<option value="sse">SSE</option>
320+
</select>
296321

297322
{state === 'ready' || (isActive && state !== 'not-connected' && state !== 'failed') ? (
298323
<button
@@ -477,7 +502,7 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[])
477502
</div>
478503

479504
{/* Only render the actual MCP connection when active */}
480-
{isActive && <McpConnection serverUrl={serverUrl} onConnectionUpdate={setConnectionData} />}
505+
{isActive && <McpConnection serverUrl={serverUrl} transportType={transportType} onConnectionUpdate={setConnectionData} />}
481506
</section>
482507
)
483508
}

test/integration/mcp-connection.test.ts

Lines changed: 68 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ function getMCPServers() {
4444
}
4545
}
4646

47-
async function connectToMCPServer(page: Page, serverUrl: string): Promise<{ success: boolean; tools: string[]; debugLog: string }> {
47+
async function connectToMCPServer(
48+
page: Page,
49+
serverUrl: string,
50+
transportType: 'auto' | 'http' | 'sse' = 'auto',
51+
): Promise<{ success: boolean; tools: string[]; debugLog: string }> {
4852
// Navigate to the inspector
4953
const stateData = readFileSync(testStateFile, 'utf-8')
5054
const state = JSON.parse(stateData)
@@ -63,6 +67,10 @@ async function connectToMCPServer(page: Page, serverUrl: string): Promise<{ succ
6367
const urlInput = page.locator('input[placeholder="Enter MCP server URL"]')
6468
await urlInput.fill(serverUrl)
6569

70+
// Set transport type
71+
const transportSelect = page.locator('select')
72+
await transportSelect.selectOption(transportType)
73+
6674
// Click connect button
6775
const connectButton = page.locator('button:has-text("Connect")')
6876
await connectButton.click()
@@ -207,34 +215,70 @@ describe('MCP Connection Integration Tests', () => {
207215
}
208216
})
209217

210-
test('should connect to all MCP servers and retrieve tools', async () => {
211-
const servers = getMCPServers()
218+
const testScenarios = [
219+
// Working examples with auto transport (should pass)
220+
{ serverName: 'hono-mcp', transportType: 'auto' as const, shouldPass: true },
221+
{ serverName: 'cf-agents', transportType: 'auto' as const, shouldPass: true },
222+
223+
// SSE endpoint with SSE transport (should pass)
224+
{ serverName: 'cf-agents-sse', transportType: 'sse' as const, shouldPass: true },
212225

213-
for (const server of servers) {
214-
console.log(`\n🔗 Testing connection to ${server.name} at ${server.url}`)
226+
// Additional test cases for HTTP transport
227+
{ serverName: 'hono-mcp', transportType: 'http' as const, shouldPass: true },
228+
{ serverName: 'cf-agents', transportType: 'http' as const, shouldPass: true },
215229

216-
const result = await connectToMCPServer(page, server.url)
230+
// Failing case: SSE endpoint with auto transport (should fail)
231+
{ serverName: 'cf-agents-sse', transportType: 'auto' as const, shouldPass: false },
232+
]
217233

218-
if (result.success) {
219-
console.log(`✅ Successfully connected to ${server.name}`)
220-
console.log(`📋 Available tools (${result.tools.length}):`)
221-
result.tools.forEach((tool, index) => {
222-
console.log(` ${index + 1}. ${tool}`)
223-
})
234+
test.each(testScenarios)(
235+
'should connect to $serverName with $transportType transport (expect: $shouldPass)',
236+
async ({ serverName, transportType, shouldPass }) => {
237+
const servers = getMCPServers()
238+
const server = servers.find((s) => s.name === serverName)
224239

225-
// Verify connection success
226-
expect(result.success).toBe(true)
227-
expect(result.tools.length).toBeGreaterThanOrEqual(server.expectedTools)
240+
if (!server) {
241+
throw new Error(`Server ${serverName} not found. Available servers: ${servers.map((s) => s.name).join(', ')}`)
242+
}
243+
244+
console.log(`\n🔗 Testing connection to ${server.name} at ${server.url} with ${transportType} transport`)
245+
246+
const result = await connectToMCPServer(page, server.url, transportType)
247+
248+
if (shouldPass) {
249+
if (result.success) {
250+
console.log(`✅ Successfully connected to ${server.name}`)
251+
console.log(`📋 Available tools (${result.tools.length}):`)
252+
result.tools.forEach((tool, index) => {
253+
console.log(` ${index + 1}. ${tool}`)
254+
})
255+
256+
// Verify connection success
257+
expect(result.success).toBe(true)
258+
expect(result.tools.length).toBeGreaterThanOrEqual(server.expectedTools)
259+
} else {
260+
console.log(`❌ Failed to connect to ${server.name}`)
261+
if (result.debugLog) {
262+
console.log(`🐛 Debug log:`)
263+
console.log(result.debugLog)
264+
}
265+
266+
// Fail the test with detailed information
267+
throw new Error(`Expected to connect to ${server.name} with ${transportType} transport but failed. Debug log: ${result.debugLog}`)
268+
}
228269
} else {
229-
console.log(`❌ Failed to connect to ${server.name}`)
230-
if (result.debugLog) {
231-
console.log(`🐛 Debug log:`)
232-
console.log(result.debugLog)
270+
// Expect failure
271+
if (result.success) {
272+
console.log(`❌ Unexpectedly connected to ${server.name}`)
273+
throw new Error(`Expected connection to ${server.name} with ${transportType} transport to fail, but it succeeded`)
274+
} else {
275+
console.log(`✅ Connection to ${server.name} failed as expected`)
276+
console.log(`🐛 Debug log: ${result.debugLog}`)
277+
// Verify it's actually a failure
278+
expect(result.success).toBe(false)
233279
}
234-
235-
// Fail the test with detailed information
236-
throw new Error(`Failed to connect to ${server.name}. Debug log: ${result.debugLog}`)
237280
}
238-
}
239-
}, 45000)
281+
},
282+
45000,
283+
)
240284
})

0 commit comments

Comments
 (0)