@plaud-ai/mcp 0.2.3 → 0.3.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.
- package/dist/chunk-BU3JMO4H.js +50 -0
- package/dist/chunk-MCKGQKYU.js +15 -0
- package/dist/chunk-NPCCDRWQ.js +10 -0
- package/dist/{chunk-BZOIX6WC.js → chunk-QXV7KYGD.js} +61 -7
- package/dist/chunk-RUFCT6DQ.js +60 -0
- package/dist/chunk-TPGKCGTQ.js +20687 -0
- package/dist/index.js +97 -16
- package/dist/{install-C7WMVIPG.js → install-2EIB7ZP3.js} +19 -6
- package/dist/server-BOR5EZLF.js +35 -0
- package/dist/{server-ORMBAVW6.js → server-ZVB7U2VZ.js} +32 -4
- package/dist/{setup-QXZHVVDP.js → setup-GLWZYNRW.js} +1 -0
- package/package.json +3 -1
- package/plugin.json +1 -1
- package/dist/chunk-3XRFIJUG.js +0 -352
- package/dist/chunk-GZ7QPRKV.js +0 -33
package/dist/index.js
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BU3JMO4H.js";
|
|
5
5
|
import {
|
|
6
6
|
loadSkills
|
|
7
7
|
} from "./chunk-4QBEOJPX.js";
|
|
8
8
|
import {
|
|
9
|
+
normalizeMcpHost,
|
|
9
10
|
registerTools
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-QXV7KYGD.js";
|
|
11
12
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
capture,
|
|
14
|
+
classifyError,
|
|
15
|
+
clearUser,
|
|
16
|
+
extractIdentity,
|
|
17
|
+
initTelemetry,
|
|
18
|
+
oauthCallbackErrorType,
|
|
19
|
+
runOAuthCallback,
|
|
20
|
+
setMcpHost,
|
|
21
|
+
setUser,
|
|
22
|
+
shutdown
|
|
23
|
+
} from "./chunk-TPGKCGTQ.js";
|
|
24
|
+
import "./chunk-NPCCDRWQ.js";
|
|
25
|
+
import "./chunk-RUFCT6DQ.js";
|
|
26
|
+
import "./chunk-MCKGQKYU.js";
|
|
14
27
|
|
|
15
28
|
// src/index.ts
|
|
16
29
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -18,7 +31,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
18
31
|
import open from "open";
|
|
19
32
|
var server = new McpServer({
|
|
20
33
|
name: "plaud",
|
|
21
|
-
version: "0.
|
|
34
|
+
version: "0.3.0"
|
|
22
35
|
});
|
|
23
36
|
var CALLBACK_PORT = 8199;
|
|
24
37
|
var LOGIN_TIMEOUT_MS = 12e4;
|
|
@@ -28,7 +41,20 @@ server.registerTool("login", {
|
|
|
28
41
|
const client = getClient();
|
|
29
42
|
const existingToken = await client.auth.getAccessToken();
|
|
30
43
|
if (existingToken) {
|
|
31
|
-
|
|
44
|
+
try {
|
|
45
|
+
await client.getCurrentUser();
|
|
46
|
+
return { content: [{ type: "text", text: "Already logged in." }] };
|
|
47
|
+
} catch (err) {
|
|
48
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
49
|
+
if (msg.includes("401") || msg.includes("Not authenticated")) {
|
|
50
|
+
await client.auth.logout();
|
|
51
|
+
} else {
|
|
52
|
+
return {
|
|
53
|
+
content: [{ type: "text", text: `Failed to verify login state: ${msg}` }],
|
|
54
|
+
isError: true
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
32
58
|
}
|
|
33
59
|
const { url, codeVerifier, state } = client.auth.createAuthorizationRequest();
|
|
34
60
|
const result = await runOAuthCallback({
|
|
@@ -43,8 +69,23 @@ server.registerTool("login", {
|
|
|
43
69
|
});
|
|
44
70
|
}
|
|
45
71
|
});
|
|
72
|
+
if (result.status === "success") {
|
|
73
|
+
capture("auth:oauth_callback:success", { passive: true });
|
|
74
|
+
} else {
|
|
75
|
+
capture("auth:oauth_callback:error", {
|
|
76
|
+
passive: true,
|
|
77
|
+
error_type: oauthCallbackErrorType(result.status)
|
|
78
|
+
});
|
|
79
|
+
}
|
|
46
80
|
switch (result.status) {
|
|
47
81
|
case "success":
|
|
82
|
+
try {
|
|
83
|
+
const user = await client.getCurrentUser();
|
|
84
|
+
if (user && typeof user.id === "string") {
|
|
85
|
+
await setUser(user.id, extractIdentity(user));
|
|
86
|
+
}
|
|
87
|
+
} catch {
|
|
88
|
+
}
|
|
48
89
|
return { content: [{ type: "text", text: "Successfully authenticated with Plaud!" }] };
|
|
49
90
|
case "timeout":
|
|
50
91
|
return {
|
|
@@ -84,10 +125,19 @@ server.registerTool("logout", {
|
|
|
84
125
|
return { content: [{ type: "text", text: "Already logged out." }] };
|
|
85
126
|
}
|
|
86
127
|
try {
|
|
87
|
-
|
|
128
|
+
try {
|
|
129
|
+
await client.revokeCurrentUser();
|
|
130
|
+
} catch {
|
|
131
|
+
}
|
|
132
|
+
await client.auth.logout();
|
|
133
|
+
capture("auth:logout:success", { passive: true });
|
|
134
|
+
} catch (err) {
|
|
135
|
+
capture("auth:logout:error", { passive: true, error_type: classifyError(err) });
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
await clearUser();
|
|
88
139
|
} catch {
|
|
89
140
|
}
|
|
90
|
-
await client.auth.logout();
|
|
91
141
|
return {
|
|
92
142
|
content: [{ type: "text", text: "Logged out and revoked authorization." }]
|
|
93
143
|
};
|
|
@@ -104,7 +154,7 @@ async function main() {
|
|
|
104
154
|
const sub = process.argv[2];
|
|
105
155
|
const sub2 = process.argv[3];
|
|
106
156
|
if (sub === "install") {
|
|
107
|
-
const { runInstall } = await import("./install-
|
|
157
|
+
const { runInstall } = await import("./install-2EIB7ZP3.js");
|
|
108
158
|
const args = process.argv.slice(3);
|
|
109
159
|
const yes = args.some((a) => a === "--yes" || a === "-y");
|
|
110
160
|
const noLogin = args.some((a) => a === "--no-login");
|
|
@@ -112,32 +162,34 @@ async function main() {
|
|
|
112
162
|
return;
|
|
113
163
|
}
|
|
114
164
|
if (sub === "clean-plugin") {
|
|
115
|
-
const { runCleanPlugin } = await import("./setup-
|
|
165
|
+
const { runCleanPlugin } = await import("./setup-GLWZYNRW.js");
|
|
116
166
|
await runCleanPlugin();
|
|
117
167
|
return;
|
|
118
168
|
}
|
|
119
169
|
if (sub === "setup" && sub2 === "codex") {
|
|
120
|
-
const { runSetupCodex } = await import("./setup-
|
|
170
|
+
const { runSetupCodex } = await import("./setup-GLWZYNRW.js");
|
|
121
171
|
await runSetupCodex();
|
|
122
172
|
return;
|
|
123
173
|
}
|
|
124
174
|
if (sub === "unsetup" && sub2 === "codex") {
|
|
125
|
-
const { runUnsetupCodex } = await import("./setup-
|
|
175
|
+
const { runUnsetupCodex } = await import("./setup-GLWZYNRW.js");
|
|
126
176
|
await runUnsetupCodex();
|
|
127
177
|
return;
|
|
128
178
|
}
|
|
129
179
|
if (sub === "setup") {
|
|
130
|
-
const { runSetup } = await import("./setup-
|
|
180
|
+
const { runSetup } = await import("./setup-GLWZYNRW.js");
|
|
131
181
|
await runSetup();
|
|
132
182
|
return;
|
|
133
183
|
}
|
|
134
184
|
if (sub === "unsetup") {
|
|
135
|
-
const { runUnsetup } = await import("./setup-
|
|
185
|
+
const { runUnsetup } = await import("./setup-GLWZYNRW.js");
|
|
136
186
|
await runUnsetup();
|
|
137
187
|
return;
|
|
138
188
|
}
|
|
139
189
|
if (sub === "http") {
|
|
140
|
-
const { startHttpServer } = await import("./server-
|
|
190
|
+
const { startHttpServer } = await import("./server-ZVB7U2VZ.js");
|
|
191
|
+
const { startMetricsServer } = await import("./server-BOR5EZLF.js");
|
|
192
|
+
startMetricsServer();
|
|
141
193
|
startHttpServer();
|
|
142
194
|
return;
|
|
143
195
|
}
|
|
@@ -158,8 +210,37 @@ Usage:
|
|
|
158
210
|
`);
|
|
159
211
|
return;
|
|
160
212
|
}
|
|
213
|
+
try {
|
|
214
|
+
await initTelemetry({
|
|
215
|
+
surface: "mcp",
|
|
216
|
+
appVersion: "0.3.0",
|
|
217
|
+
transport: "stdio"
|
|
218
|
+
});
|
|
219
|
+
} catch {
|
|
220
|
+
}
|
|
221
|
+
const exitWithFlush = async (code) => {
|
|
222
|
+
try {
|
|
223
|
+
await shutdown();
|
|
224
|
+
} catch {
|
|
225
|
+
}
|
|
226
|
+
process.exit(code);
|
|
227
|
+
};
|
|
228
|
+
process.on("SIGINT", () => void exitWithFlush(130));
|
|
229
|
+
process.on("SIGTERM", () => void exitWithFlush(143));
|
|
161
230
|
await registerSkillPrompts();
|
|
231
|
+
server.server.oninitialized = () => {
|
|
232
|
+
try {
|
|
233
|
+
setMcpHost(normalizeMcpHost(server.server.getClientVersion()?.name));
|
|
234
|
+
} catch {
|
|
235
|
+
}
|
|
236
|
+
};
|
|
162
237
|
const transport = new StdioServerTransport();
|
|
163
|
-
|
|
238
|
+
try {
|
|
239
|
+
await server.connect(transport);
|
|
240
|
+
capture("mcp:server:success", { passive: true });
|
|
241
|
+
} catch (err) {
|
|
242
|
+
capture("mcp:server:error", { passive: true, error_type: classifyError(err) });
|
|
243
|
+
await exitWithFlush(1);
|
|
244
|
+
}
|
|
164
245
|
}
|
|
165
246
|
main().catch(console.error);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getClient
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BU3JMO4H.js";
|
|
4
4
|
import {
|
|
5
5
|
copyToClipboard,
|
|
6
6
|
getMcpEntry,
|
|
@@ -11,7 +11,9 @@ import {
|
|
|
11
11
|
} from "./chunk-4QBEOJPX.js";
|
|
12
12
|
import {
|
|
13
13
|
runOAuthCallback
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-TPGKCGTQ.js";
|
|
15
|
+
import "./chunk-RUFCT6DQ.js";
|
|
16
|
+
import "./chunk-MCKGQKYU.js";
|
|
15
17
|
|
|
16
18
|
// src/install.ts
|
|
17
19
|
import { createInterface } from "readline/promises";
|
|
@@ -411,8 +413,13 @@ async function runLogin() {
|
|
|
411
413
|
try {
|
|
412
414
|
const user = await client.getCurrentUser();
|
|
413
415
|
return { status: "already-authed", who: pickIdentity(user) };
|
|
414
|
-
} catch {
|
|
415
|
-
|
|
416
|
+
} catch (err) {
|
|
417
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
418
|
+
if (msg.includes("401") || msg.includes("Not authenticated")) {
|
|
419
|
+
await client.auth.logout().catch(() => void 0);
|
|
420
|
+
} else {
|
|
421
|
+
return { status: "already-authed" };
|
|
422
|
+
}
|
|
416
423
|
}
|
|
417
424
|
}
|
|
418
425
|
} catch {
|
|
@@ -534,8 +541,14 @@ async function doLoginStep(nonInteractive) {
|
|
|
534
541
|
const who = pickIdentity(user);
|
|
535
542
|
console.log(` already signed in${who ? ` as ${who}` : ""} \u2014 skipping OAuth.`);
|
|
536
543
|
return { status: "already-authed", who };
|
|
537
|
-
} catch {
|
|
538
|
-
|
|
544
|
+
} catch (err) {
|
|
545
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
546
|
+
if (msg.includes("401") || msg.includes("Not authenticated")) {
|
|
547
|
+
console.log(" saved token was revoked server-side \u2014 clearing and re-authenticating.");
|
|
548
|
+
await client.auth.logout().catch(() => void 0);
|
|
549
|
+
} else {
|
|
550
|
+
console.log(" token present but user lookup failed \u2014 will re-auth.");
|
|
551
|
+
}
|
|
539
552
|
}
|
|
540
553
|
}
|
|
541
554
|
} catch {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
logger
|
|
3
|
+
} from "./chunk-NPCCDRWQ.js";
|
|
4
|
+
import {
|
|
5
|
+
registry
|
|
6
|
+
} from "./chunk-RUFCT6DQ.js";
|
|
7
|
+
import "./chunk-MCKGQKYU.js";
|
|
8
|
+
|
|
9
|
+
// src/metrics/server.ts
|
|
10
|
+
import express from "express";
|
|
11
|
+
var METRICS_PORT = Number(process.env.PLAUD_METRICS_PORT ?? 9080);
|
|
12
|
+
var METRICS_HOST = process.env.PLAUD_METRICS_HOST ?? "0.0.0.0";
|
|
13
|
+
function startMetricsServer() {
|
|
14
|
+
const app = express();
|
|
15
|
+
app.get("/metrics", async (_req, res, next) => {
|
|
16
|
+
try {
|
|
17
|
+
res.setHeader("Content-Type", registry.contentType);
|
|
18
|
+
res.end(await registry.metrics());
|
|
19
|
+
} catch (err) {
|
|
20
|
+
next(err);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
app.get("/healthz", (_req, res) => {
|
|
24
|
+
res.status(200).send("ok");
|
|
25
|
+
});
|
|
26
|
+
const server = app.listen(METRICS_PORT, METRICS_HOST, () => {
|
|
27
|
+
logger.info({ event: "metrics_server_started", port: METRICS_PORT, host: METRICS_HOST });
|
|
28
|
+
});
|
|
29
|
+
server.on("error", (err) => {
|
|
30
|
+
logger.error({ event: "metrics_server_error", err: err.message });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
startMetricsServer
|
|
35
|
+
};
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
-
logger,
|
|
3
2
|
registerTools
|
|
4
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QXV7KYGD.js";
|
|
5
4
|
import {
|
|
6
5
|
PlaudClient
|
|
7
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TPGKCGTQ.js";
|
|
7
|
+
import {
|
|
8
|
+
logger
|
|
9
|
+
} from "./chunk-NPCCDRWQ.js";
|
|
10
|
+
import {
|
|
11
|
+
httpRequestDuration,
|
|
12
|
+
httpRequestsInProgress,
|
|
13
|
+
oauthTokenRefresh
|
|
14
|
+
} from "./chunk-RUFCT6DQ.js";
|
|
15
|
+
import "./chunk-MCKGQKYU.js";
|
|
8
16
|
|
|
9
17
|
// src/http/server.ts
|
|
10
18
|
import express from "express";
|
|
@@ -680,17 +688,21 @@ var PlaudOAuthProvider = class extends ProxyOAuthServerProvider {
|
|
|
680
688
|
}
|
|
681
689
|
logger.error({ event: "oauth_token_refresh_failed", status: fetchRes.status, body: text.slice(0, 500) });
|
|
682
690
|
if (fetchRes.status >= 500) {
|
|
691
|
+
oauthTokenRefresh.inc({ result: "upstream_error" });
|
|
683
692
|
throw new McpServerError(`Upstream refresh endpoint error: ${fetchRes.status} ${text.slice(0, 200)}`);
|
|
684
693
|
}
|
|
694
|
+
oauthTokenRefresh.inc({ result: "invalid_grant" });
|
|
685
695
|
throw new InvalidGrantError(`Plaud token refresh: ${fetchRes.status} ${text.slice(0, 200)}`);
|
|
686
696
|
}
|
|
687
697
|
let data;
|
|
688
698
|
try {
|
|
689
699
|
data = await fetchRes.json();
|
|
690
700
|
} catch (err) {
|
|
701
|
+
oauthTokenRefresh.inc({ result: "parse_failed" });
|
|
691
702
|
logger.error({ event: "oauth_refresh_json_parse_failed", error: String(err) });
|
|
692
703
|
throw new McpServerError("Refresh endpoint returned non-JSON response");
|
|
693
704
|
}
|
|
705
|
+
oauthTokenRefresh.inc({ result: "success" });
|
|
694
706
|
logger.info({
|
|
695
707
|
event: "oauth_token_refresh_ok",
|
|
696
708
|
has_refresh_token: !!data.refresh_token,
|
|
@@ -805,6 +817,22 @@ function startHttpServer() {
|
|
|
805
817
|
};
|
|
806
818
|
const app = createMcpExpressApp({ host: HTTP_HOST });
|
|
807
819
|
app.set("trust proxy", 1);
|
|
820
|
+
app.use((req, res, next) => {
|
|
821
|
+
const start = process.hrtime.bigint();
|
|
822
|
+
const method = req.method;
|
|
823
|
+
const inProgressLabels = { method, handler: req.path };
|
|
824
|
+
httpRequestsInProgress.inc(inProgressLabels);
|
|
825
|
+
res.on("finish", () => {
|
|
826
|
+
const handler = req.route?.path ?? req.path;
|
|
827
|
+
const durSec = Number(process.hrtime.bigint() - start) / 1e9;
|
|
828
|
+
httpRequestDuration.observe(
|
|
829
|
+
{ method, handler, status: String(res.statusCode) },
|
|
830
|
+
durSec
|
|
831
|
+
);
|
|
832
|
+
httpRequestsInProgress.dec(inProgressLabels);
|
|
833
|
+
});
|
|
834
|
+
next();
|
|
835
|
+
});
|
|
808
836
|
app.get("/.well-known/openai-apps-challenge", (_req, res) => {
|
|
809
837
|
res.type("text/plain").send(OPENAI_APPS_CHALLENGE_TOKEN);
|
|
810
838
|
});
|
|
@@ -982,7 +1010,7 @@ function startHttpServer() {
|
|
|
982
1010
|
apiBase,
|
|
983
1011
|
staticToken: token
|
|
984
1012
|
});
|
|
985
|
-
const mcpServer = new McpServer({ name: "plaud", version: "0.
|
|
1013
|
+
const mcpServer = new McpServer({ name: "plaud", version: "0.3.0" });
|
|
986
1014
|
registerTools(mcpServer, client);
|
|
987
1015
|
const transport = new StreamableHTTPServerTransport({
|
|
988
1016
|
sessionIdGenerator: void 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plaud-ai/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -25,10 +25,12 @@
|
|
|
25
25
|
"express": "^5.2.1",
|
|
26
26
|
"open": "^10.2.0",
|
|
27
27
|
"pino": "^10.3.1",
|
|
28
|
+
"prom-client": "^15.1.3",
|
|
28
29
|
"zod": "^4.3.6"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"@plaud-ai/shared": "workspace:*",
|
|
33
|
+
"@plaud-ai/telemetry": "workspace:*",
|
|
32
34
|
"@types/express": "^5.0.6",
|
|
33
35
|
"@types/node": "^25.5.0",
|
|
34
36
|
"typescript": "^5.7.0"
|