@setluca/mcp 0.2.1 → 0.3.1
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/CHANGELOG.md +331 -0
- package/LICENSE +21 -0
- package/README.md +19 -288
- package/dist/annotations.js +33 -18
- package/dist/client-address.js +64 -0
- package/dist/completions.js +24 -27
- package/dist/config.js +89 -38
- package/dist/errors.js +94 -13
- package/dist/fields.js +68 -0
- package/dist/fixed-window.js +46 -0
- package/dist/generated/openapi-inputs.js +216 -5820
- package/dist/generated/openapi-outputs.js +19014 -14001
- package/dist/generated/route-catalog.js +80 -0
- package/dist/http.js +107 -44
- package/dist/index.js +4 -1
- package/dist/oauth-challenge.js +74 -0
- package/dist/oauth-resolver.js +58 -61
- package/dist/observability.js +30 -15
- package/dist/openapi-schema.js +175 -0
- package/dist/operations/catalog.js +17 -0
- package/dist/operations/groups/analytics.js +20 -10
- package/dist/operations/groups/bookings.js +43 -15
- package/dist/operations/groups/broadcasts.js +29 -58
- package/dist/operations/groups/cadences.js +3 -1
- package/dist/operations/groups/callEvents.js +19 -72
- package/dist/operations/groups/campaigns.js +28 -32
- package/dist/operations/groups/channels.js +23 -0
- package/dist/operations/groups/conversations.js +14 -25
- package/dist/operations/groups/insights.js +4 -0
- package/dist/operations/groups/integrations.js +15 -17
- package/dist/operations/groups/knowledge.js +5 -1
- package/dist/operations/groups/leads.js +22 -23
- package/dist/operations/groups/learning.js +13 -1
- package/dist/operations/groups/memory.js +4 -6
- package/dist/operations/groups/reports.js +1 -1
- package/dist/operations/groups/reviewQueue.js +17 -14
- package/dist/operations/groups/safety.js +1 -1
- package/dist/operations/groups/voice.js +0 -1
- package/dist/operations/groups/webhooks.js +15 -3
- package/dist/operations/manifest.js +7 -6
- package/dist/operations/registry.js +102 -108
- package/dist/operations.js +4 -3
- package/dist/optional-field.js +15 -3
- package/dist/page-contract.js +74 -0
- package/dist/pagination.js +147 -67
- package/dist/prompts.js +122 -97
- package/dist/rate-limit.js +40 -0
- package/dist/remote.js +145 -65
- package/dist/resilience.js +107 -52
- package/dist/resolvers.js +125 -0
- package/dist/scopes.js +70 -17
- package/dist/serialization.js +32 -22
- package/dist/server.js +148 -132
- package/dist/standard-schema.js +215 -0
- package/dist/task-tools/analytics.js +145 -86
- package/dist/task-tools/bookings.js +168 -81
- package/dist/task-tools/cadences.js +30 -45
- package/dist/task-tools/calls.js +131 -124
- package/dist/task-tools/inbox.js +37 -47
- package/dist/task-tools/leads.js +49 -77
- package/dist/task-tools/runtime.js +75 -15
- package/dist/token-verification.js +47 -0
- package/dist/tool-cache.js +3 -2
- package/dist/tool.js +151 -96
- package/dist/version.js +1 -1
- package/package.json +37 -16
- package/dist/openapi-zod.js +0 -335
- package/dist/page-shape.js +0 -62
- package/dist/tsconfig.tsbuildinfo +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,337 @@ input schema, or changing what a tool does to a workspace.
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [0.3.1] - 2026-10-06
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Restore authenticated remote MCP discovery and tool calls on Cloudflare.
|
|
18
|
+
Token checks and tool requests now use a direct service binding to Luca's API,
|
|
19
|
+
avoiding the public API's WAF challenge. Both paths use Cloudflare's supported
|
|
20
|
+
manual redirect mode and still reject redirected responses without forwarding
|
|
21
|
+
credentials.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- The remote tool catalog includes explicit safety annotations for directory
|
|
26
|
+
review. The protocol suite checks the published `tools/list` shape.
|
|
27
|
+
|
|
28
|
+
## [0.3.0] - 2026-10-05
|
|
29
|
+
|
|
30
|
+
This is the first Luca MCP release from its own repository. The package and
|
|
31
|
+
hosted connection now share a release path, with checks against the Luca API
|
|
32
|
+
currently in production. The README starts with what people can do in Luca;
|
|
33
|
+
setup and development details live in the guides.
|
|
34
|
+
|
|
35
|
+
### Breaking
|
|
36
|
+
|
|
37
|
+
- **Tool names are snake_case throughout.** Operation tools used the camelCase
|
|
38
|
+
of their operation id, so the list mixed `luca_analytics_speedImpact` with
|
|
39
|
+
`luca_book_call`. Every name now matches the task tools' casing. 73 tools
|
|
40
|
+
are renamed; the other 130 keep their names. A client or saved prompt that
|
|
41
|
+
calls an old name gets an unknown-tool error. 203 tools ship: 188 operations
|
|
42
|
+
and 15 task tools.
|
|
43
|
+
|
|
44
|
+
<details>
|
|
45
|
+
<summary>Every renamed tool</summary>
|
|
46
|
+
|
|
47
|
+
| Old name | New name |
|
|
48
|
+
| ------------------------------------------------- | -------------------------------------------------- |
|
|
49
|
+
| `luca_leads_fieldDefinitions_list` | `luca_leads_field_definitions_list` |
|
|
50
|
+
| `luca_leads_fieldDefinitions_upsert` | `luca_leads_field_definitions_upsert` |
|
|
51
|
+
| `luca_leads_importPreview` | `luca_leads_import_preview` |
|
|
52
|
+
| `luca_leads_importApply` | `luca_leads_import_apply` |
|
|
53
|
+
| `luca_reviewQueue_list` | `luca_review_queue_list` |
|
|
54
|
+
| `luca_reviewQueue_explain` | `luca_review_queue_explain` |
|
|
55
|
+
| `luca_reviewQueue_approve` | `luca_review_queue_approve` |
|
|
56
|
+
| `luca_reviewQueue_reject` | `luca_review_queue_reject` |
|
|
57
|
+
| `luca_reviewQueue_restore` | `luca_review_queue_restore` |
|
|
58
|
+
| `luca_reviewQueue_media_retry` | `luca_review_queue_media_retry` |
|
|
59
|
+
| `luca_reviewQueue_sla` | `luca_review_queue_sla` |
|
|
60
|
+
| `luca_reviewQueue_objectionVariant` | `luca_review_queue_objection_variant` |
|
|
61
|
+
| `luca_bookings_managedAvailability` | `luca_bookings_managed_availability` |
|
|
62
|
+
| `luca_bookings_outcomeReasons_list` | `luca_bookings_outcome_reasons_list` |
|
|
63
|
+
| `luca_bookings_needsOutcome` | `luca_bookings_needs_outcome` |
|
|
64
|
+
| `luca_bookings_lifecycleAttention` | `luca_bookings_lifecycle_attention` |
|
|
65
|
+
| `luca_bookings_lifecycleResolution` | `luca_bookings_lifecycle_resolution` |
|
|
66
|
+
| `luca_bookings_providerSync_retry` | `luca_bookings_provider_sync_retry` |
|
|
67
|
+
| `luca_bookings_guestLinks_create` | `luca_bookings_guest_links_create` |
|
|
68
|
+
| `luca_bookings_guestLinks_revoke` | `luca_bookings_guest_links_revoke` |
|
|
69
|
+
| `luca_bookings_outcomeReasons_create` | `luca_bookings_outcome_reasons_create` |
|
|
70
|
+
| `luca_bookings_outcomeReasons_update` | `luca_bookings_outcome_reasons_update` |
|
|
71
|
+
| `luca_callEvents_needingFeedback` | `luca_call_events_needing_feedback` |
|
|
72
|
+
| `luca_callEvents_get` | `luca_call_events_get` |
|
|
73
|
+
| `luca_callEvents_byBooking` | `luca_call_events_by_booking` |
|
|
74
|
+
| `luca_callEvents_byLead` | `luca_call_events_by_lead` |
|
|
75
|
+
| `luca_callEvents_feedback` | `luca_call_events_feedback` |
|
|
76
|
+
| `luca_callEvents_summary_generate` | `luca_call_events_summary_generate` |
|
|
77
|
+
| `luca_callEvents_summary_replace` | `luca_call_events_summary_replace` |
|
|
78
|
+
| `luca_callEvents_pushToCrm` | `luca_call_events_push_to_crm` |
|
|
79
|
+
| `luca_callEvents_undoOutcome` | `luca_call_events_undo_outcome` |
|
|
80
|
+
| `luca_callEvents_backfill` | `luca_call_events_backfill` |
|
|
81
|
+
| `luca_campaigns_providerCapabilities` | `luca_campaigns_provider_capabilities` |
|
|
82
|
+
| `luca_campaigns_commentEvents_list` | `luca_campaigns_comment_events_list` |
|
|
83
|
+
| `luca_campaigns_commentSimulationSuite_run` | `luca_campaigns_comment_simulation_suite_run` |
|
|
84
|
+
| `luca_campaigns_setStatus` | `luca_campaigns_set_status` |
|
|
85
|
+
| `luca_webhooks_testDelivery` | `luca_webhooks_test_delivery` |
|
|
86
|
+
| `luca_webhooks_signatureGuide` | `luca_webhooks_signature_guide` |
|
|
87
|
+
| `luca_webhooks_events_bulkReplay` | `luca_webhooks_events_bulk_replay` |
|
|
88
|
+
| `luca_integrations_crm_oauthUrl` | `luca_integrations_crm_oauth_url` |
|
|
89
|
+
| `luca_integrations_crm_connections_webhooksSetup` | `luca_integrations_crm_connections_webhooks_setup` |
|
|
90
|
+
| `luca_integrations_crm_syncRuns_list` | `luca_integrations_crm_sync_runs_list` |
|
|
91
|
+
| `luca_integrations_crm_syncRuns_create` | `luca_integrations_crm_sync_runs_create` |
|
|
92
|
+
| `luca_coach_nicheProfile` | `luca_coach_niche_profile` |
|
|
93
|
+
| `luca_coach_objectionPlaybook` | `luca_coach_objection_playbook` |
|
|
94
|
+
| `luca_coach_postCallSettings` | `luca_coach_post_call_settings` |
|
|
95
|
+
| `luca_coach_postCallCrmMapping` | `luca_coach_post_call_crm_mapping` |
|
|
96
|
+
| `luca_coach_postCallDealSync` | `luca_coach_post_call_deal_sync` |
|
|
97
|
+
| `luca_coach_auditLog` | `luca_coach_audit_log` |
|
|
98
|
+
| `luca_insights_unreadCount` | `luca_insights_unread_count` |
|
|
99
|
+
| `luca_insights_markRead` | `luca_insights_mark_read` |
|
|
100
|
+
| `luca_insights_markActioned` | `luca_insights_mark_actioned` |
|
|
101
|
+
| `luca_learning_frameworkPerformance` | `luca_learning_framework_performance` |
|
|
102
|
+
| `luca_learning_abTests_list` | `luca_learning_ab_tests_list` |
|
|
103
|
+
| `luca_learning_abTests_get` | `luca_learning_ab_tests_get` |
|
|
104
|
+
| `luca_knowledge_approveSuggestion` | `luca_knowledge_approve_suggestion` |
|
|
105
|
+
| `luca_knowledge_rejectSuggestion` | `luca_knowledge_reject_suggestion` |
|
|
106
|
+
| `luca_memory_setArchived` | `luca_memory_set_archived` |
|
|
107
|
+
| `luca_cadences_rescueStart` | `luca_cadences_rescue_start` |
|
|
108
|
+
| `luca_analytics_speedImpact` | `luca_analytics_speed_impact` |
|
|
109
|
+
| `luca_analytics_callIntelligence` | `luca_analytics_call_intelligence` |
|
|
110
|
+
| `luca_analytics_callIntelligenceCalls` | `luca_analytics_call_intelligence_calls` |
|
|
111
|
+
| `luca_analytics_ghostedLeads` | `luca_analytics_ghosted_leads` |
|
|
112
|
+
| `luca_analytics_trustScore` | `luca_analytics_trust_score` |
|
|
113
|
+
| `luca_analytics_leadScore` | `luca_analytics_lead_score` |
|
|
114
|
+
| `luca_analytics_lossReasons` | `luca_analytics_loss_reasons` |
|
|
115
|
+
| `luca_analytics_contentAttribution` | `luca_analytics_content_attribution` |
|
|
116
|
+
| `luca_analytics_contentPerformance` | `luca_analytics_content_performance` |
|
|
117
|
+
| `luca_analytics_topicPerformance` | `luca_analytics_topic_performance` |
|
|
118
|
+
| `luca_analytics_benchmarkConsent` | `luca_analytics_benchmark_consent` |
|
|
119
|
+
| `luca_analytics_learningInsights` | `luca_analytics_learning_insights` |
|
|
120
|
+
| `luca_analytics_crmSyncHealth` | `luca_analytics_crm_sync_health` |
|
|
121
|
+
| `luca_analytics_objectionDrilldown` | `luca_analytics_objection_drilldown` |
|
|
122
|
+
|
|
123
|
+
</details>
|
|
124
|
+
|
|
125
|
+
- **A tool call with an argument the tool does not define fails.** It used to
|
|
126
|
+
drop the field and run, so a typo such as `limt` silently fell back to the
|
|
127
|
+
default. The error names the field, and no request is sent.
|
|
128
|
+
- **Seven further tools need `confirm: true`:**
|
|
129
|
+
`luca_bookings_lifecycle_resolution`, `luca_bookings_provider_sync_retry`,
|
|
130
|
+
`luca_call_events_summary_replace`, `luca_call_events_push_to_crm`,
|
|
131
|
+
`luca_webhooks_test_delivery`,
|
|
132
|
+
`luca_integrations_crm_connections_webhooks_setup`, and
|
|
133
|
+
`luca_integrations_crm_sync_runs_create`. Each writes to a connected
|
|
134
|
+
calendar or CRM, or posts to an outside URL. 27 operations are now gated,
|
|
135
|
+
which covers every write that can reach past the workspace.
|
|
136
|
+
- **`luca_find_leads` takes `channel` as one of `telegram`, `instagram`,
|
|
137
|
+
`messenger`, or `whatsapp`,** the values `GET /api/leads` accepts. Any other
|
|
138
|
+
value fails before a request is sent.
|
|
139
|
+
- **The analytics task tools return what they could read.**
|
|
140
|
+
`luca_analytics_rollup`, `luca_analytics_magic_monday`, and
|
|
141
|
+
`luca_analytics_deep_dive` used to fail when any one read failed. Each
|
|
142
|
+
section is now optional, and a `failedSections` list names the section and
|
|
143
|
+
the error for every read that failed. The call fails only when every read
|
|
144
|
+
does, or when a read is refused with a 401 or a scope 403.
|
|
145
|
+
- **Six more tools need `confirm: true`:** `luca_leads_import_apply`,
|
|
146
|
+
`luca_leads_consents_grant`, `luca_bookings_cancel`,
|
|
147
|
+
`luca_webhooks_subscriptions_create`, `luca_webhooks_subscriptions_update`,
|
|
148
|
+
and `luca_campaigns_set_status` when it sets `published` (resuming sends). A
|
|
149
|
+
client that called these without it now gets a tool error asking for it.
|
|
150
|
+
- **Two tools are gone.** `luca_integrations_crm_oauthCallback` and
|
|
151
|
+
`luca_integrations_crm_webhooks_record` were provider callbacks that an agent
|
|
152
|
+
had no reason to call.
|
|
153
|
+
- **`openWorldHint` is now `false` for most tools.** It is `true` only for the
|
|
154
|
+
25 operations, and the task tools built on them, that can reach past the
|
|
155
|
+
workspace: messaging a lead, posting to an outside URL, or writing to a
|
|
156
|
+
connected calendar or CRM.
|
|
157
|
+
- **The remote resolver API changed.** `apiKeyResolver(settings)` and
|
|
158
|
+
`oauthResolver(settings)` take the API base URL, auth header, and timeout as
|
|
159
|
+
one settings object, and a `TokenResolver` returns `Option<LucaConfig>`.
|
|
160
|
+
`ResolvedIdentity` and `chainResolvers` are gone. Pick a resolver by the
|
|
161
|
+
token's shape with the new `looksLikeDeveloperKey`.
|
|
162
|
+
- **`LucaConfig.apiKey` is a `Redacted<string>`.** A custom `TokenResolver`
|
|
163
|
+
wraps the key with `Redacted.make` from `effect/Redacted`, so a logged or
|
|
164
|
+
inspected config prints `<redacted>` instead of the key.
|
|
165
|
+
- **Booking and moving a call need `confirm: true`:** `luca_book_call`,
|
|
166
|
+
`luca_reschedule_call`, `luca_bookings_create`, and `luca_bookings_update`
|
|
167
|
+
now match `luca_bookings_cancel`. A booking moves the lead to booked and
|
|
168
|
+
notifies the coach's webhook subscribers; a move updates the connected
|
|
169
|
+
calendar and the lead's reminder. All four now report `destructiveHint: true`.
|
|
170
|
+
To migrate, show the coach the slot, then pass `confirm: true` once they
|
|
171
|
+
approve it. A call without it returns a tool error and sends nothing.
|
|
172
|
+
- **`luca_close_call_loop` needs `confirm: true` when `attendance` is
|
|
173
|
+
`no_show`.** That report can start recovery that messages the lead. Other
|
|
174
|
+
attendance values run without it.
|
|
175
|
+
- **`provider` on `luca_book_call` and `luca_reschedule_call` is one of
|
|
176
|
+
`manual`, `cal_com`, `calendly`, `google_calendar`, `iclosed`, or
|
|
177
|
+
`gohighlevel`.** Any other value fails before a request is sent. It used to
|
|
178
|
+
be skipped by the availability check without a word.
|
|
179
|
+
- **The hosted server checks developer keys.** A `luca_` key is checked with
|
|
180
|
+
one `GET /api/capabilities` before a server is built, so a made-up key gets
|
|
181
|
+
401 instead of a tool list. `apiKeyResolver(settings, fetchImpl?, checks?)`
|
|
182
|
+
now resolves asynchronously and can fail with
|
|
183
|
+
`TokenVerificationUnavailable`.
|
|
184
|
+
- **An empty `idempotencyKey` fails before a request is sent** on every task
|
|
185
|
+
tool that takes one. It used to reach the API as a blank header.
|
|
186
|
+
- **`RemoteRateLimiters` has a required `perTokenAddress` limiter,** charged
|
|
187
|
+
per client address on requests that carry a token.
|
|
188
|
+
- **`luca_call_events_feedback` asks for confirmation on a `no_show` report.**
|
|
189
|
+
A no-show can start recovery messaging, so that outcome now needs
|
|
190
|
+
`confirm: true`. Other outcomes need no confirmation, and the tool stays on
|
|
191
|
+
the `luca:draft` scope. `luca_close_call_loop` keeps its own no-show gate.
|
|
192
|
+
|
|
193
|
+
### Added
|
|
194
|
+
|
|
195
|
+
- Every tool declares the lowest OAuth scope that can call it in
|
|
196
|
+
`_meta.securitySchemes`. On the hosted server, a call that fails because the
|
|
197
|
+
token was revoked or its scopes fall short returns
|
|
198
|
+
`_meta["mcp/www_authenticate"]`, so a client such as ChatGPT can ask the coach
|
|
199
|
+
to reconnect. See [docs/remote.md](./docs/remote.md#per-tool-scopes-and-re-authorization).
|
|
200
|
+
- Two prompts, `luca-plan-campaign` and `luca-plan-broadcast`, which take a
|
|
201
|
+
campaign or broadcast through a dry run or preview before anything goes live.
|
|
202
|
+
- Server instructions, returned on `initialize`, naming the starting tools, the
|
|
203
|
+
confirm rule, and how to treat lead-authored text.
|
|
204
|
+
- Cancelling a tool call now aborts the request it has in flight.
|
|
205
|
+
- `luca_book_call` takes an optional `bookingTypeId` and sends it with the
|
|
206
|
+
booking. The API requires one for a `google_calendar` booking, so that
|
|
207
|
+
provider could not be booked through the tool before.
|
|
208
|
+
- Two tools: `luca_learning_ab_tests_list` and `luca_learning_ab_tests_get`
|
|
209
|
+
read the coach's A/B tests and per-variant results. Creating, running, and
|
|
210
|
+
adopting a test stay in the Luca app.
|
|
211
|
+
- Four channel tools under the new `channels:read` API-key scope, granted from
|
|
212
|
+
`luca:read` up: `luca_channels_list` and `luca_channels_get` read the coach's
|
|
213
|
+
connected accounts with their status and health, `luca_channels_catalog`
|
|
214
|
+
says which channels can be connected yet, and `luca_channels_features` says
|
|
215
|
+
what each provider supports. Connecting, pausing, and repairing an account
|
|
216
|
+
stay in the Luca app.
|
|
217
|
+
- The 15 task tools declare an `outputSchema`, so a client can read their
|
|
218
|
+
`structuredContent` without guessing its shape.
|
|
219
|
+
- `createRemoteResponder` in `@setluca/mcp/remote` returns the remote handler as
|
|
220
|
+
an Effect, for a host that runs its own Effect program around each request.
|
|
221
|
+
`createRemoteHandler` still returns a plain fetch handler.
|
|
222
|
+
- `createLocalRateLimits` in `@setluca/mcp/remote` builds the in-memory
|
|
223
|
+
limiters, and `createRemoteHandler` and `createRemoteResponder` take them as
|
|
224
|
+
an optional `rateLimits`, so a host can keep one set across requests.
|
|
225
|
+
|
|
226
|
+
### Changed
|
|
227
|
+
|
|
228
|
+
- A tool call stops after 45 seconds in total, retries and waits included, and
|
|
229
|
+
each attempt still stops after 30. A write that times out says its outcome is
|
|
230
|
+
unknown and names the idempotency key that makes a second send safe. The
|
|
231
|
+
timeout error carries the last 429 or 5xx the call saw.
|
|
232
|
+
- A 429, 502, 503, or 504 retries even when its body is HTML or plain text, and
|
|
233
|
+
honors `Retry-After`. It used to fail as a decode error.
|
|
234
|
+
- A paged list that stops early keeps the pages it fetched and leads with a
|
|
235
|
+
`warning` that says the list is incomplete and how to fetch the rest. It
|
|
236
|
+
stops when a page fails or can't be read, when the server repeats a cursor
|
|
237
|
+
or sends an empty page with one, or after 120 seconds in total. A later page
|
|
238
|
+
refused with 401, or 403 for a missing scope, fails the whole call instead,
|
|
239
|
+
so the client gets the challenge that sends it back through sign-in.
|
|
240
|
+
- Lead-authored text is marked untrusted per operation instead of only on
|
|
241
|
+
reads, so a write that returns lead text is framed too. 51 operations are
|
|
242
|
+
framed, among them every booking route that returns the invitee's
|
|
243
|
+
cancellation reason (`luca_bookings_list`, `luca_bookings_get`,
|
|
244
|
+
`luca_bookings_create`, `luca_bookings_update`, `luca_bookings_cancel`,
|
|
245
|
+
`luca_bookings_lifecycle_attention`, and
|
|
246
|
+
`luca_bookings_lifecycle_resolution`), `luca_bookings_needs_outcome`,
|
|
247
|
+
`luca_analytics_ghosted_leads`, and the five lead writes that echo the lead
|
|
248
|
+
record back: `luca_leads_create`, `luca_leads_update`,
|
|
249
|
+
`luca_leads_import_preview`, `luca_leads_import_apply`, and
|
|
250
|
+
`luca_leads_identities_attach`. Those five now list `full_content` as their
|
|
251
|
+
data sensitivity. `luca_book_call`, `luca_reschedule_call`, and
|
|
252
|
+
`luca_analytics_deep_dive` are framed as well.
|
|
253
|
+
- A task tool that returns partial results fails the whole call when the API
|
|
254
|
+
answers 401, or 403 with `scope_required` or `needs_scope`, so the agent
|
|
255
|
+
sees a credentials problem instead of a missing section. This covers the
|
|
256
|
+
three analytics task tools, `luca_close_call_loop`, the explanations of
|
|
257
|
+
`luca_triage_inbox`, and the guest links of `luca_reschedule_call`. Other failures still come back as a section error.
|
|
258
|
+
- `luca_book_call` and `luca_reschedule_call` skip the availability check when
|
|
259
|
+
the call carries an `idempotencyKey`, so a retry of a booking that went
|
|
260
|
+
through reaches the API's replay instead of reporting the slot taken.
|
|
261
|
+
`luca_book_call` sends `provider` with the booking; `luca_reschedule_call`
|
|
262
|
+
uses it only for the availability check and keeps the booking's provider.
|
|
263
|
+
- `luca_book_call` with a `bookingTypeId` checks the slot against that booking
|
|
264
|
+
type's own schedule instead of the calendar provider's free time. An
|
|
265
|
+
availability check refused with 401, or 403 for a missing scope, fails the
|
|
266
|
+
call instead of booking unchecked.
|
|
267
|
+
- `luca_close_call_loop` says what filing starts: no-show recovery, a call
|
|
268
|
+
summary that can sync to the CRM, and a CRM deal-stage update.
|
|
269
|
+
- The workflow prompts point at the task tools, such as
|
|
270
|
+
`luca_morning_report` and `luca_draft_reply`, instead of the raw operations.
|
|
271
|
+
- Completion suggestions match the typed prefix in any case.
|
|
272
|
+
- `luca-rescue-silent-leads` applies its `days` window to the conversation
|
|
273
|
+
list step, not only to the heading.
|
|
274
|
+
- `luca_analytics_deep_dive` no longer requires `question`.
|
|
275
|
+
- `luca_close_call_loop` reports a failed call-event lookup as
|
|
276
|
+
`feedbackError`. It used to read as "no call event for this booking".
|
|
277
|
+
- A failed resource read answers with a JSON-RPC error: resource-not-found for
|
|
278
|
+
a missing record, an invalid request carrying the same
|
|
279
|
+
`mcp/www_authenticate` challenge a tool error carries for a refused token or
|
|
280
|
+
missing scope, and an internal error for anything else.
|
|
281
|
+
- An API response that is not JSON is reported by its length. The error no
|
|
282
|
+
longer quotes the body, text no Luca schema shaped.
|
|
283
|
+
- Calls to the Luca API refuse to follow redirects, so a key or token is never
|
|
284
|
+
sent to a host the config did not name.
|
|
285
|
+
- The hosted server:
|
|
286
|
+
- checks an OAuth token within 5 seconds and answers 503 if it cannot;
|
|
287
|
+
- treats only a 401 from the token check as a refused token, so a misrouted
|
|
288
|
+
or overloaded API no longer sends every client back through sign-in;
|
|
289
|
+
- limits each bearer token to 60 requests a minute, so coaches who
|
|
290
|
+
share an address no longer share a budget, and also limits requests with
|
|
291
|
+
a token to 600 a minute per address, so made-up tokens run out too;
|
|
292
|
+
- limits requests without a token to 600 a minute per address;
|
|
293
|
+
- refuses a token over 4,096 characters, or an OAuth token that is not
|
|
294
|
+
three base64url segments, with 401 `invalid_token` and no API call;
|
|
295
|
+
- leaves `scope` out of an `invalid_token` challenge, so a client that
|
|
296
|
+
reconnects asks for the scope it had rather than a lower one;
|
|
297
|
+
- answers 429 with "Too many requests";
|
|
298
|
+
- reads the client address from `CF-Connecting-IP` only and ignores
|
|
299
|
+
`X-Forwarded-For`, which any client can set;
|
|
300
|
+
- answers 500 to every request when a production deploy is missing any of
|
|
301
|
+
its three rate-limit bindings, or when `MCP_PUBLIC_ORIGIN` is not an
|
|
302
|
+
http(s) origin with no path;
|
|
303
|
+
- serves its discovery documents to any origin, CORS preflight included.
|
|
304
|
+
- The package no longer depends on Zod directly.
|
|
305
|
+
- Tool input schemas now advertise closed objects
|
|
306
|
+
(`additionalProperties: false`) and keep each field's format, title, and
|
|
307
|
+
description.
|
|
308
|
+
- The docs describe Luca as a DM sales platform.
|
|
309
|
+
- The hosted Worker reads `LUCA_AUTH_HEADER` and `LUCA_REQUEST_TIMEOUT_MS` with
|
|
310
|
+
the stdio parser. `bearer` now works there, and an unknown value answers 500
|
|
311
|
+
instead of sending keys in a header the API ignores.
|
|
312
|
+
- The `WWW-Authenticate` challenge on a tool error now carries
|
|
313
|
+
`realm="luca-mcp"`, like the transport's 401.
|
|
314
|
+
- A tool call missing a path parameter fails as a tool input error before any
|
|
315
|
+
request is sent.
|
|
316
|
+
- Prompts no longer use em dashes, and every workflow prompt ends with the same
|
|
317
|
+
safety rules.
|
|
318
|
+
- A task tool's read-only, confirm, and untrusted-content flags now come from
|
|
319
|
+
the operations it composes, so a task tool cannot claim to be safer than the
|
|
320
|
+
routes it calls.
|
|
321
|
+
- Cancelling a resource read aborts the request it has in flight.
|
|
322
|
+
- A write that needs an idempotency key and gets none now mints a fresh key
|
|
323
|
+
each time the call runs, rather than once per built request.
|
|
324
|
+
- A cancelled tool call is logged with `outcome: "interrupted"`.
|
|
325
|
+
- Each tool's `x-luca-redacted-fields` list now comes from the API's
|
|
326
|
+
`sensitive()` markers at generation time instead of a hand-written list, and
|
|
327
|
+
`redaction:check` is gone. The lists did not change.
|
|
328
|
+
- **`luca_reschedule_call` checks the booking's own schedule.** It reads the
|
|
329
|
+
booking first and checks the new time against the slots of its booking type,
|
|
330
|
+
or the provider calendar when the booking has no booking type or cannot be
|
|
331
|
+
read.
|
|
332
|
+
- **More routes frame lead-written text as untrusted.** CRM rows, broadcast
|
|
333
|
+
recipients, campaign enrollments, and integration sync records now carry the
|
|
334
|
+
untrusted-content marker and `full_content` data sensitivity.
|
|
335
|
+
- **`luca_rescue_silent_leads` rejects empty lead ids.**
|
|
336
|
+
|
|
337
|
+
### Fixed
|
|
338
|
+
|
|
339
|
+
- The hosted server logs `mcp.token_verification_unavailable`, with the error
|
|
340
|
+
message and no token, when the token verifier cannot answer and the request
|
|
341
|
+
gets a 503.
|
|
342
|
+
- Resource registration shares one read path for fixed and templated URIs.
|
|
343
|
+
|
|
13
344
|
## [0.2.1] - 2026-08-22
|
|
14
345
|
|
|
15
346
|
### Added
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Luca
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|