# MCP Server Validators # Tools, prompts, resources, capabilities, and sampling validation let constraints = import "../constraints/constraints.toml" in let common = import "./common-validator.ncl" in let string_val = import "./string-validator.ncl" in { # Validate max concurrent tool executions ValidMaxConcurrentTools = fun count => common.ValidRange constraints.mcp_server.tools.max_concurrent.min constraints.mcp_server.tools.max_concurrent.max count, # Validate tool execution timeout in milliseconds ValidToolTimeout = fun timeout => common.ValidRange constraints.mcp_server.tools.timeout.min constraints.mcp_server.tools.timeout.max timeout, # Validate max resource size in bytes ValidMaxResourceSize = fun size => common.ValidRange constraints.mcp_server.resources.max_size.min constraints.mcp_server.resources.max_size.max size, # Validate resource cache TTL in seconds ValidResourceCacheTtl = fun ttl => common.ValidRange constraints.mcp_server.resources.cache_ttl.min constraints.mcp_server.resources.cache_ttl.max ttl, # Validate max custom prompt templates ValidMaxPromptTemplates = fun count => common.ValidRange constraints.mcp_server.prompts.max_templates.min constraints.mcp_server.prompts.max_templates.max count, # Validate max tokens for sampling ValidMaxSamplingTokens = fun tokens => common.ValidRange constraints.mcp_server.sampling.max_tokens.min constraints.mcp_server.sampling.max_tokens.max tokens, # Validate temperature value (0.0-2.0 typical range) ValidTemperature = fun temperature => if temperature < 0.0 then std.contract.blame_with_message "Temperature must be >= 0.0" temperature else if temperature > 2.0 then std.contract.blame_with_message "Temperature must be <= 2.0" temperature else temperature, # Validate tool name ValidToolName = fun name => string_val.ValidIdentifier name, # Validate prompt template name ValidPromptTemplateName = fun name => string_val.ValidIdentifier name, # Validate resource type ValidResourceType = fun resource_type => string_val.ValidCategoryName resource_type, # Validate tool category ValidToolCategory = fun category => string_val.ValidCategoryName category, # Validate protocol version ValidProtocolVersion = fun version => if version == "" then std.contract.blame_with_message "Protocol version cannot be empty" version else if !std.string.matches "^[0-9]+(\\.[0-9]+)*$" version then std.contract.blame_with_message "Protocol version must be semantic version (e.g., 1.0, 2.1.3)" version else version, # Validate tool definition completeness ValidToolDefinition = fun tool => if tool.name == null || tool.name == "" then std.contract.blame_with_message "Tool must have a non-empty name" tool else if tool.description == null || tool.description == "" then std.contract.blame_with_message "Tool must have a non-empty description" tool else tool, # Validate prompt template structure ValidPromptTemplate = fun prompt => if prompt.name == null || prompt.name == "" then std.contract.blame_with_message "Prompt must have a non-empty name" prompt else prompt, # Validate resource path ValidResourcePath = fun path => string_val.ValidFilesystemPath path, # Validate MCP capabilities configuration ValidCapabilitiesConfig = fun capabilities => if !capabilities.tools.enabled && !capabilities.prompts.enabled && !capabilities.resources.enabled then std.contract.blame_with_message "At least one capability (tools, prompts, or resources) must be enabled" capabilities else capabilities, # Validate template engine ValidTemplateEngine = fun engine => let valid_engines = ['jinja2, 'tera, 'handlebars] in common.ValidEnum valid_engines engine, # Validate sampling model identifier ValidSamplingModel = fun model => string_val.ValidIdentifier model, }