How the Browse Connectors Modal Helps Users Discover MCP Integrations in y-gui

The browse connectors modal queries the y-gui backend at /api/browse-connectors to surface available MCP servers, rendering them in a curated card interface where users can add integrations to their local configuration with a single click.

The y-gui repository (luohy15/y-gui) provides a React-based frontend for managing MCP (Model Context Protocol) connections through an intuitive settings panel. The browse connectors modal serves as the primary discovery mechanism, bridging the gap between public connector registries and local instance configuration by fetching and displaying available integrations that can be instantly activated without manual JSON editing.

Triggering the Discovery Interface

Users initiate the discovery flow from the main connectors view. In ConnectorSection.tsx, the component maintains a local isBrowseModalOpen state that is toggled when the user clicks the Browse Connectors button. When this state becomes true, the component renders the BrowseConnectorsModal and passes a callback handler for adding servers.

<button
  onClick={() => setIsBrowseModalOpen(true)}
  className={`px-3 py-1.5 sm:px-4 sm:py-2 ${isDarkMode ? 'bg-gray-600 hover:bg-gray-700' : 'bg-gray-600 hover:bg-gray-700'} text-white rounded-md text-sm sm:text-base`}
>
  Browse Connectors
</button>

Located in frontend/src/components/Settings/ConnectorSection.tsx (lines 25‑33).

Fetching Available MCP Integrations

When the modal mounts or the isOpen prop changes to true, a useEffect hook triggers the fetchServers function. This utility uses the shared useApi hook to perform an authenticated GET request to the /api/browse-connectors endpoint, retrieving a list of publicly available connector descriptors.

useEffect(() => {
  if (isOpen) {
    fetchServers();               // ← runs when modal becomes visible
  }
}, [isOpen]);

const fetchServers = async () => {
  setLoading(true);
  try {
    const response = await api.get('/api/browse-connectors');
    setServers(response.data?.servers || []);
  } finally {
    setLoading(false);
  }
};

From frontend/src/components/Settings/BrowseConnectorsModal.tsx (lines 38‑55).

The backend route is defined in backend/src/api/mcp-server.ts. It currently returns a static array of server objects—including fields like name, author_name, description, and server_url—but can be easily swapped to query an external registry without modifying the frontend logic.

router.get('/api/browse-connectors', async (req, res) => {
  const servers = [
    {
      uuid: '1',
      name: 'OpenAI',
      author_name: 'OpenAI',
      title: 'OpenAI GPT',
      description: 'Connect to OpenAI GPT models',
      server_key: 'openai',
      config_name: 'openai',
      server_url: 'https://api.openai.com/v1',
      is_openapi: true,
    },
    // ... additional entries
  ];
  res.json(jsonResponse({ servers }));
});

Located in backend/src/api/mcp-server.ts (lines 103‑121).

Rendering the Connector Catalog

Once the data arrives, the modal maps over the servers array and renders each integration as a discrete card. Each card displays the connector’s title, author, and description, alongside an Add button that initiates the installation flow. This presentation layer decouples the discovery UI from the persistence logic, keeping the modal focused solely on selection.

The rendering logic iterates over the state populated by fetchServers:

{servers.map((server) => (
  <div key={server.uuid} className="...">
    <h3>{server.title}</h3>
    <p>{server.description}</p>
    <span>{server.author_name}</span>
    <button onClick={() => handleAddServer(server)}>Add</button>
  </div>
))}

Adapted from the rendering loop in BrowseConnectorsModal.tsx (lines 19‑53).

Adding Connectors to Your Configuration

When a user clicks Add, the handleAddServer function transforms the API response into the internal McpServer type required by y-gui’s state management. It constructs an object with name, url, status, and is_default fields, then invokes the onAddServer callback passed down from ConnectorSection.

const handleAddServer = async (serverFromAPI: ServerFromAPI) => {
  setAddingServer(serverFromAPI.name);
  const mcpServer: McpServer = {
    name: serverFromAPI.config_name || serverFromAPI.name,
    url: serverFromAPI.server_url,
    status: 'disconnected',
    is_default: false,
  };
  await onAddServer(mcpServer);   // passes to ConnectorSection
  onClose();                      // closes modal
  setAddingServer(null);
};

From frontend/src/components/Settings/BrowseConnectorsModal.tsx (lines 58‑71).

Persisting New Connections

The ConnectorSection component implements handleAddServerFromBrowse to receive the new McpServer object. It POSTs the payload to /api/mcp-server, displays a success toast via setStatusMessage, and triggers mutateConnectors() to revalidate the local cache. This SWR mutation ensures the UI refreshes immediately, showing the newly added connector in the main list without a page reload.

const handleAddServerFromBrowse = async (server: McpServer) => {
  await api.post('/api/mcp-server', server);
  setStatusMessage({ type: 'success', text: `Connector "${server.name}" added successfully` });
  mutateConnectors();             // refresh list
};

Located in frontend/src/components/Settings/ConnectorSection.tsx (lines 84‑95).

Summary

  • The browse connectors modal is triggered via setIsBrowseModalOpen in ConnectorSection.tsx, rendering only when the user explicitly requests discovery.
  • It fetches the catalog from the /api/browse-connectors endpoint defined in backend/src/api/mcp-server.ts, which can be backed by a static list or external registry.
  • The modal displays server metadata—title, author, and description—in a card-based layout generated by mapping the servers state.
  • The handleAddServer function transforms API-specific fields into the canonical McpServer interface before passing the object upward.
  • Persistence occurs in ConnectorSection through handleAddServerFromBrowse, which POSTs to /api/mcp-server and calls mutateConnectors() to update the UI.

Frequently Asked Questions

What endpoint powers the connector discovery feature?

The modal queries /api/browse-connectors, a REST endpoint mounted in backend/src/api/mcp-server.ts. This route returns a JSON payload containing an array of available server descriptors, which the frontend consumes to populate the discovery list.

How does the modal transform external connector data into local configuration objects?

The handleAddServer function in BrowseConnectorsModal.tsx maps fields from the API response—such as config_name and server_url—into the McpServer interface, setting default values for status ('disconnected') and is_default (false) before invoking the parent’s add handler.

Where is the new connector persisted after a user clicks Add?

The handleAddServerFromBrowse method in ConnectorSection.tsx receives the transformed McpServer object and sends it to the backend via POST /api/mcp-server. After a successful response, it calls mutateConnectors() to refresh the SWR cache and update the visible connector list.

Can the backend serve dynamic connector lists instead of static data?

Yes. The current implementation in backend/src/api/mcp-server.ts uses a hardcoded array for demonstration, but the route handler can be modified to query a database or external registry service. Because the frontend expects only the standard { servers: [...] } envelope, no changes are required in BrowseConnectorsModal.tsx to support dynamic sources.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →