Skip to content

Latest commit

 

History

History
465 lines (366 loc) · 20.1 KB

mcp.md

File metadata and controls

465 lines (366 loc) · 20.1 KB

MCP Server

The smbCloud CLI can run as a Model Context Protocol (MCP) server, so an AI assistant or agent — Claude Desktop, Claude Code, Cursor, or any other MCP-capable client — can send transactional email and manage your smbCloud projects, tenants, Mail apps, and Auth apps directly, without you leaving the chat to run smb commands by hand. Start it with smb --mcp; it speaks standard MCP over stdio and exposes 41 tools covering the account, project, deploy, tenant, Mail, and Auth surfaces.

Cross-platform mobile and TV app testing is exposed as a separate, focused MCP profile through xcrs --mcp or smb --mcp --scope automation. Keeping cloud and device tools in separate profiles makes tool selection more predictable for agents.

This page is the setup guide and the full tool reference. For how --mcp compares to the CLI's other two interfaces (headless and --tui), see Interfaces. The server is also listed in the official MCP Registry as io.github.smbcloudXYZ/smbcloud-cli, so clients that browse the registry can install it for you — see MCP Registry. For building and starting the native runners, see ControlKit runners.

Prerequisites

  1. Install the CLI (smb --version should print something).

  2. Log in once, headlessly — the MCP server itself is non-interactive and can't run the login flow:

    smb login

    This writes a token to ~/.smb/token (~/.smb-dev/token in the dev environment). Every MCP tool call reuses that token; there's nothing client-specific to configure for auth.

Connect your client

Every MCP client ultimately does the same thing: run smb --mcp as a subprocess and speak JSON-RPC over its stdin/stdout. The differences are in where each client wants that command declared.

Claude Desktop

Edit your Claude Desktop config — ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows — and add an entry under mcpServers:

{
  "mcpServers": {
    "smbcloud": {
      "command": "smb",
      "args": ["--mcp"]
    }
  }
}

Restart Claude Desktop. The tools listed below become available in any chat.

Claude Code

claude mcp add smbcloud -- smb --mcp

Or add it directly to your project's .mcp.json:

{
  "mcpServers": {
    "smbcloud": {
      "command": "smb",
      "args": ["--mcp"]
    }
  }
}

Cursor

Add the same shape to ~/.cursor/mcp.json (global) or .cursor/mcp.json (project-scoped):

{
  "mcpServers": {
    "smbcloud": {
      "command": "smb",
      "args": ["--mcp"]
    }
  }
}

Any other MCP client

If your client's config isn't listed above, it almost certainly still takes a command + args pair for a stdio server — point it at smb with --mcp exactly as shown above. That's the entire integration surface; there's no separate server to run or port to expose.

Targeting a local API during development

Add the global -e/--environment flag before --mcp to point the server at a local dev API instead of production:

{
  "mcpServers": {
    "smbcloud-dev": {
      "command": "smb",
      "args": ["-e", "dev", "--mcp"]
    }
  }
}

Session state: tenant and project selection

Several tools take an optional project_id, and project creation targets whichever tenant is currently selected. Two tools manage that selection:

  • tenant_use — selects a tenant (workspace) for the session. While selected, project_create targets it instead of your personal tenant.
  • project_use — selects a project for the session. Tools with an optional project_id (Mail apps, Auth apps) default to it when omitted. Pass frontend_app_id to select one of the project's frontend apps too.

Both persist to ~/.smb/config.toml (~/.smb-dev/config.toml in dev) — the same file smb tenant use / smb project use write from the terminal. Switch context in a chat with an agent, then run smb project list in a terminal a minute later, and it reflects the same selection. Selecting a tenant that the current project doesn't belong to clears the project selection, so a stale cross-tenant project_id can never linger silently.

Tools reference

Every tool returns structured JSON — a single object for _show/_new/ _update/_use, an array for _list. Fields are the CLI's own JSON models, not a separate MCP-specific shape.

Account

Tool Arguments Returns
me (none) The authenticated user.

Projects

