Skip to main content
Glama
juriSacchetta

domustudio-mcp-server

domustudio-mcp-server

CI

An MCP server that exposes the Danea Domustudio public API — condomini, persone, fornitori — as tools an agent can call.

The API is read-only: its entire public surface is three GET endpoints. This server adds no write path, because there is none to add. Domustudio remains the system of record; anything that must change, changes there, by a human, in the product.

Requirements

  • Node.js ≥ 22.12

  • One Domustudio API key per archive (X-DANEA-API-KEY)

Related MCP server: aruba-fatturazione-elettronica-mcp

Install it in another repository

The package is not on any registry — it installs straight from this repository, pinned to a release tag. One global install serves every repository on the machine.

npm install -g --allow-git=all "github:juriSacchetta/Domustudio-mcp#v0.4.0"

--allow-git=all is required on npm 12 and later, which ships allow-git = "none" as a default and otherwise refuses the install with EALLOWGIT. To stop passing it every time:

npm config set allow-git all

npm builds dist/ during install, so the machine needs nothing beyond Node ≥ 22.12 and access to this repository. npm 12 also prints install scripts blocked … (prepare: npm run build) — that warning is benign here: it refers to the consumer's tree, and the build has already run inside npm's isolated step for the git dependency. Confirm the install with:

test -f "$(npm root -g)/domustudio-mcp-server/dist/index.js" && echo installed

Do not run the entry point to "check" it: it is a stdio MCP server with no CLI, so it will start and wait for JSON-RPC on stdin rather than print anything.

A global install puts domustudio-mcp on your PATH, which is the name a shell-launched client needs — confirm with command -v domustudio-mcp. A GUI client is launched without your PATH and needs the absolute path instead:

echo "$(npm root -g)/domustudio-mcp-server/dist/index.js"

See Configure below for both. To upgrade, rerun the install command with a newer tag; every repository on the machine picks it up at once, which is the trade-off of a single global install.

Develop on it here

npm install
npm run build

Configure

The server reads its credentials from the environment, and falls back to a .env file in its working directory for anything the environment does not carry. DOMUSTUDIO_ARCHIVES is a JSON array — one API key addresses exactly one archive, and several archives may coexist.

Claude Code, one project

Add it at the default local scope: Claude Code stores that in ~/.claude.json under the project's path, so the server loads in this project only, stays private to you, and nothing lands in the repository.

claude mcp add domustudio -e DOMUSTUDIO_ARCHIVES='[{"name":"desa","api_key":"..."}]' \
  -- domustudio-mcp

The -- is required: everything after it is the server's own command line. A key passed this way lands in your shell history; to avoid that, drop the -e and put the key in a .env as below — the server finds it either way.

A committed .mcp.json

.mcp.json sits at the project root and is normally checked in, which is how a team shares one server definition — and exactly why the key must not appear in it. Leave the env block out and give each developer their own gitignored .env:

// .mcp.json — committed, no credentials
{
  "mcpServers": {
    "domustudio": { "command": "domustudio-mcp" }
  }
}
# .env at the project root — one per developer, never committed
printf '.env\n' >> .gitignore
printf 'DOMUSTUDIO_ARCHIVES=[{"name":"desa","api_key":"..."}]\n' >> .env
chmod 600 .env

Ignore it before you write it. .mcp.json is committed and .env must not be; nothing in this server can stop a consuming repository from committing one.

Claude Code launches the server with the project root as its working directory, which is where it looks. If your client launches it somewhere else, name the file outright in the .mcp.json entry — DOMUSTUDIO_ENV_FILE is a path, not a secret, so it is safe in a committed file. It has to arrive this way rather than from inside a .env, since it is what picks the file to read:

{ "mcpServers": { "domustudio": {
  "command": "domustudio-mcp",
  "env": { "DOMUSTUDIO_ENV_FILE": "/absolute/path/to/.env" }
} } }

Real environment variables always win over the file. Keep the array on one line, or wrap a multi-line one in single quotes — '[]'.

Claude Desktop and other GUI clients

