Files
herolib/examples/mcp/inspector/server.vsh
2025-10-12 12:30:19 +03:00

187 lines
4.6 KiB
GLSL
Executable File

#!/usr/bin/env -S v -n -w -cg -d use_openssl -d json_no_inline_sumtypes -enable-globals run
import incubaid.herolib.mcp
import incubaid.herolib.mcp.transport
import incubaid.herolib.schemas.jsonrpc
import incubaid.herolib.schemas.jsonschema
import x.json2
import os
// Example custom tool handler function
fn my_custom_handler(arguments map[string]json2.Any) !mcp.ToolCallResult {
return mcp.ToolCallResult{
is_error: false
content: [
mcp.ToolContent{
typ: 'text'
text: 'Hello from custom handler! Arguments: ${arguments}'
},
]
}
}
// Example of calculating 2 numbers
fn calculate(arguments map[string]json2.Any) !mcp.ToolCallResult {
// Check if num1 exists and can be converted to a number
if 'num1' !in arguments {
return mcp.ToolCallResult{
is_error: true
content: [
mcp.ToolContent{
typ: 'text'
text: 'Missing num1 parameter'
},
]
}
}
// Try to get num1 as a number (JSON numbers can be int, i64, or f64)
num1 := arguments['num1'].f64()
// Check if num2 exists and can be converted to a number
if 'num2' !in arguments {
return mcp.ToolCallResult{
is_error: true
content: [
mcp.ToolContent{
typ: 'text'
text: 'Missing num2 parameter'
},
]
}
}
// Try to get num2 as a number
num2 := arguments['num2'].f64()
// Calculate the result
result := num1 + num2
// Return the result
return mcp.ToolCallResult{
is_error: false
content: [
mcp.ToolContent{
typ: 'text'
text: 'Result: ${result} (${num1} + ${num2})'
},
]
}
}
// Parse command line arguments
fn parse_args() (transport.TransportMode, int) {
args := os.args[1..]
mut mode := transport.TransportMode.stdio
mut port := 8080
for i, arg in args {
match arg {
'--http' {
mode = .http
}
'--port' {
if i + 1 < args.len {
port = args[i + 1].int()
}
}
else {}
}
}
return mode, port
}
fn main() {
// Parse command line arguments
mode, port := parse_args()
// Create a backend with custom tools and handlers
backend := mcp.MemoryBackend{
tools: {
'custom_method': mcp.Tool{
name: 'custom_method'
description: 'A custom example tool'
input_schema: jsonschema.Schema{
typ: 'object'
properties: {
'message': jsonschema.SchemaRef(jsonschema.Schema{
typ: 'string'
description: 'A message to process'
})
}
required: ['message']
}
}
'calculate': mcp.Tool{
name: 'calculate'
description: 'Calculates the sum of two numbers'
input_schema: jsonschema.Schema{
typ: 'object'
properties: {
'num1': jsonschema.SchemaRef(jsonschema.Schema{
typ: 'number'
description: 'The first number'
})
'num2': jsonschema.SchemaRef(jsonschema.Schema{
typ: 'number'
description: 'The second number'
})
}
required: ['num1', 'num2']
}
}
}
tool_handlers: {
'custom_method': my_custom_handler
'calculate': calculate
}
}
// Create transport configuration
transport_config := transport.TransportConfig{
mode: mode
http: transport.HttpConfig{
port: port
protocol: .both // Support both JSON-RPC and REST
}
}
// Create and start the server
mut server := mcp.new_server(backend, mcp.ServerParams{
config: mcp.ServerConfiguration{
server_info: mcp.ServerInfo{
name: 'inspector_example'
version: '1.0.0'
}
}
transport: transport_config
})!
if mode == .http {
println('🚀 MCP Inspector Server - HTTP Mode')
println('===================================')
println('')
println('📡 Server running on: http://localhost:${port}')
println('')
println('🔗 Endpoints:')
println(' Health: http://localhost:${port}/health')
println(' JSON-RPC: http://localhost:${port}/jsonrpc')
println(' Tools: http://localhost:${port}/api/tools')
println('')
println('🧪 Test Commands:')
println(' curl http://localhost:${port}/health')
println(' curl http://localhost:${port}/api/tools')
println(' curl -X POST http://localhost:${port}/api/tools/calculate/call -H "Content-Type: application/json" -d \'{"num1":10,"num2":5}\'')
println('')
println('🔌 MCP Inspector Integration:')
println(' Use JSON-RPC endpoint: http://localhost:${port}/jsonrpc')
println('')
} else {
// In STDIO mode, we should be completely silent to avoid interfering with JSON-RPC communication
// The MCP Inspector captures both stdout and stderr, so any output can cause parsing errors
// If you need to see startup messages, run with --http mode instead
}
server.start()!
}