@awesomate/hosting-mcp 0.17.0 → 0.18.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 CHANGED
@@ -39950,11 +39950,11 @@ function scrubKeyMaterial(text) {
39950
39950
  var KNOWLEDGE_GATE_COPY = {
39951
39951
  displayName: "Knowledge Base",
39952
39952
  requiredPlan: "Pro",
39953
- description: "Turn your own content \u2014 videos, blog posts, books, socials \u2014 into a knowledge base your AI agents answer from, with a citation for every claim. If it isn't in your content, the bot says so instead of making something up.",
39953
+ description: "Turn your own content (videos, blog posts, books, socials) into a knowledge base your AI agents answer from, with a citation for every claim. If it isn't in your content, the bot says so instead of making something up.",
39954
39954
  bullets: [
39955
39955
  "Answers come only from your published content, cited back to the exact source",
39956
- `No made-up answers in front of a customer \u2014 no evidence means an honest "I don't know"`,
39957
- "Feed it videos, podcasts, blog posts and books \u2014 we transcribe and index the lot",
39956
+ `No made-up answers in front of a customer: no evidence means an honest "I don't know"`,
39957
+ "Feed it videos, podcasts, blog posts and books. We transcribe and index the lot",
39958
39958
  "Plugs straight into your n8n chat agents, so the 10pm enquiry gets a real answer",
39959
39959
  "Hosted in Sydney, isolated to your account, and gone the moment you delete it"
39960
39960
  ]
@@ -39965,7 +39965,7 @@ function upsellPayload(apiBase, plan) {
39965
39965
  ...typeof plan === "string" ? { plan } : {},
39966
39966
  feature: KNOWLEDGE_GATE_COPY,
39967
39967
  billingUrl: `${apiBase}/billing`,
39968
- note: "Knowledge Base needs the Pro plan. Do NOT retry \u2014 relay this honestly, share the billing link, and let the user decide. Preview + explicit confirmation before any upgrade."
39968
+ note: "Knowledge Base needs the Pro plan. Do NOT retry. Relay this honestly, share the billing link, and let the user decide. Preview + explicit confirmation before any upgrade."
39969
39969
  };
39970
39970
  }
39971
39971
  function consentPayload(message) {
@@ -39973,14 +39973,14 @@ function consentPayload(message) {
39973
39973
  consent_required: true,
39974
39974
  message,
39975
39975
  settingsPath: 'Settings \u2192 Privacy \u2192 "Knowledge Platform"',
39976
- note: "The user must flip the consent themselves in the hub \u2014 do NOT retry until they confirm it is on."
39976
+ note: "The user must flip the consent themselves in the hub. Do NOT retry until they confirm it is on."
39977
39977
  };
39978
39978
  }
39979
39979
  function notAvailablePayload(apiBase) {
39980
39980
  return {
39981
39981
  available: false,
39982
39982
  reason: "not_available_on_this_hub",
39983
- note: "Knowledge Base is not enabled on this hub (feature switch off, or the hub predates it). The connection itself is fine \u2014 do not retry. The user can ask Awesomate support when it will be available for their account.",
39983
+ note: "Knowledge Base is not enabled on this hub (feature switch off, or the hub predates it). The connection itself is fine; do not retry. The user can ask Awesomate support when it will be available for their account.",
39984
39984
  hubUrl: apiBase
39985
39985
  };
39986
39986
  }
@@ -39990,7 +39990,7 @@ function packConfirmationPayload(body) {
39990
39990
  purchased: false,
39991
39991
  dimension: body.dimension ?? null,
39992
39992
  pack: body.pack ?? null,
39993
- note: "This ingest would exceed the included allowance. NOTHING was purchased and the source was NOT added. An Ingestion Pack costs 1 credit ($100) \u2014 state that plainly, get an explicit yes, then send the user to the hub Knowledge \u2192 Usage page to buy it (this tool never spends credits)."
39993
+ note: "This ingest would exceed the included allowance. NOTHING was purchased and the source was NOT added. An Ingestion Pack costs 1 credit ($100). State that plainly, get an explicit yes, then send the user to the hub Knowledge \u2192 Usage page to buy it (this tool never spends credits)."
39994
39994
  };
39995
39995
  }
39996
39996
  function bodyOf(err) {
@@ -40018,14 +40018,14 @@ async function knowledgeStatus(config3) {
40018
40018
  const annotated = {
40019
40019
  ...status,
40020
40020
  usage_glossary: {
40021
- pages: "month-to-date hub-submitted page quota used (vs usage.included.pages) \u2014 NOT the size of the library",
40021
+ pages: "month-to-date hub-submitted page quota used (vs usage.included.pages): NOT the size of the library",
40022
40022
  sources_total: 'sources currently in the library; kinds in usage.sources_by_kind or awesomate_knowledge_sources {action:"summary"}'
40023
40023
  }
40024
40024
  };
40025
40025
  if (usage.sources_total_source === "hourly_gauge") {
40026
- annotated.note = "The live source count failed for this call: usage.sources_total / sources_failed are the last hourly gauge \u2014 possibly stale, and 0 for a library the gauge could never count. Retry before quoting them; the tenant itself is active.";
40026
+ annotated.note = "The live source count failed for this call: usage.sources_total / sources_failed are the last hourly gauge: possibly stale, and 0 for a library the gauge could never count. Retry before quoting them; the tenant itself is active.";
40027
40027
  } else if (usage.sources_total_truncated === true) {
40028
- annotated.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.`;
40028
+ annotated.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: never quote it as the exact total.`;
40029
40029
  }
40030
40030
  return annotated;
40031
40031
  } catch (err) {
@@ -40038,7 +40038,7 @@ async function knowledgeProvision(config3) {
40038
40038
  if (result.pending) {
40039
40039
  return {
40040
40040
  ...result,
40041
- note: "Provisioning continues in the background \u2014 poll awesomate_knowledge_status until the tenant is active (a few minutes at most). Re-calling provision is safe (idempotent)."
40041
+ note: "Provisioning continues in the background. Poll awesomate_knowledge_status until the tenant is active (a few minutes at most). Re-calling provision is safe (idempotent)."
40042
40042
  };
40043
40043
  }
40044
40044
  return result;
@@ -40058,7 +40058,7 @@ function describeSourcePage(page) {
40058
40058
  ...page,
40059
40059
  page: { returned: page.sources.length, kinds_on_this_page: kinds, has_more: hasMore },
40060
40060
  ...hasMore ? {
40061
- 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").'
40061
+ note: 'This is ONE page of the most recently ingested sources, not the whole library: 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").'
40062
40062
  } : {}
40063
40063
  };
40064
40064
  }
@@ -40104,7 +40104,7 @@ async function knowledgeSources(config3, args) {
40104
40104
  if (!args.url && !args.sitemap) {
40105
40105
  return {
40106
40106
  error: "invalid_request",
40107
- note: "add needs url or sitemap. For a local FILE, send the user to the hub: Knowledge \u2192 Sources \u2192 Upload \u2014 files stream there; this tool cannot carry file bytes in v1."
40107
+ note: "add needs url or sitemap. For a local FILE, send the user to the hub: Knowledge \u2192 Sources \u2192 Upload. Files stream there; this tool cannot carry file bytes in v1."
40108
40108
  };
40109
40109
  }
40110
40110
  const body = args.url ? { url: args.url } : { sitemap: args.sitemap, ...args.since ? { since: args.since } : {} };
@@ -40139,7 +40139,7 @@ function renderAnswer(meta, streamedAnswer, streamError = null) {
40139
40139
  detail: streamError ?? (streamedAnswer || null),
40140
40140
  configured_fallback: fallback,
40141
40141
  ...session,
40142
- note: "The knowledge platform failed to answer \u2014 a service problem, NOT a content gap. Do not tell the user their content lacks this. Say the service hit a problem, retry once, and if it persists raise it via awesomate_support. configured_fallback is only what an end customer would have seen meanwhile."
40142
+ note: "The knowledge platform failed to answer: a service problem, NOT a content gap. Do not tell the user their content lacks this. Say the service hit a problem, retry once, and if it persists raise it via awesomate_support. configured_fallback is only what an end customer would have seen meanwhile."
40143
40143
  };
40144
40144
  }
40145
40145
  if (status !== "ok") {
@@ -40149,7 +40149,7 @@ function renderAnswer(meta, streamedAnswer, streamError = null) {
40149
40149
  not_in_verified_content: true,
40150
40150
  configured_fallback: fallback,
40151
40151
  ...session,
40152
- note: "The knowledge base has no verified answer for this \u2014 relay that honestly (use the configured fallback wording if present). Never fill the gap from memory."
40152
+ note: "The knowledge base has no verified answer for this. Relay that honestly (use the configured fallback wording if present). Never fill the gap from memory."
40153
40153
  };
40154
40154
  }
40155
40155
  const rawSources = Array.isArray(meta.sources) ? meta.sources : [];
@@ -40166,7 +40166,7 @@ function renderAnswer(meta, streamedAnswer, streamError = null) {
40166
40166
  sources,
40167
40167
  ...typeof meta.score === "number" ? { score: meta.score } : {},
40168
40168
  ...session,
40169
- note: "Present the answer with its numbered sources \u2014 the citations are the product."
40169
+ note: "Present the answer with its numbered sources; the citations are the product."
40170
40170
  };
40171
40171
  }
40172
40172
  async function knowledgeAsk(config3, args) {
@@ -40174,7 +40174,7 @@ async function knowledgeAsk(config3, args) {
40174
40174
  const raw = await hubPost(
40175
40175
  config3,
40176
40176
  "/api/knowledge/chat",
40177
- { question: args.question, ...args.session ? { session: args.session } : {} },
40177
+ { question: args.question, ...args.session ? { session: args.session } : {}, ...args.filters ? { filters: askFilters(args.filters) } : {} },
40178
40178
  { accept: "application/json" }
40179
40179
  );
40180
40180
  if (raw && typeof raw === "object") {
@@ -40210,10 +40210,10 @@ function entityLayerUnavailablePayload() {
40210
40210
  return {
40211
40211
  available: false,
40212
40212
  reason: "entity_layer_not_available",
40213
- note: "People, places and connections are not switched on for this knowledge base yet (the platform has not deployed the entity layer for this tenant). Nothing to fix on the user's side \u2014 do not retry; the counts appear once the first resolution runs."
40213
+ note: "People, places and connections are not switched on for this knowledge base yet (the platform has not deployed the entity layer for this tenant). Nothing to fix on the user's side: do not retry; the counts appear once the first resolution runs."
40214
40214
  };
40215
40215
  }
40216
- var PHOTOS_NOTE = "Text only: names, mention counts and the sources behind them. Photos of unnamed people are only viewable on the hub Knowledge \u2192 People page \u2014 never guess who someone is from a handle.";
40216
+ var PHOTOS_NOTE = "Text only: names, mention counts and the sources behind them. Photos of unnamed people are only viewable on the hub Knowledge \u2192 People page: never guess who someone is from a handle.";
40217
40217
  function invalid(note) {
40218
40218
  return { error: "invalid_request", note };
40219
40219
  }
@@ -40224,7 +40224,7 @@ function mapPeopleError(err, apiBase) {
40224
40224
  return {
40225
40225
  error: "not_found",
40226
40226
  message: typeof body.message === "string" ? body.message : "No such person or entity on this knowledge base",
40227
- note: "Use the exact person_id / entity_id from a fresh list \u2014 ids are opaque and per-tenant."
40227
+ note: "Use the exact person_id / entity_id from a fresh list: ids are opaque and per-tenant."
40228
40228
  };
40229
40229
  }
40230
40230
  }
@@ -40256,13 +40256,13 @@ async function knowledgePeople(config3, args) {
40256
40256
  const page = await hubGet(config3, `/api/knowledge/entities/aliases?${q.toString()}`);
40257
40257
  return {
40258
40258
  ...page,
40259
- note: "Each suggestion is a text name the content uses that probably refers to a known entity. Show the user the alias, the suggested match and the confidence, then use decide with the (kind, alias_norm) pair \u2014 only after they explicitly say accept, reject, or create."
40259
+ note: "Each suggestion is a text name the content uses that probably refers to a known entity. Show the user the alias, the suggested match and the confidence, then use decide with the (kind, alias_norm) pair: only after they explicitly say accept, reject, or create."
40260
40260
  };
40261
40261
  }
40262
40262
  const result = await hubPost(config3, "/api/knowledge/entities/resolve", {});
40263
40263
  return {
40264
40264
  ...result,
40265
- note: result.status === "queued" ? "Resolution queued. It re-scans the content for people/places/topics and counts toward the ingestion allowance; the user's names and decisions are never undone. Check back with list for the refreshed counts." : "A resolution is already queued or running \u2014 nothing new was started. Check back with list for the refreshed counts."
40265
+ note: result.status === "queued" ? "Resolution queued. It re-scans the content for people/places/topics and counts toward the ingestion allowance; the user's names and decisions are never undone. Check back with list for the refreshed counts." : "A resolution is already queued or running: nothing new was started. Check back with list for the refreshed counts."
40266
40266
  };
40267
40267
  }
40268
40268
  if (args.action === "get") {
@@ -40278,7 +40278,7 @@ async function knowledgePeople(config3, args) {
40278
40278
  let body;
40279
40279
  if (args.action === "rename") {
40280
40280
  const name = args.displayName?.trim();
40281
- if (!name) return invalid("rename needs displayName (1\u201380 chars) \u2014 the name the USER gave, never a guess");
40281
+ if (!name) return invalid("rename needs displayName (1\u201380 chars): the name the USER gave, never a guess");
40282
40282
  body = { display_name: name };
40283
40283
  } else {
40284
40284
  body = { status: args.action === "hide" ? "hidden" : "unknown" };
@@ -40292,7 +40292,7 @@ async function knowledgePeople(config3, args) {
40292
40292
  changed: Object.keys(body),
40293
40293
  requested: body,
40294
40294
  ...result,
40295
- note: args.action === "rename" ? "The name is attached to every source this person appears in and the agent uses it from the next reindex. Read the new display_name back to the user to confirm." : args.action === "hide" ? "Hidden \u2014 this person no longer appears in answers. Reversible with unhide." : "Unhidden \u2014 back in answers from the next resolution."
40295
+ note: args.action === "rename" ? "The name is attached to every source this person appears in and the agent uses it from the next reindex. Read the new display_name back to the user to confirm." : args.action === "hide" ? "Hidden: this person no longer appears in answers. Reversible with unhide." : "Unhidden: back in answers from the next resolution."
40296
40296
  };
40297
40297
  }
40298
40298
  if (args.action === "merge") {
@@ -40325,7 +40325,7 @@ async function knowledgePeople(config3, args) {
40325
40325
  return {
40326
40326
  requested: body,
40327
40327
  ...result,
40328
- note: args.decision === "reject" ? "Rejected \u2014 the alias stays a plain text mention and will not be suggested again." : "Accepted \u2014 mentions re-link on the next resolution. Read entity_id back to the user."
40328
+ note: args.decision === "reject" ? "Rejected: the alias stays a plain text mention and will not be suggested again." : "Accepted: mentions re-link on the next resolution. Read entity_id back to the user."
40329
40329
  };
40330
40330
  }
40331
40331
  return invalid(`unknown action ${String(args.action)}`);
@@ -40357,6 +40357,101 @@ async function knowledgeAgent(config3, args) {
40357
40357
  return mapKnowledgeError(err, config3.apiBase);
40358
40358
  }
40359
40359
  }
40360
+ function askFilters(f) {
40361
+ const out = {};
40362
+ for (const name of ["kind", "topic", "person", "place", "category", "author"]) {
40363
+ if (f[name] !== void 0) out[name] = f[name];
40364
+ }
40365
+ const docs = f.doc ?? f.doc_ids;
40366
+ if (docs !== void 0) out.doc_ids = docs;
40367
+ if (f.year !== void 0) {
40368
+ const years = Array.isArray(f.year) ? f.year : [f.year];
40369
+ out.year = years.map((y) => Number(y)).filter((y) => Number.isInteger(y));
40370
+ }
40371
+ return out;
40372
+ }
40373
+ var SENTINEL_PRE = "\uE000";
40374
+ var SENTINEL_POST = "\uE001";
40375
+ function plainSnippet(text) {
40376
+ return text.split(SENTINEL_PRE).join("**").split(SENTINEL_POST).join("**");
40377
+ }
40378
+ async function knowledgeSearch(config3, args) {
40379
+ try {
40380
+ const q = new URLSearchParams();
40381
+ if (args.q) q.set("q", args.q);
40382
+ if (args.kind) q.set("kind", args.kind);
40383
+ for (const [name, values] of [
40384
+ ["topic", args.topic],
40385
+ ["person", args.person],
40386
+ ["place", args.place],
40387
+ ["category", args.category],
40388
+ ["author", args.author],
40389
+ ["year", args.year],
40390
+ ["doc", args.doc]
40391
+ ]) {
40392
+ for (const v of values ?? []) q.append(name, v);
40393
+ }
40394
+ if (args.limit !== void 0) q.set("limit", String(args.limit));
40395
+ if (args.offset !== void 0) q.set("offset", String(args.offset));
40396
+ if (args.include_media) q.set("include", "media");
40397
+ const qs = q.toString();
40398
+ const result = await hubGet(config3, `/api/knowledge/explore${qs ? `?${qs}` : ""}`);
40399
+ const hits = Array.isArray(result.hits) ? result.hits.map((h) => ({
40400
+ ...h,
40401
+ snippet: typeof h.snippet === "string" ? plainSnippet(h.snippet) : h.snippet
40402
+ })) : result.hits;
40403
+ const { highlight: _highlight, ...rest } = result;
40404
+ return {
40405
+ ...rest,
40406
+ hits,
40407
+ note: "Facet counts describe the CURRENT filters; pass repeated facet values to OR within a facet. media URLs (url/poster_url, present with include_media) are presigned and expire in minutes: use them immediately, never store them."
40408
+ };
40409
+ } catch (err) {
40410
+ return mapKnowledgeError(err, config3.apiBase);
40411
+ }
40412
+ }
40413
+ function mapAgentsError(err, apiBase) {
40414
+ if (err instanceof HubApiError && err.status === 404) {
40415
+ const body = bodyOf(err);
40416
+ if (body && body.error === "not_found") {
40417
+ return { error: "not_found", detail: typeof body.message === "string" ? body.message : "No such agent or resource for this account." };
40418
+ }
40419
+ }
40420
+ return mapKnowledgeError(err, apiBase);
40421
+ }
40422
+ async function knowledgeAgents(config3, args) {
40423
+ try {
40424
+ if (args.action === "list") {
40425
+ return await hubGet(config3, "/api/knowledge/agents");
40426
+ }
40427
+ if (args.action === "get") {
40428
+ if (!args.agentId) return { error: "agentId is required for get" };
40429
+ return await hubGet(config3, `/api/knowledge/agents/${encodeURIComponent(args.agentId)}`);
40430
+ }
40431
+ if (args.action === "create") {
40432
+ if (args.goal) {
40433
+ const draft = await hubPost(config3, "/api/knowledge/agents/draft", { goal: args.goal });
40434
+ if (!draft.proposal) return { error: "draft_failed", detail: draft };
40435
+ const created = await hubPost(config3, "/api/knowledge/agents", draft.proposal);
40436
+ return { ...created, test_questions: draft.test_questions ?? [], status_note: "Created as a private DRAFT: test it, then publish when the user approves." };
40437
+ }
40438
+ if (!args.name) return { error: "name (or goal) is required for create" };
40439
+ return await hubPost(config3, "/api/knowledge/agents", { name: args.name });
40440
+ }
40441
+ if (args.action === "publish") {
40442
+ if (!args.agentId) return { error: "agentId is required for publish" };
40443
+ const out = await hubPost(config3, `/api/knowledge/agents/${encodeURIComponent(args.agentId)}/publish`, {});
40444
+ return { ...out, status_note: "Live immediately for every key bound to this agent." };
40445
+ }
40446
+ if (!args.agentId || !args.message) return { error: "agentId and message are required for test" };
40447
+ return await hubPost(config3, `/api/knowledge/agents/${encodeURIComponent(args.agentId)}/chat`, {
40448
+ message: args.message,
40449
+ ...args.sessionId ? { session_id: args.sessionId } : {}
40450
+ });
40451
+ } catch (err) {
40452
+ return mapAgentsError(err, config3.apiBase);
40453
+ }
40454
+ }
40360
40455
 
40361
40456
  // src/index.ts
40362
40457
  var config2 = null;
@@ -41209,18 +41304,55 @@ server.registerTool(
41209
41304
  }
41210
41305
  }
41211
41306
  );
41307
+ server.registerTool(
41308
+ "awesomate_knowledge_search",
41309
+ {
41310
+ description: "Instant search over the knowledge library with live facet counts: the fastest way to see WHAT is in there and to find the exact video moment, book page, dataset or web section. Returns hits (title, kind, locator like t=612-640 or p.42, snippet with **matched words**, score) plus facets {kind, year, category, author, people, places, topics} whose counts describe the current filters: repeat a facet value to OR within it, combine facets to AND. include_media adds presigned url/poster_url to hits: they expire in minutes, use immediately, never store. Keyword-only and free (no answer quota); for a verified ANSWER use awesomate_knowledge_ask, optionally with the same filters.",
41311
+ inputSchema: {
41312
+ q: external_exports.string().max(2e3).optional().describe("Search words; empty lists the library filtered by the facets"),
41313
+ kind: external_exports.enum(["book", "document", "web", "image", "video", "audio", "post", "dataset"]).optional(),
41314
+ topic: external_exports.array(external_exports.string().max(200)).max(10).optional(),
41315
+ person: external_exports.array(external_exports.string().max(200)).max(10).optional(),
41316
+ place: external_exports.array(external_exports.string().max(200)).max(10).optional(),
41317
+ category: external_exports.array(external_exports.string().max(200)).max(10).optional(),
41318
+ author: external_exports.array(external_exports.string().max(200)).max(10).optional(),
41319
+ year: external_exports.array(external_exports.string().regex(/^\d{4}$/)).max(10).optional(),
41320
+ doc: external_exports.array(external_exports.string().max(200)).max(50).optional().describe("Restrict to these doc_ids (from earlier hits)"),
41321
+ limit: external_exports.number().int().min(1).max(50).optional(),
41322
+ offset: external_exports.number().int().min(0).max(2e3).optional(),
41323
+ include_media: external_exports.boolean().optional().describe("Add presigned url/poster_url to hits; they expire in minutes")
41324
+ }
41325
+ },
41326
+ async (args) => {
41327
+ try {
41328
+ return knowledgeResult(await knowledgeSearch(requireConfig(), args));
41329
+ } catch (err) {
41330
+ return knowledgeError(err);
41331
+ }
41332
+ }
41333
+ );
41212
41334
  server.registerTool(
41213
41335
  "awesomate_knowledge_ask",
41214
41336
  {
41215
41337
  description: `Ask the account's knowledge base a question and get the VERIFIED answer with numbered sources (title, locator, url) \u2014 the test surface for 'is my content in there and answering well'. Read status: ok \u2192 present answer + sources. no_results / failed_validation (not_in_verified_content:true) \u2192 the verified content has no answer: relay that honestly (use configured_fallback), never fill the gap from memory \u2014 an honest "it doesn't know" is the feature working. error (platform_error:true) \u2192 the platform itself failed (model/API/infra): NOT a content gap \u2014 never tell the user their content lacks the answer; retry once, then awesomate_support. Counts against the monthly answers quota.`,
41216
41338
  inputSchema: {
41217
41339
  question: external_exports.string().min(1).max(2e3),
41218
- session: external_exports.string().max(128).optional().describe("Stable id to keep follow-up questions in one conversation thread")
41340
+ session: external_exports.string().max(128).optional().describe("Stable id to keep follow-up questions in one conversation thread"),
41341
+ filters: external_exports.object({
41342
+ kind: external_exports.enum(["book", "document", "web", "image", "video", "audio", "post", "dataset"]).optional(),
41343
+ topic: external_exports.array(external_exports.string().max(200)).max(10).optional(),
41344
+ person: external_exports.array(external_exports.string().max(200)).max(10).optional(),
41345
+ place: external_exports.array(external_exports.string().max(200)).max(10).optional(),
41346
+ category: external_exports.array(external_exports.string().max(200)).max(10).optional(),
41347
+ author: external_exports.array(external_exports.string().max(200)).max(10).optional(),
41348
+ year: external_exports.array(external_exports.string().regex(/^\d{4}$/)).max(10).optional(),
41349
+ doc: external_exports.array(external_exports.string().max(200)).max(50).optional().describe("doc_ids from search hits")
41350
+ }).optional().describe("Ask within a slice of the library: EXACTLY the awesomate_knowledge_search input shapes, reusable verbatim; filters only ever narrow")
41219
41351
  }
41220
41352
  },
41221
- async ({ question, session }) => {
41353
+ async ({ question, session, filters }) => {
41222
41354
  try {
41223
- return knowledgeResult(await knowledgeAsk(requireConfig(), { question, session }));
41355
+ return knowledgeResult(await knowledgeAsk(requireConfig(), { question, session, filters }));
41224
41356
  } catch (err) {
41225
41357
  return knowledgeError(err);
41226
41358
  }
@@ -41239,7 +41371,7 @@ server.registerTool(
41239
41371
  tone: external_exports.string().max(500).optional()
41240
41372
  }).optional().describe("set only: persona fields to change"),
41241
41373
  no_answer_message: external_exports.string().max(1e3).optional().describe("set only: wording used when the content has no answer"),
41242
- model_tier: external_exports.enum(["sonnet", "opus"]).optional().describe("set only: opus needs the Embedded plan"),
41374
+ model_tier: external_exports.enum(["flash", "sonnet", "opus"]).optional().describe("set only: flash is the fastest (Gemini Flash, same citation checks), sonnet the thorough default, opus needs the Embedded plan"),
41243
41375
  datasets: external_exports.array(external_exports.string().max(64)).max(16).optional().describe("set only: datasets the agent may answer from")
41244
41376
  }
41245
41377
  },
@@ -41253,6 +41385,27 @@ server.registerTool(
41253
41385
  }
41254
41386
  }
41255
41387
  );
