|
| 1 | +# fduty safari — command card |
| 2 | + |
| 3 | +Prereq: `SKILL.md` read. This is the **AI-SRE platform self-management** group: install/configure the account's own **MCP servers (connectors)**, **skills**, and **A2A agents**, plus inspect **sessions**. Mutating verbs (`create`, `update`, `delete`, `upload`) change account configuration — confirm before running. `delete` is **irreversible**. |
| 4 | + |
| 5 | +> Registering an MCP server is THIS group (`fduty safari mcp-server-create`) — **not** a tool search. A tool search only discovers callable tools on servers already connected to you; it can neither register nor configure one. |
| 6 | +
|
| 7 | +## Route here when |
| 8 | + |
| 9 | +"安装 / 添加 / 配置 MCP / connector / 连接器 / install mcp / add mcp server / 上传 skill / 自定义 skill / skill upload / A2A agent / customize / AI-SRE 平台配置 / session 导出" → **safari**. Key IDs: **`server_id`** (`mcp_…`) from `mcp-server-list`; **`skill_id`** from `skill-list`; **`agent_id`** from `a2a-agent-list`; **`session_id`** (`sess_…`). |
| 10 | + |
| 11 | +## Intent → verb |
| 12 | + |
| 13 | +| want | verb | |
| 14 | +|---|---| |
| 15 | +| list MCP servers / connectors | `mcp-server-list` | |
| 16 | +| install / register an MCP server | `mcp-server-create` | |
| 17 | +| change an MCP server's config | `mcp-server-update` | |
| 18 | +| turn an MCP server on / off | `mcp-server-enable` / `mcp-server-disable` | |
| 19 | +| inspect one MCP server (+ live tool probe) | `mcp-server-get` | |
| 20 | +| remove an MCP server | `mcp-server-delete` | |
| 21 | +| list / upload / update a skill | `skill-list` / `skill-upload` / `skill-update` | |
| 22 | +| enable / disable / delete a skill | `skill-enable` / `skill-disable` / `skill-delete` | |
| 23 | +| list / create / update an A2A agent | `a2a-agent-list` / `a2a-agent-create` / `a2a-agent-update` | |
| 24 | +| enable / disable / delete an A2A agent | `a2a-agent-enable` / `a2a-agent-disable` / `a2a-agent-delete` | |
| 25 | +| list / get / export / delete a session | `session-list` / `session-get` / `session-export` / `session-delete` | |
| 26 | + |
| 27 | +## Hot flow — install an MCP server |
| 28 | + |
| 29 | +Pass the nested `env` / `headers` objects through `--data` (they have no scalar flags); `args` has a repeatable `--args` flag but is shown via `--data` below for one-line copy-paste. |
| 30 | + |
| 31 | +```bash |
| 32 | +# stdio (local process): command + args + secrets via env |
| 33 | +fduty safari mcp-server-create --data '{"server_name":"GitHub Tools","transport":"stdio","description":"Read issues and pull requests from GitHub.","command":"npx","args":["-y","@modelcontextprotocol/server-github"],"env":{"GITHUB_TOKEN":"ghp_xxx"},"team_id":0,"status":"enabled"}' |
| 34 | + |
| 35 | +# remote (streamable-http) with per-user OAuth — oauth_metadata stays empty (auto-discovered + DCR at runtime) |
| 36 | +fduty safari mcp-server-create --data '{"server_name":"Aliyun OpenAPI","transport":"streamable-http","description":"Alibaba Cloud OpenAPI MCP.","url":"https://openapi-mcp.example.com/mcp","auth_mode":"per_user_oauth","team_id":0,"status":"enabled"}' |
| 37 | + |
| 38 | +# confirm it registered, then inspect its live tool catalogue |
| 39 | +fduty safari mcp-server-list --output-format toon |
| 40 | +fduty safari mcp-server-get --data '{"server_id":"mcp_xxx"}' |
| 41 | +``` |
| 42 | + |
| 43 | +<!-- GENERATED:safari START · 由 fduty __dump-commands 同步 · 勿手改 fence 内 --> |
| 44 | + |
| 45 | +### a2a-agent-create |
| 46 | +Create A2A agent |
| 47 | +- `--agent-name` string (required) — Agent display name. (≤128 chars) |
| 48 | +- `--auth-mode` string — Authentication mode: shared (default), per_user_secret, or per_user_oauth. |
| 49 | +- `--auth-type` string — Authentication type for the remote agent. |
| 50 | +- `--card-url` string (required) — URL of the remote agent card. |
| 51 | +- `--description` string — Agent description. |
| 52 | +- `--oauth-metadata` string — JSON OAuth metadata; reserved for per_user_oauth. |
| 53 | +- `--secret-schema` string — JSON secret schema; required when auth_mode=per_user_secret. |
| 54 | +- `--streaming` bool — Whether the remote agent supports streaming. |
| 55 | +- `--team-id` int64 — Team scope: 0 = account-wide; >0 = team. |
| 56 | +- body-only (`--data`): auth_config (object) |
| 57 | + |
| 58 | +### a2a-agent-delete <agent-id> |
| 59 | +Delete A2A agent |
| 60 | +- `<agent-id>` (positional, required) string — Target agent ID. |
| 61 | + |
| 62 | +### a2a-agent-disable <agent-id> |
| 63 | +Disable A2A agent |
| 64 | +- `<agent-id>` (positional, required) string — Target agent ID. |
| 65 | + |
| 66 | +### a2a-agent-enable <agent-id> |
| 67 | +Enable A2A agent |
| 68 | +- `<agent-id>` (positional, required) string — Target agent ID. |
| 69 | + |
| 70 | +### a2a-agent-get <agent-id> |
| 71 | +Get A2A agent detail |
| 72 | +- `<agent-id>` (positional, required) string — Target agent ID. |
| 73 | + |
| 74 | +### a2a-agent-list |
| 75 | +List A2A agents |
| 76 | +- `--include-account` bool — Include account-scoped (team_id=0) rows. Defaults to true. |
| 77 | +- `--limit` int64 — Page size. |
| 78 | +- `--offset` int64 — Row offset for pagination. |
| 79 | +- `--team-ids` intSlice — Filter to these team IDs; empty = the caller's visible set. |
| 80 | + |
| 81 | +### a2a-agent-update <agent-id> |
| 82 | +Update A2A agent |
| 83 | +- `<agent-id>` (positional, required) string — Target agent ID. |
| 84 | +- `--agent-name` string — New display name. Omit to leave unchanged. (≤128 chars) |
| 85 | +- `--auth-mode` string — New auth mode: shared, per_user_secret, or per_user_oauth. |
| 86 | +- `--auth-type` string — New auth type. Omit to leave unchanged. |
| 87 | +- `--card-url` string — New card URL. Omit to leave unchanged. |
| 88 | +- `--description` string — New description. Omit to leave unchanged. |
| 89 | +- `--oauth-metadata` string — New JSON OAuth metadata. |
| 90 | +- `--secret-schema` string — New JSON secret schema. |
| 91 | +- `--streaming` bool — Toggle streaming support. Omit to leave unchanged. |
| 92 | +- `--team-id` int64 — Reassign team scope. Omit to leave unchanged. |
| 93 | +- body-only (`--data`): auth_config (object) |
| 94 | + |
| 95 | +### mcp-server-create |
| 96 | +Create MCP server |
| 97 | +- `--args` stringSlice — Command arguments (stdio transport). |
| 98 | +- `--auth-mode` string — Authentication mode: shared (default), per_user_secret, or per_user_oauth. |
| 99 | +- `--call-timeout` int64 — Tool-call timeout in seconds. 0 = default (60s). |
| 100 | +- `--command` string — Executable command (stdio transport). |
| 101 | +- `--connect-timeout` int64 — Connection timeout in seconds. 0 = default (10s). |
| 102 | +- `--description` string (required) — Server description. (1-1024 chars) |
| 103 | +- `--oauth-metadata` string — JSON OAuth metadata; reserved for per_user_oauth. |
| 104 | +- `--secret-schema` string — JSON secret schema; required when auth_mode=per_user_secret. |
| 105 | +- `--server-name` string (required) — MCP server name, unique within the account. (1-255 chars) |
| 106 | +- `--source-template-name` string — Marketplace template name when created from a connector template. |
| 107 | +- `--status` string — Initial status. · enum: enabled | disabled |
| 108 | +- `--team-id` int64 — Team scope: 0 = account-wide; >0 = team. |
| 109 | +- `--transport` string (required) — Transport protocol. · enum: stdio | sse | streamable-http |
| 110 | +- `--url` string — Server URL (sse / streamable-http transport). |
| 111 | +- body-only (`--data`): env (object); headers (object) |
| 112 | + |
| 113 | +### mcp-server-delete <server-id> |
| 114 | +Delete MCP server |
| 115 | +- `<server-id>` (positional, required) string — Target MCP server ID. |
| 116 | + |
| 117 | +### mcp-server-disable <server-id> |
| 118 | +Disable MCP server |
| 119 | +- `<server-id>` (positional, required) string — Target MCP server ID. |
| 120 | + |
| 121 | +### mcp-server-enable <server-id> |
| 122 | +Enable MCP server |
| 123 | +- `<server-id>` (positional, required) string — Target MCP server ID. |
| 124 | + |
| 125 | +### mcp-server-get <server-id> |
| 126 | +Get MCP server detail |
| 127 | +- `<server-id>` (positional, required) string — Target MCP server ID. |
| 128 | + |
| 129 | +### mcp-server-list |
| 130 | +List MCP servers |
| 131 | +- `--include-account` bool — Include account-scoped (team_id=0) rows. Defaults to true. |
| 132 | +- `--limit` int64 — Page size. |
| 133 | +- `--page` int64 — Page number, 1-based. |
| 134 | +- `--search-after-ctx` string |
| 135 | +- `--team-ids` intSlice — Filter to these team IDs; empty = the caller's visible set. |
| 136 | + |
| 137 | +### mcp-server-update <server-id> |
| 138 | +Update MCP server |
| 139 | +- `--args` stringSlice — Command arguments (stdio transport). |
| 140 | +- `--auth-mode` string — Authentication mode: shared (default), per_user_secret, or per_user_oauth. |
| 141 | +- `--call-timeout` int64 — Tool-call timeout in seconds. 0 = default (60s). |
| 142 | +- `--command` string — Executable command (stdio transport). |
| 143 | +- `--connect-timeout` int64 — Connection timeout in seconds. 0 = default (10s). |
| 144 | +- `--description` string — New description. (1-1024 chars) |
| 145 | +- `--oauth-metadata` string — JSON OAuth metadata; reserved for per_user_oauth. |
| 146 | +- `--secret-schema` string — JSON secret schema; required when auth_mode=per_user_secret. |
| 147 | +- `<server-id>` (positional, required) string — Target MCP server ID. |
| 148 | +- `--server-name` string — New name. (1-255 chars) |
| 149 | +- `--team-id` int64 — Reassign team scope: 0 = account-wide; >0 = team. Omit to leave unchanged. |
| 150 | +- `--transport` string — Transport protocol. · enum: stdio | sse | streamable-http |
| 151 | +- `--url` string — Server URL (sse / streamable-http transport). |
| 152 | +- body-only (`--data`): env (object); headers (object) |
| 153 | + |
| 154 | +### session-delete <session-id> |
| 155 | +Delete session |
| 156 | +- `<session-id>` (positional, required) string — Target session ID. (≥1 chars) |
| 157 | + |
| 158 | +### session-export <session_id> |
| 159 | +Stream a session's full event transcript as NDJSON |
| 160 | +- `--include-subagents` bool |
| 161 | + |
| 162 | +### session-get <session-id> |
| 163 | +Get session detail |
| 164 | +- `--limit` int64 — Page size for events; takes precedence over 'num_recent_events'. 0 uses the server default (100). (0-1000) |
| 165 | +- `--num-recent-events` int64 — Legacy page size: number of most-recent events to return. Superseded by 'limit' when both are set; 0 uses the server default (100). (0-1000) |
| 166 | +- `--search-after-ctx` string — Opaque keyset cursor from a previous response; pass it back to fetch the next older page. (≤4096 chars) |
| 167 | +- `<session-id>` (positional, required) string — Target session ID. (≥1 chars) |
| 168 | + |
| 169 | +### session-list |
| 170 | +List sessions |
| 171 | +- `--app-name` string (required) — Agent app whose sessions to list. · enum: ask-ai | support | support-website | support-flashcat | ai-sre | template-assistant | swe |
| 172 | +- `--asc` bool — Ascending order when true; applies only when 'orderby' is set. |
| 173 | +- `--entry-kinds` stringSlice — Restrict to sessions produced by these surfaces; empty returns every kind. · enum: web | im | api | automation |
| 174 | +- `--include-subagent-sessions` bool — Include subagent-dispatched sessions in the list. |
| 175 | +- `--keyword` string — Filter by session-name keyword. (≤64 chars) |
| 176 | +- `--limit` int64 — Page size, 1–100. (1-100) |
| 177 | +- `--orderby` string — Sort field. · enum: created_at | updated_at |
| 178 | +- `--page` int64 — Page number, 1-based. (min 1) |
| 179 | +- `--scope` string — Visibility scope: all (own + member-of-team rows, default), personal, or team. · enum: all | personal | team |
| 180 | +- `--search-after-ctx` string |
| 181 | +- `--status` string — Archive bucket: active (default) returns un-archived, archived returns archived, all returns both. · enum: active | archived | all |
| 182 | +- `--team-ids` intSlice — Optional explicit team filter; intersects with 'scope'. |
| 183 | + |
| 184 | +### skill-delete <skill-id> |
| 185 | +Delete skill |
| 186 | +- `<skill-id>` (positional, required) string — Target skill ID. |
| 187 | + |
| 188 | +### skill-disable <skill-id> |
| 189 | +Disable skill |
| 190 | +- `<skill-id>` (positional, required) string — Target skill ID. |
| 191 | + |
| 192 | +### skill-enable <skill-id> |
| 193 | +Enable skill |
| 194 | +- `<skill-id>` (positional, required) string — Target skill ID. |
| 195 | + |
| 196 | +### skill-get <skill-id> |
| 197 | +Get skill detail |
| 198 | +- `<skill-id>` (positional, required) string — Target skill ID. |
| 199 | + |
| 200 | +### skill-list |
| 201 | +List skills |
| 202 | +- `--include-account` bool — Include account-scoped (team_id=0) rows. Defaults to true. |
| 203 | +- `--limit` int64 — Page size. |
| 204 | +- `--page` int64 — Page number, 1-based. |
| 205 | +- `--search-after-ctx` string |
| 206 | +- `--team-ids` intSlice — Filter to these team IDs; empty = the caller's visible set. |
| 207 | + |
| 208 | +### skill-update <skill-id> |
| 209 | +Update skill |
| 210 | +- `--description` string — New description. (≤1024 chars) |
| 211 | +- `<skill-id>` (positional, required) string — Target skill ID. |
| 212 | +- `--team-id` int64 — Reassign team scope: 0 = account-wide; >0 = team. Omit to leave unchanged. |
| 213 | + |
| 214 | +### skill-upload |
| 215 | +Upload skill |
| 216 | + |
| 217 | +<!-- GENERATED:safari END --> |
| 218 | + |
| 219 | +## Key concepts |
| 220 | + |
| 221 | +- **Transport ⇒ which fields matter.** `stdio` uses `command` + `args` + `env`; `sse` / `streamable-http` use `url` + `headers`. The nested `env` / `headers` objects have no scalar flags — pass them through `--data '{...}'`; typed scalar flags (`--server-name`, `--url`, `--args`, …) override matching `--data` keys. |
| 222 | +- **Scope (`team_id`).** `0` = account-wide (every team sees it); `>0` = that team only. Same field on every safari verb. |
| 223 | +- **Auth mode (`auth_mode`).** `shared` (default) = one credential for everyone, stored on the server. `per_user_secret` = each user supplies a secret matching `secret_schema` (which must carry a `header_name`). `per_user_oauth` = each user authorizes the server via OAuth. |
| 224 | +- **`per_user_oauth` needs no OAuth config up front.** Create it with an **empty `oauth_metadata`** — that is the normal, complete state, not a missing prerequisite. The runtime **auto-discovers the OAuth server and dynamically registers a client (DCR)** the first time a user authorizes; you do **not** collect `authorization_url` / `client_id` / `client_secret` / `scopes`. Only pass `oauth_metadata` as a rare fallback, when the endpoint advertises no discovery document. |
| 225 | + |
| 226 | +## Gotchas |
| 227 | + |
| 228 | +- **`mcp-server-create` requires `server_name`, `description`, `transport`.** A `stdio` server also needs `command`; a remote (`sse` / `streamable-http`) server needs `url`. |
| 229 | +- **`env` / `headers` go through `--data`** — there are no `--env` / `--header` scalar flags for them (`args` does have a repeatable `--args` flag). |
| 230 | +- **Don't reach for a tool search to install or configure a server** — that only finds tools on already-connected servers. Registration and configuration are `mcp-server-create` / `mcp-server-update`. |
| 231 | +- **`delete` is irreversible** — prefer `disable` to park a server / skill / agent without destroying it. `list` first to confirm the id. |
0 commit comments