@claudeink/mcp-server 0.5.0 → 0.6.1
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/index.js +142 -175
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
6
6
|
|
|
7
7
|
// src/tools/source.ts
|
|
8
8
|
import { z } from "zod";
|
|
9
|
-
import { mkdir as mkdir3 } from "fs/promises";
|
|
9
|
+
import { mkdir as mkdir3, readFile as readFile4 } from "fs/promises";
|
|
10
10
|
import { join as join4 } from "path";
|
|
11
11
|
|
|
12
12
|
// src/lib/config.ts
|
|
@@ -23,7 +23,7 @@ var PATHS = {
|
|
|
23
23
|
logs: join(CLAUDEINK_DIR, "logs")
|
|
24
24
|
};
|
|
25
25
|
var DEFAULT_CONFIG = {
|
|
26
|
-
apiBaseUrl: "https://
|
|
26
|
+
apiBaseUrl: "https://app.claudeink.com",
|
|
27
27
|
syncIntervalMs: 3e5,
|
|
28
28
|
// 5 minutes
|
|
29
29
|
heartbeatIntervalMs: 3e5,
|
|
@@ -39,9 +39,6 @@ var DEFAULT_TAG_QUEUE = {
|
|
|
39
39
|
avgTagsPerItem: 0
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
|
-
var DEFAULT_CRAWL_SCHEDULES = {
|
|
43
|
-
schedules: []
|
|
44
|
-
};
|
|
45
42
|
async function ensureDir() {
|
|
46
43
|
await mkdir(CLAUDEINK_DIR, { recursive: true });
|
|
47
44
|
await mkdir(PATHS.logs, { recursive: true });
|
|
@@ -73,18 +70,22 @@ async function getCredentials() {
|
|
|
73
70
|
if (!await fileExists(PATHS.credentials)) return null;
|
|
74
71
|
return readJson(PATHS.credentials, null);
|
|
75
72
|
}
|
|
73
|
+
async function saveCredentials(creds) {
|
|
74
|
+
await writeJson(PATHS.credentials, creds, true);
|
|
75
|
+
}
|
|
76
76
|
async function getConfig() {
|
|
77
77
|
return readJson(PATHS.config, DEFAULT_CONFIG);
|
|
78
78
|
}
|
|
79
|
+
async function saveConfig(config) {
|
|
80
|
+
const current = await getConfig();
|
|
81
|
+
await writeJson(PATHS.config, { ...current, ...config });
|
|
82
|
+
}
|
|
79
83
|
async function getTagQueue() {
|
|
80
84
|
return readJson(PATHS.tagQueue, DEFAULT_TAG_QUEUE);
|
|
81
85
|
}
|
|
82
86
|
async function saveTagQueue(queue) {
|
|
83
87
|
await writeJson(PATHS.tagQueue, queue);
|
|
84
88
|
}
|
|
85
|
-
async function getCrawlSchedules() {
|
|
86
|
-
return readJson(PATHS.crawlSchedules, DEFAULT_CRAWL_SCHEDULES);
|
|
87
|
-
}
|
|
88
89
|
|
|
89
90
|
// src/lib/sources.ts
|
|
90
91
|
import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
@@ -166,6 +167,7 @@ var DEFAULT_STATE = {
|
|
|
166
167
|
published: {},
|
|
167
168
|
configs: {},
|
|
168
169
|
crawlerSources: {},
|
|
170
|
+
writingMasters: {},
|
|
169
171
|
lastSyncAt: ""
|
|
170
172
|
};
|
|
171
173
|
async function getStatePath() {
|
|
@@ -211,11 +213,6 @@ async function moveDraftToPublished(id, data) {
|
|
|
211
213
|
state.published[id] = data;
|
|
212
214
|
await writeState(state);
|
|
213
215
|
}
|
|
214
|
-
async function updateConfig(key, data) {
|
|
215
|
-
const state = await readState();
|
|
216
|
-
state.configs[key] = data;
|
|
217
|
-
await writeState(state);
|
|
218
|
-
}
|
|
219
216
|
async function updateCrawlerSource(id, data) {
|
|
220
217
|
const state = await readState();
|
|
221
218
|
state.crawlerSources[id] = data;
|
|
@@ -254,7 +251,13 @@ async function sourceAdd(input) {
|
|
|
254
251
|
const filePath = join4(dir, filename);
|
|
255
252
|
const meta = {
|
|
256
253
|
title: input.title,
|
|
257
|
-
source: input.url ?
|
|
254
|
+
source: input.url ? (() => {
|
|
255
|
+
try {
|
|
256
|
+
return new URL(input.url).hostname;
|
|
257
|
+
} catch {
|
|
258
|
+
return input.url;
|
|
259
|
+
}
|
|
260
|
+
})() : "manual",
|
|
258
261
|
published: date,
|
|
259
262
|
url: input.url
|
|
260
263
|
};
|
|
@@ -303,14 +306,21 @@ var sourceCrawlSchema = z.object({
|
|
|
303
306
|
sourceId: z.string().optional().describe("\u6307\u5B9A\u722C\u866B\u6E90\u540D\u79F0\uFF0C\u4E0D\u4F20\u5219\u5168\u91CF")
|
|
304
307
|
});
|
|
305
308
|
async function sourceCrawl(input) {
|
|
306
|
-
const
|
|
307
|
-
|
|
309
|
+
const config = await getConfig();
|
|
310
|
+
const configPath = join4(config.workflowDir || process.cwd(), "tools", "crawler", "config.json");
|
|
311
|
+
let crawlerConfig;
|
|
312
|
+
try {
|
|
313
|
+
crawlerConfig = JSON.parse(await readFile4(configPath, "utf-8"));
|
|
314
|
+
} catch {
|
|
315
|
+
crawlerConfig = { sources: [] };
|
|
316
|
+
}
|
|
317
|
+
if (crawlerConfig.sources.length === 0) {
|
|
308
318
|
return {
|
|
309
319
|
success: false,
|
|
310
320
|
message: "\u6682\u65E0\u914D\u7F6E\u722C\u866B\u6E90\u3002\u8BF7\u5148\u7528 source.subscribe \u6DFB\u52A0\u3002"
|
|
311
321
|
};
|
|
312
322
|
}
|
|
313
|
-
const targets = input.sourceId ?
|
|
323
|
+
const targets = input.sourceId ? crawlerConfig.sources.filter((s) => s.name === input.sourceId) : crawlerConfig.sources.filter((s) => s.enabled !== false);
|
|
314
324
|
if (targets.length === 0) {
|
|
315
325
|
return {
|
|
316
326
|
success: false,
|
|
@@ -420,7 +430,7 @@ async function sourceTagApply(input) {
|
|
|
420
430
|
|
|
421
431
|
// src/tools/subscribe.ts
|
|
422
432
|
import { z as z2 } from "zod";
|
|
423
|
-
import { readFile as
|
|
433
|
+
import { readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
424
434
|
import { join as join5 } from "path";
|
|
425
435
|
var sourceSubscribeSchema = z2.object({
|
|
426
436
|
action: z2.enum(["add", "remove", "list"]).describe("\u64CD\u4F5C\u7C7B\u578B"),
|
|
@@ -435,7 +445,7 @@ async function sourceSubscribe(input) {
|
|
|
435
445
|
const configPath = join5(config.workflowDir || process.cwd(), "tools/crawler/config.json");
|
|
436
446
|
let crawlerConfig;
|
|
437
447
|
try {
|
|
438
|
-
crawlerConfig = JSON.parse(await
|
|
448
|
+
crawlerConfig = JSON.parse(await readFile5(configPath, "utf-8"));
|
|
439
449
|
} catch {
|
|
440
450
|
crawlerConfig = { sources: [] };
|
|
441
451
|
}
|
|
@@ -488,7 +498,7 @@ async function sourceSubscribe(input) {
|
|
|
488
498
|
import { z as z3 } from "zod";
|
|
489
499
|
|
|
490
500
|
// src/lib/drafts.ts
|
|
491
|
-
import { readFile as
|
|
501
|
+
import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir4, unlink } from "fs/promises";
|
|
492
502
|
import { join as join6, basename } from "path";
|
|
493
503
|
import matter2 from "gray-matter";
|
|
494
504
|
import { glob as glob2 } from "glob";
|
|
@@ -533,7 +543,7 @@ async function saveDraft(options) {
|
|
|
533
543
|
return { filePath, meta, content: options.content };
|
|
534
544
|
}
|
|
535
545
|
async function publishDraft(options) {
|
|
536
|
-
const raw = await
|
|
546
|
+
const raw = await readFile6(options.file, "utf-8");
|
|
537
547
|
const { data, content } = matter2(raw);
|
|
538
548
|
const meta = data;
|
|
539
549
|
meta.status = "published";
|
|
@@ -683,6 +693,8 @@ async function analyticsPush(input) {
|
|
|
683
693
|
sources: [],
|
|
684
694
|
drafts: [],
|
|
685
695
|
published: [],
|
|
696
|
+
configs: [],
|
|
697
|
+
crawlerSources: [],
|
|
686
698
|
analytics: [payload]
|
|
687
699
|
});
|
|
688
700
|
if (!res.ok) {
|
|
@@ -704,114 +716,21 @@ var analyticsReportSchema = z4.object({
|
|
|
704
716
|
async function analyticsReport(input) {
|
|
705
717
|
return {
|
|
706
718
|
success: true,
|
|
707
|
-
message: "\u6570\u636E\u62A5\u544A\u529F\u80FD\u9700\u8981\u4E91\u7AEF Dashboard \u652F\u6301\uFF0C\u8BF7\u8BBF\u95EE https://app.claudeink.
|
|
719
|
+
message: "\u6570\u636E\u62A5\u544A\u529F\u80FD\u9700\u8981\u4E91\u7AEF Dashboard \u652F\u6301\uFF0C\u8BF7\u8BBF\u95EE https://app.claudeink.com \u67E5\u770B\u8BE6\u7EC6\u6570\u636E\u5206\u6790\u3002",
|
|
708
720
|
data: {
|
|
709
|
-
dashboardUrl: "https://app.claudeink.
|
|
721
|
+
dashboardUrl: "https://app.claudeink.com/analytics",
|
|
710
722
|
account: input.account,
|
|
711
723
|
period: input.period || "30d"
|
|
712
724
|
}
|
|
713
725
|
};
|
|
714
726
|
}
|
|
715
727
|
|
|
716
|
-
// src/tools/
|
|
728
|
+
// src/tools/sync.ts
|
|
717
729
|
import { z as z5 } from "zod";
|
|
718
|
-
import {
|
|
730
|
+
import { writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
|
|
719
731
|
import { join as join7 } from "path";
|
|
720
|
-
var
|
|
721
|
-
|
|
722
|
-
platform: z5.string().describe("\u5E73\u53F0\u540D\u79F0\uFF0C\u5982 wechat, xiaohongshu"),
|
|
723
|
-
displayName: z5.string().optional().describe("\u663E\u793A\u540D\u79F0"),
|
|
724
|
-
domains: z5.array(z5.string()).describe("\u5185\u5BB9\u9886\u57DF"),
|
|
725
|
-
description: z5.string().optional().describe("\u8D26\u53F7\u5B9A\u4F4D\u63CF\u8FF0"),
|
|
726
|
-
profileUrl: z5.string().optional().describe("\u8D26\u53F7\u5728\u5E73\u53F0\u4E0A\u7684\u4E3B\u9875 URL")
|
|
727
|
-
});
|
|
728
|
-
async function accountCreate(input) {
|
|
729
|
-
const config = await getConfig();
|
|
730
|
-
const yamlPath = join7(config.workflowDir, "accounts", `${input.name}.yaml`);
|
|
731
|
-
try {
|
|
732
|
-
await readFile6(yamlPath);
|
|
733
|
-
return { success: false, message: `\u8D26\u53F7 ${input.name} \u5DF2\u5B58\u5728` };
|
|
734
|
-
} catch {
|
|
735
|
-
}
|
|
736
|
-
let template = "";
|
|
737
|
-
try {
|
|
738
|
-
template = await readFile6(
|
|
739
|
-
join7(config.workflowDir, "accounts", "_template.yaml"),
|
|
740
|
-
"utf-8"
|
|
741
|
-
);
|
|
742
|
-
} catch {
|
|
743
|
-
template = defaultTemplate();
|
|
744
|
-
}
|
|
745
|
-
const yamlContent = template.replace(/name:\s*""/, `name: "${input.displayName || input.name}"`).replace(/id:\s*""/, `id: "${input.name}"`).replace(/platform:\s*""/, `platform: "${input.platform}"`).replace(/profile_url:\s*""/, `profile_url: "${input.profileUrl || ""}"`).replace(/description:\s*""/, `description: "${input.description || ""}"`).replace(
|
|
746
|
-
/domains:\s*\n\s*- ""/,
|
|
747
|
-
`domains:
|
|
748
|
-
${input.domains.map((d) => ` - "${d}"`).join("\n")}`
|
|
749
|
-
);
|
|
750
|
-
await writeFile6(yamlPath, yamlContent, "utf-8");
|
|
751
|
-
const accountDir = join7(config.workflowDir, "accounts", input.name);
|
|
752
|
-
await mkdir5(join7(accountDir, "drafts"), { recursive: true });
|
|
753
|
-
await mkdir5(join7(accountDir, "published"), { recursive: true });
|
|
754
|
-
await mkdir5(join7(accountDir, "assets"), { recursive: true });
|
|
755
|
-
await updateConfig(`account:${input.name}`, {
|
|
756
|
-
type: "account",
|
|
757
|
-
name: input.name,
|
|
758
|
-
displayName: input.displayName || input.name,
|
|
759
|
-
content: yamlContent,
|
|
760
|
-
metadata: { platform: input.platform, profileUrl: input.profileUrl || "" },
|
|
761
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
762
|
-
});
|
|
763
|
-
return {
|
|
764
|
-
success: true,
|
|
765
|
-
message: `\u8D26\u53F7 ${input.name} \u5DF2\u521B\u5EFA
|
|
766
|
-
\u914D\u7F6E: accounts/${input.name}.yaml
|
|
767
|
-
\u76EE\u5F55: accounts/${input.name}/drafts/, published/, assets/`,
|
|
768
|
-
data: {
|
|
769
|
-
config: yamlPath,
|
|
770
|
-
directories: [
|
|
771
|
-
`accounts/${input.name}/drafts/`,
|
|
772
|
-
`accounts/${input.name}/published/`,
|
|
773
|
-
`accounts/${input.name}/assets/`
|
|
774
|
-
]
|
|
775
|
-
}
|
|
776
|
-
};
|
|
777
|
-
}
|
|
778
|
-
function defaultTemplate() {
|
|
779
|
-
return `# ClaudeInk \u8D26\u53F7\u914D\u7F6E
|
|
780
|
-
name: ""
|
|
781
|
-
id: ""
|
|
782
|
-
platform: ""
|
|
783
|
-
profile_url: ""
|
|
784
|
-
description: ""
|
|
785
|
-
|
|
786
|
-
domains:
|
|
787
|
-
- ""
|
|
788
|
-
|
|
789
|
-
style:
|
|
790
|
-
tone: "\u5E73\u5B9E"
|
|
791
|
-
voice: "\u53E3\u8BED\u5316"
|
|
792
|
-
formality: "medium"
|
|
793
|
-
emotion: "\u9002\u5EA6"
|
|
794
|
-
humor: "\u5076\u5C14"
|
|
795
|
-
language: "zh-CN"
|
|
796
|
-
|
|
797
|
-
persona:
|
|
798
|
-
role: ""
|
|
799
|
-
background: ""
|
|
800
|
-
first_person: "\u6211"
|
|
801
|
-
|
|
802
|
-
paths:
|
|
803
|
-
drafts: "accounts/{id}/drafts/"
|
|
804
|
-
published: "accounts/{id}/published/"
|
|
805
|
-
assets: "accounts/{id}/assets/"
|
|
806
|
-
`;
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
// src/tools/sync.ts
|
|
810
|
-
import { z as z6 } from "zod";
|
|
811
|
-
import { writeFile as writeFile7 } from "fs/promises";
|
|
812
|
-
import { join as join8 } from "path";
|
|
813
|
-
var syncPushSchema = z6.object({
|
|
814
|
-
workDir: z6.string().optional().describe("\u5DE5\u4F5C\u76EE\u5F55\uFF08\u9ED8\u8BA4\u4F7F\u7528\u914D\u7F6E\u4E2D\u7684 workflowDir\uFF09")
|
|
732
|
+
var syncPushSchema = z5.object({
|
|
733
|
+
workDir: z5.string().optional().describe("\u5DE5\u4F5C\u76EE\u5F55\uFF08\u9ED8\u8BA4\u4F7F\u7528\u914D\u7F6E\u4E2D\u7684 workflowDir\uFF09")
|
|
815
734
|
});
|
|
816
735
|
async function syncPush(input) {
|
|
817
736
|
const creds = await getCredentials();
|
|
@@ -899,8 +818,8 @@ async function syncPush(input) {
|
|
|
899
818
|
return { success: false, message: `\u540C\u6B65\u7F51\u7EDC\u9519\u8BEF: ${err instanceof Error ? err.message : err}` };
|
|
900
819
|
}
|
|
901
820
|
}
|
|
902
|
-
var syncPullSchema =
|
|
903
|
-
workDir:
|
|
821
|
+
var syncPullSchema = z5.object({
|
|
822
|
+
workDir: z5.string().optional().describe("\u5DE5\u4F5C\u76EE\u5F55")
|
|
904
823
|
});
|
|
905
824
|
async function syncPull(input) {
|
|
906
825
|
const creds = await getCredentials();
|
|
@@ -925,37 +844,77 @@ async function syncPull(input) {
|
|
|
925
844
|
}
|
|
926
845
|
let updated = 0;
|
|
927
846
|
const state = await readState();
|
|
928
|
-
for (const
|
|
929
|
-
const stateKey = `${
|
|
847
|
+
for (const cfgItem of cloudData.configs) {
|
|
848
|
+
const stateKey = `${cfgItem.type}:${cfgItem.name}`;
|
|
930
849
|
const localUpdatedAt = state.configs[stateKey]?.updatedAt || "";
|
|
931
|
-
if (!localUpdatedAt ||
|
|
850
|
+
if (!localUpdatedAt || cfgItem.updatedAt > localUpdatedAt) {
|
|
932
851
|
let filePath = "";
|
|
933
|
-
if (
|
|
934
|
-
filePath =
|
|
935
|
-
} else if (
|
|
936
|
-
filePath =
|
|
937
|
-
} else if (
|
|
938
|
-
filePath =
|
|
852
|
+
if (cfgItem.type === "base_rules") {
|
|
853
|
+
filePath = join7(workDir, "base-rules.md");
|
|
854
|
+
} else if (cfgItem.type === "platform") {
|
|
855
|
+
filePath = join7(workDir, "platforms", `${cfgItem.name}.md`);
|
|
856
|
+
} else if (cfgItem.type === "account") {
|
|
857
|
+
filePath = join7(workDir, "accounts", `${cfgItem.name}.yaml`);
|
|
939
858
|
}
|
|
940
|
-
if (filePath &&
|
|
941
|
-
await
|
|
859
|
+
if (filePath && cfgItem.content) {
|
|
860
|
+
await writeFile6(filePath, cfgItem.content, "utf-8");
|
|
942
861
|
state.configs[stateKey] = {
|
|
943
|
-
type:
|
|
944
|
-
name:
|
|
945
|
-
displayName:
|
|
946
|
-
content:
|
|
947
|
-
metadata:
|
|
948
|
-
updatedAt:
|
|
862
|
+
type: cfgItem.type,
|
|
863
|
+
name: cfgItem.name,
|
|
864
|
+
displayName: cfgItem.displayName,
|
|
865
|
+
content: cfgItem.content,
|
|
866
|
+
metadata: cfgItem.metadata || {},
|
|
867
|
+
updatedAt: cfgItem.updatedAt
|
|
949
868
|
};
|
|
950
869
|
updated++;
|
|
951
870
|
}
|
|
952
871
|
}
|
|
953
872
|
}
|
|
873
|
+
let crawlerCount = 0;
|
|
874
|
+
state.crawlerSources = {};
|
|
875
|
+
for (const cfg of cloudData.configs || []) {
|
|
876
|
+
if (cfg.type === "crawler" && cfg.content) {
|
|
877
|
+
try {
|
|
878
|
+
const sources = JSON.parse(cfg.content);
|
|
879
|
+
for (const s of sources) {
|
|
880
|
+
state.crawlerSources[s.id] = {
|
|
881
|
+
name: s.name,
|
|
882
|
+
url: s.url,
|
|
883
|
+
type: s.type || "rss",
|
|
884
|
+
icon: s.icon || "",
|
|
885
|
+
enabled: s.enabled !== false
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
const crawlerDir = join7(workDir, "tools", "crawler");
|
|
889
|
+
await mkdir5(crawlerDir, { recursive: true });
|
|
890
|
+
const crawlerConfigPath = join7(crawlerDir, "config.json");
|
|
891
|
+
await writeFile6(crawlerConfigPath, JSON.stringify({ sources }, null, 2), "utf-8");
|
|
892
|
+
crawlerCount = sources.length;
|
|
893
|
+
} catch (e) {
|
|
894
|
+
console.error("[sync.pull] Failed to parse crawler sources:", e);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
if (cloudData.writingMasters && Object.keys(cloudData.writingMasters).length > 0) {
|
|
899
|
+
state.writingMasters = state.writingMasters || {};
|
|
900
|
+
for (const [accountName, master] of Object.entries(cloudData.writingMasters)) {
|
|
901
|
+
state.writingMasters[accountName] = {
|
|
902
|
+
id: master.id,
|
|
903
|
+
name: master.name,
|
|
904
|
+
stylePrompt: master.stylePrompt
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
}
|
|
954
908
|
await replaceState(state);
|
|
909
|
+
const masterCount = cloudData.writingMasters ? Object.keys(cloudData.writingMasters).length : 0;
|
|
955
910
|
return {
|
|
956
911
|
success: true,
|
|
957
|
-
message: updated > 0
|
|
958
|
-
|
|
912
|
+
message: updated > 0 || masterCount > 0 || crawlerCount > 0 ? [
|
|
913
|
+
`\u2705 \u4ECE\u4E91\u7AEF\u540C\u6B65\u4E86 ${updated} \u4E2A\u914D\u7F6E\u6587\u4EF6`,
|
|
914
|
+
crawlerCount > 0 ? ` \u8BA2\u9605\u6E90: ${crawlerCount} \u4E2A` : "",
|
|
915
|
+
masterCount > 0 ? ` \u5199\u4F5C\u5927\u5E08: ${masterCount} \u4E2A` : ""
|
|
916
|
+
].filter(Boolean).join("\n") : "\u672C\u5730\u914D\u7F6E\u5DF2\u662F\u6700\u65B0\uFF0C\u65E0\u9700\u66F4\u65B0",
|
|
917
|
+
data: { updated, crawlerSources: crawlerCount, writingMasters: masterCount }
|
|
959
918
|
};
|
|
960
919
|
} catch (err) {
|
|
961
920
|
return { success: false, message: `\u62C9\u53D6\u9519\u8BEF: ${err instanceof Error ? err.message : err}` };
|
|
@@ -963,16 +922,17 @@ async function syncPull(input) {
|
|
|
963
922
|
}
|
|
964
923
|
|
|
965
924
|
// src/tools/workflow.ts
|
|
966
|
-
import { z as
|
|
967
|
-
import { cp, mkdir as mkdir6, access as access2
|
|
968
|
-
import { join as
|
|
925
|
+
import { z as z6 } from "zod";
|
|
926
|
+
import { cp, mkdir as mkdir6, access as access2 } from "fs/promises";
|
|
927
|
+
import { join as join8, dirname } from "path";
|
|
969
928
|
import { fileURLToPath } from "url";
|
|
929
|
+
var DEFAULT_API_BASE_URL = "https://app.claudeink.com";
|
|
970
930
|
var __filename = fileURLToPath(import.meta.url);
|
|
971
931
|
var __dirname = dirname(__filename);
|
|
972
|
-
var WORKFLOW_SRC =
|
|
973
|
-
var workflowInitSchema =
|
|
974
|
-
workDir:
|
|
975
|
-
licenseKey:
|
|
932
|
+
var WORKFLOW_SRC = join8(__dirname, "..", "workflow");
|
|
933
|
+
var workflowInitSchema = z6.object({
|
|
934
|
+
workDir: z6.string().describe("\u5DE5\u4F5C\u6D41\u521D\u59CB\u5316\u76EE\u6807\u76EE\u5F55\uFF08\u7EDD\u5BF9\u8DEF\u5F84\uFF09"),
|
|
935
|
+
licenseKey: z6.string().optional().describe("License Key\uFF08\u53EF\u9009\uFF0C\u4F20\u5165\u5219\u81EA\u52A8\u6FC0\u6D3B\uFF09")
|
|
976
936
|
});
|
|
977
937
|
async function workflowInit(input) {
|
|
978
938
|
const cwd = input.workDir;
|
|
@@ -980,8 +940,8 @@ async function workflowInit(input) {
|
|
|
980
940
|
try {
|
|
981
941
|
const items = ["CLAUDE.md", "base-rules.md", "platforms", "accounts", "tools"];
|
|
982
942
|
for (const item of items) {
|
|
983
|
-
const src =
|
|
984
|
-
const dest =
|
|
943
|
+
const src = join8(WORKFLOW_SRC, item);
|
|
944
|
+
const dest = join8(cwd, item);
|
|
985
945
|
try {
|
|
986
946
|
await access2(dest);
|
|
987
947
|
results.push(`\u23ED\uFE0F ${item} \u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7`);
|
|
@@ -1000,34 +960,45 @@ async function workflowInit(input) {
|
|
|
1000
960
|
".claudeink"
|
|
1001
961
|
];
|
|
1002
962
|
for (const dir of dirs) {
|
|
1003
|
-
await mkdir6(
|
|
963
|
+
await mkdir6(join8(cwd, dir), { recursive: true });
|
|
1004
964
|
}
|
|
1005
965
|
results.push("\u2705 \u8FD0\u884C\u65F6\u76EE\u5F55\u5DF2\u521B\u5EFA");
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
966
|
+
await saveConfig({ workflowDir: cwd });
|
|
967
|
+
const statePath = join8(cwd, ".claudeink", "state.json");
|
|
968
|
+
try {
|
|
969
|
+
await access2(statePath);
|
|
970
|
+
results.push("\u23ED\uFE0F \u672C\u5730\u72B6\u6001\u8868\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7");
|
|
971
|
+
} catch {
|
|
972
|
+
const emptyState = {
|
|
973
|
+
sources: {},
|
|
974
|
+
drafts: {},
|
|
975
|
+
published: {},
|
|
976
|
+
configs: {},
|
|
977
|
+
crawlerSources: {},
|
|
978
|
+
writingMasters: {},
|
|
979
|
+
lastSyncAt: ""
|
|
980
|
+
};
|
|
981
|
+
await replaceState(emptyState);
|
|
982
|
+
results.push("\u2705 \u672C\u5730\u72B6\u6001\u8868\u5DF2\u521D\u59CB\u5316");
|
|
983
|
+
}
|
|
1016
984
|
let activated = false;
|
|
1017
985
|
if (input.licenseKey) {
|
|
1018
986
|
try {
|
|
1019
|
-
const
|
|
987
|
+
const activateUrl = `${DEFAULT_API_BASE_URL}/api/auth/activate`;
|
|
988
|
+
const res = await fetch(activateUrl, {
|
|
1020
989
|
method: "POST",
|
|
1021
990
|
headers: { "Content-Type": "application/json" },
|
|
1022
991
|
body: JSON.stringify({ key: input.licenseKey })
|
|
1023
992
|
});
|
|
1024
993
|
const data = await res.json();
|
|
1025
994
|
if (data.userId) {
|
|
1026
|
-
await
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
995
|
+
await saveCredentials({
|
|
996
|
+
licenseKey: input.licenseKey,
|
|
997
|
+
token: data.token,
|
|
998
|
+
userId: data.userId,
|
|
999
|
+
plan: data.plan,
|
|
1000
|
+
expiresAt: data.expiresAt
|
|
1001
|
+
});
|
|
1031
1002
|
results.push(`\u2705 License \u6FC0\u6D3B\u6210\u529F\uFF08\u5957\u9910: ${data.plan}\uFF09`);
|
|
1032
1003
|
activated = true;
|
|
1033
1004
|
} else {
|
|
@@ -1050,10 +1021,10 @@ async function workflowInit(input) {
|
|
|
1050
1021
|
}
|
|
1051
1022
|
}
|
|
1052
1023
|
try {
|
|
1053
|
-
await access2(
|
|
1024
|
+
await access2(join8(cwd, "tools", "crawler", "package.json"));
|
|
1054
1025
|
const { execSync } = await import("child_process");
|
|
1055
1026
|
execSync("npm install --silent", {
|
|
1056
|
-
cwd:
|
|
1027
|
+
cwd: join8(cwd, "tools", "crawler"),
|
|
1057
1028
|
stdio: "pipe"
|
|
1058
1029
|
});
|
|
1059
1030
|
results.push("\u2705 \u722C\u866B\u4F9D\u8D56\u5DF2\u5B89\u88C5");
|
|
@@ -1083,7 +1054,7 @@ async function workflowInit(input) {
|
|
|
1083
1054
|
// src/index.ts
|
|
1084
1055
|
var server = new McpServer({
|
|
1085
1056
|
name: "ClaudeInk",
|
|
1086
|
-
version: "0.
|
|
1057
|
+
version: "0.6.1"
|
|
1087
1058
|
});
|
|
1088
1059
|
server.tool("workflow.init", "\u521D\u59CB\u5316\u5199\u4F5C\u5DE5\u4F5C\u6D41\uFF08\u91CA\u653E\u4E09\u5C42\u914D\u7F6E + \u6FC0\u6D3B License + \u81EA\u52A8\u540C\u6B65\u4E91\u7AEF\u914D\u7F6E\uFF09", workflowInitSchema.shape, async (input) => {
|
|
1089
1060
|
const result = await workflowInit(input);
|
|
@@ -1133,14 +1104,10 @@ server.tool("analytics.report", "\u83B7\u53D6\u6570\u636E\u5206\u6790\u62A5\u544
|
|
|
1133
1104
|
const result = await analyticsReport(input);
|
|
1134
1105
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1135
1106
|
});
|
|
1136
|
-
server.tool("account.create", "\u521B\u5EFA\u65B0\u81EA\u5A92\u4F53\u8D26\u53F7", accountCreateSchema.shape, async (input) => {
|
|
1137
|
-
const result = await accountCreate(input);
|
|
1138
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1139
|
-
});
|
|
1140
1107
|
async function main() {
|
|
1141
1108
|
const transport = new StdioServerTransport();
|
|
1142
1109
|
await server.connect(transport);
|
|
1143
|
-
console.error("[ClaudeInk MCP] Server started on stdio (
|
|
1110
|
+
console.error("[ClaudeInk MCP] Server started on stdio (12 tools)");
|
|
1144
1111
|
}
|
|
1145
1112
|
main().catch((err) => {
|
|
1146
1113
|
console.error("[ClaudeInk MCP] Fatal error:", err);
|