@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,116 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { MeetingsDbClient } from '@ikenga/meetings-contract';
4
+ import { handleSearchTool, SEARCH_TOOLS } from './search.js';
5
+ import { InMemorySqlExecutor } from '../sqlite.js';
6
+ class MockSearchExecutor {
7
+ async query(sql, params = []) {
8
+ if (sql.includes('SELECT * FROM meeting_transcripts WHERE text LIKE ?')) {
9
+ return [
10
+ {
11
+ id: '770e8400-e29b-41d4-a716-446655440002',
12
+ meeting_id: '550e8400-e29b-41d4-a716-446655440000',
13
+ speaker_name: 'Speaker 1',
14
+ speaker_source: 'dom_cue',
15
+ start_ms: 1000,
16
+ end_ms: 3000,
17
+ text: 'lorem ipsum test search keyword target text',
18
+ confidence: 0.98,
19
+ },
20
+ ];
21
+ }
22
+ if (sql.includes('SELECT * FROM meeting_transcripts WHERE meeting_id = ?')) {
23
+ return [
24
+ {
25
+ id: '770e8400-e29b-41d4-a716-446655440002',
26
+ meeting_id: '550e8400-e29b-41d4-a716-446655440000',
27
+ speaker_name: 'Speaker 1',
28
+ speaker_source: 'dom_cue',
29
+ start_ms: 1000,
30
+ end_ms: 3000,
31
+ text: 'lorem ipsum test search keyword target text',
32
+ confidence: 0.98,
33
+ },
34
+ ];
35
+ }
36
+ if (sql.includes('SELECT * FROM meeting_speakers WHERE meeting_id = ?')) {
37
+ return [
38
+ {
39
+ id: '660e8400-e29b-41d4-a716-446655440001',
40
+ meeting_id: '550e8400-e29b-41d4-a716-446655440000',
41
+ name: 'Speaker 1',
42
+ speaker_source: 'dom_cue',
43
+ },
44
+ ];
45
+ }
46
+ if (sql.includes('SELECT * FROM meeting_summaries WHERE meeting_id = ?')) {
47
+ const id = String(params[0]);
48
+ if (id === '550e8400-e29b-41d4-a716-446655440000') {
49
+ return [
50
+ {
51
+ id: '990e8400-e29b-41d4-a716-446655440004',
52
+ meeting_id: '550e8400-e29b-41d4-a716-446655440000',
53
+ executive_summary: 'test meeting summary text',
54
+ key_decisions_json: '["test decision 1"]',
55
+ topics_json: '["topic 1", "topic 2"]',
56
+ created_at: '2026-08-31T10:00:00.000Z',
57
+ },
58
+ ];
59
+ }
60
+ return [];
61
+ }
62
+ return [];
63
+ }
64
+ async exec() { }
65
+ }
66
+ describe('MCP Meetings Search Tools', () => {
67
+ it('exposes correct search tool definitions', () => {
68
+ const toolNames = SEARCH_TOOLS.map((t) => t.name);
69
+ assert.deepEqual(toolNames, [
70
+ 'search_transcripts',
71
+ 'get_meeting_transcript',
72
+ 'get_meeting_summary',
73
+ ]);
74
+ });
75
+ it('searches transcripts across meetings', async () => {
76
+ const client = new MeetingsDbClient(new MockSearchExecutor());
77
+ const res = await handleSearchTool(client, 'search_transcripts', { query: 'keyword target' });
78
+ assert.equal(res.count, 1);
79
+ assert.equal(res.segments[0]?.speaker, 'Speaker 1');
80
+ assert.ok(res.segments[0]?.text.includes('keyword target'));
81
+ });
82
+ it('retrieves full meeting transcript segments and speaker roster', async () => {
83
+ const client = new MeetingsDbClient(new MockSearchExecutor());
84
+ const res = await handleSearchTool(client, 'get_meeting_transcript', {
85
+ meeting_id: '550e8400-e29b-41d4-a716-446655440000',
86
+ });
87
+ assert.equal(res.meeting_id, '550e8400-e29b-41d4-a716-446655440000');
88
+ assert.equal(res.segment_count, 1);
89
+ assert.equal(res.speakers.length, 1);
90
+ assert.equal(res.speakers[0]?.name, 'Speaker 1');
91
+ assert.equal(res.segments[0]?.speaker, 'Speaker 1');
92
+ });
93
+ it('retrieves meeting summary when found', async () => {
94
+ const client = new MeetingsDbClient(new MockSearchExecutor());
95
+ const res = await handleSearchTool(client, 'get_meeting_summary', {
96
+ meeting_id: '550e8400-e29b-41d4-a716-446655440000',
97
+ });
98
+ assert.equal(res.found, true);
99
+ assert.equal(res.executive_summary, 'test meeting summary text');
100
+ assert.equal(res.key_decisions.length, 1);
101
+ assert.deepEqual(res.topics, ['topic 1', 'topic 2']);
102
+ });
103
+ it('returns graceful not-found message when summary does not exist', async () => {
104
+ const client = new MeetingsDbClient(new MockSearchExecutor());
105
+ const res = await handleSearchTool(client, 'get_meeting_summary', {
106
+ meeting_id: '00000000-0000-0000-0000-000000000000',
107
+ });
108
+ assert.equal(res.found, false);
109
+ assert.ok(res.message.includes('No summary generated yet'));
110
+ });
111
+ it('throws error for unknown search tool', async () => {
112
+ const client = new MeetingsDbClient(new InMemorySqlExecutor());
113
+ await assert.rejects(async () => handleSearchTool(client, 'unknown_tool', {}), /Unknown search tool/);
114
+ });
115
+ });
116
+ //# sourceMappingURL=search.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.test.js","sourceRoot":"","sources":["../../src/tools/search.test.ts"],"names":[],"mappings":"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"}
package/manifest.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "id": "com.ikenga.mcp-meetings",
3
+ "name": "Meetings MCP",
4
+ "version": "0.1.0",
5
+ "ikenga_api": "3",
6
+ "kind": "skill",
7
+
8
+ "author": {
9
+ "name": "Royalti, Inc.",
10
+ "key": "royalti"
11
+ },
12
+
13
+ "description": "Model Context Protocol (MCP) server for querying meeting transcripts, search, summaries, and recording controls.",
14
+
15
+ "mcp": [
16
+ {
17
+ "name": "meetings",
18
+ "command": "node",
19
+ "args": ["dist/index.js"],
20
+ "lifecycle": "long-lived"
21
+ }
22
+ ],
23
+
24
+ "capabilities": {
25
+ "sqlite": true
26
+ },
27
+
28
+ "permissions": {
29
+ "sqlite.tables": [
30
+ "meetings",
31
+ "meeting_speakers",
32
+ "meeting_transcripts",
33
+ "meeting_action_items",
34
+ "meeting_summaries"
35
+ ],
36
+ "shell.execute": ["node"],
37
+ "net": ["http://127.0.0.1:*"]
38
+ }
39
+ }
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@ikenga/mcp-meetings",
3
+ "version": "0.1.0",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/ikenga-hq/ikenga-pkgs.git",
7
+ "directory": "packages/mcp/meetings"
8
+ },
9
+ "mcpName": "dev.ikenga/mcp-meetings",
10
+ "description": "Model Context Protocol (MCP) server for querying meeting transcripts, search, summaries, and recording controls.",
11
+ "license": "Apache-2.0",
12
+ "type": "module",
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "files": [
16
+ "dist",
17
+ "manifest.json",
18
+ "README.md"
19
+ ],
20
+ "dependencies": {
21
+ "@modelcontextprotocol/sdk": "^1.23.0",
22
+ "better-sqlite3": "^13.0.3",
23
+ "@ikenga/meetings-contract": "0.1.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/better-sqlite3": "^9.6.0",
27
+ "@types/node": "^20.0.0",
28
+ "tsx": "^4.21.0",
29
+ "typescript": "^5.4.0"
30
+ },
31
+ "scripts": {
32
+ "build": "tsc -p tsconfig.json",
33
+ "dev": "tsc -p tsconfig.json --watch",
34
+ "typecheck": "tsc -p tsconfig.json --noEmit",
35
+ "clean": "rm -rf dist",
36
+ "test": "node --test --import=tsx src/tools/search.test.ts src/tools/recorder.test.ts src/integration.test.ts src/index.test.ts src/sqlite.test.ts"
37
+ }
38
+ }