41388
+ server.registerTool(
41389
+ "awesomate_knowledge_agents",
41390
+ {
41391
+ description: "The agent builder (multi-agent; the older awesomate_knowledge_agent tool is the single workspace default). action 'list' \u2014 every agent with status (draft/published vN/suspended). 'get' {agentId} \u2014 full config incl. system message and scope. 'create' {goal} \u2014 AI drafts the whole setup (instructions, scope, tone, test questions) from the account's own content and saves it as a PRIVATE DRAFT (never live, nothing lost); or {name} for a blank draft. 'test' {agentId, message, sessionId?} \u2014 chat with the DRAFT config: free, unmetered, the right way to check behaviour before going live. 'publish' {agentId} \u2014 makes the draft LIVE immediately for every key bound to the agent: get the user's explicit approval first, and read the version back. Editing fields, policies, API keys and the request log live in the hub UI (Knowledge \u2192 Agents); keys are shown once there and never pass through this tool.",
41392
+ inputSchema: {
41393
+ action: external_exports.enum(["list", "get", "create", "publish", "test"]),
41394
+ agentId: external_exports.string().max(64).optional().describe("get/publish/test: agent_id from list"),
41395
+ name: external_exports.string().max(80).optional().describe("create: blank draft with this name"),
41396
+ goal: external_exports.string().max(2e3).optional().describe("create: describe the agent and AI drafts it from the account content"),
41397
+ message: external_exports.string().max(4e3).optional().describe("test: the question to ask the draft"),
41398
+ sessionId: external_exports.string().max(128).optional().describe("test: keep follow-ups in one thread")
41399
+ }
41400
+ },
41401
+ async (args) => {
41402
+ try {
41403
+ return knowledgeResult(await knowledgeAgents(requireConfig(), args));
41404
+ } catch (err) {
41405
+ return knowledgeError(err);
41406
+ }
41407
+ }
41408
+ );
41256
41409
  server.registerTool(
41257
41410
  "awesomate_knowledge_people",
41258
41411
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awesomate/hosting-mcp",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
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",
@@ -32,4 +32,4 @@
32
32
  "esbuild": "^0.25.0",
33
33
  "typescript": "^6.0.3"
34
34
  }
