thorbit-content-mcp 0.1.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.
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Thorbit Content MCP
2
+
3
+ Local stdio MCP server for Thorbit content research and on-page analysis. The package proxies tool calls to hosted Thorbit API routes; hosted Thorbit handles API-key auth, metering, MCP Scraper extraction, MCP Scraper SERP/PAA harvests, MCP Scraper browser-agent Reddit reads, and durable on-page analysis.
4
+
5
+ ## Install
6
+
7
+ Generate a Thorbit MCP API key from Thorbit Settings -> MCPs with content/onpage scopes:
8
+
9
+ - `content_onpage:read`
10
+ - `content_onpage:research`
11
+ - `content_onpage:analyze`
12
+
13
+ Then run:
14
+
15
+ ```bash
16
+ npx -y thorbit-content-mcp@latest
17
+ ```
18
+
19
+ MCP client example:
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "thorbit-content": {
25
+ "command": "npx",
26
+ "args": ["-y", "thorbit-content-mcp@latest"],
27
+ "env": {
28
+ "THORBIT_API_KEY": "thbt_mcp_..."
29
+ }
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ Generate the same JSON from the CLI:
36
+
37
+ ```bash
38
+ npx -y -p thorbit-content-mcp@latest thorbit-content-mcp-install --json --api-key thbt_mcp_...
39
+ ```
40
+
41
+ Prefer a key file on shared machines and servers:
42
+
43
+ ```bash
44
+ mkdir -p ~/.config/thorbit
45
+ printf '%s\n' 'thbt_mcp_...' > ~/.config/thorbit/content-mcp-key
46
+ chmod 600 ~/.config/thorbit/content-mcp-key
47
+ npx -y -p thorbit-content-mcp@latest thorbit-content-mcp-install --key-path ~/.config/thorbit/content-mcp-key
48
+ ```
49
+
50
+ ## Environment
51
+
52
+ - `THORBIT_API_KEY` or `THORBIT_MCP_API_KEY`: raw Thorbit MCP API key.
53
+ - `THORBIT_CONTENT_MCP_API_KEY`: content-specific raw key override.
54
+ - `THORBIT_CONTENT_MCP_KEY_PATH`: file containing the API key. Defaults to `~/.thorbit-content-mcp-key`.
55
+ - `THORBIT_BASE_URL`: Thorbit app URL. Defaults to `https://thorbit.ai`.
56
+ - `THORBIT_CONTENT_MCP_BASE_URL`: content-specific Thorbit app URL override.
57
+
58
+ ## Tools
59
+
60
+ - `thorbit_content_extract_url`: extract a URL through MCP Scraper.
61
+ - `thorbit_content_harvest_serp`: harvest SERP/PAA evidence through MCP Scraper.
62
+ - `thorbit_content_reddit_research`: discover Reddit candidates with MCP Scraper SERP and read posts through MCP Scraper browser-agent by default.
63
+ - `thorbit_onpage_start_analysis`: start durable Thorbit on-page analysis for a project keyword or inline content.
64
+ - `thorbit_onpage_get_analysis`: read persisted analysis status, score, signal counts, and summary.
65
+
66
+ ## Resources
67
+
68
+ - `thorbit-content://analyses/{analysisPublicId}`: JSON status and summary for one persisted on-page analysis.
69
+
70
+ ## Metering
71
+
72
+ The package cannot be used without a Thorbit MCP API key. Hosted Thorbit records MCP tool calls and provider costs against that key. Admin unmetered keys can be generated only through the server-side Thorbit operator script, not through public Settings routes.
@@ -0,0 +1,352 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // bin/thorbit-content-mcp-install.ts
22
+ var thorbit_content_mcp_install_exports = {};
23
+ __export(thorbit_content_mcp_install_exports, {
24
+ buildMcpConfig: () => buildMcpConfig,
25
+ hasFlag: () => hasFlag,
26
+ main: () => main,
27
+ readArg: () => readArg,
28
+ renderBanner: () => renderBanner,
29
+ renderHelp: () => renderHelp,
30
+ renderInstallInstructions: () => renderInstallInstructions,
31
+ resolveInstallOptions: () => resolveInstallOptions
32
+ });
33
+ module.exports = __toCommonJS(thorbit_content_mcp_install_exports);
34
+ var import_node_fs = require("fs");
35
+ var import_node_url = require("url");
36
+ var import_meta = {};
37
+ function readArg(name, argv = process.argv.slice(2)) {
38
+ const prefix = `--${name}=`;
39
+ const inline = argv.find((arg) => arg.startsWith(prefix));
40
+ if (inline) return inline.slice(prefix.length);
41
+ const index = argv.indexOf(`--${name}`);
42
+ return index >= 0 ? argv[index + 1] : void 0;
43
+ }
44
+ function hasFlag(name, argv = process.argv.slice(2)) {
45
+ return argv.includes(`--${name}`);
46
+ }
47
+ function resolveInstallOptions(argv = process.argv.slice(2)) {
48
+ return {
49
+ apiKey: readArg("api-key", argv) ?? process.env.THORBIT_API_KEY ?? process.env.THORBIT_MCP_API_KEY ?? "thbt_mcp_...",
50
+ baseUrl: readArg("base-url", argv) ?? process.env.THORBIT_BASE_URL,
51
+ keyPath: readArg("key-path", argv) ?? process.env.THORBIT_CONTENT_MCP_KEY_PATH,
52
+ serverName: readArg("server-name", argv) ?? "thorbit-content",
53
+ json: hasFlag("json", argv),
54
+ color: !hasFlag("no-color", argv),
55
+ help: hasFlag("help", argv) || hasFlag("h", argv)
56
+ };
57
+ }
58
+ function buildMcpConfig(options) {
59
+ const env = options.keyPath ? { THORBIT_CONTENT_MCP_KEY_PATH: options.keyPath } : { THORBIT_API_KEY: options.apiKey };
60
+ if (options.baseUrl) {
61
+ env.THORBIT_BASE_URL = options.baseUrl.replace(/\/$/, "");
62
+ }
63
+ return {
64
+ mcpServers: {
65
+ [options.serverName]: {
66
+ command: "npx",
67
+ args: ["-y", "thorbit-content-mcp@latest"],
68
+ env
69
+ }
70
+ }
71
+ };
72
+ }
73
+ var ansi = {
74
+ reset: "\x1B[0m",
75
+ bold: "\x1B[1m",
76
+ dim: "\x1B[2m",
77
+ terracotta: "\x1B[38;2;198;90;54m",
78
+ cardBg: "\x1B[48;2;31;31;31m",
79
+ cardBorder: "\x1B[38;2;108;66;50m",
80
+ clay: "\x1B[38;2;226;138;92m",
81
+ cream: "\x1B[38;2;255;244;230m",
82
+ green: "\x1B[38;2;75;181;67m",
83
+ shadow: "\x1B[38;2;116;70;56m",
84
+ slate: "\x1B[38;2;174;181;195m",
85
+ wire: "\x1B[38;2;198;90;54m"
86
+ };
87
+ function paint(value, code, enabled) {
88
+ return enabled ? `${code}${value}${ansi.reset}` : value;
89
+ }
90
+ function renderHelp(color) {
91
+ return [
92
+ renderBanner(color),
93
+ "",
94
+ "Usage:",
95
+ " npx -y -p thorbit-content-mcp@latest thorbit-content-mcp-install [options]",
96
+ "",
97
+ "Options:",
98
+ " --api-key <key> Thorbit MCP API key from Settings -> MCPs.",
99
+ " --key-path <path> File containing the API key. Preferred for shared machines and servers.",
100
+ " --base-url <url> Thorbit app URL. Defaults to https://thorbit.ai.",
101
+ " --server-name <name> MCP client server name. Defaults to thorbit-content.",
102
+ " --json Print only MCP client JSON.",
103
+ " --no-color Disable ANSI color.",
104
+ " --help Show this help.",
105
+ ""
106
+ ].join("\n");
107
+ }
108
+ function renderBanner(color) {
109
+ return color ? renderReferenceCardBanner() : renderAsciiBanner();
110
+ }
111
+ var cardWidth = 104;
112
+ var thorbitPixelLetters = {
113
+ T: [
114
+ "1111111",
115
+ "0011000",
116
+ "0011000",
117
+ "0011000",
118
+ "0011000",
119
+ "0011000",
120
+ "0011000"
121
+ ],
122
+ H: [
123
+ "110011",
124
+ "110011",
125
+ "110011",
126
+ "111111",
127
+ "110011",
128
+ "110011",
129
+ "110011"
130
+ ],
131
+ O: [
132
+ "011110",
133
+ "110011",
134
+ "110011",
135
+ "110011",
136
+ "110011",
137
+ "110011",
138
+ "011110"
139
+ ],
140
+ R: [
141
+ "111110",
142
+ "110011",
143
+ "110011",
144
+ "111110",
145
+ "110110",
146
+ "110011",
147
+ "110011"
148
+ ],
149
+ B: [
150
+ "111110",
151
+ "110011",
152
+ "110011",
153
+ "111110",
154
+ "110011",
155
+ "110011",
156
+ "111110"
157
+ ],
158
+ I: [
159
+ "1111",
160
+ "0110",
161
+ "0110",
162
+ "0110",
163
+ "0110",
164
+ "0110",
165
+ "1111"
166
+ ]
167
+ };
168
+ function renderReferenceCardBanner() {
169
+ const heading = justifyCardContent(" Plain text", "\u29C9", cardWidth);
170
+ return [
171
+ `${ansi.cardBorder}\u256D${"\u2500".repeat(cardWidth + 2)}\u256E${ansi.reset}`,
172
+ renderCardLine(heading, "title"),
173
+ renderCardLine("", "blank"),
174
+ ...renderLayeredPixelWordmarkCardLines("THORBIT"),
175
+ renderCardLine("", "blank"),
176
+ renderCardLine(" THORBIT CONTENT MCP", "caption"),
177
+ `${ansi.cardBorder}\u2570${"\u2500".repeat(cardWidth + 2)}\u256F${ansi.reset}`
178
+ ].join("\n");
179
+ }
180
+ function renderAsciiBanner() {
181
+ const contentWidth = 96;
182
+ const border = `+${"-".repeat(contentWidth + 2)}+`;
183
+ const cardLine = (content = "") => `| ${content.padEnd(contentWidth)} |`;
184
+ const title = "Plain text";
185
+ const copy = "[copy]";
186
+ const lines = [
187
+ border,
188
+ cardLine(`${title}${" ".repeat(contentWidth - title.length - copy.length)}${copy}`),
189
+ cardLine(),
190
+ ...renderAsciiWordmark("THORBIT").map((line) => cardLine(` ${line}`)),
191
+ cardLine(),
192
+ cardLine(" THORBIT CONTENT MCP"),
193
+ border
194
+ ];
195
+ return lines.join("\n");
196
+ }
197
+ function renderCardLine(content, tone) {
198
+ const foreground = {
199
+ title: ansi.cream,
200
+ mark: ansi.clay,
201
+ wire: ansi.wire,
202
+ caption: ansi.terracotta,
203
+ blank: ansi.slate
204
+ }[tone];
205
+ return renderCardLineParts([{ color: foreground, text: content }]);
206
+ }
207
+ function renderCardLineParts(parts) {
208
+ const visibleWidth = parts.reduce((width, part) => width + part.text.length, 0);
209
+ const padding = " ".repeat(Math.max(0, cardWidth - visibleWidth));
210
+ return [
211
+ `${ansi.cardBorder}\u2502${ansi.reset}`,
212
+ ansi.cardBg,
213
+ " ",
214
+ ...parts.map((part) => `${part.color}${part.text}`),
215
+ padding,
216
+ " ",
217
+ ansi.reset,
218
+ `${ansi.cardBorder}\u2502${ansi.reset}`
219
+ ].join("");
220
+ }
221
+ function justifyCardContent(left, right, width) {
222
+ return `${left}${" ".repeat(Math.max(1, width - left.length - right.length))}${right}`;
223
+ }
224
+ function buildPixelWordmarkMatrix(word) {
225
+ const rows = Array.from({ length: 7 }, () => []);
226
+ for (let rowIndex = 0; rowIndex < 7; rowIndex += 1) {
227
+ word.split("").forEach((letter, letterIndex) => {
228
+ const pattern = thorbitPixelLetters[letter];
229
+ if (!pattern) return;
230
+ if (letterIndex > 0) rows[rowIndex].push(false);
231
+ rows[rowIndex].push(...pattern[rowIndex].split("").map((cell) => cell === "1"));
232
+ });
233
+ }
234
+ return rows;
235
+ }
236
+ function renderLayeredPixelWordmarkCardLines(word) {
237
+ const matrix = buildPixelWordmarkMatrix(word);
238
+ const wordmarkWidth = Math.max(...matrix.map((row) => row.length));
239
+ const shadowOffsetX = 1;
240
+ const shadowOffsetY = -1;
241
+ const outputRows = matrix.length + Math.abs(Math.min(0, shadowOffsetY));
242
+ const outputWidth = wordmarkWidth + shadowOffsetX;
243
+ return Array.from({ length: outputRows }, (_, outputRowIndex) => {
244
+ const rowParts = [{ color: ansi.slate, text: " " }];
245
+ for (let columnIndex = 0; columnIndex < outputWidth; columnIndex += 1) {
246
+ const foregroundRow = outputRowIndex - Math.abs(Math.min(0, shadowOffsetY));
247
+ const hasForeground = foregroundRow >= 0 && Boolean(matrix[foregroundRow]?.[columnIndex]);
248
+ const shadowSourceRow = outputRowIndex - shadowOffsetY - Math.abs(Math.min(0, shadowOffsetY));
249
+ const shadowSourceColumn = columnIndex - shadowOffsetX;
250
+ const hasShadow = shadowSourceRow >= 0 && shadowSourceColumn >= 0 && Boolean(matrix[shadowSourceRow]?.[shadowSourceColumn]);
251
+ if (hasForeground) {
252
+ appendCardPart(rowParts, ansi.clay, "\u2588\u2588");
253
+ } else if (hasShadow) {
254
+ appendCardPart(rowParts, ansi.shadow, "\u2591\u2591");
255
+ } else {
256
+ appendCardPart(rowParts, ansi.slate, " ");
257
+ }
258
+ }
259
+ return renderCardLineParts(rowParts);
260
+ });
261
+ }
262
+ function appendCardPart(parts, color, text) {
263
+ const previous = parts[parts.length - 1];
264
+ if (previous?.color === color) {
265
+ previous.text += text;
266
+ return;
267
+ }
268
+ parts.push({ color, text });
269
+ }
270
+ function renderAsciiWordmark(word) {
271
+ const matrix = buildPixelWordmarkMatrix(word);
272
+ const rows = [];
273
+ for (const matrixRow of matrix) {
274
+ rows.push(matrixRow.map((cell) => cell ? "#" : " ").join(""));
275
+ }
276
+ return rows;
277
+ }
278
+ function renderInstallInstructions(options) {
279
+ const color = options.color;
280
+ const json = JSON.stringify(buildMcpConfig(options), null, 2);
281
+ const keySetup = options.keyPath ? [
282
+ paint("Key file mode", ansi.terracotta, color),
283
+ ` chmod 600 ${options.keyPath}`
284
+ ].join("\n") : [
285
+ paint("Safer key-file option", ansi.terracotta, color),
286
+ " mkdir -p ~/.config/thorbit",
287
+ " printf '%s\\n' 'thbt_mcp_...' > ~/.config/thorbit/content-mcp-key",
288
+ " chmod 600 ~/.config/thorbit/content-mcp-key",
289
+ "",
290
+ " Then run:",
291
+ " npx -y -p thorbit-content-mcp@latest thorbit-content-mcp-install --key-path ~/.config/thorbit/content-mcp-key"
292
+ ].join("\n");
293
+ return [
294
+ renderBanner(color),
295
+ paint("MCP Scraper research and on-page analysis for MCP agents.", ansi.slate, color),
296
+ "",
297
+ `${paint("1.", ansi.terracotta, color)} Generate an API key in Thorbit Settings -> MCPs with content/onpage scopes.`,
298
+ `${paint("2.", ansi.terracotta, color)} Add this server config to your MCP client:`,
299
+ "",
300
+ json,
301
+ "",
302
+ `${paint("3.", ansi.terracotta, color)} Restart your MCP client, then call ${paint("thorbit_content_harvest_serp", ansi.green, color)} or ${paint("thorbit_content_reddit_research", ansi.green, color)}.`,
303
+ "",
304
+ keySetup,
305
+ "",
306
+ paint("Tools", ansi.terracotta, color),
307
+ " thorbit_content_extract_url Extract a URL through MCP Scraper.",
308
+ " thorbit_content_harvest_serp Harvest SERP/PAA evidence through MCP Scraper.",
309
+ " thorbit_content_reddit_research Read Reddit through MCP Scraper browser-agent.",
310
+ " thorbit_onpage_start_analysis Start durable Thorbit on-page analysis.",
311
+ " thorbit_onpage_get_analysis Read analysis status and summary.",
312
+ "",
313
+ paint("Raw JSON:", ansi.slate, color),
314
+ " npx -y -p thorbit-content-mcp@latest thorbit-content-mcp-install --json --api-key thbt_mcp_...",
315
+ ""
316
+ ].join("\n");
317
+ }
318
+ function main() {
319
+ const options = resolveInstallOptions();
320
+ if (options.help) {
321
+ process.stdout.write(renderHelp(options.color));
322
+ return;
323
+ }
324
+ if (options.json) {
325
+ process.stdout.write(`${JSON.stringify(buildMcpConfig(options), null, 2)}
326
+ `);
327
+ return;
328
+ }
329
+ process.stdout.write(renderInstallInstructions(options));
330
+ }
331
+ function isMainModule() {
332
+ const entry = process.argv[1];
333
+ if (!entry) return false;
334
+ try {
335
+ return (0, import_node_fs.realpathSync)(entry) === (0, import_node_fs.realpathSync)((0, import_node_url.fileURLToPath)(import_meta.url));
336
+ } catch {
337
+ return false;
338
+ }
339
+ }
340
+ if (isMainModule()) main();
341
+ // Annotate the CommonJS export names for ESM import in node:
342
+ 0 && (module.exports = {
343
+ buildMcpConfig,
344
+ hasFlag,
345
+ main,
346
+ readArg,
347
+ renderBanner,
348
+ renderHelp,
349
+ renderInstallInstructions,
350
+ resolveInstallOptions
351
+ });
352
+ //# sourceMappingURL=thorbit-content-mcp-install.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../bin/thorbit-content-mcp-install.ts"],"sourcesContent":["import { realpathSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\n\nexport type InstallOptions = {\n apiKey: string\n baseUrl?: string\n keyPath?: string\n serverName: string\n json: boolean\n color: boolean\n help: boolean\n}\n\nexport function readArg(name: string, argv = process.argv.slice(2)): string | undefined {\n const prefix = `--${name}=`\n const inline = argv.find(arg => arg.startsWith(prefix))\n if (inline) return inline.slice(prefix.length)\n const index = argv.indexOf(`--${name}`)\n return index >= 0 ? argv[index + 1] : undefined\n}\n\nexport function hasFlag(name: string, argv = process.argv.slice(2)): boolean {\n return argv.includes(`--${name}`)\n}\n\nexport function resolveInstallOptions(argv = process.argv.slice(2)): InstallOptions {\n return {\n apiKey: readArg('api-key', argv) ?? process.env.THORBIT_API_KEY ?? process.env.THORBIT_MCP_API_KEY ?? 'thbt_mcp_...',\n baseUrl: readArg('base-url', argv) ?? process.env.THORBIT_BASE_URL,\n keyPath: readArg('key-path', argv) ?? process.env.THORBIT_CONTENT_MCP_KEY_PATH,\n serverName: readArg('server-name', argv) ?? 'thorbit-content',\n json: hasFlag('json', argv),\n color: !hasFlag('no-color', argv),\n help: hasFlag('help', argv) || hasFlag('h', argv),\n }\n}\n\nexport function buildMcpConfig(options: InstallOptions) {\n const env: Record<string, string> = options.keyPath\n ? { THORBIT_CONTENT_MCP_KEY_PATH: options.keyPath }\n : { THORBIT_API_KEY: options.apiKey }\n\n if (options.baseUrl) {\n env.THORBIT_BASE_URL = options.baseUrl.replace(/\\/$/, '')\n }\n\n return {\n mcpServers: {\n [options.serverName]: {\n command: 'npx',\n args: ['-y', 'thorbit-content-mcp@latest'],\n env,\n },\n },\n }\n}\n\nconst ansi = {\n reset: '\\u001b[0m',\n bold: '\\u001b[1m',\n dim: '\\u001b[2m',\n terracotta: '\\u001b[38;2;198;90;54m',\n cardBg: '\\u001b[48;2;31;31;31m',\n cardBorder: '\\u001b[38;2;108;66;50m',\n clay: '\\u001b[38;2;226;138;92m',\n cream: '\\u001b[38;2;255;244;230m',\n green: '\\u001b[38;2;75;181;67m',\n shadow: '\\u001b[38;2;116;70;56m',\n slate: '\\u001b[38;2;174;181;195m',\n wire: '\\u001b[38;2;198;90;54m',\n}\n\nfunction paint(value: string, code: string, enabled: boolean): string {\n return enabled ? `${code}${value}${ansi.reset}` : value\n}\n\nexport function renderHelp(color: boolean): string {\n return [\n renderBanner(color),\n '',\n 'Usage:',\n ' npx -y -p thorbit-content-mcp@latest thorbit-content-mcp-install [options]',\n '',\n 'Options:',\n ' --api-key <key> Thorbit MCP API key from Settings -> MCPs.',\n ' --key-path <path> File containing the API key. Preferred for shared machines and servers.',\n ' --base-url <url> Thorbit app URL. Defaults to https://thorbit.ai.',\n ' --server-name <name> MCP client server name. Defaults to thorbit-content.',\n ' --json Print only MCP client JSON.',\n ' --no-color Disable ANSI color.',\n ' --help Show this help.',\n '',\n ].join('\\n')\n}\n\nexport function renderBanner(color: boolean): string {\n return color ? renderReferenceCardBanner() : renderAsciiBanner()\n}\n\nconst cardWidth = 104\n\ntype CardTone = 'title' | 'mark' | 'wire' | 'caption' | 'blank'\ntype CardPart = {\n color: string\n text: string\n}\n\nconst thorbitPixelLetters: Record<string, string[]> = {\n T: [\n '1111111',\n '0011000',\n '0011000',\n '0011000',\n '0011000',\n '0011000',\n '0011000',\n ],\n H: [\n '110011',\n '110011',\n '110011',\n '111111',\n '110011',\n '110011',\n '110011',\n ],\n O: [\n '011110',\n '110011',\n '110011',\n '110011',\n '110011',\n '110011',\n '011110',\n ],\n R: [\n '111110',\n '110011',\n '110011',\n '111110',\n '110110',\n '110011',\n '110011',\n ],\n B: [\n '111110',\n '110011',\n '110011',\n '111110',\n '110011',\n '110011',\n '111110',\n ],\n I: [\n '1111',\n '0110',\n '0110',\n '0110',\n '0110',\n '0110',\n '1111',\n ],\n}\n\nfunction renderReferenceCardBanner(): string {\n const heading = justifyCardContent(' Plain text', '⧉', cardWidth)\n\n return [\n `${ansi.cardBorder}╭${'─'.repeat(cardWidth + 2)}╮${ansi.reset}`,\n renderCardLine(heading, 'title'),\n renderCardLine('', 'blank'),\n ...renderLayeredPixelWordmarkCardLines('THORBIT'),\n renderCardLine('', 'blank'),\n renderCardLine(' THORBIT CONTENT MCP', 'caption'),\n `${ansi.cardBorder}╰${'─'.repeat(cardWidth + 2)}╯${ansi.reset}`,\n ].join('\\n')\n}\n\nfunction renderAsciiBanner(): string {\n const contentWidth = 96\n const border = `+${'-'.repeat(contentWidth + 2)}+`\n const cardLine = (content = '') => `| ${content.padEnd(contentWidth)} |`\n const title = 'Plain text'\n const copy = '[copy]'\n const lines = [\n border,\n cardLine(`${title}${' '.repeat(contentWidth - title.length - copy.length)}${copy}`),\n cardLine(),\n ...renderAsciiWordmark('THORBIT').map(line => cardLine(` ${line}`)),\n cardLine(),\n cardLine(' THORBIT CONTENT MCP'),\n border,\n ]\n\n return lines.join('\\n')\n}\n\nfunction renderCardLine(content: string, tone: CardTone): string {\n const foreground = {\n title: ansi.cream,\n mark: ansi.clay,\n wire: ansi.wire,\n caption: ansi.terracotta,\n blank: ansi.slate,\n }[tone]\n return renderCardLineParts([{ color: foreground, text: content }])\n}\n\nfunction renderCardLineParts(parts: CardPart[]): string {\n const visibleWidth = parts.reduce((width, part) => width + part.text.length, 0)\n const padding = ' '.repeat(Math.max(0, cardWidth - visibleWidth))\n return [\n `${ansi.cardBorder}│${ansi.reset}`,\n ansi.cardBg,\n ' ',\n ...parts.map(part => `${part.color}${part.text}`),\n padding,\n ' ',\n ansi.reset,\n `${ansi.cardBorder}│${ansi.reset}`,\n ].join('')\n}\n\nfunction justifyCardContent(left: string, right: string, width: number): string {\n return `${left}${' '.repeat(Math.max(1, width - left.length - right.length))}${right}`\n}\n\nfunction buildPixelWordmarkMatrix(word: string): boolean[][] {\n const rows: boolean[][] = Array.from({ length: 7 }, () => [])\n for (let rowIndex = 0; rowIndex < 7; rowIndex += 1) {\n word.split('').forEach((letter, letterIndex) => {\n const pattern = thorbitPixelLetters[letter]\n if (!pattern) return\n if (letterIndex > 0) rows[rowIndex].push(false)\n rows[rowIndex].push(...pattern[rowIndex].split('').map(cell => cell === '1'))\n })\n }\n return rows\n}\n\nfunction renderLayeredPixelWordmarkCardLines(word: string): string[] {\n const matrix = buildPixelWordmarkMatrix(word)\n const wordmarkWidth = Math.max(...matrix.map(row => row.length))\n const shadowOffsetX = 1\n const shadowOffsetY = -1\n const outputRows = matrix.length + Math.abs(Math.min(0, shadowOffsetY))\n const outputWidth = wordmarkWidth + shadowOffsetX\n\n return Array.from({ length: outputRows }, (_, outputRowIndex) => {\n const rowParts: CardPart[] = [{ color: ansi.slate, text: ' ' }]\n\n for (let columnIndex = 0; columnIndex < outputWidth; columnIndex += 1) {\n const foregroundRow = outputRowIndex - Math.abs(Math.min(0, shadowOffsetY))\n const hasForeground = foregroundRow >= 0 && Boolean(matrix[foregroundRow]?.[columnIndex])\n const shadowSourceRow = outputRowIndex - shadowOffsetY - Math.abs(Math.min(0, shadowOffsetY))\n const shadowSourceColumn = columnIndex - shadowOffsetX\n const hasShadow = shadowSourceRow >= 0 && shadowSourceColumn >= 0\n && Boolean(matrix[shadowSourceRow]?.[shadowSourceColumn])\n\n if (hasForeground) {\n appendCardPart(rowParts, ansi.clay, '██')\n } else if (hasShadow) {\n appendCardPart(rowParts, ansi.shadow, '░░')\n } else {\n appendCardPart(rowParts, ansi.slate, ' ')\n }\n }\n\n return renderCardLineParts(rowParts)\n })\n}\n\nfunction appendCardPart(parts: CardPart[], color: string, text: string): void {\n const previous = parts[parts.length - 1]\n if (previous?.color === color) {\n previous.text += text\n return\n }\n parts.push({ color, text })\n}\n\nfunction renderAsciiWordmark(word: string): string[] {\n const matrix = buildPixelWordmarkMatrix(word)\n const rows: string[] = []\n for (const matrixRow of matrix) {\n rows.push(matrixRow.map(cell => (cell ? '#' : ' ')).join(''))\n }\n return rows\n}\n\nexport function renderInstallInstructions(options: InstallOptions): string {\n const color = options.color\n const json = JSON.stringify(buildMcpConfig(options), null, 2)\n const keySetup = options.keyPath\n ? [\n paint('Key file mode', ansi.terracotta, color),\n ` chmod 600 ${options.keyPath}`,\n ].join('\\n')\n : [\n paint('Safer key-file option', ansi.terracotta, color),\n ' mkdir -p ~/.config/thorbit',\n \" printf '%s\\\\n' 'thbt_mcp_...' > ~/.config/thorbit/content-mcp-key\",\n ' chmod 600 ~/.config/thorbit/content-mcp-key',\n '',\n ' Then run:',\n ' npx -y -p thorbit-content-mcp@latest thorbit-content-mcp-install --key-path ~/.config/thorbit/content-mcp-key',\n ].join('\\n')\n\n return [\n renderBanner(color),\n paint('MCP Scraper research and on-page analysis for MCP agents.', ansi.slate, color),\n '',\n `${paint('1.', ansi.terracotta, color)} Generate an API key in Thorbit Settings -> MCPs with content/onpage scopes.`,\n `${paint('2.', ansi.terracotta, color)} Add this server config to your MCP client:`,\n '',\n json,\n '',\n `${paint('3.', ansi.terracotta, color)} Restart your MCP client, then call ${paint('thorbit_content_harvest_serp', ansi.green, color)} or ${paint('thorbit_content_reddit_research', ansi.green, color)}.`,\n '',\n keySetup,\n '',\n paint('Tools', ansi.terracotta, color),\n ' thorbit_content_extract_url Extract a URL through MCP Scraper.',\n ' thorbit_content_harvest_serp Harvest SERP/PAA evidence through MCP Scraper.',\n ' thorbit_content_reddit_research Read Reddit through MCP Scraper browser-agent.',\n ' thorbit_onpage_start_analysis Start durable Thorbit on-page analysis.',\n ' thorbit_onpage_get_analysis Read analysis status and summary.',\n '',\n paint('Raw JSON:', ansi.slate, color),\n ' npx -y -p thorbit-content-mcp@latest thorbit-content-mcp-install --json --api-key thbt_mcp_...',\n '',\n ].join('\\n')\n}\n\nexport function main(): void {\n const options = resolveInstallOptions()\n if (options.help) {\n process.stdout.write(renderHelp(options.color))\n return\n }\n\n if (options.json) {\n process.stdout.write(`${JSON.stringify(buildMcpConfig(options), null, 2)}\\n`)\n return\n }\n\n process.stdout.write(renderInstallInstructions(options))\n}\n\nfunction isMainModule(): boolean {\n const entry = process.argv[1]\n if (!entry) return false\n try {\n return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url))\n } catch {\n return false\n }\n}\n\nif (isMainModule()) main()\n"],"mappings":"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","names":[]}
@@ -0,0 +1,27 @@
1
+ type InstallOptions = {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ keyPath?: string;
5
+ serverName: string;
6
+ json: boolean;
7
+ color: boolean;
8
+ help: boolean;
9
+ };
10
+ declare function readArg(name: string, argv?: string[]): string | undefined;
11
+ declare function hasFlag(name: string, argv?: string[]): boolean;
12
+ declare function resolveInstallOptions(argv?: string[]): InstallOptions;
13
+ declare function buildMcpConfig(options: InstallOptions): {
14
+ mcpServers: {
15
+ [options.serverName]: {
16
+ command: string;
17
+ args: string[];
18
+ env: Record<string, string>;
19
+ };
20
+ };
21
+ };
22
+ declare function renderHelp(color: boolean): string;
23
+ declare function renderBanner(color: boolean): string;
24
+ declare function renderInstallInstructions(options: InstallOptions): string;
25
+ declare function main(): void;
26
+
27
+ export { type InstallOptions, buildMcpConfig, hasFlag, main, readArg, renderBanner, renderHelp, renderInstallInstructions, resolveInstallOptions };
@@ -0,0 +1,27 @@
1
+ type InstallOptions = {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ keyPath?: string;
5
+ serverName: string;
6
+ json: boolean;
7
+ color: boolean;
8
+ help: boolean;
9
+ };
10
+ declare function readArg(name: string, argv?: string[]): string | undefined;
11
+ declare function hasFlag(name: string, argv?: string[]): boolean;
12
+ declare function resolveInstallOptions(argv?: string[]): InstallOptions;
13
+ declare function buildMcpConfig(options: InstallOptions): {
14
+ mcpServers: {
15
+ [options.serverName]: {
16
+ command: string;
17
+ args: string[];
18
+ env: Record<string, string>;
19
+ };
20
+ };
21
+ };
22
+ declare function renderHelp(color: boolean): string;
23
+ declare function renderBanner(color: boolean): string;
24
+ declare function renderInstallInstructions(options: InstallOptions): string;
25
+ declare function main(): void;
26
+
27
+ export { type InstallOptions, buildMcpConfig, hasFlag, main, readArg, renderBanner, renderHelp, renderInstallInstructions, resolveInstallOptions };