Tool Arguments Returns
project_list (none) The user's projects.
project_show id A single project by ID.
project_use id, frontend_app_id (optional, must belong to the project) The selected project. Persists the selection (see above).
project_create name, description (optional) The created project. Targets the selected tenant, if any.
project_update id, description, runner (optional) The updated project. The runner is kept when omitted.
project_delete id Confirmation. Destructive and irreversible.
deployments project_id A project's deployments. On MCP Apps hosts it also renders a dashboard (see below).
deployment_show project_id, id A single deployment.

Frontend apps, deploy repos, and deploy config

A project holds a deploy repo (the git repository or monorepo root) and the frontend apps that ship from it. runner is one of node_js, static, ruby, swift, rust.

Tool Arguments Returns
frontend_app_list project_id The project's frontend apps.
frontend_app_show id A single frontend app.
frontend_app_new project_id, name, source_path (optional), runner (optional, default node_js) The created frontend app.
deploy_repo_new project_id, repository, repo_kind (single_app or monorepo), runner (optional) The created repo. A single-app repo embeds the app it creates.
deploy_config_show frontend_app_id The app's server-side deploy config.
deploy_config_update frontend_app_id, plus any of runner, deployment_method (git or rsync), kind, source_path, remote_path, package_manager, pm2_app, port, output_path, build_command, install_command, binary_name, build_target, shared_lib_path The updated config. Only the fields passed change.

Local tools (project_init, deploy, migrate)

These act on a directory on the machine running smb --mcp, so each takes an explicit absolute cwd. They never prompt: anything the interactive CLI would ask is an argument, or the call fails with a message saying what is missing.

Tool Arguments Returns
project_init cwd, name, description (optional), repository, repo_kind, runner, apps (name, source_path, runner), overwrite (all optional) The project, its first app, and the written config path. Writes <cwd>/.smb/config.toml. Refuses to replace an existing config unless overwrite is true.
deploy cwd, project (optional monorepo sub-project) { success, exit_code, output_tail }.
migrate cwd { success, exit_code, output_tail }.

deploy and migrate need an existing .smb/config.toml in cwd (run project_init first). deploy builds locally, pushes to the server, and restarts the app, so it can take minutes; the call returns when it finishes.

Both run the smb binary itself as a child process in cwd with --ci, rather than in the MCP process. The deploy paths use paths relative to the working directory and print progress to stdout, which in an MCP session is the JSON-RPC channel. output_tail is the last 200 lines of combined output with colors and spinner frames removed. The call is flagged as an error when the command exits non-zero.

Interactive views (MCP Apps)

Three tools declare an MCP Apps view. Hosts that support the extension, such as Claude and ChatGPT, render it in a sandboxed frame next to the result:

  • deployments → ui://smbcloud/deployments.html: a table of deployments with status, app, commit, and created/updated times, newest first, plus a Refresh button.

  • mail_message_list → ui://smbcloud/inbox.html: the inbox as a table (from, subject, preview, received, forward status). Click a row to open the message, which calls mail_message_show; Back returns to the list and Refresh reloads it. Only the plain-text body is shown, never html_body.

  • auth_app_show and auth_app_new → ui://smbcloud/auth-app.html: a setup card with the client ID (copy), the client secret (masked, with Reveal and Copy), the support email, and a Sign in with Apple checklist. The secret is only present when the API returns it.

List views show the newest 50 rows. Other clients see the same JSON result as before. Each view is a single self-contained HTML document that makes no network requests; Refresh and drill-in go back through the host with a tools/call. Tool _meta carries the view URI under both ui.resourceUri and the legacy ui/resourceUri key, since older hosts read only the flat one.

Tenants

A tenant is a workspace — your personal one, or an organization you belong to. tenant_new/tenant_delete only apply to organization tenants; the personal tenant is bootstrapped on signup and isn't user-managed.

Tool Arguments Returns
tenant_list (none) The user's tenants, with role and project count.
tenant_show id A single tenant by ID.
tenant_use id The selected tenant. Persists the selection (see above).
tenant_new name The created organization tenant.
tenant_update id, name The renamed tenant.
tenant_delete id Confirmation. Destructive and irreversible — cascades to every project, Mail app, and Auth app the tenant owns.

