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
setIsBrowseModalOpeninConnectorSection.tsx, rendering only when the user explicitly requests discovery. - It fetches the catalog from the
/api/browse-connectorsendpoint defined inbackend/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
serversstate. - The
handleAddServerfunction transforms API-specific fields into the canonicalMcpServerinterface before passing the object upward. - Persistence occurs in
ConnectorSectionthroughhandleAddServerFromBrowse, which POSTs to/api/mcp-serverand callsmutateConnectors()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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →