rudof_mcp 0.2.1

RDF data shapes implementation in Rust
Documentation
//! SPARQL query resources.
//!
//! Provides information about supported SPARQL query types
//! and result formats.
//!
//! ## Resources
//!
//! - `rudof://formats/query-types` - Supported SPARQL query types
//! - `rudof://formats/query-results` - Supported query result formats

use rmcp::{
    ErrorData as McpError,
    model::{Annotated, RawResource, ReadResourceResult, ResourceContents},
};
use serde_json::json;

/// Returns the list of SPARQL query-related resources.
pub fn get_query_resources() -> Vec<Annotated<RawResource>> {
    vec![
        Annotated {
            raw: RawResource {
                uri: "rudof://formats/query-types".to_string(),
                name: "Supported SPARQL Query Types".to_string(),
                description: Some("List of supported SPARQL query types".to_string()),
                mime_type: Some("application/json".to_string()),
                title: None,
                size: None,
                icons: None,
                meta: None,
            },
            annotations: None,
        },
        Annotated {
            raw: RawResource {
                uri: "rudof://formats/query-results".to_string(),
                name: "Supported Query Result Formats".to_string(),
                description: Some("List of all supported SPARQL query result formats".to_string()),
                mime_type: Some("application/json".to_string()),
                title: None,
                size: None,
                icons: None,
                meta: None,
            },
            annotations: None,
        },
    ]
}

pub fn handle_query_resource(uri: &str) -> Option<Result<ReadResourceResult, McpError>> {
    match uri {
        "rudof://formats/query-types" => Some(get_query_types(uri)),
        "rudof://formats/query-results" => Some(get_query_result_formats(uri)),
        _ => None,
    }
}

fn get_query_types(uri: &str) -> Result<ReadResourceResult, McpError> {
    let types = json!({
        "query_types": [
            {
                "name": "SELECT",
                "description": "Returns a table of variable bindings",
                "example": "SELECT ?subject ?predicate ?object WHERE { ?subject ?predicate ?object }"
            },
            {
                "name": "CONSTRUCT",
                "description": "Returns an RDF graph constructed by substituting variables",
                "example": "CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }"
            },
            {
                "name": "ASK",
                "description": "Returns a boolean indicating whether a query pattern matches",
                "example": "ASK WHERE { ?s ?p ?o }"
            },
            {
                "name": "DESCRIBE",
                "description": "Returns an RDF graph describing resources",
                "example": "DESCRIBE <http://example.org/resource>"
            }
        ]
    });

    Ok(ReadResourceResult {
        contents: vec![ResourceContents::TextResourceContents {
            uri: uri.to_string(),
            mime_type: Some("application/json".to_string()),
            text: serde_json::to_string_pretty(&types).unwrap(),
            meta: None,
        }],
    })
}

fn get_query_result_formats(uri: &str) -> Result<ReadResourceResult, McpError> {
    let formats = json!({
        "formats": [
            {
                "name": "Internal",
                "value": "internal",
                "description": "Internal format for query results"
            },
            {
                "name": "JSON",
                "value": "json",
                "mime_type": "application/sparql-results+json",
                "extensions": [".srj", ".json"],
                "description": "SPARQL JSON Results format"
            },
            {
                "name": "XML",
                "value": "xml",
                "mime_type": "application/sparql-results+xml",
                "extensions": [".srx", ".xml"],
                "description": "SPARQL XML Results format"
            },
            {
                "name": "CSV",
                "value": "csv",
                "mime_type": "text/csv",
                "extensions": [".csv"],
                "description": "Comma-separated values format"
            },
            {
                "name": "TSV",
                "value": "tsv",
                "mime_type": "text/tab-separated-values",
                "extensions": [".tsv"],
                "description": "Tab-separated values format"
            },
            {
                "name": "Turtle",
                "value": "turtle",
                "mime_type": "text/turtle",
                "extensions": [".ttl"],
                "description": "Terse RDF Triple Language (for CONSTRUCT/DESCRIBE)"
            },
            {
                "name": "N-Triples",
                "value": "ntriples",
                "mime_type": "application/n-triples",
                "extensions": [".nt"],
                "description": "N-Triples format (for CONSTRUCT/DESCRIBE)"
            },
            {
                "name": "RDF/XML",
                "value": "rdfxml",
                "mime_type": "application/rdf+xml",
                "extensions": [".rdf"],
                "description": "RDF/XML format (for CONSTRUCT/DESCRIBE)"
            },
            {
                "name": "TriG",
                "value": "trig",
                "mime_type": "application/trig",
                "description": "Extension of Turtle for named graphs"
            }
        ],
        "default": "internal"
    });

    Ok(ReadResourceResult {
        contents: vec![ResourceContents::TextResourceContents {
            uri: uri.to_string(),
            mime_type: Some("application/json".to_string()),
            text: serde_json::to_string_pretty(&formats).unwrap(),
            meta: None,
        }],
    })
}