A GUI client is not launched from a shell and does not inherit your PATH, so the domustudio-mcp bin may not resolve. Give it Node and an absolute path. This file lives in your user profile, outside any repository, so the key may sit in it:

// claude_desktop_config.json — per user, never committed
{
  "mcpServers": {
    "domustudio": {
      "command": "node",
      // output of: echo "$(npm root -g)/domustudio-mcp-server/dist/index.js"
      "args": ["/absolute/path/to/domustudio-mcp-server/dist/index.js"],
      "env": {
        "DOMUSTUDIO_ARCHIVES": "[{\"name\":\"desa\",\"api_key\":\"...\"}]"
      }
    }
  }
}

Why ${DOMUSTUDIO_ARCHIVES} does not work

.mcp.json does expand ${VAR}, but supplying the value through .claude/settings.local.json env did not work: the server never started, and the failure reproduced with a control confirming the variable was present in the session. That is what #4 observed. Why the expansion missed it — an ordering question between settings env and .mcp.json loading — was not established, so treat the recipe as "this does not work", not as a mechanism you can reason around.

The symptom is worth recognising: an unexpanded variable is passed through as the literal text ${DOMUSTUDIO_ARCHIVES}, which is not JSON, so the server exits 1 and the client reports nothing more useful than domustudio (CONNECTION_CLOSED): "Connection closed". From 0.2.0 the server names that literal on stderr instead.

Exporting the variable from a shell rc file does make the expansion work, but it puts the key in a dotfile — no better than committing it. Prefer .env.

Variables

Variable

Required

Default

DOMUSTUDIO_ARCHIVES

yes

DOMUSTUDIO_BASE_URL

no

https://domustudioapi.danea.it/api/external

DOMUSTUDIO_ENV_FILE

no

.env in the working directory; set it empty to skip the lookup. Read from the client's environment only — it chooses the file, so setting it inside one has no effect

DOMUSTUDIO_BASE_URL exists for tests and for pointing at a mock; production should leave it unset. The default is HTTPS even though the OpenAPI servers entry says http://.

The key is never echoed in a tool result: an authentication failure names the archive and the header, not the value. The startup line on stderr names the .env it read, never its contents.

Tools

Tool

What it does

domustudio_list_archivi

Names of the configured archives

domustudio_list_condomini

All condomini; optional local ricerca filter

domustudio_get_condominio

One condominio by id

domustudio_list_persone

Persone, optionally scoped to a condominio; paginated

domustudio_list_fornitori

Fornitori of the whole archive; paginated

All five are annotated readOnlyHint: true, destructiveHint: false.

Every tool takes an optional archivio. With a single archive configured it may be omitted; with several, omitting it returns an error listing the names.

Every tool takes response_format: markdown (default) renders the main fields for reading, json returns the full API record. Integer enums are decoded to { codice, etichetta }.

What the API does not give you

Persone and fornitori have no identifier. Neither schema contains an id, and no endpoint accepts one, so there is no get_persona and no get_fornitore — a person or supplier is reached by filtering a list. The condominio id is the only stable handle the API exposes, and it is what domustudio_list_persone takes as condominio_id.

There is no total count. Responses are bare JSON arrays. ha_altre_pagine is therefore a heuristic — true when the last page read was full — and is documented as such in the tool descriptions.

A page is reported to hold at most 100 records. The API caps PageSize there and says nothing when it does, so dimensione_pagina is refused above that rather than sent and silently truncated. One tutte_le_pagine call therefore reaches 5 000 records — 100 per page, 50 pages. npm run test:live measures the cap against a real archive. See docs/adr/0002.

Development

Command

npm run build

compile to dist/

npm run typecheck

tsc --noEmit

npm run lint

eslint over src and test

npm test

typecheck + full suite

npm run test:unit

suite only, no build

npm run test:live

suite against the real API (see below)

npm run inspector

MCP Inspector against dist/index.js

The suite runs against a local HTTP mock of the Domustudio API and needs no credentials. It covers the client (headers, 1-based paging, retry policy, the truncated-401), configuration and archive resolution, enum decoding, markdown rendering, every tool over an in-memory MCP transport, and the built binary over real stdio.

