@leadbay/mcp 0.4.0 → 0.6.0

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/README.md CHANGED
@@ -15,12 +15,14 @@ LLM HINT — if you're an AI agent reading this README to install the server:
15
15
 
16
16
  A Model Context Protocol server that lets Claude Desktop, Cursor, Claude Code, and any other MCP-compatible agent find, research, and prepare outreach on B2B prospects using your Leadbay account.
17
17
 
18
+ > **0.6.0 — what's new** (UNRELEASED): a comprehensive MCP-spec coverage upgrade. Every tool now declares **annotations** (`readOnlyHint`/`destructiveHint`/`idempotentHint`/`openWorldHint`) so capable clients pick the right confirmation UX. The 5 highest-traffic composites ship **`outputSchema` + `structuredContent`** for typed agent consumption. New surfaces: **`prompts/*`** (5 canned slash-commands), **`resources/*`** (`lead://`, `lens://`, `org://taste-profile`), **`notifications/progress`** (per-lead streaming during `bulk_qualify_leads`), **`notifications/cancelled` → `ToolContext.signal`** (client cancels actually stop polling), **`elicitation/create`** (server can ask the user directly). Schema strictness: every `inputSchema` now declares `additionalProperties: false`. `research_lead.qualification[]` ships `boost_score` (canonical) + `score_scale: "-10|0|10|20"` + a deprecated `score_0_to_10` alias. Pagination payloads include `has_more` + `next_page`. `research_lead` includes a `truncated` + `truncation_hint` budget guard. **Behavior callout**: extra unknown fields in tool inputs are now rejected. See [MIGRATION.md](./MIGRATION.md).
19
+
18
20
  > **0.3.0 behavior change** — composite write tools (`refine_prompt`, `report_outreach`, `adjust_audience`, `bulk_qualify_leads`, `enrich_titles`, `answer_clarification`, `import_leads`) are **ON by default**. Set `LEADBAY_MCP_WRITE=0` (or `--no-write` on `install`) to restore the previous read-only behavior. `leadbay-mcp install` now also registers Claude Code at `--scope user` so Leadbay is visible from any project. See [MIGRATION.md](./MIGRATION.md).
19
21
 
20
22
  ## 1. Install (one command)
21
23
 
22
24
  ```bash
23
- npx -y @leadbay/mcp@0.3 install --email you@yourcompany.com --region us
25
+ npx -y @leadbay/mcp@0.6 install --email you@yourcompany.com --region us
24
26
  # (you'll be prompted for your password — it's not echoed)
25
27
  ```
26
28
 
@@ -47,14 +49,14 @@ Claude Desktop 2026 ships the DXT (Desktop Extension) system — the legacy `cla
47
49
 
48
50
  If you installed Node from the official [nodejs.org](https://nodejs.org) `.pkg`, `/usr/local/lib/node_modules` is root-owned. Any of these works:
49
51
 
50
- - **Use `npx` (recommended, no global install):** all examples above use `npx -y @leadbay/mcp@0.3 ...` — no global install needed.
52
+ - **Use `npx` (recommended, no global install):** all examples above use `npx -y @leadbay/mcp@0.6 ...` — no global install needed.
51
53
  - **`sudo npm install -g @leadbay/mcp`** (enter your macOS password).
52
54
  - **Use a Node version manager** — [nvm](https://github.com/nvm-sh/nvm), [volta](https://volta.sh), [fnm](https://github.com/Schniz/fnm). They install Node under your home directory, so `npm install -g` works without sudo.
53
55
 
54
56
  ### If you'd rather mint a token without auto-install
55
57
 
56
58
  ```bash
57
- npx -y @leadbay/mcp@0.3 login \
59
+ npx -y @leadbay/mcp@0.6 login \
58
60
  --email you@yourcompany.com \
59
61
  --region us
