Composer sources
ProA "Connected sources" section for Composer's @ menu, from your MCP connections. A connected source can be mentioned and says "Connected". One that needs signing in says so; with onSignIn, choosing it starts the sign-in instead of inserting anything, and without it the option says it needs signing in and can't be chosen. An unavailable source stays in the menu with your reason and can't be chosen. Nothing is hidden because it can't be used. Pass what it returns as Composer's mentions, with any others.
Version 5.2.0· other versions
This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).
Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.4.0, 2.5.0, 2.5.1, 2.6.0, 2.6.1, 2.6.2, 2.7.0 and 2.8.0: the page came later, or had another name then.
Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.
Preview
Loading the preview
Install
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/composer-sources
Usage
"use client"
import * as React from "react"
import { Composer } from "@/components/candor/composer"
import { useComposerSources, type ConnectedSource } from "@/components/candor/composer-sources"
import type { EntityRef } from "@/lib/candor/chat"
export default function Example() {
const [value, setValue] = React.useState("")
const [refs, setRefs] = React.useState<EntityRef[]>([])
// As your MCP client reports each connection. A real app starts its sign-in flow in onSignIn.
const [sources, setSources] = React.useState<ConnectedSource[]>([
{ id: "tracker", name: "Issue tracker", status: "connected", description: "tracker.example.com", entity: { kind: "source", name: "Issue tracker" } },
{ id: "mail", name: "Shared inbox", status: "needs-sign-in" },
{ id: "drive", name: "Team drive", status: { kind: "unavailable", reason: "The drive’s server isn’t answering. Last heard from 20 minutes ago." } },
])
const sourceMentions = useComposerSources(sources, {
onSignIn: (s) => setSources((all) => all.map((x) => (x.id === s.id ? { ...x, status: "connected", entity: { kind: "source", name: x.name } } : x))),
})
return (
<Composer
className="max-w-2xl"
value={value}
onValueChange={setValue}
onSubmit={() => setValue("")}
references={refs}
onReferencesChange={setRefs}
placeholder="Type @ to see the connected sources"
mentions={[{ id: "p1", group: "People", label: "Dana Ortiz", description: "Support lead" }, ...sourceMentions]}
/>
)
}Functions
useComposerSources(sources: ConnectedSource[], options?: { /** Called when the person chooses a source that needs signing in. Without it, such a source can't be chosen and says why. */ onSignIn?: ((source: ConnectedSource) => void) | undefined; /** The heading over the section. Defaults to "Connected sources". */ group?: string | undefined; })Strings
The fixed words, in English by default. Change any of them under composerSources in <LocaleProvider strings={{ … }}>; the table is exported as composerSourcesStrings.
| Key | English |
|---|---|
| group | Connected sources |
| connected | Connected |
| signIn | Sign in |
| needsSignIn | Needs sign-in |
| signInElsewhere | Needs signing in again before it can be used |
| unavailable | Unavailable |
Types
- ConnectedSource
- One source the agent can read through, as your MCP client reports its connection.
{ /** Your id for the connection. */ id: string; /** The name to show, e.g. "Linear", as your app knows it. */ name: string; /** The connection as it stands: "connected", "needs-sign-in" (missing or expired), or unavailable with the reason in your app's words. */ status: "connected" | "needs-sign-in" | { kind: "unavailable"; reason: string; }; /** One line under the name while it can be used, such as the server's host. */ description?: string | undefined; /** What @ inserts for it, as a chip the agent receives as a reference. Without one, "@Name" is typed. */ entity?: EntityRef | undefined; }
Types from other items
The props above take these. Each is defined by another item; import it from the path shown.
- EntityRef from @/lib/candor/chat
{ kind: EntityKind; /** The identifier, e.g. "orders.status" or "billing.invoice.due_date". */ name: string; /** A friendlier label when there is one, e.g. "Region". */ label?: string | undefined; /** Where it lives, when more than one place is in scope, e.g. "Shop staging". */ location?: string | undefined; }- EntityKind from @/lib/candor/chat
- What kind of thing an entity is: "record", "table", "workflow"… Any string; the app registers each kind's icon and noun (see EntityKindsProvider), and presets cover the kinds of the systems an app commonly works with.
string