@awesomate/hosting-mcp 0.16.3 → 0.16.4

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 CHANGED
@@ -40013,6 +40013,13 @@ async function knowledgeStatus(config3) {
40013
40013
  if (status.upgrade_required) {
40014
40014
  return { ...status, upsell: upsellPayload(config3.apiBase, status.plan) };
40015
40015
  }
40016
+ const usage = status.usage;
40017
+ if (usage && usage.sources_total_truncated === true) {
40018
+ return {
40019
+ ...status,
40020
+ note: `usage.sources_total is a floor: the live count stopped at ${String(usage.sources_total)} sources (paged-count cap). The library holds at least that many \u2014 never quote it as the exact total.`
40021
+ };
40022
+ }
40016
40023
  return status;
40017
40024
  } catch (err) {
40018
40025
  return mapKnowledgeError(err, config3.apiBase);
@@ -40032,10 +40039,31 @@ async function knowledgeProvision(config3) {
40032
40039
  return mapKnowledgeError(err, config3.apiBase);
40033
40040
  }
40034
40041
  }
40042
+ function describeSourcePage(page) {
40043
+ if (!Array.isArray(page.sources)) return page;
40044
+ const kinds = {};
40045
+ for (const s of page.sources) {
40046
+ const k = typeof s.kind === "string" ? s.kind : "unknown";
40047
+ kinds[k] = (kinds[k] ?? 0) + 1;
40048
+ }
40049
+ const hasMore = typeof page.next_cursor === "string" && page.next_cursor.length > 0;
40050
+ return {
40051
+ ...page,
40052
+ page: { returned: page.sources.length, kinds_on_this_page: kinds, has_more: hasMore },
40053
+ ...hasMore ? {
40054
+ note: 'This is ONE page of the most recently ingested sources, not the whole library \u2014 do not summarise the knowledge base from it. Pass cursor=next_cursor to continue (limit up to 200). For the total, use awesomate_knowledge_status \u2192 usage.sources_total (sources_total_truncated:true means "at least that many").'
40055
+ } : {}
40056
+ };
40057
+ }
40035
40058
  async function knowledgeSources(config3, args) {
40036
40059
  try {
40037
40060
  if (args.action === "list") {
40038
- return await hubGet(config3, "/api/knowledge/sources");
40061
+ const q = new URLSearchParams();
40062
+ if (args.cursor) q.set("cursor", args.cursor);
40063
+ if (args.limit !== void 0) q.set("limit", String(args.limit));
40064
+ const qs = q.toString();
40065
+ const page = await hubGet(config3, `/api/knowledge/sources${qs ? `?${qs}` : ""}`);
40066
+ return describeSourcePage(page);
40039
40067
  }
40040
40068
  if (args.action === "jobs") {
40041
40069
  const q = args.status ? `?status=${encodeURIComponent(args.status)}` : "";
@@ -40125,7 +40153,8 @@ async function knowledgeAsk(config3, args) {
40125
40153
  { accept: "application/json" }
40126
40154
  );
40127
40155
  if (raw && typeof raw === "object") {
40128
- return renderAnswer(raw, "");
40156
+ const envelope = raw;
40157
+ return renderAnswer(envelope, typeof envelope.answer === "string" ? envelope.answer : "");
40129
40158
  }
40130
40159
  const events = parseSse(String(raw ?? ""));
40131
40160
  let streamedAnswer = "";
@@ -41006,20 +41035,22 @@ server.registerTool(
41006
41035
  server.registerTool(
41007
41036
  "awesomate_knowledge_sources",
41008
41037
  {
41009
- description: "The knowledge base's content sources. action 'list' \u2014 current sources (live metadata). '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), and for local FILES send the user to the hub's Knowledge \u2192 Sources upload page \u2014 this tool cannot carry file bytes. 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.",
41038
+ 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, and the total lives in awesomate_knowledge_status \u2192 usage.sources_total. '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), and for local FILES send the user to the hub's Knowledge \u2192 Sources upload page \u2014 this tool cannot carry file bytes. 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.",
41010
41039
  inputSchema: {
41011
41040
  action: external_exports.enum(["list", "add", "remove", "jobs"]),
41012
41041
  url: external_exports.string().url().optional().describe("add: one public page / blog post / YouTube link"),
41013
41042
  sitemap: external_exports.string().url().optional().describe("add: sitemap.xml URL \u2014 ingests every listed page"),
41014
41043
  since: external_exports.string().optional().describe("add+sitemap only: skip entries with lastmod older than this ISO date"),
41015
41044
  sourceId: external_exports.string().optional().describe("remove only"),
41016
- status: external_exports.string().optional().describe("jobs only: queued|running|succeeded|failed")
41045
+ status: external_exports.string().optional().describe("jobs only: queued|running|succeeded|failed"),
41046
+ cursor: external_exports.string().max(512).optional().describe("list only: next_cursor from the previous page"),
41047
+ limit: external_exports.number().int().min(1).max(200).optional().describe("list only: page size (default 50, max 200)")
41017
41048
  }
41018
41049
  },
41019
- async ({ action, url, sitemap, since, sourceId, status }) => {
41050
+ async ({ action, url, sitemap, since, sourceId, status, cursor, limit }) => {
41020
41051
  try {
41021
41052
  return knowledgeResult(
41022
- await knowledgeSources(requireConfig(), { action, url, sitemap, since, sourceId, status })
41053
+ await knowledgeSources(requireConfig(), { action, url, sitemap, since, sourceId, status, cursor, limit })
41023
41054
  );
41024
41055
  } catch (err) {
41025
41056
  return knowledgeError(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awesomate/hosting-mcp",
3
- "version": "0.16.3",
3
+ "version": "0.16.4",
4
4
  "description": "Awesomate MCP server \u2014 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",
@@ -36,9 +36,13 @@ platform's answer beats anything you remember.
36
36
  content is indexed in Sydney, deletable any time), wait, re-check.
37
37
  - `tenant: null` or `status: 'provisioning'` → not enabled yet /
38
38
  still building; `usage` → month-to-date vs `usage.included` quota.
39
- 3. Only then design: what content exists, what's already ingested
40
- (`awesomate_knowledge_sources {action:'list'}`), what the user wants the
41
- bot to answer.
39
+ 3. Only then design: what content exists, what's already ingested, what the
40
+ user wants the bot to answer. For "what's ingested" use
41
+ `status.usage.sources_total` (with `sources_total_truncated:true` it is a
42
+ floor). `awesomate_knowledge_sources {action:'list'}` returns ONE page —
43
+ the most recently ingested first (default 50, `limit` up to 200) — read
44
+ `page.kinds_on_this_page` / `page.has_more` and follow `next_cursor`;
45
+ never describe the library from a single page.
42
46
 
43
47
  ## 1. Tools
44
48