Metadata-Version: 2.4
Name: guzli-cli
Version: 0.2.0
Summary: AI voice calling CLI and MCP server for agents using Guzli.
Author: Guzli
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/kodeine/guzli-cli
Project-URL: Documentation, https://github.com/kodeine/guzli-cli#readme
Project-URL: Repository, https://github.com/kodeine/guzli-cli
Project-URL: Issues, https://github.com/kodeine/guzli-cli/issues
Project-URL: Changelog, https://github.com/kodeine/guzli-cli/blob/main/CHANGELOG.md
Keywords: ai-agents,ai-voice,cli,mcp,model-context-protocol,outbound-calling,telephony
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Communications :: Telephony
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.31
Provides-Extra: mcp
Requires-Dist: mcp<2,>=1.28; extra == "mcp"
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: mypy>=1.15; extra == "dev"
Requires-Dist: pytest>=8.3; extra == "dev"
Requires-Dist: pytest-cov>=6; extra == "dev"
Requires-Dist: requests-mock>=1.12; extra == "dev"
Requires-Dist: ruff>=0.11; extra == "dev"
Requires-Dist: twine>=5.1; extra == "dev"
Dynamic: license-file

# Guzli CLI — AI voice calling and MCP server for agents

Guzli CLI is an open-source Python command-line interface and local Model
Context Protocol (MCP) server for AI voice calling. It connects AI agents to
Guzli so they can place one-off phone calls, launch outbound calling campaigns,
manage phone-number pools and voices, inspect call results, and work with inbox
conversations through structured CLI commands or MCP tools.

Use `guzli call` to call one person or as many as 1,000 recipients. Quick tasks
and larger voice campaigns use the same tested workflow, so an agent can order
food, reroute a delivery, confirm appointments, or contact a list of customers
without learning separate calling APIs.

> Calls are real and may be billable. Use `--dry-run` or MCP `dry_run=true` to
> validate recipients, number-pool selection, and voice configuration before
> dialing.

## Features

- **AI phone calls from the command line:** place a one-off outbound call with
  one `guzli call` command.
- **MCP server for AI agents:** expose typed calling, campaign, result, number,
  voice, and conversation tools to any MCP-compatible agent host.
- **One recipient or 1,000:** use repeatable `--to` arguments or a recipients
  file without switching workflows.
- **Structured automation:** return machine-readable JSON, stable identifiers,
  request metadata, and typed errors for reliable agent workflows.
- **Existing number-pool selection:** list, inspect, select, and save a default
  pool without creating new telephony resources implicitly.
- **Campaign and call-result inspection:** inspect runs, attempts, recordings,
  performance, and structured post-call extraction results.
- **Shared CLI and MCP implementation:** both interfaces call the same Python
  services and Guzli public API instead of duplicating orchestration logic.
- **No added CLI telemetry:** commands, prompts, phone numbers, transcripts,
  tokens, and profiles are not collected by the CLI itself.

## Common AI calling use cases

- Make a one-off operational call, such as ordering food or rerouting a package.
- Confirm appointments, reservations, deliveries, or service windows.
- Launch an outbound voice campaign for dozens or hundreds of recipients.
- Give each call instructions, an opening message, an objective, and structured
  post-call fields to extract.
- Let an AI agent discover number pools and voice profiles before placing calls.
- Inspect campaign runs and call outcomes before retrying interrupted work.
- Read Guzli inbox conversations and send agent replies.

## Installation

Python 3.10 or newer is required.

```bash
# CLI only
pipx install guzli-cli

# CLI plus MCP server
pipx install 'guzli-cli[mcp]'

# Alternative: install with uv
uv tool install 'guzli-cli[mcp]'
```

For development from a source checkout:

```bash
python -m venv .venv
.venv/bin/pip install -e '.[dev,mcp]'
.venv/bin/pytest
```

This repository is licensed under Apache-2.0. Release artifacts are published
to PyPI from GitHub Actions using short-lived trusted-publishing credentials.

