Agent Skills / maison-features
Install this skill alone, or read it below. Raw file: SKILL.md · references/tools.md
npx skills add https://docs.maison-labs.com --skill maison-featuresMaison — Feature plans and entitlements (Maison staff)
Control what a hotel's plan includes: read the caller's per-feature access snapshot for a hotel, list and change the hotel's entitled features (grant/revoke in one call), push a feature to every child property, and manage plan templates (create, update, assign, apply with optional pruning, drift report, per-client overrides, plan history), Maison's payment gateway fees and the feature catalogue. Each plan feature is on or locked (shown to the hotel locked, with the plan's message); a feature left out is off. Use when a hotel upgrades or downgrades, when a tool answers 403 not_entitled, or when standardising plans across a group.
Part of the Maison public API. Read the maison-public-api skill first for authentication, discovery and transport details (https://docs.maison-labs.com/skills/maison-public-api/SKILL.md).
When to use
- A tool returned
not_entitled—get_client_accessshows what the plan lacks;set_client_featuresfixes it. - Roll out a plan —
set_client_plan(assign + apply) orapply_plan_template. - Who changed a plan and when —
list_plan_template_history/list_client_plan_history. - Invoice hotels for payments —
get_gateway_fee_totalswithfrom/to(optionallyclientId).
Before you start
- Send
x-api-key: <key>on every call; the key only reaches/api/v1. GET /api/v1/tools(or MCPtools/list) returns the tools THIS key may run — if a tool below is missing there, you lack a grant; do not retry it.- Client-scoped tools take
clientId(a hotel id).whoamilists the ids you can act on.
Tools
| Tool | What it does | REST | Needs |
|---|---|---|---|
apply_plan_template | Sync the client's features to its assigned template: grant missing features, optionally revoke extras. | POST /api/v1/client/{clientId}/plan/apply | client-feature-management WRITE (global) |
assign_plan_template | Assign or remove the client's plan template (pass null to unassign). | PUT /api/v1/client/{clientId}/plan | client-feature-management WRITE (global) |
clear_client_feature_override | Remove the client's override for one feature so it follows the plan template again, and reconcile its features. | DELETE /api/v1/client/{clientId}/plan/override/{feature} | client-feature-management WRITE (global); destructive |
clear_client_gateway_fee | Remove the hotel's own fee for one gateway so its plan's fee applies again. | DELETE /api/v1/client/{clientId}/gatewayfee/{gateway} | clients WRITE (global); destructive |
clear_plan_gateway_fee | Remove a plan template's fee for one gateway; its clients without a fee of their own then pay none. | DELETE /api/v1/featureplan/{templateId}/gatewayfee/{gateway} | clients WRITE (global); destructive |
create_feature | Add a feature to the catalogue that grants (policy rules) and plans name. | POST /api/v1/feature | maison-roles WRITE (global) |
create_plan_template | Create a new plan template. | POST /api/v1/featureplan | client-feature-management WRITE (global) |
delete_plan_template | Soft-delete a plan template. | DELETE /api/v1/featureplan/{templateId} | client-feature-management WRITE (global); destructive |
deprecate_feature | Mark a catalogue feature deprecated: it leaves the catalogue offered to grants and plans and every client's eligibility. | DELETE /api/v1/feature/{featureId} | maison-roles WRITE (global); destructive |
get_client_access | For every feature in the catalogue, returns whether the caller is entitled (plan), and whether they may read, write or execute it on this client; plus lockedFeatures (features the plan shows locked — offered as an upgrade, not hidden) and lockedMessage (the plan's locked copy, or the default). | GET /api/v1/client/{clientId}/access | clients READ (client); read-only |
get_client_plan | Return the client's assigned plan template, its overrides ([{ feature, state }]), the effective entitlement (effective), the features shown locked (locked) and the drift: features the client has that its plan and overrides don't call for (extra), and effective features it is missing (missing). | GET /api/v1/client/{clientId}/plan | client-feature-management READ (global); read-only |
get_gateway_fee_totals | Paid payments and the Maison fees recorded on them for an inclusive date range, per client, gateway and currency (amounts in minor units), optionally for one client. | GET /api/v1/gatewayfees/totals | clients READ (global); read-only |
get_plan_template | Return one plan template by id, including its features with their states, locked message and counts. | GET /api/v1/featureplan/{templateId} | client-feature-management READ (global); read-only |
grant_client_feature | Add a single feature to the client's plan. | POST /api/v1/client/{clientId}/feature | client-feature-management WRITE (global) |
grant_feature_to_children | Add a feature to every child property's plan. | POST /api/v1/client/{clientId}/children/feature | client-feature-management WRITE (global) |
list_client_features | Returns the feature strings currently in the client's plan (layer-1 entitlements). | GET /api/v1/client/{clientId}/features | client-feature-management READ (global); read-only |
list_client_gateway_fees | Maison's fee per payment gateway (stripe, elavon) for one hotel as it applies: the client's own fee, else its plan's, else none (source: client | template | null). | GET /api/v1/client/{clientId}/gatewayfees | update-client READ (client); read-only |
list_client_plan_history | A client's plan history, newest first: the plans it was assigned and its feature override changes. | GET /api/v1/client/{clientId}/plan/history | client-feature-management READ (global); read-only |
list_plan_gateway_fees | The Maison fees a plan template sets per gateway; every client on the plan without its own fee pays these. | GET /api/v1/featureplan/{templateId}/gatewayfees | clients READ (global); read-only |
list_plan_template_clients | The active clients on one plan template (id and name), as the plan page lists them. | GET /api/v1/featureplan/{templateId}/clients | client-feature-management READ (global); read-only |
list_plan_template_history | A plan template's change history, newest first: its own field and feature-state changes, its creation and deletion, and clients assigned to it or moved off it. | GET /api/v1/featureplan/{templateId}/history | client-feature-management READ (global); read-only |
list_plan_templates | List all non-deleted plan templates with their features ([{ feature, state }], state "on" or "locked"), locked message and counts (client_count, on_count, locked_count). | GET /api/v1/featureplans | client-feature-management READ (global); read-only |
revoke_client_feature | Remove a single feature from the client's plan. | DELETE /api/v1/client/{clientId}/feature/{feature} | client-feature-management WRITE (global); destructive |
set_client_feature_override | Set the client's own state for one feature ("on", "off" or "locked"), winning over its plan template, and reconcile its features. | PUT /api/v1/client/{clientId}/plan/override/{feature} | client-feature-management WRITE (global) |
set_client_features | Grant and/or revoke a set of features. | PUT /api/v1/client/{clientId}/features | client-feature-management WRITE (global); composite of grant_client_feature, revoke_client_feature |
set_client_gateway_fee | Set the hotel's own Maison fee for one gateway, overriding its plan's fee; recorded on each later payment for invoicing. | PUT /api/v1/client/{clientId}/gatewayfee/{gateway} | clients WRITE (global) |
set_client_plan | Assign a template, set the client's overrides (each { feature, state } with state "on", "off" or "locked"; a plain name means on) and apply it. | PUT /api/v1/client/{clientId}/plan/set | client-feature-management WRITE (global); composite of assign_plan_template, set_client_feature_override, apply_plan_template |
set_plan_gateway_fee | Set a plan template's Maison fee for one gateway; it applies to every client on the plan that has no fee of its own. | PUT /api/v1/featureplan/{templateId}/gatewayfee/{gateway} | clients WRITE (global) |
update_feature | Rename a catalogue feature or change its description; at least one field. | PUT /api/v1/feature/{featureId} | maison-roles WRITE (global) |
update_plan_template | Update the name, description, locked message or features (with their states) of an existing plan template; changing the features reconciles every client on the plan. | PUT /api/v1/featureplan/{templateId} | client-feature-management WRITE (global) |
Full input fields for every tool: references/tools.md.
Recommended workflows
Upgrade a hotel to a plan template
list_plan_templates→ pick the template id.set_client_planwithtemplateIdandprune: false(keeps extra grants) ortrue(exact match).get_client_planto review drift afterwards.
Give one hotel an exception to its plan
set_client_feature_overridewithstate"on","off"or"locked"— it wins over the plan and the hotel's features are reconciled at once.clear_client_feature_overridereturns the feature to the plan default.get_client_planlists the hotel's overrides and itslockedfeatures.
Tips
get_client_accessis the fastest way to answer 'what can I do for this hotel?' — it merges plan entitlement with the caller's grants.- Plan history pages by offset (
limit,offset) and returnstotal. - Gateway fees: a client's own fee wins over its plan's fee (
sourcesays which applies); setting and clearing fees is Maison staff only (globalclientsWRITE). create_feature/update_feature/deprecate_featurechange the platform feature catalogue (globalmaison-rolesWRITE) — prefer an existing feature.
Pitfalls
- All plan tools except
get_client_accessneed the GLOBALclient-feature-managementgrant (Maison staff). apply_plan_templatewithprune: truerevokes features not in the template — confirm with the user first.- A Maison-only feature cannot be locked (400) — use off instead.
delete_plan_templateanswers 409 while any hotel is on the plan —list_plan_template_clientslists them; move them to another plan first.
Calling conventions
Same tool, three transports — pick whichever your runtime already speaks. Always send x-api-key.
# REST
curl -X POST "https://maison-labs.com/api/v1/client/<clientId>/plan/apply" -H "x-api-key: $MAISON_API_KEY" -H "content-type: application/json" -d '{}'// MCP (https://maison-labs.com/mcp, Streamable HTTP): tools/call
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "apply_plan_template", "arguments": {} } }// A2A (https://maison-labs.com/a2a): tasks/send with a data part
{ "jsonrpc": "2.0", "id": 1, "method": "tasks/send", "params": { "message": { "role": "user", "parts": [{ "type": "data", "data": { "tool": "apply_plan_template", "input": {} } }] } } }Errors are the same everywhere: 401 no/invalid key; 403 forbidden with details.missing (the grants you lack — fall back to the composite's parts or stop); 403 not_entitled (the hotel's plan lacks the feature); 404, 409, 413 too_large, 503. Inputs that fail validation return 400 invalid_input with the Zod issues — fix and retry once.