huozi-mcp-server 0.3.0 → 0.4.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/dist/index.js +101 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { z } from "zod";
|
|
|
5
5
|
import { apiCall, getApiKey } from "./api.js";
|
|
6
6
|
const server = new McpServer({
|
|
7
7
|
name: "huozi",
|
|
8
|
-
version: "0.
|
|
8
|
+
version: "0.4.0",
|
|
9
9
|
});
|
|
10
10
|
// --- Auth tools ---
|
|
11
11
|
server.tool("huozi_signup", "Sign in or register a Huozi account. Sends a verification code to the email. No password needed.", {
|
|
@@ -109,7 +109,12 @@ server.tool("huozi_publish", "Publish or update a page on Huozi. Supports Markdo
|
|
|
109
109
|
.enum(["markdown", "html"])
|
|
110
110
|
.optional()
|
|
111
111
|
.describe("Content type: 'markdown' (default) or 'html'. HTML accepts full documents or body fragments. CSS is preserved, JS is stripped."),
|
|
112
|
-
|
|
112
|
+
access_token: z
|
|
113
|
+
.string()
|
|
114
|
+
.nullable()
|
|
115
|
+
.optional()
|
|
116
|
+
.describe('Page access protection. "random" = generate 6-char code, custom string = your password, null = remove protection (public).'),
|
|
117
|
+
}, async ({ title, content, slug, description, content_type, access_token }) => {
|
|
113
118
|
const apiKey = getApiKey();
|
|
114
119
|
if (!apiKey) {
|
|
115
120
|
return {
|
|
@@ -128,6 +133,8 @@ server.tool("huozi_publish", "Publish or update a page on Huozi. Supports Markdo
|
|
|
128
133
|
body.description = description;
|
|
129
134
|
if (content_type)
|
|
130
135
|
body.content_type = content_type;
|
|
136
|
+
if (access_token !== undefined)
|
|
137
|
+
body.access_token = access_token;
|
|
131
138
|
const res = await apiCall("/api/v1/pages", {
|
|
132
139
|
method: "POST",
|
|
133
140
|
body,
|
|
@@ -147,7 +154,7 @@ server.tool("huozi_publish", "Publish or update a page on Huozi. Supports Markdo
|
|
|
147
154
|
content: [
|
|
148
155
|
{
|
|
149
156
|
type: "text",
|
|
150
|
-
text: `Published! URL: ${res.data.url}`,
|
|
157
|
+
text: `Published! URL: ${res.data.url}${res.data.version ? ` (v${res.data.version})` : ""}${res.data.access_token ? `\nAccess code: ${res.data.access_token}` : ""}`,
|
|
151
158
|
},
|
|
152
159
|
],
|
|
153
160
|
};
|
|
@@ -250,6 +257,97 @@ server.tool("huozi_delete", "Delete a page.", {
|
|
|
250
257
|
],
|
|
251
258
|
};
|
|
252
259
|
});
|
|
260
|
+
server.tool("huozi_versions", "List all versions of a page.", {
|
|
261
|
+
slug: z.string().describe("Page slug"),
|
|
262
|
+
}, async ({ slug }) => {
|
|
263
|
+
const apiKey = getApiKey();
|
|
264
|
+
if (!apiKey) {
|
|
265
|
+
return {
|
|
266
|
+
content: [
|
|
267
|
+
{ type: "text", text: "HUOZI_API_KEY is not set." },
|
|
268
|
+
],
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
const res = await apiCall(`/api/v1/pages/${slug}/versions`, { apiKey });
|
|
272
|
+
if (!res.ok) {
|
|
273
|
+
return {
|
|
274
|
+
content: [
|
|
275
|
+
{
|
|
276
|
+
type: "text",
|
|
277
|
+
text: `Failed: ${res.data.error || "Unknown error"}`,
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
const versions = res.data.versions;
|
|
283
|
+
if (!versions || versions.length === 0) {
|
|
284
|
+
return {
|
|
285
|
+
content: [{ type: "text", text: "No versions found." }],
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
const list = versions
|
|
289
|
+
.map((v) => `v${v.version} (${v.content_type}) — ${v.created_at}`)
|
|
290
|
+
.join("\n");
|
|
291
|
+
return {
|
|
292
|
+
content: [{ type: "text", text: `Versions of /${slug}:\n${list}` }],
|
|
293
|
+
};
|
|
294
|
+
});
|
|
295
|
+
server.tool("huozi_token", 'Manage access token (password protection) for a page. Set "random" to generate a 6-char code, a custom string for your own password, or null to remove protection.', {
|
|
296
|
+
slug: z.string().describe("Page slug"),
|
|
297
|
+
access_token: z
|
|
298
|
+
.string()
|
|
299
|
+
.nullable()
|
|
300
|
+
.describe('"random" = generate code, custom string = your password, null = remove (make public)'),
|
|
301
|
+
}, async ({ slug, access_token }) => {
|
|
302
|
+
const apiKey = getApiKey();
|
|
303
|
+
if (!apiKey) {
|
|
304
|
+
return {
|
|
305
|
+
content: [
|
|
306
|
+
{ type: "text", text: "HUOZI_API_KEY is not set." },
|
|
307
|
+
],
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
const res = await apiCall(`/api/v1/pages/${slug}/token`, {
|
|
311
|
+
method: "PUT",
|
|
312
|
+
body: { access_token },
|
|
313
|
+
apiKey,
|
|
314
|
+
});
|
|
315
|
+
if (!res.ok) {
|
|
316
|
+
return {
|
|
317
|
+
content: [
|
|
318
|
+
{
|
|
319
|
+
type: "text",
|
|
320
|
+
text: `Failed: ${res.data.error || "Unknown error"}`,
|
|
321
|
+
},
|
|
322
|
+
],
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
if (res.data.access_token) {
|
|
326
|
+
return {
|
|
327
|
+
content: [
|
|
328
|
+
{
|
|
329
|
+
type: "text",
|
|
330
|
+
text: `Access code set for /${slug}: ${res.data.access_token}\nTell the user to share this code with people who need access.`,
|
|
331
|
+
},
|
|
332
|
+
],
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
if (res.data.has_access_token) {
|
|
336
|
+
return {
|
|
337
|
+
content: [
|
|
338
|
+
{ type: "text", text: `Access code updated for /${slug}.` },
|
|
339
|
+
],
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
return {
|
|
343
|
+
content: [
|
|
344
|
+
{
|
|
345
|
+
type: "text",
|
|
346
|
+
text: `Protection removed. /${slug} is now public.`,
|
|
347
|
+
},
|
|
348
|
+
],
|
|
349
|
+
};
|
|
350
|
+
});
|
|
253
351
|
// --- Start server ---
|
|
254
352
|
async function main() {
|
|
255
353
|
const transport = new StdioServerTransport();
|