## Authentication and configuration

The recommended setup is a persistent named profile:

```bash
guzli auth login
guzli auth status
guzli auth list
guzli auth use staging
```

Profiles live at `~/.guzli/config.json` with restricted permissions. You can
also configure:

```bash
export GUZLI_API_BASE_URL='https://gateway.guzli.com'
export GUZLI_API_KEY='your_workspace_api_key'
export GUZLI_AGENT_ID='your_agent_id'
export GUZLI_ORGANIZATION_ID='your_organization_id'
export GUZLI_NUMBER_POOL_ID='your_default_pool_id'  # optional
```

Resolution order is command-line flag, environment variable, stored profile,
then built-in default. OAuth bearer sessions are supported for user-only admin
routes. Ordinary routes accept either API-key or bearer auth, and agent replies
support identity-signing API keys.

The CLI adds no telemetry of its own. It does not send command text, prompts,
phone numbers, transcripts, tokens, or profile contents anywhere except as
required by the Guzli API operation the user invokes.

## Make an AI phone call from the CLI

`call` is the short, canonical entry point for quick work:

```bash
guzli call \
  --to +12025550123 \
  --message 'Hi, I am calling about a delivery.' \
  --instructions 'Ask FedEx to reroute package 123 to the saved alternate address.'
```

The descriptive long form is identical:

```bash
guzli campaigns launch \
  --to +12025550126 \
  --to +12025550127 \
  --instructions 'Confirm each appointment for Thursday.'
```

Use `--recipients-file recipients.txt` for larger batches. Recipients are
validated as E.164, deduplicated, and limited to 1,000. `--name` is optional.

These commands create real, potentially billable external calls by default.
Resolve and validate without mutations first when appropriate:

```bash
guzli call --to +12025550126 --instructions 'Order one large cheese pizza.' --dry-run
```

Useful options include `--message`, `--instructions`, `--objective`,
`--voice-profile-id`, `--voice-id`, `--number-pool-id`, `--from`,
`--extraction-file`, `--no-run`, and `--no-activate`. Run `guzli call --help`
for the complete surface.

### Number-pool selection

Campaign Launch only uses existing number pools; it never creates one
implicitly. Resolution is:

1. `--number-pool-id`
2. `GUZLI_NUMBER_POOL_ID`
3. saved default on the selected CLI profile
4. the existing pool containing `--from <E.164>`
5. the only eligible active pool

If more than one pool is eligible, the command stops and shows the choices.

```bash
guzli numbers pool list --is-active on
guzli numbers pool get <pool_id>
guzli numbers pool use <pool_id>      # save on the active profile
guzli auth status                     # displays the saved pool
```

### Intentional fast-launch compliance

Campaign Launch intentionally configures and approves a streamlined US
support-call profile so agents can make quick operational calls. Defaults are
advisory mode, automated-voice and recording disclosures off, spoken opt-out
on, quiet-hours enforcement off, and consent not required. Use the standalone
compliance commands for campaigns that need a different posture.

### Inspect the outcome

Every launch returns structured JSON including `launch_id`, state, recipient
count, campaign ID, pool ID and selection source, voice-profile ID, readiness,
and run response.

```bash
guzli campaigns runs <campaign_id>
guzli campaigns run-get <campaign_id> <run_id>
guzli campaigns run-cancel <campaign_id> <run_id>
guzli calls list <campaign_id> --campaign-run-id <run_id>
guzli calls get <campaign_id> <attempt_id>
guzli campaigns results list <campaign_id>
guzli campaigns results get <campaign_id> <result_id>
```

Launch is not atomically idempotent. If a request is interrupted, inspect its
campaign and run before retrying.

## Connect AI agents with the Guzli MCP server

Install the `mcp` extra, authenticate once, and configure the stdio server in
your agent host:

