@spekoai/mcp-calls 0.4.0 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spekoai/mcp-calls",
3
- "version": "0.4.0",
3
+ "version": "0.4.3",
4
4
  "description": "Place real, disclosed phone calls to businesses straight from your coding agent — the Speko \"AI calls for devs\" MCP. Single self-contained package: `npx @spekoai/mcp-calls init` to set up.",
5
5
  "mcpName": "ai.speko/mcp-calls",
6
6
  "type": "module",
package/server.json CHANGED
@@ -4,13 +4,13 @@
4
4
  "title": "Speko — AI Calls for Devs",
5
5
  "description": "Place real, disclosed outbound phone calls to businesses straight from your coding agent.",
6
6
  "repository": { "url": "https://github.com/SpekoAI/mcp-dev-calls", "source": "github" },
7
- "version": "0.4.0",
7
+ "version": "0.4.3",
8
8
  "websiteUrl": "https://speko.ai",
9
9
  "packages": [
10
10
  {
11
11
  "registryType": "npm",
12
12
  "identifier": "@spekoai/mcp-calls",
13
- "version": "0.4.0",
13
+ "version": "0.4.3",
14
14
  "transport": { "type": "stdio" },
15
15
  "environmentVariables": [
16
16
  {
@@ -1,67 +1,88 @@
1
1
  ---
2
2
  name: speko-calls
3
3
  description: >-
4
- Use when the user wants to place a REAL outbound phone call to a BUSINESS via the
5
- Speko Calls MCP — e.g. "call <place> and ask <question>", book a reservation, check
6
- hours/availability/pricing, or chase an order. Teaches the lookup → dial_token →
7
- make_call workflow, the mandatory AI disclosure, the business-lines-only + quiet-hours
8
- rails, and how to report the call OUTCOME honestly. Not for personal/consumer calls.
4
+ Use when the user wants to place a REAL outbound phone call via the Speko Calls MCP — e.g.
5
+ "call <place> and ask <question>", "find the best <X> near me and call them", book a
6
+ reservation, check hours/availability/pricing, or place/chase an order. Covers calling a
7
+ number you have or found via web search (call_number) and Speko's verified business lookup
8
+ (lookup_business → make_call), the mandatory AI disclosure, the quiet-hours + no-spam rails,
9
+ and reporting the call OUTCOME honestly.
9
10
  ---
10
11
 
11
- # Speko Calls — placing real, disclosed business calls
12
+ # Speko Calls — placing real, disclosed phone calls
12
13
 
13
- The Speko Calls MCP places **real, disclosed** outbound phone calls to **businesses** and
14
- returns the result as text. Every call opens with a non-removable AI disclosure
15
- (*"Hi, this is an AI assistant calling on behalf of …"*). You drive it through three tools
16
- and **never dial a raw number directly**.
14
+ The Speko Calls MCP places **real, disclosed** outbound phone calls and returns the result as
15
+ text. Every call opens with a non-removable AI disclosure — the callee hears
16
+ *"Hey! Quick heads up I'm \<your-name\>'s AI assistant, \<your-name\> asked me to give you a
17
+ call…"* before anything else.
17
18
 
18
- ## Workflow always in this order
19
- 1. **`check_call_readiness()`** — read-only preflight (auth, credit balance, outbound
20
- caller-ID). Run first if unsure the account can dial. Never dials.
21
- 2. **`lookup_business(name, location?, phone_number?, utc_offset_minutes?)`** — resolves the business
22
- to dialable candidates, each with a **signed, single-use `dial_token`**. This is the ONLY thing that
23
- can authorize a call. If you can find the business's official phone number via web search, pass it as
24
- `phone_number` (E.164) to skip the directory lookup — it's still carrier-verified as a business line.
25
- If the number's region isn't auto-recognized for quiet-hours, also pass `utc_offset_minutes`
26
- (e.g. -300 US Eastern) — you know the business's city from your search.
27
- 3. **`make_call(dial_token, objective, caller_name, context?)`** — places the disclosed
28
- call, waits while it rings, returns the `OUTCOME:` line + transcript.
19
+ There are **two ways to dial**:
20
+ - **`call_number`** — dial a number you already have, or one you found via web search. Works
21
+ with just the user's Speko key, no extra setup. **This is the hero path for "find a place and
22
+ call it."**
23
+ - **`lookup_business` `make_call`** let Speko find the business in a directory and
24
+ carrier-verify it's a real business line, then dial. Use when you want that verification (the
25
+ server must have directory/carrier keys configured).
29
26
 
30
- `make_call` is impossible without a fresh `dial_token` from `lookup_business`. There is no
31
- way to pass a raw phone number that's a safety boundary, not a limitation.
27
+ ## Find the number yourself (the hero flow)
28
+ When the user names a *kind* of place ("the best taco spot in the Bay Area"), don't ask them
29
+ for a number — find it and call it. **Be decisive — don't stall the user with options.**
30
+ 1. **Web-search** and pick the SINGLE best match; don't make the user choose from a list. Read
31
+ its official site/listing for the full phone number and its city.
32
+ 2. **`call_number(phone_number=<+E.164>, objective, caller_name)`** places the disclosed call.
33
+ Use a full international number with a leading `+` and country code (`+14152857117`, not
34
+ `(415) 285-7117`). The destination timezone auto-derives from common area codes; if the tool
35
+ says it couldn't determine the timezone (an unusual area code, or a toll-free
36
+ 800/888/877/866 number), re-run with `utc_offset_minutes` for the business's city
37
+ (US Pacific is `-420` in summer / `-480` in winter, US Eastern `-240`/`-300`, UK `+60`/`0`).
38
+ 3. One quick inline confirm ("calling La Taqueria, +1 415-285-7117, to ask if they have carnitas
39
+ — go?"), then dial. A call is a real-world action, so keep the gate to a single yes/no.
32
40
 
33
- ## Before dialing confirm with the human
34
- - **Confirm the business and the objective with the user.** A call is a real-world action.
35
- - Pass the user's name as `caller_name` (the disclosure says "on behalf of `<caller_name>`").
36
- - Write `objective` as ONE clear transactional goal:
37
- *"Ask if there's a table for 4 at 8pm tonight and book it under John."*
41
+ Example: *"find the best taco place in the Bay Area and ask if they're open and have carnitas"*
42
+ search pick La Taqueria `call_number(...)` relay the `OUTCOME`.
43
+
44
+ ## Writing the objective
45
+ One plain, transactional goal in everyday words:
46
+ - **reservation:** *"Ask if there's a table for 4 at 8pm tonight and book it under John."*
47
+ - **order:** *"Order 2 carnitas tacos and a Coke Zero for pickup, and ask when it'll be ready."*
48
+ - **info:** *"Ask if they're open now and how long the wait is for a table for 2."*
49
+
50
+ Pass the user's name as `caller_name` (the disclosure says *"I'm \<caller_name\>'s AI assistant"*).
51
+ Avoid words the no-spam screen refuses — they match as substrings (e.g. "promot" catches
52
+ "promotion"): *sell, sales pitch, promote, discount, sponsor, advertise, marketing, survey,
53
+ donate, fundraise, vote, campaign, debt, warranty, crypto, investment.* Just say it plainly
54
+ ("order…", "ask if…", "book…", "check the price of…"). ("deal" is fine.)
55
+
56
+ ## The verified directory path — `lookup_business` → `make_call`
57
+ 1. **`check_call_readiness()`** — read-only preflight (auth, credit, outbound caller-ID). Run
58
+ first if unsure the account can dial. Never dials.
59
+ 2. **`lookup_business(name, location?, phone_number?, utc_offset_minutes?)`** — resolves the
60
+ business to candidates, each with a **signed, single-use `dial_token`** (the only thing that
61
+ can authorize `make_call`). Needs the server's directory/carrier keys; without them, use
62
+ `call_number` with a number you found instead.
63
+ 3. **`make_call(dial_token, objective, caller_name, context?)`** — places the disclosed call,
64
+ waits while it rings, and returns the `OUTCOME:` line + transcript.
38
65
 
39
66
  ## The rails (enforced server-side — you cannot override them)
40
- - **Business lines only** — mobiles are blocked (carrier line-type check).
41
- - **Transactional objectives only** — reservations, availability, hours, pricing, order
42
- status. **Refused:** selling, promotion, surveys, fundraising, political campaigning.
43
- - **Quiet hours** — 08:00–21:00 in the destination's local time (fail-closed if unknown).
44
67
  - **AI disclosure** — hard-coded; cannot be removed or reworded.
68
+ - **Transactional objectives only** — reservations, availability, hours, pricing, orders.
69
+ **Refused:** selling, promotion, surveys, fundraising, political campaigning.
70
+ - **Quiet hours** — 08:00–21:00 in the destination's local time; calls outside are rejected
71
+ (fail-closed if the timezone is unknown — pass `utc_offset_minutes`).
72
+ - **Business-line verification** applies on the `lookup_business` path (mobiles blocked there).
45
73
 
46
- If an objective trips a rail, `make_call` returns a rejection with a reason. Rewrite the
47
- objective as a single transactional question and retry, or tell the user it isn't allowed.
74
+ If an objective trips a rail, the tool returns a rejection with a reason. Fix the objective (or
75
+ pass `utc_offset_minutes`) and retry, or tell the user it isn't allowed.
48
76
 
49
77
  ## Reading the result — honestly
50
- - `connected` / `answered` are reported truthfully. If the platform never put a real call
51
- on the wire (no telephony leg), it returns **`not_connected`** — do **not** report that
52
- as success. Run `check_call_readiness` and tell the user the deployment's outbound
53
- trunk / caller-ID may need setup.
54
- - The `OUTCOME:` line is the answer (e.g. *"table for 4 at 8pm, booked under John"*).
55
- Relay it plainly and offer the transcript.
56
-
57
- ## Personal calls — `call_number`
58
- If the user wants to call a **specific number they give you** (e.g. a friend), use
59
- `call_number(phone_number, objective, caller_name, recipient_name?)` — not the business
60
- flow. It works by default. Mobiles are allowed here; the AI disclosure, quiet hours, and
61
- no-spam screen still apply. Only ever call a number the user **explicitly provides and has
62
- consent to call** — never one you guessed. For businesses, use `lookup_business` instead.
78
+ - `connected` / `answered` are reported truthfully. If the platform never put a real call on
79
+ the wire, it returns **`not_connected`** — do **not** report that as success; run
80
+ `check_call_readiness` and tell the user the deployment's outbound trunk/caller-ID may need setup.
81
+ - The `OUTCOME:` line is the answer (e.g. *"table for 4 at 8pm, booked under John"*). Relay it
82
+ plainly and offer the transcript.
63
83
 
64
84
  ## Don't
65
- - Don't invent or guess phone numbers — `make_call` dials only a server-minted `dial_token`; `call_number` dials only a number the user explicitly gave you.
66
- - Don't retry after a pre-dial rejection without fixing the objective first.
85
+ - Don't invent or guess phone numbers — only dial a number the user gave you or one you found
86
+ from the business's own official listing.
87
+ - Don't retry after a pre-dial rejection without fixing the objective/timezone first.
67
88
  - Don't promise a call will connect — report what actually happened.