@speakai/mcp-server 1.12.2 → 1.13.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 +46 -7
- package/dist/index.js +1223 -179
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2390,6 +2390,27 @@ var recorder_exports = {};
|
|
|
2390
2390
|
__export(recorder_exports, {
|
|
2391
2391
|
register: () => register5
|
|
2392
2392
|
});
|
|
2393
|
+
function optionsFromMetaType(metaType) {
|
|
2394
|
+
const bool = (v, fallback) => typeof v === "boolean" ? v : fallback;
|
|
2395
|
+
const upload = metaType?.upload ?? {};
|
|
2396
|
+
return {
|
|
2397
|
+
audio: bool(metaType?.audio, true),
|
|
2398
|
+
video: bool(metaType?.video, true),
|
|
2399
|
+
screenShare: bool(metaType?.screenShare, false),
|
|
2400
|
+
upload: {
|
|
2401
|
+
file: bool(upload.file, true),
|
|
2402
|
+
multiple: bool(upload.multiple, false),
|
|
2403
|
+
url: bool(upload.url, false)
|
|
2404
|
+
},
|
|
2405
|
+
liveTranscription: bool(metaType?.liveTranscription, false)
|
|
2406
|
+
};
|
|
2407
|
+
}
|
|
2408
|
+
function addRecorderOptions(recorder) {
|
|
2409
|
+
if (recorder && typeof recorder === "object") {
|
|
2410
|
+
recorder.options = optionsFromMetaType(recorder.meta?.type);
|
|
2411
|
+
}
|
|
2412
|
+
return recorder;
|
|
2413
|
+
}
|
|
2393
2414
|
function register5(server, client) {
|
|
2394
2415
|
const api = client ?? speakClient;
|
|
2395
2416
|
registerSpeakTool(
|
|
@@ -2441,6 +2462,7 @@ function register5(server, client) {
|
|
|
2441
2462
|
async (body) => {
|
|
2442
2463
|
try {
|
|
2443
2464
|
const result = await api.post("/v1/recorder/create", body);
|
|
2465
|
+
addRecorderOptions(result.data?.data?.recorderData);
|
|
2444
2466
|
return {
|
|
2445
2467
|
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
2446
2468
|
};
|
|
@@ -2471,6 +2493,7 @@ function register5(server, client) {
|
|
|
2471
2493
|
async (params) => {
|
|
2472
2494
|
try {
|
|
2473
2495
|
const result = await api.get("/v1/recorder", { params });
|
|
2496
|
+
result.data?.data?.recorderList?.forEach?.(addRecorderOptions);
|
|
2474
2497
|
return {
|
|
2475
2498
|
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
2476
2499
|
};
|
|
@@ -2530,6 +2553,7 @@ function register5(server, client) {
|
|
|
2530
2553
|
async ({ recorderId }) => {
|
|
2531
2554
|
try {
|
|
2532
2555
|
const result = await api.get(`/v1/recorder/${recorderId}`);
|
|
2556
|
+
addRecorderOptions(result.data?.data);
|
|
2533
2557
|
return {
|
|
2534
2558
|
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
2535
2559
|
};
|
|
@@ -2616,6 +2640,7 @@ function register5(server, client) {
|
|
|
2616
2640
|
async ({ recorderId, ...body }) => {
|
|
2617
2641
|
try {
|
|
2618
2642
|
const result = await api.put(`/v1/recorder/settings/${recorderId}`, body);
|
|
2643
|
+
addRecorderOptions(result.data?.data?.recorderData);
|
|
2619
2644
|
return {
|
|
2620
2645
|
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
2621
2646
|
};
|
|
@@ -3641,8 +3666,16 @@ function register10(server, client) {
|
|
|
3641
3666
|
registerSpeakTool(
|
|
3642
3667
|
server,
|
|
3643
3668
|
"list_automations",
|
|
3644
|
-
"List
|
|
3645
|
-
{
|
|
3669
|
+
"List automation rules in the workspace, with paging and filters.",
|
|
3670
|
+
{
|
|
3671
|
+
page: import_zod11.z.number().int().min(0).optional().describe("0-based page index"),
|
|
3672
|
+
pageSize: import_zod11.z.number().int().min(1).max(100).optional().describe("Results per page"),
|
|
3673
|
+
sortBy: import_zod11.z.string().optional().describe('Sort expression, e.g. "createdAt:desc"'),
|
|
3674
|
+
query: import_zod11.z.string().optional().describe("Free-text search over automation names"),
|
|
3675
|
+
folderIds: import_zod11.z.string().optional().describe("Comma-separated folder ids to filter by"),
|
|
3676
|
+
isActive: import_zod11.z.boolean().optional().describe("Filter by active state"),
|
|
3677
|
+
runType: import_zod11.z.enum(["instant", "schedule"]).optional().describe("Filter by run type")
|
|
3678
|
+
},
|
|
3646
3679
|
{
|
|
3647
3680
|
title: "List Automations",
|
|
3648
3681
|
readOnlyHint: true,
|
|
@@ -3650,9 +3683,35 @@ function register10(server, client) {
|
|
|
3650
3683
|
idempotentHint: true,
|
|
3651
3684
|
openWorldHint: false
|
|
3652
3685
|
},
|
|
3686
|
+
async (params) => {
|
|
3687
|
+
try {
|
|
3688
|
+
const result = await api.get("/v1/automations", { params });
|
|
3689
|
+
return {
|
|
3690
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
3691
|
+
};
|
|
3692
|
+
} catch (err) {
|
|
3693
|
+
return {
|
|
3694
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
3695
|
+
isError: true
|
|
3696
|
+
};
|
|
3697
|
+
}
|
|
3698
|
+
}
|
|
3699
|
+
);
|
|
3700
|
+
registerSpeakTool(
|
|
3701
|
+
server,
|
|
3702
|
+
"list_automation_names",
|
|
3703
|
+
"List automations as lightweight { name, id } pairs \u2014 useful for pickers without fetching full configs.",
|
|
3704
|
+
{},
|
|
3705
|
+
{
|
|
3706
|
+
title: "List Automation Names",
|
|
3707
|
+
readOnlyHint: true,
|
|
3708
|
+
destructiveHint: false,
|
|
3709
|
+
idempotentHint: true,
|
|
3710
|
+
openWorldHint: false
|
|
3711
|
+
},
|
|
3653
3712
|
async () => {
|
|
3654
3713
|
try {
|
|
3655
|
-
const result = await api.get("/v1/automations");
|
|
3714
|
+
const result = await api.get("/v1/automations/list");
|
|
3656
3715
|
return {
|
|
3657
3716
|
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
3658
3717
|
};
|
|
@@ -3667,7 +3726,7 @@ function register10(server, client) {
|
|
|
3667
3726
|
registerSpeakTool(
|
|
3668
3727
|
server,
|
|
3669
3728
|
"get_automation",
|
|
3670
|
-
"Get detailed information about a specific automation rule.",
|
|
3729
|
+
"Get detailed information about a specific automation rule, including its trigger and step graph.",
|
|
3671
3730
|
{
|
|
3672
3731
|
automationId: import_zod11.z.string().min(1).describe("Unique identifier of the automation")
|
|
3673
3732
|
},
|
|
@@ -3694,21 +3753,40 @@ function register10(server, client) {
|
|
|
3694
3753
|
);
|
|
3695
3754
|
registerSpeakTool(
|
|
3696
3755
|
server,
|
|
3697
|
-
"
|
|
3698
|
-
"
|
|
3756
|
+
"get_automation_runs",
|
|
3757
|
+
"Get the run history (executions) for an automation, with paging and optional status filter.",
|
|
3699
3758
|
{
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
)
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3759
|
+
automationId: import_zod11.z.string().min(1).describe("Unique identifier of the automation"),
|
|
3760
|
+
page: import_zod11.z.number().int().min(0).optional().describe("0-based page index"),
|
|
3761
|
+
pageSize: import_zod11.z.number().int().min(1).max(100).optional().describe("Results per page"),
|
|
3762
|
+
status: import_zod11.z.enum(["pending", "running", "completed", "failed", "killed"]).optional().describe("Filter runs by status")
|
|
3763
|
+
},
|
|
3764
|
+
{
|
|
3765
|
+
title: "Get Automation Runs",
|
|
3766
|
+
readOnlyHint: true,
|
|
3767
|
+
destructiveHint: false,
|
|
3768
|
+
idempotentHint: true,
|
|
3769
|
+
openWorldHint: false
|
|
3711
3770
|
},
|
|
3771
|
+
async ({ automationId, ...params }) => {
|
|
3772
|
+
try {
|
|
3773
|
+
const result = await api.get(`/v1/automations/${automationId}/runs`, { params });
|
|
3774
|
+
return {
|
|
3775
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
3776
|
+
};
|
|
3777
|
+
} catch (err) {
|
|
3778
|
+
return {
|
|
3779
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
3780
|
+
isError: true
|
|
3781
|
+
};
|
|
3782
|
+
}
|
|
3783
|
+
}
|
|
3784
|
+
);
|
|
3785
|
+
registerSpeakTool(
|
|
3786
|
+
server,
|
|
3787
|
+
"create_automation",
|
|
3788
|
+
"Create a new automation rule using the V2 graph model (trigger + ordered steps). Fetch valid step/trigger options with list_automation_triggers / list_automation_actions if unsure.",
|
|
3789
|
+
writeSchema,
|
|
3712
3790
|
{
|
|
3713
3791
|
title: "Create Automation",
|
|
3714
3792
|
readOnlyHint: false,
|
|
@@ -3733,20 +3811,10 @@ function register10(server, client) {
|
|
|
3733
3811
|
registerSpeakTool(
|
|
3734
3812
|
server,
|
|
3735
3813
|
"update_automation",
|
|
3736
|
-
"Update an existing automation rule. This replaces the whole automation, so fetch the current values with get_automation first and pass them all back.",
|
|
3814
|
+
"Update an existing automation rule. This replaces the whole automation (name, trigger, and steps), so fetch the current values with get_automation first and pass them all back with your changes.",
|
|
3737
3815
|
{
|
|
3738
3816
|
automationId: import_zod11.z.string().min(1).describe("Unique identifier of the automation"),
|
|
3739
|
-
|
|
3740
|
-
trigger: import_zod11.z.record(import_zod11.z.unknown()).describe(
|
|
3741
|
-
'Trigger object. Keys: `type` (e.g. "folders") and `folderIds` (array of folder IDs).'
|
|
3742
|
-
),
|
|
3743
|
-
action: import_zod11.z.record(import_zod11.z.unknown()).describe(
|
|
3744
|
-
'Single action object (not an array). Keys: `type` ("magic-prompt" or "translation"). For magic-prompt, include a `magicPrompt` object ({ prompt, title?, assistantType?, fieldIds?, ... }). For translation, include a `translation` object ({ targetLanguage }).'
|
|
3745
|
-
),
|
|
3746
|
-
description: import_zod11.z.string().optional().describe("Optional description"),
|
|
3747
|
-
isActive: import_zod11.z.boolean().optional().describe("Whether the automation is active (defaults to true)"),
|
|
3748
|
-
runType: import_zod11.z.string().optional().describe('Run type, e.g. "instant" (default) or "scheduled"'),
|
|
3749
|
-
schedule: import_zod11.z.record(import_zod11.z.unknown()).optional().describe("Schedule object for scheduled automations: { timePeriod, repeatAt }")
|
|
3817
|
+
...writeSchema
|
|
3750
3818
|
},
|
|
3751
3819
|
{
|
|
3752
3820
|
title: "Update Automation",
|
|
@@ -3757,10 +3825,7 @@ function register10(server, client) {
|
|
|
3757
3825
|
},
|
|
3758
3826
|
async ({ automationId, ...body }) => {
|
|
3759
3827
|
try {
|
|
3760
|
-
const result = await api.put(
|
|
3761
|
-
`/v1/automations/${automationId}`,
|
|
3762
|
-
body
|
|
3763
|
-
);
|
|
3828
|
+
const result = await api.put(`/v1/automations/${automationId}`, body);
|
|
3764
3829
|
return {
|
|
3765
3830
|
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
3766
3831
|
};
|
|
@@ -3788,9 +3853,204 @@ function register10(server, client) {
|
|
|
3788
3853
|
},
|
|
3789
3854
|
async ({ automationId }) => {
|
|
3790
3855
|
try {
|
|
3791
|
-
const result = await api.put(
|
|
3792
|
-
|
|
3793
|
-
|
|
3856
|
+
const result = await api.put(`/v1/automations/status/${automationId}`);
|
|
3857
|
+
return {
|
|
3858
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
3859
|
+
};
|
|
3860
|
+
} catch (err) {
|
|
3861
|
+
return {
|
|
3862
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
3863
|
+
isError: true
|
|
3864
|
+
};
|
|
3865
|
+
}
|
|
3866
|
+
}
|
|
3867
|
+
);
|
|
3868
|
+
registerSpeakTool(
|
|
3869
|
+
server,
|
|
3870
|
+
"bulk_update_automation_status",
|
|
3871
|
+
"Activate or deactivate multiple automations at once.",
|
|
3872
|
+
{
|
|
3873
|
+
automationIds: import_zod11.z.array(import_zod11.z.string().min(1)).min(1).max(100).describe("Automation ids to update"),
|
|
3874
|
+
isActive: import_zod11.z.boolean().describe("true to activate, false to deactivate, for all listed automations")
|
|
3875
|
+
},
|
|
3876
|
+
{
|
|
3877
|
+
title: "Bulk Update Automation Status",
|
|
3878
|
+
readOnlyHint: false,
|
|
3879
|
+
destructiveHint: false,
|
|
3880
|
+
idempotentHint: true,
|
|
3881
|
+
openWorldHint: false
|
|
3882
|
+
},
|
|
3883
|
+
async (body) => {
|
|
3884
|
+
try {
|
|
3885
|
+
const result = await api.put("/v1/automations/bulk/status", body);
|
|
3886
|
+
return {
|
|
3887
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
3888
|
+
};
|
|
3889
|
+
} catch (err) {
|
|
3890
|
+
return {
|
|
3891
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
3892
|
+
isError: true
|
|
3893
|
+
};
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3896
|
+
);
|
|
3897
|
+
registerSpeakTool(
|
|
3898
|
+
server,
|
|
3899
|
+
"bulk_assign_automation_folders",
|
|
3900
|
+
"Set the folder scope for multiple automations at once. Pass an empty folderIds array to remove the folder restriction (run on all folders).",
|
|
3901
|
+
{
|
|
3902
|
+
automationIds: import_zod11.z.array(import_zod11.z.string().min(1)).min(1).max(100).describe("Automation ids to update"),
|
|
3903
|
+
folderIds: import_zod11.z.array(import_zod11.z.string().min(1)).max(50).describe("Folder ids to scope the automations to. Empty array = all folders.")
|
|
3904
|
+
},
|
|
3905
|
+
{
|
|
3906
|
+
title: "Bulk Assign Automation Folders",
|
|
3907
|
+
readOnlyHint: false,
|
|
3908
|
+
destructiveHint: false,
|
|
3909
|
+
idempotentHint: true,
|
|
3910
|
+
openWorldHint: false
|
|
3911
|
+
},
|
|
3912
|
+
async (body) => {
|
|
3913
|
+
try {
|
|
3914
|
+
const result = await api.put("/v1/automations/bulk/folders", body);
|
|
3915
|
+
return {
|
|
3916
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
3917
|
+
};
|
|
3918
|
+
} catch (err) {
|
|
3919
|
+
return {
|
|
3920
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
3921
|
+
isError: true
|
|
3922
|
+
};
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
3925
|
+
);
|
|
3926
|
+
registerSpeakTool(
|
|
3927
|
+
server,
|
|
3928
|
+
"run_automations",
|
|
3929
|
+
"Manually run one or more automations against one or more media items now (outside the normal trigger).",
|
|
3930
|
+
{
|
|
3931
|
+
mediaIds: import_zod11.z.array(import_zod11.z.string().min(1)).min(1).describe("Media ids to run the automations against"),
|
|
3932
|
+
automationIds: import_zod11.z.array(import_zod11.z.string().min(1)).min(1).describe("Automation ids to run")
|
|
3933
|
+
},
|
|
3934
|
+
{
|
|
3935
|
+
title: "Run Automations",
|
|
3936
|
+
readOnlyHint: false,
|
|
3937
|
+
destructiveHint: false,
|
|
3938
|
+
idempotentHint: false,
|
|
3939
|
+
openWorldHint: false
|
|
3940
|
+
},
|
|
3941
|
+
async (body) => {
|
|
3942
|
+
try {
|
|
3943
|
+
const result = await api.post("/v1/automations/run", body);
|
|
3944
|
+
return {
|
|
3945
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
3946
|
+
};
|
|
3947
|
+
} catch (err) {
|
|
3948
|
+
return {
|
|
3949
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
3950
|
+
isError: true
|
|
3951
|
+
};
|
|
3952
|
+
}
|
|
3953
|
+
}
|
|
3954
|
+
);
|
|
3955
|
+
registerSpeakTool(
|
|
3956
|
+
server,
|
|
3957
|
+
"delete_automation",
|
|
3958
|
+
"Permanently delete an automation rule.",
|
|
3959
|
+
{
|
|
3960
|
+
automationId: import_zod11.z.string().min(1).describe("Unique identifier of the automation to delete")
|
|
3961
|
+
},
|
|
3962
|
+
{
|
|
3963
|
+
title: "Delete Automation",
|
|
3964
|
+
readOnlyHint: false,
|
|
3965
|
+
destructiveHint: true,
|
|
3966
|
+
idempotentHint: true,
|
|
3967
|
+
openWorldHint: false
|
|
3968
|
+
},
|
|
3969
|
+
async ({ automationId }) => {
|
|
3970
|
+
try {
|
|
3971
|
+
const result = await api.delete(`/v1/automations/${automationId}`);
|
|
3972
|
+
return {
|
|
3973
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
3974
|
+
};
|
|
3975
|
+
} catch (err) {
|
|
3976
|
+
return {
|
|
3977
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
3978
|
+
isError: true
|
|
3979
|
+
};
|
|
3980
|
+
}
|
|
3981
|
+
}
|
|
3982
|
+
);
|
|
3983
|
+
registerSpeakTool(
|
|
3984
|
+
server,
|
|
3985
|
+
"list_automation_apps",
|
|
3986
|
+
"List the apps available in the automation catalog (e.g. Speak native + connected integrations). Use to discover what triggers/actions exist before building an automation.",
|
|
3987
|
+
{},
|
|
3988
|
+
{
|
|
3989
|
+
title: "List Automation Apps",
|
|
3990
|
+
readOnlyHint: true,
|
|
3991
|
+
destructiveHint: false,
|
|
3992
|
+
idempotentHint: true,
|
|
3993
|
+
openWorldHint: false
|
|
3994
|
+
},
|
|
3995
|
+
async () => {
|
|
3996
|
+
try {
|
|
3997
|
+
const result = await api.get("/v1/automations/catalog/apps");
|
|
3998
|
+
return {
|
|
3999
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
4000
|
+
};
|
|
4001
|
+
} catch (err) {
|
|
4002
|
+
return {
|
|
4003
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
4004
|
+
isError: true
|
|
4005
|
+
};
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
);
|
|
4009
|
+
registerSpeakTool(
|
|
4010
|
+
server,
|
|
4011
|
+
"list_automation_triggers",
|
|
4012
|
+
"List the trigger types available in the automation catalog. Optionally filter by app.",
|
|
4013
|
+
{
|
|
4014
|
+
app: import_zod11.z.string().min(1).max(100).optional().describe("Filter triggers to a specific app slug")
|
|
4015
|
+
},
|
|
4016
|
+
{
|
|
4017
|
+
title: "List Automation Triggers",
|
|
4018
|
+
readOnlyHint: true,
|
|
4019
|
+
destructiveHint: false,
|
|
4020
|
+
idempotentHint: true,
|
|
4021
|
+
openWorldHint: false
|
|
4022
|
+
},
|
|
4023
|
+
async (params) => {
|
|
4024
|
+
try {
|
|
4025
|
+
const result = await api.get("/v1/automations/catalog/triggers", { params });
|
|
4026
|
+
return {
|
|
4027
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
4028
|
+
};
|
|
4029
|
+
} catch (err) {
|
|
4030
|
+
return {
|
|
4031
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
4032
|
+
isError: true
|
|
4033
|
+
};
|
|
4034
|
+
}
|
|
4035
|
+
}
|
|
4036
|
+
);
|
|
4037
|
+
registerSpeakTool(
|
|
4038
|
+
server,
|
|
4039
|
+
"list_automation_actions",
|
|
4040
|
+
"List the action/step types available in the automation catalog. Optionally filter by app.",
|
|
4041
|
+
{
|
|
4042
|
+
app: import_zod11.z.string().min(1).max(100).optional().describe("Filter actions to a specific app slug")
|
|
4043
|
+
},
|
|
4044
|
+
{
|
|
4045
|
+
title: "List Automation Actions",
|
|
4046
|
+
readOnlyHint: true,
|
|
4047
|
+
destructiveHint: false,
|
|
4048
|
+
idempotentHint: true,
|
|
4049
|
+
openWorldHint: false
|
|
4050
|
+
},
|
|
4051
|
+
async (params) => {
|
|
4052
|
+
try {
|
|
4053
|
+
const result = await api.get("/v1/automations/catalog/actions", { params });
|
|
3794
4054
|
return {
|
|
3795
4055
|
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
3796
4056
|
};
|
|
@@ -3803,13 +4063,26 @@ function register10(server, client) {
|
|
|
3803
4063
|
}
|
|
3804
4064
|
);
|
|
3805
4065
|
}
|
|
3806
|
-
var import_zod11;
|
|
4066
|
+
var import_zod11, STEPS_DESCRIPTION, TRIGGER_DESCRIPTION, writeSchema;
|
|
3807
4067
|
var init_automations = __esm({
|
|
3808
4068
|
"src/tools/automations.ts"() {
|
|
3809
4069
|
"use strict";
|
|
3810
4070
|
import_zod11 = require("zod");
|
|
3811
4071
|
init_helpers();
|
|
3812
4072
|
init_client();
|
|
4073
|
+
STEPS_DESCRIPTION = 'Ordered array of graph steps (1-20). Each step is an object: { stepId: string (unique within the array), stepType: one of "magic-prompt" | "translation" | "filter" | "composio-action" | "speak-upload", dependsOn?: string[] (stepIds this step runs after) } plus ONE payload key matching stepType:\n- magic-prompt -> magicPrompt: { prompt (required unless fieldIds given), title?, assistantType? ("general"|"researcher"|"marketer"|"sales"|"recruiter"|"custom", default "general"), assistantTemplateId? (required if assistantType="custom"), fieldIds?: string[] (max 10, for field extraction) }\n- translation -> translation: { targetLanguage: BCP-47 code, e.g. "es" }\n- filter -> filter: { logic: "AND"|"OR", rules: [{ field, op: "eq"|"neq"|"contains"|"ncontains"|"startsWith"|"gt"|"lt"|"exists", value? }] }\n- composio-action -> composio: { app, action, connectedAccountId?, argsTemplate? } (Composio is currently behind a server flag and may be unavailable)\n- speak-upload -> speakUpload: { folderId, sourceMode: "url"|"file", sourceUrl? (required when sourceMode="url"), name?, fieldsMap?, language? }';
|
|
4074
|
+
TRIGGER_DESCRIPTION = 'Trigger object. For folder-based automations: { type: "folders", folderIds: string[] } (at least one folder is required). Note: only "folders" is currently supported for multi-step automations via the API \u2014 "tags"/"keywords" are rejected, and "composio"/"webhook" triggers (provider, app, triggerSlug, webhookId, childKey, connectedAccountId) are gated by server flags.';
|
|
4075
|
+
writeSchema = {
|
|
4076
|
+
name: import_zod11.z.string().min(1).max(150).describe("Display name for the automation"),
|
|
4077
|
+
trigger: import_zod11.z.record(import_zod11.z.unknown()).describe(TRIGGER_DESCRIPTION),
|
|
4078
|
+
steps: import_zod11.z.array(import_zod11.z.record(import_zod11.z.unknown())).min(1).max(20).describe(STEPS_DESCRIPTION),
|
|
4079
|
+
description: import_zod11.z.string().max(1e3).optional().describe("Optional description"),
|
|
4080
|
+
isActive: import_zod11.z.boolean().optional().describe("Whether the automation is active (defaults to true)"),
|
|
4081
|
+
runType: import_zod11.z.enum(["instant", "schedule"]).optional().describe('Run type: "instant" (default, runs on trigger) or "schedule" (cron)'),
|
|
4082
|
+
schedule: import_zod11.z.record(import_zod11.z.unknown()).optional().describe(
|
|
4083
|
+
'Required when runType="schedule": { timePeriod: "today"|"yesterday"|"last7days"|"last14days"|"thisWeek", repeatAt: string }'
|
|
4084
|
+
)
|
|
4085
|
+
};
|
|
3813
4086
|
}
|
|
3814
4087
|
});
|
|
3815
4088
|
|
|
@@ -4379,36 +4652,708 @@ var init_workflows = __esm({
|
|
|
4379
4652
|
}
|
|
4380
4653
|
});
|
|
4381
4654
|
|
|
4382
|
-
// src/tools/
|
|
4383
|
-
var
|
|
4384
|
-
__export(
|
|
4385
|
-
|
|
4655
|
+
// src/tools/users.ts
|
|
4656
|
+
var users_exports = {};
|
|
4657
|
+
__export(users_exports, {
|
|
4658
|
+
register: () => register15
|
|
4386
4659
|
});
|
|
4387
|
-
function
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4660
|
+
function register15(server, client) {
|
|
4661
|
+
const api = client ?? speakClient;
|
|
4662
|
+
registerSpeakTool(
|
|
4663
|
+
server,
|
|
4664
|
+
"list_users",
|
|
4665
|
+
"List the users (members) in the workspace/company, with their ids, names, emails, and permissions. Use the returned _id values when assigning members to user groups.",
|
|
4666
|
+
{
|
|
4667
|
+
filterName: import_zod16.z.string().optional().describe(
|
|
4668
|
+
'Search text. Plain text matches first/last name or email; prefix with "email:" or "name:" to scope, e.g. "email:jane@acme.com".'
|
|
4669
|
+
),
|
|
4670
|
+
sortBy: import_zod16.z.string().optional().describe('Sort expression "field:asc" or "field:desc", e.g. "createdAt:desc", "email:asc"'),
|
|
4671
|
+
page: import_zod16.z.number().int().min(0).optional().describe("0-based page index (default 0)"),
|
|
4672
|
+
pageSize: import_zod16.z.number().int().min(1).max(200).optional().describe("Results per page (default 50)")
|
|
4673
|
+
},
|
|
4674
|
+
{
|
|
4675
|
+
title: "List Users",
|
|
4676
|
+
readOnlyHint: true,
|
|
4677
|
+
destructiveHint: false,
|
|
4678
|
+
idempotentHint: true,
|
|
4679
|
+
openWorldHint: false
|
|
4680
|
+
},
|
|
4681
|
+
async (params) => {
|
|
4682
|
+
try {
|
|
4683
|
+
const result = await api.get("/v1/admin/users", { params });
|
|
4684
|
+
return {
|
|
4685
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
4686
|
+
};
|
|
4687
|
+
} catch (err) {
|
|
4688
|
+
return {
|
|
4689
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
4690
|
+
isError: true
|
|
4691
|
+
};
|
|
4692
|
+
}
|
|
4693
|
+
}
|
|
4694
|
+
);
|
|
4695
|
+
registerSpeakTool(
|
|
4696
|
+
server,
|
|
4697
|
+
"list_user_groups",
|
|
4698
|
+
"List all user groups in the company. Each group includes its members (hydrated names/emails) and member ids. Use this to discover group ids and current membership before updating or deleting a group.",
|
|
4699
|
+
{},
|
|
4700
|
+
{
|
|
4701
|
+
title: "List User Groups",
|
|
4702
|
+
readOnlyHint: true,
|
|
4703
|
+
destructiveHint: false,
|
|
4704
|
+
idempotentHint: true,
|
|
4705
|
+
openWorldHint: false
|
|
4706
|
+
},
|
|
4707
|
+
async () => {
|
|
4708
|
+
try {
|
|
4709
|
+
const result = await api.get("/v1/admin/usergroup");
|
|
4710
|
+
return {
|
|
4711
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
4712
|
+
};
|
|
4713
|
+
} catch (err) {
|
|
4714
|
+
return {
|
|
4715
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
4716
|
+
isError: true
|
|
4717
|
+
};
|
|
4718
|
+
}
|
|
4719
|
+
}
|
|
4720
|
+
);
|
|
4721
|
+
registerSpeakTool(
|
|
4722
|
+
server,
|
|
4723
|
+
"create_user_group",
|
|
4724
|
+
"Create a new user group and assign members. Member ids come from list_users. Fails with a 409 if a group with the same name already exists in the company.",
|
|
4725
|
+
{
|
|
4726
|
+
description: import_zod16.z.string().min(1).describe("Group name"),
|
|
4727
|
+
users: import_zod16.z.array(import_zod16.z.string().min(1)).default([]).describe("User _id strings to add as members (fetch via list_users)")
|
|
4728
|
+
},
|
|
4729
|
+
{
|
|
4730
|
+
title: "Create User Group",
|
|
4731
|
+
readOnlyHint: false,
|
|
4732
|
+
destructiveHint: false,
|
|
4733
|
+
idempotentHint: false,
|
|
4734
|
+
openWorldHint: false
|
|
4735
|
+
},
|
|
4736
|
+
async (body) => {
|
|
4737
|
+
try {
|
|
4738
|
+
const result = await api.post("/v1/admin/usergroup", body);
|
|
4739
|
+
return {
|
|
4740
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
4741
|
+
};
|
|
4742
|
+
} catch (err) {
|
|
4743
|
+
return {
|
|
4744
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
4745
|
+
isError: true
|
|
4746
|
+
};
|
|
4747
|
+
}
|
|
4748
|
+
}
|
|
4749
|
+
);
|
|
4750
|
+
registerSpeakTool(
|
|
4751
|
+
server,
|
|
4752
|
+
"update_user_group",
|
|
4753
|
+
"Update a user group's name and member list. NOTE: the users array is a FULL REPLACEMENT, not a delta \u2014 any member id you omit is removed from the group. Fetch the current members with list_user_groups first and send the complete list.",
|
|
4754
|
+
{
|
|
4755
|
+
_id: import_zod16.z.string().min(1).describe("Group _id to update (from list_user_groups)"),
|
|
4756
|
+
description: import_zod16.z.string().min(1).describe("New group name"),
|
|
4757
|
+
users: import_zod16.z.array(import_zod16.z.string().min(1)).describe("Full replacement list of member _id strings (omitted users are removed)")
|
|
4758
|
+
},
|
|
4759
|
+
{
|
|
4760
|
+
title: "Update User Group",
|
|
4761
|
+
readOnlyHint: false,
|
|
4762
|
+
destructiveHint: false,
|
|
4763
|
+
idempotentHint: true,
|
|
4764
|
+
openWorldHint: false
|
|
4765
|
+
},
|
|
4766
|
+
async (body) => {
|
|
4767
|
+
try {
|
|
4768
|
+
const result = await api.put("/v1/admin/usergroup", body);
|
|
4769
|
+
return {
|
|
4770
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
4771
|
+
};
|
|
4772
|
+
} catch (err) {
|
|
4773
|
+
return {
|
|
4774
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
4775
|
+
isError: true
|
|
4776
|
+
};
|
|
4777
|
+
}
|
|
4778
|
+
}
|
|
4779
|
+
);
|
|
4780
|
+
registerSpeakTool(
|
|
4781
|
+
server,
|
|
4782
|
+
"delete_user_group",
|
|
4783
|
+
"Delete a user group. This removes the group only; it does not delete the users themselves.",
|
|
4784
|
+
{
|
|
4785
|
+
id: import_zod16.z.string().min(1).describe("Group _id to delete (from list_user_groups)")
|
|
4786
|
+
},
|
|
4787
|
+
{
|
|
4788
|
+
title: "Delete User Group",
|
|
4789
|
+
readOnlyHint: false,
|
|
4790
|
+
destructiveHint: true,
|
|
4791
|
+
idempotentHint: true,
|
|
4792
|
+
openWorldHint: false
|
|
4793
|
+
},
|
|
4794
|
+
async ({ id }) => {
|
|
4795
|
+
try {
|
|
4796
|
+
const result = await api.delete(`/v1/admin/usergroup/${id}`);
|
|
4797
|
+
return {
|
|
4798
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
4799
|
+
};
|
|
4800
|
+
} catch (err) {
|
|
4801
|
+
return {
|
|
4802
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
4803
|
+
isError: true
|
|
4804
|
+
};
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
4807
|
+
);
|
|
4808
|
+
}
|
|
4809
|
+
var import_zod16;
|
|
4810
|
+
var init_users = __esm({
|
|
4811
|
+
"src/tools/users.ts"() {
|
|
4812
|
+
"use strict";
|
|
4813
|
+
import_zod16 = require("zod");
|
|
4814
|
+
init_helpers();
|
|
4815
|
+
init_client();
|
|
4816
|
+
}
|
|
4817
|
+
});
|
|
4818
|
+
|
|
4819
|
+
// src/tools/dashboard-widgets.ts
|
|
4820
|
+
function buildDashboardWidgets(items) {
|
|
4821
|
+
let y = 0;
|
|
4822
|
+
let rowX = 0;
|
|
4823
|
+
let rowH = 0;
|
|
4824
|
+
return items.map((item) => {
|
|
4825
|
+
const meta = WIDGET_META[item.type];
|
|
4826
|
+
const full = meta.w >= GRID_COLS;
|
|
4827
|
+
let x;
|
|
4828
|
+
if (full) {
|
|
4829
|
+
if (rowX !== 0) {
|
|
4830
|
+
y += rowH;
|
|
4831
|
+
rowX = 0;
|
|
4832
|
+
rowH = 0;
|
|
4833
|
+
}
|
|
4834
|
+
x = 0;
|
|
4835
|
+
const widget2 = makeWidget(item, x, y);
|
|
4836
|
+
y += meta.h;
|
|
4837
|
+
return widget2;
|
|
4838
|
+
}
|
|
4839
|
+
if (rowX + meta.w > GRID_COLS) {
|
|
4840
|
+
y += rowH;
|
|
4841
|
+
rowX = 0;
|
|
4842
|
+
rowH = 0;
|
|
4843
|
+
}
|
|
4844
|
+
x = rowX;
|
|
4845
|
+
const widget = makeWidget(item, x, y);
|
|
4846
|
+
rowX += meta.w;
|
|
4847
|
+
rowH = Math.max(rowH, meta.h);
|
|
4848
|
+
if (rowX >= GRID_COLS) {
|
|
4849
|
+
y += rowH;
|
|
4850
|
+
rowX = 0;
|
|
4851
|
+
rowH = 0;
|
|
4852
|
+
}
|
|
4853
|
+
return widget;
|
|
4854
|
+
});
|
|
4855
|
+
}
|
|
4856
|
+
function makeWidget(item, x, y) {
|
|
4857
|
+
const meta = WIDGET_META[item.type];
|
|
4858
|
+
return {
|
|
4859
|
+
id: (0, import_crypto.randomUUID)(),
|
|
4860
|
+
type: item.type,
|
|
4861
|
+
title: item.title ?? meta.titleDefault,
|
|
4862
|
+
config: item.config ?? {},
|
|
4863
|
+
layout: { x, y, w: meta.w, h: meta.h, minW: meta.minW, minH: meta.minH }
|
|
4864
|
+
};
|
|
4865
|
+
}
|
|
4866
|
+
var import_crypto, GRID_COLS, WIDGET_TYPES, WIDGET_META, WIDGET_CATALOG, COMMON_WIDGET_CONFIG, DASHBOARD_EXAMPLES;
|
|
4867
|
+
var init_dashboard_widgets = __esm({
|
|
4868
|
+
"src/tools/dashboard-widgets.ts"() {
|
|
4869
|
+
"use strict";
|
|
4870
|
+
import_crypto = require("crypto");
|
|
4871
|
+
GRID_COLS = 12;
|
|
4872
|
+
WIDGET_TYPES = [
|
|
4873
|
+
"stat-cards",
|
|
4874
|
+
"sentiment",
|
|
4875
|
+
"media-list",
|
|
4876
|
+
"field-distribution",
|
|
4877
|
+
"upload-timeline",
|
|
4878
|
+
"themes",
|
|
4879
|
+
"team-activity",
|
|
4880
|
+
"kpi-trend",
|
|
4881
|
+
"field-metric",
|
|
4882
|
+
"metric-group",
|
|
4883
|
+
"notes",
|
|
4884
|
+
"people",
|
|
4885
|
+
"comparison",
|
|
4886
|
+
"sentiment-trend"
|
|
4887
|
+
];
|
|
4888
|
+
WIDGET_META = {
|
|
4889
|
+
"stat-cards": { w: GRID_COLS, h: 3, minW: 4, minH: 2, titleDefault: "Usage overview" },
|
|
4890
|
+
sentiment: { w: 6, h: 4, minW: 3, minH: 3, titleDefault: "Sentiment" },
|
|
4891
|
+
"media-list": { w: GRID_COLS, h: 4, minW: 4, minH: 3, titleDefault: "Recent media" },
|
|
4892
|
+
"field-distribution": { w: 6, h: 4, minW: 3, minH: 3, titleDefault: "Field breakdown" },
|
|
4893
|
+
"upload-timeline": { w: 6, h: 4, minW: 3, minH: 3, titleDefault: "Uploads over time" },
|
|
4894
|
+
themes: { w: 6, h: 4, minW: 3, minH: 3, titleDefault: "Themes" },
|
|
4895
|
+
"team-activity": { w: 6, h: 4, minW: 3, minH: 3, titleDefault: "Team activity" },
|
|
4896
|
+
"kpi-trend": { w: 3, h: 2, minW: 2, minH: 2, titleDefault: "Total files" },
|
|
4897
|
+
"field-metric": { w: 3, h: 2, minW: 2, minH: 2, titleDefault: "Field metric" },
|
|
4898
|
+
"metric-group": { w: 6, h: 2, minW: 3, minH: 2, titleDefault: "Metrics" },
|
|
4899
|
+
notes: { w: GRID_COLS, h: 2, minW: 2, minH: 1, titleDefault: "Note" },
|
|
4900
|
+
people: { w: 6, h: 4, minW: 3, minH: 3, titleDefault: "People" },
|
|
4901
|
+
comparison: { w: 6, h: 3, minW: 3, minH: 2, titleDefault: "Comparison" },
|
|
4902
|
+
"sentiment-trend": { w: 6, h: 4, minW: 3, minH: 3, titleDefault: "Sentiment over time" }
|
|
4903
|
+
};
|
|
4904
|
+
WIDGET_CATALOG = [
|
|
4905
|
+
{
|
|
4906
|
+
type: "stat-cards",
|
|
4907
|
+
purpose: "Headline totals for the scope (full width).",
|
|
4908
|
+
config: 'metrics?: string[] \u2014 any of "media", "storage", "words", "speakers", "duration", "sentiment"'
|
|
4909
|
+
},
|
|
4910
|
+
{ type: "sentiment", purpose: "Sentiment distribution + representative sentences.", config: "none" },
|
|
4911
|
+
{ type: "media-list", purpose: "Most recent media in scope (full width).", config: "none" },
|
|
4912
|
+
{
|
|
4913
|
+
type: "field-distribution",
|
|
4914
|
+
purpose: "Value-frequency breakdown for one custom field.",
|
|
4915
|
+
config: 'fieldId: string (a custom field id from list_fields); measure?: "count" | "words" | "duration" | "avg:<numericFieldId>" | "sum:<numericFieldId>"'
|
|
4916
|
+
},
|
|
4917
|
+
{ type: "upload-timeline", purpose: "Uploads over time per media type.", config: "none" },
|
|
4918
|
+
{ type: "themes", purpose: "Dominant theme clusters.", config: 'chartType?: "cloud" | "bar"' },
|
|
4919
|
+
{ type: "team-activity", purpose: "Activity by team member.", config: "none" },
|
|
4920
|
+
{
|
|
4921
|
+
type: "kpi-trend",
|
|
4922
|
+
purpose: "A KPI with period-over-period delta.",
|
|
4923
|
+
config: 'metrics?: string[] \u2014 any of "totalFiles", "totalDurationSeconds", "totalWords", "uniqueSpeakers"'
|
|
4924
|
+
},
|
|
4925
|
+
{
|
|
4926
|
+
type: "field-metric",
|
|
4927
|
+
purpose: "A single custom field's aggregate, with a period-over-period delta.",
|
|
4928
|
+
config: 'fieldId: string (custom field id from list_fields); aggregator: "sum" | "avg" | "min" | "max" | "count"'
|
|
4929
|
+
},
|
|
4930
|
+
{
|
|
4931
|
+
type: "metric-group",
|
|
4932
|
+
purpose: "A scorecard of several field metrics in one card.",
|
|
4933
|
+
config: 'metrics: Array<{ fieldId: string, op: "sum"|"avg"|"min"|"max"|"count", label?: string }> (note the per-item key is `op`, not `aggregator`)'
|
|
4934
|
+
},
|
|
4935
|
+
{
|
|
4936
|
+
type: "notes",
|
|
4937
|
+
purpose: "Free-text note/context block (full width).",
|
|
4938
|
+
config: "heading?: string; content?: string"
|
|
4939
|
+
},
|
|
4940
|
+
{ type: "people", purpose: "Speaker/people breakdown.", config: "none" },
|
|
4941
|
+
{
|
|
4942
|
+
type: "comparison",
|
|
4943
|
+
purpose: "Period-over-period comparison of KPIs.",
|
|
4944
|
+
config: 'metrics?: string[] \u2014 any of "totalFiles", "totalDurationSeconds", "totalWords", "uniqueSpeakers"'
|
|
4945
|
+
},
|
|
4946
|
+
{ type: "sentiment-trend", purpose: "Sentiment over time.", config: "none" }
|
|
4947
|
+
];
|
|
4948
|
+
COMMON_WIDGET_CONFIG = [
|
|
4949
|
+
{
|
|
4950
|
+
key: "accentColor",
|
|
4951
|
+
appliesTo: "any widget",
|
|
4952
|
+
description: 'Hex color for the widget accent, e.g. "#6366F1". Omit for the default.'
|
|
4953
|
+
},
|
|
4954
|
+
{
|
|
4955
|
+
key: "scopeOverride",
|
|
4956
|
+
appliesTo: "any widget except notes",
|
|
4957
|
+
description: "Override the dashboard's scope for just this widget: { datePreset: string, folderId: string }. Omit to inherit the dashboard scope."
|
|
4958
|
+
}
|
|
4959
|
+
];
|
|
4960
|
+
DASHBOARD_EXAMPLES = [
|
|
4961
|
+
{
|
|
4962
|
+
name: "Sales calls overview",
|
|
4963
|
+
payload: {
|
|
4964
|
+
title: "Customer Calls Overview",
|
|
4965
|
+
folderScope: ["<folderId>"],
|
|
4966
|
+
dateRange: { preset: "last30days" },
|
|
4967
|
+
filters: { filterList: [{ fieldName: "Stage", fieldOperator: "is", fieldValue: ["Closed Won"] }] },
|
|
4968
|
+
widgets: [
|
|
4969
|
+
{ type: "stat-cards", config: { metrics: ["media", "words", "speakers"] } },
|
|
4970
|
+
{ type: "sentiment", config: { accentColor: "#6366F1" } },
|
|
4971
|
+
{ type: "field-distribution", title: "Deals by stage", config: { fieldId: "<fieldId>", measure: "count" } },
|
|
4972
|
+
{ type: "themes", config: { chartType: "bar" } },
|
|
4973
|
+
{ type: "media-list" }
|
|
4974
|
+
]
|
|
4975
|
+
}
|
|
4976
|
+
},
|
|
4977
|
+
{
|
|
4978
|
+
name: "Field-metrics scorecard (new widgets)",
|
|
4979
|
+
payload: {
|
|
4980
|
+
title: "Deal Metrics",
|
|
4981
|
+
folderScope: ["<folderId>"],
|
|
4982
|
+
dateRange: { preset: "thisQuarter" },
|
|
4983
|
+
widgets: [
|
|
4984
|
+
{ type: "kpi-trend", title: "Total calls", config: { metrics: ["totalFiles"] } },
|
|
4985
|
+
{ type: "field-metric", title: "Avg deal size", config: { fieldId: "<dealSizeFieldId>", aggregator: "avg" } },
|
|
4986
|
+
{
|
|
4987
|
+
type: "metric-group",
|
|
4988
|
+
title: "Pipeline",
|
|
4989
|
+
config: {
|
|
4990
|
+
metrics: [
|
|
4991
|
+
{ fieldId: "<dealSizeFieldId>", op: "sum", label: "Total pipeline" },
|
|
4992
|
+
{ fieldId: "<dealSizeFieldId>", op: "max", label: "Largest deal" }
|
|
4993
|
+
]
|
|
4994
|
+
}
|
|
4995
|
+
},
|
|
4996
|
+
// Per-widget scope override: this card ignores the dashboard scope.
|
|
4997
|
+
{ type: "field-metric", title: "EMEA avg", config: { fieldId: "<dealSizeFieldId>", aggregator: "avg", scopeOverride: { datePreset: "last7days", folderId: "<emeaFolderId>" } } }
|
|
4998
|
+
]
|
|
4999
|
+
}
|
|
5000
|
+
}
|
|
5001
|
+
];
|
|
5002
|
+
}
|
|
5003
|
+
});
|
|
5004
|
+
|
|
5005
|
+
// src/tools/dashboards.ts
|
|
5006
|
+
var dashboards_exports = {};
|
|
5007
|
+
__export(dashboards_exports, {
|
|
5008
|
+
register: () => register16
|
|
5009
|
+
});
|
|
5010
|
+
function withBuiltWidgets(body) {
|
|
5011
|
+
if (Array.isArray(body.widgets)) {
|
|
5012
|
+
return { ...body, widgets: buildDashboardWidgets(body.widgets) };
|
|
5013
|
+
}
|
|
5014
|
+
return body;
|
|
5015
|
+
}
|
|
5016
|
+
function register16(server, client) {
|
|
5017
|
+
const api = client ?? speakClient;
|
|
5018
|
+
registerSpeakTool(
|
|
5019
|
+
server,
|
|
5020
|
+
"list_dashboards",
|
|
5021
|
+
"List all analytics dashboards the caller can access, including share state.",
|
|
5022
|
+
{},
|
|
5023
|
+
{
|
|
5024
|
+
title: "List Dashboards",
|
|
5025
|
+
readOnlyHint: true,
|
|
5026
|
+
destructiveHint: false,
|
|
5027
|
+
idempotentHint: true,
|
|
5028
|
+
openWorldHint: false
|
|
5029
|
+
},
|
|
5030
|
+
async () => {
|
|
5031
|
+
try {
|
|
5032
|
+
const result = await api.get("/v1/dashboards");
|
|
5033
|
+
return {
|
|
5034
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
5035
|
+
};
|
|
5036
|
+
} catch (err) {
|
|
5037
|
+
return {
|
|
5038
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
5039
|
+
isError: true
|
|
5040
|
+
};
|
|
5041
|
+
}
|
|
5042
|
+
}
|
|
5043
|
+
);
|
|
5044
|
+
registerSpeakTool(
|
|
5045
|
+
server,
|
|
5046
|
+
"get_dashboard",
|
|
5047
|
+
"Get a single dashboard's full config (widgets, filters, date range, folder scope).",
|
|
5048
|
+
{
|
|
5049
|
+
dashboardId: import_zod17.z.string().min(1).describe("Dashboard business id (the dashboardId field from list_dashboards, not the Mongo _id)")
|
|
5050
|
+
},
|
|
5051
|
+
{
|
|
5052
|
+
title: "Get Dashboard",
|
|
5053
|
+
readOnlyHint: true,
|
|
5054
|
+
destructiveHint: false,
|
|
5055
|
+
idempotentHint: true,
|
|
5056
|
+
openWorldHint: false
|
|
5057
|
+
},
|
|
5058
|
+
async ({ dashboardId }) => {
|
|
5059
|
+
try {
|
|
5060
|
+
const result = await api.get(`/v1/dashboards/${dashboardId}`);
|
|
5061
|
+
return {
|
|
5062
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
5063
|
+
};
|
|
5064
|
+
} catch (err) {
|
|
5065
|
+
return {
|
|
5066
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
5067
|
+
isError: true
|
|
5068
|
+
};
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
);
|
|
5072
|
+
registerSpeakTool(
|
|
5073
|
+
server,
|
|
5074
|
+
"list_dashboard_widgets",
|
|
5075
|
+
"Discovery + how-to helper for building and customizing dashboards. Returns every widget type with what it shows and the exact `config` keys it accepts (metrics, fieldId, aggregator, chartType, accentColor, scopeOverride, \u2026), the config that applies to all widgets, two complete worked example payloads (including the field-metric and metric-group cards), and tips for managing dashboards. Call this before create_dashboard / update_dashboard.",
|
|
5076
|
+
{},
|
|
5077
|
+
{
|
|
5078
|
+
title: "List Dashboard Widgets",
|
|
5079
|
+
readOnlyHint: true,
|
|
5080
|
+
destructiveHint: false,
|
|
5081
|
+
idempotentHint: true,
|
|
5082
|
+
openWorldHint: false
|
|
5083
|
+
},
|
|
5084
|
+
async () => {
|
|
5085
|
+
const data = {
|
|
5086
|
+
widgets: WIDGET_CATALOG,
|
|
5087
|
+
commonConfig: COMMON_WIDGET_CONFIG,
|
|
5088
|
+
notes: [
|
|
5089
|
+
"Pass widgets to create_dashboard as a simple ordered list; ids and grid layout are computed for you.",
|
|
5090
|
+
"Field-driven widgets (field-distribution, field-metric, metric-group) need custom field ids from list_fields in their config.",
|
|
5091
|
+
"field-metric uses config.aggregator; metric-group items use the key `op` (both: sum|avg|min|max|count).",
|
|
5092
|
+
"accentColor (hex) and scopeOverride ({datePreset, folderId}) can be set on any widget's config to customize it.",
|
|
5093
|
+
"Most other widgets render on sensible defaults with no config."
|
|
5094
|
+
],
|
|
5095
|
+
managing: [
|
|
5096
|
+
"To customize an existing dashboard, call get_dashboard, edit the widgets array, and send the full array to update_dashboard (widgets are replaced, not merged).",
|
|
5097
|
+
"To start from a working layout, duplicate_dashboard a good one, then update_dashboard to tweak it.",
|
|
5098
|
+
"share_dashboard returns a public token; chain it after the dashboard is built."
|
|
5099
|
+
],
|
|
5100
|
+
examples: DASHBOARD_EXAMPLES
|
|
5101
|
+
};
|
|
5102
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
5103
|
+
}
|
|
5104
|
+
);
|
|
5105
|
+
registerSpeakTool(
|
|
5106
|
+
server,
|
|
5107
|
+
"create_dashboard",
|
|
5108
|
+
"Create an analytics dashboard. Only `title` is required. Add widgets by listing their types (the MCP assigns ids and lays them out automatically) and scope with folderScope, dateRange, and filters. Call list_dashboard_widgets first to see the available widget types and their config keys, plus a full example.",
|
|
5109
|
+
{
|
|
5110
|
+
title: import_zod17.z.string().min(1).max(200).describe("Dashboard name (the only required field)"),
|
|
5111
|
+
...writeFields
|
|
5112
|
+
},
|
|
5113
|
+
{
|
|
5114
|
+
title: "Create Dashboard",
|
|
5115
|
+
readOnlyHint: false,
|
|
5116
|
+
destructiveHint: false,
|
|
5117
|
+
idempotentHint: false,
|
|
5118
|
+
openWorldHint: false
|
|
5119
|
+
},
|
|
5120
|
+
async (body) => {
|
|
5121
|
+
try {
|
|
5122
|
+
const result = await api.post("/v1/dashboards", withBuiltWidgets(body));
|
|
5123
|
+
return {
|
|
5124
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
5125
|
+
};
|
|
5126
|
+
} catch (err) {
|
|
5127
|
+
return {
|
|
5128
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
5129
|
+
isError: true
|
|
5130
|
+
};
|
|
5131
|
+
}
|
|
5132
|
+
}
|
|
5133
|
+
);
|
|
5134
|
+
registerSpeakTool(
|
|
5135
|
+
server,
|
|
5136
|
+
"update_dashboard",
|
|
5137
|
+
"Update a dashboard. Only the fields you pass are changed (partial update). NOTE: passing `widgets` replaces the entire widget set \u2014 fetch the dashboard first if you want to preserve existing widgets.",
|
|
5138
|
+
{
|
|
5139
|
+
dashboardId: import_zod17.z.string().min(1).describe("Dashboard business id"),
|
|
5140
|
+
title: import_zod17.z.string().min(1).max(200).optional().describe("New dashboard name"),
|
|
5141
|
+
...writeFields
|
|
5142
|
+
},
|
|
5143
|
+
{
|
|
5144
|
+
title: "Update Dashboard",
|
|
5145
|
+
readOnlyHint: false,
|
|
5146
|
+
destructiveHint: false,
|
|
5147
|
+
idempotentHint: true,
|
|
5148
|
+
openWorldHint: false
|
|
5149
|
+
},
|
|
5150
|
+
async ({ dashboardId, ...body }) => {
|
|
5151
|
+
try {
|
|
5152
|
+
const result = await api.put(`/v1/dashboards/${dashboardId}`, withBuiltWidgets(body));
|
|
5153
|
+
return {
|
|
5154
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
5155
|
+
};
|
|
5156
|
+
} catch (err) {
|
|
5157
|
+
return {
|
|
5158
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
5159
|
+
isError: true
|
|
5160
|
+
};
|
|
5161
|
+
}
|
|
5162
|
+
}
|
|
5163
|
+
);
|
|
5164
|
+
registerSpeakTool(
|
|
5165
|
+
server,
|
|
5166
|
+
"delete_dashboard",
|
|
5167
|
+
"Soft-delete a dashboard. This also deactivates its public share link.",
|
|
5168
|
+
{
|
|
5169
|
+
dashboardId: import_zod17.z.string().min(1).describe("Dashboard business id to delete")
|
|
5170
|
+
},
|
|
5171
|
+
{
|
|
5172
|
+
title: "Delete Dashboard",
|
|
5173
|
+
readOnlyHint: false,
|
|
5174
|
+
destructiveHint: true,
|
|
5175
|
+
idempotentHint: true,
|
|
5176
|
+
openWorldHint: false
|
|
5177
|
+
},
|
|
5178
|
+
async ({ dashboardId }) => {
|
|
5179
|
+
try {
|
|
5180
|
+
const result = await api.delete(`/v1/dashboards/${dashboardId}`);
|
|
5181
|
+
return {
|
|
5182
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
5183
|
+
};
|
|
5184
|
+
} catch (err) {
|
|
5185
|
+
return {
|
|
5186
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
5187
|
+
isError: true
|
|
5188
|
+
};
|
|
5189
|
+
}
|
|
5190
|
+
}
|
|
5191
|
+
);
|
|
5192
|
+
registerSpeakTool(
|
|
5193
|
+
server,
|
|
5194
|
+
"duplicate_dashboard",
|
|
5195
|
+
'Clone an existing dashboard. The copy gets fresh widget ids, a "<name> (copy)" title, and cleared sharing. Ideal for cloning a fully-configured dashboard, then tweaking it via update_dashboard.',
|
|
5196
|
+
{
|
|
5197
|
+
dashboardId: import_zod17.z.string().min(1).describe("Source dashboard business id to clone")
|
|
5198
|
+
},
|
|
5199
|
+
{
|
|
5200
|
+
title: "Duplicate Dashboard",
|
|
5201
|
+
readOnlyHint: false,
|
|
5202
|
+
destructiveHint: false,
|
|
5203
|
+
idempotentHint: false,
|
|
5204
|
+
openWorldHint: false
|
|
5205
|
+
},
|
|
5206
|
+
async ({ dashboardId }) => {
|
|
5207
|
+
try {
|
|
5208
|
+
const result = await api.post(`/v1/dashboards/${dashboardId}/duplicate`, {});
|
|
5209
|
+
return {
|
|
5210
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
5211
|
+
};
|
|
5212
|
+
} catch (err) {
|
|
5213
|
+
return {
|
|
5214
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
5215
|
+
isError: true
|
|
5216
|
+
};
|
|
5217
|
+
}
|
|
5218
|
+
}
|
|
5219
|
+
);
|
|
5220
|
+
registerSpeakTool(
|
|
5221
|
+
server,
|
|
5222
|
+
"share_dashboard",
|
|
5223
|
+
"Enable public sharing for a dashboard and return its share token + embed id. WARNING: by default the public link resolves with no passphrase, so anyone with the token can view the dashboard data until an owner sets one.",
|
|
5224
|
+
{
|
|
5225
|
+
dashboardId: import_zod17.z.string().min(1).describe("Dashboard business id to share")
|
|
5226
|
+
},
|
|
5227
|
+
{
|
|
5228
|
+
title: "Share Dashboard",
|
|
5229
|
+
readOnlyHint: false,
|
|
5230
|
+
destructiveHint: false,
|
|
5231
|
+
idempotentHint: true,
|
|
5232
|
+
openWorldHint: false
|
|
5233
|
+
},
|
|
5234
|
+
async ({ dashboardId }) => {
|
|
5235
|
+
try {
|
|
5236
|
+
const result = await api.put(`/v1/dashboards/${dashboardId}/share`, {});
|
|
5237
|
+
return {
|
|
5238
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
5239
|
+
};
|
|
5240
|
+
} catch (err) {
|
|
5241
|
+
return {
|
|
5242
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
5243
|
+
isError: true
|
|
5244
|
+
};
|
|
5245
|
+
}
|
|
5246
|
+
}
|
|
5247
|
+
);
|
|
5248
|
+
registerSpeakTool(
|
|
5249
|
+
server,
|
|
5250
|
+
"get_dashboard_speakers_insight",
|
|
5251
|
+
"Compute a speakers breakdown for a given folder scope, date range, and field filters. Standalone analytics \u2014 does not require a dashboard to exist.",
|
|
5252
|
+
SPEAKERS_FILTER_SCHEMA,
|
|
5253
|
+
{
|
|
5254
|
+
title: "Get Dashboard Speakers Insight",
|
|
5255
|
+
readOnlyHint: true,
|
|
5256
|
+
destructiveHint: false,
|
|
5257
|
+
idempotentHint: true,
|
|
5258
|
+
openWorldHint: false
|
|
5259
|
+
},
|
|
5260
|
+
async (body) => {
|
|
5261
|
+
try {
|
|
5262
|
+
const result = await api.post("/v1/dashboards/insights/speakers", body);
|
|
5263
|
+
return {
|
|
5264
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }]
|
|
5265
|
+
};
|
|
5266
|
+
} catch (err) {
|
|
5267
|
+
return {
|
|
5268
|
+
content: [{ type: "text", text: `Error: ${formatAxiosError(err)}` }],
|
|
5269
|
+
isError: true
|
|
5270
|
+
};
|
|
5271
|
+
}
|
|
5272
|
+
}
|
|
5273
|
+
);
|
|
5274
|
+
}
|
|
5275
|
+
var import_zod17, FILTER_LIST_DESCRIPTION, widgetInputSchema, writeFields, SPEAKERS_FILTER_SCHEMA;
|
|
5276
|
+
var init_dashboards = __esm({
|
|
5277
|
+
"src/tools/dashboards.ts"() {
|
|
5278
|
+
"use strict";
|
|
5279
|
+
import_zod17 = require("zod");
|
|
5280
|
+
init_helpers();
|
|
5281
|
+
init_client();
|
|
5282
|
+
init_dashboard_widgets();
|
|
5283
|
+
FILTER_LIST_DESCRIPTION = "Field filters. filters.filterList is an array of { fieldName, fieldOperator?, fieldValue?: string[], fieldCondition? }. Other keys pass through but only filterList is enforced.";
|
|
5284
|
+
widgetInputSchema = import_zod17.z.object({
|
|
5285
|
+
type: import_zod17.z.enum(WIDGET_TYPES).describe(
|
|
5286
|
+
"Widget type: stat-cards | sentiment | media-list | field-distribution | upload-timeline | themes | team-activity | kpi-trend | field-metric | metric-group | notes | people | comparison | sentiment-trend"
|
|
5287
|
+
),
|
|
5288
|
+
title: import_zod17.z.string().max(200).optional().describe("Widget title (defaults to a per-type label)"),
|
|
5289
|
+
config: import_zod17.z.record(import_zod17.z.unknown()).optional().describe(
|
|
5290
|
+
"Optional render settings. Per-type: fieldId+measure (field-distribution), fieldId+aggregator (field-metric), metrics list (stat-cards, kpi-trend, comparison, metric-group), chartType (themes), heading+content (notes). Any widget also accepts accentColor (hex) and scopeOverride ({datePreset, folderId}). Call list_dashboard_widgets for the full catalog + examples. Leave empty for sensible defaults."
|
|
5291
|
+
)
|
|
5292
|
+
});
|
|
5293
|
+
writeFields = {
|
|
5294
|
+
description: import_zod17.z.string().max(2e3).optional().describe("Dashboard description"),
|
|
5295
|
+
icon: import_zod17.z.string().max(200).optional().describe("Icon identifier"),
|
|
5296
|
+
folderScope: import_zod17.z.array(import_zod17.z.string().max(100)).max(100).optional().describe("Folder ids to scope analytics to. Empty/omitted = all accessible folders."),
|
|
5297
|
+
assignTo: import_zod17.z.array(import_zod17.z.string()).max(100).optional().describe('User ids, or group ids in the "<groupId> (G)" convention, to share view access with'),
|
|
5298
|
+
dateRange: import_zod17.z.object({
|
|
5299
|
+
preset: import_zod17.z.string().max(50).optional(),
|
|
5300
|
+
startDate: import_zod17.z.string().optional(),
|
|
5301
|
+
endDate: import_zod17.z.string().optional()
|
|
5302
|
+
}).optional().describe("Date range: { preset?, startDate?, endDate? }"),
|
|
5303
|
+
filters: import_zod17.z.record(import_zod17.z.unknown()).optional().describe(FILTER_LIST_DESCRIPTION),
|
|
5304
|
+
widgets: import_zod17.z.array(widgetInputSchema).max(50).optional().describe(
|
|
5305
|
+
"Widgets to place on the dashboard, in order. The MCP assigns ids and computes a tidy two-per-row grid layout matching the Speak UI. Just list the widget types you want."
|
|
5306
|
+
),
|
|
5307
|
+
isDefault: import_zod17.z.boolean().optional().describe("Make this the company default dashboard")
|
|
5308
|
+
};
|
|
5309
|
+
SPEAKERS_FILTER_SCHEMA = {
|
|
5310
|
+
folderScope: import_zod17.z.array(import_zod17.z.string().max(100)).max(100).optional().describe("Folder ids to scope to"),
|
|
5311
|
+
startDate: import_zod17.z.string().optional().describe("ISO start date"),
|
|
5312
|
+
endDate: import_zod17.z.string().optional().describe("ISO end date"),
|
|
5313
|
+
filterList: import_zod17.z.array(
|
|
5314
|
+
import_zod17.z.object({
|
|
5315
|
+
fieldName: import_zod17.z.string().max(100),
|
|
5316
|
+
fieldOperator: import_zod17.z.string().max(50).optional(),
|
|
5317
|
+
fieldValue: import_zod17.z.array(import_zod17.z.string().max(500)).optional(),
|
|
5318
|
+
fieldCondition: import_zod17.z.string().max(50).optional()
|
|
5319
|
+
})
|
|
5320
|
+
).max(20).optional().describe("Field filter rules")
|
|
5321
|
+
};
|
|
5322
|
+
}
|
|
5323
|
+
});
|
|
5324
|
+
|
|
5325
|
+
// src/tools/index.ts
|
|
5326
|
+
var tools_exports = {};
|
|
5327
|
+
__export(tools_exports, {
|
|
5328
|
+
registerAllTools: () => registerAllTools
|
|
5329
|
+
});
|
|
5330
|
+
function registerAllTools(server, client) {
|
|
5331
|
+
for (const mod of modules) {
|
|
5332
|
+
mod.register(server, client);
|
|
5333
|
+
}
|
|
5334
|
+
}
|
|
5335
|
+
var modules;
|
|
5336
|
+
var init_tools = __esm({
|
|
5337
|
+
"src/tools/index.ts"() {
|
|
5338
|
+
"use strict";
|
|
5339
|
+
init_media3();
|
|
5340
|
+
init_text2();
|
|
5341
|
+
init_exports();
|
|
5342
|
+
init_folders();
|
|
5343
|
+
init_recorder3();
|
|
5344
|
+
init_embed3();
|
|
5345
|
+
init_prompt3();
|
|
5346
|
+
init_meeting3();
|
|
5347
|
+
init_fields2();
|
|
5348
|
+
init_automations();
|
|
5349
|
+
init_webhooks();
|
|
5350
|
+
init_analytics();
|
|
5351
|
+
init_clips();
|
|
5352
|
+
init_workflows();
|
|
5353
|
+
init_users();
|
|
5354
|
+
init_dashboards();
|
|
5355
|
+
modules = [
|
|
5356
|
+
media_exports,
|
|
4412
5357
|
text_exports,
|
|
4413
5358
|
exports_exports,
|
|
4414
5359
|
folders_exports,
|
|
@@ -4421,7 +5366,9 @@ var init_tools = __esm({
|
|
|
4421
5366
|
webhooks_exports,
|
|
4422
5367
|
analytics_exports,
|
|
4423
5368
|
clips_exports,
|
|
4424
|
-
workflows_exports
|
|
5369
|
+
workflows_exports,
|
|
5370
|
+
users_exports,
|
|
5371
|
+
dashboards_exports
|
|
4425
5372
|
];
|
|
4426
5373
|
}
|
|
4427
5374
|
});
|
|
@@ -4538,8 +5485,8 @@ function registerPrompts(server) {
|
|
|
4538
5485
|
"analyze-meeting",
|
|
4539
5486
|
"Upload a meeting recording and get a full analysis \u2014 transcript, insights, action items, and key takeaways.",
|
|
4540
5487
|
{
|
|
4541
|
-
url:
|
|
4542
|
-
name:
|
|
5488
|
+
url: import_zod18.z.string().describe("URL of the meeting recording \u2014 a direct file link or a shareable social/video link (resolved automatically)"),
|
|
5489
|
+
name: import_zod18.z.string().optional().describe("Meeting name (optional)")
|
|
4543
5490
|
},
|
|
4544
5491
|
async ({ url, name }) => ({
|
|
4545
5492
|
messages: [
|
|
@@ -4571,8 +5518,8 @@ function registerPrompts(server) {
|
|
|
4571
5518
|
"research-across-media",
|
|
4572
5519
|
"Search for themes, patterns, or topics across multiple recordings or your entire media library.",
|
|
4573
5520
|
{
|
|
4574
|
-
topic:
|
|
4575
|
-
folder:
|
|
5521
|
+
topic: import_zod18.z.string().describe("The topic, theme, or question to research"),
|
|
5522
|
+
folder: import_zod18.z.string().optional().describe("Folder ID to scope the research (optional)")
|
|
4576
5523
|
},
|
|
4577
5524
|
async ({ topic, folder }) => ({
|
|
4578
5525
|
messages: [
|
|
@@ -4605,8 +5552,8 @@ function registerPrompts(server) {
|
|
|
4605
5552
|
"meeting-brief",
|
|
4606
5553
|
"Prepare a brief from recent meetings \u2014 pull transcripts, extract decisions, and summarize open items.",
|
|
4607
5554
|
{
|
|
4608
|
-
days:
|
|
4609
|
-
folder:
|
|
5555
|
+
days: import_zod18.z.string().optional().describe("Number of days to look back (default: 7)"),
|
|
5556
|
+
folder: import_zod18.z.string().optional().describe("Folder ID to scope to (optional)")
|
|
4610
5557
|
},
|
|
4611
5558
|
async ({ days, folder }) => {
|
|
4612
5559
|
const lookback = parseInt(days ?? "7");
|
|
@@ -4643,11 +5590,148 @@ function registerPrompts(server) {
|
|
|
4643
5590
|
}
|
|
4644
5591
|
);
|
|
4645
5592
|
}
|
|
4646
|
-
var
|
|
5593
|
+
var import_zod18;
|
|
4647
5594
|
var init_prompts = __esm({
|
|
4648
5595
|
"src/prompts.ts"() {
|
|
4649
5596
|
"use strict";
|
|
4650
|
-
|
|
5597
|
+
import_zod18 = require("zod");
|
|
5598
|
+
}
|
|
5599
|
+
});
|
|
5600
|
+
|
|
5601
|
+
// src/tool-names.ts
|
|
5602
|
+
var tool_names_exports = {};
|
|
5603
|
+
__export(tool_names_exports, {
|
|
5604
|
+
SPEAK_MCP_TOOL_NAMES: () => SPEAK_MCP_TOOL_NAMES
|
|
5605
|
+
});
|
|
5606
|
+
var SPEAK_MCP_TOOL_NAMES;
|
|
5607
|
+
var init_tool_names = __esm({
|
|
5608
|
+
"src/tool-names.ts"() {
|
|
5609
|
+
"use strict";
|
|
5610
|
+
SPEAK_MCP_TOOL_NAMES = [
|
|
5611
|
+
// analytics
|
|
5612
|
+
"get_media_statistics",
|
|
5613
|
+
// automations
|
|
5614
|
+
"list_automations",
|
|
5615
|
+
"list_automation_names",
|
|
5616
|
+
"get_automation",
|
|
5617
|
+
"get_automation_runs",
|
|
5618
|
+
"create_automation",
|
|
5619
|
+
"update_automation",
|
|
5620
|
+
"toggle_automation_status",
|
|
5621
|
+
"bulk_update_automation_status",
|
|
5622
|
+
"bulk_assign_automation_folders",
|
|
5623
|
+
"run_automations",
|
|
5624
|
+
"delete_automation",
|
|
5625
|
+
"list_automation_apps",
|
|
5626
|
+
"list_automation_triggers",
|
|
5627
|
+
"list_automation_actions",
|
|
5628
|
+
// clips
|
|
5629
|
+
"get_clips",
|
|
5630
|
+
"create_clip",
|
|
5631
|
+
"update_clip",
|
|
5632
|
+
"delete_clip",
|
|
5633
|
+
// embed
|
|
5634
|
+
"create_embed",
|
|
5635
|
+
"update_embed",
|
|
5636
|
+
"check_embed",
|
|
5637
|
+
"get_embed_iframe_url",
|
|
5638
|
+
// exports
|
|
5639
|
+
"export_media",
|
|
5640
|
+
"export_multiple_media",
|
|
5641
|
+
// fields
|
|
5642
|
+
"list_fields",
|
|
5643
|
+
"create_field",
|
|
5644
|
+
"update_field",
|
|
5645
|
+
"update_multiple_fields",
|
|
5646
|
+
// folders
|
|
5647
|
+
"list_folders",
|
|
5648
|
+
"create_folder",
|
|
5649
|
+
"update_folder",
|
|
5650
|
+
"delete_folder",
|
|
5651
|
+
"get_folder_info",
|
|
5652
|
+
"clone_folder",
|
|
5653
|
+
"get_folder_views",
|
|
5654
|
+
"get_all_folder_views",
|
|
5655
|
+
"create_folder_view",
|
|
5656
|
+
"update_folder_view",
|
|
5657
|
+
"clone_folder_view",
|
|
5658
|
+
// media
|
|
5659
|
+
"get_signed_upload_url",
|
|
5660
|
+
"upload_media",
|
|
5661
|
+
"get_media_status",
|
|
5662
|
+
"get_media_insights",
|
|
5663
|
+
"get_transcript",
|
|
5664
|
+
"list_media",
|
|
5665
|
+
"search_media",
|
|
5666
|
+
"delete_media",
|
|
5667
|
+
"update_media_metadata",
|
|
5668
|
+
"toggle_media_favorite",
|
|
5669
|
+
"reanalyze_media",
|
|
5670
|
+
"get_captions",
|
|
5671
|
+
"list_supported_languages",
|
|
5672
|
+
"update_transcript_speakers",
|
|
5673
|
+
"bulk_update_transcript_speakers",
|
|
5674
|
+
"bulk_move_media",
|
|
5675
|
+
// meeting
|
|
5676
|
+
"list_meeting_events",
|
|
5677
|
+
"schedule_meeting_event",
|
|
5678
|
+
"remove_assistant_from_meeting",
|
|
5679
|
+
"delete_scheduled_assistant",
|
|
5680
|
+
"get_live_meeting_transcript",
|
|
5681
|
+
// prompt
|
|
5682
|
+
"ask_magic_prompt",
|
|
5683
|
+
"list_prompts",
|
|
5684
|
+
"get_favorite_prompts",
|
|
5685
|
+
"toggle_prompt_favorite",
|
|
5686
|
+
"get_chat_history",
|
|
5687
|
+
"get_chat_messages",
|
|
5688
|
+
"update_chat_title",
|
|
5689
|
+
"delete_chat_message",
|
|
5690
|
+
"submit_chat_feedback",
|
|
5691
|
+
"retry_magic_prompt",
|
|
5692
|
+
"export_chat_answer",
|
|
5693
|
+
"get_chat_statistics",
|
|
5694
|
+
// recorder
|
|
5695
|
+
"list_recorders",
|
|
5696
|
+
"create_recorder",
|
|
5697
|
+
"update_recorder_settings",
|
|
5698
|
+
"update_recorder_questions",
|
|
5699
|
+
"delete_recorder",
|
|
5700
|
+
"generate_recorder_url",
|
|
5701
|
+
"get_recorder_info",
|
|
5702
|
+
"get_recorder_recordings",
|
|
5703
|
+
"check_recorder_status",
|
|
5704
|
+
"clone_recorder",
|
|
5705
|
+
// text
|
|
5706
|
+
"create_text_note",
|
|
5707
|
+
"update_text_note",
|
|
5708
|
+
"get_text_insight",
|
|
5709
|
+
"reanalyze_text",
|
|
5710
|
+
// webhooks
|
|
5711
|
+
"list_webhooks",
|
|
5712
|
+
"create_webhook",
|
|
5713
|
+
"update_webhook",
|
|
5714
|
+
"delete_webhook",
|
|
5715
|
+
// workflows (high-level wrappers around media + upload tools)
|
|
5716
|
+
"upload_and_analyze",
|
|
5717
|
+
"upload_local_file",
|
|
5718
|
+
// users / team management
|
|
5719
|
+
"list_users",
|
|
5720
|
+
"list_user_groups",
|
|
5721
|
+
"create_user_group",
|
|
5722
|
+
"update_user_group",
|
|
5723
|
+
"delete_user_group",
|
|
5724
|
+
// dashboards
|
|
5725
|
+
"list_dashboard_widgets",
|
|
5726
|
+
"list_dashboards",
|
|
5727
|
+
"get_dashboard",
|
|
5728
|
+
"create_dashboard",
|
|
5729
|
+
"update_dashboard",
|
|
5730
|
+
"delete_dashboard",
|
|
5731
|
+
"duplicate_dashboard",
|
|
5732
|
+
"share_dashboard",
|
|
5733
|
+
"get_dashboard_speakers_insight"
|
|
5734
|
+
];
|
|
4651
5735
|
}
|
|
4652
5736
|
});
|
|
4653
5737
|
|
|
@@ -5694,8 +6778,71 @@ function createCli() {
|
|
|
5694
6778
|
process.exit(1);
|
|
5695
6779
|
}
|
|
5696
6780
|
});
|
|
6781
|
+
async function loadToolHandlers() {
|
|
6782
|
+
const client = await getClient();
|
|
6783
|
+
const handlers = {};
|
|
6784
|
+
const stub = {
|
|
6785
|
+
registerTool: (name, _def, cb) => {
|
|
6786
|
+
handlers[name] = cb;
|
|
6787
|
+
return {};
|
|
6788
|
+
}
|
|
6789
|
+
};
|
|
6790
|
+
const { registerAllTools: registerAllTools2 } = await Promise.resolve().then(() => (init_tools(), tools_exports));
|
|
6791
|
+
registerAllTools2(stub, client);
|
|
6792
|
+
return handlers;
|
|
6793
|
+
}
|
|
6794
|
+
program.command("tools").description("List every MCP tool callable via `call`").option("--json", "Output raw JSON").action(async (opts) => {
|
|
6795
|
+
const { SPEAK_MCP_TOOL_NAMES: SPEAK_MCP_TOOL_NAMES2 } = await Promise.resolve().then(() => (init_tool_names(), tool_names_exports));
|
|
6796
|
+
const names = [...SPEAK_MCP_TOOL_NAMES2].sort();
|
|
6797
|
+
if (opts.json) {
|
|
6798
|
+
printJson(names);
|
|
6799
|
+
} else {
|
|
6800
|
+
console.log(`${names.length} tools:
|
|
6801
|
+
`);
|
|
6802
|
+
for (const n of names) console.log(` ${n}`);
|
|
6803
|
+
}
|
|
6804
|
+
});
|
|
6805
|
+
program.command("call").description("Call any MCP tool by name with JSON arguments").argument("<tool>", "Tool name (see `speakai-mcp tools`)").argument("[json]", "Arguments as a JSON object", "{}").action(async (tool, json) => {
|
|
6806
|
+
requireApiKey();
|
|
6807
|
+
let args2;
|
|
6808
|
+
try {
|
|
6809
|
+
args2 = JSON.parse(json);
|
|
6810
|
+
} catch {
|
|
6811
|
+
printError(`Invalid JSON arguments: ${json}`);
|
|
6812
|
+
process.exit(1);
|
|
6813
|
+
return;
|
|
6814
|
+
}
|
|
6815
|
+
const handlers = await loadToolHandlers();
|
|
6816
|
+
const handler = handlers[tool];
|
|
6817
|
+
if (!handler) {
|
|
6818
|
+
printError(`Unknown tool "${tool}". Run "speakai-mcp tools" to list them.`);
|
|
6819
|
+
process.exit(1);
|
|
6820
|
+
return;
|
|
6821
|
+
}
|
|
6822
|
+
try {
|
|
6823
|
+
const result = await handler(args2);
|
|
6824
|
+
const text = result?.content?.find((c) => c.type === "text")?.text;
|
|
6825
|
+
if (result?.isError) {
|
|
6826
|
+
printError(text ?? "Tool call failed");
|
|
6827
|
+
process.exit(1);
|
|
6828
|
+
return;
|
|
6829
|
+
}
|
|
6830
|
+
const data = result?.structuredContent?.data ?? (text ? safeParse(text) : result);
|
|
6831
|
+
printJson(data);
|
|
6832
|
+
} catch (err) {
|
|
6833
|
+
printError(err.response?.data?.message ?? err.message);
|
|
6834
|
+
process.exit(1);
|
|
6835
|
+
}
|
|
6836
|
+
});
|
|
5697
6837
|
return program;
|
|
5698
6838
|
}
|
|
6839
|
+
function safeParse(text) {
|
|
6840
|
+
try {
|
|
6841
|
+
return JSON.parse(text);
|
|
6842
|
+
} catch {
|
|
6843
|
+
return text;
|
|
6844
|
+
}
|
|
6845
|
+
}
|
|
5699
6846
|
var import_commander, import_readline;
|
|
5700
6847
|
var init_cli = __esm({
|
|
5701
6848
|
"src/cli/index.ts"() {
|
|
@@ -5723,110 +6870,7 @@ init_tools();
|
|
|
5723
6870
|
init_resources();
|
|
5724
6871
|
init_prompts();
|
|
5725
6872
|
init_client();
|
|
5726
|
-
|
|
5727
|
-
// src/tool-names.ts
|
|
5728
|
-
var SPEAK_MCP_TOOL_NAMES = [
|
|
5729
|
-
// analytics
|
|
5730
|
-
"get_media_statistics",
|
|
5731
|
-
// automations
|
|
5732
|
-
"list_automations",
|
|
5733
|
-
"get_automation",
|
|
5734
|
-
"create_automation",
|
|
5735
|
-
"update_automation",
|
|
5736
|
-
"toggle_automation_status",
|
|
5737
|
-
// clips
|
|
5738
|
-
"get_clips",
|
|
5739
|
-
"create_clip",
|
|
5740
|
-
"update_clip",
|
|
5741
|
-
"delete_clip",
|
|
5742
|
-
// embed
|
|
5743
|
-
"create_embed",
|
|
5744
|
-
"update_embed",
|
|
5745
|
-
"check_embed",
|
|
5746
|
-
"get_embed_iframe_url",
|
|
5747
|
-
// exports
|
|
5748
|
-
"export_media",
|
|
5749
|
-
"export_multiple_media",
|
|
5750
|
-
// fields
|
|
5751
|
-
"list_fields",
|
|
5752
|
-
"create_field",
|
|
5753
|
-
"update_field",
|
|
5754
|
-
"update_multiple_fields",
|
|
5755
|
-
// folders
|
|
5756
|
-
"list_folders",
|
|
5757
|
-
"create_folder",
|
|
5758
|
-
"update_folder",
|
|
5759
|
-
"delete_folder",
|
|
5760
|
-
"get_folder_info",
|
|
5761
|
-
"clone_folder",
|
|
5762
|
-
"get_folder_views",
|
|
5763
|
-
"get_all_folder_views",
|
|
5764
|
-
"create_folder_view",
|
|
5765
|
-
"update_folder_view",
|
|
5766
|
-
"clone_folder_view",
|
|
5767
|
-
// media
|
|
5768
|
-
"get_signed_upload_url",
|
|
5769
|
-
"upload_media",
|
|
5770
|
-
"get_media_status",
|
|
5771
|
-
"get_media_insights",
|
|
5772
|
-
"get_transcript",
|
|
5773
|
-
"list_media",
|
|
5774
|
-
"search_media",
|
|
5775
|
-
"delete_media",
|
|
5776
|
-
"update_media_metadata",
|
|
5777
|
-
"toggle_media_favorite",
|
|
5778
|
-
"reanalyze_media",
|
|
5779
|
-
"get_captions",
|
|
5780
|
-
"list_supported_languages",
|
|
5781
|
-
"update_transcript_speakers",
|
|
5782
|
-
"bulk_update_transcript_speakers",
|
|
5783
|
-
"bulk_move_media",
|
|
5784
|
-
// meeting
|
|
5785
|
-
"list_meeting_events",
|
|
5786
|
-
"schedule_meeting_event",
|
|
5787
|
-
"remove_assistant_from_meeting",
|
|
5788
|
-
"delete_scheduled_assistant",
|
|
5789
|
-
"get_live_meeting_transcript",
|
|
5790
|
-
// prompt
|
|
5791
|
-
"ask_magic_prompt",
|
|
5792
|
-
"list_prompts",
|
|
5793
|
-
"get_favorite_prompts",
|
|
5794
|
-
"toggle_prompt_favorite",
|
|
5795
|
-
"get_chat_history",
|
|
5796
|
-
"get_chat_messages",
|
|
5797
|
-
"update_chat_title",
|
|
5798
|
-
"delete_chat_message",
|
|
5799
|
-
"submit_chat_feedback",
|
|
5800
|
-
"retry_magic_prompt",
|
|
5801
|
-
"export_chat_answer",
|
|
5802
|
-
"get_chat_statistics",
|
|
5803
|
-
// recorder
|
|
5804
|
-
"list_recorders",
|
|
5805
|
-
"create_recorder",
|
|
5806
|
-
"update_recorder_settings",
|
|
5807
|
-
"update_recorder_questions",
|
|
5808
|
-
"delete_recorder",
|
|
5809
|
-
"generate_recorder_url",
|
|
5810
|
-
"get_recorder_info",
|
|
5811
|
-
"get_recorder_recordings",
|
|
5812
|
-
"check_recorder_status",
|
|
5813
|
-
"clone_recorder",
|
|
5814
|
-
// text
|
|
5815
|
-
"create_text_note",
|
|
5816
|
-
"update_text_note",
|
|
5817
|
-
"get_text_insight",
|
|
5818
|
-
"reanalyze_text",
|
|
5819
|
-
// webhooks
|
|
5820
|
-
"list_webhooks",
|
|
5821
|
-
"create_webhook",
|
|
5822
|
-
"update_webhook",
|
|
5823
|
-
"delete_webhook",
|
|
5824
|
-
// workflows (high-level wrappers around media + upload tools)
|
|
5825
|
-
"upload_and_analyze",
|
|
5826
|
-
"upload_local_file"
|
|
5827
|
-
];
|
|
5828
|
-
|
|
5829
|
-
// src/index.ts
|
|
6873
|
+
init_tool_names();
|
|
5830
6874
|
var args = process.argv.slice(2);
|
|
5831
6875
|
var cliCommands = [
|
|
5832
6876
|
"config",
|