Class: McpProcessor

Inherits:
Object
  • Object
show all
Includes:
RpcErrorHelpers
Defined in:
lib/stack-service-base/mcp_processor.rb

Constant Summary collapse

PROTOCOL_VERSION =
'2025-06-18'
ParseError =
Class.new(StandardError) do
  attr_reader :body, :status

  def initialize(body:, status:)
    @body = body
    @status = status
    super("MCP parse error")
  end
end

Instance Method Summary collapse

Methods included from RpcErrorHelpers

#rpc_error!

Constructor Details

#initialize(logger: LOGGER) ⇒ McpProcessor

Returns a new instance of McpProcessor.



30
31
32
# File 'lib/stack-service-base/mcp_processor.rb', line 30

def initialize(logger: LOGGER)
  @logger = logger
end

Instance Method Details

#error_response(id:, code:, message:) ⇒ Object



54
55
56
# File 'lib/stack-service-base/mcp_processor.rb', line 54

def error_response(id:, code:, message:)
  json_rpc_response(id: id) { rpc_error!(code, message) }
end

#handle(method:, params:, body:) ⇒ Object



62
63
64
65
66
67
68
69
70
71
# File 'lib/stack-service-base/mcp_processor.rb', line 62

def handle(method:, params:, body: )
  case method
  when "tools/list"  then list_tools
  when "tools/call"  then call_tool(params || {})
  when "initialize"  then initialize_(body)
  when "initialized" then {}
  else
    rpc_error!(-32601, "Unknown method #{method}")
  end
end

#initialize_(body) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/stack-service-base/mcp_processor.rb', line 75

def initialize_(body)
  body[:serverInfo] = {
    name: 'mcp-server',
    title: 'MCP Server',
    version: '1.0.0'
  }
  # result
  {
    protocolVersion: PROTOCOL_VERSION,
    capabilities: {
      logging: {},
      prompts: { listChanged: false },
      resources: { listChanged: false },
      tools: { listChanged: false }
    }
  }
end

#list_toolsObject



46
47
48
# File 'lib/stack-service-base/mcp_processor.rb', line 46

def list_tools
  { tools: ToolRegistry.list, nextCursor: nil }
end

#root_endpointObject



34
35
36
# File 'lib/stack-service-base/mcp_processor.rb', line 34

def root_endpoint
  root_response
end

#root_responseObject



50
51
52
# File 'lib/stack-service-base/mcp_processor.rb', line 50

def root_response
  json_rpc_response(id: nil) { list_tools }
end

#rpc_endpoint(raw_body) ⇒ Object



38
39
40
41
42
43
44
# File 'lib/stack-service-base/mcp_processor.rb', line 38

def rpc_endpoint(raw_body)
  req = JSON.parse(raw_body.to_s)
  rpc_response(id: req["id"], method: req["method"], params: req["params"])
rescue JSON::ParserError
  body = error_response(id: nil, code: -32700, message: "Parse error")
  raise ParseError.new(body: body, status: 400)
end

#rpc_response(id:, method:, params:) ⇒ Object



58
59
60
# File 'lib/stack-service-base/mcp_processor.rb', line 58

def rpc_response(id:, method:, params:)
  json_rpc_response(id: id) { |body| handle(method: method, params: params, body: body) }
end