Mail apps

A Mail app owns one domain's mail routing; it belongs to a project.

Tool Arguments Returns
mail_list project_id (optional, defaults to the selected project) The user's Mail apps.
mail_show id A single Mail app by ID.
mail_new name, domain, project_id (optional), aws_region (optional) The created Mail app.
mail_update id, name/domain/aws_region (at least one) The updated Mail app.
mail_delete id Confirmation. Destructive and irreversible.

Sending email

Tool Arguments Returns
mail_send from, to, subject/html/text/cc/bcc/reply_to/idempotency_key (optional; one of html or text required) The sent message with its delivery status.

mail_send is the one tool that does not use the smb login session. The send API authenticates with a Mail app API key scoped to that app's verified sending domain, so the key has to reach the server through its environment:

{
  "mcpServers": {
    "smbcloud": {
      "command": "smb",
      "args": ["--mcp"],
      "env": { "SMB_MAIL_API_KEY": "smb_mail_your_key" }
    }
  }
}

Mint the key for your Mail app in the smbCloud console. Without it, mail_send fails with a message saying so and every other tool keeps working.

Reuse an idempotency_key and the original message comes back instead of a second send, which is what you want when an agent retries after a timeout.

Mail inboxes

An inbox route forwards mail arriving at one address under a Mail app's domain.

Tool Arguments Returns
mail_inbox_new app_id, local_part, forward_to_email, sender_email (optional) The created inbox route.
mail_inbox_update app_id, id, local_part/forward_to_email/sender_email (at least one) The updated inbox route.
mail_inbox_delete app_id, id Confirmation. Destructive and irreversible.
mail_inbox_test app_id, id, recipient_email/subject/body (all optional) The test delivery result.

Mail messages

Read-only access to an inbox's stored inbound message history.

Tool Arguments Returns
mail_message_list app_id, inbox_id, limit (optional, default 10) Recent inbound messages, newest first.
mail_message_show app_id, inbox_id, id A single inbound message.

Auth apps

An Auth app is a hosted identity/sign-in service for your own product's end users; it belongs to a project.

Tool Arguments Returns
auth_app_list project_id (optional, defaults to the selected project) The user's Auth apps.
auth_app_show id A single Auth app by ID.
auth_app_new name, project_id (optional), support_email (optional) The created Auth app.
auth_app_update id, name/support_email (at least one) The updated Auth app.
auth_app_delete id Confirmation. Destructive and irreversible.

Mobile and TV app automation

Start a dedicated automation server instead of mixing device tools into the cloud profile:

smb --mcp --scope automation
# or install the smaller standalone crate:
xcrs --mcp

Installing xcrs: the standalone binary is published to crates.io — install it with cargo install xcrs. It is not distributed through Homebrew; brew install smbcloud-cli only provides the smb binary (use smb --mcp --scope automation for the same tools without a separate install).

Both commands expose the same target-aware tools with the same names. Tool names do not repeat the server brand because MCP clients already namespace them by server.

Recommended flow:

  1. Call device_list to discover Apple simulators and adb-connected Android phones, tablets, emulators, and TV devices.
  2. Call device_select with the Apple simulator/runner details or Android adb serial. Later actions use that target by default.
  3. Call device_capabilities before choosing an input or inspection action.
  4. Use screen_capture or ui_describe/ui_element_list to inspect the app, then use semantic ui_tap or the raw input_* tools.
Tool Purpose
device_list Discover available Apple simulators and Android adb devices.
device_select Remember the Apple or Android target used by later actions.
device_capabilities Report the selected target's supported automation operations.
app_install_launch Boot, install, and launch an iOS simulator app bundle.
app_launch / app_terminate Start or stop an installed app on the selected target.
screen_capture Capture the selected target as a PNG image.
url_open Open an HTTP(S) URL or custom scheme where the target supports it.
ui_describe / ui_element_list / ui_tap Inspect or activate accessible elements through ControlKit (Apple) or AndroidKit (Android).
input_tap / input_text / input_swipe / input_button Drive shared touch, text, gesture, and button actions.
input_click Click a macOS target with pointer coordinates.
input_spatial_tap Perform a visionOS spatial tap.
orientation_get / orientation_set Read or update orientation where supported.

