@integrity-labs/agt-cli 0.28.1112 → 0.28.1114
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/bin/agt.js +5 -5
- package/dist/{chunk-5EYINOIW.js → chunk-2XQPQOJX.js} +2 -2
- package/dist/chunk-2XQPQOJX.js.map +1 -0
- package/dist/{chunk-TJUDOE53.js → chunk-J3L66T65.js} +194 -22
- package/dist/{chunk-TJUDOE53.js.map → chunk-J3L66T65.js.map} +1 -1
- package/dist/{chunk-NO57I56V.js → chunk-OBZB6MUE.js} +74 -1
- package/dist/chunk-OBZB6MUE.js.map +1 -0
- package/dist/{claude-pair-runtime-CKWLQMAC.js → claude-pair-runtime-2LVLURUE.js} +2 -2
- package/dist/lib/manager-worker.js +17 -16
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +107 -4
- package/dist/mcp/index.js +106 -3
- package/dist/mcp/origami.js +73 -0
- package/dist/mcp/slack-channel.js +110 -7
- package/dist/mcp/teams-channel.js +34 -4
- package/dist/mcp/telegram-channel.js +108 -5
- package/dist/{persistent-session-SDYY75X7.js → persistent-session-TDPGTHTG.js} +3 -3
- package/dist/{responsiveness-probe-NEBHDSMI.js → responsiveness-probe-6P7TB4QA.js} +3 -3
- package/dist/{session-auth-dead-CNV4O7RF.js → session-auth-dead-LMCPZJ4K.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-5EYINOIW.js.map +0 -1
- package/dist/chunk-NO57I56V.js.map +0 -1
- /package/dist/{claude-pair-runtime-CKWLQMAC.js.map → claude-pair-runtime-2LVLURUE.js.map} +0 -0
- /package/dist/{persistent-session-SDYY75X7.js.map → persistent-session-TDPGTHTG.js.map} +0 -0
- /package/dist/{responsiveness-probe-NEBHDSMI.js.map → responsiveness-probe-6P7TB4QA.js.map} +0 -0
- /package/dist/{session-auth-dead-CNV4O7RF.js.map → session-auth-dead-LMCPZJ4K.js.map} +0 -0
|
@@ -33059,6 +33059,51 @@ var OAUTH_PROVIDERS = {
|
|
|
33059
33059
|
}
|
|
33060
33060
|
]
|
|
33061
33061
|
},
|
|
33062
|
+
"otter": {
|
|
33063
|
+
// CS-2029: Otter.ai's official MCP — remote streamable-HTTP at
|
|
33064
|
+
// https://mcp.otter.ai/mcp. Same Granola/Kajabi shape: OAuth 2.0
|
|
33065
|
+
// authorization-code with PKCE (S256) and a public client
|
|
33066
|
+
// (token_endpoint_auth_method 'none') issued via Dynamic Client
|
|
33067
|
+
// Registration (RFC 7591). Values below are taken verbatim from the
|
|
33068
|
+
// metadata, not inferred:
|
|
33069
|
+
// - https://mcp.otter.ai/.well-known/oauth-protected-resource names the
|
|
33070
|
+
// AS as https://otter.ai/ and advertises scopes profile:read,
|
|
33071
|
+
// conversations:read;
|
|
33072
|
+
// - https://otter.ai/.well-known/oauth-authorization-server gives
|
|
33073
|
+
// authorize /oauth2/authorize, token /oauth/token, revoke
|
|
33074
|
+
// /oauth/revoke_token, register /oauth/register, PKCE S256, `none`,
|
|
33075
|
+
// and the refresh_token grant.
|
|
33076
|
+
// NOTE the authorize path is /oauth2/authorize while token/revoke live
|
|
33077
|
+
// under /oauth/ — that is Otter's own split, do not "normalise" it.
|
|
33078
|
+
// The prod client was registered 2026-10-10 against /oauth/register with
|
|
33079
|
+
// scope 'profile:read conversations:read' and BOTH API callbacks,
|
|
33080
|
+
// https://api.augmented.team/... and https://api.ninjafy.com/integrations/oauth/callback,
|
|
33081
|
+
// because redirect_uri follows API_PUBLIC_URL and the ENG-11060 flip makes
|
|
33082
|
+
// the ninjafy name canonical; Otter returns no RFC 7592 handle, so a redirect
|
|
33083
|
+
// cannot be added later without a new client and a re-consent per connection.
|
|
33084
|
+
// OAUTH_OTTER_CLIENT_ID is set from its output (docs/runbooks/otter-dogfood.md). Otter advertises ONLY
|
|
33085
|
+
// read scopes, so this integration is read-only by construction: there is
|
|
33086
|
+
// no write scope to request even by mistake.
|
|
33087
|
+
definitionId: "otter",
|
|
33088
|
+
authorizeUrl: "https://otter.ai/oauth2/authorize",
|
|
33089
|
+
tokenUrl: "https://otter.ai/oauth/token",
|
|
33090
|
+
revokeUrl: "https://otter.ai/oauth/revoke_token",
|
|
33091
|
+
defaultScopes: ["profile:read", "conversations:read"],
|
|
33092
|
+
supportsRefresh: true,
|
|
33093
|
+
extraAuthorizeParams: {},
|
|
33094
|
+
clientAuthMethod: "body",
|
|
33095
|
+
pkce: "S256",
|
|
33096
|
+
publicClient: true,
|
|
33097
|
+
mcpUrl: "https://mcp.otter.ai/mcp",
|
|
33098
|
+
// Curated surface (matches the catalog seed's defined_scopes[].tools).
|
|
33099
|
+
// These are the server's three tools, all read-only. The names are
|
|
33100
|
+
// Otter's own, quoted from the tools' descriptions ("use `otter_search`
|
|
33101
|
+
// first", "call otter_get_user_info() first"), not Composio's wrapped
|
|
33102
|
+
// OTTER_AI_MCP_* slugs. An allowlisted name the server does not advertise
|
|
33103
|
+
// is logged and SKIPPED by the proxy, so confirm against the first live
|
|
33104
|
+
// tools/list after a real consent (runbook Step 3).
|
|
33105
|
+
toolAllowlist: ["otter_get_user_info", "otter_search", "otter_fetch"]
|
|
33106
|
+
},
|
|
33062
33107
|
"notion-cli": {
|
|
33063
33108
|
// Notion's public OAuth app. Tokens are workspace-scoped and long-lived —
|
|
33064
33109
|
// Notion does not issue refresh_tokens, so `supportsRefresh: false` and
|
|
@@ -33692,6 +33737,34 @@ var INTEGRATION_REGISTRY = [
|
|
|
33692
33737
|
docs_url: "https://help.kajabi.com/articles/api-integrations/connect-kajabi-to-claude-or-chatgpt",
|
|
33693
33738
|
beta: true
|
|
33694
33739
|
},
|
|
33740
|
+
{
|
|
33741
|
+
id: "otter",
|
|
33742
|
+
name: "Otter.ai",
|
|
33743
|
+
category: "knowledge",
|
|
33744
|
+
description: "Read Otter.ai meetings: search recordings by date, attendee or topic, and read summaries, action items and full speaker-attributed transcripts.",
|
|
33745
|
+
// CS-2029: same remote streamable-HTTP MCP + OAuth pattern as Granola/Kajabi.
|
|
33746
|
+
// Otter's server implements the MCP discovery chain (RFC 9728 protected-
|
|
33747
|
+
// resource metadata at mcp.otter.ai → RFC 8414 AS metadata at otter.ai →
|
|
33748
|
+
// RFC 7591 registration); auth is OAuth 2.0 authorization-code with PKCE
|
|
33749
|
+
// (S256) and a public client registered via one-time Dynamic Client
|
|
33750
|
+
// Registration (scripts/dcr-register.ts against https://otter.ai/oauth/register
|
|
33751
|
+
// → OAUTH_OTTER_CLIENT_ID, --scope 'profile:read conversations:read').
|
|
33752
|
+
// Consent is brokered by the webapp through the shared
|
|
33753
|
+
// /integrations/oauth/authorize → /callback path, and the access_token
|
|
33754
|
+
// reaches the host via the generic remote-oauth-proxy
|
|
33755
|
+
// (OAUTH_PROVIDERS.otter.mcpUrl). Read-only by construction: Otter
|
|
33756
|
+
// advertises no write scope.
|
|
33757
|
+
supported_auth_types: ["oauth2"],
|
|
33758
|
+
capabilities: [
|
|
33759
|
+
{ id: "otter:read", name: "Read Meetings & Transcripts", description: "Find recorded meetings by date, attendee, topic or title, and read their summaries, action items, outlines and full transcripts (otter_get_user_info, otter_search, otter_fetch)", access: "read" }
|
|
33760
|
+
],
|
|
33761
|
+
// Otter's own Help Center article for the MCP server (CodeRabbit, #6906). It
|
|
33762
|
+
// exists even though help.otter.ai answers 403 to non-browser clients; the
|
|
33763
|
+
// help-centre API confirmed it (title "Otter MCP Server"). The MCP endpoint
|
|
33764
|
+
// itself is a JSON-RPC URL, not a page (Obi Wan 8305072d5414).
|
|
33765
|
+
docs_url: "https://help.otter.ai/hc/en-us/articles/35287607569687-Otter-MCP-Server",
|
|
33766
|
+
beta: true
|
|
33767
|
+
},
|
|
33695
33768
|
{
|
|
33696
33769
|
id: "anchor-browser",
|
|
33697
33770
|
name: "Anchor Browser",
|
|
@@ -39777,8 +39850,38 @@ import { join as join10 } from "path";
|
|
|
39777
39850
|
import { existsSync as existsSync4, readFileSync as readFileSync8 } from "fs";
|
|
39778
39851
|
import { homedir as homedir2 } from "os";
|
|
39779
39852
|
import { join as join9 } from "path";
|
|
39780
|
-
function
|
|
39781
|
-
|
|
39853
|
+
function hasUsableFlags(path) {
|
|
39854
|
+
try {
|
|
39855
|
+
if (!existsSync4(path)) return false;
|
|
39856
|
+
const parsed = JSON.parse(readFileSync8(path, "utf8"));
|
|
39857
|
+
if (!parsed || typeof parsed !== "object") return false;
|
|
39858
|
+
const flags = parsed.flags;
|
|
39859
|
+
return !!flags && typeof flags === "object" && !Array.isArray(flags);
|
|
39860
|
+
} catch {
|
|
39861
|
+
return false;
|
|
39862
|
+
}
|
|
39863
|
+
}
|
|
39864
|
+
function cacheUpdatedAt(path) {
|
|
39865
|
+
try {
|
|
39866
|
+
if (!existsSync4(path)) return void 0;
|
|
39867
|
+
const parsed = JSON.parse(readFileSync8(path, "utf8"));
|
|
39868
|
+
if (!parsed || typeof parsed !== "object") return void 0;
|
|
39869
|
+
const u = parsed.updated_at;
|
|
39870
|
+
return typeof u === "string" && u.length > 0 ? u : void 0;
|
|
39871
|
+
} catch {
|
|
39872
|
+
return void 0;
|
|
39873
|
+
}
|
|
39874
|
+
}
|
|
39875
|
+
function defaultFlagsCachePath(env2 = process.env) {
|
|
39876
|
+
const hostWide = join9(homedir2(), ".augmented", "flags-cache.json");
|
|
39877
|
+
const agentId = env2["AGT_AGENT_ID"]?.trim();
|
|
39878
|
+
if (!agentId) return hostWide;
|
|
39879
|
+
const perAgent = join9(homedir2(), ".augmented", agentId, "flags-cache.json");
|
|
39880
|
+
if (!hasUsableFlags(perAgent)) return hostWide;
|
|
39881
|
+
const hostWideAt = cacheUpdatedAt(hostWide);
|
|
39882
|
+
const perAgentAt = cacheUpdatedAt(perAgent);
|
|
39883
|
+
if (hostWideAt && (!perAgentAt || perAgentAt < hostWideAt)) return hostWide;
|
|
39884
|
+
return perAgent;
|
|
39782
39885
|
}
|
|
39783
39886
|
function envBoolean(raw) {
|
|
39784
39887
|
if (raw === void 0) return void 0;
|
|
@@ -39805,7 +39908,7 @@ function resolveHostBooleanFlag(opts) {
|
|
|
39805
39908
|
const env2 = opts.env ?? process.env;
|
|
39806
39909
|
const envValue = envBoolean(env2[opts.envVar]);
|
|
39807
39910
|
if (envValue !== void 0) return envValue;
|
|
39808
|
-
const cached2 = cachedBoolean(opts.key, opts.cachePath ?? defaultFlagsCachePath());
|
|
39911
|
+
const cached2 = cachedBoolean(opts.key, opts.cachePath ?? defaultFlagsCachePath(env2));
|
|
39809
39912
|
if (cached2 !== void 0) return cached2;
|
|
39810
39913
|
return opts.defaultValue;
|
|
39811
39914
|
}
|
|
@@ -39836,7 +39939,7 @@ function cachedMaintenanceMode(path) {
|
|
|
39836
39939
|
}
|
|
39837
39940
|
}
|
|
39838
39941
|
function resolveMaintenanceMode(opts) {
|
|
39839
|
-
const cached2 = cachedMaintenanceMode(opts?.cachePath ?? defaultFlagsCachePath());
|
|
39942
|
+
const cached2 = cachedMaintenanceMode(opts?.cachePath ?? defaultFlagsCachePath(opts?.env));
|
|
39840
39943
|
if (cached2 !== void 0) return cached2;
|
|
39841
39944
|
return "off";
|
|
39842
39945
|
}
|
package/dist/mcp/index.js
CHANGED
|
@@ -25562,6 +25562,51 @@ var OAUTH_PROVIDERS = {
|
|
|
25562
25562
|
}
|
|
25563
25563
|
]
|
|
25564
25564
|
},
|
|
25565
|
+
"otter": {
|
|
25566
|
+
// CS-2029: Otter.ai's official MCP — remote streamable-HTTP at
|
|
25567
|
+
// https://mcp.otter.ai/mcp. Same Granola/Kajabi shape: OAuth 2.0
|
|
25568
|
+
// authorization-code with PKCE (S256) and a public client
|
|
25569
|
+
// (token_endpoint_auth_method 'none') issued via Dynamic Client
|
|
25570
|
+
// Registration (RFC 7591). Values below are taken verbatim from the
|
|
25571
|
+
// metadata, not inferred:
|
|
25572
|
+
// - https://mcp.otter.ai/.well-known/oauth-protected-resource names the
|
|
25573
|
+
// AS as https://otter.ai/ and advertises scopes profile:read,
|
|
25574
|
+
// conversations:read;
|
|
25575
|
+
// - https://otter.ai/.well-known/oauth-authorization-server gives
|
|
25576
|
+
// authorize /oauth2/authorize, token /oauth/token, revoke
|
|
25577
|
+
// /oauth/revoke_token, register /oauth/register, PKCE S256, `none`,
|
|
25578
|
+
// and the refresh_token grant.
|
|
25579
|
+
// NOTE the authorize path is /oauth2/authorize while token/revoke live
|
|
25580
|
+
// under /oauth/ — that is Otter's own split, do not "normalise" it.
|
|
25581
|
+
// The prod client was registered 2026-10-10 against /oauth/register with
|
|
25582
|
+
// scope 'profile:read conversations:read' and BOTH API callbacks,
|
|
25583
|
+
// https://api.augmented.team/... and https://api.ninjafy.com/integrations/oauth/callback,
|
|
25584
|
+
// because redirect_uri follows API_PUBLIC_URL and the ENG-11060 flip makes
|
|
25585
|
+
// the ninjafy name canonical; Otter returns no RFC 7592 handle, so a redirect
|
|
25586
|
+
// cannot be added later without a new client and a re-consent per connection.
|
|
25587
|
+
// OAUTH_OTTER_CLIENT_ID is set from its output (docs/runbooks/otter-dogfood.md). Otter advertises ONLY
|
|
25588
|
+
// read scopes, so this integration is read-only by construction: there is
|
|
25589
|
+
// no write scope to request even by mistake.
|
|
25590
|
+
definitionId: "otter",
|
|
25591
|
+
authorizeUrl: "https://otter.ai/oauth2/authorize",
|
|
25592
|
+
tokenUrl: "https://otter.ai/oauth/token",
|
|
25593
|
+
revokeUrl: "https://otter.ai/oauth/revoke_token",
|
|
25594
|
+
defaultScopes: ["profile:read", "conversations:read"],
|
|
25595
|
+
supportsRefresh: true,
|
|
25596
|
+
extraAuthorizeParams: {},
|
|
25597
|
+
clientAuthMethod: "body",
|
|
25598
|
+
pkce: "S256",
|
|
25599
|
+
publicClient: true,
|
|
25600
|
+
mcpUrl: "https://mcp.otter.ai/mcp",
|
|
25601
|
+
// Curated surface (matches the catalog seed's defined_scopes[].tools).
|
|
25602
|
+
// These are the server's three tools, all read-only. The names are
|
|
25603
|
+
// Otter's own, quoted from the tools' descriptions ("use `otter_search`
|
|
25604
|
+
// first", "call otter_get_user_info() first"), not Composio's wrapped
|
|
25605
|
+
// OTTER_AI_MCP_* slugs. An allowlisted name the server does not advertise
|
|
25606
|
+
// is logged and SKIPPED by the proxy, so confirm against the first live
|
|
25607
|
+
// tools/list after a real consent (runbook Step 3).
|
|
25608
|
+
toolAllowlist: ["otter_get_user_info", "otter_search", "otter_fetch"]
|
|
25609
|
+
},
|
|
25565
25610
|
"notion-cli": {
|
|
25566
25611
|
// Notion's public OAuth app. Tokens are workspace-scoped and long-lived —
|
|
25567
25612
|
// Notion does not issue refresh_tokens, so `supportsRefresh: false` and
|
|
@@ -26195,6 +26240,34 @@ var INTEGRATION_REGISTRY = [
|
|
|
26195
26240
|
docs_url: "https://help.kajabi.com/articles/api-integrations/connect-kajabi-to-claude-or-chatgpt",
|
|
26196
26241
|
beta: true
|
|
26197
26242
|
},
|
|
26243
|
+
{
|
|
26244
|
+
id: "otter",
|
|
26245
|
+
name: "Otter.ai",
|
|
26246
|
+
category: "knowledge",
|
|
26247
|
+
description: "Read Otter.ai meetings: search recordings by date, attendee or topic, and read summaries, action items and full speaker-attributed transcripts.",
|
|
26248
|
+
// CS-2029: same remote streamable-HTTP MCP + OAuth pattern as Granola/Kajabi.
|
|
26249
|
+
// Otter's server implements the MCP discovery chain (RFC 9728 protected-
|
|
26250
|
+
// resource metadata at mcp.otter.ai → RFC 8414 AS metadata at otter.ai →
|
|
26251
|
+
// RFC 7591 registration); auth is OAuth 2.0 authorization-code with PKCE
|
|
26252
|
+
// (S256) and a public client registered via one-time Dynamic Client
|
|
26253
|
+
// Registration (scripts/dcr-register.ts against https://otter.ai/oauth/register
|
|
26254
|
+
// → OAUTH_OTTER_CLIENT_ID, --scope 'profile:read conversations:read').
|
|
26255
|
+
// Consent is brokered by the webapp through the shared
|
|
26256
|
+
// /integrations/oauth/authorize → /callback path, and the access_token
|
|
26257
|
+
// reaches the host via the generic remote-oauth-proxy
|
|
26258
|
+
// (OAUTH_PROVIDERS.otter.mcpUrl). Read-only by construction: Otter
|
|
26259
|
+
// advertises no write scope.
|
|
26260
|
+
supported_auth_types: ["oauth2"],
|
|
26261
|
+
capabilities: [
|
|
26262
|
+
{ id: "otter:read", name: "Read Meetings & Transcripts", description: "Find recorded meetings by date, attendee, topic or title, and read their summaries, action items, outlines and full transcripts (otter_get_user_info, otter_search, otter_fetch)", access: "read" }
|
|
26263
|
+
],
|
|
26264
|
+
// Otter's own Help Center article for the MCP server (CodeRabbit, #6906). It
|
|
26265
|
+
// exists even though help.otter.ai answers 403 to non-browser clients; the
|
|
26266
|
+
// help-centre API confirmed it (title "Otter MCP Server"). The MCP endpoint
|
|
26267
|
+
// itself is a JSON-RPC URL, not a page (Obi Wan 8305072d5414).
|
|
26268
|
+
docs_url: "https://help.otter.ai/hc/en-us/articles/35287607569687-Otter-MCP-Server",
|
|
26269
|
+
beta: true
|
|
26270
|
+
},
|
|
26198
26271
|
{
|
|
26199
26272
|
id: "anchor-browser",
|
|
26200
26273
|
name: "Anchor Browser",
|
|
@@ -46116,8 +46189,38 @@ var StdioServerTransport = class {
|
|
|
46116
46189
|
import { existsSync as existsSync2, readFileSync as readFileSync4 } from "fs";
|
|
46117
46190
|
import { homedir as homedir2 } from "os";
|
|
46118
46191
|
import { join as join6 } from "path";
|
|
46119
|
-
function
|
|
46120
|
-
|
|
46192
|
+
function hasUsableFlags(path) {
|
|
46193
|
+
try {
|
|
46194
|
+
if (!existsSync2(path)) return false;
|
|
46195
|
+
const parsed = JSON.parse(readFileSync4(path, "utf8"));
|
|
46196
|
+
if (!parsed || typeof parsed !== "object") return false;
|
|
46197
|
+
const flags = parsed.flags;
|
|
46198
|
+
return !!flags && typeof flags === "object" && !Array.isArray(flags);
|
|
46199
|
+
} catch {
|
|
46200
|
+
return false;
|
|
46201
|
+
}
|
|
46202
|
+
}
|
|
46203
|
+
function cacheUpdatedAt(path) {
|
|
46204
|
+
try {
|
|
46205
|
+
if (!existsSync2(path)) return void 0;
|
|
46206
|
+
const parsed = JSON.parse(readFileSync4(path, "utf8"));
|
|
46207
|
+
if (!parsed || typeof parsed !== "object") return void 0;
|
|
46208
|
+
const u = parsed.updated_at;
|
|
46209
|
+
return typeof u === "string" && u.length > 0 ? u : void 0;
|
|
46210
|
+
} catch {
|
|
46211
|
+
return void 0;
|
|
46212
|
+
}
|
|
46213
|
+
}
|
|
46214
|
+
function defaultFlagsCachePath(env2 = process.env) {
|
|
46215
|
+
const hostWide = join6(homedir2(), ".augmented", "flags-cache.json");
|
|
46216
|
+
const agentId = env2["AGT_AGENT_ID"]?.trim();
|
|
46217
|
+
if (!agentId) return hostWide;
|
|
46218
|
+
const perAgent = join6(homedir2(), ".augmented", agentId, "flags-cache.json");
|
|
46219
|
+
if (!hasUsableFlags(perAgent)) return hostWide;
|
|
46220
|
+
const hostWideAt = cacheUpdatedAt(hostWide);
|
|
46221
|
+
const perAgentAt = cacheUpdatedAt(perAgent);
|
|
46222
|
+
if (hostWideAt && (!perAgentAt || perAgentAt < hostWideAt)) return hostWide;
|
|
46223
|
+
return perAgent;
|
|
46121
46224
|
}
|
|
46122
46225
|
function envBoolean(raw) {
|
|
46123
46226
|
if (raw === void 0) return void 0;
|
|
@@ -46154,7 +46257,7 @@ function cachedMaintenanceMode(path) {
|
|
|
46154
46257
|
}
|
|
46155
46258
|
}
|
|
46156
46259
|
function resolveMaintenanceMode(opts) {
|
|
46157
|
-
const cached2 = cachedMaintenanceMode(opts?.cachePath ?? defaultFlagsCachePath());
|
|
46260
|
+
const cached2 = cachedMaintenanceMode(opts?.cachePath ?? defaultFlagsCachePath(opts?.env));
|
|
46158
46261
|
if (cached2 !== void 0) return cached2;
|
|
46159
46262
|
return "off";
|
|
46160
46263
|
}
|
package/dist/mcp/origami.js
CHANGED
|
@@ -39711,6 +39711,51 @@ var OAUTH_PROVIDERS = {
|
|
|
39711
39711
|
}
|
|
39712
39712
|
]
|
|
39713
39713
|
},
|
|
39714
|
+
"otter": {
|
|
39715
|
+
// CS-2029: Otter.ai's official MCP — remote streamable-HTTP at
|
|
39716
|
+
// https://mcp.otter.ai/mcp. Same Granola/Kajabi shape: OAuth 2.0
|
|
39717
|
+
// authorization-code with PKCE (S256) and a public client
|
|
39718
|
+
// (token_endpoint_auth_method 'none') issued via Dynamic Client
|
|
39719
|
+
// Registration (RFC 7591). Values below are taken verbatim from the
|
|
39720
|
+
// metadata, not inferred:
|
|
39721
|
+
// - https://mcp.otter.ai/.well-known/oauth-protected-resource names the
|
|
39722
|
+
// AS as https://otter.ai/ and advertises scopes profile:read,
|
|
39723
|
+
// conversations:read;
|
|
39724
|
+
// - https://otter.ai/.well-known/oauth-authorization-server gives
|
|
39725
|
+
// authorize /oauth2/authorize, token /oauth/token, revoke
|
|
39726
|
+
// /oauth/revoke_token, register /oauth/register, PKCE S256, `none`,
|
|
39727
|
+
// and the refresh_token grant.
|
|
39728
|
+
// NOTE the authorize path is /oauth2/authorize while token/revoke live
|
|
39729
|
+
// under /oauth/ — that is Otter's own split, do not "normalise" it.
|
|
39730
|
+
// The prod client was registered 2026-10-10 against /oauth/register with
|
|
39731
|
+
// scope 'profile:read conversations:read' and BOTH API callbacks,
|
|
39732
|
+
// https://api.augmented.team/... and https://api.ninjafy.com/integrations/oauth/callback,
|
|
39733
|
+
// because redirect_uri follows API_PUBLIC_URL and the ENG-11060 flip makes
|
|
39734
|
+
// the ninjafy name canonical; Otter returns no RFC 7592 handle, so a redirect
|
|
39735
|
+
// cannot be added later without a new client and a re-consent per connection.
|
|
39736
|
+
// OAUTH_OTTER_CLIENT_ID is set from its output (docs/runbooks/otter-dogfood.md). Otter advertises ONLY
|
|
39737
|
+
// read scopes, so this integration is read-only by construction: there is
|
|
39738
|
+
// no write scope to request even by mistake.
|
|
39739
|
+
definitionId: "otter",
|
|
39740
|
+
authorizeUrl: "https://otter.ai/oauth2/authorize",
|
|
39741
|
+
tokenUrl: "https://otter.ai/oauth/token",
|
|
39742
|
+
revokeUrl: "https://otter.ai/oauth/revoke_token",
|
|
39743
|
+
defaultScopes: ["profile:read", "conversations:read"],
|
|
39744
|
+
supportsRefresh: true,
|
|
39745
|
+
extraAuthorizeParams: {},
|
|
39746
|
+
clientAuthMethod: "body",
|
|
39747
|
+
pkce: "S256",
|
|
39748
|
+
publicClient: true,
|
|
39749
|
+
mcpUrl: "https://mcp.otter.ai/mcp",
|
|
39750
|
+
// Curated surface (matches the catalog seed's defined_scopes[].tools).
|
|
39751
|
+
// These are the server's three tools, all read-only. The names are
|
|
39752
|
+
// Otter's own, quoted from the tools' descriptions ("use `otter_search`
|
|
39753
|
+
// first", "call otter_get_user_info() first"), not Composio's wrapped
|
|
39754
|
+
// OTTER_AI_MCP_* slugs. An allowlisted name the server does not advertise
|
|
39755
|
+
// is logged and SKIPPED by the proxy, so confirm against the first live
|
|
39756
|
+
// tools/list after a real consent (runbook Step 3).
|
|
39757
|
+
toolAllowlist: ["otter_get_user_info", "otter_search", "otter_fetch"]
|
|
39758
|
+
},
|
|
39714
39759
|
"notion-cli": {
|
|
39715
39760
|
// Notion's public OAuth app. Tokens are workspace-scoped and long-lived —
|
|
39716
39761
|
// Notion does not issue refresh_tokens, so `supportsRefresh: false` and
|
|
@@ -40344,6 +40389,34 @@ var INTEGRATION_REGISTRY = [
|
|
|
40344
40389
|
docs_url: "https://help.kajabi.com/articles/api-integrations/connect-kajabi-to-claude-or-chatgpt",
|
|
40345
40390
|
beta: true
|
|
40346
40391
|
},
|
|
40392
|
+
{
|
|
40393
|
+
id: "otter",
|
|
40394
|
+
name: "Otter.ai",
|
|
40395
|
+
category: "knowledge",
|
|
40396
|
+
description: "Read Otter.ai meetings: search recordings by date, attendee or topic, and read summaries, action items and full speaker-attributed transcripts.",
|
|
40397
|
+
// CS-2029: same remote streamable-HTTP MCP + OAuth pattern as Granola/Kajabi.
|
|
40398
|
+
// Otter's server implements the MCP discovery chain (RFC 9728 protected-
|
|
40399
|
+
// resource metadata at mcp.otter.ai → RFC 8414 AS metadata at otter.ai →
|
|
40400
|
+
// RFC 7591 registration); auth is OAuth 2.0 authorization-code with PKCE
|
|
40401
|
+
// (S256) and a public client registered via one-time Dynamic Client
|
|
40402
|
+
// Registration (scripts/dcr-register.ts against https://otter.ai/oauth/register
|
|
40403
|
+
// → OAUTH_OTTER_CLIENT_ID, --scope 'profile:read conversations:read').
|
|
40404
|
+
// Consent is brokered by the webapp through the shared
|
|
40405
|
+
// /integrations/oauth/authorize → /callback path, and the access_token
|
|
40406
|
+
// reaches the host via the generic remote-oauth-proxy
|
|
40407
|
+
// (OAUTH_PROVIDERS.otter.mcpUrl). Read-only by construction: Otter
|
|
40408
|
+
// advertises no write scope.
|
|
40409
|
+
supported_auth_types: ["oauth2"],
|
|
40410
|
+
capabilities: [
|
|
40411
|
+
{ id: "otter:read", name: "Read Meetings & Transcripts", description: "Find recorded meetings by date, attendee, topic or title, and read their summaries, action items, outlines and full transcripts (otter_get_user_info, otter_search, otter_fetch)", access: "read" }
|
|
40412
|
+
],
|
|
40413
|
+
// Otter's own Help Center article for the MCP server (CodeRabbit, #6906). It
|
|
40414
|
+
// exists even though help.otter.ai answers 403 to non-browser clients; the
|
|
40415
|
+
// help-centre API confirmed it (title "Otter MCP Server"). The MCP endpoint
|
|
40416
|
+
// itself is a JSON-RPC URL, not a page (Obi Wan 8305072d5414).
|
|
40417
|
+
docs_url: "https://help.otter.ai/hc/en-us/articles/35287607569687-Otter-MCP-Server",
|
|
40418
|
+
beta: true
|
|
40419
|
+
},
|
|
40347
40420
|
{
|
|
40348
40421
|
id: "anchor-browser",
|
|
40349
40422
|
name: "Anchor Browser",
|
|
@@ -30673,8 +30673,38 @@ function isSlackDirectMessage(channelId) {
|
|
|
30673
30673
|
import { existsSync, readFileSync } from "fs";
|
|
30674
30674
|
import { homedir } from "os";
|
|
30675
30675
|
import { join } from "path";
|
|
30676
|
-
function
|
|
30677
|
-
|
|
30676
|
+
function hasUsableFlags(path) {
|
|
30677
|
+
try {
|
|
30678
|
+
if (!existsSync(path)) return false;
|
|
30679
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
30680
|
+
if (!parsed || typeof parsed !== "object") return false;
|
|
30681
|
+
const flags = parsed.flags;
|
|
30682
|
+
return !!flags && typeof flags === "object" && !Array.isArray(flags);
|
|
30683
|
+
} catch {
|
|
30684
|
+
return false;
|
|
30685
|
+
}
|
|
30686
|
+
}
|
|
30687
|
+
function cacheUpdatedAt(path) {
|
|
30688
|
+
try {
|
|
30689
|
+
if (!existsSync(path)) return void 0;
|
|
30690
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
30691
|
+
if (!parsed || typeof parsed !== "object") return void 0;
|
|
30692
|
+
const u = parsed.updated_at;
|
|
30693
|
+
return typeof u === "string" && u.length > 0 ? u : void 0;
|
|
30694
|
+
} catch {
|
|
30695
|
+
return void 0;
|
|
30696
|
+
}
|
|
30697
|
+
}
|
|
30698
|
+
function defaultFlagsCachePath(env2 = process.env) {
|
|
30699
|
+
const hostWide = join(homedir(), ".augmented", "flags-cache.json");
|
|
30700
|
+
const agentId = env2["AGT_AGENT_ID"]?.trim();
|
|
30701
|
+
if (!agentId) return hostWide;
|
|
30702
|
+
const perAgent = join(homedir(), ".augmented", agentId, "flags-cache.json");
|
|
30703
|
+
if (!hasUsableFlags(perAgent)) return hostWide;
|
|
30704
|
+
const hostWideAt = cacheUpdatedAt(hostWide);
|
|
30705
|
+
const perAgentAt = cacheUpdatedAt(perAgent);
|
|
30706
|
+
if (hostWideAt && (!perAgentAt || perAgentAt < hostWideAt)) return hostWide;
|
|
30707
|
+
return perAgent;
|
|
30678
30708
|
}
|
|
30679
30709
|
function envBoolean(raw) {
|
|
30680
30710
|
if (raw === void 0) return void 0;
|
|
@@ -30701,7 +30731,7 @@ function resolveHostBooleanFlag(opts) {
|
|
|
30701
30731
|
const env2 = opts.env ?? process.env;
|
|
30702
30732
|
const envValue = envBoolean(env2[opts.envVar]);
|
|
30703
30733
|
if (envValue !== void 0) return envValue;
|
|
30704
|
-
const cached2 = cachedBoolean(opts.key, opts.cachePath ?? defaultFlagsCachePath());
|
|
30734
|
+
const cached2 = cachedBoolean(opts.key, opts.cachePath ?? defaultFlagsCachePath(env2));
|
|
30705
30735
|
if (cached2 !== void 0) return cached2;
|
|
30706
30736
|
return opts.defaultValue;
|
|
30707
30737
|
}
|
|
@@ -30737,7 +30767,7 @@ function resolveGhostReplyMode(opts) {
|
|
|
30737
30767
|
if (modeOverride !== void 0) return modeOverride;
|
|
30738
30768
|
const legacyOverride = parseGhostReplyMode(env2["AGT_GHOST_REPLY_INTENT_CLASSIFIER_ENABLED"]);
|
|
30739
30769
|
if (legacyOverride !== void 0) return legacyOverride;
|
|
30740
|
-
const cached2 = cachedGhostReplyMode(opts?.cachePath ?? defaultFlagsCachePath());
|
|
30770
|
+
const cached2 = cachedGhostReplyMode(opts?.cachePath ?? defaultFlagsCachePath(env2));
|
|
30741
30771
|
if (cached2 !== void 0) return cached2;
|
|
30742
30772
|
return "off";
|
|
30743
30773
|
}
|
|
@@ -30768,7 +30798,7 @@ function cachedMaintenanceMode(path) {
|
|
|
30768
30798
|
}
|
|
30769
30799
|
}
|
|
30770
30800
|
function resolveMaintenanceMode(opts) {
|
|
30771
|
-
const cached2 = cachedMaintenanceMode(opts?.cachePath ?? defaultFlagsCachePath());
|
|
30801
|
+
const cached2 = cachedMaintenanceMode(opts?.cachePath ?? defaultFlagsCachePath(opts?.env));
|
|
30772
30802
|
if (cached2 !== void 0) return cached2;
|
|
30773
30803
|
return "off";
|
|
30774
30804
|
}
|
|
@@ -30802,7 +30832,7 @@ function resolveSlackHotThreadMode(opts) {
|
|
|
30802
30832
|
const env2 = opts?.env ?? process.env;
|
|
30803
30833
|
const modeOverride = parseSlackHotThreadMode(env2["AGT_SLACK_HOT_THREAD_GUARD_MODE"]);
|
|
30804
30834
|
if (modeOverride !== void 0) return modeOverride;
|
|
30805
|
-
const cached2 = cachedSlackHotThreadMode(opts?.cachePath ?? defaultFlagsCachePath());
|
|
30835
|
+
const cached2 = cachedSlackHotThreadMode(opts?.cachePath ?? defaultFlagsCachePath(env2));
|
|
30806
30836
|
if (cached2 !== void 0) return cached2;
|
|
30807
30837
|
return "off";
|
|
30808
30838
|
}
|
|
@@ -30838,7 +30868,7 @@ function resolveSlackScheduledChannelGuardMode(opts) {
|
|
|
30838
30868
|
env2["AGT_SLACK_SCHEDULED_CHANNEL_GUARD_MODE"]
|
|
30839
30869
|
);
|
|
30840
30870
|
if (modeOverride !== void 0) return modeOverride;
|
|
30841
|
-
const cached2 = cachedSlackScheduledChannelGuardMode(opts?.cachePath ?? defaultFlagsCachePath());
|
|
30871
|
+
const cached2 = cachedSlackScheduledChannelGuardMode(opts?.cachePath ?? defaultFlagsCachePath(env2));
|
|
30842
30872
|
if (cached2 !== void 0) return cached2;
|
|
30843
30873
|
return "shadow";
|
|
30844
30874
|
}
|
|
@@ -34068,6 +34098,51 @@ var OAUTH_PROVIDERS = {
|
|
|
34068
34098
|
}
|
|
34069
34099
|
]
|
|
34070
34100
|
},
|
|
34101
|
+
"otter": {
|
|
34102
|
+
// CS-2029: Otter.ai's official MCP — remote streamable-HTTP at
|
|
34103
|
+
// https://mcp.otter.ai/mcp. Same Granola/Kajabi shape: OAuth 2.0
|
|
34104
|
+
// authorization-code with PKCE (S256) and a public client
|
|
34105
|
+
// (token_endpoint_auth_method 'none') issued via Dynamic Client
|
|
34106
|
+
// Registration (RFC 7591). Values below are taken verbatim from the
|
|
34107
|
+
// metadata, not inferred:
|
|
34108
|
+
// - https://mcp.otter.ai/.well-known/oauth-protected-resource names the
|
|
34109
|
+
// AS as https://otter.ai/ and advertises scopes profile:read,
|
|
34110
|
+
// conversations:read;
|
|
34111
|
+
// - https://otter.ai/.well-known/oauth-authorization-server gives
|
|
34112
|
+
// authorize /oauth2/authorize, token /oauth/token, revoke
|
|
34113
|
+
// /oauth/revoke_token, register /oauth/register, PKCE S256, `none`,
|
|
34114
|
+
// and the refresh_token grant.
|
|
34115
|
+
// NOTE the authorize path is /oauth2/authorize while token/revoke live
|
|
34116
|
+
// under /oauth/ — that is Otter's own split, do not "normalise" it.
|
|
34117
|
+
// The prod client was registered 2026-10-10 against /oauth/register with
|
|
34118
|
+
// scope 'profile:read conversations:read' and BOTH API callbacks,
|
|
34119
|
+
// https://api.augmented.team/... and https://api.ninjafy.com/integrations/oauth/callback,
|
|
34120
|
+
// because redirect_uri follows API_PUBLIC_URL and the ENG-11060 flip makes
|
|
34121
|
+
// the ninjafy name canonical; Otter returns no RFC 7592 handle, so a redirect
|
|
34122
|
+
// cannot be added later without a new client and a re-consent per connection.
|
|
34123
|
+
// OAUTH_OTTER_CLIENT_ID is set from its output (docs/runbooks/otter-dogfood.md). Otter advertises ONLY
|
|
34124
|
+
// read scopes, so this integration is read-only by construction: there is
|
|
34125
|
+
// no write scope to request even by mistake.
|
|
34126
|
+
definitionId: "otter",
|
|
34127
|
+
authorizeUrl: "https://otter.ai/oauth2/authorize",
|
|
34128
|
+
tokenUrl: "https://otter.ai/oauth/token",
|
|
34129
|
+
revokeUrl: "https://otter.ai/oauth/revoke_token",
|
|
34130
|
+
defaultScopes: ["profile:read", "conversations:read"],
|
|
34131
|
+
supportsRefresh: true,
|
|
34132
|
+
extraAuthorizeParams: {},
|
|
34133
|
+
clientAuthMethod: "body",
|
|
34134
|
+
pkce: "S256",
|
|
34135
|
+
publicClient: true,
|
|
34136
|
+
mcpUrl: "https://mcp.otter.ai/mcp",
|
|
34137
|
+
// Curated surface (matches the catalog seed's defined_scopes[].tools).
|
|
34138
|
+
// These are the server's three tools, all read-only. The names are
|
|
34139
|
+
// Otter's own, quoted from the tools' descriptions ("use `otter_search`
|
|
34140
|
+
// first", "call otter_get_user_info() first"), not Composio's wrapped
|
|
34141
|
+
// OTTER_AI_MCP_* slugs. An allowlisted name the server does not advertise
|
|
34142
|
+
// is logged and SKIPPED by the proxy, so confirm against the first live
|
|
34143
|
+
// tools/list after a real consent (runbook Step 3).
|
|
34144
|
+
toolAllowlist: ["otter_get_user_info", "otter_search", "otter_fetch"]
|
|
34145
|
+
},
|
|
34071
34146
|
"notion-cli": {
|
|
34072
34147
|
// Notion's public OAuth app. Tokens are workspace-scoped and long-lived —
|
|
34073
34148
|
// Notion does not issue refresh_tokens, so `supportsRefresh: false` and
|
|
@@ -34707,6 +34782,34 @@ var INTEGRATION_REGISTRY = [
|
|
|
34707
34782
|
docs_url: "https://help.kajabi.com/articles/api-integrations/connect-kajabi-to-claude-or-chatgpt",
|
|
34708
34783
|
beta: true
|
|
34709
34784
|
},
|
|
34785
|
+
{
|
|
34786
|
+
id: "otter",
|
|
34787
|
+
name: "Otter.ai",
|
|
34788
|
+
category: "knowledge",
|
|
34789
|
+
description: "Read Otter.ai meetings: search recordings by date, attendee or topic, and read summaries, action items and full speaker-attributed transcripts.",
|
|
34790
|
+
// CS-2029: same remote streamable-HTTP MCP + OAuth pattern as Granola/Kajabi.
|
|
34791
|
+
// Otter's server implements the MCP discovery chain (RFC 9728 protected-
|
|
34792
|
+
// resource metadata at mcp.otter.ai → RFC 8414 AS metadata at otter.ai →
|
|
34793
|
+
// RFC 7591 registration); auth is OAuth 2.0 authorization-code with PKCE
|
|
34794
|
+
// (S256) and a public client registered via one-time Dynamic Client
|
|
34795
|
+
// Registration (scripts/dcr-register.ts against https://otter.ai/oauth/register
|
|
34796
|
+
// → OAUTH_OTTER_CLIENT_ID, --scope 'profile:read conversations:read').
|
|
34797
|
+
// Consent is brokered by the webapp through the shared
|
|
34798
|
+
// /integrations/oauth/authorize → /callback path, and the access_token
|
|
34799
|
+
// reaches the host via the generic remote-oauth-proxy
|
|
34800
|
+
// (OAUTH_PROVIDERS.otter.mcpUrl). Read-only by construction: Otter
|
|
34801
|
+
// advertises no write scope.
|
|
34802
|
+
supported_auth_types: ["oauth2"],
|
|
34803
|
+
capabilities: [
|
|
34804
|
+
{ id: "otter:read", name: "Read Meetings & Transcripts", description: "Find recorded meetings by date, attendee, topic or title, and read their summaries, action items, outlines and full transcripts (otter_get_user_info, otter_search, otter_fetch)", access: "read" }
|
|
34805
|
+
],
|
|
34806
|
+
// Otter's own Help Center article for the MCP server (CodeRabbit, #6906). It
|
|
34807
|
+
// exists even though help.otter.ai answers 403 to non-browser clients; the
|
|
34808
|
+
// help-centre API confirmed it (title "Otter MCP Server"). The MCP endpoint
|
|
34809
|
+
// itself is a JSON-RPC URL, not a page (Obi Wan 8305072d5414).
|
|
34810
|
+
docs_url: "https://help.otter.ai/hc/en-us/articles/35287607569687-Otter-MCP-Server",
|
|
34811
|
+
beta: true
|
|
34812
|
+
},
|
|
34710
34813
|
{
|
|
34711
34814
|
id: "anchor-browser",
|
|
34712
34815
|
name: "Anchor Browser",
|
|
@@ -14169,8 +14169,38 @@ function emitToolCallMarkupRedactionTelemetry(channel) {
|
|
|
14169
14169
|
import { existsSync, readFileSync } from "fs";
|
|
14170
14170
|
import { homedir } from "os";
|
|
14171
14171
|
import { join } from "path";
|
|
14172
|
-
function
|
|
14173
|
-
|
|
14172
|
+
function hasUsableFlags(path) {
|
|
14173
|
+
try {
|
|
14174
|
+
if (!existsSync(path)) return false;
|
|
14175
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
14176
|
+
if (!parsed || typeof parsed !== "object") return false;
|
|
14177
|
+
const flags = parsed.flags;
|
|
14178
|
+
return !!flags && typeof flags === "object" && !Array.isArray(flags);
|
|
14179
|
+
} catch {
|
|
14180
|
+
return false;
|
|
14181
|
+
}
|
|
14182
|
+
}
|
|
14183
|
+
function cacheUpdatedAt(path) {
|
|
14184
|
+
try {
|
|
14185
|
+
if (!existsSync(path)) return void 0;
|
|
14186
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
14187
|
+
if (!parsed || typeof parsed !== "object") return void 0;
|
|
14188
|
+
const u = parsed.updated_at;
|
|
14189
|
+
return typeof u === "string" && u.length > 0 ? u : void 0;
|
|
14190
|
+
} catch {
|
|
14191
|
+
return void 0;
|
|
14192
|
+
}
|
|
14193
|
+
}
|
|
14194
|
+
function defaultFlagsCachePath(env = process.env) {
|
|
14195
|
+
const hostWide = join(homedir(), ".augmented", "flags-cache.json");
|
|
14196
|
+
const agentId = env["AGT_AGENT_ID"]?.trim();
|
|
14197
|
+
if (!agentId) return hostWide;
|
|
14198
|
+
const perAgent = join(homedir(), ".augmented", agentId, "flags-cache.json");
|
|
14199
|
+
if (!hasUsableFlags(perAgent)) return hostWide;
|
|
14200
|
+
const hostWideAt = cacheUpdatedAt(hostWide);
|
|
14201
|
+
const perAgentAt = cacheUpdatedAt(perAgent);
|
|
14202
|
+
if (hostWideAt && (!perAgentAt || perAgentAt < hostWideAt)) return hostWide;
|
|
14203
|
+
return perAgent;
|
|
14174
14204
|
}
|
|
14175
14205
|
function envBoolean(raw) {
|
|
14176
14206
|
if (raw === void 0) return void 0;
|
|
@@ -14197,7 +14227,7 @@ function resolveHostBooleanFlag(opts) {
|
|
|
14197
14227
|
const env = opts.env ?? process.env;
|
|
14198
14228
|
const envValue = envBoolean(env[opts.envVar]);
|
|
14199
14229
|
if (envValue !== void 0) return envValue;
|
|
14200
|
-
const cached2 = cachedBoolean(opts.key, opts.cachePath ?? defaultFlagsCachePath());
|
|
14230
|
+
const cached2 = cachedBoolean(opts.key, opts.cachePath ?? defaultFlagsCachePath(env));
|
|
14201
14231
|
if (cached2 !== void 0) return cached2;
|
|
14202
14232
|
return opts.defaultValue;
|
|
14203
14233
|
}
|
|
@@ -14233,7 +14263,7 @@ function resolveGhostReplyMode(opts) {
|
|
|
14233
14263
|
if (modeOverride !== void 0) return modeOverride;
|
|
14234
14264
|
const legacyOverride = parseGhostReplyMode(env["AGT_GHOST_REPLY_INTENT_CLASSIFIER_ENABLED"]);
|
|
14235
14265
|
if (legacyOverride !== void 0) return legacyOverride;
|
|
14236
|
-
const cached2 = cachedGhostReplyMode(opts?.cachePath ?? defaultFlagsCachePath());
|
|
14266
|
+
const cached2 = cachedGhostReplyMode(opts?.cachePath ?? defaultFlagsCachePath(env));
|
|
14237
14267
|
if (cached2 !== void 0) return cached2;
|
|
14238
14268
|
return "off";
|
|
14239
14269
|
}
|