@sealab/mcp-server 1.0.1 → 1.0.3

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.
@@ -212,7 +212,7 @@ async function applySavedSettingsToArticles<T extends { settingsName?: string; [
212
212
  return Promise.all(articles.map(applySavedSettingToArticle));
213
213
  }
214
214
 
215
- const ArticleItemSchema = z.object({
215
+ export const ArticleItemSchema = z.object({
216
216
  serialNumber: z.string(),
217
217
  positionName: z.string().max(25).describe(
218
218
  'Unique label for this cabinet within the order. Must be unique across ALL articles in the order. ' +
@@ -0,0 +1,169 @@
1
+ import { z } from 'zod';
2
+ import { client, handleAxiosError } from '../client/api-client';
3
+
4
+ // ─── Schemas ─────────────────────────────────────────────────────────────────
5
+
6
+ const ShareOrderSchema = z.object({
7
+ orderId: z.string().describe('The order ID to share access to.'),
8
+ grantedToEmail: z.string().describe('Email address of the user to grant access to.'),
9
+ permissionType: z.enum(['VIEW', 'EDIT', 'ADMIN']).default('VIEW').describe(
10
+ 'Permission level to grant. VIEW = read-only (default), EDIT = can modify order options, ADMIN = full control.'
11
+ ),
12
+ hidePrice: z.boolean().default(false).describe(
13
+ 'Whether to hide pricing information from this user. Defaults to false.'
14
+ ),
15
+ });
16
+
17
+ const UpdateOrderAccessSchema = z.object({
18
+ orderId: z.string().describe('The order ID whose permission you want to update.'),
19
+ grantedToEmail: z.string().describe('Email address of the user whose permission to update.'),
20
+ permissionType: z.enum(['VIEW', 'EDIT', 'ADMIN']).describe(
21
+ 'New permission level. VIEW = read-only, EDIT = can modify order options, ADMIN = full control.'
22
+ ),
23
+ hidePrice: z.boolean().default(false).describe(
24
+ 'Whether to hide pricing information from this user.'
25
+ ),
26
+ });
27
+
28
+ const RevokeOrderAccessSchema = z.object({
29
+ orderId: z.string().describe('The order ID to revoke access from.'),
30
+ email: z.string().describe('Email address of the user whose access to revoke.'),
31
+ });
32
+
33
+ const ListOrderAccessSchema = z.object({
34
+ orderId: z.string().describe('The order ID to list shared access for.'),
35
+ });
36
+
37
+ // ─── Handlers ────────────────────────────────────────────────────────────────
38
+
39
+ export async function shareOrderAccess(input: z.infer<typeof ShareOrderSchema>): Promise<string> {
40
+ try {
41
+ const { data } = await client.post(`/orders/${input.orderId}/permissions/grant`, {
42
+ grantedToEmail: input.grantedToEmail,
43
+ permissionType: input.permissionType,
44
+ hidePrice: input.hidePrice,
45
+ });
46
+ const priceNote = input.hidePrice ? ' Prices will be hidden from them.' : '';
47
+ return `Access granted. ${input.grantedToEmail} now has ${input.permissionType} access to order ${input.orderId}.${priceNote} They will receive an email notification.`;
48
+ } catch (error) {
49
+ try { handleAxiosError(error); } catch (e: any) { return e.message; }
50
+ return 'Unexpected error granting order access.';
51
+ }
52
+ }
53
+
54
+ export async function updateOrderAccess(input: z.infer<typeof UpdateOrderAccessSchema>): Promise<string> {
55
+ try {
56
+ await client.put(`/orders/${input.orderId}/permissions/update`, {
57
+ grantedToEmail: input.grantedToEmail,
58
+ permissionType: input.permissionType,
59
+ hidePrice: input.hidePrice,
60
+ });
61
+ const priceNote = input.hidePrice ? ' Prices are hidden from them.' : ' Prices are visible to them.';
62
+ return `Permission updated. ${input.grantedToEmail} now has ${input.permissionType} access to order ${input.orderId}.${priceNote}`;
63
+ } catch (error) {
64
+ try { handleAxiosError(error); } catch (e: any) { return e.message; }
65
+ return 'Unexpected error updating order access.';
66
+ }
67
+ }
68
+
69
+ export async function revokeOrderAccess(input: z.infer<typeof RevokeOrderAccessSchema>): Promise<string> {
70
+ try {
71
+ await client.delete(`/orders/${input.orderId}/permissions/revoke`, {
72
+ params: { email: input.email },
73
+ });
74
+ return `Access revoked. ${input.email} can no longer access order ${input.orderId}.`;
75
+ } catch (error) {
76
+ try { handleAxiosError(error); } catch (e: any) { return e.message; }
77
+ return 'Unexpected error revoking order access.';
78
+ }
79
+ }
80
+
81
+ export async function listOrderAccess(input: z.infer<typeof ListOrderAccessSchema>): Promise<string> {
82
+ try {
83
+ const { data } = await client.get(`/orders/${input.orderId}/permissions`);
84
+ if (!data || data.length === 0) {
85
+ return `No shared access on order ${input.orderId}. Only you can view it.`;
86
+ }
87
+ const lines: string[] = [`Shared access for order ${input.orderId}:\n`];
88
+ for (const p of data) {
89
+ const priceNote = p.hidePrice ? ' | Prices hidden' : '';
90
+ const grantedDate = p.grantedDate ? ` | Granted: ${p.grantedDate.split('T')[0]}` : '';
91
+ lines.push(`• ${p.grantedToEmail} — ${p.permissionType}${priceNote}${grantedDate}`);
92
+ }
93
+ return lines.join('\n');
94
+ } catch (error) {
95
+ try { handleAxiosError(error); } catch (e: any) { return e.message; }
96
+ return 'Unexpected error listing order access.';
97
+ }
98
+ }
99
+
100
+ // ─── Tool Definitions ─────────────────────────────────────────────────────────
101
+
102
+ export const permissionTools = [
103
+ {
104
+ name: 'share_order_access',
105
+ description: `Grant another user access to one of your orders.
106
+
107
+ Use when the user says things like:
108
+ - "Share order 12345 with someone@email.com"
109
+ - "Give Jane access to my order"
110
+ - "Let my contractor view this order without seeing prices"
111
+
112
+ BEFORE calling, confirm with the user:
113
+ - The order ID
114
+ - The recipient's email address
115
+ - Permission level: VIEW (read-only, default), EDIT (modify options), ADMIN (full control)
116
+ - Whether to hide prices from the recipient (default: no)
117
+
118
+ After granting:
119
+ - The recipient receives an email notification
120
+ - They log in to their Sealab account to view the shared order
121
+ - You can update or revoke access at any time using the other permission tools
122
+
123
+ Rules enforced by the system:
124
+ - You can only share your own orders
125
+ - Cannot share with yourself
126
+ - Maximum 50 users per order`,
127
+ inputSchema: ShareOrderSchema,
128
+ handler: shareOrderAccess,
129
+ },
130
+ {
131
+ name: 'update_order_access',
132
+ description: `Update the permission level or price visibility for a user who already has access to one of your orders.
133
+
134
+ Use when the user wants to:
135
+ - Change someone's permission from VIEW to EDIT or ADMIN
136
+ - Toggle whether prices are hidden for a specific user
137
+ - Adjust existing shared access without revoking and re-granting
138
+
139
+ Requires the order ID, the user's email, the new permission type, and the new hidePrice setting.`,
140
+ inputSchema: UpdateOrderAccessSchema,
141
+ handler: updateOrderAccess,
142
+ },
143
+ {
144
+ name: 'revoke_order_access',
145
+ description: `Revoke a user's access to one of your orders.
146
+
147
+ Use when the user wants to:
148
+ - Remove someone's access to an order
149
+ - Revoke a collaborator or contractor's view of an order
150
+
151
+ After revoking, the user immediately loses access. No email notification is sent on revocation.
152
+
153
+ Requires the order ID and the email address of the user whose access to remove.`,
154
+ inputSchema: RevokeOrderAccessSchema,
155
+ handler: revokeOrderAccess,
156
+ },
157
+ {
158
+ name: 'list_order_access',
159
+ description: `List all users who currently have shared access to one of your orders.
160
+
161
+ Returns each user's email, permission level (VIEW/EDIT/ADMIN), whether prices are hidden for them, and the date access was granted.
162
+
163
+ Use when the user asks:
164
+ - "Who has access to order 12345?"
165
+ - "Show me who I've shared this order with"`,
166
+ inputSchema: ListOrderAccessSchema,
167
+ handler: listOrderAccess,
168
+ },
169
+ ];