35
- }
35
+ }
@@ -52,8 +52,10 @@ platform's answer beats anything you remember.
52
52
  | Tenant state, plan gate, consent, quota, packs (CALL FIRST) | `awesomate_knowledge_status` |
53
53
  | Enable the knowledge base (idempotent; 202 = keep polling status) | `awesomate_knowledge_provision` |
54
54
  | Sources list / add url·sitemap / remove / ingest jobs | `awesomate_knowledge_sources` |
55
- | Ask a question verified answer + numbered sources | `awesomate_knowledge_ask` |
56
- | Agent persona / fallback message / model tier get & set | `awesomate_knowledge_agent` |
55
+ | Instant search with facet counts (find WHAT is in there: moments, pages, datasets; free) | `awesomate_knowledge_search` |
56
+ | Ask a question verified answer + numbered sources (accepts the same facet `filters` to ask within a slice) | `awesomate_knowledge_ask` |
57
+ | Agent persona / fallback message / model tier — get & set (the single workspace default) | `awesomate_knowledge_agent` |
58
+ | Agent BUILDER: list / get / create (AI-drafted from their content, saved as a private draft) / test the draft / publish (explicit approval first) | `awesomate_knowledge_agents` |
57
59
  | People, places, topics: list / name / hide / merge / alias suggestions / re-run resolution | `awesomate_knowledge_people` |
58
60
  | Refresh these skills from the latest package | `awesomate_skill_update` |
59
61