Partelisto MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Partelisto MCPWhat arrivals are coming in this week?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Partelisto MCP
SES.HOSPEDAJES and guest check-in for Spanish vacation rentals, exposed to AI agents.
A remote MCP server that lets Claude, ChatGPT, or any MCP-compatible AI agent answer operational questions about a signed-in host's Spanish accommodation — which arrivals still have an incomplete guest form, which bookings failed SES.HOSPEDAJES (police registration) submission, how close the account is to its plan limit — and, with a separately granted permission, resend a guest's check-in link. It adds no business logic of its own: every tool is a thin wrapper over one query or mutation that already exists on the api-gateway, gated exactly the way the web app is.
Tools: list_properties · list_bookings · get_guest_form_status · list_ses_statuses ·
get_usage_summary · get_attention_required · send_guest_checkin_link · create_booking (the last
two need the extra partelisto:write scope — see the Tools table below for what each one
wraps).
Example prompts: "What needs my attention today?" · "Which of today's arrivals still have an incomplete guest form?" · "Show me bookings where SES.HOSPEDAJES submission failed." · "Create a booking for Casa Sol, 12–15 September, guest Ana García." · "Resend the check-in link for booking X."
No guest PII (email, phone, passport/DNI, date of birth, nationality, document content) is ever selected or returned by any tool — see Tools (v1) below.
Claude / ChatGPT / Copilot
│ MCP over HTTP, Bearer token from Keycloak OAuth
▼
partelisto-mcp (this service)
│ same GraphQL call the SPA would make, same Bearer token forwarded as-is
▼
api-gateway → backoffice / booking / guestdocsWhy it deviates from the usual service-structure template
Every other TargetGrps service owns data (MongoDB, tenancy middleware, ApiServiceBootstrapper). This
one doesn't — it has no Domain layer and no database. It's a client of the gateway, not a peer of it.
The project layout keeps Application (DTOs, the fixed GraphQL documents, and the pure
response-shaping/redaction logic) and Infrastructure (the gateway HTTP client) for the same testability
reasons the template exists, but skips Mongo/multitenancy bootstrap because there's nothing to bootstrap.
Related MCP server: Hostaway MCP
Tools (v1)
Tool | Scope | Wraps |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
None of these ever select or return guest email, phone, passport/DNI, date of birth, nationality, or
document content — see GatewayQueries (what's selected) and ResponseShaper (what's mapped into the
DTO). GatewayQueriesTests fails the build if a query is ever widened to select a field that looks like
PII, as a second line of defense.
list_bookings doesn't yet expose BookingsQuery.BookingFilter (propertyId/date range/status) because
its GraphQL input type name is generated by HotChocolate's mutation-conventions and wasn't worth
guessing blind — add it once the gateway schema can be introspected against directly.
Authorization — two independent layers
Scope, checked in this service (
PartelistoTools.RequireScope): the bearer token's JWTscopeclaim must containpartelisto:readfor the five read tools,partelisto:writeadditionally forsend_guest_checkin_link. The token is validated (signature, issuer, expiry) against Keycloak by the standardAddJwtBearerhandler inProgram.cs— this service does real JWT verification, it does not trust an unverified claim. This is what lets an OAuth consent screen offer "read my data" separately from "send email on my behalf."Ownership/tenant, enforced by the api-gateway on every call, same as for the web app: the raw bearer token is forwarded unchanged, and the gateway's
OwnerAccesspolicy decides what data that specific user may see. A validpartelisto:writescope does not by itself grant access to any particular booking — the gateway still checks the caller owns it.
RFC 9728 protected-resource metadata is published at /.well-known/oauth-protected-resource, pointing
authorization_servers at Keycloak's realm and listing both scopes, so a spec-compliant MCP client can
discover how to obtain a token without a human pasting one in.
Keycloak setup (done)
The partelisto realm has a client partelisto-mcp (uuid f5a1cb7f-d6f9-474c-818a-183584dbec30):
public client, standardFlowEnabled (authorization_code + PKCE), consentRequired: true,
directAccessGrantsEnabled: true. Two optional client scopes are assigned and shown on the consent
screen: partelisto:read and partelisto:write (both display.on.consent.screen: true). Two access
token audience mappers are attached to the client — one adding partelisto-mcp (so this service accepts
the token), one adding api-gateway (so the same token, forwarded unchanged, is also accepted by the
gateway; the first mapper alone replaces the audience rather than extending it, which silently broke the
gateway hop — worth remembering if another audience mapper gets added here later).
Registered redirect URIs: https://claude.ai/api/mcp/auth_callback and
https://chatgpt.com/connector_platform_oauth_redirect. Add more (Claude Code's local callback, etc.)
as each client actually gets connected — Keycloak needs the exact URI before that client's OAuth flow
will complete.
Two more fixes were needed, found only by testing against a real signed-in Claude.ai session (browser, not curl) with a real (non-e2e) Partelisto account:
fullScopeAllowedwasfalseon thepartelisto-mcpclient (Keycloak's default for a client created via the Admin API). With it off, the issued token'srealm_access.rolescontained onlyoffline_access— none of the user's actual roles — regardless of what the user actually had. Fixed by setting it totrue(alreadytrueonpartelisto-spa; brings this client in line with that).Missing the
oidc-usermodel-realm-role-mapperprotocol mapper (name "realm roles", claim nameroles) thatpartelisto-spahas directly on the client.TargetGrps.BuildingBlocks.Bootstrapper's JWT setup setsRoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"and never mapsrealm_access.rolesinto that claim type itself (confirmed by decompiling the installed NuGet package — itsOnTokenValidatedhandler only logs claims) — soRequireRole(...)policies likeOwnerAccessfail for any client missing this exact mapper, no matter what roles the user has or whatrealm_accesscontains. Copied verbatim frompartelisto-spa's mapper config ontopartelisto-mcp.
Verified end to end with a real signed-in Claude.ai session, not just curl: added the custom
connector, completed the full browser OAuth + consent flow (both scopes shown and granted separately,
confirming the two-scope design renders correctly), had list_properties fail twice with the two bugs
above, fixed both live, reconnected, and got a real answer back from backoffice through the whole chain
(gateway → backoffice → GraphQL → this service → Claude). This is now the most-verified path in the
whole project — the only thing left unverified is a ChatGPT connection specifically.
Deployed
Live at https://mcp.partelisto.es — k8s/deployment.yaml applied directly (kubectl apply -f k8s/,
not Helm; see that file's header comment for why), image ghcr.io/targetgrps/partelisto-mcp, namespace
targetgrps-microservices. CI (.github/workflows/build-publish.yml) builds, tests, and pushes on
every push to main. Bump the image: tag in k8s/deployment.yaml and re-apply for future releases.
CI is self-contained — it does not call targetgrps/reusable-workflows the way every sibling
service's build-publish.yml does. That repo is private, and this one is deliberately public (see
"Made public" below); a public repository cannot call a reusable workflow in a private one at all —
GitHub rejects it at dispatch time ("workflow was not found"), independent of that repo's access-level
setting. The reusable workflow's other features (npm/nuget client publish, a Mongo image, Slack notify)
don't apply to this service anyway, so a small inline workflow was the right call, not a workaround.
Also needed GH_TOKEN_TARGETGRPS (not secrets.GITHUB_TOKEN) to log in to GHCR — the package was first
pushed with a personal token during initial rollout, so this repo's own Actions identity was never on
its "Manage Actions access" list (a GHCR setting with no REST API to fix remotely).
Two bugs found and fixed only by actually deploying, not by local docker run/docker compose:
dotnet publish --no-build -o /appwas publishing into the same directory the source tree already occupied, which silently drops Content items (appsettings.json). The image had no config at all and crashed on startup withKeycloak:Authority is not configured. Fixed by publishing to/outinstead.request.Schemereadhttpbehind the TLS-terminating ingress, so/.well-known/oauth-protected-resourcereported"resource": "http://mcp.partelisto.es". Fixed withUseForwardedHeaders.
Also hit and fixed as part of this rollout, outside this repo: cert-manager 1.18.2 in this cluster
couldn't issue any new TLS certificate (an upstream bug with ingress-nginx's strict path validation —
cert-manager#7791). Patched by adding
--feature-gates=ACMEHTTP01IngressPathTypeExact=false to the cert-manager Deployment's args in the
cert-manager namespace — the documented workaround, reverting to pre-1.18 behavior. This was blocking
certificate issuance cluster-wide, not just for this service.
Verified live over real HTTPS: /healthz, /.well-known/oauth-protected-resource (correct https://
resource and both scopes listed), and the MCP initialize handshake.
Listed in the official MCP registry
io.github.TargetGrps/partelisto-mcp is live and active at registry.modelcontextprotocol.io — verify
with curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=partelisto-mcp". Published by
.github/workflows/publish-mcp-registry.yml on every push to main that touches server.json, via
GitHub Actions OIDC — no login, no stored token, nobody approves anything by hand. The namespace has to
match the org's exact casing (TargetGrps, not targetgrps) or the registry's OIDC check 403s.
What's NOT done yet (manual follow-ups)
Not submitted to the ChatGPT App directory. Unlike the MCP registry, there's no OIDC/CI path for this — OpenAI's submission flow is a human review process behind a developer-account login: verify the production
/mcpURL, verify the domain, provide reviewer credentials for the OAuth flow, write test cases, submit for a 5-10 business day review (submission guidelines). That needs someone who owns (or will own) the org's OpenAI developer account — logging into or creating one isn't something to automate.Not actually connected from ChatGPT — the redirect URI is registered but nobody has completed ChatGPT's connector-add flow against this server yet, unlike Claude.ai (see the Keycloak section above, verified end to end).
Only Claude.ai's and ChatGPT's redirect URIs are registered on the
partelisto-mcpKeycloak client. Add more as other clients (Copilot, etc.) actually get connected.
Local development
dotnet build # builds src/*.sln
dotnet test # 8 unit tests, ResponseShaper + GatewayQueries PII guard
dotnet run --project src/TargetGrps.Partelisto.Mcp.Api -- --stdio # MCP over stdin/stdout (Glama introspection)
docker compose build targetgrps-partelisto-mcp
docker compose up -d
curl http://localhost:5207/healthz
curl http://localhost:5207/.well-known/oauth-protected-resource
docker compose downappsettings.Development.json points Gateway:BaseUrl at http://localhost:5201 — the api-gateway
port from the workspace compose stack (see the partelisto local-dev-startup notes for how to bring that
up). The Docker Compose file instead uses http://host.docker.internal:5201, since this service's own
container isn't on that stack's docker network.
Manually exercising a tool without going through a real MCP client
tools/list needs no token. tools/call needs an access token minted for the partelisto-mcp client
with partelisto:read/partelisto:write in its scope — a token from partelisto-spa (e.g. copied from
the SPA's dev tools) will not work, RequireScope rejects it. The client has consentRequired: true,
so it won't hand out a token via password grant (no browser to show consent to) unless that's toggled
off in the Keycloak admin console first — fine for one-off local testing, but flip it back afterward.
Available Tools
8 toolscreate_bookingAInspect
Creates a new booking (a check-in workflow) for one of the host's properties. Requires the write permission granted separately during sign-in. Ask the host to confirm the property and dates before calling this. Does not email the guest — call send_guest_checkin_link afterwards if a link should go out now.
| Name | Required | Description | Default |
|---|---|---|---|
| checkIn | Yes | Check-in date, yyyy-MM-dd. | |
| checkOut | Yes | Check-out date, yyyy-MM-dd. | |
| guestName | No | Guest name, optional. | |
| guestEmail | No | Guest email, optional. | |
| guestPhone | No | Guest phone, optional. | |
| propertyId | Yes | The property id, from list_properties. | |
| templateId | No | Check-in template id. Omit if the property has exactly one active (non-archived) template — it is picked automatically; otherwise this is required. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark readOnlyHint=false and destructiveHint=false, but the description adds meaningful behavioral context: the operation requires separately granted write permission, should only be invoked after host confirmation, and will not send an email to the guest. This goes beyond the annotations and helps set expectations for side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three focused sentences with no filler: purpose first, then permission, then confirmation requirement, then the send_guest_checkin_link follow-up. Every sentence earns its place and the most important operational constraints are front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with 7 parameters, no output schema, and sibling send_guest_checkin_link, the description plus a fully documented schema gives an agent everything needed to invoke the tool correctly. It covers permission, confirmation, side effects, and the relevant alternative/follow-up behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents every parameter thoroughly, including the templateId logic. The description adds only general context around property and dates rather than parameter-level detail. A baseline of 3 is appropriate because the schema is doing the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Creates a new booking (a check-in workflow) for one of the host's properties.' It clearly separates this from siblings like send_guest_checkin_link and list_bookings by defining what the tool itself accomplishes. The parenthetical clarifies the domain meaning of 'booking' rather than leaving it ambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit preconditions: write permission is required, and the host should confirm property and dates before calling. It also provides a when-not/what-next rule by stating it does not email the guest and directing the agent to send_guest_checkin_link if a link should go out. This is actionable guidance, not just context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_attention_requiredARead-onlyIdempotentInspect
Scans the signed-in host's most recent bookings (up to 50) and returns only what needs action right now: stays that are imminent or under way where the guest has not completed check-in, and bookings whose SES.HOSPEDAJES submission failed. Empty list means nothing needs attention within the window. No guest PII.
| Name | Required | Description | Default |
|---|---|---|---|
| arrivalWindowDays | No | How many days ahead counts as "imminent" (a negative gap means the stay already started). Defaults to 3. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the description's job is lighter. It still adds meaningful behavioral context: the 50-booking scan window, the signed-in host scope, empty-list semantics, and the explicit 'No guest PII' guarantee. The exact return shape and ordering are not disclosed, but this is not critical for a read-only tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. It front-loads the tool's action and outcome, then compactly lists the criteria and key behavioral facts (empty-list meaning, PII exclusion). Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with one optional parameter and no output schema, the description covers the input semantics, output selection criteria, empty-list behavior, and privacy boundary. The main unstated detail is the exact response structure, but the described behavior is sufficient for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter arrivalWindowDays is fully documented in the schema with a default value and an explanation of the negative-gap meaning, giving a baseline of 3. The description itself does not add further parameter detail, but none is needed given the schema's complete coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it scans the signed-in host's recent bookings and returns only actionable items. It then enumerates the exact inclusion criteria (imminent/in-progress stays with no guest check-in, and failed SES.HOSPEDAJES submissions), which clearly distinguishes it from list_bookings and status-related siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly communicates when this tool is appropriate: it is for surfacing only items that need immediate action, and an empty list means nothing requires attention. However, it does not explicitly mention alternatives such as list_bookings for full booking history or get_guest_form_status for individual form status, so the exclusion guidance is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_guest_form_statusARead-onlyIdempotentInspect
Whether the guest has completed the check-in form for a booking the host owns (None or Submitted). No form content.
| Name | Required | Description | Default |
|---|---|---|---|
| bookingId | Yes | The booking id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds useful behavioral detail by stating the possible outcomes (None or Submitted) and explicitly clarifying that form content is not returned, which goes beyond the structured metadata.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that front-loads the primary result and includes a scope qualifier and an explicit exclusion ('No form content'). There is no filler or redundant restating of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter, read-only status tool with rich annotations, the description is largely complete: it gives the possible values, the ownership constraint, and what is not included. It does not describe error behavior for non-owned bookings or invalid IDs, but that is a minor gap given the simplicity of the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the bookingId parameter is documented as 'The booking id.' The description adds that the booking must be one the host owns, but it does not provide additional format, constraints, or usage details, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the resource (guest check-in form status), the scope (booking the host owns), and the expected output values (None or Submitted). It lacks an explicit imperative verb like 'Get' or 'Returns', but the tool name plus description make the purpose unambiguous, and 'No form content' helps distinguish it from content-retrieval tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool by scoping it to host-owned bookings and excluding form content. However, it does not explicitly mention alternatives or state when not to use it, such as when the caller is not the host or when form content is needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_usage_summaryARead-onlyIdempotentInspect
The signed-in host's plan tier, trial status, and this month's usage against plan limits (properties, templates, bookings).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds useful behavioral context by specifying that the data is scoped to the signed-in host and reflects the current month's usage, which implies time-dependent data. However, it does not describe response structure, potential absence of plan limits, or any edge behavior such as what happens when the host has no plan.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single compact sentence that front-loads the subject (the signed-in host) and quickly enumerates the three key result categories: plan tier, trial status, and usage against plan limits. Every phrase earns its place; there is no repetition, filler, or schema duplication.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only summary tool, the description is adequately complete. It describes what the response covers and the scope ('signed-in host'), and the annotations cover the operational safety. The absence of an output schema is mitigated by the explicit enumeration of the result content, though a note on the format of usage limits would make it fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters, so parameter disambiguation is unnecessary. The description correctly focuses entirely on the output semantics, which is the appropriate baseline for a parameterless read-only tool. No parameter-related ambiguity exists.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool's purpose: retrieving the signed-in host's plan tier, trial status, and current usage against plan limits. It names the specific resource (usage summary) and the data domains (properties, templates, bookings), which distinguishes it from sibling listing tools. It lacks an explicit verb like 'retrieves' or 'gets', but the tool name and content specification make the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives such as list_bookings or list_properties. It implies it is for account-level usage/limit checking, but does not state explicit conditions, exclusions, or comparison with sibling tools. An agent would need to infer from the tool name that this is for plan usage rather than operational data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_bookingsARead-onlyIdempotentInspect
Lists the signed-in host's bookings (newest first), paged. Returns id, property id, check-in/check-out dates, status, and whether a check-in link and guest contact exist — never the guest's email, phone, or documents.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Rows to skip, for paging. Defaults to 0. | |
| take | No | Rows to return, max 50. Defaults to 20. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description adds valuable behavioral context: results are newest first, paged, and explicitly never include guest email, phone, or documents. This privacy guarantee is important for an agent deciding whether this tool fits a request.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences cover scope, ordering, paging, return fields, and exclusions. Every phrase carries information, and the core action is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with a fully documented schema and safety annotations, the description is complete. It explains what is returned, what is never returned, and the paging behavior, so an agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully documents skip and take, including defaults and max value, so the baseline is 3. The description only adds that results are paged, which reinforces the schema without adding new parameter-level detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists the signed-in host's bookings, with explicit ordering and paging. It distinguishes itself from sibling resources like list_properties and send_guest_checkin_link by naming the exact resource and scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes clear this is for retrieving the signed-in host's bookings and that results are paginated. It does not explicitly state when to avoid this tool or prefer a sibling, but the resource and scope are specific enough for an agent to select it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_propertiesARead-onlyIdempotentInspect
Lists the signed-in host's properties: id, name, address, municipality/province, and whether it is archived. No guest data.
| Name | Required | Description | Default |
|---|---|---|---|
| includeArchived | No | Include archived properties. Defaults to false. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds meaningful context about scope (signed-in host) and data boundaries, without contradicting annotations. Minor gaps like ordering or pagination are not critical for this simple read-only list.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence that states the operation, scope, and returned fields without wasted words. The 'No guest data' exclusion is concise and valuable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only listing tool with one optional parameter, the description is complete: it names the resource, scope, included fields, and exclusion. The output schema is absent, but the description enumerates the return fields sufficiently, and annotations cover behavioral safety.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema fully documents the single optional includeArchived parameter with its default and meaning, so the description does not need to add parameter details. The description adds no extra parameter-level semantics, but the high schema coverage keeps this at baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Lists') and resource ('signed-in host's properties') and enumerates the returned fields. It also draws a clear boundary with 'No guest data,' distinguishing it from guest-related sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly establishes when to use the tool: to list the signed-in host's properties. The explicit 'No guest data' note provides a useful when-not signal, though it does not name alternative sibling tools for guest-specific operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_ses_statusesARead-onlyIdempotentInspect
SES.HOSPEDAJES (police registration) submission status for a set of bookings the host owns: status, attempts, last error, and the official reference once accepted. Bookings with no submission yet are omitted.
| Name | Required | Description | Default |
|---|---|---|---|
| bookingIds | Yes | Booking ids to check, up to 50. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only and idempotent behavior. The description adds non-obvious behavioral context: bookings without a submission are omitted, and the response includes attempts, last error, and official reference once accepted. This goes beyond what the annotations and schema provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The description front-loads the domain and purpose, then adds the important omission caveat. Every sentence contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter, read-only tool with no output schema, the description covers purpose, scope, returned fields, and the omission behavior. It does not specify response formatting or possible status values, but an agent has enough information to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter is fully documented in the schema ('Booking ids to check, up to 50'), so the baseline applies. The description reinforces that the ids refer to host-owned bookings, but adds no additional syntax or constraints beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (SES.HOSPEDAJES police-registration submissions) and the action (checking status for host-owned bookings), and lists the returned fields. It is clearly distinct from list_bookings, but it does not explicitly differentiate from the sibling get_guest_form_status, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The use case is implied—check SES submission status for a set of bookings the host owns—and the host-ownership scope is stated. However, there is no explicit when-to-use guidance, no mention of alternatives, and no condition distinguishing it from get_guest_form_status.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_guest_checkin_linkAInspect
Sends (or resends) the guest check-in link by email for a booking the host owns. This is a real action with a side effect: it emails the guest and, on resend, invalidates the guest's previous link. Requires the write permission granted separately during sign-in. Ask the host to confirm before calling this.
| Name | Required | Description | Default |
|---|---|---|---|
| No | Guest email to send to. Omit to use the email already on the booking. | ||
| bookingId | Yes | The booking id. | |
| guestName | No | Guest name, for the email greeting. Omit to keep the name already on the booking. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses concrete side effects: 'it emails the guest and, on resend, invalidates the guest's previous link.' It also adds the write-permission and host-confirmation requirements, giving the agent a strong behavioral model.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences front-load the core action and side effect, then add permission and confirmation guidance. Each sentence earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating tool with no output schema, the description covers the essential pre-invocation context: side effect, link invalidation, required permission, and the need for host confirmation. The schema handles parameter details, and siblings are plainly different read-only tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage with clear descriptions for bookingId, email, and guestName. The description does not add parameter-specific meaning beyond what the schema already provides, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the specific action: 'Sends (or resends) the guest check-in link by email for a booking the host owns.' This clearly identifies a verb and resource and is easy to distinguish from the sibling get/list tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear usage context: the tool requires write permission and the agent should 'Ask the host to confirm before calling this.' It does not explicitly name alternative tools or say when not to use it, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.1.0- First observed
create_booking - First observed
get_attention_required - First observed
get_guest_form_status - First observed
get_usage_summary - First observed
list_bookings - First observed
list_properties - First observed
list_ses_statuses - First observed
send_guest_checkin_link
TDQS
Scored across 8 tools
Each tool targets a distinct resource or action: usage/plan, bookings, guest link sending, police registration status, guest form status, and properties. Aggregating tools like get_attention_required clearly complement rather than duplicate the individual status-checking tools.
All tool names use lowercase snake_case with a consistent verb-first pattern: get_, list_, create_, send_. The naming is uniform and predictable, making it easy to infer each tool's purpose from its name alone.
Eight tools is well-scoped for a check-in workflow MCP server. Each tool covers a meaningful operation without redundancy, and the count feels neither thin nor bloated.
The core workflow is well covered: create a booking, send a check-in link, check guest form completion, check police registration status, and get an attention-required summary. Minor gaps exist around booking updates/cancellations and property management, but these appear outside the server's stated focus.
Maintenance
Related MCP Connectors
- HAVNOAuthapp.havnre
Read-only AI access to HAVN properties, leads, tasks, files, media, and analytics.
Manage your Hostex vacation rentals—properties, reservations, availability, listings, and guest me…
Read-only property facts, indicative availability, authorised booking links and guest-safe support.
AI access to Hitsteps analytics, live visitors, uptime, goals, alerts, and chats.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to interact with Hostaway's property management platform through standardized MCP tools. Provides access to listings, bookings, guest communication, and availability checking for vacation rental management.-
- AlicenseBqualityBmaintenanceA read-only hospitality-focused MCP server that enables users to retrieve reservation details, listing briefs, and guest conversation contexts from Hostaway. It simplifies hospitality workflows by providing specialized tools for searching threads and viewing reservation data through natural language interfaces.658 npmMIT
- AlicenseAqualityCmaintenanceConnects AI assistants to the Hostaway property management API via 10 read-only tools covering listings, reservations, calendars, guest conversations, and owner statements.10779 npm2MIT
- AlicenseNot gradedqualityFmaintenanceConnects AI agents to RealtyCalendar accounts, allowing users to query bookings, availability, and check-ins via natural language, with local-first privacy and read-only access.MIT