gmail-workspace-mcp-server 0.0.3 → 0.0.5

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 (33) hide show
  1. package/README.md +145 -15
  2. package/build/index.integration-with-mock.js +140 -4
  3. package/build/index.js +23 -6
  4. package/package.json +1 -1
  5. package/shared/gmail-client/lib/drafts.d.ts +42 -0
  6. package/shared/gmail-client/lib/drafts.js +81 -0
  7. package/shared/gmail-client/lib/mime-utils.d.ts +20 -0
  8. package/shared/gmail-client/lib/mime-utils.js +38 -0
  9. package/shared/gmail-client/lib/modify-message.d.ts +9 -0
  10. package/shared/gmail-client/lib/modify-message.js +20 -0
  11. package/shared/gmail-client/lib/send-message.d.ts +18 -0
  12. package/shared/gmail-client/lib/send-message.js +40 -0
  13. package/shared/index.d.ts +2 -2
  14. package/shared/index.js +2 -2
  15. package/shared/server.d.ts +108 -1
  16. package/shared/server.js +43 -3
  17. package/shared/tools/change-email-conversation.d.ts +66 -0
  18. package/shared/tools/change-email-conversation.js +148 -0
  19. package/shared/tools/draft-email.d.ts +79 -0
  20. package/shared/tools/draft-email.js +150 -0
  21. package/shared/tools/{get-email.d.ts → get-email-conversation.d.ts} +9 -2
  22. package/shared/tools/{get-email.js → get-email-conversation.js} +59 -10
  23. package/shared/tools/{list-recent-emails.d.ts → list-email-conversations.d.ts} +28 -13
  24. package/shared/tools/list-email-conversations.js +150 -0
  25. package/shared/tools/search-email-conversations.d.ts +45 -0
  26. package/shared/tools/search-email-conversations.js +110 -0
  27. package/shared/tools/send-email.d.ts +104 -0
  28. package/shared/tools/send-email.js +181 -0
  29. package/shared/tools.d.ts +19 -2
  30. package/shared/tools.js +56 -8
  31. package/shared/utils/email-helpers.d.ts +4 -0
  32. package/shared/utils/email-helpers.js +15 -0
  33. package/shared/tools/list-recent-emails.js +0 -133
@@ -0,0 +1,18 @@
1
+ import type { Email } from '../../types.js';
2
+ /**
3
+ * Sends an email directly
4
+ */
5
+ export declare function sendMessage(baseUrl: string, headers: Record<string, string>, from: string, options: {
6
+ to: string;
7
+ subject: string;
8
+ body: string;
9
+ cc?: string;
10
+ bcc?: string;
11
+ threadId?: string;
12
+ inReplyTo?: string;
13
+ references?: string;
14
+ }): Promise<Email>;
15
+ /**
16
+ * Sends a draft (and deletes it)
17
+ */
18
+ export declare function sendDraft(baseUrl: string, headers: Record<string, string>, draftId: string): Promise<Email>;
@@ -0,0 +1,40 @@
1
+ import { handleApiError } from './api-errors.js';
2
+ import { buildMimeMessage, toBase64Url } from './mime-utils.js';
3
+ /**
4
+ * Sends an email directly
5
+ */
6
+ export async function sendMessage(baseUrl, headers, from, options) {
7
+ const url = `${baseUrl}/messages/send`;
8
+ const rawMessage = buildMimeMessage(from, options);
9
+ const encodedMessage = toBase64Url(rawMessage);
10
+ const requestBody = {
11
+ raw: encodedMessage,
12
+ };
13
+ if (options.threadId) {
14
+ requestBody.threadId = options.threadId;
15
+ }
16
+ const response = await fetch(url, {
17
+ method: 'POST',
18
+ headers,
19
+ body: JSON.stringify(requestBody),
20
+ });
21
+ if (!response.ok) {
22
+ handleApiError(response.status, 'sending message');
23
+ }
24
+ return (await response.json());
25
+ }
26
+ /**
27
+ * Sends a draft (and deletes it)
28
+ */
29
+ export async function sendDraft(baseUrl, headers, draftId) {
30
+ const url = `${baseUrl}/drafts/send`;
31
+ const response = await fetch(url, {
32
+ method: 'POST',
33
+ headers,
34
+ body: JSON.stringify({ id: draftId }),
35
+ });
36
+ if (!response.ok) {
37
+ handleApiError(response.status, 'sending draft', draftId);
38
+ }
39
+ return (await response.json());
40
+ }
package/shared/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { createMCPServer, createDefaultClient, ServiceAccountGmailClient, type IGmailClient, type ClientFactory, type ServiceAccountCredentials, } from './server.js';
2
- export { createRegisterTools, registerTools } from './tools.js';
1
+ export { createMCPServer, createDefaultClient, ServiceAccountGmailClient, type IGmailClient, type ClientFactory, type ServiceAccountCredentials, type CreateMCPServerOptions, type Draft, } from './server.js';
2
+ export { createRegisterTools, registerTools, parseEnabledToolGroups, getAvailableToolGroups, type ToolGroup, } from './tools.js';
3
3
  export { logServerStart, logError, logWarning, logDebug } from './logging.js';
