Files
cline/sdk/DOC.md
Tomás Barreiro 731f48462b Support MCP Resources [NO-OP] (#15165)
* Support MCP Resources

* Small fixes

* Address PR comments

* remove CreateMcpToolsOptions mcpApps option
2026-10-19 00:10:19 +02:00

24 KiB
Raw Permalink Blame History

Oversized tool result recovery

Cached text excludes native image data. Cache admission uses the persisted JSON/string model-preview size for the truncation threshold; YAML size controls only cache capacity. Plain strings stay unchanged; structured cached text is serialized as YAML, preserving multiline payloads as literal blocks without automatic wrapping. Original history and tool events keep their existing format. Recovery uses the existing read_files output and per-line limits; disabling that tool does not disable caching or remove recovery notices.

Tools created with createTool may set resultPolicy: "cache-oversized". Core enables this for MCP and Composio tools. Original output remains in history and events; synchronous model preparation sends a bounded preview with a cline://cache/<encoded-session-id>/<result-id>.result.txt URI for cached oversized responses. Use read_files with start_line/end_line to read omitted content. Shell and filesystem search tools do not support these URIs. The stateless agent runtime does not own a cache.

Entries expire after five further model iterations without a cache read, across follow-up turns. Explicit reads refresh expiry; model requests do not. A 16 MiB UTF-8 text limit per session evicts least recently read entries; individually larger results have no recovery URI. Shutdown, history reset, and restore clear the cache, and resume does not regenerate entries. Missing reads instruct the agent to refetch with an appropriate read/query tool without repeating side-effecting actions. Evicting cached text does not remove original conversation output or change earlier recovery notices; URI references remain until the cache is cleared. Cache-miss feedback appears only when an agent attempts to read missing content.

Shared agent review UI

@cline/ui exports presentation-only components for showing a session's changed files and pull-request status. Configure Tailwind v4 and a token entry point before importing @cline/ui/components.css, following the complete styling setup. Then import the components from the package root:

import {
  AgentChangedFile,
  AgentChangesPanel,
  AgentPullRequestBar,
} from "@cline/ui";

AgentChangesPanel owns the Changes header, count, close action, empty state, and scroll region. Compose AgentChangedFile children to show collapsible paths, copy feedback, additions/deletions, host-provided actions, and rendered diff content. The host retains change collection, clipboard and editor integration, and conversation focus.

AgentPullRequestBar accepts normalized AgentPullRequestData plus loading and error state. The host owns refresh, polling, navigation, and telemetry, and provides its accessible checks popover through renderChecks. Native hosts can intercept links with onNavigate; web hosts can omit it to render external anchors. getAgentPullRequestMergeStatus and summarizeAgentPullRequestChecks expose the same status normalization for other host presentation.

Fork metadata

createForkSessionMetadata from @cline/core copies metadata, replaces fork ancestry, and removes inherited handoff markers. Callers supply the source ID, timestamp, source, and optional beforeRunCount; titles and session creation remain caller-owned.

Cloud sessions (experimental)

CloudSessionApi and CloudSessionController are exported from @cline/core/cloud. The API handles REST requests; the controller handles remote Hub connections, session lifecycle, transcript reconciliation, and approvals. Hosts provide API URLs and a fresh-token callback; feature gating and account selection stay in the host. Importing this subpath does not start a local agent.

For ordinary creation, CloudCreationUnconfirmedError means a dispatched request could not be reconciled. It remains a CloudSessionError with code request_failed; hosts should direct users to their session list instead of offering a blind retry.

Use subscribe for immutable snapshots and live events, attach/readMessages to open a session, and send for a follow-up. Attaching a provisioning or failed session returns its receipt without connecting. detach closes this viewer, not the remote task. Call dispose when the host shuts down. Viewers hydrating active runs with readMessages reconcile canonical history at completion even when they missed the run-start event and earlier content deltas.

create accepts sandboxType: "standard" | "resumable" (default: "standard"). The controller resumes suspended sessions when opened and restores their saved tasks.

Hosts replacing controllers during credential refresh can share the pendingInitialTasks: Map<string, CloudCreationOptions> constructor option. It retains first-task approval/thinking/reasoning preferences, including updates through restoreCreationOptions, until the inner task is found or created (or the outer session is deleted). dispose preserves an injected map; without one, the controller owns and clears its pending state. Restoring options alone never authorizes recreation of a missing established task.

Experimental cloud handoff

loadCloudModels and CloudSessionController.listModels() provide eligible cloud models. Handoff requires the selected model; it never substitutes another.

Use create({ handoff, ... }) to provision and seed, or seedHandoff(id, seed) for an existing target. Persist target IDs and dispatch markers through the callbacks; use recoverOnly after uncertain dispatch to avoid duplicate conversations. Handoff creation requires onCreating: durably save intent before returning, and reject a previously unconfirmed intent after restart. Callback errors preserve their original type; they do not prove an earlier POST was rejected or permit clearing its intent. CloudHandoffSeedRejectedError means no seed was dispatched; clear only the seed marker before retrying the saved target. verifyHandoffTranscript checks the seeded history; waitUntilReady(id) waits for provisioning.

Voice input models

getLocalTranscriptionModels(providerId, config?) from @cline/core returns the voice models supported by a provider's transcription transport. Use it to build voice pickers rather than filtering the bundled chat catalog. Vercel uses its live model list and advertised streaming tags; unavailable or malformed responses fail discovery rather than restoring stale bundled models. Voice selection saves and both batch and streaming execution revalidate through the same service.

isTranscriptionModel from @cline/shared (also exported for browsers) accepts exact audio-only input and text-only output modalities. An explicit transcription label does not override additional input or output modalities. Multimodal live models are classified as realtime, which currently has no built-in transport support and is excluded from voice and chat pickers. Dedicated transcription can still use either batch or streaming mode. Classification alone does not prove that a provider implements the required transport.

createStreamingAudioTranscriptionSession mints short-lived Vercel or single-use ElevenLabs credentials. Its shared response includes transport and sampleRate; browser clients must capture PCM at that rate (Google live routes require 16 kHz). ElevenLabs exposes batch scribe_v2 and live scribe_v2_realtime separately.

SSH remote environments

RemoteEnvironmentService (exported by @cline/core and @cline/sdk) owns SSH profiles, connection testing, helper installation, authenticated loopback tunnels, remote commands, status changes, and cleanup. It runs in the client's Node host; browser clients expose this API through their host transport. No desktop code is required. OpenSSH config aliases, identity files, and ssh-agent authentication are supported. Connections use batch mode and require an already-trusted host key in OpenSSH known_hosts (or knownHostsPath). Before first use, verify the server fingerprint through a trusted channel and enroll it using your SSH client. Unknown or changed keys are rejected before inspection, upload, or execution.

import { ClineCore, RemoteEnvironmentService } from "@cline/core";

const environments = new RemoteEnvironmentService({
  helperBinaryDirectory: "/opt/my-client/remote-helpers",
  onStatusChange: (status) => console.log(status),
});
const profile = await environments.upsert({ name: "Build host", host: "builder" });
const connection = await environments.connect(profile.id);
const core = await ClineCore.create({
  clientName: "my-client",
  backendMode: "remote",
  remote: {
    endpoint: connection.endpoint,
    authToken: connection.authToken,
    workspaceRoot: connection.workspaceRoot,
  },
});
try {
  // The ordinary session, tools, approvals, and event APIs execute on this host.
  // Supply provider credentials in the session config, as for other remote hubs.
  console.log(await core.list());
} finally {
  await core.dispose();
  await environments.dispose();
}

The service also exposes list, upsert, delete, test, disconnect, run, getConnection, getActive, activateConnection, and getStatuses. onConnectionLost lets clients retire runtime bindings after a tunnel fails. Each service instance has a unique remote Hub discovery record, so another client connecting to the same host cannot stop its Hub. Connect/disconnect/profile mutations are serialized; concurrent connects reuse one tunnel. Dispose the ClineCore runtime before disconnecting its environment. Do not expose the connection's authentication token to a browser or logs.

Profiles default to ~/.cline/data/settings/remote-environments.json, written atomically with mode 0600. They contain identity-file paths, never private keys. Options include profilesPath, sshPath, knownHostsPath, process timeouts, helperBinaryPath, and helperBinaryDirectory. The corresponding helper/SSH configuration variables are CLINE_REMOTE_HELPER_BINARY, CLINE_REMOTE_HELPER_DIRECTORY, CLINE_SSH_PATH, and CLINE_SSH_KNOWN_HOSTS_FILE.

Remote Hubs are CLI-managed. Clients package the self-contained Cline CLI binary (apps/cli, compiled with Bun) for each remote OS and architecture; the service stages it on the host and runs cline hub ensure --json --discovery-path <path> ... to start or reuse a loopback Hub, and cline hub stop --discovery-path <path> to stop it. Use remoteHelperBinaryFilename({ platform, arch }) for the bundled filename (cline-<target-triple>). Linux and macOS on x64/arm64 are supported. The CLI must be built from the same SDK build as the client; missing binaries produce an explicit error, without installing a runtime from the network. Agent tools and persistence run remotely; the host only manages SSH and forwards the authenticated hub connection.

Clients whose own process cannot host the Hub daemon can call setHubDaemonLauncher({ command: "/path/to/cline" }) so detached Hubs they start are launched through the Cline CLI.

Provider authentication metadata for host UIs

@cline/shared (including its browser entry point) exports ProviderAuthInfo, ProviderLocalCli, resolveProviderLocalCli(provider), and resolveProviderApiKeyOptional(provider). The resolvers accept provider data (metadata.localCliCommand with optional docsUrl, and metadata.apiKeyOptional); they perform no registry lookup. Hosts resolve providers through @cline/llms and then pass that data to the shared helpers. listLocalProviders includes the resulting facts in each ProviderListItem.auth (localCli, and apiKeyOptional for local inference servers and cloud-credential providers that run without a key), allowing browser clients to render authentication guidance and gate sessions without importing the LLM catalog. ProviderListItem.modelTools likewise carries provider-level native tool availability for settings indicators.

Concurrent subagent tool calls

spawn_agent and configured subagent_* tools declare executionMode: "parallel". Consecutive calls to these tools in one model response run concurrently even when the parent runtime uses its default sequential mode. Each call still returns its child's completed answer, and tool results remain in the model's original call order.

A tool's optional executionMode overrides the runtime's toolExecution setting. Unmarked tools inherit the runtime setting. Sequential calls form ordering boundaries: read_file → [spawn A, spawn B] → edit_file executes the read first, then both child runs together, then the edit after both finish. This does not change the execution mode of tools inside the child agents.

Preparation remains serial for the whole response, before any tool executes. All before-tool hooks and required approvals therefore complete before the parallel group starts. A before-tool skip blocks its own call; a before-tool stop prevents the entire response's execution, as before. Pending approvals can delay sibling execution. No background-run handles or new concurrency limit are introduced.

Configured subagent approvals

Configured agents do not expose a tool approval policy setting. The parent’s subagent_<name> call follows the parent session’s approval policy; the child executes its available tools without inheriting that policy or approval callback. Its configured tools allowlist and disabled-tool filtering still apply. Runtime hooks remain inherited and can block tool execution.

Saving provider credentials

saveLocalProviderSettings is asynchronous; callers must await it before reloading provider catalogs or continuing onboarding. When a saved provider has a modelsSourceUrl, credential, header, and base URL updates refresh its model list before saving the new settings. updateLocalProvider follows the same rule even when the request omits models and modelsSourceUrl. Endpoint changes relocate same-origin model sources; separate catalog origins remain unchanged. Model refresh in saveLocalProviderSettings is best-effort: if it fails during discovery, the new settings are still saved and the last known catalog is retained. Settings and catalog persistence errors still reject the save. Provider-service mutations are serialized per catalog file within the process, including across manager instances and different providers. Discovery prepares the update before the complete settings patch is persisted once. If the catalog write fails, the prior provider settings are restored only while the failed operation still owns the current settings entry; newer saves and removals are preserved. A rollback failure is reported alongside the original error. Explicit updateLocalProvider calls still reject failed model fetches and retain the prior settings and catalog.

Catalog refreshes replace discovery-owned model IDs while retaining manually added models, their default selection, and overrides on retained model entries. models.json records discovery-only IDs in discoveredModelIds; IDs also supplied explicitly are user-managed. An explicit models update replaces the manual list. An existing model selection in provider settings does not count as a manual addition when initializing a source-backed catalog. Provider capabilities are inherited when registering models, so stored per-model capability overrides continue to take precedence after refreshes.

Shared UI session rows

@cline/ui exports AgentSessionRow, AgentSessionRowEditor, and AgentSessionOverview, together with their public props types. These are presentation primitives for session navigation, rename, and metadata content; the host retains session data, routing, menus, permissions, formatting, and interaction policy. Import the shared component stylesheet with the host theme.

AgentSessionRow owns the row geometry, selected/hover appearance, timestamp placement, and pending/provisioning/running/unread status-dot precedence. Hosts provide the already-formatted label and timestamp, optional leading and pinnedIndicator content, and a sibling action. Root DOM props and refs pass through to the row wrapper for host-owned context-menu or hover-card triggers.

The default control is the desktop native button; its disabled and onSelect props apply only in that mode. URL or router navigation uses the mutually exclusive renderControl mode, which receives the shared navigation className and row children for the host's link or router control. The host control owns its href, accessibility, disabled behavior, and event handling. The control union prevents combining renderControl with disabled or onSelect, and keeps optional actions as siblings so interactive elements are not nested.

AgentSessionRowEditor supplies the matching edit frame while the host owns the rename input, focus, Enter/Escape/blur handling, and saving state. AgentSessionOverview renders a title and [label, value, fullValue?] metadata rows; the host owns the hover-card lifecycle, positioning, and metadata formatting. See the session-row adoption guide for the import, slot, and trigger/ref examples.

Shared context usage presentation (@cline/ui)

AgentContextUsage exposes desktop's context ring and token breakdown through its children render callback. It adds no wrapper: the host receives AgentContextUsagePresentation (triggerLabel, ring, and details) and keeps its own accessible trigger, popover, positioning, focus, and keyboard behavior.

AgentContextUsageProps accepts usage: AgentContextUsageData, optional costLabel: ReactNode, and the required render callback. Usage contains tokensIn, tokensOut, cacheReadTokens, and optional contextWindow. Supply current-request metrics and the model's authoritative context capacity, not accumulated session token traffic. The component renders nothing when usage is empty or context capacity is unavailable or nonpositive. Cached tokens are part of input usage, not additional context consumption.

costLabel is a separate host-formatted cost. Numeric zero is displayed; previously hidden falsy values remain omitted. Desktop retains its existing cost formatter and usage source. Import the component and all three public types from @cline/ui; see UI adoption guidance for theme setup, styling, and composition examples.

Shared command output and image presentation (@cline/ui)

AgentCommandOutput renders output with a running cursor controlled by isRunning. Optional children let the host retain ANSI rendering or normalize control characters. It follows new output initially, pauses when the user scrolls away, and resumes within 24px of the bottom. Hosts own output collection, limits, and session identity; remount it when switching commands. tabIndex and classNames.viewport / classNames.cursor allow host-specific accessibility styling.

AgentImageLightboxContent renders an image and two close controls calling onClose. The host owns the dialog, positioning, Escape handling, focus management, and image navigation. backdropTabIndex can exclude the backdrop from a managed dialog's tab order. Image source validation and resolution remain host-owned; provider-generated URLs must go through an explicit host trust policy before rendering. This presentation primitive does not replace GeneratedMediaContent or its inline-byte validation.

Shell executor errors

The executor returned by createShellExecutor rejects on execution failure. The following error classes are exported from @cline/core so hosts can distinguish process outcomes without parsing messages. They are not an exhaustive list of rejections: cancellation, timeout, and stdin-write failures can reject with other errors.

  • CommandExitError — the shell started and exited non-zero. exitCode is the numeric process exit code and output contains a completion notice and the captured output (subject to the configured truncation limit).
  • CommandTerminationError — the process terminated without a numeric exit code. signal is the terminating signal, or null if none was reported; output contains a termination notice and the captured output. This error has no exitCode field.
  • CommandSpawnError — the shell process could not be started, so there is no exit code. The message keeps the pre-existing Failed to execute command: … form. code is the operating system error libuv reported (ENOENT, EACCES, EFTYPE for a file that is not a valid executable). Because spawn reports ENOENT with the same message when the executable is not found and when the working directory no longer exists, missing records which path was absent at failure time: "executable" or "cwd". It is undefined for every other code. code itself is undefined if the underlying error has no code.

The public run_commands tool catches executor failures and resolves with per-command results containing success: false, rather than propagating these errors as rejected tool calls. For CommandExitError and CommandTerminationError, the failed result retains output in its result field. For CommandSpawnError, result is empty and error includes the spawn failure message. Hosts that need the structured error fields must observe the executor rejection before this conversion.

Hosts that record command telemetry should label a CommandSpawnError by its code (and missing) rather than inventing an exit code. The VS Code and standalone adapters do this in the errorCode dimension, and use the bounded labels signal and no_exit_code for CommandTerminationError. Only an actual numeric exit is reported as exitCode.

Symlinked instruction files

Rules and workflows can be symbolic links to regular files. Source paths and fallback names use the link's name and location, not the target's. Broken, circular, and non-file targets are skipped.

UnifiedConfigFileWatcher watches only the directory containing the link, not the link's target. Edits to a symlink's target are picked up on the next refresh or new session.

Unknown model completion recovery

The AI SDK adapter maps unified length to max-tokens and missing or unrecognized reasons (including other) to unknown. Explicit stop, tool-calls, content-filter, and error retain their meanings. The agent also treats a stream without a finish event as unknown.

Without tool activity, an unknown response is preserved in history and continued once, with the model-visible user message “Previous turn ended unexpectedly. Continue from where you left off.” The message uses displayRole: "system" and userRunSpan: 0, matching injected hook context so it stays out of live and replayed chat transcripts. The system prompt is unchanged. A second unknown completion fails the run. Queued user instructions are consumed before the continuation, including in the first iteration. Tool calls receive their results through the normal loop; provider-executed actions are not replayed.

Host connector transport

Pass connectorsRequest: (path, init) => Promise<Response> to LocalRuntimeHost and createLocalHubScheduleRuntimeHandlers to supply connector authentication. Paths start with /api/v1/connectors; the host supplies the API origin and authentication. Omit it to retain local account authentication and rollout checks.

MCP Apps (experimental)

MCP Apps support is off by default. createDefaultMcpServerClientFactory({ mcpApps: true }) turns it on by advertising the io.modelcontextprotocol/ui extension (MCP_APPS_EXTENSION_ID) with the text/html;profile=mcp-app MIME type during initialize, for stdio and URL servers alike.

createMcpTools always leaves out tools whose _meta.ui.visibility does not include "model", whether or not the client advertised the extension.

Tool descriptors keep the server's _meta. getMcpAppToolMeta reads _meta.ui: resourceUri is kept only for ui:// URIs, and visibility defaults to ["model", "app"] when it is not an array. An explicit array is used as given after dropping unknown entries, so [] makes the tool visible to neither. isMcpToolVisibleToModel and isMcpToolVisibleToApp check those lists; a host must reject app-initiated tool calls when isMcpToolVisibleToApp is false.

McpManager.readResource({ serverName, uri, context }) sends resources/read and returns { contents, _meta? }, validated against the MCP SDK schema; malformed replies throw. It is optional on McpManager and McpServerClient. InMemoryMcpManager reads without waiting for in-flight tool calls on an already connected server. A read that starts while the server is being disconnected or re-registered can fail with a disconnect error; retry it.