# Integrating MCP Servers with McpWorkbench for External Tool Access: A Complete Technical Guide

> Integrate MCP servers with McpWorkbench using AutoGen Studio for seamless external tool access. Explore the WebSocket protocol bridge for real-time communication and transport options.

- Repository: [Microsoft/autogen](https://github.com/microsoft/autogen)
- Tags: how-to-guide
- Published: 2026-03-07

---

**The MCP Workbench in AutoGen Studio provides a WebSocket-based protocol bridge that enables real-time bidirectional communication between the frontend UI and any MCP-compatible external tool server, supporting stdio, SSE, and streamable HTTP transports.**

The Microsoft AutoGen repository includes a powerful Model-Context Protocol (MCP) Workbench within AutoGen Studio that simplifies connecting to external tools. This guide explains how to leverage `McpWorkbench` to integrate MCP servers using a standardized WebSocket gateway architecture that handles protocol translation, session management, and user elicitation.

## Architecture Overview

The integration relies on three distinct architectural layers that manage transport, protocol translation, and business logic.

### Transport Layer

Located in [`autogenstudio/web/routes/mcp.py`](https://github.com/microsoft/autogen/blob/main/autogenstudio/web/routes/mcp.py), the `mcp_websocket` endpoint accepts WebSocket connections and decodes the `server_params` query string to instantiate the appropriate MCP client. The `create_mcp_session` helper function determines whether to use stdio, SSE, or streamable HTTP based on the decoded parameters.

### Protocol Bridge

The `MCPWebSocketBridge` class in [`autogenstudio/mcp/wsbridge.py`](https://github.com/microsoft/autogen/blob/main/autogenstudio/mcp/wsbridge.py) implements the `MCPEventHandler` interface. This bridge translates MCP events (initialization, operation results, errors, sampling requests) into JSON messages for the UI, and forwards UI-initiated operations back to the MCP client.

### Business Logic Layer

Callbacks for logging protocol messages, handling AI sampling, and managing user input requests reside in [`autogenstudio/mcp/callbacks.py`](https://github.com/microsoft/autogen/blob/main/autogenstudio/mcp/callbacks.py). Key functions include `create_message_handler`, `create_sampling_callback`, and `create_elicitation_callback`, which convert MCP protocol callbacks into UI-friendly activity logs.

## Core Components and File Paths

Understanding the source structure is essential for extending the integration or debugging connection issues.

- **[`autogenstudio/web/routes/mcp.py`](https://github.com/microsoft/autogen/blob/main/autogenstudio/web/routes/mcp.py)**: FastAPI router handling the WebSocket endpoint, session creation via `create_mcp_session`, and cleanup logic.

- **[`autogenstudio/mcp/wsbridge.py`](https://github.com/microsoft/autogen/blob/main/autogenstudio/mcp/wsbridge.py)**: Bridge class implementing protocol translation between MCP events and UI JSON messages.

- **[`autogenstudio/mcp/client.py`](https://github.com/microsoft/autogen/blob/main/autogenstudio/mcp/client.py)**: Wraps `mcp.ClientSession`, exposing `initialize` and `handle_operation` methods to process tool calls.

- **[`autogenstudio/mcp/callbacks.py`](https://github.com/microsoft/autogen/blob/main/autogenstudio/mcp/callbacks.py)**: Creates callbacks for logging, AI sampling, and user elicitation handling.

- **[`autogenstudio/mcp/utils.py`](https://github.com/microsoft/autogen/blob/main/autogenstudio/mcp/utils.py)**: Error extraction, JSON serialization helpers, and WebSocket disconnect detection utilities.

- **[`autogen_ext/tools/mcp/_config.py`](https://github.com/microsoft/autogen/blob/main/autogen_ext/tools/mcp/_config.py)**: Pydantic models for server parameters including `StdioServerParams`, `SseServerParams`, and `StreamableHttpServerParams`.

- **[`frontend/src/components/views/teambuilder/builder/component-editor/fields/workbench/useMcpWebSocket.ts`](https://github.com/microsoft/autogen/blob/main/frontend/src/components/views/teambuilder/builder/component-editor/fields/workbench/useMcpWebSocket.ts)**: React hook that builds the WebSocket URL and manages the connection state.

## Data Flow Walkthrough

The communication follows a strict sequence from UI initialization through tool execution and response handling.

1. **Connection Initiation**: The UI constructs a WebSocket URL in the format `ws://<host>/mcp/ws/<session_id>?server_params=<base64-json>`, where `server_params` encodes the server configuration type and connection details.

2. **Session Creation**: The `mcp_websocket` handler decodes the base64 parameters and invokes `create_mcp_session` to instantiate the appropriate MCP client (stdio, SSE, or HTTP).

3. **Bridge Registration**: The `MCPWebSocketBridge` registers the client via `set_mcp_client` and calls `mcp_client.initialize()`, relaying the `initialized` event to the UI.

4. **Operation Execution**: The UI sends JSON messages with `"type": "operation"` (e.g., `list_tools`, `call_tool`), which the bridge forwards to `MCPClient.handle_operation` for processing by the underlying MCP library.

5. **Response Handling**: Results, errors, and sampling requests flow back through bridge callbacks (`on_operation_result`, `on_sampling`, etc.) as typed JSON messages.

6. **Elicitation Management**: When tools require user input, the bridge stores an `asyncio.Future` in `pending_elicitations` keyed by a UUID. The UI receives an `elicitation_request`, and when the user responds, the bridge resolves the future to continue the MCP operation.

## Implementation Examples

### Frontend WebSocket Connection

The React hook in [`useMcpWebSocket.ts`](https://github.com/microsoft/autogen/blob/main/useMcpWebSocket.ts) demonstrates how to construct the connection URL and manage the WebSocket lifecycle.

```typescript
import { v4 as uuidv4 } from "uuid";

function buildMcpWsUrl(
  host: string,
  sessionId: string,
  serverParams: StdioServerParams | SseServerParams | StreamableHttpServerParams
) {
  const json = JSON.stringify(serverParams);
  const b64 = btoa(json);
  return `ws://${host}/mcp/ws/${sessionId}?server_params=${b64}`;
}

// Example: Connect to a local stdio-based tool server
const url = buildMcpWsUrl(
  "localhost:8081",
  uuidv4(),
  {
    type: "StdioServerParams",
    command: "python",
    args: ["-m", "my_tool_server"],
    env: { OPENAI_API_KEY: "*****" }
  }
);

const ws = new WebSocket(url);
ws.onmessage = ev => console.log("MCP message:", JSON.parse(ev.data));

```

### Programmatic Python Access

You can bypass the UI entirely by connecting directly to the WebSocket endpoint using Python.

```python
import asyncio
import json
import base64
import uuid
from websockets import connect

async def main():
    # Build base64-encoded params matching the UI format

    params = {
        "type": "StdioServerParams",
        "command": "python",
        "args": ["-m", "my_tool_server"],
        "env": {}
    }
    server_params = base64.b64encode(json.dumps(params).encode()).decode()
    
    ws_url = f"ws://localhost:8081/mcp/ws/{uuid.uuid4()}?server_params={server_params}"
    
    async with connect(ws_url) as ws:
        # Wait for initialization confirmation

        init_msg = json.loads(await ws.recv())
        print("Init:", init_msg)
        
        # List available tools

        await ws.send(json.dumps({
            "type": "operation", 
            "operation": "list_tools"
        }))
        tools = json.loads(await ws.recv())
        print("Tools:", tools)
        
        # Call a specific tool

        await ws.send(json.dumps({
            "type": "operation",
            "operation": "call_tool",
            "tool_name": "my_tool",
            "arguments": {"text": "hello"}
        }))
        result = json.loads(await ws.recv())
        print("Result:", result)

asyncio.run(main())

```

### Extending with Custom Operations

To add new operation types, extend the `handle_operation` method in [`autogenstudio/mcp/client.py`](https://github.com/microsoft/autogen/blob/main/autogenstudio/mcp/client.py).

```python

# In autogenstudio/mcp/client.py

elif operation_type == "custom_foo":
    payload = operation.get("payload", {})
    result = await self.session.custom_foo(payload)
    await self.event_handler.on_operation_result(
        "custom_foo", 
        {"payload": payload, "result": result}
    )

```

The UI can then invoke this custom operation by sending:

```json
{
  "type": "operation",
  "operation": "custom_foo",
  "payload": { "key": "value" }
}

```

## Configuration and Server Types

The integration supports three transport mechanisms defined in [`autogen_ext/tools/mcp/_config.py`](https://github.com/microsoft/autogen/blob/main/autogen_ext/tools/mcp/_config.py):

- **StdioServerParams**: For local subprocess-based tools requiring command and arguments
- **SseServerParams**: For Server-Sent Events HTTP connections
- **StreamableHttpServerParams**: For modern streamable HTTP-based MCP servers

Each model validates the specific parameters required for its transport type, ensuring type-safe configuration when building the WebSocket URL.

## Summary

- The MCP Workbench provides a WebSocket gateway that bridges AutoGen Studio's UI with external MCP-compatible tool servers.
- Key architectural components include the FastAPI router ([`mcp.py`](https://github.com/microsoft/autogen/blob/main/mcp.py)), protocol bridge ([`wsbridge.py`](https://github.com/microsoft/autogen/blob/main/wsbridge.py)), and client wrapper ([`client.py`](https://github.com/microsoft/autogen/blob/main/client.py)).
- The system supports stdio, SSE, and streamable HTTP transports through Pydantic configuration models.
- Data flows through initialization, operation execution, and response handling with support for user elicitation and AI sampling.
- Both frontend TypeScript and backend Python can interact with the Workbench using the same WebSocket protocol.

## Frequently Asked Questions

### What transport protocols does the MCP Workbench support?

The MCP Workbench supports three transport mechanisms: stdio for local subprocess communication, Server-Sent Events (SSE) for HTTP streaming, and streamable HTTP for modern MCP servers. These are configured via `StdioServerParams`, `SseServerParams`, and `StreamableHttpServerParams` models in [`autogen_ext/tools/mcp/_config.py`](https://github.com/microsoft/autogen/blob/main/autogen_ext/tools/mcp/_config.py).

### How does the Workbench handle user input requests from tools?

When an MCP tool requires user input, the bridge stores an `asyncio.Future` in a `pending_elicitations` dictionary keyed by a UUID. The UI receives an `elicitation_request` message and responds with an `elicitation_response` containing the UUID and user data, which resolves the future and allows the MCP operation to continue execution.

### Can I connect to MCP servers without using the AutoGen Studio UI?

Yes, you can connect programmatically by constructing the same WebSocket URL used by the frontend. Encode your server parameters as base64 JSON and connect to `ws://<host>/mcp/ws/<session_id>?server_params=<params>`. You can then send operation messages and receive responses using any WebSocket client library in Python, TypeScript, or other languages.

### Where do I add support for a new MCP server type?

To add a new server type, define a Pydantic model in [`autogen_ext/tools/mcp/_config.py`](https://github.com/microsoft/autogen/blob/main/autogen_ext/tools/mcp/_config.py), import it at the top of [`autogenstudio/web/routes/mcp.py`](https://github.com/microsoft/autogen/blob/main/autogenstudio/web/routes/mcp.py), and extend the `create_mcp_session` function with a new conditional branch to instantiate the appropriate MCP client. The bridge and callback layers remain unchanged because they operate on the generic MCP protocol.