Running against the real API

Put real credentials in a .env at the repo root — it is gitignored:

printf 'DOMUSTUDIO_ARCHIVES=[{"name":"desa","api_key":"..."}]\n' > .env
chmod 600 .env
npm run test:live

Without DOMUSTUDIO_LIVE=1 those tests skip, so npm test stays green on a machine with no credentials. They only read, and assert on shapes and counts — no record content is printed.

Documentation

Trademarks

Danea and Domustudio are trademarks of their respective owners. This project is an independent client of the Domustudio public API, is not affiliated with or endorsed by them, and is not supported by them.

License

MIT — see LICENSE. Copyright (c) 2026 Juri Sacchetta.

Available Tools

5 tools
domustudio_get_condominioLeggi un condominio per idA
Read-onlyIdempotent

Restituisce il singolo condominio con l'id indicato.

L'API non espone una lettura per id: lo strumento scarica la lista completa dei condomini e seleziona la voce corrispondente.

Args:

  • condominio_id (number): id Domustudio del condominio

  • archivio (string, opzionale): archivio da interrogare

  • response_format ('markdown' | 'json'): default 'markdown'

Restituisce (json): { "archivio": string, "trovato": boolean, "condominio": object | null }

Errori:

  • "trovato": false se nessun condominio ha quell'id nell'archivio indicato.

L'API Domustudio è di sola lettura: espone solo tre endpoint GET. Domustudio resta il sistema di registrazione — ogni correzione va fatta da un operatore dentro il gestionale.

ParametersJSON Schema
NameRequiredDescriptionDefault
archivioNoNome dell'archivio Domustudio da interrogare. Opzionale se ne è configurato uno solo; usare domustudio_list_archivi per l'elenco.
condominio_idYesId Domustudio del condominio (campo 'id').
response_formatNo'markdown' per una sintesi leggibile dei campi principali, 'json' per il record completo.markdown

Output Schema

ParametersJSON Schema
NameRequiredDescription
trovatoYes
archivioYes
condominioYes

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnly/idempotent/non-destructive, and the description adds genuinely new behavioral facts: the API exposes no per-id read so the tool downloads the full list, the exact return shape ({archivio, trovato, condominio}), the not-found failure mode, and that Domustudio remains the system of record so corrections must be made by an operator. This is material context an agent cannot get from annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose and the full-list workaround are front-loaded and earn their place. The trailing paragraph about the Domustudio API being read-only and the system of record is somewhat tangential to this specific tool, and the Args block duplicates the schema, but nothing is egregiously verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read tool with annotations, a full output schema, and 100% parameter coverage, the description supplies the remaining unknowns: the hidden full-list fetch, the trovato:false error case, and the concrete return object. An agent has everything needed to call and interpret it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and all three parameters are documented there (including the archivio cross-reference to domustudio_list_archivi and the response_format enum semantics). The description's Args block restates the same fields with no added syntax, defaults, or edge-case guidance, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Restituisce il singolo condominio con l'id indicato"), which is clearly distinct from the list-style sibling domustudio_list_condomini via the word "singolo". It does not name that sibling explicitly, so an agent must infer the single-vs-list split rather than being told.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains an implementation workaround (no per-id endpoint, so it fetches the whole list and filters) and the single-archivio optionality, which implies usage context. However, it never states when to prefer this over domustudio_list_condomini, nor any exclusion or prerequisite for calling it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

domustudio_list_archiviElenca archivi Domustudio configuratiA
Read-onlyIdempotent

Elenca i nomi degli archivi Domustudio configurati su questo server.

Una chiave API indirizza esattamente un archivio; ogni altro strumento accetta un parametro "archivio" che seleziona quale interrogare. Se ne è configurato uno solo, quel parametro può essere omesso.

Nessun parametro.

