@awesomate/hosting-mcp 0.87.0 → 0.88.2

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 (39) hide show
  1. package/dist/index.js +6 -136
  2. package/package.json +2 -1
  3. package/skill/CHANGELOG.json +18 -0
  4. package/skill/awesomate-app-builder/SKILL.md +4 -3
  5. package/skill/awesomate-app-builder/references/node-recipes.md +3 -2
  6. package/skill/awesomate-app-builder/references/stack-decision.md +4 -3
  7. package/skill/awesomate-bookings/SKILL.md +9 -6
  8. package/skill/awesomate-database/SKILL.md +52 -62
  9. package/skill/awesomate-n8n/SKILL.md +165 -108
  10. package/skill/awesomate-n8n/evals/n8n-agent-build/graders/grader.md +2 -1
  11. package/skill/awesomate-n8n/references/ai-agents.md +10 -8
  12. package/skill/awesomate-n8n/references/datatables.md +46 -66
  13. package/skill/awesomate-n8n/references/error-handling.md +5 -5
  14. package/skill/awesomate-n8n/references/n8n-agents.md +10 -9
  15. package/skill/awesomate-n8n/references/onebrain.md +4 -4
  16. package/skill/awesomate-n8n/references/platform-notes.md +13 -13
  17. package/skill/awesomate-n8n/references/possibilities.md +12 -11
  18. package/skill/awesomate-n8n/references/testing-policy.md +51 -47
  19. package/skill/awesomate-n8n/references/troubleshooting.md +15 -16
  20. package/skill/awesomate-n8n/references/webhook-pages.md +5 -5
  21. package/skill/awesomate-n8n/references/wp-form-handler.md +6 -4
  22. package/skill/awesomate-n8n/evals/ai-agent-build/graders/grader.md +0 -31
  23. package/skill/awesomate-n8n/evals/ai-agent-build/prompt.md +0 -1
  24. package/skill/awesomate-n8n/evals/build-form-email/graders/grader.md +0 -30
  25. package/skill/awesomate-n8n/evals/build-form-email/prompt.md +0 -1
  26. package/skill/awesomate-n8n/evals/datatable-dedupe/graders/grader.md +0 -32
  27. package/skill/awesomate-n8n/evals/datatable-dedupe/prompt.md +0 -2
  28. package/skill/awesomate-n8n/evals/essentials-upsell/graders/grader.md +0 -27
  29. package/skill/awesomate-n8n/evals/essentials-upsell/prompt.md +0 -2
  30. package/skill/awesomate-n8n/evals/live-change-promote/graders/grader.md +0 -35
  31. package/skill/awesomate-n8n/evals/live-change-promote/prompt.md +0 -2
  32. package/skill/awesomate-n8n/evals/validated-not-done/graders/grader.md +0 -27
  33. package/skill/awesomate-n8n/evals/validated-not-done/prompt.md +0 -2
  34. package/skill/awesomate-n8n/evals/webhook-body-fix/graders/grader.md +0 -26
  35. package/skill/awesomate-n8n/evals/webhook-body-fix/prompt.md +0 -3
  36. package/skill/awesomate-n8n/evals/webhook-page-build/graders/grader.md +0 -36
  37. package/skill/awesomate-n8n/evals/webhook-page-build/prompt.md +0 -1
  38. package/skill/awesomate-n8n/references/rest-fallback.md +0 -77
  39. package/skill/awesomate-n8n/references/upgrade-loop.md +0 -98
