Skip to main content
Glama
Yashodeeps

fleet-dispatch

by Yashodeeps
README.md
# Fleet Dispatch

A blocked Claude Code session phones you. You say the answer out loud. The session unblocks and continues.

A stuck session costs the forty minutes it sits idle, not the eight seconds the decision takes. One-way alerts don't fix that because you still have to walk back and type. This is a two-way channel: one MCP tool, `call_me(context, question, options)`, that places a real outbound call through [CALL-E](https://www.heycall-e.com/), blocks until you answer, and returns your spoken decision to the session.

## Prerequisites

- Node 24 or newer.
- A CALL-E account. New accounts get 20 free calls. Create an API key at <https://dashboard.heycall-e.com/account/api-keys>.
- A phone number CALL-E can dial. Coverage is 40+ countries; see the [regions table](https://github.com/CALLE-AI/call-e-integrations#supported-regions). India (+91) is on the international line.

## Step 0: prove your phone rings

No code of ours involved. This uses CALL-E's own CLI:

```bash
export CALLE_API_KEY=calle_...
npx @call-e/calle@latest calls create \
  --phone "+91XXXXXXXXXX" \
  --task "Call this person, say 'this is Fleet Dispatch, testing', and ask if they can hear you clearly." \
  --wait --json
```

If your phone rings, everything else will work.

## Step 1: install the MCP server

```bash
git clone git@github.com:Yashodeeps/fleet-dispatch.git ~/fleet-dispatch
cd ~/fleet-dispatch && npm install && npm test

cat > .env <<'EOF'
CALLE_API_KEY=calle_...
FLEET_DISPATCH_PHONE=+91XXXXXXXXXX
FLEET_DISPATCH_REGION=IN
EOF

claude mcp add --scope user --transport stdio fleet-dispatch -- node ~/fleet-dispatch/src/server.ts
```

The server reads `.env` next to its source. Variables set in the shell or via `claude mcp add --env` take precedence. `.env` is gitignored. User scope means every session on this machine gets the tool.

## Step 2: install the Skill

The Skill holds the policy for when a session should dial and when it should not.

```bash
mkdir -p ~/.claude/skills && cp -r ~/fleet-dispatch/skill ~/.claude/skills/fleet-dispatch
```

## Step 3: try it

In any `claude` session:

```text
Call me and ask whether to drop the users table or skip the migration.
```

Your phone rings. Say "skip it". The tool returns:

```json
{
  "answered": true,
  "decision": "Skip the migration",
  "chosen_option": "Skip the migration",
  "reasoning": null,
  "reason": "answered",
  "call_id": "call_...",
  "summary": "...",
  "transcript": [{ "speaker": "bot", "text": "..." }, { "speaker": "user", "text": "..." }]
}
```

## Dry run

Set `FLEET_DISPATCH_DRY_RUN=1` instead of `CALLE_API_KEY` and the server answers with the first option after a moment, without dialing. Useful for wiring up a new machine or recording a demo.

## Configuration

| Variable | Required | Meaning |
| --- | --- | --- |
| `CALLE_API_KEY` | yes, unless dry run | CALL-E API key |
| `FLEET_DISPATCH_PHONE` | yes | Your number in E.164, the only number this server will ever dial |
| `FLEET_DISPATCH_REGION` | no | Country code hint for routing, e.g. `IN` |
| `FLEET_DISPATCH_LOCALE` | no | BCP 47 locale hint, e.g. `en-IN` |
| `FLEET_DISPATCH_DRY_RUN` | no | `1` to never dial |

## Tool contract

`call_me(context, question, options?, default?, session?, timeout_seconds?)`

- Blocks up to `timeout_seconds` (default 300, max 900). Claude Code's MCP tool timeout defaults to many hours, so nothing else to configure.
- `answered: true` means you gave and confirmed a decision.
- `reason: hold` means you told it to wait. The default is never applied over an explicit hold.
- `reason: timeout` or `failed:<code>` returns `default` if one was given, otherwise `null` so the session halts.
- The phone number comes from the environment, never from the model. The model cannot choose whom to call.

## Side effects and safety

- Every non-dry-run tool call places one real phone call to `FLEET_DISPATCH_PHONE` and consumes CALL-E credit.
- There is no retry. A missed call returns the fallback and the Skill tells the session not to call again for the same question.
- Cancel by hanging up. The call ends and the session gets `reason: unclear` or `hold` depending on what was said.

TDQS

A4.4/5.0

Scored across 1 tool

Disambiguation5/5

With only one tool available, there is no possibility of confusing it with another. The tool's purpose is clearly described and unique within the server.

Naming Consistency4/5

The single tool name 'call_me' follows a verb_noun pattern, but with only one tool there is no established pattern to evaluate for consistency. It is internally consistent but offers limited evidence of a naming convention.

Tool Count2/5

The server is named 'fleet-dispatch', implying a broad dispatch domain, yet it exposes only a single tool for calling an engineer. This is far too few tools for the apparent scope and leaves the core functionality unaddressed.

Completeness1/5

The tool surface is severely incomplete for a fleet dispatch server—there are no tools for managing fleets, routes, vehicles, or dispatches. The single call tool is an outlier that does not cover the domain implied by the server name.

Maintenance

ActivityMaintained
ResponsivenessNo issues