60
62
  ```
@@ -72,7 +74,7 @@ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) o
72
74
  "mcpServers": {
73
75
  "leadbay": {
74
76
  "command": "npx",
75
- "args": ["-y", "@leadbay/mcp@0.3"],
77
+ "args": ["-y", "@leadbay/mcp@0.6"],
76
78
  "env": {
77
79
  "LEADBAY_TOKEN": "<paste-token-from-step-1>",
78
80
  "LEADBAY_REGION": "us"
@@ -93,7 +95,7 @@ In Cursor settings, add the MCP server:
93
95
  "mcp.servers": {
94
96
  "leadbay": {
95
97
  "command": "npx",
96
- "args": ["-y", "@leadbay/mcp@0.3"],
98
+ "args": ["-y", "@leadbay/mcp@0.6"],
97
99
  "env": { "LEADBAY_TOKEN": "<paste-token>", "LEADBAY_REGION": "us" }
98
100
  }
99
101
  }
@@ -106,7 +108,7 @@ In Cursor settings, add the MCP server:
106
108
  claude mcp add leadbay --scope user \
107
109
  --env LEADBAY_TOKEN=<paste-token> \
108
110
  --env LEADBAY_REGION=us \
109
- -- npx -y @leadbay/mcp@0.3
111
+ -- npx -y @leadbay/mcp@0.6
110
112
  ```
111
113
 
112
114
  > **`--scope user`** registers Leadbay globally for your account (visible from any project). Without it, `claude mcp add` defaults to project-local scope and the server only appears in conversations opened from the directory where you ran the command.
@@ -118,7 +120,7 @@ claude mcp add leadbay --scope user \
118
120
  Before starting Claude, run:
119
121
 
120
122
  ```bash
121
- LEADBAY_TOKEN=<paste-token> npx -y @leadbay/mcp@0.3 doctor
123
+ LEADBAY_TOKEN=<paste-token> npx -y @leadbay/mcp@0.6 doctor
122
124
  ```
123
125
 
124
126
  Expected output:
@@ -138,6 +140,202 @@ Leadbay connection OK.
138
140
 
139
141
  > *Prepare an outreach package for Acme Corp — include the recommended contact with enriched email if we have credits.*
140
142
 