See ControlKit runners for Apple runner setup and XCRS AndroidKit for Android semantic UI automation. Android tools require adb and an authorized device; Android TV app launches resolve the device's Leanback launcher activity.

Automation migration in 0.5.0

The automation profile is a clean breaking replacement. Old Apple-default and Android-prefixed names are not exposed as aliases because duplicate tools make agent selection less reliable.

Previous tools Replacement
smb_list_simulators, smb_android_device_list device_list
smb_use_target device_select
smb_capabilities device_capabilities
smb_boot_and_install app_install_launch
smb_launch_app, smb_android_app_launch app_launch
smb_terminate_app, smb_android_app_terminate app_terminate
smb_screenshot, smb_android_screenshot screen_capture
smb_open_url, smb_android_open_url url_open
smb_describe_ui ui_describe
smb_list_elements ui_element_list
smb_tap, smb_android_tap input_tap
smb_type_text, smb_android_type_text input_text
smb_swipe, smb_android_swipe input_swipe
smb_button, smb_android_press_button input_button
smb_click input_click
smb_gesture input_spatial_tap
smb_orientation_get orientation_get
smb_orientation_set orientation_set

The standalone server makes the same replacement without the former xcrs_ prefix.

Safety: tools run without confirmation

The CLI's own project delete, tenant delete, and similar commands ask for confirmation on a terminal — some require typing the resource's name back. MCP tools skip that entirely. Destructive tools carry the destructiveHint annotation so clients can prompt you, but the server itself does not ask. MCP is a non-interactive protocol, so a *_delete tool call executes immediately the moment the client sends it. The calling agent — and the person directing it — is responsible for confirming intent before invoking a destructive tool, exactly as with any other irreversible action an assistant can take on your behalf.

If you want a harder guardrail, keep destructive operations out of an agent's reach at the client level (most MCP clients let you allow/deny individual tools per server) rather than relying on the server to ask twice.

Not exposed as tools

These stay in the terminal on purpose:

  • login, signup, logout, account forgot. They take credentials or end the session, and a password should not pass through a chat. Tools that need a session tell you to run smb login.
  • control-kit. Device automation lives in its own profile (--scope automation, above).

Talking to it directly

You don't need an MCP client to try this — the server reads newline-delimited JSON-RPC on stdin and writes responses on stdout. Diagnostics go to stderr and logging goes to the on-disk log file, so stdout stays a clean protocol channel end to end. A minimal handshake plus a tool listing:

printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
  | smb --mcp

A tool call names the tool and its arguments:

{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"project_show","arguments":{"id":"<id>"}}}

FAQ

Does the MCP server need a different install than the regular CLI? No — smb --mcp is the same binary you already use for smb deploy, smb project list, and so on. There's nothing extra to install.

Do I need to log in separately for MCP? No. Log in once with smb login on a terminal; every interface (headless, --tui, --mcp) reads the same token from ~/.smb/token. The one exception is mail_send, which needs a Mail app API key in SMB_MAIL_API_KEY because the send API authenticates per sending domain rather than per user.

Can I run multiple smbCloud MCP servers for different environments? Yes — register two entries with different args (e.g. one with -e dev, one without) under different names, as shown above.

Does selecting a tenant or project in an agent chat affect my terminal? Yes, and vice versa — tenant_use/project_use write to the same ~/.smb/config.toml the CLI itself reads, so the two stay in sync.

Is the MCP server safe to point an autonomous agent at? Every write tool, including every *_delete tool and deploy, executes immediately with no confirmation prompt, since MCP is non-interactive by design. Treat tool access the way you'd treat handing someone your terminal with smb already logged in: fine for a trusted agent you're directing, not something to expose unsupervised.