```json
{
  "mcpServers": {
    "guzli": {
      "command": "guzli-mcp",
      "env": {
        "GUZLI_PROFILE": "default"
      }
    }
  }
}
```

The server exposes typed, structured tools:

- `launch_calls`
- `list_number_pools`, `get_number_pool`, `list_phone_numbers`
- `list_voice_profiles`
- `get_campaign`, `list_campaign_runs`
- `list_calls`, `get_call`, `get_call_result`
- `list_conversations`, `get_conversation`, `send_agent_reply`

Tool annotations identify reads and side effects. `launch_calls` is marked
destructive and non-idempotent because it may place real, billable calls. The
server calls shared Python workflows directly; it does not shell out to the
CLI. `guzli://capabilities` reports non-secret local configuration readiness.

## Campaign, inbox, and telephony commands

```bash
# Inbox
guzli conversations list --status active --limit 20
guzli conversations get <conversation_id>
guzli agent-replies send <conversation_id> 'Thanks—I can help with that.'

# Campaign management
guzli campaigns list
guzli campaigns preview --config-file campaign.json
guzli campaigns create --config-file campaign.json
guzli campaigns readiness <campaign_id>
guzli campaigns archive <campaign_id>

# Compliance diagnostics
guzli campaigns compliance preview <campaign_id> --config-file audience.json
guzli campaigns compliance preflight <campaign_id>

# Voice profiles and pools
guzli voice-profiles get <profile_id>
guzli voice-profiles update <profile_id> --config-json '{"name":"Support"}'
guzli voice-profiles set-default <profile_id>
guzli voice-profiles usage --window-days 30
guzli numbers pool update <pool_id> --config-json '{"strategy":"sticky"}'
```

Place global options before the command. For stable automation output and
structured errors, use:

```bash
guzli --output json campaigns list
```

## Development and release boundaries

- The CLI is intentionally a client of existing public engine APIs. No engine
  changes are required for Campaign Launch or MCP.
- Live-call tests are excluded from the default suite.
- PyPI releases are built from GitHub releases by the trusted-publishing
  workflow; maintainers should follow [RELEASING.md](RELEASING.md).
- See [CONTRIBUTING.md](CONTRIBUTING.md) and
  [SECURITY.md](SECURITY.md) before contributing or reporting a vulnerability.

Detailed endpoint and payload notes live in [references/api.md](references/api.md).

## Frequently asked questions

### Can an AI agent make a one-off phone call with Guzli CLI?

Yes. `guzli call` is designed for quick operational calls such as confirming an
appointment, ordering food, or contacting a delivery provider. The agent passes
the recipient and instructions, while Guzli handles the voice campaign workflow.

### Does Guzli CLI support bulk outbound calling?

Yes. The same command supports one to 1,000 recipients through repeated `--to`
arguments, comma-separated numbers, or `--recipients-file`. Recipients are
validated and deduplicated before launch.

### What is the Guzli MCP server?

`guzli-mcp` is a local stdio Model Context Protocol server that exposes Guzli
operations as typed tools. MCP-compatible AI agents can launch calls, discover
number pools and voices, inspect campaign results, and handle conversations
without parsing terminal output.

### Do the CLI and MCP server require changes to the Guzli engine?

No. Both clients use the existing public Guzli API. The hosted engine remains
responsible for authorization, readiness, compliance enforcement, provider
capabilities, and call execution.

### Can I preview configuration without placing a call?

Yes. Pass `--dry-run` to `guzli call` or set `dry_run=true` when using the MCP
`launch_calls` tool. Dry runs resolve and validate configuration without
creating a campaign or dialing recipients.

### Is Guzli CLI open source?

Yes. The CLI, MCP server, agent skill, and documentation are licensed under
Apache-2.0. The separately hosted Guzli engine and service are not included in
this repository.

## License

Licensed under the [Apache License 2.0](LICENSE). The Guzli name and hosted
service are not granted under the code license beyond customary descriptive use.
