@agent-native/core 0.48.4 → 0.49.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.
Files changed (122) hide show
  1. package/dist/agent/context-xray/actions/context-evict.d.ts +1 -1
  2. package/dist/agent/context-xray/actions/context-pin.d.ts +1 -1
  3. package/dist/agent/context-xray/actions/context-report.d.ts +4 -4
  4. package/dist/agent/context-xray/actions/context-restore.d.ts +1 -1
  5. package/dist/application-state/handlers.d.ts +2 -2
  6. package/dist/application-state/handlers.d.ts.map +1 -1
  7. package/dist/cli/app-skill.d.ts +157 -0
  8. package/dist/cli/app-skill.d.ts.map +1 -0
  9. package/dist/cli/app-skill.js +17 -7
  10. package/dist/cli/app-skill.js.map +1 -1
  11. package/dist/cli/audit-agent-web.d.ts +2 -0
  12. package/dist/cli/audit-agent-web.d.ts.map +1 -0
  13. package/dist/cli/code-agent-connector.d.ts +17 -0
  14. package/dist/cli/code-agent-connector.d.ts.map +1 -0
  15. package/dist/cli/code.d.ts +66 -0
  16. package/dist/cli/code.d.ts.map +1 -0
  17. package/dist/cli/connect.d.ts +168 -0
  18. package/dist/cli/connect.d.ts.map +1 -0
  19. package/dist/cli/connect.js +118 -30
  20. package/dist/cli/connect.js.map +1 -1
  21. package/dist/cli/context-xray-local.d.ts +16 -0
  22. package/dist/cli/context-xray-local.d.ts.map +1 -0
  23. package/dist/cli/create-workspace.d.ts +8 -0
  24. package/dist/cli/create-workspace.d.ts.map +1 -0
  25. package/dist/cli/index.d.ts +3 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/info.d.ts +2 -0
  28. package/dist/cli/info.d.ts.map +1 -0
  29. package/dist/cli/mcp-config-writers.d.ts +108 -0
  30. package/dist/cli/mcp-config-writers.d.ts.map +1 -0
  31. package/dist/cli/mcp-config-writers.js +143 -0
  32. package/dist/cli/mcp-config-writers.js.map +1 -1
  33. package/dist/cli/mcp.d.ts +16 -0
  34. package/dist/cli/mcp.d.ts.map +1 -0
  35. package/dist/cli/mcp.js +10 -10
  36. package/dist/cli/mcp.js.map +1 -1
  37. package/dist/cli/migrate.d.ts +38 -0
  38. package/dist/cli/migrate.d.ts.map +1 -0
  39. package/dist/cli/plan-local.d.ts +43 -0
  40. package/dist/cli/plan-local.d.ts.map +1 -0
  41. package/dist/cli/plan-publish-store.d.ts +62 -0
  42. package/dist/cli/plan-publish-store.d.ts.map +1 -0
  43. package/dist/cli/pr-visual-recap-workflow.d.ts +11 -0
  44. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -0
  45. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  46. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  47. package/dist/cli/recap.d.ts +453 -0
  48. package/dist/cli/recap.d.ts.map +1 -0
  49. package/dist/cli/recap.js +228 -95
  50. package/dist/cli/recap.js.map +1 -1
  51. package/dist/cli/skills.d.ts +193 -0
  52. package/dist/cli/skills.d.ts.map +1 -0
  53. package/dist/cli/skills.js +369 -171
  54. package/dist/cli/skills.js.map +1 -1
  55. package/dist/cli/telemetry.d.ts +13 -0
  56. package/dist/cli/telemetry.d.ts.map +1 -0
  57. package/dist/cli/telemetry.js +115 -0
  58. package/dist/cli/telemetry.js.map +1 -0
  59. package/dist/cli/workspace-dev.d.ts +96 -0
  60. package/dist/cli/workspace-dev.d.ts.map +1 -0
  61. package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
  62. package/dist/client/blocks/library/AnnotatedCodeBlock.js +15 -7
  63. package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
  64. package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
  65. package/dist/client/blocks/library/DiffBlock.js +17 -10
  66. package/dist/client/blocks/library/DiffBlock.js.map +1 -1
  67. package/dist/client/blocks/library/annotation-rail.d.ts +5 -0
  68. package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
  69. package/dist/client/blocks/library/annotation-rail.js +6 -0
  70. package/dist/client/blocks/library/annotation-rail.js.map +1 -1
  71. package/dist/client/blocks/types.d.ts +5 -0
  72. package/dist/client/blocks/types.d.ts.map +1 -1
  73. package/dist/client/blocks/types.js.map +1 -1
  74. package/dist/extensions/schema.d.ts +54 -54
  75. package/dist/extensions/slots/schema.d.ts +13 -13
  76. package/dist/file-upload/actions/upload-image.d.ts +4 -4
  77. package/dist/mcp/actions/create-org-service-token.d.ts +1 -1
  78. package/dist/mcp/actions/list-org-service-tokens.d.ts +7 -7
  79. package/dist/mcp/build-server.d.ts +12 -12
  80. package/dist/mcp/build-server.d.ts.map +1 -1
  81. package/dist/mcp/build-server.js.map +1 -1
  82. package/dist/mcp/connect-route.js +1 -1
  83. package/dist/mcp/connect-route.js.map +1 -1
  84. package/dist/mcp/oauth-route.d.ts +10 -0
  85. package/dist/mcp/oauth-route.d.ts.map +1 -1
  86. package/dist/mcp/oauth-route.js +34 -3
  87. package/dist/mcp/oauth-route.js.map +1 -1
  88. package/dist/mcp/oauth-store.d.ts +15 -1
  89. package/dist/mcp/oauth-store.d.ts.map +1 -1
  90. package/dist/mcp/oauth-store.js +60 -4
  91. package/dist/mcp/oauth-store.js.map +1 -1
  92. package/dist/mcp/oauth-token.d.ts +3 -1
  93. package/dist/mcp/oauth-token.d.ts.map +1 -1
  94. package/dist/mcp/oauth-token.js +78 -6
  95. package/dist/mcp/oauth-token.js.map +1 -1
  96. package/dist/mcp/server.d.ts.map +1 -1
  97. package/dist/mcp/server.js +8 -6
  98. package/dist/mcp/server.js.map +1 -1
  99. package/dist/observability/routes.d.ts +11 -11
  100. package/dist/org/handlers.d.ts +7 -11
  101. package/dist/org/handlers.d.ts.map +1 -1
  102. package/dist/secrets/schema.d.ts +7 -7
  103. package/dist/server/csrf.d.ts +1 -1
  104. package/dist/server/csrf.d.ts.map +1 -1
  105. package/dist/server/poll-events.d.ts +1 -1
  106. package/dist/server/security-headers.d.ts +1 -1
  107. package/dist/server/security-headers.d.ts.map +1 -1
  108. package/dist/sharing/actions/list-resource-shares.d.ts +3 -3
  109. package/dist/sharing/actions/set-resource-visibility.d.ts +2 -2
  110. package/dist/sharing/actions/share-resource.d.ts +4 -4
  111. package/dist/sharing/actions/unshare-resource.d.ts +1 -1
  112. package/dist/sharing/schema.d.ts +12 -12
  113. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +2 -2
  114. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +6 -6
  115. package/dist/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +2 -2
  116. package/dist/workspace-files/schema.d.ts +8 -8
  117. package/docs/content/external-agents.md +14 -0
  118. package/docs/content/plan-plugin.md +16 -7
  119. package/package.json +5 -1
  120. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +2 -2
  121. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +6 -6
  122. package/src/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +2 -2