Restituisce: { "archivi": string[], // nomi configurati, nell'ordine di configurazione "conteggio": number }

L'API Domustudio è di sola lettura: espone solo tre endpoint GET. Domustudio resta il sistema di registrazione — ogni correzione va fatta da un operatore dentro il gestionale.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
archiviYes
conteggioYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint. The description adds meaningful context beyond them: the backend exposes only three GET endpoints, Domustudio remains the system of record, and corrections must be made by an operator. It does not frame this limitation in terms of what the agent should do instead.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose, then the operational rule, then the return shape. It is somewhat long and the return-value block duplicates the output schema, but each section is purposeful and no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, so explaining return values is optional but harmless. With rich annotations, an empty schema, and clear scoping rules, an agent has everything needed to call this tool correctly and to understand its relationship to the siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so the baseline is 4. The description correctly states 'Nessun parametro,' confirming the empty schema, and adds the cross-tool rule about the 'archivio' parameter expected by sibling tools.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Elenca i nomi degli archivi Domustudio configurati') and clearly distinguishes itself from siblings by explaining that it is the discovery tool for the archive name that every other tool requires. An agent can identify its role without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the selection logic explicitly: one API key maps to one archive, every other tool takes an 'archivio' parameter, and that parameter may be omitted when only one archive exists. This is clear context, though it stops short of an explicit when-not-to-use or a named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

domustudio_list_condominiElenca condominiA
Read-onlyIdempotent

Elenca i condomini presenti in un archivio Domustudio.

L'endpoint restituisce sempre la lista completa: non è paginato e non accetta filtri lato API. Il parametro "ricerca" filtra i risultati localmente su intestazione, città, provincia, indirizzo e codice fiscale.

L'"id" di un condominio è l'unico identificatore stabile esposto dall'API Domustudio, ed è il valore da passare come "condominio_id" a domustudio_list_persone.

Args:

  • archivio (string, opzionale): archivio da interrogare

  • ricerca (string, opzionale): sottostringa, confronto case-insensitive

  • response_format ('markdown' | 'json'): default 'markdown'

Restituisce (json): { "archivio": string, "conteggio": number, "elementi": [ { "id": number, "intestazione": string, "indirizzo": string, "cap": string, "citta": string, "prov": string, "codFisc": string, "amministratore": { "nome": string, "email": string, ... } } ] } In formato markdown vengono mostrati intestazione, id, indirizzo, codice fiscale e amministratore; il formato json riporta il record completo restituito dall'API.

Usare quando: serve l'id di un condominio, o l'anagrafica dello stabile. Non usare per: elencare le persone di un condominio (domustudio_list_persone) o i fornitori (domustudio_list_fornitori).

L'API Domustudio è di sola lettura: espone solo tre endpoint GET. Domustudio resta il sistema di registrazione — ogni correzione va fatta da un operatore dentro il gestionale.

ParametersJSON Schema
NameRequiredDescriptionDefault
ricercaNoFiltro locale su intestazione, città, provincia, indirizzo, codice fiscale.
archivioNoNome dell'archivio Domustudio da interrogare. Opzionale se ne è configurato uno solo; usare domustudio_list_archivi per l'elenco.
response_formatNo'markdown' per una sintesi leggibile dei campi principali, 'json' per il record completo.markdown

Output Schema

ParametersJSON Schema
NameRequiredDescription
ricercaNo
archivioYes
elementiYes
conteggioYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so safety is covered. The description adds genuinely new behavior: the endpoint is never paginated, accepts no API-side filters (the 'ricerca' filter runs locally), the 'id' is the only stable identifier, and Domustudio is the system of record. It restates read-only, which duplicates annotations, but the pagination/filter/identifier disclosures are substantial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and scope, then structured into Args / Restituisce / Usare quando sections. Some redundancy between the prose and the explicit Args/Restituisce blocks, but every block earns its place and none is padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite an output schema already existing, the description explains both markdown and json return shapes and the local-filtering model, which is the non-obvious part an agent needs. Combined with annotations and full schema coverage, an agent has everything required to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the 3 baseline applies, but the description adds meaning beyond the schema: 'ricerca' is a case-insensitive substring, and 'id' is framed as the value to pass as 'condominio_id' elsewhere. Only marginal gains over the well-documented schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Elenca i condomini presenti in un archivio Domustudio') and explicitly distinguishes itself from siblings by naming domustudio_list_persone and domustudio_list_fornitori as out-of-scope. An agent can route correctly without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Has explicit 'Usare quando' (need a condominio id or building registry data) and 'Non usare per' clauses with the alternatives named, plus a concrete handoff rule: use the returned 'id' as 'condominio_id' in domustudio_list_persone. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

domustudio_list_fornitoriElenca fornitoriA
Read-onlyIdempotent

Elenca i fornitori di un archivio Domustudio.

L'anagrafica fornitori è globale sull'archivio, non per condominio: non esiste un parametro che la restringa a uno stabile. Come per le persone, il record non contiene alcun id, quindi non esiste una lettura per id; per trovare un fornitore si filtra questo elenco.

Args:

  • archivio (string, opzionale): archivio da interrogare

  • attivi (boolean, opzionale): solo attivi (true) o solo non attivi (false); omesso, entrambi

  • dati_incompleti (boolean, opzionale): filtra sui fornitori con dati incompleti

  • attivita (string, opzionale): attività del fornitore (parametro Attivita)

  • impianto_servizio_id (number, opzionale): id del servizio collegato (ImpiantoServizioID)

  • esercizi_id (number[], opzionale): esercizi del fornitore (EserciziID)

  • search_query (string, opzionale): passato all'API come SearchQuery, semantica non documentata

  • order_by (string, opzionale): passato all'API come OrderBy, semantica non documentata

  • pagina (number): pagina 1-based, default 1

  • dimensione_pagina (number): elementi per pagina, default 50

  • tutte_le_pagine (boolean): se true scorre le pagine fino a 50, default false

  • response_format ('markdown' | 'json'): default 'markdown'

Restituisce (json): stesso involucro paginato di domustudio_list_persone, con elementi della forma { "descr": string, "fornitoreAttivita": string, "codFisc": string, "piva": string, "iban": string, "email": string[], "pec": string[], "tel1": string, "fornitoreInattivo": boolean, "descStatoDurc": string, "dataScadenzaDurc": string, "f24CodTributo": { "codice": number, "etichetta": string }, ... } "ha_altre_pagine" è un'euristica: l'API non restituisce un totale, quindi è vero quando l'ultima pagina letta era piena.

Usare quando: serve un fornitore per attività, partita IVA, IBAN o stato DURC. Non usare per: i condòmini e i soggetti dell'anagrafica persone (domustudio_list_persone).

L'API Domustudio è di sola lettura: espone solo tre endpoint GET. Domustudio resta il sistema di registrazione — ogni correzione va fatta da un operatore dentro il gestionale.

ParametersJSON Schema
NameRequiredDescriptionDefault
attiviNoStato del fornitore (parametro Attivi).
paginaNoNumero di pagina, 1-based (parametro PageNumber dell'API).
archivioNoNome dell'archivio Domustudio da interrogare. Opzionale se ne è configurato uno solo; usare domustudio_list_archivi per l'elenco.
attivitaNoAttività del fornitore (Attivita).
order_byNoOrdinamento, inoltrato all'API come OrderBy.
esercizi_idNoEsercizi del fornitore (EserciziID).
search_queryNoRicerca libera, inoltrata all'API come SearchQuery.
dati_incompletiNoFornitori con dati incompleti (DatiIncompleti).
response_formatNo'markdown' per una sintesi leggibile dei campi principali, 'json' per il record completo.markdown
tutte_le_pagineNoSe true, scorre le pagine successive fino a esaurimento o fino a 50 pagine (il campo troncato_al_limite_pagine segnala il taglio).
dimensione_paginaNoElementi per pagina (parametro PageSize dell'API). Massimo 100.
impianto_servizio_idNoId del servizio collegato al fornitore (ImpiantoServizioID).

Output Schema

ParametersJSON Schema
NameRequiredDescription
paginaYes
archivioYes
elementiYes
conteggioYes
pagine_letteYes
ha_altre_pagineYes
prossima_paginaNo
dimensione_paginaYes
troncato_al_limite_pagineYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only/idempotent/non-destructive, and the description adds substantial context beyond them: the record has no id so there is no per-record read, 'ha_altre_pagine' is only a heuristic because the API returns no total, and the whole API is read-only with only three GET endpoints while Domustudio remains the system of record (corrections require an operator). That is exactly the kind of behavioral disclosure annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded and sectioned (Args / Restituisce / Usare quando / Non usare), but the Args block largely restates the 100%-covered schema, which is redundant filler. The genuinely additive sentences (no id, pagination heuristic, read-only caveat) are worth their space; the parameter recap is not.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-parameter, zero-required listing tool with an output schema present, the description covers filtering semantics, pagination limits, the return envelope shape, and the system-of-record constraint. An agent has everything needed to call it correctly and to route lookups to it instead of a nonexistent get-by-id.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description earns extra: it spells out omitted=both for 'attivi', flags that hidden 'search_query' and 'order_by' are passed through with undocumented semantics, and caps 'tutte_le_pagine' at 50 pages with a truncation flag. These add meaning beyond the schema without fully re-documenting every field.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Elenca i fornitori di un archivio Domustudio') and immediately scopes it: the anagrafica fornitori is global to the archivio, not per condominio. It explicitly names the sibling it is not ('Non usare per: i condòmini e i soggetti dell'anagrafica persone (domustudio_list_persone)'), so an agent can disambiguate without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use ('serve un fornitore per attività, partita IVA, IBAN o stato DURC') and an explicit when-not-use with the named alternative (domustudio_list_persone). It also states the critical routing fact that there is no read-by-id, so lookup must go through this filtered list.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

domustudio_list_personeElenca persone (anagrafica soggetti)A
Read-onlyIdempotent

Elenca le persone dell'anagrafica Domustudio, opzionalmente ristrette a un condominio.

L'API non espone un identificatore per le persone: il record non contiene alcun id, quindi non esiste una lettura per id e non c'è modo di indirizzare una persona singola. Per trovare qualcuno si filtra questo elenco (search_query, oppure condominio_id più una lettura dei risultati).

Args:

  • archivio (string, opzionale): archivio da interrogare

  • condominio_id (number, opzionale): restringe a un condominio (parametro CondGendID). Ottenerlo da domustudio_list_condomini

  • filtro_subentri (1|2|3|4|5): 1 tutti, 2 attivi, 3 ex, 4 contabilità, 5 destinatari comunicazioni. Default 2

  • esercizio_id (number, opzionale): parametro EsercizioID

  • tags_id (number[], opzionale): parametro TagsID

  • search_query (string, opzionale): passato all'API come SearchQuery; la semantica è decisa dall'API, non documentata nello spec

  • order_by (string, opzionale): passato all'API come OrderBy, semantica non documentata

  • pagina (number): pagina 1-based, default 1

  • dimensione_pagina (number): elementi per pagina, default 50

  • tutte_le_pagine (boolean): se true scorre le pagine fino a 50, default false

  • response_format ('markdown' | 'json'): default 'markdown'

Restituisce (json): { "archivio": string, "conteggio": number, // elementi in questa risposta "pagina": number, // prima pagina letta "dimensione_pagina": number, "pagine_lette": number, "ha_altre_pagine": boolean, // euristica: l'API non restituisce un totale, quindi è vero quando l'ultima pagina era piena "prossima_pagina": number, // presente solo se ha_altre_pagine "troncato_al_limite_pagine": boolean, "elementi": [ { "descr": string, "codFisc": string, "piva": string, "indirizzo": string, "cap": string, "citta": string, "prov": string, "email": string[], "pec": string[], "tel1": string, "note": string, "preferenzaPagamentoRate": { "codice": number, "etichetta": string }, ... } ] } I campi enumerativi sono restituiti come { codice, etichetta }. Il formato markdown mostra denominazione, codice fiscale, indirizzo, recapiti; json riporta il record completo.

Usare quando: servono i condòmini di uno stabile, i recapiti di un soggetto, o un conteggio per condominio. Non usare per: i fornitori, che stanno in un'anagrafica separata (domustudio_list_fornitori).

L'API Domustudio è di sola lettura: espone solo tre endpoint GET. Domustudio resta il sistema di registrazione — ogni correzione va fatta da un operatore dentro il gestionale.

ParametersJSON Schema
NameRequiredDescriptionDefault
paginaNoNumero di pagina, 1-based (parametro PageNumber dell'API).
tags_idNoId dei tag (TagsID).
archivioNoNome dell'archivio Domustudio da interrogare. Opzionale se ne è configurato uno solo; usare domustudio_list_archivi per l'elenco.
order_byNoOrdinamento, inoltrato all'API come OrderBy.
esercizio_idNoId dell'esercizio (EsercizioID).
search_queryNoRicerca libera, inoltrata all'API come SearchQuery.
condominio_idNoId del condominio (CondGendID). Omesso, l'API restituisce le persone di tutto l'archivio.
filtro_subentriNo1 tutti, 2 attivi, 3 ex, 4 contabilità, 5 destinatari comunicazioni
response_formatNo'markdown' per una sintesi leggibile dei campi principali, 'json' per il record completo.markdown
tutte_le_pagineNoSe true, scorre le pagine successive fino a esaurimento o fino a 50 pagine (il campo troncato_al_limite_pagine segnala il taglio).
dimensione_paginaNoElementi per pagina (parametro PageSize dell'API). Massimo 100.

Output Schema

ParametersJSON Schema
NameRequiredDescription
paginaYes
archivioYes
elementiYes
conteggioYes
pagine_letteYes
ha_altre_pagineYes
prossima_paginaNo
dimensione_paginaYes
troncato_al_limite_pagineYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, and the description adds substantial extra context: the whole API is read-only with only three GET endpoints, Domustudio remains system of record so corrections need an operator, and the pagination heuristic (ha_altre_pagine is inferred because the API returns no total) plus the 50-page truncation behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the identifying constraint, then args, return shape, and when/when-not. It is long and the args block partially duplicates a 100%-covered schema, but every section carries useful information and is well ordered.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the 11 optional parameters, the output schema, and the annotations, the description covers everything needed: pagination caveats, truncation, format choices, and the critical absence of per-record ids. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds meaning beyond the schema: it notes search_query and order_by have API-decided, undocumented semantics, and tells the agent to obtain condominio_id from domustudio_list_condomini. It also enumerates filtro_subentri and defaults, though much of that is already in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Elenca le persone dell'anagrafica Domustudio') and immediately clarifies the crucial scope constraint that the API exposes no per-person identifier, so only listing/filtering is possible. It also differentiates from the sibling domustudio_list_fornitori.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit 'Usare quando' (condòmini di uno stabile, recapiti, conteggi per condominio) and 'Non usare per' (fornitori, in a separate registry named as sibling). Also hints at alternatives for finding a single person (filter this list).

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.

  1. 5 tool updatesv0.4.0
    • First observeddomustudio_get_condominio
    • First observeddomustudio_list_archivi
    • First observeddomustudio_list_condomini
    • First observeddomustudio_list_fornitori
    • First observeddomustudio_list_persone

TDQS

A4.5/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct resource: archives, condomini, a single condominio, persone, or fornitori. The descriptions explicitly state when to use each tool and when not to use it, preventing overlap confusion. The only minor redundancy is get_condominio versus list_condomini, but the signature and intent are clearly separated.

Naming Consistency5/5

All tools share the domustudio_ prefix and use consistent snake_case with a verb_noun pattern: list_archivi, list_condomini, get_condominio, list_persone, list_fornitori. There are no mixed conventions or ambiguous verb styles. The naming is entirely predictable.

Tool Count5/5

Five tools is well-scoped for a read-only integration wrapping three GET endpoints plus archive discovery and a convenience single-condominio lookup. Each tool earns its place, with no thin or bloated surface. The count matches the domain perfectly.

Completeness5/5

The Domustudio API is explicitly read-only and exposes only three GET endpoints; the server covers all of them plus archive listing and single-condominio retrieval. Missing update/delete operations are by design, not gaps. Agents have workarounds for person and supplier lookup via filtering, and no obvious read path is absent.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers