Skip to content

Commit 4cde499

Browse files
committed
feat: better tool doc
1 parent fc8be7d commit 4cde499

5 files changed

Lines changed: 90 additions & 27 deletions

File tree

CLAUDE.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,11 @@ Note: keep these tools available, but do not treat them as the default entry poi
7474
- `explore_external_endpoint` - Explore classes/counts of an external SPARQL endpoint
7575

7676
**Local Ontology (Group K):**
77-
- `inspect_local_ontology` - Load and summarize a local TTL/OWL/NT/JSON-LD file (classes, properties, namespaces, triple count)
78-
- `query_local_ontology` - Execute SPARQL SELECT against a local ontology file
79-
- `compare_local_with_remote` - Compare local classes/properties against schema.gov.it to find matches and gaps
77+
- `inspect_local_ontology` - Load and summarize an ontology from a server-local path, inline RDF content, or `upload_id`
78+
- `query_local_ontology` - Execute SPARQL SELECT against an ontology reachable by the server or previously uploaded via HTTP
79+
- `compare_local_with_remote` - Compare classes/properties from a server-local or uploaded ontology against schema.gov.it
80+
81+
Remote HTTP note: `file_path` always refers to the MCP server filesystem. If the file lives on the client machine, use `POST /upload` and pass the returned `upload_id` instead of retrying local path variants.
8082

8183
**Meta:**
8284
- `suggest_new_tools` - Analyze usage logs to suggest new specialized tools

README.md

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ Nota: questi tool restano utili, ma su `schema.gov.it` sono spesso secondari. Il
6565
* `explore_external_endpoint`: Esplora la struttura di un endpoint esterno (classi e conteggi).
6666

6767
### 10. Ontologia Locale
68-
* `inspect_local_ontology`: Carica e riassume un file RDF/OWL locale (TTL, OWL, NT, JSON-LD) — classi, proprietà, namespace, conteggio triple. Il file viene cachato in memoria dopo il primo caricamento.
69-
* `query_local_ontology`: Esegue una query SPARQL SELECT su un file locale. Prefissi standard iniettati automaticamente. Risultati compressi come gli altri tool.
70-
* `compare_local_with_remote`: Confronta le classi/proprietà definite localmente con quelle presenti in schema.gov.it — utile per scoprire cosa riusare o allineare.
68+
* `inspect_local_ontology`: Carica e riassume un'ontologia RDF/OWL disponibile al server via `file_path`, contenuto inline o `upload_id`. Attenzione: `file_path` indica sempre un path leggibile dal server MCP, non dal laptop dell'utente.
69+
* `query_local_ontology`: Esegue una query SPARQL SELECT su un'ontologia accessibile dal server o caricata prima via `POST /upload`. Prefissi standard iniettati automaticamente. Risultati compressi come gli altri tool.
70+
* `compare_local_with_remote`: Confronta le classi/proprietà definite in un'ontologia accessibile dal server o via `upload_id` con quelle presenti in schema.gov.it — utile per scoprire cosa riusare o allineare.
7171

7272
### 11. Workflow Upload HTTP
73-
* `query_uploaded_store`: Esegue query SPARQL SELECT su uno store temporaneo creato via `POST /upload`, utile in modalità HTTP.
73+
* `query_uploaded_store`: Esegue query SPARQL SELECT su uno store temporaneo creato via `POST /upload`. In modalità HTTP/remota è spesso il flusso corretto quando il file sta sulla macchina client e non sul filesystem del server.
7474

7575
### 12. Meta-Ottimizzazione
7676
* `suggest_new_tools`: Analizza i log delle query RAW e suggerisce nuovi tool specializzati in base all'utilizzo reale.
@@ -198,6 +198,8 @@ In `.vscode/mcp.json`:
198198

199199
Adatta per ambienti condivisi, CI/CD o deployment remoto. Il server deve essere già in esecuzione (es. via Docker Compose).
200200

201+
Importante: in questa modalità `file_path` si riferisce al filesystem del server/container. Se il file RDF sta sul computer del client, il flusso corretto è `POST /upload` e poi uso di `upload_id`.
202+
201203
#### Claude Code
202204

203205
```bash
@@ -232,6 +234,41 @@ In `.vscode/mcp.json`:
232234
}
233235
```
234236

237+
#### Upload di un file locale verso un server remoto
238+
239+
Quando il server gira altrove e non può leggere il file locale del client, evita di provare percorsi diversi. Carica il file una volta e riusa l'`id` restituito.
240+
241+
Questo punto è importante anche per i costi e l'affidabilità: non usare la conversazione con il modello come canale di trasporto del file, e non incollare ontologie grandi nel prompt. Il file va inviato dal client con un tool locale che spedisca i byte direttamente al server, per esempio `curl`, `nc` o un helper equivalente del client MCP.
242+
243+
Con `curl`:
244+
245+
```bash
246+
curl -X POST \
247+
-H "Content-Type: text/turtle" \
248+
--data-binary @./mia-ontologia.ttl \
249+
http://localhost:3000/upload
250+
```
251+
252+
Risposta tipica:
253+
254+
```json
255+
{"id":"9d7...","tripleCount":1234,"format":"text/turtle","endpoint":"/sparql/9d7..."}
256+
```
257+
258+
Poi usa quell'`id` come `upload_id` con `inspect_local_ontology`, `query_local_ontology` o `compare_local_with_remote`, oppure interroga direttamente lo store:
259+
260+
```bash
261+
curl --get \
262+
--data-urlencode 'query=SELECT ?c WHERE { ?c a <http://www.w3.org/2002/07/owl#Class> } LIMIT 10' \
263+
http://localhost:3000/sparql/9d7...
264+
```
265+
266+
Con `nc`:
267+
268+
```bash
269+
{ printf 'POST /upload HTTP/1.1\r\nHost: localhost:3000\r\nContent-Type: text/turtle\r\nContent-Length: %s\r\n\r\n' "$(wc -c < ./mia-ontologia.ttl)"; cat ./mia-ontologia.ttl; } | nc localhost 3000
270+
```
271+
235272
---
236273

237274
## Esempi di Utilizzo
@@ -246,9 +283,9 @@ Una volta configurato, puoi chiedere all'agente cose come:
246283
* *"Trova i comuni della Lombardia e il loro codice Belfiore."* (Userà `list_municipalities`)
247284
* *"Consigliami alcuni endpoint SPARQL esterni da interrogare dopo schema.gov.it."* (Userà `recommend_external_endpoints`)
248285
* *"Esegui una query SPARQL su DBpedia per trovare le città italiane."* (Userà `query_external_endpoint`)
249-
* *"Dammi una panoramica dell'ontologia in `/home/user/mia-ontologia.ttl`."* (Userà `inspect_local_ontology`)
250-
* *"Quali classi della mia ontologia esistono già in schema.gov.it?"* (Userà `compare_local_with_remote`)
251-
* *"Trova tutte le classi senza rdfs:label nel file locale."* (Userà `query_local_ontology`)
286+
* *"Dammi una panoramica dell'ontologia in `/srv/ontologie/mia-ontologia.ttl`."* (Userà `inspect_local_ontology` con `file_path`, se il file è davvero leggibile dal server)
287+
* *"Ho un server MCP remoto e un file TTL sul mio laptop: caricalo via `POST /upload` e poi confronta le classi con schema.gov.it."* (Userà `upload_id` + `compare_local_with_remote`)
288+
* *"Trova tutte le classi senza rdfs:label nel file che ho appena caricato via upload."* (Userà `query_local_ontology` con `upload_id`)
252289
* *"Esistono vocabolari internazionali nel settore pubblico che potremmo allineare a schema.gov.it?"* (Userà `search_okg_resources`)
253290
* *"La classe Person di CPV ha equivalenti riconosciuti a livello internazionale?"* (Userà `find_okg_alignments`)
254291
* *"Quali tool open source posso usare per lavorare con SKOS e OWL?"* (Userà `find_semantic_software`)
@@ -262,8 +299,8 @@ Una volta configurato, puoi chiedere all'agente cose come:
262299
* **Prefixes Automatici**: Non serve definire `rdf:`, `owl:`, `skos:`, ecc. nelle query interne. Il server li aggiunge automaticamente. Per gli endpoint esterni i prefissi non vengono iniettati di default.
263300
* **Compressione Token**: Le liste lunghe (> 5 item) vengono restituite in formato tabellare compatto per risparmiare token.
264301
* **Input Sanitizzati**: Tutti i parametri utente sono sanitizzati per prevenire SPARQL injection.
265-
* **Ontologia Locale**: I tool del gruppo 10 (`inspect_local_ontology`, `query_local_ontology`, `compare_local_with_remote`) usano [oxigraph](https://github.com/oxigraph/oxigraph) (WASM) per caricare file RDF/OWL locali in memoria ed eseguire SPARQL. I file vengono cachati dopo il primo caricamento; le query successive sullo stesso file non rileggono il disco. Formati supportati: `.ttl`, `.owl`, `.rdf`, `.nt`, `.jsonld`.
266-
* **Workflow Upload HTTP**: Il tool del gruppo 11 (`query_uploaded_store`) permette di interrogare via SPARQL uno store temporaneo creato via `POST /upload`, con scadenza automatica dopo un'ora.
302+
* **Ontologia Locale**: I tool del gruppo 10 (`inspect_local_ontology`, `query_local_ontology`, `compare_local_with_remote`) usano [oxigraph](https://github.com/oxigraph/oxigraph) (WASM) per caricare file RDF/OWL in memoria ed eseguire SPARQL. `file_path` funziona solo per file davvero leggibili dal processo server; non trasferisce file dal client. I file vengono cachati dopo il primo caricamento; le query successive sullo stesso file non rileggono il disco. Formati supportati: `.ttl`, `.owl`, `.rdf`, `.nt`, `.jsonld`.
303+
* **Workflow Upload HTTP**: Il tool del gruppo 11 (`query_uploaded_store`) permette di interrogare via SPARQL uno store temporaneo creato via `POST /upload`, con scadenza automatica dopo un'ora. In modalità HTTP/SSE remota questo è il fallback consigliato quando il file non è accessibile via `file_path`.
267304
* **Open Knowledge Graphs (OKG)**: I tool del gruppo 13 chiamano `api.openknowledgegraphs.com` (REST JSON, CC0, nessuna autenticazione, timeout 10s). Le categorie tematiche vengono scaricate dinamicamente dalla root dell'API (`GET /`) al primo utilizzo e messe in cache in memoria per la durata della sessione; non è più necessario aggiornarle manualmente nel codice. Il tool `compare_coverage_with_okg` combina una chiamata OKG con una query SPARQL su schema.gov.it usando i Wikidata ID come chiave di collegamento.
268305
* **Logging**: Tutte le chiamate vengono loggate in `logs/usage_log.jsonl` per analisi e miglioramento continuo. Ogni entry include argomenti, riepilogo, `source_data_metrics` e `ai_data_metrics`: metriche quantitative dei dati ricevuti e del payload finale passato al modello, ad esempio numero di caratteri e, quando rilevabile, righe, colonne o numero di elementi.
269306
* **Trasporto**: Il server supporta sia `stdio` (default, per uso locale) che HTTP/SSE (via `MCP_TRANSPORT=sse`, per uso remoto/Docker).

src/local-ontology.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -330,13 +330,13 @@ export async function resolveLocalStore(
330330
throw new Error("Provide exactly one of: file_path, content, or upload_id.");
331331
}
332332
if (provided === 0) {
333-
throw new Error("Provide one of: file_path (local server), content (remote server), or upload_id (HTTP upload).");
333+
throw new Error("Provide one of: file_path (server-local file), content (inline RDF for small payloads), or upload_id (recommended for remote HTTP servers).");
334334
}
335335

336336
if (uploadId) {
337337
const entry = uploadedStores.get(uploadId);
338338
if (!entry) {
339-
throw new Error(`Upload store '${uploadId}' not found or expired. Upload a file first via POST /upload (stores expire after 1 hour).`);
339+
throw new Error(`Upload store '${uploadId}' not found or expired. Upload the file first via POST /upload (preferred when the file is on the client machine and the MCP server is remote). Stores expire after 1 hour.`);
340340
}
341341
return { store: entry.store, tripleCount: entry.tripleCount, format: entry.format, source: `upload:${uploadId}` };
342342
}
@@ -350,7 +350,7 @@ export async function resolveLocalStore(
350350
if (content!.length > MAX_INLINE_CONTENT_SIZE) {
351351
throw new Error(
352352
`Content length (${content!.length} chars) exceeds the ${MAX_INLINE_CONTENT_SIZE}-character limit. ` +
353-
`Use file_path instead for large ontologies.`
353+
`Use upload_id instead for large ontologies on remote servers, or file_path only when the server can read the file directly.`
354354
);
355355
}
356356
const fmt = format ?? "text/turtle";

src/tools/group-k.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@ server.registerTool(
1414
"inspect_local_ontology",
1515
{
1616
title: "Inspect Local Ontology",
17-
description: `Load and summarize a local RDF/OWL ontology file (TTL, OWL/RDF-XML, NT, JSON-LD, Graphol XML).
17+
description: `Load and summarize an RDF/OWL ontology from the server filesystem, inline content, or an uploaded HTTP store (TTL, OWL/RDF-XML, NT, JSON-LD, Graphol XML).
1818
1919
**Input (provide exactly one):**
20-
- file_path: Absolute path on the server filesystem — use when running locally or via Docker with a mounted volume
21-
- content + format: Raw RDF text — use when the server is remote (HTTP mode); the client reads the file and sends its content inline (max 1 MB)
22-
- upload_id: UUID returned by POST /upload — use when the file was already uploaded via HTTP
20+
- file_path: Absolute path on the MCP server filesystem. Use this only when the server process can really read that path (local stdio, same machine, or Docker with that directory mounted).
21+
- content + format: Raw RDF text sent inline. Works in remote HTTP mode too, but only for small payloads (max 1 MB).
22+
- upload_id: UUID returned by POST /upload. This is the preferred remote workflow when the ontology file is on the client machine instead of the server.
23+
24+
**Important for remote MCP servers:**
25+
- Do not assume file_path points to the user's laptop or local workstation.
26+
- If the MCP server runs on another machine/container and cannot access the file directly, upload it first with POST /upload, then call this tool with upload_id.
27+
- Prefer upload_id over trying many path variants when access to the original file is uncertain.
28+
- Do not paste large ontology files into the chat or spend model tokens to relay them. Send the bytes with a local client-side tool such as curl, nc, or an equivalent upload helper.
2329
2430
**format values:** "text/turtle" (default), "application/rdf+xml", "application/n-triples", "application/ld+json", "application/graphol+xml"
2531
@@ -95,14 +101,19 @@ server.registerTool(
95101
"query_local_ontology",
96102
{
97103
title: "Query Local Ontology",
98-
description: `Execute a SPARQL SELECT query against a local RDF/OWL ontology file.
104+
description: `Execute a SPARQL SELECT query against an ontology available on the server filesystem or through HTTP upload.
99105
100106
**Args (provide exactly one of file_path or upload_id):**
101-
- file_path: Absolute path to the ontology file (local/Docker)
102-
- upload_id: UUID returned by POST /upload (HTTP mode)
107+
- file_path: Absolute path on the MCP server filesystem. Use only if the server can really read that path.
108+
- upload_id: UUID returned by POST /upload. Use this in HTTP/remote mode when the file is local to the client, not the server.
103109
- query: SPARQL SELECT query
104110
- inject_prefixes: Inject standard prefixes (rdf, rdfs, owl, skos, dct…) — default true
105111
112+
**Important for remote MCP servers:**
113+
- If a direct file path is not accessible from the server, do not keep retrying with alternative local paths.
114+
- Upload the file with POST /upload and call this tool with upload_id.
115+
- Do not use the model conversation as a transport layer for the ontology body. Use a local upload tool to send the file directly to the server.
116+
106117
**Returns:**
107118
- Compressed SPARQL results (tabular for >5 rows, compact for ≤5 rows)
108119
@@ -137,14 +148,19 @@ server.registerTool(
137148
"compare_local_with_remote",
138149
{
139150
title: "Compare Local Ontology with schema.gov.it",
140-
description: `Compare classes and/or properties defined in a local ontology file against schema.gov.it.
151+
description: `Compare classes and/or properties defined in an ontology available on the server filesystem or through HTTP upload against schema.gov.it.
141152
142153
**Args (provide exactly one of file_path or upload_id):**
143-
- file_path: Absolute path to the local ontology file (local/Docker)
144-
- upload_id: UUID returned by POST /upload (HTTP mode)
154+
- file_path: Absolute path on the MCP server filesystem. Use only if the server can really read that path.
155+
- upload_id: UUID returned by POST /upload. Use this in HTTP/remote mode when the ontology file is not present on the server.
145156
- type: What to compare — "classes" | "properties" | "all" (default: "classes")
146157
- limit: Max local items to check (default: 50)
147158
159+
**Important for remote MCP servers:**
160+
- file_path is not a transport mechanism. It works only for files visible to the server process.
161+
- If the ontology sits on the client machine, upload it first and pass upload_id.
162+
- Do not waste tokens by copying the ontology text into the conversation when a local upload tool can send the file directly.
163+
148164
**Returns:**
149165
- matched: URIs found in both local file and schema.gov.it (with Italian label if available)
150166
- local_only: URIs defined locally but absent from schema.gov.it

src/tools/group-l.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,24 @@ server.registerTool(
1717
description: `Execute a SPARQL SELECT query against a temporary ontology store created via HTTP upload.
1818
1919
**Workflow (HTTP mode only):**
20-
1. Upload a local RDF file: \`POST /upload\` with raw RDF body and correct Content-Type (max 1 MB)
20+
1. Upload the RDF file to the MCP server with \`POST /upload\` and the raw RDF body (max 1 MB)
2121
2. Response: \`{"id": "<uuid>", "tripleCount": N, "endpoint": "/sparql/<uuid>"}\`
2222
3. Use the \`id\` here to run SPARQL queries, OR pass it as \`upload_id\` to \`inspect_local_ontology\`, \`query_local_ontology\`, \`compare_local_with_remote\`
2323
24+
**When to use this workflow:**
25+
- The MCP server is remote, containerized, or otherwise cannot read the user's local filesystem.
26+
- A previous \`file_path\` attempt failed because the path only exists on the client machine.
27+
- You need a predictable remote-safe path instead of guessing how to forward local files.
28+
- You want the client to send the raw file bytes directly, instead of consuming model tokens by pasting the ontology into the prompt.
29+
2430
**Supported Content-Types for upload:** text/turtle, application/rdf+xml, application/n-triples, application/ld+json, application/graphol+xml
2531
2632
**Notes:**
2733
- Uploaded stores are kept for 1 hour then evicted
2834
- Standard prefixes (rdf/rdfs/owl/skos/dct/xsd/dcat/foaf/clv/cpv/l0/sm) are auto-injected
29-
- The same store is also queryable directly via \`GET /sparql/<id>?query=...\``,
35+
- The same store is also queryable directly via \`GET /sparql/<id>?query=...\`
36+
- For remote files, this is usually the right fallback instead of retrying \`file_path\` with many local path variants
37+
- Prefer a local upload command or helper over copying RDF text through the model conversation`,
3038
inputSchema: {
3139
id: z.string().describe("Upload UUID returned by POST /upload"),
3240
query: z.string().describe("SPARQL SELECT query to execute against the uploaded store"),

0 commit comments

Comments
 (0)