@@ -0,0 +1,168 @@
1
+ /**
2
+ * `agent-native connect <url>` — wire your local Claude Code / Codex / Cowork
3
+ * to a DEPLOYED agent-native app. OAuth-capable clients receive a standard
4
+ * remote MCP URL entry and authenticate in the host. Fallback clients use the
5
+ * browser device-code flow: open the verification URL, approve in the browser,
6
+ * and the minted HTTP MCP server entry is written idempotently.
7
+ *
8
+ * agent-native connect <url> [--client all|claude-code|claude-code-cli|
9
+ * codex|cowork] [--scope user|project]
10
+ * [--name <serverName>]
11
+ * agent-native reconnect [<url>] [--client ...] [--name <serverName>]
12
+ * agent-native connect <url> --token <token> (no-browser fallback)
13
+ * agent-native connect [--client ...] (pick first-party apps)
14
+ * agent-native connect --all [--client ...] (separate first-party app MCP resources)
15
+ *
16
+ * Server contract (implemented by another agent on `<url>`):
17
+ * POST <url>/_agent-native/mcp/connect/device/start (no auth)
18
+ * body { client?, app? }
19
+ * → { device_code, user_code, verification_uri,
20
+ * verification_uri_complete, interval, expires_in }
21
+ * POST <url>/_agent-native/mcp/connect/device/poll (no auth)
22
+ * body { device_code }
23
+ * → { status: "pending" }
24
+ * | { status: "approved", token, mcpUrl, serverName, mcpServerEntry }
25
+ * | { status: "expired" }
26
+ * | { status: "consumed" }
27
+ * | { status: "error" | "not_found", message? }
28
+ *
29
+ * Node-only CLI module. Uses Node built-ins, @clack/prompts, and global fetch.
30
+ */
31
+ import { ClientId } from "./mcp-config-writers.js";
32
+ export interface ParsedConnectArgs {
33
+ /** Developer profile switch: local dev gateway or saved production config. */
34
+ mode?: "dev" | "prod" | "reauth" | "reconnect";
35
+ /** Positional URL (the deployed app origin). Undefined for `--all`. */
36
+ url?: string;
37
+ /** all | claude-code | claude-code-cli | codex | cowork (default "all"). */
38
+ client: string;
39
+ /** True when the user passed --client explicitly, so we skip the picker. */
40
+ clientExplicit: boolean;
41
+ /** user | project (default "user"). */
42
+ scope: string;
43
+ /** Override the minted MCP server name. */
44
+ name?: string;
45
+ /** No-browser fallback: skip device flow, use this token directly. */
46
+ token?: string;
47
+ /**
48
+ * Mint an ORG SERVICE token with this service name (e.g. "ci") instead of
49
+ * writing local MCP configs. Authenticates the human via the device flow,
50
+ * then calls the app's `create-org-service-token` action and prints the
51
+ * token once — for CI secrets like PLAN_RECAP_TOKEN.
52
+ */
53
+ serviceToken?: string;
54
+ /** Optional token TTL in days (1–365) for --service-token. */
55
+ ttlDays?: number;
56
+ /** Connect every first-party hosted app. */
57
+ all: boolean;
58
+ /** Comma-separated app names for profile switching. */
59
+ apps?: string;
60
+ /** Local dev-lazy gateway URL for `connect dev`. */
61
+ gateway?: string;
62
+ /** Shorthand for a local dev-lazy gateway port. */
63
+ port?: number;
64
+ /** Local owner email override for dev entries. */
65
+ ownerEmail?: string;
66
+ /**
67
+ * Embed `catalog_scope: "full"` in the minted token so the connected client
68
+ * bypasses the connector-catalog tier and sees the complete action surface,
69
+ * identical to the local/dev experience. Matches the `fullCatalog` body
70
+ * param on the app's token-mint route.
71
+ */
72
+ fullCatalog?: boolean;
73
+ }
74
+ export declare function parseConnectArgs(argv: string[]): ParsedConnectArgs;
75
+ /**
76
+ * Normalize a user-supplied app URL: trim, require http/https, strip the
77
+ * trailing slash. Throws a friendly Error otherwise.
78
+ */
79
+ export declare function normalizeUrl(raw: string): string;
80
+ /** Resolve the requested clients list. "all" → every supported client. */
81
+ export declare function resolveClients(client: string): ClientId[];
82
+ export declare function connectPreferencesPath(): string;
83
+ export declare function readConnectClientPreferences(file?: string): ClientId[] | null;
84
+ export declare function writeConnectClientPreferences(clients: ClientId[], file?: string): void;
85
+ export interface ConnectClientPromptContext {
86
+ initialClients: ClientId[];
87
+ options: {
88
+ value: ClientId;
89
+ label: string;
90
+ hint: string;
91
+ }[];
92
+ preferencesFile: string;
93
+ }
94
+ export interface HostedApp {
95
+ name: string;
96
+ label: string;
97
+ url: string;
98
+ }
99
+ export interface ConnectHostedAppsPromptContext {
100
+ apps: HostedApp[];
101
+ initialApps: string[];
102
+ }
103
+ export declare function supportsRemoteMcpOAuth(client: ClientId): boolean;
104
+ /** Injectable hooks so the poll state machine is unit-testable. */
105
+ export interface ConnectDeps {
106
+ /** Defaults to global fetch. */
107
+ fetchImpl?: typeof fetch;
108
+ /** Sleep between polls (ms). Defaults to real setTimeout. */
109
+ sleep?: (ms: number) => Promise<void>;
110
+ /** Open the verification URL. Defaults to the platform browser opener. */
111
+ openBrowser?: (url: string) => void;
112
+ /** Override "now" for the expiry cap (ms epoch). Defaults to Date.now. */
113
+ now?: () => number;
114
+ /** Tests/embedders can force or suppress the interactive client picker. */
115
+ isInteractive?: () => boolean;
116
+ /** Injectable client picker. Defaults to @clack/prompts multiselect. */
117
+ promptClients?: (context: ConnectClientPromptContext) => Promise<ClientId[] | null>;
118
+ /** Injectable hosted app picker. Defaults to @clack/prompts multiselect. */
119
+ promptHostedApps?: (context: ConnectHostedAppsPromptContext) => Promise<string[] | null>;
120
+ /** Override the persisted connect preferences file. */
121
+ preferencesFile?: string;
122
+ /** Override the saved dev/prod profile file. */
123
+ profilesFile?: string;
124
+ }
125
+ /**
126
+ * Run the device-code flow against `baseUrl` and return the approved grant.
127
+ * Resolves with `null` (and prints a clear message) on expired/consumed or
128
+ * other terminal failure — the caller maps that to a non-zero exit.
129
+ */
130
+ export declare function runDeviceFlow(baseUrl: string, appSlug: string, clientArg: string, deps?: ConnectDeps, options?: {
131
+ fullCatalog?: boolean;
132
+ }): Promise<{
133
+ token?: string;
134
+ mcpUrl: string;
135
+ serverName: string;
136
+ headers?: Record<string, string>;
137
+ } | null>;
138
+ /**
139
+ * Write the HTTP MCP entry into every requested client config idempotently.
140
+ * Returns the list of files written so the caller can print them.
141
+ */
142
+ export declare function writeConfigs(clients: ClientId[], serverName: string, mcpUrl: string, token: string | undefined, scope: string, baseDir?: string, headers?: Record<string, string>): {
143
+ client: ClientId;
144
+ file: string;
145
+ }[];
146
+ export declare function connectProfilesPath(): string;
147
+ /** Hosted first-party apps: visible (non-hidden) templates with a prodUrl. */
148
+ export declare function hostedApps(): HostedApp[];
149
+ /**
150
+ * `agent-native connect <url> --service-token <name>` — mint an ORG service
151
+ * token for CI (e.g. the PLAN_RECAP_TOKEN GitHub secret).
152
+ *
153
+ * Flow: authenticate the human via the existing browser device flow, then use
154
+ * that short-lived grant to call the app's `create-org-service-token` action
155
+ * (org owner/admin gated server-side). The service token is printed exactly
156
+ * once and never written to any local config file.
157
+ */
158
+ export declare function runServiceTokenMint(parsed: ParsedConnectArgs, deps?: ConnectDeps): Promise<boolean>;
159
+ /**
160
+ * `agent-native connect` entry point. `deps` is injectable for tests; the
161
+ * dispatcher in index.ts calls it with just `args`.
162
+ *
163
+ * Sets `process.exitCode = 1` on failure (so the process exits non-zero
164
+ * once the event loop drains) rather than calling `process.exit`, keeping
165
+ * the function testable — same pattern as `audit-agent-web`.
166
+ */
167
+ export declare function runConnect(args: string[], deps?: ConnectDeps): Promise<void>;
168
+ //# sourceMappingURL=connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/cli/connect.ts"],"names":[],"mappings":"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"}
@@ -33,7 +33,7 @@ import os from "node:os";
33
33
  import { spawn } from "node:child_process";
