@@ -2197,223 +2197,6 @@ server.registerTool(
21972197 return server ;
21982198}
21992199
2200- // =============================================================================
2201- // GROUP J: Linked SPARQL Endpoints
2202- // =============================================================================
2203-
2204- server . registerTool (
2205- "list_linked_endpoints" ,
2206- {
2207- title : "List Linked SPARQL Endpoints" ,
2208- description : `Discover SPARQL endpoints referenced in the schema.gov.it catalog via dcat:DataService.
2209-
2210- **Args:** None
2211-
2212- **Returns:**
2213- - List of data services with endpoint URL, title, description, and conformsTo standard
2214-
2215- **Use when:** Exploring what external SPARQL endpoints are connected to the Italian PA semantic catalog.` ,
2216- inputSchema : { } ,
2217- annotations : {
2218- readOnlyHint : true ,
2219- destructiveHint : false ,
2220- idempotentHint : true ,
2221- openWorldHint : true ,
2222- } ,
2223- } ,
2224- async ( ) => {
2225- const query = `
2226- SELECT ?service ?endpointURL ?title ?description ?conformsTo
2227- WHERE {
2228- ?service a dcat:DataService .
2229- ?service dcat:endpointURL ?endpointURL .
2230- OPTIONAL { ?service dct:title ?title }
2231- OPTIONAL { ?service dct:description ?description }
2232- OPTIONAL { ?service dct:conformsTo ?conformsTo }
2233- }
2234- ` ;
2235- return executeSparqlTool ( "list_linked_endpoints" , { } , query ) ;
2236- }
2237- ) ;
2238-
2239- server . registerTool (
2240- "query_external_endpoint" ,
2241- {
2242- title : "Query External SPARQL Endpoint" ,
2243- description : `Execute a SPARQL query against any public HTTPS SPARQL endpoint.
2244-
2245- **Args:**
2246- - endpointUrl: URL of the target SPARQL endpoint (must be HTTPS)
2247- - query: SPARQL query to execute
2248- - injectPrefixes: Whether to inject schema.gov.it standard prefixes (default: false)
2249-
2250- **Returns:**
2251- - Compressed SPARQL results in the same format as internal tools
2252-
2253- **Security:** Only HTTPS endpoints are allowed. Requests timeout after 15 seconds.
2254-
2255- **Examples:**
2256- - Query DBpedia: endpointUrl="https://dbpedia.org/sparql"
2257- - Query EU Publications Office: endpointUrl="https://publications.europa.eu/webapi/rdf/sparql"` ,
2258- inputSchema : {
2259- endpointUrl : z . string ( ) . describe ( "URL of the target SPARQL endpoint (HTTPS required)" ) ,
2260- query : z . string ( ) . describe ( "SPARQL query to execute" ) ,
2261- injectPrefixes : z . boolean ( ) . optional ( ) . default ( false ) . describe ( "Whether to inject schema.gov.it standard prefixes (rdf, rdfs, owl, skos, dct...)" ) ,
2262- } ,
2263- annotations : {
2264- readOnlyHint : true ,
2265- destructiveHint : false ,
2266- idempotentHint : true ,
2267- openWorldHint : true ,
2268- } ,
2269- } ,
2270- async ( { endpointUrl, query, injectPrefixes } ) => {
2271- return executeTool ( "query_external_endpoint" , { endpointUrl, query, injectPrefixes } , async ( ) => {
2272- const safeEndpoint = sanitizeSparqlUri ( endpointUrl ) ;
2273- const result = await executeSparql ( query , safeEndpoint , injectPrefixes ?? false , 15000 ) ;
2274- const rowCount = result . results ?. bindings ?. length ?? 0 ;
2275- const compressed = compressSparqlResult ( result ) ;
2276- return { success : true , data : compressed , rowCount } ;
2277- } ) ;
2278- }
2279- ) ;
2280-
2281- server . registerTool (
2282- "find_external_alignments" ,
2283- {
2284- title : "Find External Alignments" ,
2285- description : `Find all alignment links from a concept in schema.gov.it toward external resources.
2286-
2287- **Args:**
2288- - uri: URI of the concept in schema.gov.it
2289-
2290- **Returns:**
2291- - concept: The queried URI
2292- - alignments: List of external URIs with relation type and domain (base URL)
2293-
2294- **Alignment types searched:**
2295- - owl:sameAs (bidirectional)
2296- - skos:exactMatch
2297- - skos:closeMatch
2298- - skos:broadMatch
2299- - skos:narrowMatch
2300-
2301- **Use when:** Understanding how a local concept maps to external systems (Eurostat, DBpedia, EU Publications Office, etc.)` ,
2302- inputSchema : {
2303- uri : z . string ( ) . describe ( "URI of the concept in schema.gov.it" ) ,
2304- } ,
2305- annotations : {
2306- readOnlyHint : true ,
2307- destructiveHint : false ,
2308- idempotentHint : true ,
2309- openWorldHint : true ,
2310- } ,
2311- } ,
2312- async ( { uri } ) => {
2313- return executeTool ( "find_external_alignments" , { uri } , async ( ) => {
2314- const safeUri = sanitizeSparqlUri ( uri ) ;
2315- const query = `
2316- SELECT DISTINCT ?target ?relation
2317- WHERE {
2318- {
2319- <${ safeUri } > owl:sameAs ?target .
2320- BIND("owl:sameAs" AS ?relation)
2321- FILTER(isIRI(?target))
2322- } UNION {
2323- ?target owl:sameAs <${ safeUri } > .
2324- BIND("owl:sameAs" AS ?relation)
2325- FILTER(isIRI(?target))
2326- } UNION {
2327- <${ safeUri } > skos:exactMatch ?target .
2328- BIND("skos:exactMatch" AS ?relation)
2329- FILTER(isIRI(?target))
2330- } UNION {
2331- <${ safeUri } > skos:closeMatch ?target .
2332- BIND("skos:closeMatch" AS ?relation)
2333- FILTER(isIRI(?target))
2334- } UNION {
2335- <${ safeUri } > skos:broadMatch ?target .
2336- BIND("skos:broadMatch" AS ?relation)
2337- FILTER(isIRI(?target))
2338- } UNION {
2339- <${ safeUri } > skos:narrowMatch ?target .
2340- BIND("skos:narrowMatch" AS ?relation)
2341- FILTER(isIRI(?target))
2342- }
2343- }
2344- ` ;
2345- const result = await executeSparql ( query ) ;
2346- const bindings = result . results ?. bindings ?? [ ] ;
2347-
2348- const alignments = bindings . map ( b => {
2349- const targetUri = b . target ?. value ?? "" ;
2350- let domain = "" ;
2351- try {
2352- domain = new URL ( targetUri ) . origin ;
2353- } catch {
2354- domain = targetUri ;
2355- }
2356- return {
2357- uri : targetUri ,
2358- relation : b . relation ?. value ?? "" ,
2359- domain,
2360- } ;
2361- } ) ;
2362-
2363- return {
2364- success : true ,
2365- data : { concept : uri , alignments } ,
2366- rowCount : alignments . length ,
2367- } ;
2368- } ) ;
2369- }
2370- ) ;
2371-
2372- server . registerTool (
2373- "explore_external_endpoint" ,
2374- {
2375- title : "Explore External SPARQL Endpoint" ,
2376- description : `Explore the structure of an external SPARQL endpoint: discover its main classes and instance counts.
2377-
2378- **Args:**
2379- - endpointUrl: URL of the SPARQL endpoint to explore (must be HTTPS)
2380- - limit: Maximum number of classes to return (default: 20)
2381-
2382- **Returns:**
2383- - List of classes with instance counts, ordered by count descending
2384-
2385- **Security:** Only HTTPS endpoints are allowed. Requests timeout after 15 seconds.
2386-
2387- **Use when:** Getting a quick overview of what data an external endpoint contains before writing detailed queries.` ,
2388- inputSchema : {
2389- endpointUrl : z . string ( ) . describe ( "URL of the SPARQL endpoint to explore (HTTPS required)" ) ,
2390- limit : z . number ( ) . optional ( ) . default ( 20 ) . describe ( "Maximum number of classes to return" ) ,
2391- } ,
2392- annotations : {
2393- readOnlyHint : true ,
2394- destructiveHint : false ,
2395- idempotentHint : false ,
2396- openWorldHint : true ,
2397- } ,
2398- } ,
2399- async ( { endpointUrl, limit } ) => {
2400- return executeTool ( "explore_external_endpoint" , { endpointUrl, limit } , async ( ) => {
2401- const safeEndpoint = sanitizeSparqlUri ( endpointUrl ) ;
2402- const query = `
2403- SELECT ?class (COUNT(?s) AS ?count)
2404- WHERE { ?s a ?class }
2405- GROUP BY ?class
2406- ORDER BY DESC(?count)
2407- LIMIT ${ limit }
2408- ` ;
2409- const result = await executeSparql ( query , safeEndpoint , false , 15000 ) ;
2410- const rowCount = result . results ?. bindings ?. length ?? 0 ;
2411- const compressed = compressSparqlResult ( result ) ;
2412- return { success : true , data : compressed , rowCount } ;
2413- } ) ;
2414- }
2415- ) ;
2416-
24172200async function main ( ) {
24182201 console . error ( "[Startup] Schema.gov.it MCP Server initializing..." ) ;
24192202 console . error ( "[Startup] Node version:" , process . version ) ;
0 commit comments