4
4
  export type { Email, EmailListItem, EmailHeader, EmailPart, Label, Thread, PaginatedResponse, } from './types.js';
package/shared/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // Main exports for Gmail MCP Server
2
2
  // Server and client
3
3
  export { createMCPServer, createDefaultClient, ServiceAccountGmailClient, } from './server.js';
4
- // Tools
5
- export { createRegisterTools, registerTools } from './tools.js';
4
+ // Tools and tool groups
5
+ export { createRegisterTools, registerTools, parseEnabledToolGroups, getAvailableToolGroups, } from './tools.js';
6
6
  // Logging utilities
7
7
  export { logServerStart, logError, logWarning, logDebug } from './logging.js';
@@ -1,5 +1,12 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import type { Email, EmailListItem } from './types.js';
3
+ /**
4
+ * Draft message structure
5
+ */
6
+ export interface Draft {
7
+ id: string;
8
+ message: Email;
9
+ }
3
10
  /**
4
11
  * Gmail API client interface
5
12
  * Defines all methods for interacting with the Gmail API
@@ -25,6 +32,65 @@ export interface IGmailClient {
25
32
  format?: 'minimal' | 'full' | 'raw' | 'metadata';
26
33
  metadataHeaders?: string[];
27
34
  }): Promise<Email>;
35
+ /**
36
+ * Modify labels on a message (add/remove labels)
37
+ */
38
+ modifyMessage(messageId: string, options: {
39
+ addLabelIds?: string[];
40
+ removeLabelIds?: string[];
41
+ }): Promise<Email>;
42
+ /**
43
+ * Create a draft email
44
+ */
45
+ createDraft(options: {
46
+ to: string;
47
+ subject: string;
48
+ body: string;
49
+ cc?: string;
50
+ bcc?: string;
51
+ threadId?: string;
52
+ inReplyTo?: string;
53
+ references?: string;
54
+ }): Promise<Draft>;
55
+ /**
56
+ * Get a draft by ID
57
+ */
58
+ getDraft(draftId: string): Promise<Draft>;
59
+ /**
60
+ * List drafts
61
+ */
62
+ listDrafts(options?: {
63
+ maxResults?: number;
64
+ pageToken?: string;
65
+ }): Promise<{
66
+ drafts: Array<{
67
+ id: string;
68
+ message: EmailListItem;
69
+ }>;
70
+ nextPageToken?: string;
71
+ resultSizeEstimate?: number;
72
+ }>;
73
+ /**
74
+ * Delete a draft
75
+ */
76
+ deleteDraft(draftId: string): Promise<void>;
77
+ /**
78
+ * Send an email (either directly or from a draft)
79
+ */
80
+ sendMessage(options: {
81
+ to: string;
82
+ subject: string;
83
+ body: string;
84
+ cc?: string;
85
+ bcc?: string;
86
+ threadId?: string;
87
+ inReplyTo?: string;
88
+ references?: string;
89
+ }): Promise<Email>;
90
+ /**
91
+ * Send a draft
92
+ */
93
+ sendDraft(draftId: string): Promise<Email>;
28
94
  }
