htmlhost-mcp 1.0.0 → 1.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 +20 -0
- package/package.json +1 -1
- package/src/api.mjs +1 -1
- package/src/server.mjs +52 -1
package/README.md
CHANGED
|
@@ -83,6 +83,8 @@ htmlhost-mcp
|
|
|
83
83
|
| `pull_site` | Download a site's files to a local directory |
|
|
84
84
|
| `delete_site` | Permanently delete a site |
|
|
85
85
|
| `whoami` | Show the current authenticated user |
|
|
86
|
+
| `list_versions` | List a site's published versions and what each changed |
|
|
87
|
+
| `restore_version` | Make an earlier version live again (Pro) |
|
|
86
88
|
|
|
87
89
|
### `deploy`
|
|
88
90
|
|
|
@@ -138,6 +140,24 @@ confirm (required) Must be true — safety check
|
|
|
138
140
|
|
|
139
141
|
Returns the authenticated user's email, name, handle, and plan.
|
|
140
142
|
|
|
143
|
+
### `list_versions`
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
slug (required) The site slug
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Returns the site's versions, newest first, with time, source, size, what changed, and which one is live. `usable: false` means the owner's plan can't restore them.
|
|
150
|
+
|
|
151
|
+
### `restore_version`
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
slug (required) The site slug
|
|
155
|
+
version (required) Version number from list_versions
|
|
156
|
+
confirm (required) Must be true — safety check
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Publishes that version again as a new version, so it can be undone the same way. Needs the site owner to be on Pro.
|
|
160
|
+
|
|
141
161
|
## Architecture
|
|
142
162
|
|
|
143
163
|
```
|
package/package.json
CHANGED
package/src/api.mjs
CHANGED
|
@@ -48,7 +48,7 @@ class ApiError extends Error {
|
|
|
48
48
|
function headers(extra = {}) {
|
|
49
49
|
const token = getToken();
|
|
50
50
|
if (!token) throw new ApiError("Not logged in. Run `htmlhost login` in a terminal first.", 0);
|
|
51
|
-
return { Authorization: `Bearer ${token}`, ...extra };
|
|
51
|
+
return { Authorization: `Bearer ${token}`, "X-HTMLHost-Client": "mcp", ...extra };
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
async function withRetry(fn, label = "request", retries = 3) {
|
package/src/server.mjs
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
mimeFromExt,
|
|
27
27
|
} from "./api.mjs";
|
|
28
28
|
|
|
29
|
-
const VERSION = "1.
|
|
29
|
+
const VERSION = "1.1.0";
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Helper: wraps a handler to return proper MCP content and catch errors.
|
|
@@ -314,5 +314,56 @@ export function createServer() {
|
|
|
314
314
|
})
|
|
315
315
|
);
|
|
316
316
|
|
|
317
|
+
// -------------------------------------------------------------------
|
|
318
|
+
// Tool: list_versions
|
|
319
|
+
// -------------------------------------------------------------------
|
|
320
|
+
server.registerTool(
|
|
321
|
+
"list_versions",
|
|
322
|
+
{
|
|
323
|
+
title: "List site versions",
|
|
324
|
+
description:
|
|
325
|
+
"List the published versions of a site, newest first, with what each one changed. " +
|
|
326
|
+
"`usable: false` means the owner's plan can't restore them (Pro feature).",
|
|
327
|
+
inputSchema: z.object({
|
|
328
|
+
slug: z.string().describe("The site slug"),
|
|
329
|
+
}),
|
|
330
|
+
},
|
|
331
|
+
wrap(async ({ slug }) => {
|
|
332
|
+
if (!isLoggedIn()) return "Not logged in. Run `htmlhost login` in a terminal first.";
|
|
333
|
+
const cleanSlug = slug.replace(/\.htmlhost\.co$/, "");
|
|
334
|
+
return apiGet(`/api/sites/${encodeURIComponent(cleanSlug)}/versions`);
|
|
335
|
+
})
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
// -------------------------------------------------------------------
|
|
339
|
+
// Tool: restore_version
|
|
340
|
+
// -------------------------------------------------------------------
|
|
341
|
+
server.registerTool(
|
|
342
|
+
"restore_version",
|
|
343
|
+
{
|
|
344
|
+
title: "Restore a site version",
|
|
345
|
+
description:
|
|
346
|
+
"Make an earlier version of a site live again. It's published as a new version " +
|
|
347
|
+
"(the current one stays in history), so this can be undone by restoring again. Needs Pro.",
|
|
348
|
+
inputSchema: z.object({
|
|
349
|
+
slug: z.string().describe("The site slug"),
|
|
350
|
+
version: z.number().int().positive().describe("The version number to restore (from list_versions)"),
|
|
351
|
+
confirm: z.boolean().describe("Must be true to confirm replacing the live site"),
|
|
352
|
+
}),
|
|
353
|
+
},
|
|
354
|
+
wrap(async ({ slug, version, confirm }) => {
|
|
355
|
+
if (!isLoggedIn()) return "Not logged in. Run `htmlhost login` in a terminal first.";
|
|
356
|
+
if (!confirm) return "Restore not confirmed. Set confirm to true to proceed.";
|
|
357
|
+
const cleanSlug = slug.replace(/\.htmlhost\.co$/, "");
|
|
358
|
+
const data = await apiPost(`/api/sites/${encodeURIComponent(cleanSlug)}/versions/${version}/restore`, {});
|
|
359
|
+
return {
|
|
360
|
+
message: `Restored v${version}; it's live as v${data.version}.`,
|
|
361
|
+
url: data.url ? (String(data.url).startsWith("http") ? data.url : `https://${data.url}`) : `https://${cleanSlug}.htmlhost.co`,
|
|
362
|
+
version: data.version,
|
|
363
|
+
restoredFrom: version,
|
|
364
|
+
};
|
|
365
|
+
})
|
|
366
|
+
);
|
|
367
|
+
|
|
317
368
|
return server;
|
|
318
369
|
}
|