@integrity-labs/agt-cli 0.28.1131 → 0.28.1132

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,7 +16,7 @@ import {
16
16
  parseEnvFileEntries,
17
17
  parseEnvIntegrations,
18
18
  shellQuote
19
- } from "./chunk-KG4IEJEF.js";
19
+ } from "./chunk-LIWZ3QER.js";
20
20
  import {
21
21
  BIND_FAILURE_QUARANTINE_THRESHOLD,
22
22
  INTEGRATIONS_SECTION_END,
@@ -79,7 +79,7 @@ import {
79
79
  sessionTranscriptDir,
80
80
  worseConnectivityOutcome,
81
81
  wrapScheduledTaskPrompt
82
- } from "./chunk-TKBGHAN3.js";
82
+ } from "./chunk-CA4OFLW4.js";
83
83
  import {
84
84
  classifyUnanswerablePane,
85
85
  isConsumerTermsDialogVisible,
@@ -8076,7 +8076,7 @@ function exchangeFailureKind(err) {
8076
8076
  }
8077
8077
 
8078
8078
  // src/lib/api-client.ts
8079
- var agtCliVersion = true ? "0.28.1131" : "dev";
8079
+ var agtCliVersion = true ? "0.28.1132" : "dev";
8080
8080
  var lastConfigHash = null;
8081
8081
  function setConfigHash(hash) {
8082
8082
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -13227,4 +13227,4 @@ export {
13227
13227
  managerInstallSystemUnitCommand,
13228
13228
  managerUninstallSystemUnitCommand
13229
13229
  };
13230
- //# sourceMappingURL=chunk-4BKN4EUH.js.map
13230
+ //# sourceMappingURL=chunk-K2V6JUIQ.js.map
@@ -24,7 +24,7 @@ import {
24
24
  rotateDailySession,
25
25
  sessionFileExists,
26
26
  todayLocalIso
27
- } from "./chunk-TKBGHAN3.js";
27
+ } from "./chunk-CA4OFLW4.js";
28
28
  import {
29
29
  classifyUnanswerablePane,
30
30
  findUsageLimitResetHint,
@@ -6114,4 +6114,4 @@ export {
6114
6114
  stopAllSessionsAndWait,
6115
6115
  getProjectDir
6116
6116
  };
6117
- //# sourceMappingURL=chunk-KG4IEJEF.js.map
6117
+ //# sourceMappingURL=chunk-LIWZ3QER.js.map
@@ -269,7 +269,7 @@ async function spawnPairSession(session) {
269
269
  return { ok: true };
270
270
  } catch {
271
271
  }
272
- const { resolveClaudeBinary } = await import("./persistent-session-F2LRKDFL.js");
272
+ const { resolveClaudeBinary } = await import("./persistent-session-WE42P4HU.js");
273
273
  const claudeBin = resolveClaudeBinary();
274
274
  const pairEnv = {
275
275
  ...process.env,
@@ -739,4 +739,4 @@ export {
739
739
  startClaudePair,
740
740
  submitClaudePairCode
741
741
  };
742
- //# sourceMappingURL=claude-pair-runtime-DNCX245G.js.map
742
+ //# sourceMappingURL=claude-pair-runtime-D7FVFPCJ.js.map
@@ -76,7 +76,7 @@ import {
76
76
  setConfigHash,
77
77
  shellGuard,
78
78
  tripClass
79
- } from "../chunk-4BKN4EUH.js";
79
+ } from "../chunk-K2V6JUIQ.js";
80
80
  import {
81
81
  getProjectDir as getProjectDir2,
82
82
  getReadyTasks,
@@ -163,7 +163,7 @@ import {
163
163
  webFetchBaselineValue,
164
164
  webFetchRestartNeeded,
165
165
  writeEgressAllowlist
166
- } from "../chunk-KG4IEJEF.js";
166
+ } from "../chunk-LIWZ3QER.js";
167
167
  import {
168
168
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
169
169
  AnchorSessionClient,
@@ -274,7 +274,7 @@ import {
274
274
  subagentActivityAgeSeconds,
275
275
  sumTranscriptUsageInWindow,
276
276
  transcriptActivityAgeSeconds
277
- } from "../chunk-TKBGHAN3.js";
277
+ } from "../chunk-CA4OFLW4.js";
278
278
  import {
279
279
  classifyUnanswerablePane,
280
280
  focusedConfirmDialogBlock,
@@ -14491,7 +14491,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
14491
14491
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
14492
14492
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
14493
14493
  async function channelInboundActivityAgeSecondsFor(codeName) {
14494
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-SM6XFJJ6.js");
14494
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-6AG6PYW7.js");
14495
14495
  const newest = newestPendingInboundActivityMtimeMs(dirname11(paneLogPath(codeName)));
14496
14496
  if (newest === null) return null;
14497
14497
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -15249,7 +15249,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
15249
15249
  var lastVersionCheckAt = 0;
15250
15250
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
15251
15251
  var lastResponsivenessProbeAt = 0;
15252
- var agtCliVersion = true ? "0.28.1131" : "dev";
15252
+ var agtCliVersion = true ? "0.28.1132" : "dev";
15253
15253
  function resolveBrewPath(execFileSync3) {
15254
15254
  try {
15255
15255
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -16879,7 +16879,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
16879
16879
  if (codeNames.length === 0) return;
16880
16880
  void (async () => {
16881
16881
  try {
16882
- const { collectDiagnostics } = await import("../persistent-session-F2LRKDFL.js");
16882
+ const { collectDiagnostics } = await import("../persistent-session-WE42P4HU.js");
16883
16883
  await api.post("/host/heartbeat", {
16884
16884
  host_id: hostId,
16885
16885
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -17021,7 +17021,7 @@ async function pollCycleInner() {
17021
17021
  }
17022
17022
  try {
17023
17023
  const { detectHostSecurity } = await import("../host-security-KQYYZZVW.js");
17024
- const { collectDiagnostics } = await import("../persistent-session-F2LRKDFL.js");
17024
+ const { collectDiagnostics } = await import("../persistent-session-WE42P4HU.js");
17025
17025
  const diagCodeNames = [...agentState.persistentSessionAgents];
17026
17026
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor) : void 0;
17027
17027
  let tailscaleHostname;
@@ -17229,7 +17229,7 @@ async function pollCycleInner() {
17229
17229
  collectPanelessActivityProbes,
17230
17230
  getResponsivenessIntervalMs,
17231
17231
  occupancyQualificationClassifications
17232
- } = await import("../responsiveness-probe-SM6XFJJ6.js");
17232
+ } = await import("../responsiveness-probe-6AG6PYW7.js");
17233
17233
  const probeIntervalMs = getResponsivenessIntervalMs();
17234
17234
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
17235
17235
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -17346,7 +17346,7 @@ async function pollCycleInner() {
17346
17346
  collectResponsivenessProbes,
17347
17347
  livePendingInboundOldestAgeSeconds,
17348
17348
  parkPendingInbound
17349
- } = await import("../responsiveness-probe-SM6XFJJ6.js");
17349
+ } = await import("../responsiveness-probe-6AG6PYW7.js");
17350
17350
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-M6AFZWNU.js");
17351
17351
  const wedgeNow = /* @__PURE__ */ new Date();
17352
17352
  const liveAgents = agentState.persistentSessionAgents;
@@ -17632,7 +17632,7 @@ async function pollCycleInner() {
17632
17632
  }
17633
17633
  }
17634
17634
  );
17635
- const { parkPendingInbound } = await import("../responsiveness-probe-SM6XFJJ6.js");
17635
+ const { parkPendingInbound } = await import("../responsiveness-probe-6AG6PYW7.js");
17636
17636
  const { parked, deadLettered } = parkPendingInbound(codeName, new Date(fatalNowMs));
17637
17637
  paneFatalStreak.delete(codeName);
17638
17638
  paneFatalRestarts.set(codeName, [...history, fatalNowMs]);
@@ -17663,7 +17663,7 @@ async function pollCycleInner() {
17663
17663
  TRANSCRIPT_MOUNT_ESCALATION_REFRESH_MS,
17664
17664
  bindSourceEscalations
17665
17665
  } = await import("../transcript-mount-health-OHE6IVJV.js");
17666
- const { transcriptBindSourcesFor, ensureTranscriptBindSources } = await import("../persistent-session-F2LRKDFL.js");
17666
+ const { transcriptBindSourcesFor, ensureTranscriptBindSources } = await import("../persistent-session-WE42P4HU.js");
17667
17667
  const mountConfig = resolveTranscriptMountConfig();
17668
17668
  const liveAgents = agentState.persistentSessionAgents;
17669
17669
  for (const tracked of [
@@ -17828,7 +17828,7 @@ async function pollCycleInner() {
17828
17828
  }
17829
17829
  try {
17830
17830
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-VR5QGP3J.js");
17831
- const { probeSessionAuth } = await import("../session-auth-dead-KNTFHDWV.js");
17831
+ const { probeSessionAuth } = await import("../session-auth-dead-H7UDGEIS.js");
17832
17832
  const observations = [];
17833
17833
  const pendingCacheCommits = [];
17834
17834
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -22423,7 +22423,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
22423
22423
  try {
22424
22424
  const freshId = rotateSessionForWedge(codeName);
22425
22425
  consecutiveWedgeCycles.delete(codeName);
22426
- const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-SM6XFJJ6.js");
22426
+ const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-6AG6PYW7.js");
22427
22427
  const { parked, deadLettered } = parkForRestart(codeName, /* @__PURE__ */ new Date());
22428
22428
  const parkNote = parked > 0 ? `, ${parked} inbound parked` : "";
22429
22429
  const deadNote = deadLettered > 0 ? `, ${deadLettered} undeliverable dead-lettered` : "";
@@ -22466,7 +22466,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
22466
22466
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
22467
22467
  void (async () => {
22468
22468
  try {
22469
- const { collectDiagnostics } = await import("../persistent-session-F2LRKDFL.js");
22469
+ const { collectDiagnostics } = await import("../persistent-session-WE42P4HU.js");
22470
22470
  await api.post("/host/heartbeat", {
22471
22471
  host_id: hostId,
22472
22472
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -22517,7 +22517,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
22517
22517
  }
22518
22518
  try {
22519
22519
  const hostId = await getHostId();
22520
- const { collectDiagnostics } = await import("../persistent-session-F2LRKDFL.js");
22520
+ const { collectDiagnostics } = await import("../persistent-session-WE42P4HU.js");
22521
22521
  await api.post("/host/heartbeat", {
22522
22522
  host_id: hostId,
22523
22523
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -23190,7 +23190,7 @@ async function processClaudePairSessions(agents) {
23190
23190
  // cannot take it for itself — by the time it runs, the write it is looking
23191
23191
  // for may already have happened.
23192
23192
  snapshotPairConfig
23193
- } = await import("../claude-pair-runtime-DNCX245G.js");
23193
+ } = await import("../claude-pair-runtime-D7FVFPCJ.js");
23194
23194
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
23195
23195
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
23196
23196
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -39599,6 +39599,61 @@ var OAUTH_PROVIDERS = {
39599
39599
  // tools/list after a real consent (runbook Step 3).
39600
39600
  toolAllowlist: ["otter_get_user_info", "otter_search", "otter_fetch"]
39601
39601
  },
39602
+ "plaud": {
39603
+ // ENG-11543 (CS-2134): Plaud's hosted MCP - remote streamable-HTTP at
39604
+ // https://mcp.plaud.ai/mcp. Same Granola/Kajabi/Otter shape: OAuth 2.0
39605
+ // authorization-code with PKCE (S256) and a public client
39606
+ // (token_endpoint_auth_method 'none') issued via Dynamic Client
39607
+ // Registration (RFC 7591). NOT the stdio `npx @plaud-ai/mcp` package,
39608
+ // which runs its own local browser sign-in and token file. Values below
39609
+ // are taken verbatim from the metadata (re-read 2026-10-16), not inferred:
39610
+ // - https://mcp.plaud.ai/.well-known/oauth-protected-resource (and the
39611
+ // path-suffixed /.well-known/oauth-protected-resource/mcp the server's
39612
+ // 401 points at) give resource https://mcp.plaud.ai/mcp, AS
39613
+ // https://mcp.plaud.ai/, bearer in the header;
39614
+ // - https://mcp.plaud.ai/.well-known/oauth-authorization-server (and
39615
+ // the identical openid-configuration) give authorize /authorize, token
39616
+ // /token, register /register, PKCE S256 only, `none` among the token
39617
+ // auth methods, and the authorization_code + refresh_token grants.
39618
+ // NOT advertised: `scopes_supported` (so defaultScopes is empty, the
39619
+ // notion-cli precedent, and the authorize URL carries `scope=`) and
39620
+ // `revocation_endpoint` (so there is no revokeUrl: disconnecting here
39621
+ // deletes our copy of the token but cannot revoke Plaud's grant; the user
39622
+ // revokes it in their Plaud account).
39623
+ //
39624
+ // DCR (operator step, NOT done as of this commit): POST the registration
39625
+ // body by hand to https://mcp.plaud.ai/register with client_name
39626
+ // `Ninjafy`, token_endpoint_auth_method `none`, grant_types
39627
+ // authorization_code + refresh_token, and BOTH API callbacks in
39628
+ // redirect_uris (https://api.augmented.team/integrations/oauth/callback
39629
+ // and https://api.ninjafy.com/integrations/oauth/callback). Do not use
39630
+ // scripts/dcr-register.ts: it takes a single --redirect-uri. Store the
39631
+ // returned client id as OAUTH_PLAUD_CLIENT_ID; unset, Connect soft-fails
39632
+ // "not configured". Full procedure: docs/runbooks/plaud-dogfood.md.
39633
+ definitionId: "plaud",
39634
+ authorizeUrl: "https://mcp.plaud.ai/authorize",
39635
+ tokenUrl: "https://mcp.plaud.ai/token",
39636
+ defaultScopes: [],
39637
+ supportsRefresh: true,
39638
+ extraAuthorizeParams: {},
39639
+ clientAuthMethod: "body",
39640
+ pkce: "S256",
39641
+ publicClient: true,
39642
+ mcpUrl: "https://mcp.plaud.ai/mcp",
39643
+ // Curated surface (matches the catalog seed's defined_scopes[].tools).
39644
+ // Plaud advertises NO scopes, so the token is not scope-limited: the
39645
+ // read-only property of this integration rests ENTIRELY on this
39646
+ // allowlist, which the remote-oauth-proxy enforces on tools/list and
39647
+ // tools/call. The five names are Plaud's documented read tools
39648
+ // (https://docs.plaud.ai/plaud-mcp-cli/mcp). `login` and `logout` are
39649
+ // deliberately excluded: sign-in is our OAuth broker's job, and `logout`
39650
+ // revokes the user's authorization, which an agent must never do. The
39651
+ // names come from the docs, not from an authenticated tools/list (that
39652
+ // needs a consented token), and the proxy SKIPS an allowlisted name the
39653
+ // server does not serve, so confirm against the first live tools/list
39654
+ // (runbook Step 3, a gate before customer use).
39655
+ toolAllowlist: ["get_current_user", "list_files", "get_file", "get_note", "get_transcript"]
39656
+ },
39602
39657
  "notion-cli": {
39603
39658
  // Notion's public OAuth app. Tokens are workspace-scoped and long-lived —
39604
39659
  // Notion does not issue refresh_tokens, so `supportsRefresh: false` and
@@ -40055,6 +40110,36 @@ var INTEGRATION_REGISTRY = [
40055
40110
  docs_url: "https://help.otter.ai/hc/en-us/articles/35287607569687-Otter-MCP-Server",
40056
40111
  beta: true
40057
40112
  },
40113
+ {
40114
+ id: "plaud",
40115
+ name: "Plaud",
40116
+ category: "knowledge",
40117
+ description: "Read Plaud recordings: list and search recordings by name or date, and read their AI notes (summary, action items, key topics) and full speaker-labelled transcripts.",
40118
+ // ENG-11543 (CS-2134): same remote streamable-HTTP MCP + OAuth pattern as
40119
+ // Granola/Kajabi/Otter, against Plaud's HOSTED server (https://mcp.plaud.ai/mcp),
40120
+ // not the stdio `npx @plaud-ai/mcp` package. Discovery chain: RFC 9728
40121
+ // protected-resource metadata at mcp.plaud.ai -> RFC 8414 AS metadata on the
40122
+ // same host -> RFC 7591 registration at /register. Auth is OAuth 2.0
40123
+ // authorization-code with PKCE (S256) and a public client registered once by
40124
+ // an operator (docs/runbooks/plaud-dogfood.md -> OAUTH_PLAUD_CLIENT_ID).
40125
+ // Consent is brokered through the shared /integrations/oauth/authorize ->
40126
+ // /callback path, and the token reaches the host via the generic
40127
+ // remote-oauth-proxy (OAUTH_PROVIDERS.plaud.mcpUrl).
40128
+ //
40129
+ // READ-ONLY RESTS ENTIRELY ON THE TOOL ALLOWLIST. Unlike Otter, Plaud
40130
+ // advertises NO scopes_supported, so there is no read scope to request and
40131
+ // the granted token is not scope-limited. What keeps this integration
40132
+ // read-only is OAUTH_PROVIDERS.plaud.toolAllowlist (the five documented
40133
+ // reads), which the proxy enforces on tools/list and tools/call. `login` and
40134
+ // `logout` are excluded; `logout` would revoke the user's authorization.
40135
+ // Anything that widens the allowlist widens what the token can do.
40136
+ supported_auth_types: ["oauth2"],
40137
+ capabilities: [
40138
+ { id: "plaud:read", name: "Read Recordings & Transcripts", description: "List and search recordings by name or date, and read their details, AI notes (summary, action items, key topics) and full transcripts with speaker labels (get_current_user, list_files, get_file, get_note, get_transcript)", access: "read" }
40139
+ ],
40140
+ docs_url: "https://docs.plaud.ai/plaud-mcp-cli/mcp",
40141
+ beta: true
40142
+ },
40058
40143
  {
40059
40144
  id: "anchor-browser",
40060
40145
  name: "Anchor Browser",
package/dist/mcp/index.js CHANGED
@@ -25624,6 +25624,61 @@ var OAUTH_PROVIDERS = {
25624
25624
  // tools/list after a real consent (runbook Step 3).
25625
25625
  toolAllowlist: ["otter_get_user_info", "otter_search", "otter_fetch"]
25626
25626
  },
25627
+ "plaud": {
25628
+ // ENG-11543 (CS-2134): Plaud's hosted MCP - remote streamable-HTTP at
25629
+ // https://mcp.plaud.ai/mcp. Same Granola/Kajabi/Otter shape: OAuth 2.0
25630
+ // authorization-code with PKCE (S256) and a public client
25631
+ // (token_endpoint_auth_method 'none') issued via Dynamic Client
25632
+ // Registration (RFC 7591). NOT the stdio `npx @plaud-ai/mcp` package,
25633
+ // which runs its own local browser sign-in and token file. Values below
25634
+ // are taken verbatim from the metadata (re-read 2026-10-16), not inferred:
25635
+ // - https://mcp.plaud.ai/.well-known/oauth-protected-resource (and the
25636
+ // path-suffixed /.well-known/oauth-protected-resource/mcp the server's
25637
+ // 401 points at) give resource https://mcp.plaud.ai/mcp, AS
25638
+ // https://mcp.plaud.ai/, bearer in the header;
25639
+ // - https://mcp.plaud.ai/.well-known/oauth-authorization-server (and
25640
+ // the identical openid-configuration) give authorize /authorize, token
25641
+ // /token, register /register, PKCE S256 only, `none` among the token
25642
+ // auth methods, and the authorization_code + refresh_token grants.
25643
+ // NOT advertised: `scopes_supported` (so defaultScopes is empty, the
25644
+ // notion-cli precedent, and the authorize URL carries `scope=`) and
25645
+ // `revocation_endpoint` (so there is no revokeUrl: disconnecting here
25646
+ // deletes our copy of the token but cannot revoke Plaud's grant; the user
25647
+ // revokes it in their Plaud account).
25648
+ //
25649
+ // DCR (operator step, NOT done as of this commit): POST the registration
25650
+ // body by hand to https://mcp.plaud.ai/register with client_name
25651
+ // `Ninjafy`, token_endpoint_auth_method `none`, grant_types
25652
+ // authorization_code + refresh_token, and BOTH API callbacks in
25653
+ // redirect_uris (https://api.augmented.team/integrations/oauth/callback
25654
+ // and https://api.ninjafy.com/integrations/oauth/callback). Do not use
25655
+ // scripts/dcr-register.ts: it takes a single --redirect-uri. Store the
25656
+ // returned client id as OAUTH_PLAUD_CLIENT_ID; unset, Connect soft-fails
25657
+ // "not configured". Full procedure: docs/runbooks/plaud-dogfood.md.
25658
+ definitionId: "plaud",
25659
+ authorizeUrl: "https://mcp.plaud.ai/authorize",
25660
+ tokenUrl: "https://mcp.plaud.ai/token",
25661
+ defaultScopes: [],
25662
+ supportsRefresh: true,
25663
+ extraAuthorizeParams: {},
25664
+ clientAuthMethod: "body",
25665
+ pkce: "S256",
25666
+ publicClient: true,
25667
+ mcpUrl: "https://mcp.plaud.ai/mcp",
25668
+ // Curated surface (matches the catalog seed's defined_scopes[].tools).
25669
+ // Plaud advertises NO scopes, so the token is not scope-limited: the
25670
+ // read-only property of this integration rests ENTIRELY on this
25671
+ // allowlist, which the remote-oauth-proxy enforces on tools/list and
25672
+ // tools/call. The five names are Plaud's documented read tools
25673
+ // (https://docs.plaud.ai/plaud-mcp-cli/mcp). `login` and `logout` are
25674
+ // deliberately excluded: sign-in is our OAuth broker's job, and `logout`
25675
+ // revokes the user's authorization, which an agent must never do. The
25676
+ // names come from the docs, not from an authenticated tools/list (that
25677
+ // needs a consented token), and the proxy SKIPS an allowlisted name the
25678
+ // server does not serve, so confirm against the first live tools/list
25679
+ // (runbook Step 3, a gate before customer use).
25680
+ toolAllowlist: ["get_current_user", "list_files", "get_file", "get_note", "get_transcript"]
25681
+ },
25627
25682
  "notion-cli": {
25628
25683
  // Notion's public OAuth app. Tokens are workspace-scoped and long-lived —
25629
25684
  // Notion does not issue refresh_tokens, so `supportsRefresh: false` and
@@ -26080,6 +26135,36 @@ var INTEGRATION_REGISTRY = [
26080
26135
  docs_url: "https://help.otter.ai/hc/en-us/articles/35287607569687-Otter-MCP-Server",
26081
26136
  beta: true
26082
26137
  },
26138
+ {
26139
+ id: "plaud",
26140
+ name: "Plaud",
26141
+ category: "knowledge",
26142
+ description: "Read Plaud recordings: list and search recordings by name or date, and read their AI notes (summary, action items, key topics) and full speaker-labelled transcripts.",
26143
+ // ENG-11543 (CS-2134): same remote streamable-HTTP MCP + OAuth pattern as
26144
+ // Granola/Kajabi/Otter, against Plaud's HOSTED server (https://mcp.plaud.ai/mcp),
26145
+ // not the stdio `npx @plaud-ai/mcp` package. Discovery chain: RFC 9728
26146
+ // protected-resource metadata at mcp.plaud.ai -> RFC 8414 AS metadata on the
26147
+ // same host -> RFC 7591 registration at /register. Auth is OAuth 2.0
26148
+ // authorization-code with PKCE (S256) and a public client registered once by
26149
+ // an operator (docs/runbooks/plaud-dogfood.md -> OAUTH_PLAUD_CLIENT_ID).
26150
+ // Consent is brokered through the shared /integrations/oauth/authorize ->
26151
+ // /callback path, and the token reaches the host via the generic
26152
+ // remote-oauth-proxy (OAUTH_PROVIDERS.plaud.mcpUrl).
26153
+ //
26154
+ // READ-ONLY RESTS ENTIRELY ON THE TOOL ALLOWLIST. Unlike Otter, Plaud
26155
+ // advertises NO scopes_supported, so there is no read scope to request and
26156
+ // the granted token is not scope-limited. What keeps this integration
26157
+ // read-only is OAUTH_PROVIDERS.plaud.toolAllowlist (the five documented
26158
+ // reads), which the proxy enforces on tools/list and tools/call. `login` and
26159
+ // `logout` are excluded; `logout` would revoke the user's authorization.
26160
+ // Anything that widens the allowlist widens what the token can do.
26161
+ supported_auth_types: ["oauth2"],
26162
+ capabilities: [
26163
+ { id: "plaud:read", name: "Read Recordings & Transcripts", description: "List and search recordings by name or date, and read their details, AI notes (summary, action items, key topics) and full transcripts with speaker labels (get_current_user, list_files, get_file, get_note, get_transcript)", access: "read" }
26164
+ ],
26165
+ docs_url: "https://docs.plaud.ai/plaud-mcp-cli/mcp",
26166
+ beta: true
26167
+ },
26083
26168
  {
26084
26169
  id: "anchor-browser",
26085
26170
  name: "Anchor Browser",
@@ -39756,6 +39756,61 @@ var OAUTH_PROVIDERS = {
39756
39756
  // tools/list after a real consent (runbook Step 3).
39757
39757
  toolAllowlist: ["otter_get_user_info", "otter_search", "otter_fetch"]
39758
39758
  },
39759
+ "plaud": {
39760
+ // ENG-11543 (CS-2134): Plaud's hosted MCP - remote streamable-HTTP at
39761
+ // https://mcp.plaud.ai/mcp. Same Granola/Kajabi/Otter shape: OAuth 2.0
39762
+ // authorization-code with PKCE (S256) and a public client
39763
+ // (token_endpoint_auth_method 'none') issued via Dynamic Client
39764
+ // Registration (RFC 7591). NOT the stdio `npx @plaud-ai/mcp` package,
39765
+ // which runs its own local browser sign-in and token file. Values below
39766
+ // are taken verbatim from the metadata (re-read 2026-10-16), not inferred:
39767
+ // - https://mcp.plaud.ai/.well-known/oauth-protected-resource (and the
39768
+ // path-suffixed /.well-known/oauth-protected-resource/mcp the server's
39769
+ // 401 points at) give resource https://mcp.plaud.ai/mcp, AS
39770
+ // https://mcp.plaud.ai/, bearer in the header;
39771
+ // - https://mcp.plaud.ai/.well-known/oauth-authorization-server (and
39772
+ // the identical openid-configuration) give authorize /authorize, token
39773
+ // /token, register /register, PKCE S256 only, `none` among the token
39774
+ // auth methods, and the authorization_code + refresh_token grants.
39775
+ // NOT advertised: `scopes_supported` (so defaultScopes is empty, the
39776
+ // notion-cli precedent, and the authorize URL carries `scope=`) and
39777
+ // `revocation_endpoint` (so there is no revokeUrl: disconnecting here
39778
+ // deletes our copy of the token but cannot revoke Plaud's grant; the user
39779
+ // revokes it in their Plaud account).
39780
+ //
39781
+ // DCR (operator step, NOT done as of this commit): POST the registration
39782
+ // body by hand to https://mcp.plaud.ai/register with client_name
39783
+ // `Ninjafy`, token_endpoint_auth_method `none`, grant_types
39784
+ // authorization_code + refresh_token, and BOTH API callbacks in
39785
+ // redirect_uris (https://api.augmented.team/integrations/oauth/callback
39786
+ // and https://api.ninjafy.com/integrations/oauth/callback). Do not use
39787
+ // scripts/dcr-register.ts: it takes a single --redirect-uri. Store the
39788
+ // returned client id as OAUTH_PLAUD_CLIENT_ID; unset, Connect soft-fails
39789
+ // "not configured". Full procedure: docs/runbooks/plaud-dogfood.md.
39790
+ definitionId: "plaud",
39791
+ authorizeUrl: "https://mcp.plaud.ai/authorize",
39792
+ tokenUrl: "https://mcp.plaud.ai/token",
39793
+ defaultScopes: [],
39794
+ supportsRefresh: true,
39795
+ extraAuthorizeParams: {},
39796
+ clientAuthMethod: "body",
39797
+ pkce: "S256",
39798
+ publicClient: true,
39799
+ mcpUrl: "https://mcp.plaud.ai/mcp",
39800
+ // Curated surface (matches the catalog seed's defined_scopes[].tools).
39801
+ // Plaud advertises NO scopes, so the token is not scope-limited: the
39802
+ // read-only property of this integration rests ENTIRELY on this
39803
+ // allowlist, which the remote-oauth-proxy enforces on tools/list and
39804
+ // tools/call. The five names are Plaud's documented read tools
39805
+ // (https://docs.plaud.ai/plaud-mcp-cli/mcp). `login` and `logout` are
39806
+ // deliberately excluded: sign-in is our OAuth broker's job, and `logout`
39807
+ // revokes the user's authorization, which an agent must never do. The
39808
+ // names come from the docs, not from an authenticated tools/list (that
39809
+ // needs a consented token), and the proxy SKIPS an allowlisted name the
39810
+ // server does not serve, so confirm against the first live tools/list
39811
+ // (runbook Step 3, a gate before customer use).
39812
+ toolAllowlist: ["get_current_user", "list_files", "get_file", "get_note", "get_transcript"]
39813
+ },
39759
39814
  "notion-cli": {
39760
39815
  // Notion's public OAuth app. Tokens are workspace-scoped and long-lived —
39761
39816
  // Notion does not issue refresh_tokens, so `supportsRefresh: false` and
@@ -40212,6 +40267,36 @@ var INTEGRATION_REGISTRY = [
40212
40267
  docs_url: "https://help.otter.ai/hc/en-us/articles/35287607569687-Otter-MCP-Server",
40213
40268
  beta: true
40214
40269
  },
40270
+ {
40271
+ id: "plaud",
40272
+ name: "Plaud",
40273
+ category: "knowledge",
40274
+ description: "Read Plaud recordings: list and search recordings by name or date, and read their AI notes (summary, action items, key topics) and full speaker-labelled transcripts.",
40275
+ // ENG-11543 (CS-2134): same remote streamable-HTTP MCP + OAuth pattern as
40276
+ // Granola/Kajabi/Otter, against Plaud's HOSTED server (https://mcp.plaud.ai/mcp),
40277
+ // not the stdio `npx @plaud-ai/mcp` package. Discovery chain: RFC 9728
40278
+ // protected-resource metadata at mcp.plaud.ai -> RFC 8414 AS metadata on the
40279
+ // same host -> RFC 7591 registration at /register. Auth is OAuth 2.0
40280
+ // authorization-code with PKCE (S256) and a public client registered once by
40281
+ // an operator (docs/runbooks/plaud-dogfood.md -> OAUTH_PLAUD_CLIENT_ID).
40282
+ // Consent is brokered through the shared /integrations/oauth/authorize ->
40283
+ // /callback path, and the token reaches the host via the generic
40284
+ // remote-oauth-proxy (OAUTH_PROVIDERS.plaud.mcpUrl).
40285
+ //
40286
+ // READ-ONLY RESTS ENTIRELY ON THE TOOL ALLOWLIST. Unlike Otter, Plaud
40287
+ // advertises NO scopes_supported, so there is no read scope to request and
40288
+ // the granted token is not scope-limited. What keeps this integration
40289
+ // read-only is OAUTH_PROVIDERS.plaud.toolAllowlist (the five documented
40290
+ // reads), which the proxy enforces on tools/list and tools/call. `login` and
40291
+ // `logout` are excluded; `logout` would revoke the user's authorization.
40292
+ // Anything that widens the allowlist widens what the token can do.
40293
+ supported_auth_types: ["oauth2"],
40294
+ capabilities: [
40295
+ { id: "plaud:read", name: "Read Recordings & Transcripts", description: "List and search recordings by name or date, and read their details, AI notes (summary, action items, key topics) and full transcripts with speaker labels (get_current_user, list_files, get_file, get_note, get_transcript)", access: "read" }
40296
+ ],
40297
+ docs_url: "https://docs.plaud.ai/plaud-mcp-cli/mcp",
40298
+ beta: true
40299
+ },
40215
40300
  {
40216
40301
  id: "anchor-browser",
40217
40302
  name: "Anchor Browser",
@@ -34143,6 +34143,61 @@ var OAUTH_PROVIDERS = {
34143
34143
  // tools/list after a real consent (runbook Step 3).
34144
34144
  toolAllowlist: ["otter_get_user_info", "otter_search", "otter_fetch"]
34145
34145
  },
34146
+ "plaud": {
34147
+ // ENG-11543 (CS-2134): Plaud's hosted MCP - remote streamable-HTTP at
34148
+ // https://mcp.plaud.ai/mcp. Same Granola/Kajabi/Otter shape: OAuth 2.0
34149
+ // authorization-code with PKCE (S256) and a public client
34150
+ // (token_endpoint_auth_method 'none') issued via Dynamic Client
34151
+ // Registration (RFC 7591). NOT the stdio `npx @plaud-ai/mcp` package,
34152
+ // which runs its own local browser sign-in and token file. Values below
34153
+ // are taken verbatim from the metadata (re-read 2026-10-16), not inferred:
34154
+ // - https://mcp.plaud.ai/.well-known/oauth-protected-resource (and the
34155
+ // path-suffixed /.well-known/oauth-protected-resource/mcp the server's
34156
+ // 401 points at) give resource https://mcp.plaud.ai/mcp, AS
34157
+ // https://mcp.plaud.ai/, bearer in the header;
34158
+ // - https://mcp.plaud.ai/.well-known/oauth-authorization-server (and
34159
+ // the identical openid-configuration) give authorize /authorize, token
34160
+ // /token, register /register, PKCE S256 only, `none` among the token
34161
+ // auth methods, and the authorization_code + refresh_token grants.
34162
+ // NOT advertised: `scopes_supported` (so defaultScopes is empty, the
34163
+ // notion-cli precedent, and the authorize URL carries `scope=`) and
34164
+ // `revocation_endpoint` (so there is no revokeUrl: disconnecting here
34165
+ // deletes our copy of the token but cannot revoke Plaud's grant; the user
34166
+ // revokes it in their Plaud account).
34167
+ //
34168
+ // DCR (operator step, NOT done as of this commit): POST the registration
34169
+ // body by hand to https://mcp.plaud.ai/register with client_name
34170
+ // `Ninjafy`, token_endpoint_auth_method `none`, grant_types
34171
+ // authorization_code + refresh_token, and BOTH API callbacks in
34172
+ // redirect_uris (https://api.augmented.team/integrations/oauth/callback
34173
+ // and https://api.ninjafy.com/integrations/oauth/callback). Do not use
34174
+ // scripts/dcr-register.ts: it takes a single --redirect-uri. Store the
34175
+ // returned client id as OAUTH_PLAUD_CLIENT_ID; unset, Connect soft-fails
34176
+ // "not configured". Full procedure: docs/runbooks/plaud-dogfood.md.
34177
+ definitionId: "plaud",
34178
+ authorizeUrl: "https://mcp.plaud.ai/authorize",
34179
+ tokenUrl: "https://mcp.plaud.ai/token",
34180
+ defaultScopes: [],
34181
+ supportsRefresh: true,
34182
+ extraAuthorizeParams: {},
34183
+ clientAuthMethod: "body",
34184
+ pkce: "S256",
34185
+ publicClient: true,
34186
+ mcpUrl: "https://mcp.plaud.ai/mcp",
34187
+ // Curated surface (matches the catalog seed's defined_scopes[].tools).
34188
+ // Plaud advertises NO scopes, so the token is not scope-limited: the
34189
+ // read-only property of this integration rests ENTIRELY on this
34190
+ // allowlist, which the remote-oauth-proxy enforces on tools/list and
34191
+ // tools/call. The five names are Plaud's documented read tools
34192
+ // (https://docs.plaud.ai/plaud-mcp-cli/mcp). `login` and `logout` are
34193
+ // deliberately excluded: sign-in is our OAuth broker's job, and `logout`
34194
+ // revokes the user's authorization, which an agent must never do. The
34195
+ // names come from the docs, not from an authenticated tools/list (that
34196
+ // needs a consented token), and the proxy SKIPS an allowlisted name the
34197
+ // server does not serve, so confirm against the first live tools/list
34198
+ // (runbook Step 3, a gate before customer use).
34199
+ toolAllowlist: ["get_current_user", "list_files", "get_file", "get_note", "get_transcript"]
34200
+ },
34146
34201
  "notion-cli": {
34147
34202
  // Notion's public OAuth app. Tokens are workspace-scoped and long-lived —
34148
34203
  // Notion does not issue refresh_tokens, so `supportsRefresh: false` and
@@ -34599,6 +34654,36 @@ var INTEGRATION_REGISTRY = [
34599
34654
  docs_url: "https://help.otter.ai/hc/en-us/articles/35287607569687-Otter-MCP-Server",
34600
34655
  beta: true
34601
34656
  },
34657
+ {
34658
+ id: "plaud",
34659
+ name: "Plaud",
34660
+ category: "knowledge",
34661
+ description: "Read Plaud recordings: list and search recordings by name or date, and read their AI notes (summary, action items, key topics) and full speaker-labelled transcripts.",
34662
+ // ENG-11543 (CS-2134): same remote streamable-HTTP MCP + OAuth pattern as
34663
+ // Granola/Kajabi/Otter, against Plaud's HOSTED server (https://mcp.plaud.ai/mcp),
34664
+ // not the stdio `npx @plaud-ai/mcp` package. Discovery chain: RFC 9728
34665
+ // protected-resource metadata at mcp.plaud.ai -> RFC 8414 AS metadata on the
34666
+ // same host -> RFC 7591 registration at /register. Auth is OAuth 2.0
34667
+ // authorization-code with PKCE (S256) and a public client registered once by
34668
+ // an operator (docs/runbooks/plaud-dogfood.md -> OAUTH_PLAUD_CLIENT_ID).
34669
+ // Consent is brokered through the shared /integrations/oauth/authorize ->
34670
+ // /callback path, and the token reaches the host via the generic
34671
+ // remote-oauth-proxy (OAUTH_PROVIDERS.plaud.mcpUrl).
34672
+ //
34673
+ // READ-ONLY RESTS ENTIRELY ON THE TOOL ALLOWLIST. Unlike Otter, Plaud
34674
+ // advertises NO scopes_supported, so there is no read scope to request and
34675
+ // the granted token is not scope-limited. What keeps this integration
34676
+ // read-only is OAUTH_PROVIDERS.plaud.toolAllowlist (the five documented
34677
+ // reads), which the proxy enforces on tools/list and tools/call. `login` and
34678
+ // `logout` are excluded; `logout` would revoke the user's authorization.
34679
+ // Anything that widens the allowlist widens what the token can do.
34680
+ supported_auth_types: ["oauth2"],
34681
+ capabilities: [
34682
+ { id: "plaud:read", name: "Read Recordings & Transcripts", description: "List and search recordings by name or date, and read their details, AI notes (summary, action items, key topics) and full transcripts with speaker labels (get_current_user, list_files, get_file, get_note, get_transcript)", access: "read" }
34683
+ ],
34684
+ docs_url: "https://docs.plaud.ai/plaud-mcp-cli/mcp",
34685
+ beta: true
34686
+ },
34602
34687
  {
34603
34688
  id: "anchor-browser",
34604
34689
  name: "Anchor Browser",