Skip to content

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" });
function connect(options: ConnectOptions): Promise<App>;
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

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.
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.
  • Events documents the full app.on() event table.
  • React hooks provides AppProvider wrappers over connect().