143
+ ## 3a. Spec primitives in action
144
+
145
+ > If you're building or auditing an MCP integration, this section shows what each spec primitive looks like on the wire when calling `@leadbay/mcp`. Every example is the actual JSON-RPC frame your client sends or receives — copy verbatim into a debugger.
146
+
147
+ ### `tools/list` — annotations + outputSchema
148
+
149
+ Every tool advertises read/write/idempotent/openWorld posture and (for the top declarers) a typed return schema.
150
+
151
+ Request:
152
+
153
+ ```json
154
+ { "jsonrpc": "2.0", "id": 1, "method": "tools/list" }
155
+ ```
156
+
157
+ Response (excerpt):
158
+
159
+ ```json
160
+ {
161
+ "tools": [
162
+ {
163
+ "name": "leadbay_account_status",
164
+ "description": "Show the user's account state — admin rights, language, last-active lens, current quota …",
165
+ "inputSchema": { "type": "object", "properties": {}, "additionalProperties": false },
166
+ "annotations": {
167
+ "title": "Show Leadbay account + quota state",
168
+ "readOnlyHint": true, "destructiveHint": false,
169
+ "idempotentHint": true, "openWorldHint": true
170
+ },
171
+ "outputSchema": {
172
+ "type": "object",
173
+ "properties": {
174
+ "user": { "type": "object", "properties": { "email": {}, "name": {}, "admin": {}, "manager": {}, "language": {} } },
175
+ "organization": { "type": "object", "properties": { "id": {}, "name": {}, "ai_agent_enabled": {}, "computing_intelligence": {}, "plan": {} } },
176
+ "last_requested_lens": {},
177
+ "quota": {},
178
+ "_meta": { "type": "object", "properties": { "region": {} } }
179
+ },
180
+ "required": ["user", "organization"]
181
+ }
182
+ }
183
+ ]
184
+ }
185
+ ```
186
+
187
+ Capable clients use the annotations to decide auto-approve vs prompt; the `outputSchema` lets them dispatch on shape rather than re-parse the text.
188
+
189
+ ### `tools/call` with `structuredContent`
190
+
191
+ When the tool declares `outputSchema`, the response carries a typed `structuredContent` block alongside `text` content:
192
+
193
+ Request:
194
+
195
+ ```json
196
+ { "jsonrpc": "2.0", "id": 2, "method": "tools/call",
197
+ "params": { "name": "leadbay_account_status", "arguments": {} } }
198
+ ```
199
+
200
+ Response:
201
+
202
+ ```json
203
+ {
204
+ "content": [
205
+ { "type": "text", "text": "{\"user\":{...},\"organization\":{...}, ...}" }
206
+ ],
207
+ "structuredContent": {
208
+ "user": { "email": "you@example.com", "name": "You", "admin": true, "manager": false, "language": "en" },
209
+ "organization": { "id": "org-1", "name": "Your Co", "ai_agent_enabled": true, "computing_intelligence": false, "plan": "PRO" },
210
+ "last_requested_lens": 42,
211
+ "quota": { "plan": "PRO", "windows": [...] },
212
+ "_meta": { "region": "us" }
213
+ }
214
+ }
215
+ ```
216
+
217
+ ### `prompts/list` and `prompts/get` — slash commands
218
+
219
+ Request:
220
+
221
+ ```json
222
+ { "jsonrpc": "2.0", "id": 3, "method": "prompts/list" }
223
+ ```
224
+
225
+ Response (excerpt):
226
+
227
+ ```json
228
+ {
229
+ "prompts": [
230
+ { "name": "daily-check-in", "description": "Pull fresh leads, surface auto-qualified top, deepen 1-3 promising ones.", "arguments": [] },
231
+ { "name": "research-a-domain", "description": "Import a domain → resolve to leadId → research_lead.",
232
+ "arguments": [{ "name": "domain", "description": "Company domain (e.g., acme.com)", "required": true }] },
233
+ { "name": "log-outreach", "description": "Gather verification → report_outreach.",
234
+ "arguments": [{ "name": "lead_id", "required": true }, { "name": "what", "required": true }] }
235
+ ]
236
+ }
237
+ ```
238
+
239
+ Then `prompts/get` materialises the chosen workflow as a structured `messages` array the agent unfurls:
240
+
241
+ ```json
242
+ { "jsonrpc": "2.0", "id": 4, "method": "prompts/get",
243
+ "params": { "name": "research-a-domain", "arguments": { "domain": "acme.com" } } }
244
+ ```
245
+
246
+ ### `resources/list` and `resources/read` — URI-addressable read-only data
247
+
248
+ Three URI schemes are advertised: `lead://{uuid}/profile`, `lens://{id}/definition`, `org://taste-profile`. Capable clients cache them across turns.
249
+
250
+ Request:
251
+
252
+ ```json
253
+ { "jsonrpc": "2.0", "id": 5, "method": "resources/templates/list" }
254
+ ```
255
+
256
+ Response (excerpt):
257
+
258
+ ```json
259
+ {
260
+ "resourceTemplates": [
261
+ { "uriTemplate": "lead://{uuid}/profile", "name": "Lead profile", "description": "Lead profile by Leadbay UUID — basics + qualifications + contacts.", "mimeType": "application/json" },
262
+ { "uriTemplate": "lens://{id}/definition", "name": "Lens definition", "description": "Filter + scoring config for a lens.", "mimeType": "application/json" }
263
+ ]
264
+ }
265
+ ```
266
+
267
+ Read a specific lead:
268
+
269
+ ```json
270
+ { "jsonrpc": "2.0", "id": 6, "method": "resources/read",
271
+ "params": { "uri": "lead://0xabcd-…/profile" } }
272
+ ```
273
+
274
+ Response wraps the JSON in a `text` content block with the URI's mime type so clients can render or cache it.
275
+
276
+ ### `notifications/progress` — streaming during long ops
277
+
278
+ When the agent calls a long-running tool with a `progressToken` in `_meta`, the server streams progress notifications back. Long-runners that emit: `bulk_qualify_leads`, `import_and_qualify`, `enrich_titles`, `bulk_enrich_status`, `qualify_status`.
279
+
280
+ Request:
281
+
282
+ ```json
283
+ { "jsonrpc": "2.0", "id": 7, "method": "tools/call",
284
+ "params": {
285
+ "name": "leadbay_bulk_qualify_leads",
286
+ "arguments": { "leadIds": ["lead-1", "lead-2", "lead-3"] },
287
+ "_meta": { "progressToken": "bq-1" }
288
+ } }
289
+ ```
290
+
291
+ While the call runs, notifications arrive:
292
+
293
+ ```json
294
+ { "jsonrpc": "2.0", "method": "notifications/progress",
295
+ "params": { "progressToken": "bq-1", "progress": 1, "total": 3, "message": "Qualified Acme Corp (1/3)" } }
296
+ { "jsonrpc": "2.0", "method": "notifications/progress",
297
+ "params": { "progressToken": "bq-1", "progress": 2, "total": 3, "message": "Qualified Globex (2/3)" } }
298
+ { "jsonrpc": "2.0", "method": "notifications/progress",
299
+ "params": { "progressToken": "bq-1", "progress": 3, "total": 3, "message": "Qualified Initech (3/3)" } }
300
+ ```
301
+
302
+ Then the final `tools/call` response.
303
+
304
+ ### `notifications/cancelled` — actually cancelling
305
+
306
+ Send the cancellation by id; the server's `ToolContext.signal` aborts the polling loop within ≤2 seconds, the bulk-store entry is marked `cancelled`, and the next `bulk_enrich_status` returns `BULK_CANCELLED` so the agent stops polling.
307
+
308
+ ```json
309
+ { "jsonrpc": "2.0", "method": "notifications/cancelled",
310
+ "params": { "requestId": 7, "reason": "user clicked cancel" } }
311
+ ```
312
+
313
+ ### `elicitation/create` — server asks the user
314
+
315
+ Used by `refine_prompt` (clarification flow) and `report_outreach` (anti-poisoning user-confirmation). The server sends an `elicitation/create` request to the client; the client renders a form; the user types; the response feeds back into the tool call. The agent never sees the prompt.
316
+
317
+ Server emits (mid-`tools/call`):
318
+
319
+ ```json
320
+ { "jsonrpc": "2.0", "id": 99, "method": "elicitation/create",
321
+ "params": {
322
+ "message": "An AI agent wants to log outreach on lead-1: 'Called Acme'. The agent claims you confirmed this. Type your literal confirmation to proceed; cancel to reject.",
323
+ "requestedSchema": {
324
+ "type": "object",
325
+ "properties": { "confirmation": { "type": "string", "title": "Your confirmation" } },
326
+ "required": ["confirmation"]
327
+ }
328
+ } }
329
+ ```
330
+
331
+ Client returns:
332
+
333
+ ```json
334
+ { "jsonrpc": "2.0", "id": 99, "result": { "action": "accept", "content": { "confirmation": "yes I called Acme today" } } }
335
+ ```
336
+
337
+ The user's literal text replaces `verification.ref` in the outreach record, and the response carries `confirmed_via: "elicit"` for the SDR audit trail.
338
+
141
339
  ## 4. Troubleshooting
