connect()
connect(options) is the entry point. It opens the MCP ext-apps handshake and
resolves once the host is ready, returning a connected App whose theme, host
info, and tool context are available immediately.
import { connect } from "@nimblebrain/synapse";
const app = await connect({ name: "my-app", version: "1.0.0" });Signature
Section titled “Signature”function connect(options: ConnectOptions): Promise<App>;Options
Section titled “Options”| Option | Type | Description |
|---|---|---|
name |
string |
App name (must match registered bundle name) |
version |
string |
Semver version |
autoResize |
boolean? |
Observe document.body and auto-send size-changed. Default false |
forwardKeys |
boolean | KeyForwardConfig[]? |
Forward keyboard shortcuts to the host so its own shortcuts fire while focus is in the app. true is Escape plus every Ctrl/Cmd combo except the clipboard keys. Forwarding is on only when the host declares ai.nimblebrain/keydown. Otherwise keys are not captured. |
on |
Record<string, (data) => void>? |
Pre-register event handlers before the handshake, so no early messages are lost |
App properties
Section titled “App properties”Available synchronously once the promise resolves.
| Property | Type | Description |
|---|---|---|
theme |
Theme |
Current theme (mode, tokens) |
hostInfo |
{ name, version } |
Host identity |
toolInfo |
{ tool } | null |
Tool context if launched from a tool call |
containerDimensions |
Dimensions | null |
Container size constraints from host |
hostContext |
McpUiHostContext |
The full host context — spec fields plus whatever the host publishes alongside |
hostCapabilities |
McpUiHostCapabilities |
What the host declared in ui/initialize. Every method and helper checks it before sending; see the portable-app contract. |
destroyed |
boolean |
True after destroy() |
supportsTasks |
boolean |
Whether the host declared the MCP tasks extension (io.modelcontextprotocol/tasks). callToolAsTask throws when this is false. |
App methods
Section titled “App methods”| Method | Description |
|---|---|
on(event, handler) |
Subscribe to events. Returns an unsubscribe function. |
resize(width?, height?) |
Send size to host. Auto-measures document.body if no args. |
openLink(url) |
Open a URL through the host. Without openLinks, or when the host refuses, opens it with window.open. |
updateModelContext(state, summary?) |
Push LLM-visible state. No-op without updateModelContext. |
callTool(name, args?) |
Call a tool on this app’s own MCP server and get a typed result. An app reaches its own server and nothing else — cross-source work belongs to the agent. Rejects with HostCapabilityError without serverTools. |
readServerResource({ uri }) |
Read an MCP resource from the originating server. Rejects with HostCapabilityError without serverResources. |
sendMessage(text) |
Send a message into the agent conversation. No-op without message. To tell the agent what the user is acting on, call updateModelContext first. |
destroy() |
Clean up all listeners, observers, and timers |
That is the whole object. It is deliberately this small: NimbleBrain’s own
extensions, downloadFile and the MCP tasks extension are functions over an App, imported
from the package root, so an app that never picks a file never carries the
picker.
| Function | Description |
|---|---|
callToolAsTask(app, name, args?) |
A tool call the server may run as a task. Resolves with a handle (task, result(), refresh(), cancel(), onStatus()); result() polls until the task ends and rejects with TaskError if it does not complete. See long-running tools. Rejects with HostCapabilityError when supportsTasks is false. |
hostSupports(app, extension) |
Whether the host declared a NimbleBrain extension: "open", "openConnectorSettings", "notify", "requestFile", "uploadFiles", "keydown" or "location". |
open(app, uri) |
Ask the host to open what a resource URI names: a record, a conversation (conversation://…), an app’s own screen (its ui:// resource) or a view another app reports in its trail. The host finds what shows it. Resolves true once the host put it on screen and handed it the URI (whether an app then shows that view is the app’s), and false without sending unless the host declares ai.nimblebrain/open. Rejects with the host’s error when nothing in the workspace shows the URI. |
openConnectorSettings(app) |
Ask the host to open this connector’s settings page. The host knows which connector’s view sent it, so an app opens only its own. Resolves true once opened, and false without sending unless the host declares ai.nimblebrain/open-connector-settings. Rejects with the host’s error when the connector has none. |
notify(app, { level, title, description? }) |
Ask the host to show the user a notice, labelled with your app: for what they would otherwise miss, such as an export finishing. level is success, info, warning or error; title is 1–120 characters, description up to 500. Resolves true once shown, and false without sending unless the host declares ai.nimblebrain/notify. Rejects with the host’s error when it refuses one, such as a burst past its limit. |
pickFile(app, options?) / pickFiles(app, options?) |
The host’s native file picker. Rejects with HostCapabilityError unless the host declares ai.nimblebrain/request-file. |
uploadFiles(app, files, options?) |
Store Files the app already holds, such as files dropped on it. The host uploads them as it uploads a pick, under the same limits, and answers the stored entries; a refusal rejects with data: { files, errors }, as a pick’s does. Each file is read in the app’s frame and a copy holding its bytes crosses (postMessage clones it), never as base64: a dropped file is readable only by the frame it was dropped on. A file over maxSize goes unread, for the host to refuse on its size. Rejects with HostCapabilityError unless the host declares ai.nimblebrain/upload-files. |
setLocation(app, trail) |
Tell the host where the app is: the whole trail, root first, as { id, label } entries. Send it when a view renders and on every navigation; each replaces the last. No-op unless the host declares ai.nimblebrain/location. |
onNavigate(app, handler) |
Run handler(id) when the user picks a trail level in the host (ai.nimblebrain/navigate). Navigate, then call setLocation again. Returns the unsubscribe. |
downloadFile(app, filename, content, mimeType?) |
Hand the user a file to save, over the spec’s ui/download-file. A string travels as the resource’s text, a Blob as base64 blob. Resolves with the host’s result — { isError: true } when the host declined or the user cancelled — and rejects with HostCapabilityError, without sending, when the host did not declare downloadFile. |
See also
Section titled “See also”- Events documents the full
app.on()event table. - React hooks provides
AppProviderwrappers overconnect().