@telitask/mcp-server 0.1.2 → 0.1.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"calls.d.ts","sourceRoot":"","sources":["../../src/tools/calls.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAyJzE,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAgF5C;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAwC5C;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAgC5C;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAuC5C;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAwC5C;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAyF5C;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6EzD"}
1
+ {"version":3,"file":"calls.d.ts","sourceRoot":"","sources":["../../src/tools/calls.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4JzE,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAgF5C;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAwE5C;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAgC5C;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAuC5C;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAwC5C;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAyF5C;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6EzD"}
@@ -13,27 +13,29 @@ async function waitForCallCompletion(callId) {
13
13
  while (Date.now() - startTime < MAX_POLL_DURATION_MS) {
14
14
  const { data: call } = await supabase
15
15
  .from('calls')
16
- .select('status, call_summary, transcript, duration_seconds')
16
+ .select('status, call_summary, summary, transcript, duration_seconds')
17
17
  .eq('id', callId)
18
18
  .eq('user_id', userId)
19
19
  .single();
20
20
  if (!call)
21
21
  return null;
22
+ // Use whichever summary field is available (voice server writes to `summary`, on-behalf writes to `call_summary`)
23
+ const callSummary = call.call_summary || call.summary;
22
24
  // Terminal non-completed statuses — return immediately with whatever data is available
23
25
  if (TERMINAL_STATUSES.includes(call.status)) {
24
26
  return {
25
27
  status: call.status,
26
- summary: call.call_summary,
28
+ summary: callSummary,
27
29
  transcript: call.transcript,
28
30
  duration_seconds: call.duration_seconds,
29
31
  };
30
32
  }
31
33
  // Call completed — wait up to 60s for summary/transcript to be generated
32
34
  if (call.status === 'completed') {
33
- if (call.call_summary && call.transcript) {
35
+ if (callSummary && call.transcript) {
34
36
  return {
35
37
  status: call.status,
36
- summary: call.call_summary,
38
+ summary: callSummary,
37
39
  transcript: call.transcript,
38
40
  duration_seconds: call.duration_seconds,
39
41
  };
@@ -43,7 +45,7 @@ async function waitForCallCompletion(callId) {
43
45
  if (Date.now() - completedSince >= POST_COMPLETION_TIMEOUT_MS) {
44
46
  return {
45
47
  status: call.status,
46
- summary: call.call_summary,
48
+ summary: callSummary,
47
49
  transcript: call.transcript,
48
50
  duration_seconds: call.duration_seconds,
49
51
  };
@@ -194,26 +196,54 @@ export async function handleScheduleCall(params) {
194
196
  const userId = getUserId();
195
197
  const voiceServerUrl = getVoiceServerUrl();
196
198
  const accessToken = getAccessToken();
197
- const contactResult = await resolveContact(params.contact_id, params.contact_name);
198
- if (Array.isArray(contactResult))
199
- return contactResult;
200
199
  const personaId = await resolvePersonaId(params.persona_id, userId);
201
200
  if (!personaId) {
202
201
  return [{ type: 'text', text: 'No persona specified and no default persona set. Please provide a persona_id.' }];
203
202
  }
203
+ // Determine if this is a self-call or a contact call
204
+ const isContactCall = !!(params.contact_id || params.contact_name);
205
+ let callType;
206
+ let contactId;
207
+ let targetName;
208
+ if (isContactCall) {
209
+ const contactResult = await resolveContact(params.contact_id, params.contact_name);
210
+ if (Array.isArray(contactResult))
211
+ return contactResult;
212
+ callType = 'on_behalf';
213
+ contactId = contactResult.id;
214
+ targetName = contactResult.full_name;
215
+ }
216
+ else {
217
+ // Self-call: verify user has a phone number
218
+ const supabase = getAuthenticatedClient();
219
+ const { data: userProfile, error } = await supabase
220
+ .from('users')
221
+ .select('phone_number')
222
+ .eq('id', userId)
223
+ .single();
224
+ if (error) {
225
+ return [{ type: 'text', text: `Failed to look up your profile: ${error.message}` }];
226
+ }
227
+ if (!userProfile?.phone_number) {
228
+ return [{ type: 'text', text: 'No phone number on your profile. Please add one in the dashboard settings.' }];
229
+ }
230
+ callType = 'direct';
231
+ targetName = 'you';
232
+ }
233
+ const body = {
234
+ personaId,
235
+ callType,
236
+ purpose: params.brief,
237
+ scheduledAt: params.scheduled_at,
238
+ ...(contactId && { contactId }),
239
+ };
204
240
  const response = await fetch(`${voiceServerUrl}/api/scheduled-calls`, {
205
241
  method: 'POST',
206
242
  headers: {
207
243
  'Content-Type': 'application/json',
208
244
  Authorization: `Bearer ${accessToken}`,
209
245
  },
210
- body: JSON.stringify({
211
- personaId,
212
- callType: 'on_behalf',
213
- contactId: contactResult.id,
214
- purpose: params.brief,
215
- scheduledAt: params.scheduled_at,
216
- }),
246
+ body: JSON.stringify(body),
217
247
  });
218
248
  if (!response.ok) {
219
249
  const errBody = await response.text().catch(() => '');
@@ -222,7 +252,7 @@ export async function handleScheduleCall(params) {
222
252
  const result = await response.json();
223
253
  return [{
224
254
  type: 'text',
225
- text: `Call scheduled to **${contactResult.full_name}** at ${params.scheduled_at}.\nBrief: ${params.brief}\nScheduled call ID: ${result.id ?? 'pending'}`,
255
+ text: `Call scheduled to **${targetName}** at ${params.scheduled_at}.\nBrief: ${params.brief}\nScheduled call ID: ${result.id ?? 'pending'}`,
226
256
  }];
227
257
  }
228
258
  export async function handleCancelCall(params) {
@@ -423,7 +453,7 @@ export function registerCallTools(server) {
423
453
  }, async ({ contact_id, contact_name, brief, persona_id, wait_for_result }) => ({
424
454
  content: await handleMakeCall({ contact_id, contact_name, brief, persona_id, wait_for_result }),
425
455
  }));
426
- server.tool('schedule_call', 'Schedule a phone call for a future time. Resolves contacts by ID or name.', {
456
+ server.tool('schedule_call', 'Schedule a phone call for a future time. If contact_id or contact_name is provided, schedules a call to that contact. If neither is provided, schedules a call to the user\'s own phone number.', {
427
457
  contact_id: z.string().optional().describe('Contact ID to call'),
428
458
  contact_name: z.string().optional().describe('Contact name to search for'),
429
459
  brief: z.string().describe('Purpose/brief for the call'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telitask/mcp-server",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "TeliTask MCP server — manage contacts, tasks, and calls from AI assistants",
5
5
  "type": "module",
6
6
  "license": "MIT",