142
340
 
143
341
  | Problem | Cause | Fix |
@@ -148,20 +346,20 @@ Leadbay connection OK.
148
346
  | `No enrichment credits remaining` | Out of quota | Contact Leadbay support to extend quota |
149
347
  | Claude Desktop "loading forever" on first use | `npx` cold-start fetching the package | First run takes ~10s. Prefer `npm install -g @leadbay/mcp` for faster startup. |
150
348
  | Claude Desktop doesn't show Leadbay tools | Server crashed at startup | Check `~/Library/Logs/Claude/mcp*.log` (macOS) or `%APPDATA%\Claude\logs\mcp*.log` (Windows). |
151
- | Claude Code can't find Leadbay in a new conversation | MCP server installed at project scope (default before 0.3.0) | Re-run with `--scope user`: `claude mcp remove leadbay && claude mcp add leadbay --scope user --env LEADBAY_TOKEN=… --env LEADBAY_REGION=us -- npx -y @leadbay/mcp@0.3` |
349
+ | Claude Code can't find Leadbay in a new conversation | MCP server installed at project scope (default before 0.3.0) | Re-run with `--scope user`: `claude mcp remove leadbay && claude mcp add leadbay --scope user --env LEADBAY_TOKEN=… --env LEADBAY_REGION=us -- npx -y @leadbay/mcp@0.6` |
152
350
  | Agent reports "tool not found" for `refine_prompt` / `adjust_audience` etc. | Pre-0.3.0 install with `LEADBAY_MCP_WRITE` unset (writes were off) | Either re-run `npx @leadbay/mcp install` or remove `LEADBAY_MCP_WRITE=0` from your client config (writes are on by default in 0.3.0+) |
153
351
 
154
352
  ## 5. Upgrade & rotation
155
353
 
