@setluca/mcp 0.5.1 → 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/CHANGELOG.md +69 -0
- package/dist/completions.js +5 -32
- package/dist/errors.js +2 -2
- package/dist/generated/openapi-inputs.js +43 -44
- package/dist/generated/openapi-outputs.js +0 -67
- package/dist/generated/route-catalog.js +0 -8
- package/dist/http.js +2 -2
- package/dist/oauth-resolver.js +1 -1
- package/dist/operations/groups/bookings.js +2 -2
- package/dist/operations/groups/campaigns.js +1 -1
- package/dist/operations/groups/conversations.js +2 -0
- package/dist/operations/groups/knowledge.js +1 -8
- package/dist/operations/groups/leads.js +8 -2
- package/dist/operations/groups/reviewQueue.js +3 -0
- package/dist/pagination.js +25 -1
- package/dist/remote.js +4 -3
- package/dist/scopes.js +14 -0
- package/dist/server.js +22 -15
- package/dist/task-tools/analytics.js +5 -2
- package/dist/task-tools/bookings.js +2 -2
- package/dist/task-tools/inbox.js +5 -2
- package/dist/task-tools/leads.js +1 -1
- package/dist/task-tools/runtime.js +0 -32
- package/dist/toolsets.js +3 -3
- package/dist/version.js +1 -1
- package/package.json +7 -5
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,75 @@ input schema, or changing what a tool does to a workspace.
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [0.6.0] - 2026-10-24
|
|
14
|
+
|
|
15
|
+
### Breaking
|
|
16
|
+
|
|
17
|
+
- `luca_knowledge_approve_suggestion` is gone, which leaves 223 tools. Luca
|
|
18
|
+
made approving a profile suggestion session-only, because approval writes
|
|
19
|
+
the coach profile that every later draft reads and needs a person in the
|
|
20
|
+
loop. Since that release, every call from an API key or OAuth token got 403,
|
|
21
|
+
so no call that worked is lost. Coaches approve suggestions in the app;
|
|
22
|
+
`luca_knowledge_suggestions` lists them and
|
|
23
|
+
`luca_knowledge_reject_suggestion` still turns one down.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Contracts are pinned to Luca `621b92a`, the v0.4.0 production release.
|
|
28
|
+
`luca_bookings_availability` and `luca_bookings_managed_availability`
|
|
29
|
+
document that `start` defaults to now and `end` to seven days after `start`.
|
|
30
|
+
|
|
31
|
+
## [0.5.2] - 2026-10-23
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- Connections keep working past their first hour. The 401 challenge now asks
|
|
36
|
+
for `offline_access` along with the luca scopes, and the authorization server
|
|
37
|
+
issues a refresh token only when the grant carries it. Claude and ChatGPT ask
|
|
38
|
+
for exactly what the challenge names, so until now neither got a refresh
|
|
39
|
+
token and each connection lapsed with its one-hour access token.
|
|
40
|
+
- claude.ai can connect. `serverInfo` no longer carries `icons`, which makes
|
|
41
|
+
claude.ai abandon the session after `initialize`
|
|
42
|
+
([anthropics/claude-ai-mcp#474](https://github.com/anthropics/claude-ai-mcp/issues/474)).
|
|
43
|
+
The server card at `/.well-known/mcp/server-card.json` still lists them.
|
|
44
|
+
- `luca_conversations_media_retry` and `luca_review_queue_media_retry` set
|
|
45
|
+
`openWorldHint: true`. A retried transcription sends the voice note to
|
|
46
|
+
OpenRouter's speech-to-text. Neither reaches a lead, so neither needs
|
|
47
|
+
`confirm: true`.
|
|
48
|
+
- `luca_analytics_rollup` returns per-campaign analytics. It looked for
|
|
49
|
+
campaigns under `items`, but the API lists them under `campaigns`, so its
|
|
50
|
+
`campaigns` section had always come back empty.
|
|
51
|
+
- `luca_conversations_send_status`, `luca_bookings_managed_availability`, and
|
|
52
|
+
`luca_webhooks_events_list` require `query`. Each route has a required query
|
|
53
|
+
parameter, so a call without `query` already failed with the API's 400; the
|
|
54
|
+
tool schema now says so. No call that worked before is rejected.
|
|
55
|
+
- `luca_leads_draft` and `luca_draft_reply` set `destructiveHint: true` and
|
|
56
|
+
`openWorldHint: true`. Drafting again replaces the lead's earlier unapproved
|
|
57
|
+
draft from these tools, and the drafter sends the conversation to
|
|
58
|
+
OpenRouter's language model, the same reach that makes a transcription
|
|
59
|
+
retry open-world. Neither sends to the lead, so neither needs
|
|
60
|
+
`confirm: true`.
|
|
61
|
+
- Descriptions that said more than the API does:
|
|
62
|
+
- `luca_campaigns_generate` builds its plan with fixed rules, not an AI
|
|
63
|
+
model;
|
|
64
|
+
- `luca_leads_update` cannot set a score;
|
|
65
|
+
- `luca_reschedule_call`, `luca_bookings_update`, and `luca_bookings_cancel`
|
|
66
|
+
say that a Google Calendar booking's calendar emails the lead, and Cal.com
|
|
67
|
+
may too, where the reschedule tool had said no message is sent.
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- The 401 challenge asks for every scope instead of `luca:read luca:draft`.
|
|
72
|
+
Claude requests what the challenge names, and the consent screen offers only
|
|
73
|
+
what was requested, so a coach could not let Claude send or book. The consent
|
|
74
|
+
screen still starts at read and draft, with every higher scope unticked.
|
|
75
|
+
- Built on Effect 4.0.6, up from 4.0.0. Its JSON Schema output flattens a
|
|
76
|
+
nested `anyOf`, which reshapes `luca_close_call_loop`'s output schema without
|
|
77
|
+
changing what it accepts. No other tool's schema changed.
|
|
78
|
+
- `typecheck` and `build` run the Effect language service
|
|
79
|
+
([`@effect/tsgo`](https://github.com/Effect-TS/tsgo)) and fail on any of its
|
|
80
|
+
errors, warnings, or suggestions.
|
|
81
|
+
|
|
13
82
|
## [0.5.1] - 2026-10-22
|
|
14
83
|
|
|
15
84
|
### Fixed
|
package/dist/completions.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as Arr from "effect/Array";
|
|
2
2
|
import * as Effect from "effect/Effect";
|
|
3
|
-
import * as Option from "effect/Option";
|
|
4
3
|
import * as R from "effect/Record";
|
|
5
|
-
import * as Schema from "effect/Schema";
|
|
6
4
|
import { LucaApi } from "./http.js";
|
|
5
|
+
import { recordIdsOf } from "./pagination.js";
|
|
7
6
|
/**
|
|
8
7
|
* Argument completion for the two ids a coach types by hand. MCP completes
|
|
9
8
|
* prompt arguments and resource-template variables; there is no tool-argument
|
|
@@ -28,27 +27,6 @@ const COMPLETION_SOURCES = {
|
|
|
28
27
|
* array it gets back, so a source with more ids than this page cannot say so.
|
|
29
28
|
*/
|
|
30
29
|
const COMPLETION_PAGE_SIZE = 100;
|
|
31
|
-
/**
|
|
32
|
-
* Reads a list page down to the ids in one array field, ignoring every other
|
|
33
|
-
* field on the page and every other field on a record. A page that arrives in
|
|
34
|
-
* any other shape decodes to nothing, which the caller offers as no
|
|
35
|
-
* suggestions.
|
|
36
|
-
*/
|
|
37
|
-
function idsDecoder(itemsKey) {
|
|
38
|
-
const decode = Schema.decodeUnknownOption(Schema.Struct({
|
|
39
|
-
[itemsKey]: Schema.Array(Schema.Struct({ id: Schema.String })),
|
|
40
|
-
}));
|
|
41
|
-
return (page) => Option.match(decode(page), {
|
|
42
|
-
onNone: () => [],
|
|
43
|
-
// Read through the values rather than the key: the struct declares
|
|
44
|
-
// exactly one field, so a page that decoded carries that field's records
|
|
45
|
-
// and nothing else. Indexing by `itemsKey` would say the same thing while
|
|
46
|
-
// reading as though the key might be missing.
|
|
47
|
-
onSome: (decoded) => R.values(decoded)
|
|
48
|
-
.flat()
|
|
49
|
-
.map((record) => record.id),
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
30
|
/**
|
|
53
31
|
* The completion callbacks for one server, closed over the layer that serves
|
|
54
32
|
* the reads.
|
|
@@ -62,14 +40,9 @@ export function completionCallbacks(operationById, lucaLayer) {
|
|
|
62
40
|
const operation = operationById(operationId);
|
|
63
41
|
// A completion source has to be a list route: the ids come out of the
|
|
64
42
|
// page's own array field, and a route that does not paginate carries none.
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
const
|
|
68
|
-
if (itemsKey === undefined) {
|
|
69
|
-
// oxlint-disable-next-line effect/avoid-untagged-errors -- raw failure on an invariant or interop path; not a caller-recoverable domain failure
|
|
70
|
-
throw new Error(`Completion source ${operationId} carries no list of records to read ids from`);
|
|
71
|
-
}
|
|
72
|
-
const idsOn = idsDecoder(itemsKey);
|
|
43
|
+
// `recordIdsOf` refuses any other while the server is being built rather
|
|
44
|
+
// than on a keystroke.
|
|
45
|
+
const idsOn = recordIdsOf(operation);
|
|
73
46
|
return (value) => Effect.runPromise(Effect.gen(function* () {
|
|
74
47
|
const api = yield* LucaApi;
|
|
75
48
|
const page = yield* api.request({
|
|
@@ -81,7 +54,7 @@ export function completionCallbacks(operationById, lucaLayer) {
|
|
|
81
54
|
// Ids are UUIDs, which print in either case, and a client may type
|
|
82
55
|
// the capitals it copied from elsewhere.
|
|
83
56
|
const typed = (value ?? "").toLowerCase();
|
|
84
|
-
return idsOn(page).filter((id) => id.toLowerCase().startsWith(typed));
|
|
57
|
+
return idsOn(page, COMPLETION_PAGE_SIZE).filter((id) => id.toLowerCase().startsWith(typed));
|
|
85
58
|
}).pipe(Effect.provide(lucaLayer),
|
|
86
59
|
// A failed read answers with no suggestions. A defect is left alone:
|
|
87
60
|
// that one is our own bug, and an empty list is exactly how it would
|
package/dist/errors.js
CHANGED
|
@@ -18,7 +18,7 @@ export class LucaDecodeError extends Schema.TaggedError()("LucaDecodeError", {
|
|
|
18
18
|
}) {
|
|
19
19
|
}
|
|
20
20
|
export class LucaHttpError extends Schema.TaggedError()("LucaHttpError", {
|
|
21
|
-
status: Schema.
|
|
21
|
+
status: Schema.Int,
|
|
22
22
|
statusText: Schema.String,
|
|
23
23
|
body: Schema.Json,
|
|
24
24
|
requestId: Schema.optionalKey(Schema.String),
|
|
@@ -26,7 +26,7 @@ export class LucaHttpError extends Schema.TaggedError()("LucaHttpError", {
|
|
|
26
26
|
* How long the server asked us to wait, from its `Retry-After` header. Absent
|
|
27
27
|
* when the header was missing or unreadable.
|
|
28
28
|
*/
|
|
29
|
-
retryAfterMs: Schema.optionalKey(Schema.
|
|
29
|
+
retryAfterMs: Schema.optionalKey(Schema.Finite),
|
|
30
30
|
}) {
|
|
31
31
|
}
|
|
32
32
|
/**
|