MCP
Connect external tools through MCP.
Manual for v0.9.5. Stable release: v0.9.5.
Source candidate distribution: 0.9.5. This bundle needs exactly octet 0.9.5. Use the version-matched installation and the 0.9.5 candidate record for availability and remaining qualification. 0.9.5 assets are not published; use the reviewed source-checkout route below until publication is approved.
Connect explicitly configured MCP tool servers to octet. Start with a local stdio server you've reviewed and installed yourself. The bridge never discovers or installs server software for you.
Connect a local server#
In octet, open /extensions, choose octet-mcp (choosing a disabled
extension enables it first), and pick Add a server. The guided form asks for
a name, the command that starts the server, its arguments, any environment
variables (hidden as you type) and a display name. It then shows the complete
command and asks before it adds and starts the server. Nothing is written if you
cancel or the result fails the same trust and schema checks as a launch.
Each server then has its own entry in that menu: Show details, Refresh tools, Restart (or Start), Stop, Enable or Disable, Edit and Remove (confirmed first). Changes apply at once, and only the edited server restarts. Servers from a trusted project file are listed with their lifecycle actions only, so edit them in the project.
The menu writes ~/.octet/mcp.json as a private (0600) file. You can also
write it yourself, replacing the executable and working-directory paths with
your reviewed local paths, and protect it with chmod 600:
{
"version": 1,
"servers": {
"local-example": {
"transport": "stdio",
"label": "Local example",
"command": "/absolute/path/to/mcp-server",
"args": ["--stdio"],
"cwd": "/absolute/trusted/working-directory",
"env": {},
"enabled": true,
"required": false
}
}
}With octet 0.9.5, Python 3.9+ on PATH, and
verified matching published assets, the catalog path is:
octet extension install octet-mcp
~/.octet/extensions/octet-mcp/octet-mcp --config ~/.octet/mcp.json --check-config
octet --enable-extension octet-mcpA reviewed source checkout is still an alternative: add
--extension-dir ./extensions when launching from the repository root.
Installation and discovery are inert, and the bridge stays disabled until you
enable it. Default full access (unsafe_host) implicitly trusts the selected
extension without persisting a grant. --trust-extension and source-bound
trusted_extensions grants are optional and never enable it. --safe-mode
removes implicit trust and blocks startup even with explicit grants: executable
processes still need unsafe_host. That doesn't change MCP server trust or
tool-call policy. If the config file is missing, the bridge stays healthy with
zero servers.
Refresh rereads the tool catalog without relaunching. Restart replaces the connection. Stop removes the server's tools and closes it.
The web UI has no options menu yet. There the same actions run as the /mcp
command: status, list, show <server>, refresh [server],
restart <server>, stop <server>, add stdio, add http, edit <server>,
enable <server>, disable <server> and remove <server>. /mcp snapshot
returns the same state the TUI and Serve show.
Connect a desktop server#
A desktop MCP server such as Cua Driver needs the same interactive session variables as your shell to reach the display. The bridge never inherits the ambient environment. It forwards exactly the reviewed non-secret session names a server descriptor asks for, and only because the bundle declares them in its manifest.
Copy config.cua-driver.example.json, point command at your installed
cua-driver, and set enabled to true once you've granted the driver's own
OS permissions. The example keeps two deliberate defaults: the server ships
disabled, and confirmUnknownTools is on, so any call the driver doesn't
mark readOnly waits for your explicit approval.
"cua-driver": {
"transport": "stdio",
"label": "Cua Driver",
"command": "/absolute/path/to/cua-driver",
"args": ["mcp"],
"inheritEnv": ["DISPLAY", "WAYLAND_DISPLAY", "XDG_RUNTIME_DIR"],
"confirmUnknownTools": true,
"enabled": false
}Two independent approvals gate each name: the host forwards only the manifest's
declared names, and the bridge forwards only what this descriptor lists. A name
outside the allowlist, a duplicate, a remote descriptor that names one, or a
value that isn't set on the bridge process is a startup error, not a silent
downgrade. Explicit env values still win over an inherited name.
Credential-like names such as SSH_AUTH_SOCK and provider tokens are never
inheritable.
confirmUnknownTools is a cooperative prompt on top of host policy, not a
sandbox. An unavailable surface, a declined or cancelled answer, or a failed
request denies the call rather than assuming approval, so headless and RPC
frontends stay fail-closed. Confirmations are asked per call, and only for tools
without an exact readOnlyHint: true.
The bundled skills/cua-driver/SKILL.md documents observation, background
delivery, the agent cursor, and the credential and confirmation boundaries. The
driver itself is separate third-party software that octet doesn't install,
vendor or start.
Trust and limitations#
A local server runs with your OS authority. Neither configuration nor tool
approval is a sandbox. Trusting a server doesn't approve every tool: only an
exact, uncontradicted JSON readOnlyHint: true counts as read-only. Unknown or
destructive calls need host policy. The working-tree coding host binds
mcp.tool.call to the active owner, process generation, published tool identity
and exact arguments. Full access (unsafe_host) permits these calls, including
mutations. Controlled policies deny them and still block extension startup,
because enabling an extension alone isn't authorization. Unrecognized policy
operations stay denied. This adapter is a source change, not a claim about the
published 0.7.6 host, which denies these calls. Calls are never replayed
automatically after an ambiguous failure, and cancelling doesn't promise a
rollback.
Server descriptions, schemas, logs and results are untrusted data. The server
gets a small non-secret environment allowlist, the reviewed session names it
explicitly requests through inheritEnv, and your explicit env values, not
ambient provider tokens or dotenv files. Keep secrets out of labels and
arguments.
Remote Streamable HTTP is blocked by default, and unsafe for production, privileged networks or sensitive credentials. Its process-owner-only experimental switch isn't a safety qualification. The nine-defect remediation record and remaining closure gates describe the tested safeguards and the outstanding qualification work.
What the remote surface supports
The supported remote surface stays deliberately narrow: one exact URL with no
redirects, proxies or cookies, one negotiated session, static extension-scoped
credentials only, and an optional permanent GET stream for a server that
declares a change notification. A remote descriptor may name one OCTET_MCP_*
environment variable that the bridge reads per request and never logs, echoes or
stores. The stock runtime has no credential broker and no OAuth flow.
CredentialProvider adapters must be composed explicitly, and OAuth or browser
authorization stays policy-gated, because the extension API has no host-brokered
authorization primitive. Legacy SSE authorization, resources, prompts, sampling,
elicitation and ambient discovery are unsupported.
Reference#
The bundle needs exactly octet 0.9.5 and uses API 0.4. What follows is a
retained bundled-runtime contract, not a general SDK authoring guide.
- Security and authority.
- Requirements and installation.
- Configuration: strict
file validation and schema.
- Desktop session environment and tool confirmation.
- Streamable HTTP configuration.
- Digest-pinned trusted project configuration.
- Enforced default bounds.
- Streamable HTTP framing and recovery, subject to the remaining closure gates.
- Catalogs, calls, and results: epochs, cancellation, schemas and media.
- Lifecycle, health, and recovery.
- TUI and Serve presentation: owner-fenced state, not a separate manager.
- Tests: documented fixtures, not live remote-transport qualification.