@trylighthouse/mcp-server 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/build/index.js +392 -24
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -126,13 +126,11 @@ server.registerTool("lighthouse_crm_get_attribute", {
126
126
  description: "Get a single custom field definition by its field_permalink.",
127
127
  inputSchema: {
128
128
  field_permalink: z.string().describe("Field permalink (unique key) of the attribute"),
129
- entity_type: z.enum(["company", "person", "deal"]).optional().describe("Record type context"),
129
+ entity_type: z.enum(["company", "person", "deal"]).describe("Record type (required)"),
130
130
  },
131
131
  }, async (params) => {
132
132
  try {
133
- const res = await api.get(`/attributes/${params.field_permalink}`, {
134
- entity_type: params.entity_type,
135
- });
133
+ const res = await api.get(`/attributes/${params.entity_type}/${params.field_permalink}`);
136
134
  return text(res);
137
135
  }
138
136
  catch (e) {
@@ -142,15 +140,16 @@ server.registerTool("lighthouse_crm_get_attribute", {
142
140
  server.registerTool("lighthouse_crm_create_attribute", {
143
141
  title: "Create CRM Attribute",
144
142
  description: "Create a new custom field in your CRM workspace. " +
145
- "Common types: short_text, long_text, number, currency, date, select, multi_select, boolean, url, email, phone, rating.",
143
+ "Types: text, number, currency, percentage, date, datetimez, select, multi_select, status, checkbox, url, email, phone, rating, record, multi_record, user, multi_user.",
146
144
  inputSchema: {
147
- name: z.string().describe("Display name for the field"),
145
+ label: z.string().describe("Display label for the field"),
148
146
  entity_type: z.enum(["company", "person", "deal"]).describe("Record type this field belongs to"),
149
- data_type: z.string().describe("Field type (short_text, long_text, number, currency, date, select, multi_select, boolean, url, email, phone, rating)"),
147
+ data_type: z.string().describe("Field type (text, number, currency, percentage, date, datetimez, select, multi_select, status, checkbox, url, email, phone, rating, record, multi_record, user, multi_user)"),
148
+ record_type: z.enum(["company", "person", "deal"]).optional().describe("For record/multi_record fields: which record type to link to"),
150
149
  options: z
151
150
  .array(z.record(z.unknown()))
152
151
  .optional()
153
- .describe("For select/multi_select fields: array of {value, label} option objects"),
152
+ .describe("For select/multi_select/status fields: array of {value, label} option objects"),
154
153
  },
155
154
  }, async (params) => {
156
155
  try {
@@ -163,16 +162,47 @@ server.registerTool("lighthouse_crm_create_attribute", {
163
162
  });
164
163
  server.registerTool("lighthouse_crm_update_attribute", {
165
164
  title: "Update CRM Attribute",
166
- description: "Update a custom field's name or configuration.",
165
+ description: "Update a custom field's label or configuration.",
167
166
  inputSchema: {
168
167
  field_permalink: z.string().describe("Field permalink of the attribute to update"),
169
- entity_type: z.enum(["company", "person", "deal"]).optional().describe("Record type context"),
170
- name: z.string().optional().describe("New display name"),
168
+ entity_type: z.enum(["company", "person", "deal"]).describe("Record type (required)"),
169
+ label: z.string().optional().describe("New display label"),
170
+ },
171
+ }, async (params) => {
172
+ try {
173
+ const { field_permalink, entity_type, ...body } = params;
174
+ const res = await api.patch(`/attributes/${entity_type}/${field_permalink}`, body);
175
+ return text(res);
176
+ }
177
+ catch (e) {
178
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
179
+ }
180
+ });
181
+ server.registerTool("lighthouse_crm_delete_attribute", {
182
+ title: "Delete CRM Attribute",
183
+ description: "Delete (archive) a custom field. Only custom fields can be deleted, not system fields.",
184
+ inputSchema: {
185
+ field_permalink: z.string().describe("Field permalink of the attribute to delete"),
186
+ entity_type: z.enum(["company", "person", "deal"]).describe("Record type (required)"),
171
187
  },
172
188
  }, async (params) => {
173
189
  try {
174
- const { field_permalink, ...body } = params;
175
- const res = await api.patch(`/attributes/${field_permalink}`, body);
190
+ const res = await api.delete(`/attributes/${params.entity_type}/${params.field_permalink}`);
191
+ return text(res);
192
+ }
193
+ catch (e) {
194
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
195
+ }
196
+ });
197
+ server.registerTool("lighthouse_crm_get_color_palette", {
198
+ title: "Get Color Palette",
199
+ description: "Get the available color palette for select/multi_select/status field options. " +
200
+ "Returns an array of {hex_code, label} objects. " +
201
+ "Use this to discover valid hex color codes when creating or updating select options.",
202
+ inputSchema: {},
203
+ }, async () => {
204
+ try {
205
+ const res = await api.get("/attributes/colors");
176
206
  return text(res);
177
207
  }
178
208
  catch (e) {
@@ -185,12 +215,12 @@ server.registerTool("lighthouse_crm_list_options", {
185
215
  description: "Get select/multi_select field options. " +
186
216
  "Use this to discover available values for select fields before setting them on records.",
187
217
  inputSchema: {
188
- field_permalink: z.string().optional().describe("Filter by field permalink"),
189
- entity_type: z.enum(["company", "person", "deal"]).optional().describe("Filter by record type"),
218
+ entity_type: z.enum(["company", "person", "deal"]).describe("Record type"),
219
+ field_permalink: z.string().describe("Field permalink of the select/multi_select field"),
190
220
  },
191
221
  }, async (params) => {
192
222
  try {
193
- const res = await api.get("/options", params);
223
+ const res = await api.get(`/options/${params.entity_type}/${params.field_permalink}`);
194
224
  return text(res);
195
225
  }
196
226
  catch (e) {
@@ -199,17 +229,34 @@ server.registerTool("lighthouse_crm_list_options", {
199
229
  });
200
230
  server.registerTool("lighthouse_crm_create_option", {
201
231
  title: "Create CRM Field Option",
202
- description: "Add a new option value to a select/multi_select field.",
232
+ description: "Add a new option to a select/multi_select field. The option value is auto-generated from the label. Returns the updated list of options for the field.",
203
233
  inputSchema: {
234
+ entity_type: z.enum(["company", "person", "deal"]).describe("Record type"),
204
235
  field_permalink: z.string().describe("Field permalink of the select/multi_select field"),
236
+ label: z.string().describe("Option display label"),
237
+ color: z.string().optional().describe("Option color (hex code from palette, auto-assigned if omitted)"),
238
+ },
239
+ }, async (params) => {
240
+ try {
241
+ const { entity_type, field_permalink, ...body } = params;
242
+ const res = await api.post(`/options/${entity_type}/${field_permalink}`, body);
243
+ return text(res);
244
+ }
245
+ catch (e) {
246
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
247
+ }
248
+ });
249
+ server.registerTool("lighthouse_crm_delete_option", {
250
+ title: "Delete CRM Field Option",
251
+ description: "Delete an option value from a select/multi_select field. Cannot delete system default options.",
252
+ inputSchema: {
205
253
  entity_type: z.enum(["company", "person", "deal"]).describe("Record type"),
206
- value: z.string().describe("Option value (stored value)"),
207
- label: z.string().describe("Option label (display text)"),
208
- color: z.string().optional().describe("Option color (hex code)"),
254
+ field_permalink: z.string().describe("Field permalink of the select/multi_select field"),
255
+ value: z.string().describe("Option value to delete"),
209
256
  },
210
257
  }, async (params) => {
211
258
  try {
212
- const res = await api.post("/options", params);
259
+ const res = await api.delete(`/options/${params.entity_type}/${params.field_permalink}/${params.value}`);
213
260
  return text(res);
214
261
  }
215
262
  catch (e) {
@@ -340,7 +387,7 @@ server.registerTool("lighthouse_crm_create_list", {
340
387
  description: "Create a new CRM list to organize records.",
341
388
  inputSchema: {
342
389
  name: z.string().describe("List name"),
343
- entity_type: z.enum(["company", "person", "deal"]).describe("Record type for this list"),
390
+ type: z.enum(["company", "person", "deal"]).describe("Record type for this list"),
344
391
  },
345
392
  }, async (params) => {
346
393
  try {
@@ -474,8 +521,8 @@ server.registerTool("lighthouse_crm_list_notes", {
474
521
  title: "List Notes",
475
522
  description: "Get notes for a CRM record.",
476
523
  inputSchema: {
477
- record_id: z.string().uuid().describe("Record ID to get notes for"),
478
- record_type: z.enum(["company", "person", "deal"]).describe("Record type"),
524
+ record_id: z.string().uuid().optional().describe("Record ID to filter notes by (optional — omit to list all notes)"),
525
+ record_type: z.enum(["company", "person", "deal"]).optional().describe("Record type (required if record_id is provided)"),
479
526
  limit: z.number().min(1).max(100).default(25),
480
527
  offset: z.number().min(0).default(0),
481
528
  },
@@ -729,6 +776,7 @@ server.registerTool("lighthouse_crm_create_view", {
729
776
  view_type: z.enum(["table", "kanban"]).default("table").describe("View layout type"),
730
777
  grouped_by: z.string().optional().describe("Field key to group by (required for kanban views)"),
731
778
  sharing: z.enum(["private", "workspace"]).default("private").describe("Visibility"),
779
+ team_ids: z.array(z.string().uuid()).optional().describe("Team UUIDs to share the view with. Replaces any existing team shares."),
732
780
  },
733
781
  }, async (params) => {
734
782
  try {
@@ -751,6 +799,7 @@ server.registerTool("lighthouse_crm_update_view", {
751
799
  view_type: z.enum(["table", "kanban"]).optional(),
752
800
  grouped_by: z.string().optional().describe("Field key to group by (required for kanban views)"),
753
801
  sharing: z.enum(["private", "workspace"]).optional(),
802
+ team_ids: z.array(z.string().uuid()).optional().describe("Team UUIDs to share the view with. Replaces any existing team shares."),
754
803
  },
755
804
  }, async (params) => {
756
805
  try {
@@ -945,6 +994,325 @@ server.registerTool("lighthouse_discovery_search_people", {
945
994
  return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
946
995
  }
947
996
  });
997
+ // ─── Reports: Dashboards ─────────────────────────────────
998
+ const WIDGET_CONFIG_DESCRIPTION = "Widget config object. Structure depends on report_type: " +
999
+ "STANDARD: {data_source:'companies'|'deals'|'people', report_type:'standard', " +
1000
+ "dimension:{field:'<field_key>', is_custom_field:boolean, time_grouping?:'day'|'week'|'month'|'quarter'|'year'}, " +
1001
+ "measure:{aggregation:'COUNT'|'SUM'|'AVG'|'MIN'|'MAX', field:'*'|'<field_key>', is_custom_field:boolean}, " +
1002
+ "segment_by?:{field:'<field_key>', is_custom_field:boolean}, " +
1003
+ "filter?:{operator:'AND'|'OR', conditions:[...], groups:[...]}, " +
1004
+ "date_range?:{type:'relative', relative_period:'all_time'|'last_7_days'|'last_30_days'|'last_90_days'|'this_month'|'last_month'|'this_quarter'|'last_quarter'|'this_year'|'last_year'} " +
1005
+ "OR {type:'absolute', start_date:'YYYY-MM-DD', end_date:'YYYY-MM-DD'}, " +
1006
+ "included_stages?:['value1','value2'], show_axis_labels?:boolean, show_zeros?:boolean, sort_by_stage_order?:boolean}. " +
1007
+ "FUNNEL: {report_type:'funnel', entity_type:'company'|'deal'|'person', stage_field:'<field_key>', " +
1008
+ "included_stages?:['stage1','stage2'], date_range?:{...}, filter?:{...}}. " +
1009
+ "HISTORICAL: {report_type:'stage_changes', entity_type:'company'|'deal'|'person', " +
1010
+ "field_permalink:'<field_key>', time_grouping?:'day'|'week'|'month'|'quarter'|'year', date_range?:{...}}. " +
1011
+ "ALWAYS call lighthouse_crm_get_attributes first to discover valid field keys for dimension, measure, and stage_field.";
1012
+ server.registerTool("lighthouse_reports_list_dashboards", {
1013
+ title: "List Dashboards",
1014
+ description: "List all report dashboards accessible to the current user. " +
1015
+ "Returns dashboards you own, workspace-shared dashboards, and team-shared dashboards.",
1016
+ inputSchema: {},
1017
+ }, async () => {
1018
+ try {
1019
+ const res = await api.get("/dashboards");
1020
+ return text(res);
1021
+ }
1022
+ catch (e) {
1023
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1024
+ }
1025
+ });
1026
+ server.registerTool("lighthouse_reports_create_dashboard", {
1027
+ title: "Create Dashboard",
1028
+ description: "Create a new report dashboard. Dashboards contain report widgets (charts, tables, KPIs). " +
1029
+ "Requires reports.create permission.",
1030
+ inputSchema: {
1031
+ name: z.string().describe("Dashboard name"),
1032
+ description: z.string().optional().describe("Dashboard description"),
1033
+ sharing: z
1034
+ .enum(["private", "workspace"])
1035
+ .default("private")
1036
+ .describe("Visibility: 'private' (only you) or 'workspace' (all members)"),
1037
+ team_ids: z
1038
+ .array(z.string().uuid())
1039
+ .optional()
1040
+ .describe("Team IDs to share this dashboard with"),
1041
+ },
1042
+ }, async (params) => {
1043
+ try {
1044
+ const res = await api.post("/dashboards", params);
1045
+ return text(res);
1046
+ }
1047
+ catch (e) {
1048
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1049
+ }
1050
+ });
1051
+ server.registerTool("lighthouse_reports_get_dashboard", {
1052
+ title: "Get Dashboard",
1053
+ description: "Get a single dashboard by ID with all its widgets.",
1054
+ inputSchema: {
1055
+ id: z.string().uuid().describe("Dashboard ID"),
1056
+ },
1057
+ }, async (params) => {
1058
+ try {
1059
+ const res = await api.get(`/dashboards/${params.id}`);
1060
+ return text(res);
1061
+ }
1062
+ catch (e) {
1063
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1064
+ }
1065
+ });
1066
+ server.registerTool("lighthouse_reports_update_dashboard", {
1067
+ title: "Update Dashboard",
1068
+ description: "Update a dashboard's name, description, or sharing. Only the dashboard owner can update.",
1069
+ inputSchema: {
1070
+ id: z.string().uuid().describe("Dashboard ID"),
1071
+ name: z.string().optional().describe("New dashboard name"),
1072
+ description: z.string().optional().describe("New description"),
1073
+ sharing: z.enum(["private", "workspace"]).optional().describe("New visibility setting"),
1074
+ },
1075
+ }, async (params) => {
1076
+ try {
1077
+ const { id, ...body } = params;
1078
+ const res = await api.patch(`/dashboards/${id}`, body);
1079
+ return text(res);
1080
+ }
1081
+ catch (e) {
1082
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1083
+ }
1084
+ });
1085
+ server.registerTool("lighthouse_reports_delete_dashboard", {
1086
+ title: "Delete Dashboard",
1087
+ description: "Permanently delete a dashboard and all its widgets. Only the dashboard owner can delete.",
1088
+ inputSchema: {
1089
+ id: z.string().uuid().describe("Dashboard ID"),
1090
+ },
1091
+ }, async (params) => {
1092
+ try {
1093
+ const res = await api.delete(`/dashboards/${params.id}`);
1094
+ return text(res);
1095
+ }
1096
+ catch (e) {
1097
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1098
+ }
1099
+ });
1100
+ server.registerTool("lighthouse_reports_refresh_dashboard", {
1101
+ title: "Refresh Dashboard Data",
1102
+ description: "Refresh/fetch report data for all widgets in a dashboard. " +
1103
+ "Returns a map of { widget_id: report_data } for each widget.",
1104
+ inputSchema: {
1105
+ id: z.string().uuid().describe("Dashboard ID"),
1106
+ },
1107
+ }, async (params) => {
1108
+ try {
1109
+ const res = await api.post(`/dashboards/${params.id}/refresh`);
1110
+ return text(res);
1111
+ }
1112
+ catch (e) {
1113
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1114
+ }
1115
+ });
1116
+ // ─── Reports: Widgets ────────────────────────────────────
1117
+ server.registerTool("lighthouse_reports_list_widgets", {
1118
+ title: "List Dashboard Widgets",
1119
+ description: "Get all widgets for a dashboard.",
1120
+ inputSchema: {
1121
+ id: z.string().uuid().describe("Dashboard ID"),
1122
+ },
1123
+ }, async (params) => {
1124
+ try {
1125
+ const res = await api.get(`/dashboards/${params.id}/widgets`);
1126
+ return text(res);
1127
+ }
1128
+ catch (e) {
1129
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1130
+ }
1131
+ });
1132
+ server.registerTool("lighthouse_reports_create_widget", {
1133
+ title: "Create Report Widget",
1134
+ description: "Create a report widget (chart/table/KPI) on a dashboard. " +
1135
+ "WORKFLOW: 1) Call lighthouse_crm_get_attributes to discover field keys for the entity type, " +
1136
+ "2) Build a config object using those keys, 3) Create the widget. " +
1137
+ "Widget types: bar, line, pie, table, kpi, funnel, area. " +
1138
+ "Report types: standard (aggregate by field), funnel (pipeline conversion), stage_changes (historical transitions).",
1139
+ inputSchema: {
1140
+ dashboard_id: z.string().uuid().describe("Dashboard ID to add widget to"),
1141
+ name: z.string().describe("Widget/report name"),
1142
+ widget_type: z
1143
+ .enum(["bar", "line", "pie", "table", "kpi", "funnel", "area"])
1144
+ .describe("Visualization type"),
1145
+ config: z.record(z.unknown()).describe(WIDGET_CONFIG_DESCRIPTION),
1146
+ position: z
1147
+ .record(z.unknown())
1148
+ .optional()
1149
+ .describe("Grid position: {x: number, y: number, w: number, h: number}"),
1150
+ },
1151
+ }, async (params) => {
1152
+ try {
1153
+ const { dashboard_id, ...body } = params;
1154
+ const res = await api.post(`/dashboards/${dashboard_id}/widgets`, body);
1155
+ return text(res);
1156
+ }
1157
+ catch (e) {
1158
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1159
+ }
1160
+ });
1161
+ server.registerTool("lighthouse_reports_update_widget", {
1162
+ title: "Update Report Widget",
1163
+ description: "Update a report widget's name, type, config, or position. " +
1164
+ "Only provide fields you want to change — others are preserved.",
1165
+ inputSchema: {
1166
+ dashboard_id: z.string().uuid().describe("Dashboard ID"),
1167
+ widget_id: z.string().uuid().describe("Widget ID"),
1168
+ name: z.string().optional().describe("New widget name"),
1169
+ widget_type: z
1170
+ .enum(["bar", "line", "pie", "table", "kpi", "funnel", "area"])
1171
+ .optional()
1172
+ .describe("New visualization type"),
1173
+ config: z.record(z.unknown()).optional().describe(WIDGET_CONFIG_DESCRIPTION),
1174
+ position: z.record(z.unknown()).optional().describe("New grid position: {x, y, w, h}"),
1175
+ },
1176
+ }, async (params) => {
1177
+ try {
1178
+ const { dashboard_id, widget_id, ...body } = params;
1179
+ const res = await api.patch(`/dashboards/${dashboard_id}/widgets/${widget_id}`, body);
1180
+ return text(res);
1181
+ }
1182
+ catch (e) {
1183
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1184
+ }
1185
+ });
1186
+ server.registerTool("lighthouse_reports_delete_widget", {
1187
+ title: "Delete Report Widget",
1188
+ description: "Permanently delete a report widget from a dashboard.",
1189
+ inputSchema: {
1190
+ dashboard_id: z.string().uuid().describe("Dashboard ID"),
1191
+ widget_id: z.string().uuid().describe("Widget ID"),
1192
+ },
1193
+ }, async (params) => {
1194
+ try {
1195
+ const res = await api.delete(`/dashboards/${params.dashboard_id}/widgets/${params.widget_id}`);
1196
+ return text(res);
1197
+ }
1198
+ catch (e) {
1199
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1200
+ }
1201
+ });
1202
+ server.registerTool("lighthouse_reports_get_widget_data", {
1203
+ title: "Get Widget Report Data",
1204
+ description: "Fetch the aggregated report data for a specific widget. " +
1205
+ "Returns the computed data based on the widget's config (dimensions, measures, segments, filters). " +
1206
+ "For standard reports: array of {dimension, measure, segment?} rows. " +
1207
+ "For funnel reports: array of {stage, count} rows. " +
1208
+ "For historical reports: array of {period, from_stage, to_stage, transition_count} rows.",
1209
+ inputSchema: {
1210
+ dashboard_id: z.string().uuid().describe("Dashboard ID"),
1211
+ widget_id: z.string().uuid().describe("Widget ID"),
1212
+ },
1213
+ }, async (params) => {
1214
+ try {
1215
+ const res = await api.get(`/dashboards/${params.dashboard_id}/widgets/${params.widget_id}/data`);
1216
+ return text(res);
1217
+ }
1218
+ catch (e) {
1219
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1220
+ }
1221
+ });
1222
+ // ─── Sharing: Dashboard Teams ─────────────────────────────
1223
+ server.registerTool("lighthouse_reports_share_dashboard_with_teams", {
1224
+ title: "Share Dashboard with Teams",
1225
+ description: "Grant team-level access to a dashboard. Only the dashboard owner can share. " +
1226
+ "Use lighthouse_workspace_list_teams to find team IDs first. " +
1227
+ "Requires reports.edit permission.",
1228
+ inputSchema: {
1229
+ id: z.string().uuid().describe("Dashboard ID"),
1230
+ team_ids: z.array(z.string().uuid()).describe("Array of team UUIDs to grant access to"),
1231
+ },
1232
+ }, async (params) => {
1233
+ try {
1234
+ const { id, ...body } = params;
1235
+ const res = await api.post(`/dashboards/${id}/teams`, body);
1236
+ return text(res);
1237
+ }
1238
+ catch (e) {
1239
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1240
+ }
1241
+ });
1242
+ server.registerTool("lighthouse_reports_revoke_dashboard_from_teams", {
1243
+ title: "Revoke Dashboard Team Access",
1244
+ description: "Revoke team-level access from a dashboard. Only the dashboard owner can revoke. " +
1245
+ "Requires reports.edit permission.",
1246
+ inputSchema: {
1247
+ id: z.string().uuid().describe("Dashboard ID"),
1248
+ team_ids: z.array(z.string().uuid()).describe("Array of team UUIDs to revoke access from"),
1249
+ },
1250
+ }, async (params) => {
1251
+ try {
1252
+ const { id, ...body } = params;
1253
+ const res = await api.delete(`/dashboards/${id}/teams`, body);
1254
+ return text(res);
1255
+ }
1256
+ catch (e) {
1257
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1258
+ }
1259
+ });
1260
+ // ─── Sharing: View Teams ──────────────────────────────────
1261
+ server.registerTool("lighthouse_crm_share_view_with_teams", {
1262
+ title: "Share View with Teams",
1263
+ description: "Grant team-level access to a CRM view. Only the view owner can share. " +
1264
+ "Use lighthouse_workspace_list_teams to find team IDs first. " +
1265
+ "Requires views.share permission.",
1266
+ inputSchema: {
1267
+ id: z.string().uuid().describe("View ID"),
1268
+ team_ids: z.array(z.string().uuid()).describe("Array of team UUIDs to grant access to"),
1269
+ },
1270
+ }, async (params) => {
1271
+ try {
1272
+ const { id, ...body } = params;
1273
+ const res = await api.post(`/views/${id}/teams`, body);
1274
+ return text(res);
1275
+ }
1276
+ catch (e) {
1277
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1278
+ }
1279
+ });
1280
+ server.registerTool("lighthouse_crm_revoke_view_from_teams", {
1281
+ title: "Revoke View Team Access",
1282
+ description: "Revoke team-level access from a CRM view. Only the view owner can revoke. " +
1283
+ "Requires views.share permission.",
1284
+ inputSchema: {
1285
+ id: z.string().uuid().describe("View ID"),
1286
+ team_ids: z.array(z.string().uuid()).describe("Array of team UUIDs to revoke access from"),
1287
+ },
1288
+ }, async (params) => {
1289
+ try {
1290
+ const { id, ...body } = params;
1291
+ const res = await api.delete(`/views/${id}/teams`, body);
1292
+ return text(res);
1293
+ }
1294
+ catch (e) {
1295
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1296
+ }
1297
+ });
1298
+ server.registerTool("lighthouse_crm_update_view_sharing", {
1299
+ title: "Update View Sharing Status",
1300
+ description: "Change a CRM view's sharing visibility. Setting to 'private' also removes all team permissions. " +
1301
+ "Only the view owner can change sharing. Requires views.share permission.",
1302
+ inputSchema: {
1303
+ id: z.string().uuid().describe("View ID"),
1304
+ sharing: z.enum(["private", "workspace"]).describe("New sharing visibility"),
1305
+ },
1306
+ }, async (params) => {
1307
+ try {
1308
+ const { id, ...body } = params;
1309
+ const res = await api.patch(`/views/${id}/sharing`, body);
1310
+ return text(res);
1311
+ }
1312
+ catch (e) {
1313
+ return err(`Failed: ${e instanceof Error ? e.message : String(e)}`);
1314
+ }
1315
+ });
948
1316
  // ─── Start ───────────────────────────────────────────────
949
1317
  async function main() {
950
1318
  const transport = new StdioServerTransport();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trylighthouse/mcp-server",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "MCP server for the Lighthouse CRM API",
5
5
  "type": "module",
6
6
  "bin": {