@plaud-ai/mcp 0.2.0 → 0.2.1
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/{chunk-UPEENHCG.js → chunk-K22WPZ7P.js} +10 -1
- package/dist/index.js +14 -10
- package/dist/{install-TU2Y3ARS.js → install-I2N3DJG4.js} +26 -12
- package/dist/{server-3256GMAD.js → server-D3H6AMVD.js} +1 -1
- package/dist/{setup-7JTG3C2W.js → setup-QRUDA7ES.js} +1 -1
- package/package.json +11 -14
- package/plugin.json +1 -1
- package/skills/plaud-shared/SKILL.md +1 -1
|
@@ -4,14 +4,23 @@ 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 findNpxCommand() {
|
|
14
|
+
const npxName = platform() === "win32" ? "npx.cmd" : "npx";
|
|
15
|
+
const found = spawnSync(platform() === "win32" ? "where" : "which", [npxName], { 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), npxName);
|
|
19
|
+
return existsSync(sibling) ? sibling : npxName;
|
|
20
|
+
}
|
|
12
21
|
function getMcpEntry() {
|
|
13
22
|
return {
|
|
14
|
-
command:
|
|
23
|
+
command: findNpxCommand(),
|
|
15
24
|
args: ["-y", "@plaud-ai/mcp@latest"]
|
|
16
25
|
};
|
|
17
26
|
}
|
package/dist/index.js
CHANGED
|
@@ -81,10 +81,14 @@ server.tool("login", "Log in, sign in, or authenticate with Plaud account via OA
|
|
|
81
81
|
}, LOGIN_TIMEOUT_MS);
|
|
82
82
|
httpServer.listen(CALLBACK_PORT, () => {
|
|
83
83
|
open(url).catch(() => {
|
|
84
|
-
cleanup();
|
|
85
84
|
resolve({
|
|
86
|
-
content: [{
|
|
87
|
-
|
|
85
|
+
content: [{
|
|
86
|
+
type: "text",
|
|
87
|
+
text: `Could not open browser automatically. Open this URL within 2 minutes to authenticate:
|
|
88
|
+
${url}
|
|
89
|
+
|
|
90
|
+
If this is a remote/headless machine, forward local port 8199 to this machine first, then open the URL locally.`
|
|
91
|
+
}],
|
|
88
92
|
isError: true
|
|
89
93
|
});
|
|
90
94
|
});
|
|
@@ -126,7 +130,7 @@ async function main() {
|
|
|
126
130
|
const sub = process.argv[2];
|
|
127
131
|
const sub2 = process.argv[3];
|
|
128
132
|
if (sub === "install") {
|
|
129
|
-
const { runInstall } = await import("./install-
|
|
133
|
+
const { runInstall } = await import("./install-I2N3DJG4.js");
|
|
130
134
|
const args = process.argv.slice(3);
|
|
131
135
|
const yes = args.some((a) => a === "--yes" || a === "-y");
|
|
132
136
|
const noLogin = args.some((a) => a === "--no-login");
|
|
@@ -134,32 +138,32 @@ async function main() {
|
|
|
134
138
|
return;
|
|
135
139
|
}
|
|
136
140
|
if (sub === "clean-plugin") {
|
|
137
|
-
const { runCleanPlugin } = await import("./setup-
|
|
141
|
+
const { runCleanPlugin } = await import("./setup-QRUDA7ES.js");
|
|
138
142
|
await runCleanPlugin();
|
|
139
143
|
return;
|
|
140
144
|
}
|
|
141
145
|
if (sub === "setup" && sub2 === "codex") {
|
|
142
|
-
const { runSetupCodex } = await import("./setup-
|
|
146
|
+
const { runSetupCodex } = await import("./setup-QRUDA7ES.js");
|
|
143
147
|
await runSetupCodex();
|
|
144
148
|
return;
|
|
145
149
|
}
|
|
146
150
|
if (sub === "unsetup" && sub2 === "codex") {
|
|
147
|
-
const { runUnsetupCodex } = await import("./setup-
|
|
151
|
+
const { runUnsetupCodex } = await import("./setup-QRUDA7ES.js");
|
|
148
152
|
await runUnsetupCodex();
|
|
149
153
|
return;
|
|
150
154
|
}
|
|
151
155
|
if (sub === "setup") {
|
|
152
|
-
const { runSetup } = await import("./setup-
|
|
156
|
+
const { runSetup } = await import("./setup-QRUDA7ES.js");
|
|
153
157
|
await runSetup();
|
|
154
158
|
return;
|
|
155
159
|
}
|
|
156
160
|
if (sub === "unsetup") {
|
|
157
|
-
const { runUnsetup } = await import("./setup-
|
|
161
|
+
const { runUnsetup } = await import("./setup-QRUDA7ES.js");
|
|
158
162
|
await runUnsetup();
|
|
159
163
|
return;
|
|
160
164
|
}
|
|
161
165
|
if (sub === "http") {
|
|
162
|
-
const { startHttpServer } = await import("./server-
|
|
166
|
+
const { startHttpServer } = await import("./server-D3H6AMVD.js");
|
|
163
167
|
startHttpServer();
|
|
164
168
|
return;
|
|
165
169
|
}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
copyToClipboard,
|
|
6
6
|
getMcpEntry,
|
|
7
7
|
writeSkillsToClaudeCode
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-K22WPZ7P.js";
|
|
9
9
|
import {
|
|
10
10
|
skillsCombined
|
|
11
11
|
} from "./chunk-4QBEOJPX.js";
|
|
@@ -32,6 +32,9 @@ function claudeDesktopConfigPath() {
|
|
|
32
32
|
function claudeCodeDir() {
|
|
33
33
|
return join(homedir(), ".claude");
|
|
34
34
|
}
|
|
35
|
+
function claudeCodeUserConfigPath() {
|
|
36
|
+
return join(homedir(), ".claude.json");
|
|
37
|
+
}
|
|
35
38
|
function codexConfigPath() {
|
|
36
39
|
return join(homedir(), ".codex", "config.toml");
|
|
37
40
|
}
|
|
@@ -87,24 +90,34 @@ async function installClaudeDesktop() {
|
|
|
87
90
|
async function installClaudeCode() {
|
|
88
91
|
await writeSkillsToClaudeCode();
|
|
89
92
|
const { command, args } = getMcpEntry();
|
|
90
|
-
const
|
|
93
|
+
const serverCommand = [command, ...args].join(" ");
|
|
94
|
+
const manualCmd = `claude mcp add --scope user plaud -- ${serverCommand}`;
|
|
91
95
|
const cliCheck = spawnSync("which", ["claude"], { encoding: "utf-8" });
|
|
92
96
|
if (cliCheck.status !== 0) {
|
|
93
|
-
|
|
97
|
+
const configPath = claudeCodeUserConfigPath();
|
|
98
|
+
let config = {};
|
|
99
|
+
try {
|
|
100
|
+
config = JSON.parse(await readFile(configPath, "utf-8"));
|
|
101
|
+
} catch {
|
|
102
|
+
if (existsSync(configPath)) {
|
|
103
|
+
return `failed: skills written to ~/.claude/CLAUDE.md, but ~/.claude.json could not be parsed. Run manually once Claude Code CLI is available:
|
|
94
104
|
${manualCmd}`;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const mcpServers = config.mcpServers ?? {};
|
|
108
|
+
config.mcpServers = { ...mcpServers, plaud: { type: "stdio", command, args, env: {} } };
|
|
109
|
+
await writeFile(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
110
|
+
return "skills written to ~/.claude/CLAUDE.md. Claude Code CLI not on PATH; MCP registered in ~/.claude.json.";
|
|
95
111
|
}
|
|
96
|
-
|
|
97
|
-
if (existing.status === 0) {
|
|
98
|
-
return "skills written to ~/.claude/CLAUDE.md. MCP already registered (scope: user).";
|
|
99
|
-
}
|
|
112
|
+
spawnSync("claude", ["mcp", "remove", "plaud", "--scope", "user"], { encoding: "utf-8" });
|
|
100
113
|
const register = spawnSync(
|
|
101
114
|
"claude",
|
|
102
|
-
["mcp", "add", "--scope", "user", "plaud", command, ...args],
|
|
115
|
+
["mcp", "add", "--scope", "user", "plaud", "--", command, ...args],
|
|
103
116
|
{ encoding: "utf-8" }
|
|
104
117
|
);
|
|
105
118
|
if (register.status !== 0) {
|
|
106
119
|
const err = (register.stderr || register.stdout || "").trim();
|
|
107
|
-
return `skills written to ~/.claude/CLAUDE.md
|
|
120
|
+
return `failed: skills written to ~/.claude/CLAUDE.md, but auto-registering MCP failed (${err || "unknown"}). Run manually:
|
|
108
121
|
${manualCmd}`;
|
|
109
122
|
}
|
|
110
123
|
return "skills written to ~/.claude/CLAUDE.md and MCP registered at user scope.";
|
|
@@ -202,9 +215,10 @@ async function runLogin() {
|
|
|
202
215
|
resolve({ status: "timeout" });
|
|
203
216
|
}, LOGIN_TIMEOUT_MS);
|
|
204
217
|
httpServer.listen(CALLBACK_PORT, () => {
|
|
218
|
+
console.log(` if no browser opens, open this URL while this command is still running:
|
|
219
|
+
${url}`);
|
|
205
220
|
open(url).catch(() => {
|
|
206
|
-
|
|
207
|
-
resolve({ status: "failed", message: `could not open browser. Visit manually: ${url}` });
|
|
221
|
+
console.log(" browser launch failed \u2014 waiting for a manual browser callback.");
|
|
208
222
|
});
|
|
209
223
|
});
|
|
210
224
|
httpServer.on("error", (err) => {
|
|
@@ -360,7 +374,7 @@ function printNextSteps(clients, login) {
|
|
|
360
374
|
console.log(" list my recent Plaud recordings");
|
|
361
375
|
console.log();
|
|
362
376
|
console.log(" This triggers OAuth in your browser (once). Tokens are then");
|
|
363
|
-
console.log(" stored in ~/.plaud/tokens.json and refreshed automatically.");
|
|
377
|
+
console.log(" stored in ~/.plaud/tokens-mcp.json and refreshed automatically.");
|
|
364
378
|
}
|
|
365
379
|
console.log();
|
|
366
380
|
console.log(bar);
|
|
@@ -186,7 +186,7 @@ var HTTP_PORT = Number(process.env.PLAUD_HTTP_PORT ?? 3e3);
|
|
|
186
186
|
var HTTP_HOST = process.env.PLAUD_HTTP_HOST ?? "0.0.0.0";
|
|
187
187
|
var CALLBACK_PORT = 8199;
|
|
188
188
|
var CALLBACK_PATH = "/auth/callback";
|
|
189
|
-
var CALLBACK_URL = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;
|
|
189
|
+
var CALLBACK_URL = process.env.PLAUD_CALLBACK_URL ?? `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;
|
|
190
190
|
function startHttpServer() {
|
|
191
191
|
const clientId = process.env.PLAUD_MCP_CLIENT_ID ?? process.env.PLAUD_CLIENT_ID ?? "client_9c501dad-8a0d-40b2-a7b0-d1cb8787f674";
|
|
192
192
|
const clientSecret = process.env.PLAUD_CLIENT_SECRET ?? "";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plaud-ai/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -12,9 +12,13 @@
|
|
|
12
12
|
".mcp.json",
|
|
13
13
|
"skills"
|
|
14
14
|
],
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
15
|
+
"scripts": {
|
|
16
|
+
"version:show": "node -p \"require('./package.json').version\"",
|
|
17
|
+
"prebuild": "node ../../scripts/sync-skills.mjs",
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"dev": "tsup --watch",
|
|
20
|
+
"clean": "rm -rf dist skills",
|
|
21
|
+
"prepublishOnly": "node -e \"const fs=require('fs'),v=require('./package.json').version,p=JSON.parse(fs.readFileSync('./plugin.json','utf8'));p.version=v;fs.writeFileSync('./plugin.json',JSON.stringify(p,null,2)+'\\n');\""
|
|
18
22
|
},
|
|
19
23
|
"dependencies": {
|
|
20
24
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
@@ -24,16 +28,9 @@
|
|
|
24
28
|
"zod": "^4.3.6"
|
|
25
29
|
},
|
|
26
30
|
"devDependencies": {
|
|
31
|
+
"@plaud-ai/shared": "workspace:*",
|
|
27
32
|
"@types/express": "^5.0.6",
|
|
28
33
|
"@types/node": "^25.5.0",
|
|
29
|
-
"typescript": "^5.7.0"
|
|
30
|
-
"@plaud-ai/shared": "0.1.0"
|
|
31
|
-
},
|
|
32
|
-
"scripts": {
|
|
33
|
-
"version:show": "node -p \"require('./package.json').version\"",
|
|
34
|
-
"prebuild": "node ../../scripts/sync-skills.mjs",
|
|
35
|
-
"build": "tsup",
|
|
36
|
-
"dev": "tsup --watch",
|
|
37
|
-
"clean": "rm -rf dist skills"
|
|
34
|
+
"typescript": "^5.7.0"
|
|
38
35
|
}
|
|
39
|
-
}
|
|
36
|
+
}
|
package/plugin.json
CHANGED
|
@@ -13,7 +13,7 @@ metadata:
|
|
|
13
13
|
|
|
14
14
|
## Authentication
|
|
15
15
|
|
|
16
|
-
- Plaud uses OAuth.
|
|
16
|
+
- Plaud MCP uses OAuth. MCP tokens are stored in `~/.plaud/tokens-mcp.json` and refreshed automatically. The terminal CLI uses `~/.plaud/tokens.json` separately.
|
|
17
17
|
- If any tool returns an auth error (message includes `Not authenticated` or `401`), call the `login` tool and wait for the browser callback. Do **not** retry the original tool until login returns success.
|
|
18
18
|
- Never ask the user to paste tokens. The `login` tool handles the whole flow.
|
|
19
19
|
|