@setluca/mcp 0.5.0 → 0.5.2
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 +80 -0
- package/dist/annotations.js +6 -5
- package/dist/completions.js +5 -32
- package/dist/errors.js +2 -2
- package/dist/generated/openapi-inputs.js +42 -42
- package/dist/http.js +2 -2
- package/dist/oauth-resolver.js +1 -1
- package/dist/operations/groups/bookings.js +9 -2
- package/dist/operations/groups/broadcasts.js +4 -0
- package/dist/operations/groups/cadences.js +1 -0
- package/dist/operations/groups/callEvents.js +6 -0
- package/dist/operations/groups/campaigns.js +1 -1
- package/dist/operations/groups/conversations.js +3 -0
- package/dist/operations/groups/insights.js +4 -0
- package/dist/operations/groups/integrations.js +9 -4
- package/dist/operations/groups/knowledge.js +2 -0
- package/dist/operations/groups/leads.js +20 -2
- package/dist/operations/groups/learning.js +1 -0
- package/dist/operations/groups/memory.js +1 -0
- package/dist/operations/groups/reviewQueue.js +10 -1
- package/dist/operations/groups/webhooks.js +1 -0
- package/dist/operations/registry.js +3 -1
- 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/tool.js +3 -0
- package/dist/toolsets.js +3 -3
- package/dist/version.js +1 -1
- package/package.json +7 -5
package/dist/task-tools/inbox.js
CHANGED
|
@@ -5,9 +5,12 @@ import * as Schema from "effect/Schema";
|
|
|
5
5
|
import { formatError } from "../errors.js";
|
|
6
6
|
import { WORKSPACE_INPUT_FIELDS } from "../fields.js";
|
|
7
7
|
import { logAgentSurfaceEvent } from "../observability.js";
|
|
8
|
-
import {
|
|
8
|
+
import { operationById } from "../operations.js";
|
|
9
|
+
import { recordIdsOf } from "../pagination.js";
|
|
10
|
+
import { isPartialFailure, numberInput, operationResult, resultOrError, taskTool, } from "./runtime.js";
|
|
9
11
|
const DEFAULT_QUEUE_LIMIT = 20;
|
|
10
12
|
const DEFAULT_EXPLAIN_TOP = 3;
|
|
13
|
+
const queueIds = recordIdsOf(operationById("reviewQueue.list"));
|
|
11
14
|
const TRIAGE_INBOX_TOOL_NAME = "luca_triage_inbox";
|
|
12
15
|
/**
|
|
13
16
|
* One explanation, with a failed lookup carried in the result instead of
|
|
@@ -79,7 +82,7 @@ const triageInbox = taskTool({
|
|
|
79
82
|
const queue = yield* call("reviewQueue.list", {
|
|
80
83
|
query: { limit: numberInput(input.limit, DEFAULT_QUEUE_LIMIT) },
|
|
81
84
|
});
|
|
82
|
-
const ids =
|
|
85
|
+
const ids = queueIds(queue, numberInput(input.explainTop, DEFAULT_EXPLAIN_TOP));
|
|
83
86
|
const attempts = yield* Effect.forEach(ids, (id) => explainOne(call, id),
|
|
84
87
|
// Effect.forEach defaults to concurrency 1 (sequential). `explainTop`
|
|
85
88
|
// caps this fan-out at 5 independent lookups, so unbounded is fine.
|
package/dist/task-tools/leads.js
CHANGED
|
@@ -48,7 +48,7 @@ const flagForHuman = taskTool({
|
|
|
48
48
|
const draftReply = taskTool({
|
|
49
49
|
name: "luca_draft_reply",
|
|
50
50
|
title: "Draft a reply for a lead",
|
|
51
|
-
description:
|
|
51
|
+
description: "Draft a reply for a lead, written the way the coach writes, and put it in the SetLuca review queue, where it waits for the coach to approve it. Drafting again replaces this lead's earlier unapproved draft from this tool. It never sends, whatever the channel's auto-send setting. Optional guidance steers tone or content. Example: call with { leadId, guidance: \"keep it short and warm\" }.",
|
|
52
52
|
inputSchema: {
|
|
53
53
|
...WORKSPACE_INPUT_FIELDS,
|
|
54
54
|
leadId: NonEmptyString.annotate({
|
|
@@ -63,38 +63,6 @@ export function taskRequest(operation, input, parts = {}) {
|
|
|
63
63
|
...optionalField("workspace", workspaceOverride(input)),
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
-
/**
|
|
67
|
-
* The only part of a listing page a composing tool reads for itself: the ids of
|
|
68
|
-
* the items it then fans out over. Decoding that alone leaves the raw page
|
|
69
|
-
* intact for the caller, returned exactly as the API sent it, while the ids the
|
|
70
|
-
* tool acts on are validated rather than asserted.
|
|
71
|
-
*/
|
|
72
|
-
const ListingIds = Schema.Struct({
|
|
73
|
-
items: Schema.optional(Schema.Array(Schema.Struct({ id: Schema.optional(Schema.String) }))),
|
|
74
|
-
});
|
|
75
|
-
const decodeListingIds = Schema.decodeUnknownOption(ListingIds);
|
|
76
|
-
/**
|
|
77
|
-
* Ids of the first `limit` items on a listing page. A page whose fields we
|
|
78
|
-
* cannot read, or whose items carry no id, contributes nothing. The tool still
|
|
79
|
-
* returns the page itself rather than failing over a fan-out it cannot do.
|
|
80
|
-
*/
|
|
81
|
-
export function listingIds(page, limit) {
|
|
82
|
-
// Both fallbacks below are empty arrays, and substituting a one-item array
|
|
83
|
-
// for either is an equivalent mutation rather than an untested branch: a
|
|
84
|
-
// substituted item carries no `id`, so the `filter` at the end of this
|
|
85
|
-
// function drops it and the result is the same empty id list. Substituting
|
|
86
|
-
// `undefined` for the outer fallback is a real change and is covered by the
|
|
87
|
-
// undecodable-page test.
|
|
88
|
-
const items = decodeListingIds(page).pipe(
|
|
89
|
-
// Stryker disable next-line ArrayDeclaration: a substituted item has no id and is filtered out below
|
|
90
|
-
Option.map((decoded) => decoded.items ?? []),
|
|
91
|
-
// Stryker disable next-line ArrayDeclaration: a substituted item has no id and is filtered out below
|
|
92
|
-
Option.getOrElse(() => []));
|
|
93
|
-
return items
|
|
94
|
-
.slice(0, limit)
|
|
95
|
-
.map((item) => item.id)
|
|
96
|
-
.filter((id) => id !== undefined);
|
|
97
|
-
}
|
|
98
66
|
/**
|
|
99
67
|
* A request body carrying a single text field, or no body at all when the input
|
|
100
68
|
* is absent or blank. Sending an empty string would mean something different to
|
package/dist/tool.js
CHANGED
|
@@ -95,6 +95,9 @@ function buildFromTaskTool(tool) {
|
|
|
95
95
|
// A task tool overwrites or removes existing state when any write it
|
|
96
96
|
// composes does.
|
|
97
97
|
mutatesExisting: composed.some((operation) => operation.mutatesExisting),
|
|
98
|
+
// Repeating a task tool has no further effect only when that holds for
|
|
99
|
+
// every operation it composes.
|
|
100
|
+
idempotent: composed.every((operation) => operation.idempotent),
|
|
98
101
|
...optionalField("confirm", confirm),
|
|
99
102
|
untrustedContent,
|
|
100
103
|
// A task tool reaches as far as the furthest operation it composes.
|
package/dist/toolsets.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { LUCA_TASK_TOOLS } from "./task-tools.js";
|
|
2
2
|
/**
|
|
3
|
-
* The tools the `claude` toolset exposes
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* The tools the `claude` toolset exposes, and a test pins it name for name.
|
|
4
|
+
* Coaches who chose `?toolset=claude` rely on it staying read and draft, so a
|
|
5
|
+
* tool that sends, books, or changes settings does not belong here.
|
|
6
6
|
*/
|
|
7
7
|
export const CLAUDE_TOOL_NAMES = [
|
|
8
8
|
"luca_triage_inbox",
|
package/dist/version.js
CHANGED
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Bump this in the same commit as package.json and server.json.
|
|
11
11
|
*/
|
|
12
|
-
export const LUCA_MCP_VERSION = "0.5.
|
|
12
|
+
export const LUCA_MCP_VERSION = "0.5.2";
|
|
13
13
|
/** The user-agent every outbound Luca API call identifies itself with. */
|
|
14
14
|
export const LUCA_MCP_USER_AGENT = `luca-mcp/${LUCA_MCP_VERSION}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@setluca/mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Connect SetLuca to Claude, ChatGPT, Cursor, or any MCP client to triage the review queue, look up leads, draft replies, and check campaigns.",
|
|
6
6
|
"keywords": [
|
|
@@ -68,15 +68,17 @@
|
|
|
68
68
|
"registry:check": "bun scripts/check-registry.ts",
|
|
69
69
|
"docs:generate": "bun scripts/generate-docs.ts --write",
|
|
70
70
|
"docs:check": "bun scripts/generate-docs.ts --check",
|
|
71
|
-
"clean": "rm -rf .turbo dist coverage node_modules"
|
|
71
|
+
"clean": "rm -rf .turbo dist coverage node_modules",
|
|
72
|
+
"prepare": "effect-tsgo patch --typescript --no-oxlint"
|
|
72
73
|
},
|
|
73
74
|
"dependencies": {
|
|
74
75
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
75
|
-
"effect": "4.0.
|
|
76
|
+
"effect": "4.0.6"
|
|
76
77
|
},
|
|
77
78
|
"devDependencies": {
|
|
78
|
-
"@effect/platform-bun": "4.0.
|
|
79
|
-
"@effect/
|
|
79
|
+
"@effect/platform-bun": "4.0.6",
|
|
80
|
+
"@effect/tsgo": "0.56.0",
|
|
81
|
+
"@effect/vitest": "4.0.6",
|
|
80
82
|
"@modelcontextprotocol/client": "^2.0.0",
|
|
81
83
|
"@modelcontextprotocol/inspector": "^2.5.0",
|
|
82
84
|
"@mpsuesser/oxlint-plugin-effect": "0.6.0",
|