Integrations
The Connections page of an AI app, for MCP servers and built-in integrations. Handles sign-in, failing servers and which tools the assistant may use.
- Category
- AI
- Components used
- 16
- Files
- 10
- Usage examples
- 3
- Access
- HextaUI Pro (55 blocks)
- Source updated
- Counted in
- UI component usage study
Part of HextaUI Pro, all 55 blocks, $49 one-time, Compare plans
Every agent product ends up with a Connections page: Claude and ChatGPT call them connectors, Cursor lists MCP servers, Raycast has extensions. Integrations is that page as one component. It lists what's connected, adds new connections, and controls which tools the assistant may use and when it has to ask.
Each row shows the icon, name, description, the account it's signed in as and how many of its tools are on. Status always has its own icon and wording: Connected, Needs sign-in, Sign-in expired, Connecting…, Error with the server's message, and Disabled. Rows that need you have the fix right there: Sign in, Reconnect or Retry. Two connections with the same name show their address so you can tell them apart.
Each tool has one setting with three choices: Always allow, Ask first or Off. Read-only tools start on Always allow and tools that change things start on Ask first. Tools are grouped into Read-only and Changes things, and each group's menu sets the whole group at once and says Mixed when its tools differ. A tool that differs from its group's default keeps its icon in color, so the exceptions stand out. Lists over 20 tools collapse behind Show all, and connections with more than eight get a search that the group menus follow.
Add connection opens a dialog with two paths. Browse searches a directory of integrations by name and category and connects in one click. Custom server takes a URL (https, except localhost), a name, Streamable HTTP or SSE, and authentication: none, OAuth, an API key or custom headers with hidden values. Test connection lists the tools it found before you add anything, and a test that fails partway says why and keeps what you typed. Sign-in shows a waiting state with Cancel, suggests cancelling if it takes long, and times out after two minutes.
Rows, notices and error messages grow and shrink in place, so nothing below them jumps. A new connection grows into the list, a disconnected one collapses out of it after you're back on the list, and a fixed error folds away. Search at the top covers connections and their tools, and matching tools open the connection filtered to that tool. A meter counts tools that are on against a soft limit, 40 by default, with a calm note past it. Every change is optimistic and rolls back with a toast if your callback throws. Disconnect asks first and names what stops working. With nothing connected, the page suggests four integrations to start with.
Get HextaUI Pro
One payment unlocks every block, including future ones. See pricing.
Add the Pro registry to components.json
components.json Add your token
Create a token on your account page and put it in
.env.localasHEXTAUI_PRO_TOKEN.Add the block
pnpm dlx shadcn@latest add @hextaui-pro/integrations
Wire it to an MCP config
Keep servers in an mcpServers object like Claude Desktop and Cursor do, and turn it into connections with their live state. Each callback saves one change to the config. Throw from any of them and the change rolls back with your message.
Feed permissions to tool approvals
On the server, turn each tool's access into the AI SDK's needsApproval. Ask first pauses the call for the Tool Calls block's Allow and Deny, Always allow runs it, and tools that are Off are left out, so the model never sees them.
Show what the assistant can access
IntegrationsSummary is a read-only list of what each connection lets the assistant read, do on its own or ask about first. Put it in a popover next to the prompt so people can check before they ask.
Anatomy
The parts you compose, from the outside in.
| Part | Description |
|---|---|
Integrations | The whole page: search, the tool meter, the connection list, the detail view, the add dialog and the disconnect confirmation. |
Connection row | Icon, name, description, status, account, tool count and the action the status needs. |
Connection detail | The connection's header with an Enabled switch and menu, a status notice, and tabs for tools, resources and prompts. Tools sit in Read-only and Changes things groups, each with a menu for the whole group. |
Add connection dialog | Browse, with search and categories, and Custom server, with URL, transport, authentication and Test connection. |
IntegrationsSummary | A read-only list of what the assistant can read, do, ask about first or never do in each connection. |
integrations-utils | The types and pure helpers: resolveTool, groupAccess, accessCounts, toolBudget, searchConnections, validateUrl, needsApproval, accessSummary and the optimistic patch helpers. |
Integrations
Also accepts every div prop except children.
| Prop | Type | Default |
|---|---|---|
connectionsWhat's connected. { id, name, type, status, tools, description?, account?, error?, icon?, url?, command?, transport?, resources?, prompts? }. type is "remote" | "local" | "builtin". status is "connected" | "needs-auth" | "expired" | "connecting" | "error" | "disabled". icon is any node; brand marks look best monochrome with fill="currentColor". Pass a new array when your data changes; changes still saving are kept on top. | Connection[] | – |
directoryIntegrations people can add. { id, name, description, category, icon?, url?, auth?, type?, featured? }. Featured entries come first in the empty state. Leave it empty to show only Custom server. | DirectoryEntry[] | [] |
onConnectConnect, sign in or retry. request is { kind: "directory", entry }, { kind: "custom", server, tools } or { kind: "reconnect", connection }. Resolve with the connection as it is now. Throw to show your message. signal aborts on Cancel or timeout. | (request, { signal }) => Promise<Connection> | – |
onTestCheck a custom server and list what it offers. server is { name, url, transport, auth }. Throw with a message people can act on. Leave it out to hide Test connection. | (server, { signal }) => Promise<{ tools, resources?, prompts? }> | – |
onAccessChangeSave a tool's access: "allow", "ask" or "off". toolNames holds every tool a group menu changed. Throw to roll back. Leave it out to make the menus read-only. | (connectionId, toolNames, access) => void | Promise<void> | – |
onToggleConnectionDisable or enable a whole connection without losing its settings. Leave it out to hide the switch. | (connectionId, enabled) => void | Promise<void> | – |
onDisconnectRemove a connection after the confirmation. The row leaves right away and comes back if this throws. | (connectionId) => void | Promise<void> | – |
toolLimitThe soft limit for tools that are on. Past it, the meter turns to a warning. Nothing is blocked. | number | 40 |
connectTimeoutHow long to wait for onConnect, in milliseconds, before aborting and saying sign-in timed out. | number | 120000 |
IntegrationTool
One tool in connection.tools.
| Prop | Type | Default |
|---|---|---|
nameThe tool's name as the server reports it. Unique within its connection. | string | – |
readOnlyFrom the MCP readOnlyHint annotation. Read-only tools sit in the Read-only group and start on Always allow; the rest sit in Changes things and start on Ask first. | boolean | – |
accessWhether the assistant runs it, asks first or doesn't see it. Leave it out to use the default for its group. Only tools that aren't off count toward toolLimit. | "allow" | "ask" | "off" | – |
IntegrationsSummary
Also accepts every div prop except children.
| Prop | Type | Default |
|---|---|---|
connectionsThe same connections. Only connected ones with tools on are listed. | Connection[] | – |
onManageShows a Manage integrations link that calls this. | () => void | – |
| Key | Action |
|---|---|
| EnterSpace | On a row, opens the connection. On an access menu, opens it. |
| ↑↓ | Moves between Always allow, Ask first and Off in an access menu. Enter picks one. |
| Escape | In a search box, clears it. In a menu or the dialog, closes it, and cancels a sign-in that's waiting. |
| ←→ | Moves between the dialog's tabs, categories, transports and sign-in options. |
| Enter | In the custom server form, tests the server if it hasn't been tested, then adds it. |
- Connections, tools, resources, prompts and the directory are lists, and each row is named by its connection or tool.
- Status is never only a color: every status and every access choice has its own icon and words, and the groups say Read-only or Changes things.
- Each access menu is a button named by the tool and its current choice, like "create_pull_request: Ask first", and opens a radio menu that describes each choice.
- A polite live region announces sign-in, test and connect results, every change and every rollback, and a token revoked while the detail is open.
- Opening a connection moves focus to its heading. Going back, or disconnecting, puts focus on the same row or the one next to it. Rows on their way out are inert.
- Touch targets are at least 44px on coarse pointers, and inputs are at least 16px so iOS doesn't zoom.
- With reduced motion, rows, notices and the detail view appear and disappear in place without growing, sliding or moving what's around them.
Built with
The free HextaUI components Integrations is made from. Each one installs on its own.
Code
10 files, added to components/blocks/integrations.