feat: comprehensive audio system and MCP server implementation
Audio System Enhancements: - Complete PipeWire configuration with WirePlumber session management - AI-powered noise suppression using RNNoise plugin - GUI applications: EasyEffects, pavucontrol, Helvum, qpwgraph, pwvucontrol - Pre-configured audio presets for microphone noise suppression - Desktop integration with auto-start and helper scripts - Validation tools and interactive audio management utilities - Real-time audio processing with RTKit optimization - Cross-application compatibility (Discord, Zoom, OBS, etc.) MCP (Model Context Protocol) Implementation in Guile Scheme: - Modular MCP server architecture with clean separation of concerns - JSON-RPC transport layer with WebSocket and stdio support - Protocol compliance with MCP specification - Comprehensive error handling and validation - Router system for tool and resource management - Integration layer for NixOS Home Lab management - Full test suite with unit and integration tests - Documentation and usage examples Technical Details: - Removed conflicting ALSA udev rules while maintaining compatibility - Fixed package dependencies and service configurations - Successfully deployed and tested on congenital-optimist machine - Functional programming approach using Guile Scheme modules - Type-safe protocol implementation with validation - Async/await pattern support for concurrent operations This represents a significant enhancement to the Home Lab infrastructure, providing both professional-grade audio capabilities and a robust MCP server implementation for AI assistant integration.
This commit is contained in:
parent
7c44a7822b
commit
52a9d544fc
22 changed files with 3802 additions and 11 deletions
228
packages/mcp-server/mcp/server/jsonrpc.scm
Normal file
228
packages/mcp-server/mcp/server/jsonrpc.scm
Normal file
|
@ -0,0 +1,228 @@
|
|||
;; JSON-RPC 2.0 Protocol Implementation for MCP
|
||||
;; This module implements the foundational JSON-RPC 2.0 protocol handling
|
||||
;; as required by the Model Context Protocol (MCP) specification.
|
||||
|
||||
(define-module (mcp server jsonrpc)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (ice-9 receive)
|
||||
#:use-module (json)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-9)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:export (make-jsonrpc-request
|
||||
make-jsonrpc-response
|
||||
make-jsonrpc-error
|
||||
make-jsonrpc-notification
|
||||
parse-jsonrpc-message
|
||||
validate-jsonrpc-message
|
||||
jsonrpc-request?
|
||||
jsonrpc-response?
|
||||
jsonrpc-notification?
|
||||
jsonrpc-error?
|
||||
jsonrpc-request-id
|
||||
jsonrpc-request-method
|
||||
jsonrpc-request-params
|
||||
jsonrpc-response-id
|
||||
jsonrpc-response-result
|
||||
jsonrpc-error-code
|
||||
jsonrpc-error-message
|
||||
jsonrpc-error-data
|
||||
jsonrpc-error-id
|
||||
jsonrpc-notification-method
|
||||
jsonrpc-notification-params
|
||||
handle-jsonrpc-batch
|
||||
jsonrpc-message->json
|
||||
*jsonrpc-error-codes*))
|
||||
|
||||
;; JSON-RPC 2.0 Error Codes
|
||||
(define *jsonrpc-error-codes*
|
||||
'((parse-error . -32700)
|
||||
(invalid-request . -32600)
|
||||
(method-not-found . -32601)
|
||||
(invalid-params . -32602)
|
||||
(internal-error . -32603)
|
||||
(server-error-start . -32099)
|
||||
(server-error-end . -32000)))
|
||||
|
||||
;; Record types for JSON-RPC messages
|
||||
(define-record-type <jsonrpc-request>
|
||||
(make-jsonrpc-request id method params)
|
||||
jsonrpc-request?
|
||||
(id jsonrpc-request-id)
|
||||
(method jsonrpc-request-method)
|
||||
(params jsonrpc-request-params))
|
||||
|
||||
(define-record-type <jsonrpc-response>
|
||||
(make-jsonrpc-response id result)
|
||||
jsonrpc-response?
|
||||
(id jsonrpc-response-id)
|
||||
(result jsonrpc-response-result))
|
||||
|
||||
(define-record-type <jsonrpc-error>
|
||||
(make-jsonrpc-error id code message data)
|
||||
jsonrpc-error?
|
||||
(id jsonrpc-error-id)
|
||||
(code jsonrpc-error-code)
|
||||
(message jsonrpc-error-message)
|
||||
(data jsonrpc-error-data))
|
||||
|
||||
(define-record-type <jsonrpc-notification>
|
||||
(make-jsonrpc-notification method params)
|
||||
jsonrpc-notification?
|
||||
(method jsonrpc-notification-method)
|
||||
(params jsonrpc-notification-params))
|
||||
|
||||
;; Validation functions
|
||||
(define (valid-jsonrpc-version? version)
|
||||
"Check if the JSON-RPC version is valid (must be '2.0')"
|
||||
(and (string? version) (string=? version "2.0")))
|
||||
|
||||
(define (valid-method-name? method)
|
||||
"Check if the method name is valid (string, not starting with 'rpc.')"
|
||||
(and (string? method)
|
||||
(not (string-prefix? "rpc." method))))
|
||||
|
||||
(define (valid-id? id)
|
||||
"Check if the ID is valid (string, number, or null)"
|
||||
(or (string? id)
|
||||
(number? id)
|
||||
(null? id)))
|
||||
|
||||
;; Message parsing and validation
|
||||
(define (parse-jsonrpc-message json-string)
|
||||
"Parse a JSON-RPC message from a JSON string"
|
||||
(catch 'json-invalid
|
||||
(lambda ()
|
||||
(let ((parsed (json-string->scm json-string)))
|
||||
(validate-and-create-message parsed)))
|
||||
(lambda (key . args)
|
||||
(make-jsonrpc-error #f
|
||||
(assoc-ref *jsonrpc-error-codes* 'parse-error)
|
||||
"Parse error"
|
||||
#f))))
|
||||
|
||||
(define (validate-jsonrpc-message message)
|
||||
"Validate a parsed JSON-RPC message structure"
|
||||
(cond
|
||||
((not (list? message))
|
||||
(make-jsonrpc-error #f
|
||||
(assoc-ref *jsonrpc-error-codes* 'invalid-request)
|
||||
"Invalid Request: message must be an object"
|
||||
#f))
|
||||
((not (valid-jsonrpc-version? (assoc-ref message "jsonrpc")))
|
||||
(make-jsonrpc-error (assoc-ref message "id")
|
||||
(assoc-ref *jsonrpc-error-codes* 'invalid-request)
|
||||
"Invalid Request: jsonrpc version must be '2.0'"
|
||||
#f))
|
||||
(else #t)))
|
||||
|
||||
(define (validate-and-create-message parsed)
|
||||
"Validate and create appropriate message type from parsed JSON"
|
||||
(let ((validation-result (validate-jsonrpc-message parsed)))
|
||||
(if (jsonrpc-error? validation-result)
|
||||
validation-result
|
||||
(create-message-from-parsed parsed))))
|
||||
|
||||
(define (create-message-from-parsed parsed)
|
||||
"Create appropriate message type from validated parsed JSON"
|
||||
(let ((method (assoc-ref parsed "method"))
|
||||
(id (assoc-ref parsed "id"))
|
||||
(params (assoc-ref parsed "params"))
|
||||
(result (assoc-ref parsed "result"))
|
||||
(error (assoc-ref parsed "error")))
|
||||
(cond
|
||||
;; Response with result
|
||||
((and (not method) result (not error))
|
||||
(if (not id)
|
||||
(make-jsonrpc-error #f
|
||||
(assoc-ref *jsonrpc-error-codes* 'invalid-request)
|
||||
"Invalid Request: response must have id"
|
||||
#f)
|
||||
(make-jsonrpc-response id result)))
|
||||
|
||||
;; Error response
|
||||
((and (not method) (not result) error)
|
||||
(if (not id)
|
||||
(make-jsonrpc-error #f
|
||||
(assoc-ref *jsonrpc-error-codes* 'invalid-request)
|
||||
"Invalid Request: error response must have id"
|
||||
#f)
|
||||
(let ((error-code (assoc-ref error "code"))
|
||||
(error-message (assoc-ref error "message"))
|
||||
(error-data (assoc-ref error "data")))
|
||||
(make-jsonrpc-error id error-code error-message error-data))))
|
||||
|
||||
;; Request or notification
|
||||
((and method (string? method))
|
||||
(if (not (valid-method-name? method))
|
||||
(make-jsonrpc-error id
|
||||
(assoc-ref *jsonrpc-error-codes* 'invalid-request)
|
||||
"Invalid Request: invalid method name"
|
||||
#f)
|
||||
(if (not id)
|
||||
;; Notification (no id)
|
||||
(make-jsonrpc-notification method params)
|
||||
;; Request (has id)
|
||||
(if (not (valid-id? id))
|
||||
(make-jsonrpc-error id
|
||||
(assoc-ref *jsonrpc-error-codes* 'invalid-request)
|
||||
"Invalid Request: invalid id"
|
||||
#f)
|
||||
(make-jsonrpc-request id method params)))))
|
||||
|
||||
;; Invalid message
|
||||
(else
|
||||
(make-jsonrpc-error id
|
||||
(assoc-ref *jsonrpc-error-codes* 'invalid-request)
|
||||
"Invalid Request: message structure is invalid"
|
||||
#f)))))
|
||||
|
||||
;; Batch request handling
|
||||
(define (handle-jsonrpc-batch messages)
|
||||
"Handle a batch of JSON-RPC messages"
|
||||
(if (and (list? messages) (not (null? messages)))
|
||||
(map parse-jsonrpc-message messages)
|
||||
(list (make-jsonrpc-error #f
|
||||
(assoc-ref *jsonrpc-error-codes* 'invalid-request)
|
||||
"Invalid Request: batch must be non-empty array"
|
||||
#f))))
|
||||
|
||||
;; Message serialization helpers
|
||||
(define (jsonrpc-message->json message)
|
||||
"Convert a JSON-RPC message to JSON string"
|
||||
(cond
|
||||
((jsonrpc-request? message)
|
||||
(scm->json-string
|
||||
`(("jsonrpc" . "2.0")
|
||||
("id" . ,(jsonrpc-request-id message))
|
||||
("method" . ,(jsonrpc-request-method message))
|
||||
,@(if (jsonrpc-request-params message)
|
||||
`(("params" . ,(jsonrpc-request-params message)))
|
||||
'()))))
|
||||
|
||||
((jsonrpc-response? message)
|
||||
(scm->json-string
|
||||
`(("jsonrpc" . "2.0")
|
||||
("id" . ,(jsonrpc-response-id message))
|
||||
("result" . ,(jsonrpc-response-result message)))))
|
||||
|
||||
((jsonrpc-error? message)
|
||||
(scm->json-string
|
||||
`(("jsonrpc" . "2.0")
|
||||
("id" . ,(jsonrpc-error-id message))
|
||||
("error" . (("code" . ,(jsonrpc-error-code message))
|
||||
("message" . ,(jsonrpc-error-message message))
|
||||
,@(if (jsonrpc-error-data message)
|
||||
`(("data" . ,(jsonrpc-error-data message)))
|
||||
'()))))))
|
||||
|
||||
((jsonrpc-notification? message)
|
||||
(scm->json-string
|
||||
`(("jsonrpc" . "2.0")
|
||||
("method" . ,(jsonrpc-notification-method message))
|
||||
,@(if (jsonrpc-notification-params message)
|
||||
`(("params" . ,(jsonrpc-notification-params message)))
|
||||
'()))))
|
||||
|
||||
(else
|
||||
(throw 'invalid-message "Unknown message type" message))))
|
Loading…
Add table
Add a link
Reference in a new issue