provisioning/schemas/platform/validators/mcp-server-validator.ncl

127 lines
4.0 KiB
Plaintext
Raw Normal View History

# 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,
}