huozi-mcp-server 0.2.1 → 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.
Files changed (2) hide show
  1. package/dist/index.js +109 -5
  2. package/package.json +2 -2
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.2.1",
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.", {
@@ -94,9 +94,9 @@ server.tool("huozi_setup", "Create a workspace and generate an API key. Requires
94
94
  };
95
95
  });
96
96
  // --- Page tools ---
97
- server.tool("huozi_publish", "Publish or update a Markdown page on Huozi. If a page with the same slug exists, it will be updated.", {
97
+ server.tool("huozi_publish", "Publish or update a page on Huozi. Supports Markdown (default) and HTML. If a page with the same slug exists, it will be updated. HTML pages support full CSS styling, SVG, and images but no JavaScript — all <script> tags and event handlers are stripped.", {
98
98
  title: z.string().min(1).describe("Page title"),
99
- content: z.string().min(1).describe("Markdown content"),
99
+ content: z.string().min(1).describe("Page content — Markdown or HTML"),
100
100
  slug: z
101
101
  .string()
102
102
  .optional()
@@ -105,7 +105,16 @@ server.tool("huozi_publish", "Publish or update a Markdown page on Huozi. If a p
105
105
  .string()
106
106
  .optional()
107
107
  .describe("SEO description (optional)"),
108
- }, async ({ title, content, slug, description }) => {
108
+ content_type: z
109
+ .enum(["markdown", "html"])
110
+ .optional()
111
+ .describe("Content type: 'markdown' (default) or 'html'. HTML accepts full documents or body fragments. CSS is preserved, JS is stripped."),
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 }) => {
109
118
  const apiKey = getApiKey();
110
119
  if (!apiKey) {
111
120
  return {
@@ -122,6 +131,10 @@ server.tool("huozi_publish", "Publish or update a Markdown page on Huozi. If a p
122
131
  body.slug = slug;
123
132
  if (description)
124
133
  body.description = description;
134
+ if (content_type)
135
+ body.content_type = content_type;
136
+ if (access_token !== undefined)
137
+ body.access_token = access_token;
125
138
  const res = await apiCall("/api/v1/pages", {
126
139
  method: "POST",
127
140
  body,
@@ -141,7 +154,7 @@ server.tool("huozi_publish", "Publish or update a Markdown page on Huozi. If a p
141
154
  content: [
142
155
  {
143
156
  type: "text",
144
- 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}` : ""}`,
145
158
  },
146
159
  ],
147
160
  };
@@ -244,6 +257,97 @@ server.tool("huozi_delete", "Delete a page.", {
244
257
  ],
245
258
  };
246
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
+ });
247
351
  // --- Start server ---
248
352
  async function main() {
249
353
  const transport = new StdioServerTransport();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "huozi-mcp-server",
3
- "version": "0.2.1",
4
- "description": "MCP server for Huozi — publish Markdown as shareable web pages",
3
+ "version": "0.4.0",
4
+ "description": "MCP server for Huozi — publish Markdown and HTML as shareable web pages",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {