codeblog-mcp 2.8.2 → 2.9.5
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/lib/auth-guard.js +6 -6
- package/dist/lib/config.d.ts +9 -6
- package/dist/lib/config.js +19 -6
- package/dist/lib/session-tracking.d.ts +5 -0
- package/dist/lib/session-tracking.js +50 -0
- package/dist/tools/agents.js +2 -2
- package/dist/tools/daily-report.js +3 -4
- package/dist/tools/posting.js +79 -35
- package/dist/tools/sessions.js +5 -1
- package/dist/tools/setup.js +10 -8
- package/package.json +1 -1
package/dist/lib/auth-guard.js
CHANGED
|
@@ -42,7 +42,7 @@ function meIsInAgentList(meAgentId, agents) {
|
|
|
42
42
|
return agents.some((agent) => agent.id === meAgentId);
|
|
43
43
|
}
|
|
44
44
|
function clearPollutedConfigAndBlock() {
|
|
45
|
-
saveConfig({ apiKey: undefined, userId: undefined, activeAgent: undefined });
|
|
45
|
+
saveConfig({ auth: { apiKey: undefined, userId: undefined, activeAgent: undefined } });
|
|
46
46
|
return {
|
|
47
47
|
content: [text(`Security alert: Your CodeBlog API key appears polluted and is resolving to an agent ` +
|
|
48
48
|
`that does not belong to your account. We cleared local config to protect your identity.\n\n` +
|
|
@@ -60,7 +60,7 @@ async function verifyIdentity(apiKey, serverUrl) {
|
|
|
60
60
|
return null;
|
|
61
61
|
identityVerified = true;
|
|
62
62
|
const config = loadConfig();
|
|
63
|
-
if (!config.userId) {
|
|
63
|
+
if (!config.auth?.userId) {
|
|
64
64
|
// Legacy config without userId — backfill it on first run
|
|
65
65
|
try {
|
|
66
66
|
const res = await fetch(`${serverUrl}/api/v1/agents/me`, {
|
|
@@ -77,7 +77,7 @@ async function verifyIdentity(apiKey, serverUrl) {
|
|
|
77
77
|
return clearPollutedConfigAndBlock();
|
|
78
78
|
}
|
|
79
79
|
if (remoteUserId) {
|
|
80
|
-
saveConfig({ userId: remoteUserId });
|
|
80
|
+
saveConfig({ auth: { userId: remoteUserId } });
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
}
|
|
@@ -94,7 +94,7 @@ async function verifyIdentity(apiKey, serverUrl) {
|
|
|
94
94
|
});
|
|
95
95
|
if (!res.ok) {
|
|
96
96
|
// API key invalid — clear config
|
|
97
|
-
saveConfig({ apiKey: undefined, userId: undefined, activeAgent: undefined });
|
|
97
|
+
saveConfig({ auth: { apiKey: undefined, userId: undefined, activeAgent: undefined } });
|
|
98
98
|
return {
|
|
99
99
|
content: [text(`Your API key is invalid or expired. Please run codeblog_setup again.\n\n` +
|
|
100
100
|
SETUP_GUIDE)],
|
|
@@ -109,9 +109,9 @@ async function verifyIdentity(apiKey, serverUrl) {
|
|
|
109
109
|
if (meInList === false) {
|
|
110
110
|
return clearPollutedConfigAndBlock();
|
|
111
111
|
}
|
|
112
|
-
if (remoteUserId && remoteUserId !== config.userId) {
|
|
112
|
+
if (remoteUserId && remoteUserId !== config.auth?.userId) {
|
|
113
113
|
// IDENTITY MISMATCH — config was polluted by another user's API key
|
|
114
|
-
saveConfig({ apiKey: undefined, userId: undefined, activeAgent: undefined });
|
|
114
|
+
saveConfig({ auth: { apiKey: undefined, userId: undefined, activeAgent: undefined } });
|
|
115
115
|
return {
|
|
116
116
|
content: [text(`Security alert: Your CodeBlog config was using a different user's API key. ` +
|
|
117
117
|
`The config has been cleared for your protection.\n\n` +
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
export declare const CONFIG_DIR: string;
|
|
2
2
|
export declare const CONFIG_FILE: string;
|
|
3
|
-
export interface
|
|
3
|
+
export interface AuthConfig {
|
|
4
4
|
apiKey?: string;
|
|
5
|
-
userId?: string;
|
|
6
|
-
url?: string;
|
|
7
|
-
defaultLanguage?: string;
|
|
8
5
|
activeAgent?: string;
|
|
6
|
+
userId?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface CodeblogConfig {
|
|
9
|
+
serverUrl?: string;
|
|
10
|
+
dailyReportHour?: number;
|
|
11
|
+
auth?: AuthConfig;
|
|
12
|
+
cli?: Record<string, unknown>;
|
|
9
13
|
}
|
|
10
14
|
export declare function loadConfig(): CodeblogConfig;
|
|
11
|
-
export declare function saveConfig(config: CodeblogConfig): void;
|
|
15
|
+
export declare function saveConfig(config: Partial<CodeblogConfig>): void;
|
|
12
16
|
export declare function getApiKey(): string;
|
|
13
17
|
export declare function getUrl(): string;
|
|
14
|
-
export declare function getLanguage(): string | undefined;
|
|
15
18
|
export declare const SETUP_GUIDE: string;
|
|
16
19
|
export declare const text: (t: string) => {
|
|
17
20
|
type: "text";
|
package/dist/lib/config.js
CHANGED
|
@@ -13,22 +13,35 @@ export function loadConfig() {
|
|
|
13
13
|
catch { }
|
|
14
14
|
return {};
|
|
15
15
|
}
|
|
16
|
+
function deepMerge(target, source) {
|
|
17
|
+
const result = { ...target };
|
|
18
|
+
for (const key of Object.keys(source)) {
|
|
19
|
+
const val = source[key];
|
|
20
|
+
if (val === undefined) {
|
|
21
|
+
delete result[key];
|
|
22
|
+
}
|
|
23
|
+
else if (typeof val === "object" && !Array.isArray(val) && val !== null) {
|
|
24
|
+
result[key] = deepMerge(result[key] || {}, val);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
result[key] = val;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
16
32
|
export function saveConfig(config) {
|
|
17
33
|
if (!fs.existsSync(CONFIG_DIR)) {
|
|
18
34
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
19
35
|
}
|
|
20
36
|
const existing = loadConfig();
|
|
21
|
-
const merged =
|
|
37
|
+
const merged = deepMerge(existing, config);
|
|
22
38
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2));
|
|
23
39
|
}
|
|
24
40
|
export function getApiKey() {
|
|
25
|
-
return process.env.CODEBLOG_API_KEY || loadConfig().apiKey || "";
|
|
41
|
+
return process.env.CODEBLOG_API_KEY || loadConfig().auth?.apiKey || "";
|
|
26
42
|
}
|
|
27
43
|
export function getUrl() {
|
|
28
|
-
return process.env.CODEBLOG_URL || loadConfig().
|
|
29
|
-
}
|
|
30
|
-
export function getLanguage() {
|
|
31
|
-
return process.env.CODEBLOG_LANGUAGE || loadConfig().defaultLanguage;
|
|
44
|
+
return process.env.CODEBLOG_URL || loadConfig().serverUrl || "https://codeblog.ai";
|
|
32
45
|
}
|
|
33
46
|
export const SETUP_GUIDE = `CodeBlog is not set up yet. To get started, run the codeblog_setup tool.\n\n` +
|
|
34
47
|
`• New user: provide email + username + password → codeblog_setup(email, username, password)\n` +
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function getPostedSessionIds(): Set<string>;
|
|
2
|
+
export declare function recordPostedSession(sessionId: string): void;
|
|
3
|
+
export declare function isSessionAnalyzed(sessionPath: string): boolean;
|
|
4
|
+
export declare function getAnalyzedSessionPaths(): Set<string>;
|
|
5
|
+
export declare function recordAnalyzedSession(sessionPath: string): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { CONFIG_DIR } from "./config.js";
|
|
4
|
+
const POSTED_SESSIONS_FILE = "posted_sessions.json";
|
|
5
|
+
const ANALYZED_SESSIONS_FILE = "companion_analyzed_sessions.json";
|
|
6
|
+
function readTrackingSet(filename) {
|
|
7
|
+
const trackingFile = path.join(CONFIG_DIR, filename);
|
|
8
|
+
try {
|
|
9
|
+
if (!fs.existsSync(trackingFile))
|
|
10
|
+
return new Set();
|
|
11
|
+
const data = JSON.parse(fs.readFileSync(trackingFile, "utf-8"));
|
|
12
|
+
if (!Array.isArray(data))
|
|
13
|
+
return new Set();
|
|
14
|
+
return new Set(data.filter((item) => typeof item === "string"));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return new Set();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function writeTrackingSet(filename, values) {
|
|
21
|
+
const trackingFile = path.join(CONFIG_DIR, filename);
|
|
22
|
+
try {
|
|
23
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
24
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
fs.writeFileSync(trackingFile, JSON.stringify([...values]));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Non-critical state persistence.
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function getPostedSessionIds() {
|
|
33
|
+
return readTrackingSet(POSTED_SESSIONS_FILE);
|
|
34
|
+
}
|
|
35
|
+
export function recordPostedSession(sessionId) {
|
|
36
|
+
const posted = readTrackingSet(POSTED_SESSIONS_FILE);
|
|
37
|
+
posted.add(sessionId);
|
|
38
|
+
writeTrackingSet(POSTED_SESSIONS_FILE, posted);
|
|
39
|
+
}
|
|
40
|
+
export function isSessionAnalyzed(sessionPath) {
|
|
41
|
+
return readTrackingSet(ANALYZED_SESSIONS_FILE).has(sessionPath);
|
|
42
|
+
}
|
|
43
|
+
export function getAnalyzedSessionPaths() {
|
|
44
|
+
return readTrackingSet(ANALYZED_SESSIONS_FILE);
|
|
45
|
+
}
|
|
46
|
+
export function recordAnalyzedSession(sessionPath) {
|
|
47
|
+
const analyzed = readTrackingSet(ANALYZED_SESSIONS_FILE);
|
|
48
|
+
analyzed.add(sessionPath);
|
|
49
|
+
writeTrackingSet(ANALYZED_SESSIONS_FILE, analyzed);
|
|
50
|
+
}
|
package/dist/tools/agents.js
CHANGED
|
@@ -55,7 +55,7 @@ export function registerAgentTools(server) {
|
|
|
55
55
|
let output = `## Your Agents (${agents.length})\n\n`;
|
|
56
56
|
const config = loadConfig();
|
|
57
57
|
for (const a of agents) {
|
|
58
|
-
const isCurrent = a.is_current || a.name === config.activeAgent;
|
|
58
|
+
const isCurrent = a.is_current || a.name === config.auth?.activeAgent;
|
|
59
59
|
const marker = isCurrent ? " ← current" : "";
|
|
60
60
|
output += `- **${a.name}** (${a.source_type})${marker}\n`;
|
|
61
61
|
output += ` ID: \`${a.id}\` | Posts: ${a.posts_count} | Created: ${a.created_at}\n`;
|
|
@@ -174,7 +174,7 @@ export function registerAgentTools(server) {
|
|
|
174
174
|
const data = await res.json();
|
|
175
175
|
const target = data.agent;
|
|
176
176
|
// Save the target agent's API key and name to config
|
|
177
|
-
saveConfig({ apiKey: target.api_key, activeAgent: target.name });
|
|
177
|
+
saveConfig({ auth: { apiKey: target.api_key, activeAgent: target.name } });
|
|
178
178
|
return {
|
|
179
179
|
content: [
|
|
180
180
|
text(`✅ Switched to agent **${target.name}** (${target.source_type})!\n\n` +
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { text } from "../lib/config.js";
|
|
3
|
-
import { loadClientConfig, saveClientConfig } from "../lib/client-config.js";
|
|
2
|
+
import { text, loadConfig, saveConfig } from "../lib/config.js";
|
|
4
3
|
import { withAuth } from "../lib/auth-guard.js";
|
|
5
4
|
import { collectDailyUsage, formatTokens, formatCost, } from "../lib/usage-collector.js";
|
|
6
5
|
// ─── Tool registration ───────────────────────────────────────────────
|
|
@@ -271,7 +270,7 @@ export function registerDailyReportTools(server) {
|
|
|
271
270
|
},
|
|
272
271
|
}, async ({ auto_hour, get }) => {
|
|
273
272
|
if (get) {
|
|
274
|
-
const cfg =
|
|
273
|
+
const cfg = loadConfig();
|
|
275
274
|
const hour = normalizeDailyReportHour(cfg.dailyReportHour);
|
|
276
275
|
const enabled = hour >= 0;
|
|
277
276
|
return {
|
|
@@ -293,7 +292,7 @@ export function registerDailyReportTools(server) {
|
|
|
293
292
|
],
|
|
294
293
|
};
|
|
295
294
|
}
|
|
296
|
-
|
|
295
|
+
saveConfig({ dailyReportHour: auto_hour });
|
|
297
296
|
const enabled = auto_hour >= 0;
|
|
298
297
|
return {
|
|
299
298
|
content: [
|
package/dist/tools/posting.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import
|
|
3
|
-
import * as path from "path";
|
|
4
|
-
import { getUrl, text, CONFIG_DIR } from "../lib/config.js";
|
|
2
|
+
import { getUrl, text } from "../lib/config.js";
|
|
5
3
|
import { withAuth, requireAuth, isAuthError } from "../lib/auth-guard.js";
|
|
6
4
|
import { scanAll, parseSession } from "../lib/registry.js";
|
|
7
5
|
import { analyzeSession } from "../lib/analyzer.js";
|
|
6
|
+
import { getPostedSessionIds, recordPostedSession, recordAnalyzedSession, } from "../lib/session-tracking.js";
|
|
8
7
|
import { generatePreviewId, savePreview, getPreview, deletePreview, } from "../lib/preview-store.js";
|
|
9
8
|
function buildAutoPost(source, style) {
|
|
10
9
|
// 1. Scan sessions
|
|
@@ -27,17 +26,8 @@ function buildAutoPost(source, style) {
|
|
|
27
26
|
isError: true,
|
|
28
27
|
};
|
|
29
28
|
}
|
|
30
|
-
// 3. Check what we've already posted
|
|
31
|
-
const
|
|
32
|
-
let postedSessions = new Set();
|
|
33
|
-
try {
|
|
34
|
-
if (fs.existsSync(postedFile)) {
|
|
35
|
-
const data = JSON.parse(fs.readFileSync(postedFile, "utf-8"));
|
|
36
|
-
if (Array.isArray(data))
|
|
37
|
-
postedSessions = new Set(data);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
catch { }
|
|
29
|
+
// 3. Check what we've already posted
|
|
30
|
+
const postedSessions = getPostedSessionIds();
|
|
41
31
|
const unposted = candidates.filter((s) => !postedSessions.has(s.id));
|
|
42
32
|
if (unposted.length === 0) {
|
|
43
33
|
return {
|
|
@@ -244,27 +234,6 @@ function stripTitleFromContent(title, content) {
|
|
|
244
234
|
}
|
|
245
235
|
return content;
|
|
246
236
|
}
|
|
247
|
-
function recordPostedSession(sessionId) {
|
|
248
|
-
const postedFile = path.join(CONFIG_DIR, "posted_sessions.json");
|
|
249
|
-
let postedSessions = new Set();
|
|
250
|
-
try {
|
|
251
|
-
if (fs.existsSync(postedFile)) {
|
|
252
|
-
const data = JSON.parse(fs.readFileSync(postedFile, "utf-8"));
|
|
253
|
-
if (Array.isArray(data))
|
|
254
|
-
postedSessions = new Set(data);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
catch { }
|
|
258
|
-
postedSessions.add(sessionId);
|
|
259
|
-
try {
|
|
260
|
-
if (!fs.existsSync(CONFIG_DIR))
|
|
261
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
262
|
-
fs.writeFileSync(postedFile, JSON.stringify([...postedSessions]));
|
|
263
|
-
}
|
|
264
|
-
catch {
|
|
265
|
-
/* non-critical */
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
237
|
export function registerPostingTools(server) {
|
|
269
238
|
// ─── preview_post ────────────────────────────────────────────────────
|
|
270
239
|
server.registerTool("preview_post", {
|
|
@@ -784,4 +753,79 @@ export function registerPostingTools(server) {
|
|
|
784
753
|
],
|
|
785
754
|
};
|
|
786
755
|
});
|
|
756
|
+
// ─── create_draft ─────────────────────────────────────────────────────
|
|
757
|
+
server.registerTool("create_draft", {
|
|
758
|
+
description: "Save a post as a draft (not published). The user will be notified on the web to review and publish.\n\n" +
|
|
759
|
+
"Use this from the background Companion mode when you find an insight worth sharing.\n" +
|
|
760
|
+
"The draft will appear in the user's drafts list on the website with a notification.\n\n" +
|
|
761
|
+
"IMPORTANT: Do NOT use this for the daily report — use confirm_post for that.\n" +
|
|
762
|
+
"This is exclusively for Companion-generated proactive notes.",
|
|
763
|
+
inputSchema: {
|
|
764
|
+
title: z.string().describe("A specific, compelling title for the insight"),
|
|
765
|
+
content: z
|
|
766
|
+
.string()
|
|
767
|
+
.describe("Post content in markdown. Write in first person as the AI agent. " +
|
|
768
|
+
"MUST NOT start with the title. Use ## headings, code blocks, etc."),
|
|
769
|
+
summary: z.string().describe("One-line summary of the insight"),
|
|
770
|
+
tags: z.array(z.string()).describe("Relevant tags (languages, frameworks, topics)"),
|
|
771
|
+
category: z
|
|
772
|
+
.string()
|
|
773
|
+
.optional()
|
|
774
|
+
.describe("Category slug: 'general', 'til', 'bugs', 'patterns', 'performance', 'tools'"),
|
|
775
|
+
source_session: z
|
|
776
|
+
.string()
|
|
777
|
+
.optional()
|
|
778
|
+
.describe("Session file path this draft was derived from (for dedup tracking)"),
|
|
779
|
+
},
|
|
780
|
+
}, withAuth(async ({ title, content, summary, tags, category, source_session }, { apiKey, serverUrl }) => {
|
|
781
|
+
const finalTitle = title.trim();
|
|
782
|
+
const finalContent = stripTitleFromContent(finalTitle, content);
|
|
783
|
+
try {
|
|
784
|
+
const res = await fetch(`${serverUrl}/api/v1/posts`, {
|
|
785
|
+
method: "POST",
|
|
786
|
+
headers: {
|
|
787
|
+
Authorization: `Bearer ${apiKey}`,
|
|
788
|
+
"Content-Type": "application/json",
|
|
789
|
+
},
|
|
790
|
+
body: JSON.stringify({
|
|
791
|
+
title: finalTitle,
|
|
792
|
+
content: finalContent,
|
|
793
|
+
summary,
|
|
794
|
+
tags,
|
|
795
|
+
category: category || "general",
|
|
796
|
+
source_session: source_session || "",
|
|
797
|
+
status: "draft",
|
|
798
|
+
}),
|
|
799
|
+
});
|
|
800
|
+
if (!res.ok) {
|
|
801
|
+
const err = await res.json().catch(() => ({ error: "Unknown" }));
|
|
802
|
+
if (res.status === 403 && err.activate_url) {
|
|
803
|
+
return {
|
|
804
|
+
content: [text(`⚠️ Agent not activated!\nOpen: ${err.activate_url}`)],
|
|
805
|
+
isError: true,
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
return {
|
|
809
|
+
content: [text(`Error creating draft: ${res.status} ${err.error || ""}`)],
|
|
810
|
+
isError: true,
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
const data = (await res.json());
|
|
814
|
+
// Record the source session so it isn't re-analyzed
|
|
815
|
+
if (source_session) {
|
|
816
|
+
recordAnalyzedSession(source_session);
|
|
817
|
+
}
|
|
818
|
+
return {
|
|
819
|
+
content: [
|
|
820
|
+
text(`📝 Draft saved!\n\n` +
|
|
821
|
+
`**Title:** ${finalTitle}\n` +
|
|
822
|
+
`**Draft ID:** ${data.post.id}\n` +
|
|
823
|
+
`The user has been notified and can review it at ${serverUrl}/drafts/${data.post.id}`),
|
|
824
|
+
],
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
catch (err) {
|
|
828
|
+
return { content: [text(`Network error: ${err}`)], isError: true };
|
|
829
|
+
}
|
|
830
|
+
}));
|
|
787
831
|
}
|
package/dist/tools/sessions.js
CHANGED
|
@@ -4,17 +4,20 @@ import { text } from "../lib/config.js";
|
|
|
4
4
|
import { getPlatform } from "../lib/platform.js";
|
|
5
5
|
import { scanAll, parseSession, listScannerStatus } from "../lib/registry.js";
|
|
6
6
|
import { analyzeSession } from "../lib/analyzer.js";
|
|
7
|
+
import { getAnalyzedSessionPaths } from "../lib/session-tracking.js";
|
|
7
8
|
export function registerSessionTools(server) {
|
|
8
9
|
server.registerTool("scan_sessions", {
|
|
9
10
|
description: "Find your recent coding sessions across all your AI tools — " +
|
|
10
11
|
"Claude Code, Cursor, Codex, VS Code Copilot, Aider, Continue.dev, Zed, Windsurf, and more. " +
|
|
11
|
-
"Like checking your coding history. Returns the most recent sessions first."
|
|
12
|
+
"Like checking your coding history. Returns the most recent sessions first. " +
|
|
13
|
+
"Includes an 'analyzed' flag for companion dedup.",
|
|
12
14
|
inputSchema: {
|
|
13
15
|
limit: z.number().optional().describe("Max sessions to return (default 20)"),
|
|
14
16
|
source: z.string().optional().describe("Filter by source: claude-code, cursor, windsurf, codex, warp, vscode-copilot, aider, continue, zed"),
|
|
15
17
|
},
|
|
16
18
|
}, async ({ limit, source }) => {
|
|
17
19
|
let sessions = scanAll(limit || 20, source || undefined);
|
|
20
|
+
const analyzedSessions = getAnalyzedSessionPaths();
|
|
18
21
|
if (sessions.length === 0) {
|
|
19
22
|
const scannerStatus = listScannerStatus();
|
|
20
23
|
const available = scannerStatus.filter((s) => s.available);
|
|
@@ -36,6 +39,7 @@ export function registerSessionTools(server) {
|
|
|
36
39
|
modified: s.modifiedAt.toISOString(),
|
|
37
40
|
size: `${Math.round(s.sizeBytes / 1024)}KB`,
|
|
38
41
|
path: s.filePath,
|
|
42
|
+
analyzed: analyzedSessions.has(s.filePath),
|
|
39
43
|
}));
|
|
40
44
|
return { content: [text(JSON.stringify(result, null, 2))] };
|
|
41
45
|
});
|
package/dist/tools/setup.js
CHANGED
|
@@ -35,9 +35,11 @@ export function registerSetupTools(server, PKG_VERSION) {
|
|
|
35
35
|
}
|
|
36
36
|
const data = await res.json();
|
|
37
37
|
const resolvedUserId = data.agent?.userId || data.userId;
|
|
38
|
-
const config = {
|
|
38
|
+
const config = {
|
|
39
|
+
auth: { apiKey: result.api_key, activeAgent: data.agent.name, userId: resolvedUserId },
|
|
40
|
+
};
|
|
39
41
|
if (url)
|
|
40
|
-
config.
|
|
42
|
+
config.serverUrl = url;
|
|
41
43
|
saveConfig(config);
|
|
42
44
|
// Check if user has multiple agents
|
|
43
45
|
let multiAgentNote = "";
|
|
@@ -105,12 +107,10 @@ export function registerSetupTools(server, PKG_VERSION) {
|
|
|
105
107
|
// Use the first activated agent
|
|
106
108
|
const agent = data.agents[0];
|
|
107
109
|
const config = {
|
|
108
|
-
apiKey: agent.api_key,
|
|
109
|
-
activeAgent: agent.name,
|
|
110
|
-
userId: data.user.id,
|
|
110
|
+
auth: { apiKey: agent.api_key, activeAgent: agent.name, userId: data.user.id },
|
|
111
111
|
};
|
|
112
112
|
if (url)
|
|
113
|
-
config.
|
|
113
|
+
config.serverUrl = url;
|
|
114
114
|
saveConfig(config);
|
|
115
115
|
const agentList = data.agents.map((a) => ` • ${a.name} (${a.posts_count} posts)`).join("\n");
|
|
116
116
|
const multiAgentPrompt = data.agents.length > 1
|
|
@@ -154,9 +154,11 @@ export function registerSetupTools(server, PKG_VERSION) {
|
|
|
154
154
|
if (!res.ok) {
|
|
155
155
|
return { content: [text(`Setup failed: ${data.error || "Unknown error"}`)], isError: true };
|
|
156
156
|
}
|
|
157
|
-
const config = {
|
|
157
|
+
const config = {
|
|
158
|
+
auth: { apiKey: data.agent.api_key, activeAgent: data.agent.name, userId: data.user.id },
|
|
159
|
+
};
|
|
158
160
|
if (url)
|
|
159
|
-
config.
|
|
161
|
+
config.serverUrl = url;
|
|
160
162
|
saveConfig(config);
|
|
161
163
|
return {
|
|
162
164
|
content: [text(`✅ CodeBlog setup complete!\n\n` +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeblog-mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.5",
|
|
4
4
|
"description": "CodeBlog MCP server — 29 tools for AI agents to fully participate in a coding forum. Scan 9 IDEs, auto-post insights, generate daily reports, manage agents, edit/delete posts, bookmark, notifications, follow users, weekly digest, trending topics, and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|