feat: implement logging/setLevel and silence STDIO
- Add `logging/setLevel` JSON-RPC method - Define `LogLevel` enum and `SetLevelParams` struct - Silence startup messages in STDIO transport - Suppress console logging during STDIO JSON-RPC errors
This commit is contained in:
Binary file not shown.
@@ -177,11 +177,9 @@ fn main() {
|
||||
println(' Use JSON-RPC endpoint: http://localhost:${port}/jsonrpc')
|
||||
println('')
|
||||
} else {
|
||||
println('📟 MCP Inspector Server - STDIO Mode')
|
||||
println('====================================')
|
||||
println('Ready for JSON-RPC messages on stdin...')
|
||||
println('')
|
||||
println('💡 Tip: Run with --http --port 9000 for HTTP mode')
|
||||
// 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()!
|
||||
|
||||
@@ -87,6 +87,14 @@ fn create_tools_call_wrapper(mut server Server) jsonrpc.ProcedureHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_logging_set_level_wrapper(mut server Server) jsonrpc.ProcedureHandler {
|
||||
return fn [mut server] (request jsonrpc.Request) !jsonrpc.Response {
|
||||
original_json := '{"jsonrpc":"${request.jsonrpc}","method":"${request.method}","params":${request.params},"id":${request.id}}'
|
||||
response_str := server.logging_set_level_handler(original_json)!
|
||||
return jsonrpc.decode_response(response_str)!
|
||||
}
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ServerParams {
|
||||
pub:
|
||||
@@ -122,6 +130,8 @@ pub fn new_server(backend Backend, params ServerParams) !&Server {
|
||||
// Core handlers
|
||||
'initialize': create_initialize_wrapper(mut server)
|
||||
'notifications/initialized': create_initialized_notification_wrapper()
|
||||
// Logging handlers
|
||||
'logging/setLevel': create_logging_set_level_wrapper(mut server)
|
||||
// Resource handlers
|
||||
'resources/list': create_resources_list_wrapper(mut server)
|
||||
'resources/read': create_resources_read_wrapper(mut server)
|
||||
|
||||
37
lib/mcp/handler_logging.v
Normal file
37
lib/mcp/handler_logging.v
Normal file
@@ -0,0 +1,37 @@
|
||||
module mcp
|
||||
|
||||
import x.json2
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc
|
||||
|
||||
// LogLevel represents the logging levels supported by MCP
|
||||
pub enum LogLevel {
|
||||
debug
|
||||
info
|
||||
notice
|
||||
warning
|
||||
error
|
||||
critical
|
||||
alert
|
||||
emergency
|
||||
}
|
||||
|
||||
// SetLevelParams represents the parameters for the logging/setLevel method
|
||||
pub struct SetLevelParams {
|
||||
pub:
|
||||
level LogLevel
|
||||
}
|
||||
|
||||
// logging_set_level_handler handles the logging/setLevel request
|
||||
// This is a stub implementation that accepts the request but doesn't actually change logging behavior
|
||||
fn (mut s Server) logging_set_level_handler(data string) !string {
|
||||
// Decode the request with SetLevelParams
|
||||
request := jsonrpc.decode_request_generic[SetLevelParams](data)!
|
||||
|
||||
// For now, we just acknowledge the request without actually implementing logging level changes
|
||||
// In a full implementation, this would configure the server's logging system
|
||||
|
||||
// Create a success response with empty object (logging/setLevel returns {} on success)
|
||||
empty_map := map[string]string{}
|
||||
response := jsonrpc.new_response_generic[map[string]string](request.id, empty_map)
|
||||
return response.encode()
|
||||
}
|
||||
@@ -17,7 +17,7 @@ pub mut:
|
||||
|
||||
// start starts the MCP server using the configured transport
|
||||
pub fn (mut s Server) start() ! {
|
||||
log.info('Starting MCP server')
|
||||
// Note: Removed log.info() as it interferes with STDIO transport JSON-RPC communication
|
||||
s.transport.start(&s.handler)!
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ pub fn (mut t StdioTransport) start(handler &jsonrpc.Handler) ! {
|
||||
unsafe {
|
||||
t.handler = handler
|
||||
}
|
||||
console.print_debug('Starting MCP server with STDIO transport')
|
||||
// Note: In STDIO mode, we should not print any debug messages to stdout
|
||||
// as it interferes with JSON-RPC communication
|
||||
|
||||
for {
|
||||
// Read a message from stdin
|
||||
@@ -37,23 +38,22 @@ pub fn (mut t StdioTransport) start(handler &jsonrpc.Handler) ! {
|
||||
|
||||
// Parse the JSON-RPC request
|
||||
request := jsonrpc.decode_request(message) or {
|
||||
console.print_stderr('Invalid JSON-RPC request: ${err}')
|
||||
// Note: Removed stderr logging as it can interfere with MCP Inspector
|
||||
// Try to extract the request ID for error response
|
||||
id := jsonrpc.decode_request_id(message) or { 0 }
|
||||
// Create an invalid request error response
|
||||
error_response := jsonrpc.new_error(id, jsonrpc.invalid_request).encode()
|
||||
print(error_response)
|
||||
println(error_response)
|
||||
continue
|
||||
}
|
||||
|
||||
// Handle the message using the JSON-RPC handler
|
||||
response := t.handler.handle(request) or {
|
||||
console.print_stderr('message: ${message}')
|
||||
console.print_stderr('Error handling message: ${err}')
|
||||
// Note: Removed stderr logging as it can interfere with MCP Inspector
|
||||
|
||||
// Create an internal error response
|
||||
error_response := jsonrpc.new_error(request.id, jsonrpc.internal_error).encode()
|
||||
console.print_debug(error_response)
|
||||
println(error_response)
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user