34
34
  import path from "node:path";
35
35
  import { findWorkspaceRoot } from "../mcp/workspace-resolve.js";
36
- import { CLIENTS, configPathFor, writeCodexBlock, writeHttpEntryForClient, writeJsonMcpEntry, } from "./mcp-config-writers.js";
36
+ import { CLIENTS, configPathFor, removeSameUrlDuplicatesForClient, writeCodexBlock, writeHttpEntryForClient, writeJsonMcpEntry, } from "./mcp-config-writers.js";
37
37
  import { isFirstPartyPlanHost, writePlanPublishAuth, } from "./plan-publish-store.js";
38
38
  import { TEMPLATES, visibleTemplates } from "./templates-meta.js";
39
39
  const DEVICE_START_PATH = "/_agent-native/mcp/connect/device/start";
@@ -41,6 +41,17 @@ const DEVICE_POLL_PATH = "/_agent-native/mcp/connect/device/poll";
41
41
  const MCP_PATH = "/_agent-native/mcp";
42
42
  const SERVER_NAME_PREFIX = "agent-native";
43
43
  const CONNECT_PREFERENCES_VERSION = 1;
44
+ /**
45
+ * Maps a normalised hosted MCP URL to the canonical server name for that
46
+ * first-party app. Kept in sync with BUILT_IN_APP_SKILLS in skills.ts (we
47
+ * cannot import from there — it imports connect.ts, which would be circular).
48
+ */
49
+ const CANONICAL_SERVER_NAME_BY_MCP_URL = {
50
+ "https://plan.agent-native.com/_agent-native/mcp": "plan",
51
+ "https://assets.agent-native.com/_agent-native/mcp": "agent-native-assets",
52
+ "https://design.agent-native.com/_agent-native/mcp": "agent-native-design",
53
+ "https://context-xray.agent-native.com/_agent-native/mcp": "agent-native-context-xray",
54
+ };
44
55
  const CONNECT_PROFILES_VERSION = 1;
