voygr-mcp
# voygr-mcp
MCP server for [VOYGR](https://voygr.tech) place verification and outbound venue calls.
Proper stdio MCP: tools, resources, prompts, progress notifications, and elicitation.
[Demo Video](https://github.com/user-attachments/assets/c92963f4-96ea-4604-8530-b70e5bf9d2a9)
## Install
```bash
cd voygr-mcp
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```
Requires a VOYGR API key at process start:
```bash
export VOYGR_API_KEY=your_key
# or: voygr login your_key
```
## Dry-run (default)
`VOYGR_DRY_RUN` defaults to `1`. **Calls only** are mocked (magic numbers, scripted
events, canned transcripts). `verify_place` / `verify_places` / `check_credits`
always hit the live VOYGR API via the official `voygr` Python client.
| Magic number | Outcome |
|---|---|
| `+1-555-0100` | `success_booked` |
| `+1-555-0101` | `failed_voicemail` |
| `+1-555-0102` | mid-call `ask_user` then `success_booked` |
| `+1-555-0103` | `failed_short_hangup` |
| `+1-555-0104` | `409` concurrency cap |
| `+1-555-0105` | `402` insufficient credits |
Live dialing:
```bash
export VOYGR_DRY_RUN=0
docker compose up -d redis # call state / event cursors
export VOYGR_REDIS_URL=redis://localhost:6379/0
voygr-mcp
```
## Claude Desktop (stdio)
1. Put `VOYGR_API_KEY=...` in the project `.env` (loaded automatically; Claude’s
cwd does not matter).
2. Edit `~/Library/Application Support/Claude/claude_desktop_config.json`
(macOS) and merge:
```json
{
"mcpServers": {
"voygr": {
"command": "/Users/vaarunsinha/voygr-mcp/scripts/claude-desktop-mcp.sh",
"env": {
"VOYGR_DRY_RUN": "1"
}
}
}
}
```
3. Fully quit and reopen Claude Desktop. Confirm under **+ → Connectors** (or
Developer settings) that `voygr` is connected and tools like `verify_place`
appear.
Or point `command` at `.venv/bin/voygr-mcp` directly — the server also loads
the package-root `.env` on start.
## Tools
| Tool | Role |
|---|---|
| `verify_place` | Single POI → agent-safe verdict (not raw open/closed) |
| `verify_places` | Batch + normalized cache |
| `call_place` | Structured call (`inquiry` / `info_gathering`); consent + slots elicited |
| `get_call` | Resume by call handle |
| `check_credits` | Usage / credits |
**Consent is never a tool parameter** — it is always an elicitation to the human.
## Resources / prompt
- `voygr://call/{id}/transcript` — 7-day retention noted in metadata
- `voygr://call/{id}/events`
- Prompt: `verify_before_recommending`
## Honesty (demo / video)
When recording the 60s demo:
- Refusal arm (`verify_places` dropping closed/not_found) should be **live** API.
- Mid-call handoff segment should be **dry-run** (`+1-555-0102`) and labeled on screen.
- List which segments used dry-run in any public write-up.
## Tests
```bash
pytest
```
Tests use `ScriptedElicitationProvider` (no human). No skip-consent env var ships
in the server.
## Stack
Python, official `mcp` SDK (stdio), `voygr` PyPI client, httpx (calls API), Redis
(live call state), Docker Compose, pytest. No FastAPI in v1.
Reference checkout of upstream CLI (not vendored): `../voygr-dev-tools`.
TDQS
Scored across 7 tools
Each tool has a distinct role: verification, credit check, call placement, consent, mid-call answer, and status retrieval. The only potential overlap is verify_place vs verify_places, but the singular/plural distinction is clearly explained in the descriptions.
All tools follow a consistent verb_noun pattern in snake_case (verify_place, check_credits, call_place, approve_call, answer_mid_call, get_call), with no naming style mixing.
Seven tools is well-scoped for a place-verification and calling service. Each tool covers a distinct step in the workflow with no redundancy.
The surface covers the full workflow: verify places, place calls, handle consent, relay mid-call answers, and retrieve status. Minor gaps like canceling a call or listing history are not critical for the core purpose.