@awesomate/hosting-mcp 0.20.8 → 0.21.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 +136 -8
- package/package.json +1 -1
- package/skill/awesomate-knowledge/SKILL.md +2 -1
package/dist/index.js
CHANGED
|
@@ -40196,6 +40196,49 @@ async function knowledgeSources(config3, args) {
|
|
|
40196
40196
|
const page = await hubGet(config3, `/api/knowledge/sources${qs ? `?${qs}` : ""}`);
|
|
40197
40197
|
return describeSourcePage(page);
|
|
40198
40198
|
}
|
|
40199
|
+
if (args.action === "search") {
|
|
40200
|
+
const q = new URLSearchParams();
|
|
40201
|
+
if (args.q) q.set("q", args.q);
|
|
40202
|
+
if (args.kind) q.set("kind", args.kind);
|
|
40203
|
+
if (args.visibility) q.set("visibility", args.visibility);
|
|
40204
|
+
for (const t of args.tags ?? []) q.append("tag", t);
|
|
40205
|
+
for (const c of args.collectionIds ?? []) q.append("collection", c);
|
|
40206
|
+
if (args.cursor) q.set("cursor", args.cursor);
|
|
40207
|
+
if (args.limit !== void 0) q.set("limit", String(args.limit));
|
|
40208
|
+
const qs = q.toString();
|
|
40209
|
+
const page = await hubGet(config3, `/api/knowledge/library${qs ? `?${qs}` : ""}`);
|
|
40210
|
+
return { ...describeSourcePage(page), note_visibility: "Each source carries visibility (private|internal|public \u2014 who may retrieve it; enforced) and collections. Nothing marked public = a public chatbot answers nothing." };
|
|
40211
|
+
}
|
|
40212
|
+
if (args.action === "tag") {
|
|
40213
|
+
if (!args.sourceId || !Array.isArray(args.tags)) return { error: "invalid_request", note: "tag needs sourceId and tags (the full replacement list of free-form tags; collections are unaffected)" };
|
|
40214
|
+
return await hubPatch(config3, `/api/knowledge/sources/${encodeURIComponent(args.sourceId)}`, { tags: args.tags });
|
|
40215
|
+
}
|
|
40216
|
+
if (args.action === "set_visibility") {
|
|
40217
|
+
const ids = args.sourceIds?.length ? args.sourceIds : args.sourceId ? [args.sourceId] : [];
|
|
40218
|
+
if (!ids.length || !args.visibility) return { error: "invalid_request", note: "set_visibility needs sourceId (or sourceIds) and visibility" };
|
|
40219
|
+
if (args.visibility === "public" && !args.confirm) {
|
|
40220
|
+
return {
|
|
40221
|
+
error: "confirmation_required",
|
|
40222
|
+
note: `Making ${ids.length} source(s) PUBLIC means anyone with a public key or a public chatbot can retrieve them, and once fetched or crawled that cannot be taken back. Explain this to the user, then call again with confirm set to their account slug (awesomate_whoami \u2192 account) only after they have agreed in so many words.`
|
|
40223
|
+
};
|
|
40224
|
+
}
|
|
40225
|
+
return await hubPost(config3, "/api/knowledge/sources/batch", {
|
|
40226
|
+
source_ids: ids,
|
|
40227
|
+
visibility: args.visibility,
|
|
40228
|
+
...args.confirm ? { confirm: args.confirm } : {}
|
|
40229
|
+
});
|
|
40230
|
+
}
|
|
40231
|
+
if (args.action === "move") {
|
|
40232
|
+
const ids = args.sourceIds?.length ? args.sourceIds : args.sourceId ? [args.sourceId] : [];
|
|
40233
|
+
if (!ids.length || !args.collectionIds?.length && !args.removeCollectionIds?.length) {
|
|
40234
|
+
return { error: "invalid_request", note: "move needs sourceId (or sourceIds) and collectionIds (add to) and/or removeCollectionIds" };
|
|
40235
|
+
}
|
|
40236
|
+
return await hubPost(config3, "/api/knowledge/sources/batch", {
|
|
40237
|
+
source_ids: ids,
|
|
40238
|
+
...args.collectionIds?.length ? { add_collection_ids: args.collectionIds } : {},
|
|
40239
|
+
...args.removeCollectionIds?.length ? { remove_collection_ids: args.removeCollectionIds } : {}
|
|
40240
|
+
});
|
|
40241
|
+
}
|
|
40199
40242
|
if (args.action === "summary") {
|
|
40200
40243
|
try {
|
|
40201
40244
|
const s = await hubGet(config3, "/api/knowledge/sources/summary");
|
|
@@ -40232,7 +40275,12 @@ async function knowledgeSources(config3, args) {
|
|
|
40232
40275
|
note: "add needs url or sitemap. For a local FILE on this machine, use awesomate_knowledge_upload \u2014 it reads the file off disk and streams it, so the bytes never pass through the conversation."
|
|
40233
40276
|
};
|
|
40234
40277
|
}
|
|
40235
|
-
const body =
|
|
40278
|
+
const body = {
|
|
40279
|
+
...args.url ? { url: args.url } : { sitemap: args.sitemap, ...args.since ? { since: args.since } : {} },
|
|
40280
|
+
...args.visibility ? { visibility: args.visibility } : {},
|
|
40281
|
+
...args.tags?.length ? { tags: args.tags } : {},
|
|
40282
|
+
...args.collectionIds?.length ? { collection_ids: args.collectionIds } : {}
|
|
40283
|
+
};
|
|
40236
40284
|
return await hubPost(config3, "/api/knowledge/sources", body);
|
|
40237
40285
|
} catch (err) {
|
|
40238
40286
|
return mapKnowledgeError(err, config3.apiBase);
|
|
@@ -40593,6 +40641,48 @@ async function knowledgeAgents(config3, args) {
|
|
|
40593
40641
|
return mapAgentsError(err, config3.apiBase);
|
|
40594
40642
|
}
|
|
40595
40643
|
}
|
|
40644
|
+
async function knowledgeCollections(config3, args) {
|
|
40645
|
+
try {
|
|
40646
|
+
if (args.action === "list") {
|
|
40647
|
+
const r = await hubGet(config3, "/api/knowledge/collections");
|
|
40648
|
+
return { ...r, note: 'A collection is a named set of sources; scope an agent to one with scope.tags ["collection:<collection_id>"]. default_visibility only pre-fills new sources \u2014 each source keeps its own visibility.' };
|
|
40649
|
+
}
|
|
40650
|
+
if (args.action === "create") {
|
|
40651
|
+
if (!args.slug || !args.name) return { error: "invalid_request", note: "create needs slug (lower-case, hyphens) and name" };
|
|
40652
|
+
return await hubPost(config3, "/api/knowledge/collections", {
|
|
40653
|
+
slug: args.slug,
|
|
40654
|
+
name: args.name,
|
|
40655
|
+
...args.description ? { description: args.description } : {},
|
|
40656
|
+
...args.defaultVisibility ? { default_visibility: args.defaultVisibility } : {}
|
|
40657
|
+
});
|
|
40658
|
+
}
|
|
40659
|
+
if (!args.collectionId) return { error: "invalid_request", note: `${args.action} needs collectionId (from list)` };
|
|
40660
|
+
if (args.action === "get") {
|
|
40661
|
+
const r = await hubGet(config3, "/api/knowledge/collections");
|
|
40662
|
+
const c = r.collections?.find((x) => x.collection_id === args.collectionId);
|
|
40663
|
+
return c ? { collection: c } : { error: "not_found", note: "No collection with that id in this workspace" };
|
|
40664
|
+
}
|
|
40665
|
+
if (args.action === "update") {
|
|
40666
|
+
const body = {
|
|
40667
|
+
...args.slug ? { slug: args.slug } : {},
|
|
40668
|
+
...args.name ? { name: args.name } : {},
|
|
40669
|
+
...args.description !== void 0 ? { description: args.description } : {},
|
|
40670
|
+
...args.defaultVisibility ? { default_visibility: args.defaultVisibility } : {}
|
|
40671
|
+
};
|
|
40672
|
+
if (!Object.keys(body).length) return { error: "invalid_request", note: "update needs at least one of slug, name, description, defaultVisibility" };
|
|
40673
|
+
return await hubPatch(config3, `/api/knowledge/collections/${encodeURIComponent(args.collectionId)}`, body);
|
|
40674
|
+
}
|
|
40675
|
+
if (args.action === "delete") {
|
|
40676
|
+
return await hubDelete(config3, `/api/knowledge/collections/${encodeURIComponent(args.collectionId)}`);
|
|
40677
|
+
}
|
|
40678
|
+
if (!args.sourceIds?.length) return { error: "invalid_request", note: `${args.action} needs sourceIds` };
|
|
40679
|
+
return await hubPost(config3, `/api/knowledge/collections/${encodeURIComponent(args.collectionId)}/sources`, {
|
|
40680
|
+
[args.action]: args.sourceIds
|
|
40681
|
+
});
|
|
40682
|
+
} catch (err) {
|
|
40683
|
+
return mapKnowledgeError(err, config3.apiBase);
|
|
40684
|
+
}
|
|
40685
|
+
}
|
|
40596
40686
|
|
|
40597
40687
|
// src/index.ts
|
|
40598
40688
|
var config2 = null;
|
|
@@ -41546,9 +41636,17 @@ server.registerTool(
|
|
|
41546
41636
|
server.registerTool(
|
|
41547
41637
|
"awesomate_knowledge_sources",
|
|
41548
41638
|
{
|
|
41549
|
-
description: "The knowledge base's content sources. action 'list' \u2014 ONE page of sources, most recently ingested first (default 50, max 200 via limit): read `page.has_more`/`next_cursor` and pass cursor to continue \u2014 a page is never the whole library. 'summary' \u2014 exact whole-library counts {total, by_kind, chunks, indexed_chunks, failed_sources, failed_jobs_7d}: use THIS to say what the knowledge base contains, and if failed_jobs_7d > 0 say so \u2014 those ingests are missing from every other count. 'jobs' \u2014 ingest job statuses (optional status filter: queued|running|succeeded|failed). 'add' \u2014 ingest a public page {url} or a whole site {sitemap, since?}; ALWAYS get explicit approval first (ingest costs money and counts against quota), for a local FILE on the user's machine use awesomate_knowledge_upload instead (it streams the file from disk; this tool takes URLs only). A pack_required response means the allowance is exhausted: NOTHING was purchased \u2014 present the pack price (1 credit = $100) and let the user buy from the hub if they want it. 'remove' {sourceId} \u2014 deletes the source AND its indexed content; explicit approval required.",
|
|
41639
|
+
description: "The knowledge base's content sources \u2014 the LIBRARY. action 'search' {q?, kind?, visibility?, tags?, collectionIds?, cursor?, limit?} \u2014 find sources by title/tag substring and metadata filters (instant, free; for CONTENT search use awesomate_knowledge_search); each row carries visibility (private|internal|public \u2014 who may retrieve it, ENFORCED), tags and collections. 'tag' {sourceId, tags} \u2014 REPLACE a source's free-form tags. 'set_visibility' {sourceId|sourceIds, visibility, confirm?} \u2014 change who may retrieve the source(s); 'public' is irreversible once fetched, so it needs the user's explicit agreement and their account slug as confirm. 'move' {sourceId|sourceIds, collectionIds?, removeCollectionIds?} \u2014 add to / remove from collections. 'list' \u2014 ONE page of sources, most recently ingested first (default 50, max 200 via limit): read `page.has_more`/`next_cursor` and pass cursor to continue \u2014 a page is never the whole library. 'summary' \u2014 exact whole-library counts {total, by_kind, chunks, indexed_chunks, failed_sources, failed_jobs_7d}: use THIS to say what the knowledge base contains, and if failed_jobs_7d > 0 say so \u2014 those ingests are missing from every other count. 'jobs' \u2014 ingest job statuses (optional status filter: queued|running|succeeded|failed). 'add' \u2014 ingest a public page {url} or a whole site {sitemap, since?}, optionally with visibility (default private), tags and collectionIds; ALWAYS get explicit approval first (ingest costs money and counts against quota), for a local FILE on the user's machine use awesomate_knowledge_upload instead (it streams the file from disk; this tool takes URLs only). A pack_required response means the allowance is exhausted: NOTHING was purchased \u2014 present the pack price (1 credit = $100) and let the user buy from the hub if they want it. 'remove' {sourceId} \u2014 deletes the source AND its indexed content; explicit approval required.",
|
|
41550
41640
|
inputSchema: {
|
|
41551
|
-
action: external_exports.enum(["list", "summary", "add", "remove", "jobs"]),
|
|
41641
|
+
action: external_exports.enum(["list", "summary", "add", "remove", "jobs", "search", "tag", "set_visibility", "move"]),
|
|
41642
|
+
q: external_exports.string().max(100).optional().describe("search: title/tag substring"),
|
|
41643
|
+
kind: external_exports.string().max(32).optional().describe("search: source kind filter (web, document, video, audio, image, book, dataset)"),
|
|
41644
|
+
visibility: external_exports.enum(["private", "internal", "public"]).optional().describe("add: the audience the new source is cleared for (default private); set_visibility: the level to apply; search: filter"),
|
|
41645
|
+
tags: external_exports.array(external_exports.string().max(64)).max(64).optional().describe("add: free-form tags; tag: the REPLACEMENT list; search: filter (AND)"),
|
|
41646
|
+
collectionIds: external_exports.array(external_exports.string().max(64)).max(16).optional().describe("add: put the source in these collections; move: add to; search: filter"),
|
|
41647
|
+
removeCollectionIds: external_exports.array(external_exports.string().max(64)).max(16).optional().describe("move: remove from these collections"),
|
|
41648
|
+
sourceIds: external_exports.array(external_exports.string().max(300)).max(200).optional().describe("set_visibility/move: several sources at once"),
|
|
41649
|
+
confirm: external_exports.string().max(64).optional().describe("set_visibility to 'public' only: the account slug, after the user agreed in so many words"),
|
|
41552
41650
|
url: external_exports.string().url().optional().describe("add: one public page / blog post / YouTube link"),
|
|
41553
41651
|
sitemap: external_exports.string().url().optional().describe("add: sitemap.xml URL \u2014 ingests every listed page"),
|
|
41554
41652
|
since: external_exports.string().optional().describe("add+sitemap only: skip entries with lastmod older than this ISO date"),
|
|
@@ -41558,10 +41656,10 @@ server.registerTool(
|
|
|
41558
41656
|
limit: external_exports.number().int().min(1).max(200).optional().describe("list only: page size (default 50, max 200)")
|
|
41559
41657
|
}
|
|
41560
41658
|
},
|
|
41561
|
-
async ({ action, url, sitemap, since, sourceId, status, cursor, limit }) => {
|
|
41659
|
+
async ({ action, url, sitemap, since, sourceId, status, cursor, limit, q, kind, visibility, tags, collectionIds, removeCollectionIds, sourceIds, confirm }) => {
|
|
41562
41660
|
try {
|
|
41563
41661
|
return knowledgeResult(
|
|
41564
|
-
await knowledgeSources(requireConfig(), { action, url, sitemap, since, sourceId, status, cursor, limit })
|
|
41662
|
+
await knowledgeSources(requireConfig(), { action, url, sitemap, since, sourceId, status, cursor, limit, q, kind, visibility, tags, collectionIds, removeCollectionIds, sourceIds, confirm })
|
|
41565
41663
|
);
|
|
41566
41664
|
} catch (err) {
|
|
41567
41665
|
return knowledgeError(err);
|
|
@@ -41672,6 +41770,28 @@ server.registerTool(
|
|
|
41672
41770
|
}
|
|
41673
41771
|
}
|
|
41674
41772
|
);
|
|
41773
|
+
server.registerTool(
|
|
41774
|
+
"awesomate_knowledge_collections",
|
|
41775
|
+
{
|
|
41776
|
+
description: "Collections: named sets of knowledge sources with a default audience \u2014 the unit a chatbot is scoped to (agent scope.tags ['collection:<collection_id>']). action 'list' \u2014 every collection with source counts by visibility. 'create' {slug, name, description?, defaultVisibility?} \u2014 defaultVisibility only pre-fills NEW sources' visibility; each source keeps its own. 'get' {collectionId}. 'update' {collectionId, slug?|name?|description?|defaultVisibility?}. 'delete' {collectionId} \u2014 removes the collection; the sources survive (explicit approval first). 'add'/'remove' {collectionId, sourceIds} \u2014 membership. A source may be in several collections. A PUBLIC chatbot over a collection whose sources are all private answers nothing \u2014 check visibility (awesomate_knowledge_sources search) before building on one.",
|
|
41777
|
+
inputSchema: {
|
|
41778
|
+
action: external_exports.enum(["list", "create", "get", "update", "delete", "add", "remove"]),
|
|
41779
|
+
collectionId: external_exports.string().max(64).optional().describe("get/update/delete/add/remove: collection_id from list"),
|
|
41780
|
+
slug: external_exports.string().max(64).optional().describe("create/update: lower-case letters, digits, hyphens"),
|
|
41781
|
+
name: external_exports.string().max(120).optional().describe("create/update"),
|
|
41782
|
+
description: external_exports.string().max(2e3).optional().describe("create/update"),
|
|
41783
|
+
defaultVisibility: external_exports.enum(["private", "internal", "public"]).optional().describe("create/update: pre-fills new sources only"),
|
|
41784
|
+
sourceIds: external_exports.array(external_exports.string().max(300)).max(200).optional().describe("add/remove")
|
|
41785
|
+
}
|
|
41786
|
+
},
|
|
41787
|
+
async (args) => {
|
|
41788
|
+
try {
|
|
41789
|
+
return knowledgeResult(await knowledgeCollections(requireConfig(), args));
|
|
41790
|
+
} catch (err) {
|
|
41791
|
+
return knowledgeError(err);
|
|
41792
|
+
}
|
|
41793
|
+
}
|
|
41794
|
+
);
|
|
41675
41795
|
server.registerTool(
|
|
41676
41796
|
"awesomate_knowledge_people",
|
|
41677
41797
|
{
|
|
@@ -41978,10 +42098,13 @@ server.registerTool(
|
|
|
41978
42098
|
description: "Ingest ONE file from the user's own computer into their Knowledge Base (Pro+). Pass a LOCAL PATH \u2014 this server runs on their machine and streams the file to the hub itself, so the file contents never pass through the conversation. Handles documents (pdf, md, txt), business data (csv, tsv, xls, xlsx, json), audio and video (transcribed), and images. Word/PowerPoint/RTF/EPUB files are NOT parseable yet \u2014 the tool refuses them with the workaround (export to PDF, or save as .md/.txt). Max 100 MB per file; bigger media goes through the hub's Knowledge \u2192 Sources page. INGESTING COSTS MONEY and counts against the monthly allowance, so ALWAYS get explicit approval for the specific file(s) first and say what it will consume. For several files, call once per file and report progress \u2014 do not loop silently. Returns a job with its live status; poll awesomate_knowledge_sources {action:'jobs'} until it succeeds (a duplicate upload replays the earlier job \u2014 a response already reading succeeded needs no polling), then probe the content with awesomate_knowledge_ask before building anything on it. A pack_required response means the allowance is exhausted: nothing was ingested and nothing was purchased.",
|
|
41979
42099
|
inputSchema: {
|
|
41980
42100
|
path: external_exports.string().min(1).max(4096).describe("Path to the file on the user's machine (~ is expanded)"),
|
|
41981
|
-
title: external_exports.string().max(300).optional().describe("Display title; defaults to the filename")
|
|
42101
|
+
title: external_exports.string().max(300).optional().describe("Display title; defaults to the filename"),
|
|
42102
|
+
visibility: external_exports.enum(["private", "internal", "public"]).optional().describe("Who may retrieve this source (default private). public = customers and public chatbots; irreversible once fetched \u2014 ask first."),
|
|
42103
|
+
tags: external_exports.array(external_exports.string().max(64)).max(64).optional().describe("Free-form tags for the new source"),
|
|
42104
|
+
collectionIds: external_exports.array(external_exports.string().max(64)).max(16).optional().describe("Put the new source in these collections (awesomate_knowledge_collections list)")
|
|
41982
42105
|
}
|
|
41983
42106
|
},
|
|
41984
|
-
async ({ path: rawPath, title }) => {
|
|
42107
|
+
async ({ path: rawPath, title, visibility, tags, collectionIds }) => {
|
|
41985
42108
|
try {
|
|
41986
42109
|
const { statSync, existsSync: existsSync3 } = await import("node:fs");
|
|
41987
42110
|
const { resolve: resolve2, basename, extname } = await import("node:path");
|
|
@@ -42021,7 +42144,12 @@ server.registerTool(
|
|
|
42021
42144
|
}
|
|
42022
42145
|
const contentType = KB_UPLOAD_TYPES[ext] ?? "application/octet-stream";
|
|
42023
42146
|
const filename = title?.trim() ? `${title.trim()}${ext}` : basename(abs);
|
|
42024
|
-
const
|
|
42147
|
+
const uploadQuery = new URLSearchParams();
|
|
42148
|
+
if (visibility) uploadQuery.set("visibility", visibility);
|
|
42149
|
+
for (const t of tags ?? []) uploadQuery.append("tags", t);
|
|
42150
|
+
for (const c of collectionIds ?? []) uploadQuery.append("collection_ids", c);
|
|
42151
|
+
const uploadQs = uploadQuery.toString();
|
|
42152
|
+
const result = await hubUploadFile(requireConfig(), `/api/knowledge/sources${uploadQs ? `?${uploadQs}` : ""}`, {
|
|
42025
42153
|
localPath: abs,
|
|
42026
42154
|
filename,
|
|
42027
42155
|
contentType
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awesomate/hosting-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Awesomate MCP server — lets Claude manage your Awesomate WordPress hosting, plan, limits, n8n automations, and build Node/static apps + databases",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -58,7 +58,8 @@ platform's answer beats anything you remember.
|
|
|
58
58
|
|---|---|
|
|
59
59
|
| Tenant state, plan gate, consent, quota, packs (CALL FIRST) | `awesomate_knowledge_status` |
|
|
60
60
|
| Enable the knowledge base (idempotent; 202 = keep polling status) | `awesomate_knowledge_provision` |
|
|
61
|
-
|
|
|
61
|
+
| The LIBRARY: search by title/tag/collection/visibility, list, add url·sitemap (with visibility, tags, collections), tag, set visibility (public needs the slug typed), move between collections, remove, ingest jobs | `awesomate_knowledge_sources` |
|
|
62
|
+
| Collections — named sets of sources a chatbot is scoped to: list / create / update / delete / add / remove members | `awesomate_knowledge_collections` |
|
|
62
63
|
| Instant search with facet counts (find WHAT is in there: moments, pages, datasets; free) | `awesomate_knowledge_search` |
|
|
63
64
|
| Ask a question → verified answer + numbered sources (accepts the same facet `filters` to ask within a slice) | `awesomate_knowledge_ask` |
|
|
64
65
|
| Agent persona / fallback message / model tier — get & set (the single workspace default) | `awesomate_knowledge_agent` |
|