45
56
  const DEFAULT_DEV_GATEWAY = "http://127.0.0.1:8080";
46
57
  const MCP_FULL_CATALOG_HEADER = "X-Agent-Native-MCP-Full-Catalog";
@@ -129,7 +140,7 @@ export function parseConnectArgs(argv) {
129
140
  export function normalizeUrl(raw) {
130
141
  const trimmed = (raw ?? "").trim();
131
142
  if (!trimmed) {
132
- throw new Error("Missing app URL. Usage: agent-native connect <url>");
143
+ throw new Error("Missing app URL. Usage: npx @agent-native/core@latest connect <url>");
133
144
  }
134
145
  let parsed;
135
146
  try {
@@ -137,7 +148,7 @@ export function normalizeUrl(raw) {
137
148
  }
138
149
  catch {
139
150
  throw new Error(`Not a valid URL: "${raw}". Pass a full origin, e.g. ` +
140
- `agent-native connect https://mail.agent-native.com`);
151
+ `npx @agent-native/core@latest connect https://mail.agent-native.com`);
141
152
  }
142
153
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
143
154
  throw new Error(`Unsupported URL scheme "${parsed.protocol}". Use http:// or https://`);
@@ -1137,7 +1148,7 @@ async function connectProdProfile(parsed, clients, deps) {
1137
1148
  for (const row of missing) {
1138
1149
  const app = apps.find((candidate) => candidate.name === row.app);
1139
1150
  logOut(` ${row.app.padEnd(12)} ${row.client.padEnd(18)} ` +
1140
- `run: agent-native connect ${app?.url ?? "<url>"} --client ${row.client}`);
1151
+ `run: npx @agent-native/core@latest connect ${app?.url ?? "<url>"} --client ${row.client}`);
1141
1152
  }
1142
1153
  }
1143
1154
  logOut("");
@@ -1159,7 +1170,23 @@ function distinctReconnectEntries(entries) {
1159
1170
  function describeReconnectEntry(entry) {
1160
1171
  return `${entry.serverName} (${entry.url}) in ${entry.client}`;
1161
1172
  }
1162
- function resolveReconnectTarget(parsed, clients) {
1173
+ /**
1174
+ * Return true when `url` is an agent-native MCP endpoint.
1175
+ * Matches any URL whose path ends with `/_agent-native/mcp` (after stripping
1176
+ * trailing slashes), regardless of the MCP server's name in the config.
1177
+ */
1178
+ function isAgentNativeMcpUrl(url) {
1179
+ if (!url)
1180
+ return false;
1181
+ try {
1182
+ const pathname = new URL(url).pathname.replace(/\/+$/, "");
1183
+ return pathname === MCP_PATH || pathname.endsWith(MCP_PATH);
1184
+ }
1185
+ catch {
1186
+ return false;
1187
+ }
1188
+ }
1189
+ async function resolveReconnectTarget(parsed, clients, deps) {
1163
1190
  const baseDir = projectBaseDir();
1164
1191
  const scope = parsed.scope === "user" ? "user" : "project";
1165
1192
  const entries = readExistingMcpEntries(clients, baseDir, scope);
@@ -1181,28 +1208,78 @@ function resolveReconnectTarget(parsed, clients) {
1181
1208
  }
1182
1209
  return { rawUrl: parsed.url };
1183
1210
  }
1184
- const candidates = distinctReconnectEntries(parsed.name
1211
+ // No URL provided: scan all configs for agent-native MCP entries by URL
1212
+ // pattern, not by server name prefix. This finds the canonical "plan" entry
1213
+ // (and any other custom-named entries) that the old prefix scan missed.
1214
+ const agentNativeEntries = distinctReconnectEntries(parsed.name
1185
1215
  ? entries.filter((entry) => entry.serverName === parsed.name)
1186
- : entries.filter((entry) => entry.serverName.startsWith(`${SERVER_NAME_PREFIX}-`)));
1187
- if (candidates.length === 0) {
1216
+ : entries.filter((entry) => isAgentNativeMcpUrl(entry.url)));
1217
+ // Group by normalised URL so we can detect multi-app situations.
1218
+ const byUrl = new Map();
1219
+ for (const entry of agentNativeEntries) {
1220
+ const key = canonicalMcpUrl(entry.url) ?? entry.url;
1221
+ const bucket = byUrl.get(key) ?? [];
1222
+ bucket.push(entry);
1223
+ byUrl.set(key, bucket);
1224
+ }
1225
+ if (byUrl.size === 0) {
1188
1226
  logErr(" No existing Agent Native MCP entry found to reconnect.");
1189
1227
  logErr(" Pass a URL, or use --name <serverName> if the entry has a custom name.");
1190
- logErr(" First-time setup still uses: agent-native connect <url> --client <client>");
1228
+ logErr(" First-time setup still uses: npx @agent-native/core@latest connect <url> --client <client>");
1191
1229
  return null;
1192
1230
  }
1193
- if (candidates.length > 1) {
1194
- logErr(" Found multiple Agent Native MCP entries:");
1195
- for (const entry of candidates) {
1196
- logErr(` ${describeReconnectEntry(entry)}`);
1231
+ if (byUrl.size === 1) {
1232
+ // Exactly one distinct URL: prefer the entry whose serverName matches the
1233
+ // canonical name for this app (e.g. "plan" over "agent-native-plans").
1234
+ // Fall back to any entry whose name doesn't start with "agent-native-"
1235
+ // (short canonical names like "plan"), then bucket[0].
1236
+ const [url, bucket] = [...byUrl.entries()][0];
1237
+ const canonicalName = CANONICAL_SERVER_NAME_BY_MCP_URL[url];
1238
+ const preferred = (canonicalName
1239
+ ? bucket.find((e) => e.serverName === canonicalName)
1240
+ : undefined) ??
1241
+ bucket.find((e) => !e.serverName.startsWith("agent-native-")) ??
1242
+ bucket[0];
1243
+ return { rawUrl: preferred.url, serverName: preferred.serverName };
1244
+ }
1245
+ // Multiple distinct URLs: pick interactively when TTY, else list with hints.
1246
+ const urlList = [...byUrl.keys()];
1247
+ if (shouldPrompt(deps)) {
1248
+ const clack = await import("@clack/prompts");
1249
+ const result = await clack.select({
1250
+ message: "Multiple Agent Native apps found. Which one do you want to reconnect?",
1251
+ options: urlList.map((u) => {
1252
+ const representativeEntry = byUrl.get(u)[0];
1253
+ return {
1254
+ value: u,
1255
+ label: representativeEntry.serverName,
1256
+ hint: u,
1257
+ };
1258
+ }),
1259
+ });
1260
+ if (clack.isCancel(result)) {
1261
+ clack.cancel("Cancelled.");
1262
+ return null;
1197
1263
  }
1198
- logErr(" Re-run with a URL or --name <serverName>.");
1199
- return null;
1264
+ const chosen = byUrl.get(result)?.[0];
1265
+ if (!chosen)
1266
+ return null;
1267
+ return { rawUrl: chosen.url, serverName: chosen.serverName };
1268
+ }
1269
+ logErr(" Found multiple Agent Native MCP entries:");
1270
+ for (const [u, bucket] of byUrl) {
1271
+ logErr(` ${bucket[0].serverName} → ${u}`);
1200
1272
  }
1201
- const [entry] = candidates;
1202
- return { rawUrl: entry.url, serverName: entry.serverName };
1273
+ logErr(" Re-run with a URL or --name <serverName>. For example:");
1274
+ for (const u of urlList) {
1275
+ // Strip the MCP path suffix for a cleaner reconnect URL suggestion.
1276
+ const baseUrl = u.replace(/\/_agent-native\/mcp$/, "");
1277
+ logErr(` npx @agent-native/core@latest reconnect ${baseUrl}`);
1278
+ }
1279
+ return null;
1203
1280
  }
1204
1281
  async function reconnectOne(parsed, clients, deps) {
1205
- const target = resolveReconnectTarget(parsed, clients);
1282
+ const target = await resolveReconnectTarget(parsed, clients, deps);
1206
1283
  if (!target)
1207
1284
  return false;
1208
1285
  const effectiveParsed = {
@@ -1274,6 +1351,17 @@ async function connectOne(rawUrl, parsed, clients, deps) {
1274
1351
  }
1275
1352
  allWritten.push(...writeConfigs(oauthClients, serverName, mcpUrl, undefined, scope, baseDir, undefined));
1276
1353
  }
1354
+ // After writing the canonical entry, remove any same-URL duplicates (alias
1355
+ // names, legacy default names, stale custom names) from the same config
1356
+ // files so each app has exactly one MCP session.
1357
+ const allRemovedNames = [];
1358
+ for (const client of clients) {
1359
+ const removed = removeSameUrlDuplicatesForClient(client, serverName, mcpUrl, baseDir, scope);
1360
+ allRemovedNames.push(...removed);
1361
+ }
1362
+ if (allRemovedNames.length > 0) {
1363
+ logOut(` Removed duplicate MCP entries: ${[...new Set(allRemovedNames)].join(", ")}`);
1364
+ }
1277
1365
  // Canonical publish-token write: when we have a real minted bearer token for
1278
1366
  // a first-party Plans app, also persist `{ url, token }` to
1279
1367
  // `~/.agent-native/plan-publish.json` so the local Plans server can read the
@@ -1431,7 +1519,7 @@ export async function runServiceTokenMint(parsed, deps = {}) {
1431
1519
  const serviceName = parsed.serviceToken?.trim() ?? "";
1432
1520
  if (!parsed.url) {
1433
1521
  logErr(" --service-token requires the app URL.");
1434
- logErr(" Usage: agent-native connect <url> --service-token <name> [--ttl-days <1-365>]");
1522
+ logErr(" Usage: npx @agent-native/core@latest connect <url> --service-token <name> [--ttl-days <1-365>]");
1435
1523
  return false;
1436
1524
  }
1437
1525
  if (!serviceName) {
@@ -1504,14 +1592,14 @@ export async function runServiceTokenMint(parsed, deps = {}) {
1504
1592
  // ---------------------------------------------------------------------------
1505
1593
  // Entry point
1506
1594
  // ---------------------------------------------------------------------------
1507
- const HELP = `agent-native connect — wire your coding agent to a deployed app
1595
+ const HELP = `npx @agent-native/core@latest connect — wire your coding agent to a deployed app
1508
1596
 
1509
1597
  Usage:
1510
- agent-native connect [--client <c>] [--scope user|project]
1598
+ npx @agent-native/core@latest connect [--client <c>] [--scope user|project]
1511
1599
  With no URL, opens a picker for the built-in hosted apps
1512
1600
  (mail.agent-native.com, calendar.agent-native.com, and friends).
1513
1601
 
1514
- agent-native connect <url> [--client <c>] [--scope user|project] [--name <n>]
1602
+ npx @agent-native/core@latest connect <url> [--client <c>] [--scope user|project] [--name <n>]
1515
1603
  Writes the HTTP MCP entry into your selected client config(s). Claude
1516
1604
  Code / Claude Code CLI use standard remote MCP OAuth: restart Claude,
1517
1605
  run /mcp, and choose Authenticate. Codex / Cowork use the browser
@@ -1523,13 +1611,13 @@ Usage:
1523
1611
  OAuth config and prompts you to authenticate with /mcp.
1524
1612
 
1525
1613
  For cross-app access, prefer the unified Dispatch gateway:
1526
- agent-native connect https://dispatch.agent-native.com
1614
+ npx @agent-native/core@latest connect https://dispatch.agent-native.com
1527
1615
 
1528
- agent-native connect <url> --token <token>
1616
+ npx @agent-native/core@latest connect <url> --token <token>
1529
1617
  No-browser fallback. Skip the device flow and write the entry with
1530
1618
  the supplied token (get it from the app's Connect page).
1531
1619
 
1532
- agent-native connect <url> --service-token <name> [--ttl-days <1-365>]
1620
+ npx @agent-native/core@latest connect <url> --service-token <name> [--ttl-days <1-365>]
1533
1621
  Mint an ORG service token for CI (e.g. the PLAN_RECAP_TOKEN secret for
1534
1622
  PR Visual Recap). Authenticates you via the browser device flow, then
1535
1623
  mints a token owned by your ORGANIZATION — it keeps working if you
@@ -1537,22 +1625,22 @@ Usage:
1537
1625
  org-visible. Org owner/admin only. Printed once; nothing is written
1538
1626
  to local MCP configs.
1539
1627
 
1540
- agent-native reconnect [<url>] [--client <c>] [--scope user|project]
1541
- agent-native connect reconnect [<url>] [--client <c>] [--scope user|project]
1628
+ npx @agent-native/core@latest reconnect [<url>] [--client <c>] [--scope user|project]
1629
+ npx @agent-native/core@latest connect reconnect [<url>] [--client <c>] [--scope user|project]
1542
1630
  Re-authenticate an existing MCP entry without reinstalling apps/skills.
1543
1631
  With a URL, it reuses the existing server name for that MCP URL when
1544
1632
  possible. Without a URL, it reconnects the only matching Agent Native
1545
1633
  entry in the selected client config. Use --name for custom server names.
1546
1634
 
1547
- agent-native connect --all [--client <c>] [--scope user|project]
1635
+ npx @agent-native/core@latest connect --all [--client <c>] [--scope user|project]
1548
1636
  Connect every first-party hosted app as separate MCP resources.
1549
1637
 
1550
1638
  Developer:
1551
- agent-native connect dev [--apps mail,calendar] [--client <c>]
1639
+ npx @agent-native/core@latest connect dev [--apps mail,calendar] [--client <c>]
1552
1640
  Switch selected first-party MCP entries to a local dev-lazy gateway.
1553
1641
  Defaults to ${DEFAULT_DEV_GATEWAY}; override with --gateway or --port.
1554
1642
 
1555
- agent-native connect prod [--apps mail,calendar] [--client <c>]
1643
+ npx @agent-native/core@latest connect prod [--apps mail,calendar] [--client <c>]
1556
1644
  Restore production MCP entries saved before the dev switch.
1557
1645
 
1558
1646
  Clients: all (default), claude-code, claude-code-cli, codex, cowork