Class: Ask::MCP::Server::Stdio

Inherits:
Object
  • Object
show all
Defined in:
lib/ask/mcp/server/stdio.rb

Overview

MCP server over stdio transport.

Reads JSON-RPC 2.0 messages from stdin and writes responses to stdout. Designed to be spawned as a child process by MCP clients (Codex Desktop, Claude Code, etc.) with command/args config.

Usage:

Server::Stdio.new(name: "my-server", tools: my_tools).start

Constant Summary collapse

PROTOCOL_VERSION =
"0.1.0"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, tools: [], capabilities: {}, resources: {}, prompts: {}, debug: false) ⇒ Stdio

Returns a new instance of Stdio.



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/ask/mcp/server/stdio.rb', line 22

def initialize(name:, tools: [], capabilities: {}, resources: {}, prompts: {}, debug: false)
  @name = name
  @capabilities = capabilities
  @resources = resources
  @prompts = prompts
  @debug = debug

  @adapter = Adapters::ToolServer.new(tools || [])
  @initialized = false
  @running = false
end

Instance Attribute Details

#capabilitiesObject (readonly)

Returns the value of attribute capabilities.



20
21
22
# File 'lib/ask/mcp/server/stdio.rb', line 20

def capabilities
  @capabilities
end

#nameObject (readonly)

Returns the value of attribute name.



20
21
22
# File 'lib/ask/mcp/server/stdio.rb', line 20

def name
  @name
end

#promptsObject (readonly)

Returns the value of attribute prompts.



20
21
22
# File 'lib/ask/mcp/server/stdio.rb', line 20

def prompts
  @prompts
end

#resourcesObject (readonly)

Returns the value of attribute resources.



20
21
22
# File 'lib/ask/mcp/server/stdio.rb', line 20

def resources
  @resources
end

#toolsObject (readonly)

Returns the value of attribute tools.



20
21
22
# File 'lib/ask/mcp/server/stdio.rb', line 20

def tools
  @tools
end

Instance Method Details

#running?Boolean

Is the server still running?

Returns:

  • (Boolean)


62
63
64
# File 'lib/ask/mcp/server/stdio.rb', line 62

def running?
  @running
end

#startObject

Start the server (blocking). Processes stdin until EOF.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/ask/mcp/server/stdio.rb', line 35

def start
  @running = true
  $stdout.sync = true

  debug_log "Server starting: #{@name} (PID #{Process.pid})"
  debug_log "Tools: #{@adapter.definitions.map { |d| d[:name] }.join(', ')}"

  while @running && (line = $stdin.gets)
    line = line.strip
    next if line.empty?

    process_line(line)
  end

  debug_log "stdin closed — exiting"
rescue Errno::EBADF, IOError
  # stdin closed externally
ensure
  @running = false
end

#stopObject

Stop the server (non-blocking, closes stdin to unblock the read loop).



57
58
59
# File 'lib/ask/mcp/server/stdio.rb', line 57

def stop
  @running = false
end