commit 6d36fb371f81558202baa32d76728e3dd5a4032f
parent 6d4bc872c15370ae5073cc12e85f7d1f904f2128
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Mon, 28 Sep 2026 13:14:56 -0400
export: the Use with AI page's MCP snippet keys the server `archilyzer` and runs `pnpm --silent … archilyzer mcp` (W2 review Q1)
The snippet named the server after the site id, which breaks the repo's
/ask and /sweep commands (their tool names embed `archilyzer`), and ran
the long `--filter … exec tsx src/index.ts` form. It is now built by
`mcpSnippet.ts` (pure): keyed `archilyzer` on every site and the hub,
`--silent -C <repo> archilyzer mcp`, the site's or hub's env line kept,
values JSON-escaped. A line under it says why the name matters.
mcpSnippet.test.ts (3) parses it; all three fail on the old template.
[Unreleased] bullet.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
4 files changed, 76 insertions(+), 15 deletions(-)
diff --git a/export/CHANGELOG.md b/export/CHANGELOG.md
@@ -2,6 +2,7 @@
## [Unreleased]
- **A chart's sixth line, bar or slice has a colour of its own.** A chart broken down by channel, or by anything else, took its colours from a set of five and started again at the sixth, so the sixth series wore the first one's colour and the two could not be told apart. The sixth now takes the palette's sixth colour, a rust, chosen to stand apart from the other five on every ground, including for colour-blind readers. From the seventh on, each gets a hue of its own instead of repeating one. The first five are unchanged. Needs a rebuild and deploy of every export site and the hub.
+- **The "Use with AI" page's MCP snippet names the server so the /ask and /sweep commands find it.** The snippet for adding the archive's MCP server to a client named the server after the site, but the source's `/ask` and `/sweep` commands for Claude Code look for its tools under the name `archilyzer`, so with the snippet as shown they found nothing. It is now named `archilyzer` on every site and the hub, still pointed at that site (or at the whole hub), and a line under it says why the name matters. It also starts the server through the source's own command, `pnpm --silent -C … archilyzer mcp`; the `--silent` keeps pnpm's start-up lines out of the channel the client reads. Needs a rebuild and deploy of every export site and the hub.
## [0.10.0] - 2026-09-28
- **A video whose recheck failed shows as possibly missing rather than available.** When a video drops out of its channel's listing it is marked "Missing?" until a recheck says why. A recheck that could not reach the video — a blocked request or a network error — used to clear the mark as if the video had been found. It now leaves "Missing?" in place until a recheck actually reaches the video. Needs a rebuild and deploy of every export site.
diff --git a/export/app/use-with-ai/mcpSnippet.test.ts b/export/app/use-with-ai/mcpSnippet.test.ts
@@ -0,0 +1,39 @@
+import { test } from "node:test";
+import assert from "node:assert/strict";
+import { MCP_SERVER_NAME, mcpServerSnippet } from "./mcpSnippet";
+
+// The /use-with-ai page's `mcpServers` snippet (release 13, W2 fix round). It
+// must parse as JSON, key the server `archilyzer` (the /ask and /sweep
+// commands' tool names embed it), and run `pnpm --silent … archilyzer mcp` —
+// without `--silent`, pnpm 9 and 10 print their script banner on stdout, the
+// JSON-RPC channel.
+
+type Entry = { command: string; args: string[]; env: Record<string, string> };
+
+function parse(snippet: string): Record<string, Entry> {
+ return (JSON.parse(snippet) as { mcpServers: Record<string, Entry> }).mcpServers;
+}
+
+test("a site's snippet: one server, keyed archilyzer, run as `pnpm --silent -C … archilyzer mcp`", () => {
+ const servers = parse(mcpServerSnippet("TRANSCRIPT_SITE_URL", "https://jeralyzer.pages.dev"));
+ assert.equal(MCP_SERVER_NAME, "archilyzer");
+ assert.deepEqual(Object.keys(servers), ["archilyzer"]);
+ const s = servers.archilyzer;
+ assert.equal(s.command, "pnpm");
+ // --silent before anything pnpm runs; the checkout by -C; then the CLI's subcommand.
+ assert.equal(s.args[0], "--silent");
+ assert.deepEqual(s.args.slice(1), ["-C", "/path/to/yt-dlp-transcript-browser", "archilyzer", "mcp"]);
+ assert.deepEqual(s.env, { TRANSCRIPT_SITE_URL: "https://jeralyzer.pages.dev" });
+});
+
+test("a hub's snippet points the same server at the hub", () => {
+ const servers = parse(mcpServerSnippet("TRANSCRIPT_HUB_URL", "https://your-hub.example"));
+ assert.deepEqual(Object.keys(servers), ["archilyzer"]);
+ assert.deepEqual(servers.archilyzer.env, { TRANSCRIPT_HUB_URL: "https://your-hub.example" });
+ assert.equal(servers.archilyzer.args[0], "--silent");
+});
+
+test("a value that needs escaping still parses", () => {
+ const servers = parse(mcpServerSnippet("TRANSCRIPT_SITE_URL", 'https://x.example/"q"'));
+ assert.equal(servers.archilyzer.env.TRANSCRIPT_SITE_URL, 'https://x.example/"q"');
+});
diff --git a/export/app/use-with-ai/mcpSnippet.ts b/export/app/use-with-ai/mcpSnippet.ts
@@ -0,0 +1,28 @@
+// The "Add it to a client" snippet on /use-with-ai: an `mcpServers` entry that
+// runs the repo's MCP server against this archive (or, on a hub, the whole
+// federation). Pure, so the page and its unit test build the same text.
+//
+// - The server is keyed `archilyzer` whatever archive it reads: Claude Code
+// reads this same shape from `.mcp.json`, and the repo's `/ask` and `/sweep`
+// commands call `mcp__archilyzer__*` tools, whose names embed that key.
+// - `--silent` keeps pnpm's script banner off stdout, which is the JSON-RPC
+// channel: `pnpm archilyzer` is a `pnpm run`, and pnpm 9 and 10 print its
+// `> …` banner to stdout before the server starts.
+
+export const MCP_SERVER_NAME = "archilyzer";
+
+export function mcpServerSnippet(envVar: string, target: string): string {
+ const q = (s: string) => JSON.stringify(s);
+ return `{
+ "mcpServers": {
+ ${q(MCP_SERVER_NAME)}: {
+ "command": "pnpm",
+ "args": [
+ "--silent", "-C", "/path/to/yt-dlp-transcript-browser",
+ "archilyzer", "mcp"
+ ],
+ "env": { ${q(envVar)}: ${q(target)} }
+ }
+ }
+}`;
+}
diff --git a/export/app/use-with-ai/page.tsx b/export/app/use-with-ai/page.tsx
@@ -3,6 +3,7 @@ import Link from "next/link";
import { currentSite } from "../lib/site";
import { instanceMode } from "../lib/mode";
import { hasArchives } from "../lib/archives";
+import { MCP_SERVER_NAME, mcpServerSnippet } from "./mcpSnippet";
export const metadata: Metadata = { title: "Use with AI" };
@@ -19,19 +20,7 @@ export default function UseWithAiPage() {
const envVar = isHub ? "TRANSCRIPT_HUB_URL" : "TRANSCRIPT_SITE_URL";
const target = base || (isHub ? "https://your-hub.example" : "https://your-site.example");
- const mcpSnippet = `{
- "mcpServers": {
- "${site.siteId}": {
- "command": "pnpm",
- "args": [
- "-C", "/path/to/yt-dlp-transcript-browser",
- "--filter", "yt-dlp-transcript-mcp",
- "exec", "tsx", "src/index.ts"
- ],
- "env": { "${envVar}": "${target}" }
- }
- }
-}`;
+ const mcpSnippet = mcpServerSnippet(envVar, target);
return (
<div className="mx-auto flex max-w-3xl flex-col gap-10">
@@ -119,8 +108,12 @@ export default function UseWithAiPage() {
<code>{mcpSnippet}</code>
</pre>
<p className="text-xs text-muted-foreground/80">
- Setup details and the <code className="font-mono">claude mcp add</code>{" "}
- command are in <code className="font-mono">mcp/README.md</code>.
+ Keep the name <code className="font-mono">{MCP_SERVER_NAME}</code>: the
+ repo's <code className="font-mono">/ask</code> and{" "}
+ <code className="font-mono">/sweep</code> commands for Claude Code call
+ its tools by it. Setup details and the{" "}
+ <code className="font-mono">claude mcp add</code> command are in{" "}
+ <code className="font-mono">mcp/README.md</code>.
</p>
</div>
</section>