Skip to content

cloudg mcp call

Calls one MCP tool in-process and prints its result. The policy, privacy transforms and middleware apply exactly as they would for a client.

cloudg mcp call is the quickest way to try a tool, debug a policy, or use a tool from a shell script. No server runs and no client is needed.

Usage

cloudg mcp call [OPTIONS] TOOL

Options

Flag Value Default Description
TOOL (argument) TEXT none Required.
--args JSON @FILE - none Tool arguments as a JSON object, @file.json, or - for stdin.
--raw flag off Print the full MCP CallToolResult.
--principal-id TEXT none Principal id to call as.
--role TEXT none Call as a principal with this role (repeatable; default: the local user). Repeatable.
-c, --config TEXT none cloudg config.yaml (defaults to the parent command's config).
--policy TEXT none Policy profile name, or a YAML/JSON policy file. Environment: CLOUDG_MCP_POLICY.
--dataset [NAME=]PATH none Preload a dataset (findings.json, inventory-map.json...). Repeatable. Repeatable.
--prefix TEXT `` Prefix for tool and prompt names.
--include-category TEXT none Only expose these categories. Repeatable. Repeatable.
--exclude-category TEXT none Hide these categories. Repeatable. Repeatable.
--include-tool TEXT none Only expose these tools. Repeatable. Repeatable.
--exclude-tool TEXT none Hide these tools. Repeatable. Repeatable.
--read-only flag off Drop tools that write files, call cloud APIs, run scanners or are destructive.
--audit-log FILE none Append a JSONL audit trail (argument values are hashed). Environment: CLOUDG_MCP_AUDIT_LOG.
--timeout FLOAT 300.0 Per-call timeout in seconds.
--registry MODULE:ATTR none Serve a custom Registry (or a zero-argument factory returning one) instead of the built-in catalog.

Generated from the click definition in /opt/hostedtoolcache/Python/3.12.15/x64/lib/python3.12/site-packages/cloudg/mcp/cli.py, so it matches cloudg mcp call --help.

How it works

Each invocation builds a fresh layer from the shared options (see cloudg mcp serve), calls TOOL once as the chosen principal, prints the result and exits. Nothing carries over between invocations. A load_dataset call in one command is gone by the next, so pass the data you need with --dataset every time.

Arguments go in --args as a JSON object. You have three ways to supply it:

Form Example
Inline JSON --args '{"ref": "bastion"}'
A file, prefixed with @ --args @args.json (a leading ~ is expanded)
stdin --args -

Anything that is not a JSON object is refused before the tool runs, with Invalid value for --args: not valid JSON: ... or must be a JSON object and exit code 2. Without --args, the tool is called with no arguments.

The principal is the local user unless you pass --role or --principal-id, as on cloudg mcp tools. A tool the policy hides from that principal behaves as if it did not exist.

What gets printed depends on the result and on --raw:

Result Printed on stdout
Has structured content The structured content, as indented JSON
Text only Each text block as is; any other block as JSON
--raw The whole CallToolResult: content, isError, structuredContent and _meta

--raw is the way to see what the policy added. Under the default standard policy, _meta carries a cloudg/transforms entry with the result's sensitivity and provenance, and cloudg/duration_ms.

A tool that fails returns isError: true rather than raising. call prints that result like any other and then exits with 1, which makes it usable in if statements. Here a typo in an asset reference returns suggestions in the error data:

$ cloudg mcp call get_asset --dataset prod=inventory/inventory-map.json --args '{"ref": "bastoin"}' --raw
{
  "content": [
    {
      "type": "text",
      "text": "No asset matches the reference in this dataset. 2 close matches, see suggestions in the error data. Use find_assets(query=...) to search by name, ARN or tag."
    }
  ],
  "isError": true,
  "_meta": {
    "cloudg/error_code": -32602,
    "cloudg/error_data": {
      "value": "bastoin",
      "dataset": "prod",
      "suggestions": [
        {"id": "bastion", "name": "bastion", "type": "EC2", ...},
        {"id": "admin-role", "name": "bastion-admin", "type": "IAM_ROLE", ...}
      ]
    }
  }
}
$ echo $?
1

(Suggestion objects shortened; they also carry arn, account_id and dataset.) This and the next capture use the synthetic estate from tests/mcp/fixtures/sample_estate.py.

stdout carries only the result. The banner and logs go to stderr, so | jq works.

Live tools

map_inventory, collect_assets, run_scanners and run_pipeline call the cloud. From call they use the cloud settings and credentials of the config given with -c (on mcp call or on the root cloudg), and they run their credential preflight before anything else. Their own timeouts (one or two hours) replace the 300-second default of --timeout. A policy or --read-only that drops them makes them unknown.

Examples

See what is loaded and where tools may read and write:

cloudg mcp call workspace_status

Search a saved map and keep only two fields per asset:

$ cloudg mcp call find_assets --dataset prod=inventory/inventory-map.json --args '{"query": "bastion", "fields": ["name", "type"]}'
{
  "dataset": "prod",
  "total": 2,
  "offset": 0,
  "returned": 2,
  "next_cursor": null,
  "truncated": false,
  "items": [
    {
      "id": "bastion",
      "name": "bastion",
      "type": "EC2"
    },
    {
      "id": "admin-role",
      "name": "bastion-admin",
      "type": "IAM_ROLE"
    }
  ]
}

Count assets by type, with the arguments in a file:

echo '{"group_by": "type", "top": 10}' > count.json
cloudg mcp call count_assets --dataset prod=./reports/inventory-map.json --args @count.json

Build the arguments in a script and pipe them in:

jq -n --arg ref "arn:aws:iam::123456789012:role/app-role" '{ref: $ref, max_depth: 5}' \
  | cloudg mcp call blast_radius --dataset prod=./reports/inventory-map.json --args -

Check whether an analyst could call a tool under your policy:

cloudg mcp call get_asset_metadata --policy ./mcp-policy.yaml --role analyst --dataset prod=./reports/inventory-map.json --args '{"ref": "bastion"}'

Stop a script when a tool reports an error:

if ! cloudg mcp call get_asset --dataset prod=./reports/inventory-map.json --args '{"ref": "orders-db"}' > orders-db.json; then
  echo "lookup failed, see orders-db.json" >&2
  exit 1
fi

Exit codes

Code When
0 The tool ran and returned isError: false
1 The tool returned isError: true; the tool is unknown or hidden (Error: Unknown tool: NAME); or the layer could not be built
2 --args is not a JSON object, or another option was rejected