diff --git a/src/config/paths.ts b/src/config/paths.ts index c9477d7..fc2eff0 100644 --- a/src/config/paths.ts +++ b/src/config/paths.ts @@ -30,9 +30,25 @@ const home = resolveHome(); // Hermetic installs run from a bundled runtime where the backend lives outside // projectRoot; the launcher points PODCLI_BACKEND at it. -const backendDir = process.env.PODCLI_BACKEND - ? resolve(process.env.PODCLI_BACKEND) - : join(projectRoot, "backend"); +function resolveBackendDir(): string { + if (process.env.PODCLI_BACKEND) { + return resolve(process.env.PODCLI_BACKEND); + } + + const sourceBackend = join(projectRoot, "backend"); + if (existsSync(join(sourceBackend, "cli.py"))) { + return sourceBackend; + } + + const runtimeBackend = join(projectRoot, "runtime", "backend"); + if (existsSync(join(runtimeBackend, "cli.py"))) { + return runtimeBackend; + } + + return sourceBackend; +} + +const backendDir = resolveBackendDir(); function detectPython(): string { if (process.env.PYTHON_PATH) return process.env.PYTHON_PATH; diff --git a/src/handlers/integrations.routes.ts b/src/handlers/integrations.routes.ts index 5e1dc39..44949b8 100644 --- a/src/handlers/integrations.routes.ts +++ b/src/handlers/integrations.routes.ts @@ -126,11 +126,18 @@ export function registerConfigIntegrationRoutes( }); app.get("/api/integration-info", (_req, res) => { - const distPath = join(projectRoot, "dist", "index.js"); + const packagedMcpPath = join(projectRoot, "runtime", "studio", "mcp-server.mjs"); + const sourceMcpPath = join(projectRoot, "dist", "index.js"); + const mcpPath = process.env.PODCLI_STUDIO + ? join(process.env.PODCLI_STUDIO, "mcp-server.mjs") + : existsSync(packagedMcpPath) + ? packagedMcpPath + : sourceMcpPath; res.json({ - dist_path: distPath, + mcp_path: mcpPath, + dist_path: mcpPath, project_root: projectRoot, - server_ok: existsSync(distPath), + server_ok: existsSync(mcpPath), }); }); } diff --git a/src/ui/client/ConfigPage.tsx b/src/ui/client/ConfigPage.tsx index bac332e..dbd09bc 100644 --- a/src/ui/client/ConfigPage.tsx +++ b/src/ui/client/ConfigPage.tsx @@ -82,9 +82,7 @@ export default function ConfigPage() { const rows: Array<[string, string]> = status ? [ ["Config home", status.home || ""], - ["Data / cache", status.cache || ""], - ["Profile marker", status.profile_marker || ""], - ["Migration", status.migration?.already_migrated ? "Up to date" : "Ran on load"], + ["Cache", status.cache || ""], ] : []; @@ -117,13 +115,13 @@ export default function ConfigPage() {
setSecretInputs((p) => ({ ...p, [s.key]: e.target.value }))} style={{ fontSize: 13, flex: 1 }} @@ -137,10 +135,7 @@ export default function ConfigPage() { {savingKey === s.key ? "Saving…" : "Save"}
-
- {s.help}{" "} - Get token → -
+ Get token ))} @@ -149,12 +144,12 @@ export default function ConfigPage() {
Actions
- - + +
- +
diff --git a/src/ui/client/McpSetupPage.tsx b/src/ui/client/McpSetupPage.tsx index 635e8f3..ede9f4b 100644 --- a/src/ui/client/McpSetupPage.tsx +++ b/src/ui/client/McpSetupPage.tsx @@ -10,9 +10,9 @@ const STATUS_STYLE: Record = { }; export default function McpSetupPage() { - const [distPath, setDistPath] = useState(null); + const [mcpPath, setMcpPath] = useState(null); const [statusKind, setStatusKind] = useState("warn"); - const [statusText, setStatusText] = useState("Checking connection…"); + const [statusText, setStatusText] = useState("Checking…"); const desktopRef = useRef(null); const codeRef = useRef(null); const [copied, setCopied] = useState>({}); @@ -20,13 +20,13 @@ export default function McpSetupPage() { useEffect(() => { api("/integration-info") .then((data) => { - setDistPath(data.dist_path); + setMcpPath(data.mcp_path || data.dist_path); if (data.server_ok) { setStatusKind("ok"); - setStatusText(`Server running · ${data.tools_count} tools available`); + setStatusText("Ready"); } else { setStatusKind("err"); - setStatusText("Server not built — run: npm run build"); + setStatusText("Not built"); } }) .catch(() => { @@ -42,15 +42,19 @@ export default function McpSetupPage() { }); } - const dist = distPath ?? "/dist/index.js"; - const desktopJson = `{ - "mcpServers": { - "podcli": { - "command": "node", - "args": ["${dist}"] - } - } -}`; + const serverPath = mcpPath ?? "/mcp-server.mjs"; + const desktopJson = JSON.stringify( + { + mcpServers: { + podcli: { + command: "node", + args: [serverPath], + }, + }, + }, + null, + 2 + ); return (
@@ -60,10 +64,6 @@ export default function McpSetupPage() {
Claude Desktop
-
- Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or - %APPDATA%\Claude\claude_desktop_config.json (Windows), then restart Claude. -
claude_desktop_config.json @@ -84,7 +84,7 @@ export default function McpSetupPage() { {copied.code ? "Copied" : "Copy"}
-
{`claude mcp add podcli node ${dist}`}
+
podcli mcp install
diff --git a/src/ui/public/css/styles.css b/src/ui/public/css/styles.css index d5a95c9..22ec263 100644 --- a/src/ui/public/css/styles.css +++ b/src/ui/public/css/styles.css @@ -394,13 +394,13 @@ h1 { font-size: 28px; font-weight: 700; letter-spacing: -0.5px; line-height: 1.1 .section-label { font-size: 11px; font-weight: 700; letter-spacing: 0.8px; color: var(--text2); margin-bottom: 10px; text-transform: uppercase; } /* ─── Form Elements ─── */ -input[type="text"], input[type="number"], select, textarea { +input[type="text"], input[type="number"], input[type="password"], select, textarea { width: 100%; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 11px 14px; color: var(--text); font-family: inherit; font-size: 14px; outline: none; transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease); } -input[type="text"]:focus, input[type="number"]:focus, select:focus, textarea:focus { +input[type="text"]:focus, input[type="number"]:focus, input[type="password"]:focus, select:focus, textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-subtle); } textarea { @@ -1078,6 +1078,8 @@ input[type="range"]::-webkit-slider-thumb { .set-note.ok { background: var(--green-subtle); color: var(--green); } .set-note.err { background: var(--red-subtle); color: var(--red); } .set-file { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; } +.set-link { display: inline-block; margin-top: 6px; font-size: 12px; color: var(--accent); text-decoration: none; } +.set-link:hover { color: var(--accent-hover); } .int-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--border); } .int-row:last-child { border-bottom: none; } .int-row .name { font-size: 14px; font-weight: 600; }