Files
herolib/lib/ai/mcp/handler_resources.v
Mahmoud-Emad 10ce2ca1cd refactor: introduce mcpcore and clean up STDIO transport
- Extract core MCP logic into a new `mcpcore` module
- Remove logging that interferes with JSON-RPC over STDIO
- Improve server loop to parse requests before handling
- Add stub for `logging/setLevel` JSON-RPC method
- Refactor vcode server into a dedicated logic submodule
2025-09-15 11:59:24 +03:00

183 lines
5.1 KiB
V

module mcp
import json
import freeflowuniverse.herolib.schemas.jsonrpc
pub struct Resource {
pub:
uri string
name string
description string
mimetype string @[json: 'mimeType']
}
// Resource List Handler
pub struct ResourceListParams {
pub:
cursor string
}
pub struct ResourceListResult {
pub:
resources []Resource
next_cursor string @[json: 'nextCursor']
}
// resources_list_handler handles the resources/list request
// This request is used to retrieve a list of available resources
fn (mut s Server) resources_list_handler(data string) !string {
// Decode the request with cursor parameter
request := jsonrpc.decode_request_generic[ResourceListParams](data)!
cursor := request.params.cursor
// TODO: Implement pagination logic using the cursor
// For now, return all resources
// Create a success response with the result
response := jsonrpc.new_response_generic[ResourceListResult](request.id, ResourceListResult{
resources: s.backend.resource_list()!
next_cursor: '' // Empty if no more pages
})
return response.encode()
}
// Resource Read Handler
pub struct ResourceReadParams {
pub:
uri string
}
pub struct ResourceReadResult {
pub:
contents []ResourceContent
}
pub struct ResourceContent {
pub:
uri string
mimetype string @[json: 'mimeType']
text string
blob string // Base64-encoded binary data
}
// resources_read_handler handles the resources/read request
// This request is used to retrieve the contents of a resource
fn (mut s Server) resources_read_handler(data string) !string {
// Decode the request with uri parameter
request := jsonrpc.decode_request_generic[ResourceReadParams](data)!
if !s.backend.resource_exists(request.params.uri)! {
return jsonrpc.new_error_response(request.id, resource_not_found(request.params.uri)).encode()
}
// Get the resource contents by URI
resource_contents := s.backend.resource_contents_get(request.params.uri)!
// Create a success response with the result
response := jsonrpc.new_response_generic[ResourceReadResult](request.id, ResourceReadResult{
contents: resource_contents
})
return response.encode()
}
// Resource Templates Handler
pub struct ResourceTemplatesListResult {
pub:
resource_templates []ResourceTemplate @[json: 'resourceTemplates']
}
pub struct ResourceTemplate {
pub:
uri_template string @[json: 'uriTemplate']
name string
description string
mimetype string @[json: 'mimeType']
}
// resources_templates_list_handler handles the resources/templates/list request
// This request is used to retrieve a list of available resource templates
fn (mut s Server) resources_templates_list_handler(data string) !string {
// Decode the request
request := jsonrpc.decode_request(data)!
// Create a success response with the result
response := jsonrpc.new_response_generic[ResourceTemplatesListResult](request.id,
ResourceTemplatesListResult{
resource_templates: s.backend.resource_templates_list()!
})
return response.encode()
}
// Resource Subscription Handler
pub struct ResourceSubscribeParams {
pub:
uri string
}
pub struct ResourceSubscribeResult {
pub:
subscribed bool
}
// resources_subscribe_handler handles the resources/subscribe request
// This request is used to subscribe to changes for a specific resource
fn (mut s Server) resources_subscribe_handler(data string) !string {
request := jsonrpc.decode_request_generic[ResourceSubscribeParams](data)!
if !s.backend.resource_exists(request.params.uri)! {
return jsonrpc.new_error_response(request.id, resource_not_found(request.params.uri)).encode()
}
s.backend.resource_subscribe(request.params.uri)!
response := jsonrpc.new_response_generic[ResourceSubscribeResult](request.id, ResourceSubscribeResult{
subscribed: true
})
return response.encode()
}
// Resource Notification Handlers
// send_resources_list_changed_notification sends a notification when the list of resources changes
pub fn (mut s Server) send_resources_list_changed_notification() ! {
// Check if the client supports this notification
if !s.client_config.capabilities.roots.list_changed {
return
}
// Create a notification
notification := jsonrpc.new_blank_notification('notifications/resources/list_changed')
s.send(json.encode(notification))
// Send the notification to all connected clients
// In a real implementation, this would use a WebSocket or other transport
// Note: Removed log.info() as it interferes with STDIO transport JSON-RPC communication
}
pub struct ResourceUpdatedParams {
pub:
uri string
}
// send_resource_updated_notification sends a notification when a subscribed resource is updated
pub fn (mut s Server) send_resource_updated_notification(uri string) ! {
// Check if the client is subscribed to this resource
if !s.backend.resource_subscribed(uri)! {
return
}
// Create a notification
notification := jsonrpc.new_notification[ResourceUpdatedParams]('notifications/resources/updated',
ResourceUpdatedParams{
uri: uri
})
s.send(json.encode(notification))
// Send the notification to all connected clients
// In a real implementation, this would use a WebSocket or other transport
// Note: Removed log.info() as it interferes with STDIO transport JSON-RPC communication
}