@plaud-ai/mcp 0.2.0 → 0.2.2-beta.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.
@@ -16,15 +16,17 @@ function parseDate(s) {
16
16
  return d.getTime();
17
17
  }
18
18
  function registerTools(server, client) {
19
- server.tool(
19
+ server.registerTool(
20
20
  "list_files",
21
- "List Plaud recordings. Supports optional client-side filtering: `query` (case-insensitive name substring), `date_from`/`date_to` (YYYY-MM-DD, inclusive). When any filter is set, paginates up to 5 pages \xD7 100 recordings and returns all matches.",
22
21
  {
23
- page: z.number().optional().default(1).describe("Page number (ignored when filters are set)"),
24
- page_size: z.number().optional().default(20).describe("Items per page (ignored when filters are set)"),
25
- query: z.string().optional().describe("Case-insensitive substring match on recording name"),
26
- date_from: z.string().optional().describe("Start date inclusive, YYYY-MM-DD"),
27
- date_to: z.string().optional().describe("End date inclusive, YYYY-MM-DD")
22
+ description: "List Plaud recordings. Supports optional client-side filtering: `query` (case-insensitive name substring), `date_from`/`date_to` (YYYY-MM-DD, inclusive). When any filter is set, paginates up to 5 pages \xD7 100 recordings and returns all matches.",
23
+ inputSchema: {
24
+ page: z.number().optional().default(1).describe("Page number (ignored when filters are set)"),
25
+ page_size: z.number().optional().default(20).describe("Items per page (ignored when filters are set)"),
26
+ query: z.string().optional().describe("Case-insensitive substring match on recording name"),
27
+ date_from: z.string().optional().describe("Start date inclusive, YYYY-MM-DD"),
28
+ date_to: z.string().optional().describe("End date inclusive, YYYY-MM-DD")
29
+ }
28
30
  },
29
31
  async ({ page, page_size, query, date_from, date_to }) => {
30
32
  const start = Date.now();
@@ -76,10 +78,12 @@ function registerTools(server, client) {
76
78
  }
77
79
  }
78
80
  );
79
- server.tool(
81
+ server.registerTool(
80
82
  "get_file",
81
- "Get details of a specific Plaud recording by ID",
82
- { file_id: z.string().describe("The file ID to retrieve") },
83
+ {
84
+ description: "Get details of a specific Plaud recording by ID",
85
+ inputSchema: { file_id: z.string().describe("The file ID to retrieve") }
86
+ },
83
87
  async ({ file_id }) => {
84
88
  const start = Date.now();
85
89
  logger.info({ event: "tool_call", tool: "get_file", file_id });
@@ -93,10 +97,12 @@ function registerTools(server, client) {
93
97
  }
94
98
  }
95
99
  );
96
- server.tool(
100
+ server.registerTool(
97
101
  "get_note",
98
- "Fetch AI-generated notes for a Plaud recording \u2014 compact summary, action items, and key topics",
99
- { file_id: z.string().describe("The file ID to retrieve notes for") },
102
+ {
103
+ description: "Fetch AI-generated notes for a Plaud recording \u2014 compact summary, action items, and key topics",
104
+ inputSchema: { file_id: z.string().describe("The file ID to retrieve notes for") }
105
+ },
100
106
  async ({ file_id }) => {
101
107
  const start = Date.now();
102
108
  logger.info({ event: "tool_call", tool: "get_note", file_id });
@@ -110,10 +116,12 @@ function registerTools(server, client) {
110
116
  }
111
117
  }
112
118
  );
113
- server.tool(
119
+ server.registerTool(
114
120
  "get_transcript",
115
- "Fetch the full timestamped transcript with speaker attribution for a Plaud recording",
116
- { file_id: z.string().describe("The file ID to retrieve transcript for") },
121
+ {
122
+ description: "Fetch the full timestamped transcript with speaker attribution for a Plaud recording",
123
+ inputSchema: { file_id: z.string().describe("The file ID to retrieve transcript for") }
124
+ },
117
125
  async ({ file_id }) => {
118
126
  const start = Date.now();
119
127
  logger.info({ event: "tool_call", tool: "get_transcript", file_id });
@@ -127,9 +135,11 @@ function registerTools(server, client) {
127
135
  }
128
136
  }
129
137
  );
130
- server.tool(
138
+ server.registerTool(
131
139
  "get_current_user",
132
- "Get current authenticated user info",
140
+ {
141
+ description: "Get current authenticated user info"
142
+ },
133
143
  async () => {
134
144
  const start = Date.now();
135
145
  logger.info({ event: "tool_call", tool: "get_current_user" });
@@ -4,15 +4,34 @@ import {
4
4
 
5
5
  // src/install-utils.ts
6
6
  import { readFile, writeFile, mkdir } from "fs/promises";
7
+ import { existsSync } from "fs";
7
8
  import { join, dirname } from "path";
8
9
  import { homedir, platform } from "os";
9
10
  import { spawnSync } from "child_process";
10
11
  var SKILLS_MARKER_START = "<!-- plaud-skills:start -->";
11
12
  var SKILLS_MARKER_END = "<!-- plaud-skills:end -->";
13
+ function findNodeBinCommand(command) {
14
+ const commandName = platform() === "win32" ? `${command}.cmd` : command;
15
+ const found = spawnSync(platform() === "win32" ? "where" : "which", [commandName], { encoding: "utf-8" });
16
+ const firstMatch = found.status === 0 ? found.stdout.split(/\r?\n/).find((line) => line.trim())?.trim() : void 0;
17
+ if (firstMatch) return firstMatch;
18
+ const sibling = join(dirname(process.execPath), commandName);
19
+ return existsSync(sibling) ? sibling : commandName;
20
+ }
21
+ function isLocalPackageSpec(spec) {
22
+ return spec.endsWith(".tgz") || spec.startsWith(".") || spec.startsWith("/") || /^[A-Za-z]:[\\/]/.test(spec);
23
+ }
12
24
  function getMcpEntry() {
25
+ const packageSpec = process.env.PLAUD_MCP_PACKAGE_SPEC?.trim() || "@plaud-ai/mcp@latest";
26
+ if (isLocalPackageSpec(packageSpec)) {
27
+ return {
28
+ command: findNodeBinCommand("npm"),
29
+ args: ["exec", "--yes", "--package", packageSpec, "--", "plaud-mcp"]
30
+ };
31
+ }
13
32
  return {
14
- command: "npx",
15
- args: ["-y", "@plaud-ai/mcp@latest"]
33
+ command: findNodeBinCommand("npx"),
34
+ args: ["-y", packageSpec]
16
35
  };
17
36
  }
18
37
  function copyToClipboard(content) {
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-4QBEOJPX.js";
8
8
  import {
9
9
  registerTools
10
- } from "./chunk-MPCF6HMK.js";
10
+ } from "./chunk-IZKXHQM3.js";
11
11
  import "./chunk-SNSGVRCU.js";
12
12
 
13
13
  // src/index.ts
@@ -17,11 +17,13 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
17
17
  import open from "open";
18
18
  var server = new McpServer({
19
19
  name: "plaud",
20
- version: "0.2.0"
20
+ version: "0.2.2-beta.0"
21
21
  });
22
22
  var CALLBACK_PORT = 8199;
23
23
  var LOGIN_TIMEOUT_MS = 12e4;
24
- server.tool("login", "Log in, sign in, or authenticate with Plaud account via OAuth (opens browser)", async () => {
24
+ server.registerTool("login", {
25
+ description: "Log in, sign in, or authenticate with Plaud account via OAuth (opens browser)"
26
+ }, async () => {
25
27
  const client = getClient();
26
28
  const existingToken = await client.auth.getAccessToken();
27
29
  if (existingToken) {
@@ -81,10 +83,14 @@ server.tool("login", "Log in, sign in, or authenticate with Plaud account via OA
81
83
  }, LOGIN_TIMEOUT_MS);
82
84
  httpServer.listen(CALLBACK_PORT, () => {
83
85
  open(url).catch(() => {
84
- cleanup();
85
86
  resolve({
86
- content: [{ type: "text", text: `Could not open browser automatically. Please open this URL to authenticate:
87
- ${url}` }],
87
+ content: [{
88
+ type: "text",
89
+ text: `Could not open browser automatically. Open this URL within 2 minutes to authenticate:
90
+ ${url}
91
+
92
+ If this is a remote/headless machine, forward local port 8199 to this machine first, then open the URL locally.`
93
+ }],
88
94
  isError: true
89
95
  });
90
96
  });
@@ -99,7 +105,9 @@ ${url}` }],
99
105
  });
100
106
  });
101
107
  registerTools(server, getClient());
102
- server.tool("logout", "Log out, sign out, revoke authorization, and disconnect from Plaud account", async () => {
108
+ server.registerTool("logout", {
109
+ description: "Log out, sign out, revoke authorization, and disconnect from Plaud account"
110
+ }, async () => {
103
111
  const client = getClient();
104
112
  const existingToken = await client.auth.getAccessToken();
105
113
  if (!existingToken) {
@@ -117,7 +125,7 @@ server.tool("logout", "Log out, sign out, revoke authorization, and disconnect f
117
125
  async function registerSkillPrompts() {
118
126
  const skills = await loadSkills();
119
127
  for (const skill of skills) {
120
- server.prompt(skill.name, skill.description, () => ({
128
+ server.registerPrompt(skill.name, { description: skill.description }, () => ({
121
129
  messages: [{ role: "user", content: { type: "text", text: skill.content } }]
122
130
  }));
123
131
  }
@@ -126,7 +134,7 @@ async function main() {
126
134
  const sub = process.argv[2];
127
135
  const sub2 = process.argv[3];
128
136
  if (sub === "install") {
129
- const { runInstall } = await import("./install-TU2Y3ARS.js");
137
+ const { runInstall } = await import("./install-EEQXUUG3.js");
130
138
  const args = process.argv.slice(3);
131
139
  const yes = args.some((a) => a === "--yes" || a === "-y");
132
140
  const noLogin = args.some((a) => a === "--no-login");
@@ -134,32 +142,32 @@ async function main() {
134
142
  return;
135
143
  }
136
144
  if (sub === "clean-plugin") {
137
- const { runCleanPlugin } = await import("./setup-7JTG3C2W.js");
145
+ const { runCleanPlugin } = await import("./setup-QXZHVVDP.js");
138
146
  await runCleanPlugin();
139
147
  return;
140
148
  }
141
149
  if (sub === "setup" && sub2 === "codex") {
142
- const { runSetupCodex } = await import("./setup-7JTG3C2W.js");
150
+ const { runSetupCodex } = await import("./setup-QXZHVVDP.js");
143
151
  await runSetupCodex();
144
152
  return;
145
153
  }
146
154
  if (sub === "unsetup" && sub2 === "codex") {
147
- const { runUnsetupCodex } = await import("./setup-7JTG3C2W.js");
155
+ const { runUnsetupCodex } = await import("./setup-QXZHVVDP.js");
148
156
  await runUnsetupCodex();
149
157
  return;
150
158
  }
151
159
  if (sub === "setup") {
152
- const { runSetup } = await import("./setup-7JTG3C2W.js");
160
+ const { runSetup } = await import("./setup-QXZHVVDP.js");
153
161
  await runSetup();
154
162
  return;
155
163
  }
156
164
  if (sub === "unsetup") {
157
- const { runUnsetup } = await import("./setup-7JTG3C2W.js");
165
+ const { runUnsetup } = await import("./setup-QXZHVVDP.js");
158
166
  await runUnsetup();
159
167
  return;
160
168
  }
161
169
  if (sub === "http") {
162
- const { startHttpServer } = await import("./server-3256GMAD.js");
170
+ const { startHttpServer } = await import("./server-JP2TN7XF.js");
163
171
  startHttpServer();
164
172
  return;
165
173
  }
@@ -169,7 +177,7 @@ async function main() {
169
177
  Usage:
170
178
  plaud-mcp start MCP over stdio
171
179
  plaud-mcp install detect AI clients, configure them, and run OAuth inline (recommended)
172
- plaud-mcp install --yes non-interactive; auto-configure every detected client (for agent-driven install)
180
+ plaud-mcp install --yes non-interactive; auto-configure detected local clients (skips manual web connectors)
173
181
  plaud-mcp install --no-login skip the OAuth step (for CI / headless setup)
174
182
  plaud-mcp http start HTTP MCP server (advanced)
175
183
  plaud-mcp setup [deprecated] alias for install (Claude Desktop only)