@ikenga/mcp-meetings 0.1.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.
Files changed (39) hide show
  1. package/LICENSE +201 -0
  2. package/dist/index.d.ts +132 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +97 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.test.d.ts +2 -0
  7. package/dist/index.test.d.ts.map +1 -0
  8. package/dist/index.test.js +72 -0
  9. package/dist/index.test.js.map +1 -0
  10. package/dist/integration.test.d.ts +2 -0
  11. package/dist/integration.test.d.ts.map +1 -0
  12. package/dist/integration.test.js +181 -0
  13. package/dist/integration.test.js.map +1 -0
  14. package/dist/sqlite.d.ts +49 -0
  15. package/dist/sqlite.d.ts.map +1 -0
  16. package/dist/sqlite.js +303 -0
  17. package/dist/sqlite.js.map +1 -0
  18. package/dist/sqlite.test.d.ts +2 -0
  19. package/dist/sqlite.test.d.ts.map +1 -0
  20. package/dist/sqlite.test.js +36 -0
  21. package/dist/sqlite.test.js.map +1 -0
  22. package/dist/tools/recorder.d.ts +94 -0
  23. package/dist/tools/recorder.d.ts.map +1 -0
  24. package/dist/tools/recorder.js +187 -0
  25. package/dist/tools/recorder.js.map +1 -0
  26. package/dist/tools/recorder.test.d.ts +2 -0
  27. package/dist/tools/recorder.test.d.ts.map +1 -0
  28. package/dist/tools/recorder.test.js +94 -0
  29. package/dist/tools/recorder.test.js.map +1 -0
  30. package/dist/tools/search.d.ts +35 -0
  31. package/dist/tools/search.d.ts.map +1 -0
  32. package/dist/tools/search.js +112 -0
  33. package/dist/tools/search.js.map +1 -0
  34. package/dist/tools/search.test.d.ts +2 -0
  35. package/dist/tools/search.test.d.ts.map +1 -0
  36. package/dist/tools/search.test.js +116 -0
  37. package/dist/tools/search.test.js.map +1 -0
  38. package/manifest.json +39 -0
  39. package/package.json +38 -0