package/dist/index.js CHANGED
@@ -41766,14 +41766,10 @@ var TITLES = {
41766
41766
  awesomate_n8n_findings: "Get n8n findings",
41767
41767
  awesomate_n8n_kpis: "Get n8n KPIs",
41768
41768
  awesomate_n8n_node_docs: "Get n8n node docs",
41769
- awesomate_n8n_deploy: "Deploy n8n workflow",
41770
41769
  awesomate_n8n_agents: "Build n8n Agents",
41771
41770
  awesomate_n8n_library: "Install Awesomate templates",
41772
41771
  awesomate_book_session: "Book a session with Awesomate",
41773
- awesomate_n8n_test: "Test-fire n8n workflow",
41774
- awesomate_n8n_datatable_write: "Write to n8n data table",
41775
41772
  awesomate_n8n_attach_to_app: "Attach n8n to app",
41776
- awesomate_n8n_provision_pg: "Provision Postgres for n8n",
41777
41773
  awesomate_request_build: "Request a build from Awesomate",
41778
41774
  awesomate_knowledge_status: "Get Knowledge Base status",
41779
41775
  awesomate_knowledge_provision: "Enable Knowledge Base",
@@ -41866,65 +41862,9 @@ server.registerTool(
41866
41862
  );
41867
41863
  readTool(
41868
41864
  "awesomate_n8n_context",
41869
- "Call FIRST before any n8n work. Returns the client's n8n instance URL, plan, whether Claude Code n8n access is consented (if consented=false, send the user to settingsUrl and re-check after), builder capability (Support Plus+), instance variant, and build/test quota limits. When consented it also returns an instance fingerprint (community packages, workflow/credential/datatable counts). Companion tools once consented: awesomate_n8n_workflows (world picture), awesomate_n8n_inspect (nodes/datatables/possibilities/credentials/variables), awesomate_n8n_executions, awesomate_n8n_node_docs (live node schemas + community templates \u2014 every plan).",
41865
+ "Call FIRST before any n8n work. Returns the client's n8n instance URL, plan, whether Claude Code n8n access is consented (if consented=false, send the user to settingsUrl and re-check after), template-install capability (Support Plus+) and instance variant. When consented it also returns an instance fingerprint (community packages, workflow/credential/datatable counts). Companion tools once consented: awesomate_n8n_workflows (world picture), awesomate_n8n_inspect (nodes/datatables/possibilities/credentials/variables), awesomate_n8n_executions, awesomate_n8n_node_docs (live node schemas + community templates \u2014 every plan).",
41870
41866
  "/api/my-n8n/machine/context"
41871
41867
  );
41872
- server.registerTool(
41873
- "awesomate_n8n_deploy",
41874
- {
41875
- annotations: annotate("awesomate_n8n_deploy", DESTRUCTIVE),
41876
- description: "Workflow lifecycle writes on the client's n8n, all consent-gated and audited server-side. Actions: 'validate' (structural + n8n-mcp check of workflowJson; ALWAYS validate before create_draft), 'create_draft' (creates an INACTIVE '[CLI] ' workflow tagged awm:client-cli; returns its webhook URLs), 'activate'/'deactivate' (activation strips the [CLI] prefix; production webhooks respond only while active; one Awesomate built may be switched on or off, and the reply says built_by_us so you can tell the client what it does first, but every other write to it is refused with agency_managed; switching on a workflow installed from the library with an empty or missing credential answers 409 setup_incomplete with the list, so walk the client through filling it first), 'promote' (swaps a TESTED draft into the live workflow IN PLACE: live id + webhookIds preserved so external callers keep working; pass workflowId=the LIVE id and draftId=the tested draft; the draft is archived '[promoted <date>]'; response includes operationId for rollback), 'rollback' (restore a promote's pre-swap state; pass operationId), 'update_draft' (replace an INACTIVE self-built draft's full JSON in place; pass workflowId + workflowJson; live workflows are refused, use the promote path), 'delete_draft' (inactive self-built drafts only). Get explicit user approval before activate, promote, rollback, and delete_draft. 429 quota_exceeded = daily plan limit; 403 consent_required \u2192 send user to settingsUrl; 409 n8n_credential_invalid = the user's OWN n8n rejected the stored API key (NOT a hub outage: reads and validate keep working because they never touch their instance): tell them to create a new API key in their n8n under Settings \u2192 n8n API, paste it into their Awesomate account at hub.awesomate.ai/n8n/settings, then retry.",
41877
- inputSchema: {
41878
- action: external_exports.enum(["validate", "create_draft", "update_draft", "activate", "deactivate", "promote", "rollback", "delete_draft"]),
41879
- workflowJson: external_exports.record(external_exports.unknown()).optional().describe("For validate: the full workflow JSON. For create_draft: must contain name, nodes, connections (settings optional)."),
41880
- workflowId: external_exports.string().optional().describe("Required for activate/deactivate/delete_draft; for promote this is the LIVE workflow id"),
41881
- draftId: external_exports.string().optional().describe("promote only: the tested draft to swap into the live workflow"),
41882
- operationId: external_exports.string().optional().describe("rollback only: the operationId returned by promote")
41883
- }
41884
- },
41885
- async ({ action, workflowJson, workflowId, draftId, operationId }) => {
41886
- try {
41887
- if (action === "validate") {
41888
- return textResult(await hubPost(requireConfig(), "/api/my-n8n/machine/workflows/validate", { workflow: workflowJson }));
41889
- }
41890
- if (action === "create_draft") {
41891
- return textResult(await hubPost(requireConfig(), "/api/my-n8n/machine/workflows/draft", workflowJson ?? {}));
41892
- }
41893
- if (action === "update_draft") {
41894
- if (!workflowId) return errorResult(new Error("workflowId is required for update_draft"));
41895
- if (!workflowJson) return errorResult(new Error("workflowJson (full: name, nodes, connections, settings?) is required for update_draft"));
41896
- return textResult(
41897
- await hubPatch(requireConfig(), `/api/my-n8n/machine/workflows/${encodeURIComponent(workflowId)}`, workflowJson)
41898
- );
41899
- }
41900
- if (action === "rollback") {
41901
- if (!operationId) return errorResult(new Error("operationId is required for rollback"));
41902
- return textResult(
41903
- await hubPost(requireConfig(), `/api/my-n8n/machine/operations/${encodeURIComponent(operationId)}/rollback`, {})
41904
- );
41905
- }
41906
- if (!workflowId) return errorResult(new Error(`workflowId is required for ${action}`));
41907
- if (action === "activate" || action === "deactivate") {
41908
- return textResult(
41909
- await hubPost(requireConfig(), `/api/my-n8n/machine/workflows/${encodeURIComponent(workflowId)}/activate`, {
41910
- active: action === "activate"
41911
- })
41912
- );
41913
- }
41914
- if (action === "promote") {
41915
- if (!draftId) return errorResult(new Error("draftId is required for promote"));
41916
- return textResult(
41917
- await hubPost(requireConfig(), `/api/my-n8n/machine/workflows/${encodeURIComponent(workflowId)}/promote`, { draftId })
41918
- );
41919
- }
41920
- return textResult(
41921
- await hubDelete(requireConfig(), `/api/my-n8n/machine/workflows/${encodeURIComponent(workflowId)}`)
41922
- );
41923
- } catch (err) {
41924
- return errorResult(err);
41925
- }
41926
- }
41927
- );
41928
41868
  var N8N_AGENT_TOOLS = [
41929
41869
  "get_agent_builder_reference",
41930
41870
  "search_projects",
@@ -41967,7 +41907,7 @@ server.registerTool(
41967
41907
  "awesomate_n8n_agents",
41968
41908
  {
41969
41909
  annotations: annotate("awesomate_n8n_agents", DESTRUCTIVE),
41970
- description: "Build and manage n8n AGENTS (the Agents tab in n8n 2.41+; NOT the AI Agent node inside a workflow, and NOT the older Chat Hub agents) on the client's own n8n. Every action works on EVERY plan, Essentials included. The hub relays one call at a time to n8n's own instance MCP server, consent-gated, quota-limited and audited; the client's MCP key never reaches this machine. Actions: 'status' (is it set up? keyConfigured / reachable / ready / limits; call FIRST, and when not ready relay setup.steps to the user in plain words), 'describe' (n8n's own description + JSON input schema for every relayed tool, or just `tool`; read it before calling a tool whose arguments you have not seen this session, never guess argument shapes), 'call' (run one n8n agent tool: pass `tool` and its `arguments` exactly as its schema defines them), 'result' (call_id: collect a call that was still running). Before the first build in a session call tool 'get_agent_builder_reference' and follow its build sequence and JSON schema; it is n8n's own live guide and beats anything remembered. Flow: search_projects \u2192 discover_agent_assets (models, workflows, subagents) + list_credentials \u2192 create_agent {projectId, name, config} \u2192 mutate_agent {agentId, baseConfigHash, operation} (always the LATEST configHash; result.ok=false with code stale_config \u2192 get_agent and retry) \u2192 validate_agent \u2192 call_agent with one representative test message (real tools run, say so) \u2192 ask the user \u2192 publish_agent ONLY on their explicit yes. call_agent can take a couple of minutes: this tool waits for it. If it comes back pending with a call_id, or 409 agent_call_in_progress, NEVER resend the message; use 'result'. 504 mcp_timeout means it may have run anyway: check before retrying. Workflow tools must start with an Execute Workflow Trigger and be active (Support Plus+ can activate through awesomate_n8n_deploy; on Essentials the client switches it on in n8n). 403 agent_tool_blocked: the config tried to attach a workflow Awesomate manages, or the n8n node / an n8n API credential; use one of the client's own workflows instead. delete_agent only works on agents Claude created. 409 mcp_key_missing / mcp_disabled / mcp_key_rejected = setup problem on THEIR n8n, relay `hint` + `setup`. 429 quota_exceeded = daily plan limit. A response with ok:false is n8n's own answer: read error.code/message and fix the input, don't retry blindly.",
41910
+ description: "Build and manage n8n AGENTS (the Agents tab in n8n 2.41+; NOT the AI Agent node inside a workflow, and NOT the older Chat Hub agents) on the client's own n8n. Every action works on EVERY plan, Essentials included. The hub relays one call at a time to n8n's own instance MCP server, consent-gated, quota-limited and audited; the client's MCP key never reaches this machine. Actions: 'status' (is it set up? keyConfigured / reachable / ready / limits; call FIRST, and when not ready relay setup.steps to the user in plain words), 'describe' (n8n's own description + JSON input schema for every relayed tool, or just `tool`; read it before calling a tool whose arguments you have not seen this session, never guess argument shapes), 'call' (run one n8n agent tool: pass `tool` and its `arguments` exactly as its schema defines them), 'result' (call_id: collect a call that was still running). Before the first build in a session call tool 'get_agent_builder_reference' and follow its build sequence and JSON schema; it is n8n's own live guide and beats anything remembered. Flow: search_projects \u2192 discover_agent_assets (models, workflows, subagents) + list_credentials \u2192 create_agent {projectId, name, config} \u2192 mutate_agent {agentId, baseConfigHash, operation} (always the LATEST configHash; result.ok=false with code stale_config \u2192 get_agent and retry) \u2192 validate_agent \u2192 call_agent with one representative test message (real tools run, say so) \u2192 ask the user \u2192 publish_agent ONLY on their explicit yes. call_agent can take a couple of minutes: this tool waits for it. If it comes back pending with a call_id, or 409 agent_call_in_progress, NEVER resend the message; use 'result'. 504 mcp_timeout means it may have run anyway: check before retrying. Workflow tools must start with an Execute Workflow Trigger and be active (the client switches it on in n8n, or through their own connection to the instance's MCP server). 403 agent_tool_blocked: the config tried to attach a workflow Awesomate manages, or the n8n node / an n8n API credential; use one of the client's own workflows instead. delete_agent only works on agents Claude created. 409 mcp_key_missing / mcp_disabled / mcp_key_rejected = setup problem on THEIR n8n, relay `hint` + `setup`. 429 quota_exceeded = daily plan limit. A response with ok:false is n8n's own answer: read error.code/message and fix the input, don't retry blindly.",
41971
41911
  inputSchema: {
41972
41912
  action: external_exports.enum(["status", "describe", "call", "result"]),
41973
41913
  tool: external_exports.enum(N8N_AGENT_TOOLS).optional().describe("call: the n8n agent tool to run (required). describe: limit to this tool (optional)"),
@@ -42072,26 +42012,6 @@ server.registerTool(
42072
42012
  }
42073
42013
  }
42074
42014
  );
42075
- server.registerTool(
42076
- "awesomate_n8n_test",
42077
- {
42078
- annotations: annotate("awesomate_n8n_test", MUTATING),
42079
- description: "Fire a synthetic test payload at an ACTIVE self-built workflow's production webhook and get back the webhook response plus the executionId it caused (then poll GET /api/my-n8n/executions/:id for node-by-node results). Sends the X-Awesomate-Test header. Real side effects DO run (emails actually send) \u2014 warn the user, use their own address, prefix subjects with [TEST]. Only works on awm:client-cli-tagged workflows.",
42080
- inputSchema: {
42081
- workflowId: external_exports.string(),
42082
- payload: external_exports.record(external_exports.unknown()).optional().describe("JSON body to POST to the webhook (format-valid, obviously-fake values)")
42083
- }
42084
- },
42085
- async ({ workflowId, payload }) => {
42086
- try {
42087
- return textResult(
42088
- await hubPost(requireConfig(), `/api/my-n8n/machine/workflows/${encodeURIComponent(workflowId)}/test-fire`, { payload })
42089
- );
42090
- } catch (err) {
42091
- return errorResult(err);
42092
- }
42093
- }
42094
- );
42095
42015
  server.registerTool(
42096
42016
  "awesomate_n8n_workflows",
42097
42017
  {
@@ -42207,41 +42127,6 @@ server.registerTool(
42207
42127
  }
42208
42128
  }
42209
42129
  );
42210
- server.registerTool(
42211
- "awesomate_n8n_datatable_write",
42212
- {
42213
- annotations: annotate("awesomate_n8n_datatable_write", DESTRUCTIVE),
42214
- description: "Datatable writes (Support Plus+, consent-gated, audited). 'create' {name, columns:[{name,type?}], workflowId?} \u2014 ALWAYS pass workflowId when the table serves a specific workflow (datatables resolve PER PROJECT at runtime; workflowId threads that workflow's project; a projectWarning in the response means pass it). 'add_column' {tableId, name, type?} \u2014 needs the 'direct database writes' privacy toggle; names: letters/digits/underscores only. 'insert' {tableId, rows:[...]} (\u2264100), 'update' {tableId, filter, data}, 'delete_rows' {tableId, filter \u2014 REQUIRED, there is no delete-all}. Writes only work on tables created through Claude Code (403 not_self_created otherwise \u2014 agency tables are off limits). Get explicit user approval before delete_rows.",
42215
- inputSchema: {
42216
- action: external_exports.enum(["create", "add_column", "insert", "update", "delete_rows"]),
42217
- tableId: external_exports.string().optional(),
42218
- name: external_exports.string().optional().describe("create: table name; add_column: column name"),
42219
- columns: external_exports.array(external_exports.object({ name: external_exports.string(), type: external_exports.enum(["string", "number", "boolean", "date"]).optional() })).optional(),
42220
- workflowId: external_exports.string().optional().describe("create: co-locate the table with this workflow (recommended)"),
42221
- type: external_exports.enum(["string", "number", "boolean", "date"]).optional().describe("add_column only"),
42222
- rows: external_exports.array(external_exports.record(external_exports.unknown())).optional().describe("insert only"),
42223
- filter: external_exports.record(external_exports.unknown()).optional().describe("update/delete_rows: {filters:[{columnName,condition,value}], type?}"),
42224
- data: external_exports.record(external_exports.unknown()).optional().describe("update only: column \u2192 new value")
42225
- }
42226
- },
42227
- async ({ action, tableId, name, columns, workflowId, type, rows, filter, data }) => {
42228
- try {
42229
- const cfg = requireConfig();
42230
- if (action === "create") {
42231
- return textResult(await hubPost(cfg, "/api/my-n8n/machine/datatables", { name, columns, workflowId }));
42232
- }
42233
- if (!tableId) return errorResult(new Error(`tableId is required for ${action}`));
42234
- const base = `/api/my-n8n/machine/datatables/${encodeURIComponent(tableId)}`;
42235
- if (action === "add_column") {
42236
- return textResult(await hubPost(cfg, `${base}/columns`, { name, type }));
42237
- }
42238
- const mode = action === "delete_rows" ? "delete" : action;
42239
- return textResult(await hubPost(cfg, `${base}/rows`, { mode, rows, filter, data }));
42240
- } catch (err) {
42241
- return errorResult(err);
42242
- }
42243
- }
42244
- );
42245
42130
  server.registerTool(
42246
42131
  "awesomate_skill_update",
42247
42132
  {
@@ -42501,7 +42386,7 @@ readTool(
42501
42386
  );
42502
42387
  readTool(
42503
42388
  "awesomate_get_limits",
42504
- "Usage vs plan limits across every dimension (sites, custom domains, apps, database provisions today, workflow credits, AI-editor credits) plus a nudges[] array. Call BEFORE any create action; when a nudge has severity 'approaching' or 'exceeded', surface it to the user with the recommended plan \u2014 never execute an upgrade without preview + explicit confirmation (upgrade tools ship in a later release; for now deep-link to the hub billing page). pgProvisionsToday is a flat daily cap that resets within 24h \u2014 no plan raises it, so don't pitch an upgrade for it.",
42389
+ "Usage vs plan limits across every dimension (sites, custom domains, apps, workflow credits, AI-editor credits) plus a nudges[] array. Call BEFORE any create action; when a nudge has severity 'approaching' or 'exceeded', surface it to the user with the recommended plan \u2014 never execute an upgrade without preview + explicit confirmation (upgrade tools ship in a later release; for now deep-link to the hub billing page).",
42505
42390
  "/api/client-hosting/limits"
42506
42391
  );
42507
42392
  var PLAN_LADDER_FALLBACK = {
@@ -42876,10 +42761,10 @@ server.registerTool(
42876
42761
  "awesomate_n8n_attach_to_app",
42877
42762
  {
42878
42763
  annotations: annotate("awesomate_n8n_attach_to_app", MUTATING),
42879
- description: "Wire an app to call the user's own n8n as a backend. Give it the app + a webhook URL you already created/tested/promoted on their n8n (via awesomate_n8n_deploy \u2014 create_draft returns the webhook URL, and promote preserves it). It stores N8N_WEBHOOK_URL + a generated N8N_WEBHOOK_SECRET on the app (encrypted + injected) and RETURNS the secret so you can add a matching `X-Awesomate-Webhook-Secret` header check to the n8n workflow (so the webhook isn't world-callable). The app then calls it via src/lib/n8n.ts callWorkflow(). Node apps only. Only reach for this when the job needs an external app/credential or AI the user already has in n8n \u2014 not for pure in-app logic.",
42764
+ description: "Wire an app to call the user's own n8n as a backend. Give it the app + the production webhook URL of a workflow on their n8n (read it with awesomate_n8n_workflows; a workflow Claude built through the instance's own MCP server works too). It stores N8N_WEBHOOK_URL + a generated N8N_WEBHOOK_SECRET on the app (encrypted + injected) and RETURNS the secret so you can add a matching `X-Awesomate-Webhook-Secret` header check to the n8n workflow (so the webhook isn't world-callable). The app then calls it via src/lib/n8n.ts callWorkflow(). Node apps only. Only reach for this when the job needs an external app/credential or AI the user already has in n8n \u2014 not for pure in-app logic.",
42880
42765
  inputSchema: {
42881
42766
  appId: external_exports.number().int().positive().describe("The app id"),
42882
- webhookUrl: external_exports.string().url().describe("The n8n workflow's production webhook URL (from awesomate_n8n_deploy)"),
42767
+ webhookUrl: external_exports.string().url().describe("The n8n workflow's production webhook URL"),
42883
42768
  env: external_exports.enum(["dev", "staging", "prod"]).default("dev").describe("Which app environment to wire")
42884
42769
  }
42885
42770
  },
@@ -42927,21 +42812,6 @@ server.registerTool(
42927
42812
  }
42928
42813
  }
42929
42814
  );
42930
- server.registerTool(
42931
- "awesomate_n8n_provision_pg",
42932
- {
42933
- annotations: annotate("awesomate_n8n_provision_pg", MUTATING),
42934
- description: "Provision a NEW Postgres database on the user's own Awesomate cPanel hosting and wire it into their n8n as a ready-to-use `postgres` credential their workflows can select. This is a WRITE that creates real infrastructure \u2014 get explicit user approval first. Requires: their n8n builder access (Support Plus+, allow_client_cli_builds) AND the allow_pg_writes consent (403 consent_required \u2192 send them to settingsUrl); AND an Awesomate cPanel hosting account (409 hosting_required otherwise). Limited to 2/day. Returns the new credential id + name, the database/user, and the password ONCE (it lives in the n8n credential, never stored by Awesomate \u2014 tell the user to note or rotate it). After this, build the workflow selecting the returned Postgres credential.",
42935
- inputSchema: {}
42936
- },
42937
- async () => {
42938
- try {
42939
- return textResult(await hubPost(requireConfig(), "/api/my-n8n/machine/pg-credentials", {}));
42940
- } catch (err) {
42941
- return errorResult(err);
42942
- }
42943
- }
42944
- );
42945
42815
  function knowledgeResult(data) {
42946
42816
  return {
42947
42817
  content: [
@@ -43731,7 +43601,7 @@ server.registerTool(
43731
43601
  key: external_exports.string().max(41).optional().describe("save_calendar, save_service: lower case, digits and underscores"),
43732
43602
  name: external_exports.string().max(80).optional(),
43733
43603
  timezone: external_exports.string().max(60).optional().describe("IANA zone, like Australia/Sydney"),
43734
- hours: external_exports.record(external_exports.string(), external_exports.array(external_exports.tuple([external_exports.string(), external_exports.string()]))).optional().describe('save_calendar: {"mon": [["09:00","17:00"]], ...}'),
43604
+ hours: external_exports.record(external_exports.string(), external_exports.array(external_exports.array(external_exports.string()).length(2))).optional().describe('save_calendar: {"mon": [["09:00","17:00"]], ...}'),
43735
43605
  min_notice_minutes: external_exports.number().int().min(0).optional(),
43736
43606
  buffer_minutes: external_exports.number().int().min(0).optional(),
43737
43607
  max_per_day: external_exports.number().int().min(1).nullable().optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awesomate/hosting-mcp",
3
- "version": "0.87.0",
3
+ "version": "0.88.2",
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",
@@ -28,6 +28,7 @@
28
28
  "zod": "^3.24.1"
29
29
  },
30
30
  "devDependencies": {
31
+ "@anthropic-ai/sdk": "^0.132.0",
31
32
  "@types/node": "^25.9.3",
32
33
  "esbuild": "^0.25.0",
33
34
  "typescript": "^6.0.3"
@@ -1,5 +1,23 @@
1
1
  {
2
2
  "versions": [
3
+ {
4
+ "version": "0.88.2",
5
+ "highlights": [
6
+ "Fixed: the booking diary tool described its opening hours in an older JSON Schema form that strict clients refuse, which would stop every Awesomate tool loading there. Nothing changes in Claude Code"
7
+ ]
8
+ },
9
+ {
10
+ "version": "0.88.1",
11
+ "highlights": [
12
+ "Bookings can keep a calendar's busy times free from Outlook as well as Google Calendar, and write each booking into it; the owner connects it in the hub"
13
+ ]
14
+ },
15
+ {
16
+ "version": "0.88.0",
17
+ "highlights": [
18
+ "Claude no longer builds workflows through Awesomate: it writes them straight on your own n8n through n8n's MCP server (switch on MCP access in your n8n and add its key to Claude Code), with no Awesomate limits on it. Reading your n8n, installing templates and n8n Agents work as before"
19
+ ]
20
+ },
3
21
  {
4
22
  "version": "0.87.0",
5
23
  "highlights": [
@@ -70,9 +70,10 @@ decision brain. The short version, matched to what they say:
70
70
  a static app — there is nowhere to put a secret. Anything the page must
71
71
  keep private (an API key, a webhook URL you don't want public) rules
72
72
  static out.
73
- - **`awesomate_n8n_attach_to_app` is Node-only.** So the "form posts to
74
- their n8n" pattern needs a Node app, unless the webhook URL being public
75
- is genuinely acceptable.
73
+ - **`awesomate_n8n_attach_to_app` is Node-only.** It takes any production
74
+ webhook URL on their n8n and stores it with a secret on the app, so the
75
+ "form posts to their n8n" pattern needs a Node app, unless the webhook
76
+ URL being public is genuinely acceptable.
76
77
  - **No separate dev site.** All three environment URLs point at the same
77
78
  single subdomain — there's no dev copy to review on, so every change is
78
79
  live the moment it's published.
@@ -50,8 +50,9 @@ with a clear reason). Postgres code should prefer `DATABASE_URL`.
50
50
  ## Attach n8n as the backend
51
51
 
52
52
  Job needs email / a lookup in their connected apps / AI → build the webhook
53
- workflow with the awesomate-n8n skill, then `awesomate_n8n_attach_to_app`
54
- (stores `N8N_WEBHOOK_URL` + secret; returns the secret ONCE — add the
53
+ workflow with the awesomate-n8n skill (through the user's own n8n MCP
54
+ server), then `awesomate_n8n_attach_to_app` with its production webhook URL
55
+ (stores `N8N_WEBHOOK_URL` + secret; returns the secret ONCE: add the
55
56
  matching `X-Awesomate-Webhook-Secret` header check to the workflow). The app
56
57
  calls `callWorkflow(payload)` from `src/lib/n8n.ts`; it no-ops when unset and
57
58
  never throws — check `result.ok` and degrade gracefully.
@@ -65,13 +65,14 @@ credentials are already connected there, so there's nothing new to set up.
65
65
  - Check what's connected with `awesomate_n8n_inspect {what:'credentials'}`
66
66
  (names/types only) and offer what they already have: *"You've got Gmail +
67
67
  Google Sheets connected — want the form to email you and add the lead to a
68
- sheet?"* That read needs the **"Build and change automations from Claude Code"**
68
+ sheet?"* That read needs the **"Let Claude Code work with your automations"**
69
69
  privacy toggle, which is off by default — a 403 `consent_required` means
70
70
  call `awesomate_privacy_settings`, name the toggle, and ask the user to flip
71
71
  it at hub.awesomate.ai/settings?tab=privacy.
72
72
  - Build the workflow with the **awesomate-n8n** skill (webhook trigger →
73
- action), take its **webhook URL**, and wire it into the app.
74
- - **Node app:** `awesomate_n8n_attach_to_app` — it stores
73
+ action, written through the user's own n8n MCP server), take its
74
+ **production webhook URL**, and wire it into the app.
75
+ - **Node app:** `awesomate_n8n_attach_to_app` with that URL. It stores
75
76
  `N8N_WEBHOOK_URL` plus a generated `N8N_WEBHOOK_SECRET` (encrypted +
76
77
  injected) and returns the secret so you can add the matching
77
78
  `X-Awesomate-Webhook-Secret` check on the n8n side. `src/lib/n8n.ts`
@@ -82,9 +82,12 @@ themselves cannot be written through `awesomate_crm_write`; only these actions c
82
82
  Essentials, the tool answers `upgrade_required`: say the owner can do the same in the hub under
83
83
  Contacts, Bookings, and do not retry.
84
84
  - Payments and deposits are not part of bookings yet. Do not promise them; the price is shown only.
85
- - **Google Calendar** is connected per calendar in the hub (Contacts, Bookings, Set up, Connect
86
- Google Calendar), by the person whose calendar it is: Claude cannot connect it, so send them
87
- there. Once connected, times they are busy in Google are never offered, and every booking is
88
- written to an "Awesomate bookings" calendar in their Google account, moved and removed with it.
89
- `setup` lists the connected calendars under `links`. Outlook is not available yet; there the
90
- notice email's invite is how a booking reaches their calendar.
85
+ - **Google Calendar or Outlook** is connected per calendar in the hub (Contacts, Bookings, Set
86
+ up, Connect Google Calendar or Connect Outlook), by the person whose calendar it is: Claude
87
+ cannot connect it, so send them there. Once connected, times they are busy there are never
88
+ offered, and every booking is written to an "Awesomate bookings" calendar in their account,
89
+ moved and removed with it. `setup` lists the connected calendars under `links` (each with its
90
+ `provider`), and says which providers this hub offers (`google.available`,
91
+ `microsoft.available`). Where neither is offered, the notice email's invite is how a booking
92
+ reaches their calendar. A work account whose organisation limits apps may need its Microsoft
93
+ 365 admin to approve Awesomate once; the hub says so when that happens.
@@ -20,17 +20,18 @@ write, or for an app your customers log into?"
20
20
 
21
21
  **(a) A list an AUTOMATION reads/writes** — a dedupe ledger, a task
22
22
  queue, a lookup map, form submissions feeding a workflow. → n8n DATA
23
- TABLE, via the awesomate-n8n skill. Create and write with
24
- `awesomate_n8n_datatable_write`, and pass `workflowId` so the table is
25
- co-located with the workflow that uses it. No hosting slot consumed, and
23
+ TABLE, via the awesomate-n8n skill. The table lives in n8n: Claude designs
24
+ the columns, the user creates it in n8n (Data tables in the left menu,
25
+ inside the project that owns the workflow), or Claude creates it through
26
+ their n8n's own MCP server when that server offers a data-table tool. No
27
+ Awesomate tool creates or writes a table. No hosting slot consumed, and
26
28
  workflows query it directly — this is the default answer for anything
27
29
  automation-shaped. Inspect what exists with
28
30
  `awesomate_n8n_inspect {what:'datatables'}`.
29
- **Both the write AND that read are gated:** Support Plus or above, plus the
30
- privacy switch **"Build and change automations from Claude Code"** in Settings,
31
- Privacy (hub.awesomate.ai/settings?tab=privacy, which is what the 403's
32
- `settingsUrl` points at). It is **off by default**, so on a fresh account
33
- both the read and the write come back 403 `consent_required`. Call
31
+ **That read is gated** by the privacy switch **"Let Claude Code work with
32
+ your automations"** in Settings, Privacy (hub.awesomate.ai/settings?tab=privacy,
33
+ which is what the 403's `settingsUrl` points at). It is **off by default**,
34
+ so on a fresh account the read comes back 403 `consent_required`. Call
34
35
  `awesomate_privacy_settings` to name the exact toggle that's off, send the
35
36
  user to flip it, then re-check. You cannot flip it for them.
36
37
 
@@ -43,25 +44,24 @@ app serves to people. → the app's own Postgres.
43
44
  via the awesomate-app-builder skill, which wires it in from the start.
44
45
 
45
46
  **(c) A WORKFLOW that needs raw SQL against its own Postgres** — real
46
- joins, aggregates, or volumes a data table shouldn't carry. →
47
- `awesomate_n8n_provision_pg`. One step creates the database AND the n8n
48
- credential, so the workflow can query it immediately. It has the most gates
49
- of anything here — check them BEFORE offering it, so the user doesn't hit a
50
- wall halfway:
51
- - Support Plus or above.
52
- - The **"Build and change automations from Claude Code"** toggle (off by
53
- default) — same one as branch (a).
54
- - The **direct database writes** consent (`allow_pg_writes`). It's on by
55
- default, so this is rare — but it has **no client-facing toggle in the
56
- hub**, so if it's off, don't send the user hunting for a switch that
57
- doesn't exist: route it to support via the awesomate-support skill.
58
- - An Awesomate cPanel hosting account. Without one it returns 409
59
- `hosting_required`; hosting comes first (awesomate-hosting skill).
60
- - Capped at **2 a day**.
61
-
62
- On any 403 here, call `awesomate_privacy_settings` first — it names the
63
- exact toggle that's blocking, which decides whether this is a "flip this
64
- switch" or a "raise it with support" answer.
47
+ joins, aggregates, or volumes a data table shouldn't carry. → a Postgres
48
+ credential the user creates in their own n8n. No Awesomate tool provisions
49
+ this any more; it is two steps the user does, and you walk them through:
50
+ 1. Get a database. If they have an Awesomate hosting account and cPanel
51
+ shows a **PostgreSQL Databases** page (not every package does; check
52
+ before promising it), it makes one (database + user + password) in a
53
+ minute; the awesomate-hosting skill opens cPanel for them. If their data
54
+ already lives in a Postgres somewhere else (their app's database, Supabase,
55
+ Neon), use that one: see (d).
56
+ 2. Create the credential in n8n at `{instanceUrl}/home/credentials`
57
+ (type Postgres: host, port, database, user, password, SSL as cPanel shows
58
+ them). The password goes from cPanel into n8n and never through the chat.
59
+ Then confirm it exists with `awesomate_n8n_inspect {what:'credentials'}`
60
+ and build the workflow on it (awesomate-n8n skill).
61
+ An app database made by `awesomate_app_provision_db` belongs to the app: a
62
+ workflow reads it through the app's own API, or through a credential the
63
+ user makes on purpose from the app's connection details, never by Claude
64
+ copying `DATABASE_URL` into n8n.
65
65
 
66
66
  **(d) Analytics/BI or data shared with other systems** — reporting
67
67
  warehouses, a spreadsheet the whole team lives in, a CRM. → recommend
@@ -92,19 +92,15 @@ reach), ask "live or dev?" before provisioning against it.
92
92
 
93
93
  ## 2. Safety rules
94
94
 
95
- - **Passwords land where they belong, and the two branches differ.**
96
- `awesomate_app_provision_db` NEVER returns a password: it's set
97
- server-side, stored encrypted, and injected as the app's `DATABASE_URL`
98
- — there is nothing to show, so don't promise the user a password.
99
- `awesomate_n8n_provision_pg` is the one that DOES return a password, once,
100
- because it lives in the n8n credential and Awesomate never stores it. The
101
- workflow doesn't need you to repeat it — the credential already holds it —
102
- so say that, and only offer the value if the user actually needs it
103
- elsewhere, warning that it has now passed through the transcript and
104
- should be rotated. Never put a `DATABASE_URL` in a message. Tell the user where
105
- it lives instead: "the app already has its connection — nothing for you
106
- to copy." (After an app database is provisioned, the app needs a restart
107
- or redeploy to pick it up.)
95
+ - **Passwords land where they belong.** `awesomate_app_provision_db`
96
+ NEVER returns a password: it's set server-side, stored encrypted, and
97
+ injected as the app's `DATABASE_URL`. There is nothing to show, so don't
98
+ promise the user a password. A workflow Postgres password lives in the n8n
99
+ credential the user created; never ask for it and never put it, or a
100
+ `DATABASE_URL`, in a message. Tell the user where it lives instead: "the
101
+ app already has its connection, nothing for you to copy." (After an app
102
+ database is provisioned, the app needs a restart or redeploy to pick it
103
+ up.)
108
104
  - Secrets the user's own app code needs (API keys, tokens) go through
109
105
  the awesomate-credentials skill, never pasted into files or chat.
110
106
  - **Deleting data requires an explicit filter and an explicit yes.**
@@ -114,28 +110,22 @@ reach), ask "live or dev?" before provisioning against it.
114
110
 
115
111
  ## 3. Limits, honestly
116
112
 
117
- Everything that provisions here needs **Support Plus or above** — app
118
- databases (`awesomate_app_provision_db`), workflow Postgres
119
- (`awesomate_n8n_provision_pg`) and data tables alike. Data tables are NOT
120
- "any plan with n8n access": Essentials gets 0 creations a day, and both the
121
- table read and the write also need the "Build and change automations from Claude Code" toggle (§0(a)).
122
-
123
- Only some of it is capped per day:
124
- - `awesomate_n8n_provision_pg` — **2 a day**, flat; no plan raises it, so
125
- don't pitch an upgrade for it.
126
- - Data table creations — **10 a day** on Support Plus and Pro (20 on
127
- Embedded), 0 on Essentials. An instance also tops out at 50 data tables.
128
- - `awesomate_app_provision_db` — **no daily cap**. It's one database per
129
- environment and refuses (409 `already_has_db`) if the app has one, so
130
- there's nothing to ration.
131
-
132
- If the user's plan doesn't cover what branch (b) or (c) needs, say it once
133
- — "app databases are on Support Plus" — point them at
134
- hub.awesomate.ai/billing to upgrade, then help fully within what their plan
135
- allows. On Essentials that means none of (a), (b) or (c) is available —
136
- don't dangle a data table as the consolation prize; say so once and look at
137
- (d), keeping the data where it already lives and connecting to it. If a
138
- daily quota is hit, say when it resets and what can proceed meanwhile.
113
+ App databases (`awesomate_app_provision_db`) need **Support Plus or
114
+ above**. There is **no daily cap**: it's one database per environment and
115
+ refuses (409 `already_has_db`) if the app has one, so there's nothing to
116
+ ration.
117
+
118
+ Data tables (a) and a workflow Postgres (c) are n8n's own features on every
119
+ plan, with no Awesomate gate, limit or count: the user creates them in n8n
120
+ and in cPanel. An instance tops out at 50 data tables (n8n's cap). Reading
121
+ tables or credentials from here needs the "Let Claude Code work with your
122
+ automations" toggle (§0(a)).
123
+
124
+ If the user's plan doesn't cover what branch (b) needs, say it once ("app
125
+ databases are on Support Plus"), point them at hub.awesomate.ai/billing to
126
+ upgrade, then help fully within what their plan allows: on Essentials (a)
127
+ and (c) still work, and so does (d), keeping the data where it already lives
128
+ and connecting to it.
139
129
 
140
130
  Report every result as a business outcome: "your workflow now remembers
141
131
  every invoice it's processed, so no customer gets emailed twice" — with