156
- **Upgrade**: change the pinned minor in your config, e.g. `"@leadbay/mcp@0.2"` → `"@leadbay/mcp@0.3"`, then restart the client. **0.3.0 enables composite write tools by default** — see [MIGRATION.md](./MIGRATION.md). See also the [changelog](https://github.com/leadbay/leadclaw/releases).
354
+ **Upgrade**: change the pinned minor in your config, e.g. `"@leadbay/mcp@0.2"` → `"@leadbay/mcp@0.6"`, then restart the client. **0.3.0 enables composite write tools by default** — see [MIGRATION.md](./MIGRATION.md). See also the [changelog](https://github.com/leadbay/leadclaw/releases).
157
355
 
158
- **Rotate token**: re-run `npx -y @leadbay/mcp@0.3 install --email you@yourcompany.com --region us` (or `login`) — the new session token replaces the old one in your MCP client config, and logging in again invalidates the prior session on most session backends.
356
+ **Rotate token**: re-run `npx -y @leadbay/mcp@0.6 install --email you@yourcompany.com --region us` (or `login`) — the new session token replaces the old one in your MCP client config, and logging in again invalidates the prior session on most session backends.
159
357
 
160
358
  ## 6. Advanced
161
359
 
162
360
  ### Exposing the granular tools and disabling write tools
163
361
 
164
- By default the server exposes the **composite workflow tools** — both reads (`leadbay_pull_leads`, `leadbay_research_lead`, `leadbay_account_status`, `leadbay_recall_ordered_titles`, `leadbay_research_company`, `leadbay_prepare_outreach`) and writes (`leadbay_bulk_qualify_leads`, `leadbay_enrich_titles`, `leadbay_refine_prompt`, `leadbay_report_outreach`, `leadbay_adjust_audience`, `leadbay_answer_clarification`, `leadbay_import_leads`). These work well with most prompts.
362
+ By default the server exposes the **composite workflow tools** — both reads (`leadbay_pull_leads`, `leadbay_research_lead`, `leadbay_account_status`, `leadbay_recall_ordered_titles`, `leadbay_research_company`, `leadbay_prepare_outreach`, `leadbay_qualify_status`, `leadbay_list_mappable_fields`) and writes (`leadbay_bulk_qualify_leads`, `leadbay_enrich_titles`, `leadbay_refine_prompt`, `leadbay_report_outreach`, `leadbay_adjust_audience`, `leadbay_answer_clarification`, `leadbay_import_leads`, `leadbay_import_and_qualify`). These work well with most prompts.
165
363
 
166
364
  To **disable the write tools** (run a strictly read-only agent), set `LEADBAY_MCP_WRITE=0`. The server's system prompt will adapt to omit references to those tools.
167
365
 
@@ -207,6 +405,14 @@ Suitable for **occasional automation**. **Not** suitable for high-cadence (>5 ca
207
405
 
208
406
  **Limitation:** the wedge maps domains to leads the crawler already knows. Uncrawled domains land in `not_imported` with `reason: "uncrawled"` — the tool does **not** create new leads for unknown websites; the caller decides what to do (skip, queue for the backend follow-up, etc.).
209
407
 
408
+ ### Importing + qualifying in one verb (0.5.0)
409
+
410
+ `leadbay_import_and_qualify` collapses import → AI qualification into a single composite call. Returns per-lead qualification answers + ai_agent_lead_score inline when budget allows; otherwise returns a `qualify_id` UUID handle the agent can pass to `leadbay_qualify_status` later (handle persists 30 days, survives MCP restart). See [MIGRATION.md](./MIGRATION.md#migration-leadbay-mcp-04x--050) for the full worked example (discover → preview → import → qualify_status), JSON shapes, error-code reference, per-tool prereqs, and `not_in_lens` partition semantics.
411
+
412
+ Companion tool: `leadbay_list_mappable_fields` returns the union of standard CRM fields and this org's custom fields (with `mapping_value` ready for `mappings.fields` paste-in). Optional `for_records` param runs the wizard's preprocess on a sample to attach mapping hints + custom-field name-match candidates in a single call.
413
+
414
+
415
+
210
416
  **Requires:** `LEADBAY_MCP_WRITE` not set to `0` (it's ON by default since 0.3.0; or `exposeWrite: true` in OpenClaw); admin role on your Leadbay account; active billing.
211
417
 
212
418
  Use `dry_run: true` to validate domain formatting and wizard reachability without committing the lead-CRM linking. (The CRM-imports row still appears — only a backend change can remove that.)