@@ -0,0 +1,94 @@
1
+ import { MeetingsDbClient } from '@ikenga/meetings-contract';
2
+ export declare const RECORDER_TOOLS: ({
3
+ name: string;
4
+ description: string;
5
+ inputSchema: {
6
+ type: string;
7
+ properties: {
8
+ status: {
9
+ type: string;
10
+ enum: string[];
11
+ description: string;
12
+ };
13
+ limit: {
14
+ type: string;
15
+ description: string;
16
+ };
17
+ title?: undefined;
18
+ meeting_id?: undefined;
19
+ start_time?: undefined;
20
+ platform?: undefined;
21
+ url?: undefined;
22
+ };
23
+ required?: undefined;
24
+ };
25
+ } | {
26
+ name: string;
27
+ description: string;
28
+ inputSchema: {
29
+ type: string;
30
+ properties: {
31
+ title: {
32
+ type: string;
33
+ description: string;
34
+ };
35
+ status?: undefined;
36
+ limit?: undefined;
37
+ meeting_id?: undefined;
38
+ start_time?: undefined;
39
+ platform?: undefined;
40
+ url?: undefined;
41
+ };
42
+ required: string[];
43
+ };
44
+ } | {
45
+ name: string;
46
+ description: string;
47
+ inputSchema: {
48
+ type: string;
49
+ properties: {
50
+ meeting_id: {
51
+ type: string;
52
+ description: string;
53
+ };
54
+ status?: undefined;
55
+ limit?: undefined;
56
+ title?: undefined;
57
+ start_time?: undefined;
58
+ platform?: undefined;
59
+ url?: undefined;
60
+ };
61
+ required: string[];
62
+ };
63
+ } | {
64
+ name: string;
65
+ description: string;
66
+ inputSchema: {
67
+ type: string;
68
+ properties: {
69
+ title: {
70
+ type: string;
71
+ description: string;
72
+ };
73
+ start_time: {
74
+ type: string;
75
+ description: string;
76
+ };
77
+ platform: {
78
+ type: string;
79
+ enum: string[];
80
+ default: string;
81
+ };
82
+ url: {
83
+ type: string;
84
+ description: string;
85
+ };
86
+ status?: undefined;
87
+ limit?: undefined;
88
+ meeting_id?: undefined;
89
+ };
90
+ required: string[];
91
+ };
92
+ })[];
93
+ export declare function handleRecorderTool(client: MeetingsDbClient, name: string, args: any): Promise<any>;
94
+ //# sourceMappingURL=recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/tools/recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAiB,MAAM,2BAA2B,CAAC;AAG5E,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAyG1B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,GAAG,GACR,OAAO,CAAC,GAAG,CAAC,CAqFd"}
@@ -0,0 +1,187 @@
1
+ import crypto from 'node:crypto';
2
+ export const RECORDER_TOOLS = [
3
+ {
4
+ name: 'list_meetings',
5
+ description: 'List recorded and scheduled meetings from local SQLite database.',
6
+ inputSchema: {
7
+ type: 'object',
8
+ properties: {
9
+ status: {
10
+ type: 'string',
11
+ enum: ['scheduled', 'joining', 'recording', 'transcribing', 'completed', 'failed'],
12
+ description: 'Filter by meeting status.',
13
+ },
14
+ limit: {
15
+ type: 'number',
16
+ description: 'Maximum number of meetings to return (default 20).',
17
+ },
18
+ },
19
+ },
20
+ },
21
+ {
22
+ name: 'start_recording',
23
+ description: 'Start a local meeting recording session (screen and microphone/system audio) with 100% on-device processing.',
24
+ inputSchema: {
25
+ type: 'object',
26
+ properties: {
27
+ title: {
28
+ type: 'string',
29
+ description: 'Title of the meeting or recording session.',
30
+ },
31
+ },
32
+ required: ['title'],
33
+ },
34
+ },
35
+ {
36
+ name: 'start_local_recorder',
37
+ description: 'Start a local own-machine meeting recording session (screen and microphone/system audio) with 100% on-device processing.',
38
+ inputSchema: {
39
+ type: 'object',
40
+ properties: {
41
+ title: {
42
+ type: 'string',
43
+ description: 'Title of the meeting or recording session.',
44
+ },
45
+ },
46
+ required: ['title'],
47
+ },
48
+ },
49
+ {
50
+ name: 'stop_recording',
51
+ description: 'Stop the active meeting recording session and trigger audio extraction.',
52
+ inputSchema: {
53
+ type: 'object',
54
+ properties: {
55
+ meeting_id: {
56
+ type: 'string',
57
+ description: 'UUID of the meeting session to stop.',
58
+ },
59
+ },
60
+ required: ['meeting_id'],
61
+ },
62
+ },
63
+ {
64
+ name: 'stop_local_recorder',
65
+ description: 'Stop the active meeting recording session and trigger audio extraction.',
66
+ inputSchema: {
67
+ type: 'object',
68
+ properties: {
69
+ meeting_id: {
70
+ type: 'string',
71
+ description: 'UUID of the meeting session to stop.',
72
+ },
73
+ },
74
+ required: ['meeting_id'],
75
+ },
76
+ },
77
+ {
78
+ name: 'schedule_recording',
79
+ description: 'Register a scheduled meeting recording slot with a specified title and planned start time.',
80
+ inputSchema: {
81
+ type: 'object',
82
+ properties: {
83
+ title: {
84
+ type: 'string',
85
+ description: 'Title for the scheduled call.',
86
+ },
87
+ start_time: {
88
+ type: 'string',
89
+ description: 'ISO-8601 datetime string for scheduled start time.',
90
+ },
91
+ platform: {
92
+ type: 'string',
93
+ enum: ['local_recording', 'google_meet', 'zoom', 'microsoft_teams', 'other'],
94
+ default: 'local_recording',
95
+ },
96
+ url: {
97
+ type: 'string',
98
+ description: 'Optional meeting URL.',
99
+ },
100
+ },
101
+ required: ['title', 'start_time'],
102
+ },
103
+ },
104
+ ];
105
+ export async function handleRecorderTool(client, name, args) {
106
+ switch (name) {
107
+ case 'list_meetings': {
108
+ const meetings = await client.listMeetings({
109
+ status: args?.status ? args.status : undefined,
110
+ limit: args?.limit ? Number(args.limit) : 20,
111
+ });
112
+ return {
113
+ count: meetings.length,
114
+ meetings: meetings.map((m) => ({
115
+ id: m.id,
116
+ title: m.title,
117
+ platform: m.platform,
118
+ status: m.status,
119
+ start_time: m.start_time,
120
+ duration_seconds: m.duration_seconds,
121
+ })),
122
+ };
123
+ }
124
+ case 'start_recording':
125
+ case 'start_local_recorder': {
126
+ const meetingId = crypto.randomUUID();
127
+ const now = new Date().toISOString();
128
+ const newMeeting = {
129
+ id: meetingId,
130
+ title: String(args?.title ?? 'Untitled Recording'),
131
+ platform: 'local_recording',
132
+ status: 'recording',
133
+ start_time: now,
134
+ duration_seconds: 0,
135
+ created_at: now,
136
+ updated_at: now,
137
+ };
138
+ await client.insertMeeting(newMeeting);
139
+ return {
140
+ ok: true,
141
+ meeting_id: meetingId,
142
+ title: newMeeting.title,
143
+ status: 'recording',
144
+ message: 'Started local meeting recording.',
145
+ };
146
+ }
147
+ case 'stop_recording':
148
+ case 'stop_local_recorder': {
149
+ const meetingId = String(args?.meeting_id ?? '');
150
+ await client.updateMeetingStatus(meetingId, 'completed', {
151
+ end_time: new Date().toISOString(),
152
+ });
153
+ return {
154
+ ok: true,
155
+ meeting_id: meetingId,
156
+ status: 'completed',
157
+ message: 'Recording stopped.',
158
+ };
159
+ }
160
+ case 'schedule_recording': {
161
+ const meetingId = crypto.randomUUID();
162
+ const now = new Date().toISOString();
163
+ const scheduled = {
164
+ id: meetingId,
165
+ title: String(args?.title ?? 'Scheduled Meeting'),
166
+ platform: (args?.platform ?? 'local_recording'),
167
+ url: typeof args?.url === 'string' && args.url.trim() ? args.url.trim() : undefined,
168
+ status: 'scheduled',
169
+ start_time: String(args?.start_time ?? now),
170
+ duration_seconds: 0,
171
+ created_at: now,
172
+ updated_at: now,
173
+ };
174
+ await client.insertMeeting(scheduled);
175
+ return {
176
+ ok: true,
177
+ meeting_id: meetingId,
178
+ title: scheduled.title,
179
+ status: 'scheduled',
180
+ start_time: scheduled.start_time,
181
+ };
182
+ }
183
+ default:
184
+ throw new Error(`Unknown recorder tool: ${name}`);
185
+ }
186
+ }
187
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../../src/tools/recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=recorder.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.test.d.ts","sourceRoot":"","sources":["../../src/tools/recorder.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,94 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { MeetingsDbClient } from '@ikenga/meetings-contract';
4
+ import { handleRecorderTool, RECORDER_TOOLS } from './recorder.js';
5
+ import { InMemorySqlExecutor } from '../sqlite.js';
6
+ class MockRecorderExecutor {
7
+ inserted = [];
8
+ async query(sql) {
9
+ if (sql.includes('SELECT * FROM meetings')) {
10
+ return [
11
+ {
12
+ id: '550e8400-e29b-41d4-a716-446655440000',
13
+ title: 'test meeting 1',
14
+ platform: 'local_recording',
15
+ status: 'completed',
16
+ start_time: '2026-08-31T11:00:00Z',
17
+ duration_seconds: 1800,
18
+ created_at: '2026-08-31T10:55:00Z',
19
+ updated_at: '2026-08-31T11:30:00Z',
20
+ },
21
+ ];
22
+ }
23
+ return [];
24
+ }
25
+ async exec(sql, params = []) {
26
+ this.inserted.push({ sql, params });
27
+ }
28
+ }
29
+ describe('MCP Meetings Recorder Tools', () => {
30
+ it('exposes list_meetings, start_recording, start_local_recorder, stop_recording, stop_local_recorder, schedule_recording', () => {
31
+ const toolNames = RECORDER_TOOLS.map((t) => t.name);
32
+ assert.ok(toolNames.includes('list_meetings'));
33
+ assert.ok(toolNames.includes('start_recording'));
34
+ assert.ok(toolNames.includes('start_local_recorder'));
35
+ assert.ok(toolNames.includes('stop_recording'));
36
+ assert.ok(toolNames.includes('stop_local_recorder'));
37
+ assert.ok(toolNames.includes('schedule_recording'));
38
+ });
39
+ it('lists meetings from database', async () => {
40
+ const mock = new MockRecorderExecutor();
41
+ const client = new MeetingsDbClient(mock);
42
+ const res = await handleRecorderTool(client, 'list_meetings', {});
43
+ assert.equal(res.count, 1);
44
+ assert.equal(res.meetings[0]?.title, 'test meeting 1');
45
+ });
46
+ it('starts and stops local recorder sessions via start_local_recorder & stop_local_recorder', async () => {
47
+ const mock = new MockRecorderExecutor();
48
+ const client = new MeetingsDbClient(mock);
49
+ const startRes = await handleRecorderTool(client, 'start_local_recorder', {
50
+ title: 'test recording session',
51
+ });
52
+ assert.equal(startRes.ok, true);
53
+ assert.equal(startRes.status, 'recording');
54
+ assert.ok(startRes.meeting_id);
55
+ const stopRes = await handleRecorderTool(client, 'stop_local_recorder', {
56
+ meeting_id: startRes.meeting_id,
57
+ });
58
+ assert.equal(stopRes.ok, true);
59
+ assert.equal(stopRes.status, 'completed');
60
+ });
61
+ it('starts and stops recorder sessions via start_recording & stop_recording aliases', async () => {
62
+ const mock = new MockRecorderExecutor();
63
+ const client = new MeetingsDbClient(mock);
64
+ const startRes = await handleRecorderTool(client, 'start_recording', {
65
+ title: 'test call',
66
+ });
67
+ assert.equal(startRes.ok, true);
68
+ assert.equal(startRes.status, 'recording');
69
+ assert.ok(startRes.meeting_id);
70
+ const stopRes = await handleRecorderTool(client, 'stop_recording', {
71
+ meeting_id: startRes.meeting_id,
72
+ });
73
+ assert.equal(stopRes.ok, true);
74
+ assert.equal(stopRes.status, 'completed');
75
+ });
76
+ it('schedules a future recording slot', async () => {
77
+ const mock = new MockRecorderExecutor();
78
+ const client = new MeetingsDbClient(mock);
79
+ const schedRes = await handleRecorderTool(client, 'schedule_recording', {
80
+ title: 'test scheduled meeting',
81
+ start_time: '2026-09-01T15:00:00Z',
82
+ platform: 'google_meet',
83
+ url: 'https://meet.google.com/xyz-test',
84
+ });
85
+ assert.equal(schedRes.ok, true);
86
+ assert.equal(schedRes.status, 'scheduled');
87
+ assert.equal(schedRes.title, 'test scheduled meeting');
88
+ });
89
+ it('throws error for unknown recorder tool', async () => {
90
+ const client = new MeetingsDbClient(new InMemorySqlExecutor());
91
+ await assert.rejects(async () => handleRecorderTool(client, 'unknown_recorder_tool', {}), /Unknown recorder tool/);
92
+ });
93
+ });
94
+ //# sourceMappingURL=recorder.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.test.js","sourceRoot":"","sources":["../../src/tools/recorder.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAe,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,oBAAoB;IACjB,QAAQ,GAAU,EAAE,CAAC;IAC5B,KAAK,CAAC,KAAK,CAAc,GAAW;QAClC,IAAI,GAAG,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;YAC3C,OAAO;gBACL;oBACE,EAAE,EAAE,sCAAsC;oBAC1C,KAAK,EAAE,gBAAgB;oBACvB,QAAQ,EAAE,iBAAiB;oBAC3B,MAAM,EAAE,WAAW;oBACnB,UAAU,EAAE,sBAAsB;oBAClC,gBAAgB,EAAE,IAAI;oBACtB,UAAU,EAAE,sBAAsB;oBAClC,UAAU,EAAE,sBAAsB;iBACnC;aACK,CAAC;QACX,CAAC;QACD,OAAO,EAAS,CAAC;IACnB,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,GAAW,EAAE,SAAoB,EAAE;QAC5C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;CACF;AAED,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,uHAAuH,EAAE,GAAG,EAAE;QAC/H,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,IAAI,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,MAAM,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yFAAyF,EAAE,KAAK,IAAI,EAAE;QACvG,MAAM,IAAI,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE1C,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,MAAM,EAAE,sBAAsB,EAAE;YACxE,KAAK,EAAE,wBAAwB;SAChC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAE/B,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,MAAM,EAAE,qBAAqB,EAAE;YACtE,UAAU,EAAE,QAAQ,CAAC,UAAU;SAChC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;QAC/F,MAAM,IAAI,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE1C,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,EAAE;YACnE,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAE/B,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,EAAE;YACjE,UAAU,EAAE,QAAQ,CAAC,UAAU;SAChC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,IAAI,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAE1C,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,MAAM,EAAE,oBAAoB,EAAE;YACtE,KAAK,EAAE,wBAAwB;YAC/B,UAAU,EAAE,sBAAsB;YAClC,QAAQ,EAAE,aAAa;YACvB,GAAG,EAAE,kCAAkC;SACxC,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,mBAAmB,EAAE,CAAC,CAAC;QAC/D,MAAM,MAAM,CAAC,OAAO,CAClB,KAAK,IAAI,EAAE,CAAC,kBAAkB,CAAC,MAAM,EAAE,uBAAuB,EAAE,EAAE,CAAC,EACnE,uBAAuB,CACxB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { MeetingsDbClient } from '@ikenga/meetings-contract';
2
+ export declare const SEARCH_TOOLS: ({
3
+ name: string;
4
+ description: string;
5
+ inputSchema: {
6
+ type: string;
7
+ properties: {
8
+ query: {
9
+ type: string;
10
+ description: string;
11
+ };
12
+ meeting_id: {
13
+ type: string;
14
+ description: string;
15
+ };
16
+ };
17
+ required: string[];
18
+ };
19
+ } | {
20
+ name: string;
21
+ description: string;
22
+ inputSchema: {
23
+ type: string;
24
+ properties: {
25
+ meeting_id: {
26
+ type: string;
27
+ description: string;
28
+ };
29
+ query?: undefined;
30
+ };
31
+ required: string[];
32
+ };
33
+ })[];
34
+ export declare function handleSearchTool(client: MeetingsDbClient, name: string, args: any): Promise<any>;
35
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAkDxB,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,GAAG,GACR,OAAO,CAAC,GAAG,CAAC,CAkEd"}
@@ -0,0 +1,112 @@
1
+ export const SEARCH_TOOLS = [
2
+ {
3
+ name: 'search_transcripts',
4
+ description: 'Search across meeting transcripts for spoken keywords, split negotiations, artist deals, or dates. Returns matching transcript chunks with timestamps and speaker names.',
5
+ inputSchema: {
6
+ type: 'object',
7
+ properties: {
8
+ query: {
9
+ type: 'string',
10
+ description: 'Search keyword or phrase to match in transcripts.',
11
+ },
12
+ meeting_id: {
13
+ type: 'string',
14
+ description: 'Optional meeting UUID to scope the search to a single call.',
15
+ },
16
+ },
17
+ required: ['query'],
18
+ },
19
+ },
20
+ {
21
+ name: 'get_meeting_transcript',
22
+ description: 'Retrieve the full timestamped transcript segments and speaker attributions for a given meeting ID.',
23
+ inputSchema: {
24
+ type: 'object',
25
+ properties: {
26
+ meeting_id: {
27
+ type: 'string',
28
+ description: 'UUID of the meeting to fetch transcript for.',
29
+ },
30
+ },
31
+ required: ['meeting_id'],
32
+ },
33
+ },
34
+ {
35
+ name: 'get_meeting_summary',
36
+ description: 'Retrieve the executive summary, key decisions, and extracted topics for a given meeting ID.',
37
+ inputSchema: {
38
+ type: 'object',
39
+ properties: {
40
+ meeting_id: {
41
+ type: 'string',
42
+ description: 'UUID of the meeting to fetch summary for.',
43
+ },
44
+ },
45
+ required: ['meeting_id'],
46
+ },
47
+ },
48
+ ];
49
+ export async function handleSearchTool(client, name, args) {
50
+ switch (name) {
51
+ case 'search_transcripts': {
52
+ const query = String(args?.query ?? '');
53
+ const meetingId = typeof args?.meeting_id === 'string' && args.meeting_id.trim()
54
+ ? args.meeting_id.trim()
55
+ : undefined;
56
+ const results = await client.searchTranscripts(query, meetingId);
57
+ return {
58
+ query,
59
+ count: results.length,
60
+ segments: results.map((r) => ({
61
+ meeting_id: r.meeting_id,
62
+ speaker: r.speaker_name ?? 'Unknown',
63
+ start_ms: r.start_ms,
64
+ end_ms: r.end_ms,
65
+ text: r.text,
66
+ confidence: r.confidence,
67
+ })),
68
+ };
69
+ }
70
+ case 'get_meeting_transcript': {
71
+ const meetingId = String(args?.meeting_id ?? '');
72
+ const segments = await client.listTranscriptSegments(meetingId);
73
+ const speakers = await client.listSpeakers(meetingId);
74
+ return {
75
+ meeting_id: meetingId,
76
+ speakers: speakers.map((s) => ({
77
+ id: s.id,
78
+ name: s.name,
79
+ source: s.speaker_source,
80
+ })),
81
+ segment_count: segments.length,
82
+ segments: segments.map((s) => ({
83
+ speaker: s.speaker_name ?? 'Speaker',
84
+ start_ms: s.start_ms,
85
+ end_ms: s.end_ms,
86
+ text: s.text,
87
+ })),
88
+ };
89
+ }
90
+ case 'get_meeting_summary': {
91
+ const meetingId = String(args?.meeting_id ?? '');
92
+ const summary = await client.getSummary(meetingId);
93
+ if (!summary) {
94
+ return {
95
+ found: false,
96
+ meeting_id: meetingId,
97
+ message: 'No summary generated yet for this meeting.',
98
+ };
99
+ }
100
+ return {
101
+ found: true,
102
+ meeting_id: summary.meeting_id,
103
+ executive_summary: summary.executive_summary,
104
+ key_decisions: summary.key_decisions,
105
+ topics: summary.topics_json,
106
+ };
107
+ }
108
+ default:
109
+ throw new Error(`Unknown search tool: ${name}`);
110
+ }
111
+ }
112
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,0KAA0K;QAC5K,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,mDAAmD;iBACjE;gBACD,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,6DAA6D;iBAC3E;aACF;YACD,QAAQ,EAAE,CAAC,OAAO,CAAC;SACpB;KACF;IACD;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EACT,oGAAoG;QACtG,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8CAA8C;iBAC5D;aACF;YACD,QAAQ,EAAE,CAAC,YAAY,CAAC;SACzB;KACF;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EACT,6FAA6F;QAC/F,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,2CAA2C;iBACzD;aACF;YACD,QAAQ,EAAE,CAAC,YAAY,CAAC;SACzB;KACF;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAwB,EACxB,IAAY,EACZ,IAAS;IAET,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,oBAAoB,CAAC,CAAC,CAAC;YAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACxC,MAAM,SAAS,GACb,OAAO,IAAI,EAAE,UAAU,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;gBAC5D,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;gBACxB,CAAC,CAAC,SAAS,CAAC;YAChB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YACjE,OAAO;gBACL,KAAK;gBACL,KAAK,EAAE,OAAO,CAAC,MAAM;gBACrB,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC5B,UAAU,EAAE,CAAC,CAAC,UAAU;oBACxB,OAAO,EAAE,CAAC,CAAC,YAAY,IAAI,SAAS;oBACpC,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,UAAU,EAAE,CAAC,CAAC,UAAU;iBACzB,CAAC,CAAC;aACJ,CAAC;QACJ,CAAC;QAED,KAAK,wBAAwB,CAAC,CAAC,CAAC;YAC9B,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;YACjD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YACtD,OAAO;gBACL,UAAU,EAAE,SAAS;gBACrB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC7B,EAAE,EAAE,CAAC,CAAC,EAAE;oBACR,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,MAAM,EAAE,CAAC,CAAC,cAAc;iBACzB,CAAC,CAAC;gBACH,aAAa,EAAE,QAAQ,CAAC,MAAM;gBAC9B,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC7B,OAAO,EAAE,CAAC,CAAC,YAAY,IAAI,SAAS;oBACpC,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,IAAI,EAAE,CAAC,CAAC,IAAI;iBACb,CAAC,CAAC;aACJ,CAAC;QACJ,CAAC;QAED,KAAK,qBAAqB,CAAC,CAAC,CAAC;YAC3B,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YACnD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO;oBACL,KAAK,EAAE,KAAK;oBACZ,UAAU,EAAE,SAAS;oBACrB,OAAO,EAAE,4CAA4C;iBACtD,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,KAAK,EAAE,IAAI;gBACX,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;gBAC5C,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,MAAM,EAAE,OAAO,CAAC,WAAW;aAC5B,CAAC;QACJ,CAAC;QAED;YACE,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=search.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.test.d.ts","sourceRoot":"","sources":["../../src/tools/search.test.ts"],"names":[],"mappings":""}