29
95
  /**
30
96
  * Service account credentials structure
@@ -68,8 +134,49 @@ export declare class ServiceAccountGmailClient implements IGmailClient {
68
134
  format?: 'minimal' | 'full' | 'raw' | 'metadata';
69
135
  metadataHeaders?: string[];
70
136
  }): Promise<Email>;
137
+ modifyMessage(messageId: string, options: {
138
+ addLabelIds?: string[];
139
+ removeLabelIds?: string[];
140
+ }): Promise<Email>;
141
+ createDraft(options: {
142
+ to: string;
143
+ subject: string;
144
+ body: string;
145
+ cc?: string;
146
+ bcc?: string;
147
+ threadId?: string;
148
+ inReplyTo?: string;
149
+ references?: string;
150
+ }): Promise<Draft>;
151
+ getDraft(draftId: string): Promise<Draft>;
152
+ listDrafts(options?: {
153
+ maxResults?: number;
154
+ pageToken?: string;
155
+ }): Promise<{
156
+ drafts: Array<{
157
+ id: string;
158
+ message: EmailListItem;
159
+ }>;
160
+ nextPageToken?: string;
161
+ resultSizeEstimate?: number;
162
+ }>;
163
+ deleteDraft(draftId: string): Promise<void>;
164
+ sendMessage(options: {
165
+ to: string;
166
+ subject: string;
167
+ body: string;
168
+ cc?: string;
169
+ bcc?: string;
170
+ threadId?: string;
171
+ inReplyTo?: string;
172
+ references?: string;
173
+ }): Promise<Email>;
174
+ sendDraft(draftId: string): Promise<Email>;
71
175
  }
72
176
  export type ClientFactory = () => IGmailClient;
177
+ export interface CreateMCPServerOptions {
178
+ version: string;
179
+ }
73
180
  /**
74
181
  * Creates the default Gmail client based on environment variables.
75
182
  * Uses service account with domain-wide delegation:
@@ -78,7 +185,7 @@ export type ClientFactory = () => IGmailClient;
78
185
  * - GMAIL_IMPERSONATE_EMAIL: Email address to impersonate
79
186
  */
80
187
  export declare function createDefaultClient(): IGmailClient;
