minutes-mcp 0.16.0 → 0.16.2
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.
- package/dist/index.d.ts +36 -0
- package/dist/index.js +63 -23
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,41 @@ export type KnowledgeConfigStatus = {
|
|
|
36
36
|
adapter: string;
|
|
37
37
|
engine: string;
|
|
38
38
|
};
|
|
39
|
+
type MeetingLike = {
|
|
40
|
+
path: string;
|
|
41
|
+
frontmatter: {
|
|
42
|
+
date?: string;
|
|
43
|
+
title?: string;
|
|
44
|
+
type?: string;
|
|
45
|
+
duration?: string;
|
|
46
|
+
recording_health?: unknown;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
export declare function meetingListItem(meeting: MeetingLike): {
|
|
50
|
+
date: string | undefined;
|
|
51
|
+
title: string | undefined;
|
|
52
|
+
content_type: string | undefined;
|
|
53
|
+
path: string;
|
|
54
|
+
duration: string | undefined;
|
|
55
|
+
};
|
|
56
|
+
export declare function meetingSearchItem(meeting: MeetingLike): {
|
|
57
|
+
date: string | undefined;
|
|
58
|
+
title: string | undefined;
|
|
59
|
+
content_type: string | undefined;
|
|
60
|
+
path: string;
|
|
61
|
+
};
|
|
62
|
+
export declare function meetingDetailPayload(input: {
|
|
63
|
+
path: string;
|
|
64
|
+
speaker_map?: unknown;
|
|
65
|
+
recording_health?: unknown;
|
|
66
|
+
overlay_applied?: boolean;
|
|
67
|
+
}): {
|
|
68
|
+
path: string;
|
|
69
|
+
view: "detail";
|
|
70
|
+
speaker_map?: unknown;
|
|
71
|
+
recording_health?: unknown;
|
|
72
|
+
overlay_applied?: boolean;
|
|
73
|
+
};
|
|
39
74
|
export declare function shouldRunMainEntry(argv1: string | null | undefined, moduleFilename: string): boolean;
|
|
40
75
|
export declare function parseKnowledgeConfig(configContent: string): KnowledgeConfigStatus | null;
|
|
41
76
|
export declare const LIVE_EVENTS_RESOURCE_URI = "minutes://events/live";
|
|
@@ -72,3 +107,4 @@ export type LiveEventsSubscriptionController = {
|
|
|
72
107
|
subscriptionCount: () => number;
|
|
73
108
|
};
|
|
74
109
|
export declare function registerLiveEventsSubscriptionHandlers(mcpServer: McpServer, options?: LiveEventsSubscriptionOptions): LiveEventsSubscriptionController;
|
|
110
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -122,6 +122,39 @@ function handleDemoSetup() {
|
|
|
122
122
|
const UI_RESOURCE_URI = "ui://minutes/dashboard";
|
|
123
123
|
const MCP_TOOLS_DOCS_BASE_URL = "https://useminutes.app/docs/mcp/tools";
|
|
124
124
|
export const MEETING_INSIGHT_KINDS = ["decision", "commitment", "question"];
|
|
125
|
+
export function meetingListItem(meeting) {
|
|
126
|
+
return {
|
|
127
|
+
date: meeting.frontmatter.date,
|
|
128
|
+
title: meeting.frontmatter.title,
|
|
129
|
+
content_type: meeting.frontmatter.type,
|
|
130
|
+
path: meeting.path,
|
|
131
|
+
duration: meeting.frontmatter.duration,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
export function meetingSearchItem(meeting) {
|
|
135
|
+
return {
|
|
136
|
+
date: meeting.frontmatter.date,
|
|
137
|
+
title: meeting.frontmatter.title,
|
|
138
|
+
content_type: meeting.frontmatter.type,
|
|
139
|
+
path: meeting.path,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export function meetingDetailPayload(input) {
|
|
143
|
+
const payload = {
|
|
144
|
+
path: input.path,
|
|
145
|
+
view: "detail",
|
|
146
|
+
};
|
|
147
|
+
if (input.speaker_map !== undefined) {
|
|
148
|
+
payload.speaker_map = input.speaker_map;
|
|
149
|
+
}
|
|
150
|
+
if (input.recording_health !== undefined) {
|
|
151
|
+
payload.recording_health = input.recording_health;
|
|
152
|
+
}
|
|
153
|
+
if (input.overlay_applied !== undefined) {
|
|
154
|
+
payload.overlay_applied = input.overlay_applied;
|
|
155
|
+
}
|
|
156
|
+
return payload;
|
|
157
|
+
}
|
|
125
158
|
function toolDocsUrl(name) {
|
|
126
159
|
return `${MCP_TOOLS_DOCS_BASE_URL}#tool-${name}`;
|
|
127
160
|
}
|
|
@@ -315,7 +348,7 @@ const LIVE_EVENTS_SUPPORTED = hasFeature(CLI_CAPABILITIES, "events_since_seq");
|
|
|
315
348
|
// `./version.ts` (see issue #183). Hosted `.mcpb` bundles will run
|
|
316
349
|
// against CLIs with different minor/patch numbers within the same
|
|
317
350
|
// major; that is explicitly supported.
|
|
318
|
-
const MCP_SERVER_VERSION = "0.16.
|
|
351
|
+
const MCP_SERVER_VERSION = "0.16.2";
|
|
319
352
|
export function parseKnowledgeConfig(configContent) {
|
|
320
353
|
const knowledgeMatch = configContent.match(/\[knowledge\][\s\S]*?(?=\n\[|$)/);
|
|
321
354
|
if (!knowledgeMatch) {
|
|
@@ -1009,7 +1042,12 @@ registerTool("start_recording", "Start recording audio with call-aware preflight
|
|
|
1009
1042
|
.default(false)
|
|
1010
1043
|
.describe("Allow a mic-only capture to continue even if Minutes detects a call but no system-audio route is configured."),
|
|
1011
1044
|
language: z.string().optional().describe("Transcription language code (e.g. 'en', 'ur', 'es', 'zh'). Overrides config.toml setting."),
|
|
1012
|
-
|
|
1045
|
+
skip_audio_probe_reason: z
|
|
1046
|
+
.string()
|
|
1047
|
+
.min(1)
|
|
1048
|
+
.optional()
|
|
1049
|
+
.describe("Per-call reason to skip the system-audio readiness probe. This is not persisted and is written into recording_health."),
|
|
1050
|
+
}, { title: "Start Recording", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }, async ({ title, mode, intent, allow_degraded, language, skip_audio_probe_reason }) => {
|
|
1013
1051
|
if (!(await isCliAvailable())) {
|
|
1014
1052
|
return { content: [{ type: "text", text: CLI_INSTALL_MSG }] };
|
|
1015
1053
|
}
|
|
@@ -1035,6 +1073,16 @@ registerTool("start_recording", "Start recording audio with call-aware preflight
|
|
|
1035
1073
|
// For non-extension mode, still delegate call recordings to the desktop app
|
|
1036
1074
|
// (it has system audio capture that the CLI can't do).
|
|
1037
1075
|
if (isExtensionRuntime || preflight.intent === "call") {
|
|
1076
|
+
if (skip_audio_probe_reason) {
|
|
1077
|
+
return {
|
|
1078
|
+
content: [{
|
|
1079
|
+
type: "text",
|
|
1080
|
+
text: "skip_audio_probe_reason cannot be honored for desktop-delegated recordings yet. Start the recording from the CLI with --skip-audio-probe \"<reason>\" if you intentionally want to bypass the system-audio readiness probe.",
|
|
1081
|
+
}],
|
|
1082
|
+
structuredContent: { preflight },
|
|
1083
|
+
isError: true,
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1038
1086
|
let response;
|
|
1039
1087
|
try {
|
|
1040
1088
|
response = await delegateRecordingToDesktop({
|
|
@@ -1129,6 +1177,8 @@ registerTool("start_recording", "Start recording audio with call-aware preflight
|
|
|
1129
1177
|
args.push("--intent", intent);
|
|
1130
1178
|
if (allow_degraded)
|
|
1131
1179
|
args.push("--allow-degraded");
|
|
1180
|
+
if (skip_audio_probe_reason)
|
|
1181
|
+
args.push("--skip-audio-probe", skip_audio_probe_reason);
|
|
1132
1182
|
if (language)
|
|
1133
1183
|
args.push("--language", language);
|
|
1134
1184
|
const child = spawn(MINUTES_BIN, args, {
|
|
@@ -1310,13 +1360,7 @@ registerDocsAppTool(server, "list_meetings", {
|
|
|
1310
1360
|
const text = filtered
|
|
1311
1361
|
.map((m) => `${m.frontmatter.date} — ${m.frontmatter.title} [${m.frontmatter.type}]\n ${m.path}`)
|
|
1312
1362
|
.join("\n\n");
|
|
1313
|
-
const meetingsJson = filtered.map(
|
|
1314
|
-
date: m.frontmatter.date,
|
|
1315
|
-
title: m.frontmatter.title,
|
|
1316
|
-
content_type: m.frontmatter.type,
|
|
1317
|
-
path: m.path,
|
|
1318
|
-
duration: m.frontmatter.duration,
|
|
1319
|
-
}));
|
|
1363
|
+
const meetingsJson = filtered.map(meetingListItem);
|
|
1320
1364
|
return {
|
|
1321
1365
|
content: [{ type: "text", text }],
|
|
1322
1366
|
structuredContent: { meetings: meetingsJson, actions: openActions.map((a) => a.item), view: "dashboard" },
|
|
@@ -1399,12 +1443,7 @@ registerDocsAppTool(server, "search_meetings", {
|
|
|
1399
1443
|
return {
|
|
1400
1444
|
content: [{ type: "text", text }],
|
|
1401
1445
|
structuredContent: {
|
|
1402
|
-
results: filtered.map(
|
|
1403
|
-
date: m.frontmatter.date,
|
|
1404
|
-
title: m.frontmatter.title,
|
|
1405
|
-
content_type: m.frontmatter.type,
|
|
1406
|
-
path: m.path,
|
|
1407
|
-
})),
|
|
1446
|
+
results: filtered.map(meetingSearchItem),
|
|
1408
1447
|
view: "search",
|
|
1409
1448
|
},
|
|
1410
1449
|
_meta: { ui: { resourceUri: UI_RESOURCE_URI }, view: "search" },
|
|
@@ -1821,19 +1860,23 @@ registerDocsAppTool(server, "get_meeting", {
|
|
|
1821
1860
|
// disk is never mutated — the CLI just layers ~/.minutes/overlays.db on
|
|
1822
1861
|
// top of the parsed frontmatter. If the CLI is unavailable or the call
|
|
1823
1862
|
// fails, degrade gracefully to raw content.
|
|
1824
|
-
|
|
1863
|
+
const rawParsed = reader.parseFrontmatter(rawContent, resolved);
|
|
1864
|
+
let structured = meetingDetailPayload({
|
|
1865
|
+
path: resolved,
|
|
1866
|
+
recording_health: rawParsed?.frontmatter?.recording_health,
|
|
1867
|
+
});
|
|
1825
1868
|
if (await isCliAvailable()) {
|
|
1826
1869
|
try {
|
|
1827
1870
|
const { stdout } = await runMinutes(["get", resolved, "--json"], 10000);
|
|
1828
1871
|
const parsed = parseJsonOutput(stdout);
|
|
1829
1872
|
if (parsed && typeof parsed === "object" && !parsed.raw) {
|
|
1830
1873
|
const speakerMap = parsed.frontmatter?.speaker_map;
|
|
1831
|
-
structured = {
|
|
1874
|
+
structured = meetingDetailPayload({
|
|
1832
1875
|
path: resolved,
|
|
1833
|
-
view: "detail",
|
|
1834
1876
|
speaker_map: Array.isArray(speakerMap) ? speakerMap : [],
|
|
1877
|
+
recording_health: parsed.frontmatter?.recording_health,
|
|
1835
1878
|
overlay_applied: Boolean(parsed.overlay_applied),
|
|
1836
|
-
};
|
|
1879
|
+
});
|
|
1837
1880
|
}
|
|
1838
1881
|
}
|
|
1839
1882
|
catch {
|
|
@@ -2116,10 +2159,7 @@ registerDocsAppTool(server, "relationship_map", {
|
|
|
2116
2159
|
server.resource("recent_meetings", "minutes://meetings/recent", { description: "List of recent meetings and memos" }, async () => {
|
|
2117
2160
|
if (!(await isCliAvailable())) {
|
|
2118
2161
|
const meetings = await reader.listMeetings(MEETINGS_DIR, 20);
|
|
2119
|
-
const json = JSON.stringify(meetings.map(
|
|
2120
|
-
date: m.frontmatter.date, title: m.frontmatter.title,
|
|
2121
|
-
content_type: m.frontmatter.type, path: m.path, duration: m.frontmatter.duration,
|
|
2122
|
-
})));
|
|
2162
|
+
const json = JSON.stringify(meetings.map(meetingListItem));
|
|
2123
2163
|
return { contents: [{ uri: "minutes://meetings/recent", mimeType: "application/json", text: json }] };
|
|
2124
2164
|
}
|
|
2125
2165
|
const { stdout } = await runMinutes(["list", "--limit", "20"]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minutes-mcp",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.2",
|
|
4
4
|
"description": "MCP server for minutes — conversation memory for AI assistants. Works with Claude Desktop, Mistral Vibe, Cursor, Windsurf, and any MCP client.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@modelcontextprotocol/ext-apps": "^1.6.0",
|
|
44
44
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
45
|
-
"minutes-sdk": "^0.16.
|
|
45
|
+
"minutes-sdk": "^0.16.2",
|
|
46
46
|
"yaml": "^2.8.3",
|
|
47
47
|
"zod": "^3.25 || ^4.0"
|
|
48
48
|
},
|