81
- export declare function createMCPServer(): {
188
+ export declare function createMCPServer(options: CreateMCPServerOptions): {
82
189
  server: Server<{
83
190
  method: string;
84
191
  params?: {
package/shared/server.js CHANGED
@@ -16,7 +16,12 @@ export class ServiceAccountGmailClient {
16
16
  this.jwtClient = new JWT({
17
17
  email: credentials.client_email,
18
18
  key: credentials.private_key,
19
- scopes: ['https://www.googleapis.com/auth/gmail.readonly'],
19
+ scopes: [
20
+ 'https://www.googleapis.com/auth/gmail.readonly',
21
+ 'https://www.googleapis.com/auth/gmail.modify',
22
+ 'https://www.googleapis.com/auth/gmail.compose',
23
+ 'https://www.googleapis.com/auth/gmail.send',
24
+ ],
20
25
  subject: impersonateEmail,
21
26
  });
22
27
  }
@@ -59,6 +64,41 @@ export class ServiceAccountGmailClient {
59
64
  const { getMessage } = await import('./gmail-client/lib/get-message.js');
60
65
  return getMessage(this.baseUrl, headers, messageId, options);
61
66
  }
67
+ async modifyMessage(messageId, options) {
68
+ const headers = await this.getHeaders();
69
+ const { modifyMessage } = await import('./gmail-client/lib/modify-message.js');
70
+ return modifyMessage(this.baseUrl, headers, messageId, options);
71
+ }
72
+ async createDraft(options) {
73
+ const headers = await this.getHeaders();
74
+ const { createDraft } = await import('./gmail-client/lib/drafts.js');
75
+ return createDraft(this.baseUrl, headers, this.impersonateEmail, options);
76
+ }
77
+ async getDraft(draftId) {
78
+ const headers = await this.getHeaders();
79
+ const { getDraft } = await import('./gmail-client/lib/drafts.js');
80
+ return getDraft(this.baseUrl, headers, draftId);
81
+ }
82
+ async listDrafts(options) {
83
+ const headers = await this.getHeaders();
84
+ const { listDrafts } = await import('./gmail-client/lib/drafts.js');
85
+ return listDrafts(this.baseUrl, headers, options);
86
+ }
87
+ async deleteDraft(draftId) {
88
+ const headers = await this.getHeaders();
89
+ const { deleteDraft } = await import('./gmail-client/lib/drafts.js');
90
+ return deleteDraft(this.baseUrl, headers, draftId);
91
+ }
92
+ async sendMessage(options) {
93
+ const headers = await this.getHeaders();
94
+ const { sendMessage } = await import('./gmail-client/lib/send-message.js');
95
+ return sendMessage(this.baseUrl, headers, this.impersonateEmail, options);
96
+ }
97
+ async sendDraft(draftId) {
98
+ const headers = await this.getHeaders();
99
+ const { sendDraft } = await import('./gmail-client/lib/send-message.js');
100
+ return sendDraft(this.baseUrl, headers, draftId);
101
+ }
62
102
  }
63
103
  /**
64
104
  * Creates the default Gmail client based on environment variables.
@@ -98,10 +138,10 @@ export function createDefaultClient() {
98
138
  };
99
139
  return new ServiceAccountGmailClient(credentials, impersonateEmail);
100
140
  }
101
- export function createMCPServer() {
141
+ export function createMCPServer(options) {
102
142
  const server = new Server({
103
143
  name: 'gmail-workspace-mcp-server',
104
- version: '0.0.2',
144
+ version: options.version,
105
145
  }, {
106
146
  capabilities: {
107
147
  tools: {},
@@ -0,0 +1,66 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { z } from 'zod';
3
+ import type { ClientFactory } from '../server.js';
4
+ export declare const ChangeEmailConversationSchema: z.ZodObject<{
5
+ email_id: z.ZodString;
6
+ status: z.ZodOptional<z.ZodEnum<["read", "unread", "archived"]>>;
7
+ labels: z.ZodOptional<z.ZodString>;
8
+ remove_labels: z.ZodOptional<z.ZodString>;
9
+ is_starred: z.ZodOptional<z.ZodBoolean>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ email_id: string;
12
+ labels?: string | undefined;
13
+ status?: "read" | "unread" | "archived" | undefined;
14
+ remove_labels?: string | undefined;
15
+ is_starred?: boolean | undefined;
16
+ }, {
17
+ email_id: string;
18
+ labels?: string | undefined;
19
+ status?: "read" | "unread" | "archived" | undefined;
20
+ remove_labels?: string | undefined;
21
+ is_starred?: boolean | undefined;
22
+ }>;
23
+ export declare function changeEmailConversationTool(server: Server, clientFactory: ClientFactory): {
24
+ name: string;
25
+ description: string;
26
+ inputSchema: {
27
+ type: "object";
28
+ properties: {
29
+ email_id: {
30
+ type: string;
31
+ description: string;
32
+ };
33
+ status: {
34
+ type: string;
35
+ enum: string[];
36
+ description: string;
37
+ };
38
+ labels: {
39
+ type: string;
40
+ description: string;
41
+ };
42
+ remove_labels: {
43
+ type: string;
44
+ description: string;
45
+ };
46
+ is_starred: {
47
+ type: string;
48
+ description: "Star or unstar the email. Set to true to star, false to unstar.";
49
+ };
50
+ };
51
+ required: string[];
52
+ };
53
+ handler: (args: unknown) => Promise<{
54
+ content: {
55
+ type: string;
56
+ text: string;
57
+ }[];
58
+ isError?: undefined;
59
+ } | {
60
+ content: {
61
+ type: string;
62
+ text: string;
63
+ }[];
64
+ isError: boolean;
65
+ }>;
66
+ };
@@ -0,0 +1,148 @@
1
+ import { z } from 'zod';
2
+ const PARAM_DESCRIPTIONS = {
3
+ email_id: 'The unique identifier of the email to modify. ' +
4
+ 'Obtain this from list_email_conversations or search_email_conversations.',
5
+ status: 'Mark the email as read, unread, or archived. ' + 'Options: read, unread, archived.',
6
+ labels: 'Labels to add to the email. Comma-separated list. ' +
7
+ 'Common labels: STARRED, IMPORTANT. User labels should be the label ID.',
8
+ remove_labels: 'Labels to remove from the email. Comma-separated list. ' +
9
+ 'Common labels: STARRED, IMPORTANT, UNREAD. User labels should be the label ID.',
10
+ is_starred: 'Star or unstar the email. Set to true to star, false to unstar.',
11
+ };
12
+ export const ChangeEmailConversationSchema = z.object({
13
+ email_id: z.string().min(1).describe(PARAM_DESCRIPTIONS.email_id),
14
+ status: z.enum(['read', 'unread', 'archived']).optional().describe(PARAM_DESCRIPTIONS.status),
15
+ labels: z.string().optional().describe(PARAM_DESCRIPTIONS.labels),
16
+ remove_labels: z.string().optional().describe(PARAM_DESCRIPTIONS.remove_labels),
17
+ is_starred: z.boolean().optional().describe(PARAM_DESCRIPTIONS.is_starred),
18
+ });
19
+ const TOOL_DESCRIPTION = `Modify an email conversation's status, labels, or starred state.
20
+
21
+ **Parameters:**
22
+ - email_id: The unique identifier of the email (required)
23
+ - status: Mark as "read", "unread", or "archived" (optional)
24
+ - labels: Comma-separated labels to add (optional)
25
+ - remove_labels: Comma-separated labels to remove (optional)
26
+ - is_starred: Set to true to star, false to unstar (optional)
27
+
28
+ **Label operations:**
29
+ - Adding STARRED marks the email as starred
30
+ - Removing INBOX archives the email
31
+ - Adding/removing UNREAD marks email as unread/read
32
+
33
+ **Use cases:**
34
+ - Mark an email as read/unread
35
+ - Star important emails
36
+ - Archive emails (remove from inbox)
37
+ - Apply custom labels for organization
38
+
39
+ **Note:** Get email_id from list_email_conversations or search_email_conversations first.`;
40
+ export function changeEmailConversationTool(server, clientFactory) {
41
+ return {
42
+ name: 'change_email_conversation',
43
+ description: TOOL_DESCRIPTION,
44
+ inputSchema: {
45
+ type: 'object',
46
+ properties: {
47
+ email_id: {
48
+ type: 'string',
49
+ description: PARAM_DESCRIPTIONS.email_id,
50
+ },
51
+ status: {
52
+ type: 'string',
53
+ enum: ['read', 'unread', 'archived'],
54
+ description: PARAM_DESCRIPTIONS.status,
55
+ },
56
+ labels: {
57
+ type: 'string',
58
+ description: PARAM_DESCRIPTIONS.labels,
59
+ },
60
+ remove_labels: {
61
+ type: 'string',
62
+ description: PARAM_DESCRIPTIONS.remove_labels,
63
+ },
64
+ is_starred: {
65
+ type: 'boolean',
66
+ description: PARAM_DESCRIPTIONS.is_starred,
67
+ },
68
+ },
69
+ required: ['email_id'],
70
+ },
71
+ handler: async (args) => {
72
+ try {
73
+ const parsed = ChangeEmailConversationSchema.parse(args ?? {});
74
+ const client = clientFactory();
75
+ const addLabelIds = [];
76
+ const removeLabelIds = [];
77
+ // Handle status
78
+ if (parsed.status === 'read') {
79
+ removeLabelIds.push('UNREAD');
80
+ }
81
+ else if (parsed.status === 'unread') {
82
+ addLabelIds.push('UNREAD');
83
+ }
84
+ else if (parsed.status === 'archived') {
85
+ removeLabelIds.push('INBOX');
86
+ }
87
+ // Handle is_starred
88
+ if (parsed.is_starred === true) {
89
+ addLabelIds.push('STARRED');
90
+ }
91
+ else if (parsed.is_starred === false) {
92
+ removeLabelIds.push('STARRED');
93
+ }
94
+ // Handle labels to add
95
+ if (parsed.labels) {
96
+ const labels = parsed.labels.split(',').map((l) => l.trim());
97
+ addLabelIds.push(...labels);
98
+ }
99
+ // Handle labels to remove
100
+ if (parsed.remove_labels) {
101
+ const labels = parsed.remove_labels.split(',').map((l) => l.trim());
102
+ removeLabelIds.push(...labels);
103
+ }
104
+ // Only make API call if there are changes to make
105
+ if (addLabelIds.length === 0 && removeLabelIds.length === 0) {
106
+ return {
107
+ content: [
108
+ {
109
+ type: 'text',
110
+ text: 'No changes specified. Provide at least one of: status, labels, remove_labels, or is_starred.',
111
+ },
112
+ ],
113
+ };
114
+ }
115
+ const updatedEmail = await client.modifyMessage(parsed.email_id, {
116
+ addLabelIds: addLabelIds.length > 0 ? addLabelIds : undefined,
117
+ removeLabelIds: removeLabelIds.length > 0 ? removeLabelIds : undefined,
118
+ });
119
+ const changes = [];
120
+ if (addLabelIds.length > 0) {
121
+ changes.push(`Added labels: ${addLabelIds.join(', ')}`);
122
+ }
123
+ if (removeLabelIds.length > 0) {
124
+ changes.push(`Removed labels: ${removeLabelIds.join(', ')}`);
125
+ }
126
+ return {
127
+ content: [
128
+ {
129
+ type: 'text',
130
+ text: `Email ${parsed.email_id} updated successfully.\n\n${changes.join('\n')}\n\nCurrent labels: ${updatedEmail.labelIds?.join(', ') || 'None'}`,
131
+ },
132
+ ],
133
+ };
134
+ }
135
+ catch (error) {
136
+ return {
137
+ content: [
138
+ {
139
+ type: 'text',
140
+ text: `Error modifying email: ${error instanceof Error ? error.message : 'Unknown error'}`,
141
+ },
142
+ ],
143
+ isError: true,
144
+ };
145
+ }
146
+ },
147
+ };
148
+ }
@@ -0,0 +1,79 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { z } from 'zod';
3
+ import type { ClientFactory } from '../server.js';
4
+ export declare const DraftEmailSchema: z.ZodObject<{
5
+ to: z.ZodString;
6
+ subject: z.ZodString;
7
+ body: z.ZodString;
8
+ cc: z.ZodOptional<z.ZodString>;
9
+ bcc: z.ZodOptional<z.ZodString>;
10
+ thread_id: z.ZodOptional<z.ZodString>;
11
+ reply_to_email_id: z.ZodOptional<z.ZodString>;
12
+ }, "strip", z.ZodTypeAny, {
13
+ body: string;
14
+ to: string;
15
+ subject: string;
16
+ cc?: string | undefined;
17
+ bcc?: string | undefined;
18
+ thread_id?: string | undefined;
19
+ reply_to_email_id?: string | undefined;
20
+ }, {
21
+ body: string;
22
+ to: string;
23
+ subject: string;
24
+ cc?: string | undefined;
25
+ bcc?: string | undefined;
26
+ thread_id?: string | undefined;
27
+ reply_to_email_id?: string | undefined;
28
+ }>;
29
+ export declare function draftEmailTool(server: Server, clientFactory: ClientFactory): {
30
+ name: string;
31
+ description: string;
32
+ inputSchema: {
33
+ type: "object";
34
+ properties: {
35
+ to: {
36
+ type: string;
37
+ description: "Recipient email address(es). For multiple recipients, separate with commas.";
38
+ };
39
+ subject: {
40
+ type: string;
41
+ description: "Subject line of the email.";
42
+ };
43
+ body: {
44
+ type: string;
45
+ description: "Plain text body content of the email.";
46
+ };
47
+ cc: {
48
+ type: string;
49
+ description: "CC recipient email address(es). For multiple, separate with commas.";
50
+ };
51
+ bcc: {
52
+ type: string;
53
+ description: "BCC recipient email address(es). For multiple, separate with commas.";
54
+ };
55
+ thread_id: {
56
+ type: string;
57
+ description: string;
58
+ };
59
+ reply_to_email_id: {
60
+ type: string;
61
+ description: string;
62
+ };
63
+ };
64
+ required: string[];
65
+ };
66
+ handler: (args: unknown) => Promise<{
67
+ content: {
68
+ type: string;
69
+ text: string;
70
+ }[];
71
+ isError?: undefined;
72
+ } | {
73
+ content: {
74
+ type: string;
75
+ text: string;
76
+ }[];
77
+ isError: boolean;
78
+ }>;
79
+ };