robot_lab 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +1 -0
  3. data/.github/workflows/deploy-github-pages.yml +52 -0
  4. data/.github/workflows/deploy-yard-docs.yml +52 -0
  5. data/CHANGELOG.md +55 -0
  6. data/COMMITS.md +196 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +332 -0
  9. data/Rakefile +67 -0
  10. data/docs/api/adapters/anthropic.md +121 -0
  11. data/docs/api/adapters/gemini.md +133 -0
  12. data/docs/api/adapters/index.md +104 -0
  13. data/docs/api/adapters/openai.md +134 -0
  14. data/docs/api/core/index.md +113 -0
  15. data/docs/api/core/memory.md +314 -0
  16. data/docs/api/core/network.md +291 -0
  17. data/docs/api/core/robot.md +273 -0
  18. data/docs/api/core/state.md +273 -0
  19. data/docs/api/core/tool.md +353 -0
  20. data/docs/api/history/active-record-adapter.md +195 -0
  21. data/docs/api/history/config.md +191 -0
  22. data/docs/api/history/index.md +132 -0
  23. data/docs/api/history/thread-manager.md +144 -0
  24. data/docs/api/index.md +82 -0
  25. data/docs/api/mcp/client.md +221 -0
  26. data/docs/api/mcp/index.md +111 -0
  27. data/docs/api/mcp/server.md +225 -0
  28. data/docs/api/mcp/transports.md +264 -0
  29. data/docs/api/messages/index.md +67 -0
  30. data/docs/api/messages/text-message.md +102 -0
  31. data/docs/api/messages/tool-call-message.md +144 -0
  32. data/docs/api/messages/tool-result-message.md +154 -0
  33. data/docs/api/messages/user-message.md +171 -0
  34. data/docs/api/streaming/context.md +174 -0
  35. data/docs/api/streaming/events.md +237 -0
  36. data/docs/api/streaming/index.md +108 -0
  37. data/docs/architecture/core-concepts.md +243 -0
  38. data/docs/architecture/index.md +138 -0
  39. data/docs/architecture/message-flow.md +320 -0
  40. data/docs/architecture/network-orchestration.md +216 -0
  41. data/docs/architecture/robot-execution.md +243 -0
  42. data/docs/architecture/state-management.md +323 -0
  43. data/docs/assets/css/custom.css +56 -0
  44. data/docs/assets/images/robot_lab.jpg +0 -0
  45. data/docs/concepts.md +216 -0
  46. data/docs/examples/basic-chat.md +193 -0
  47. data/docs/examples/index.md +129 -0
  48. data/docs/examples/mcp-server.md +290 -0
  49. data/docs/examples/multi-robot-network.md +312 -0
  50. data/docs/examples/rails-application.md +420 -0
  51. data/docs/examples/tool-usage.md +310 -0
  52. data/docs/getting-started/configuration.md +230 -0
  53. data/docs/getting-started/index.md +56 -0
  54. data/docs/getting-started/installation.md +179 -0
  55. data/docs/getting-started/quick-start.md +203 -0
  56. data/docs/guides/building-robots.md +376 -0
  57. data/docs/guides/creating-networks.md +366 -0
  58. data/docs/guides/history.md +359 -0
  59. data/docs/guides/index.md +68 -0
  60. data/docs/guides/mcp-integration.md +356 -0
  61. data/docs/guides/memory.md +309 -0
  62. data/docs/guides/rails-integration.md +432 -0
  63. data/docs/guides/streaming.md +314 -0
  64. data/docs/guides/using-tools.md +394 -0
  65. data/docs/index.md +160 -0
  66. data/examples/01_simple_robot.rb +38 -0
  67. data/examples/02_tools.rb +106 -0
  68. data/examples/03_network.rb +103 -0
  69. data/examples/04_mcp.rb +219 -0
  70. data/examples/05_streaming.rb +124 -0
  71. data/examples/06_prompt_templates.rb +324 -0
  72. data/examples/07_network_memory.rb +329 -0
  73. data/examples/prompts/assistant/system.txt.erb +2 -0
  74. data/examples/prompts/assistant/user.txt.erb +1 -0
  75. data/examples/prompts/billing/system.txt.erb +7 -0
  76. data/examples/prompts/billing/user.txt.erb +1 -0
  77. data/examples/prompts/classifier/system.txt.erb +4 -0
  78. data/examples/prompts/classifier/user.txt.erb +1 -0
  79. data/examples/prompts/entity_extractor/system.txt.erb +11 -0
  80. data/examples/prompts/entity_extractor/user.txt.erb +3 -0
  81. data/examples/prompts/escalation/system.txt.erb +35 -0
  82. data/examples/prompts/escalation/user.txt.erb +34 -0
  83. data/examples/prompts/general/system.txt.erb +4 -0
  84. data/examples/prompts/general/user.txt.erb +1 -0
  85. data/examples/prompts/github_assistant/system.txt.erb +6 -0
  86. data/examples/prompts/github_assistant/user.txt.erb +1 -0
  87. data/examples/prompts/helper/system.txt.erb +1 -0
  88. data/examples/prompts/helper/user.txt.erb +1 -0
  89. data/examples/prompts/keyword_extractor/system.txt.erb +8 -0
  90. data/examples/prompts/keyword_extractor/user.txt.erb +3 -0
  91. data/examples/prompts/order_support/system.txt.erb +27 -0
  92. data/examples/prompts/order_support/user.txt.erb +22 -0
  93. data/examples/prompts/product_support/system.txt.erb +30 -0
  94. data/examples/prompts/product_support/user.txt.erb +32 -0
  95. data/examples/prompts/sentiment_analyzer/system.txt.erb +9 -0
  96. data/examples/prompts/sentiment_analyzer/user.txt.erb +3 -0
  97. data/examples/prompts/synthesizer/system.txt.erb +14 -0
  98. data/examples/prompts/synthesizer/user.txt.erb +15 -0
  99. data/examples/prompts/technical/system.txt.erb +7 -0
  100. data/examples/prompts/technical/user.txt.erb +1 -0
  101. data/examples/prompts/triage/system.txt.erb +16 -0
  102. data/examples/prompts/triage/user.txt.erb +17 -0
  103. data/lib/generators/robot_lab/install_generator.rb +78 -0
  104. data/lib/generators/robot_lab/robot_generator.rb +55 -0
  105. data/lib/generators/robot_lab/templates/initializer.rb.tt +41 -0
  106. data/lib/generators/robot_lab/templates/migration.rb.tt +32 -0
  107. data/lib/generators/robot_lab/templates/result_model.rb.tt +52 -0
  108. data/lib/generators/robot_lab/templates/robot.rb.tt +46 -0
  109. data/lib/generators/robot_lab/templates/robot_test.rb.tt +32 -0
  110. data/lib/generators/robot_lab/templates/routing_robot.rb.tt +53 -0
  111. data/lib/generators/robot_lab/templates/thread_model.rb.tt +40 -0
  112. data/lib/robot_lab/adapters/anthropic.rb +163 -0
  113. data/lib/robot_lab/adapters/base.rb +85 -0
  114. data/lib/robot_lab/adapters/gemini.rb +193 -0
  115. data/lib/robot_lab/adapters/openai.rb +159 -0
  116. data/lib/robot_lab/adapters/registry.rb +81 -0
  117. data/lib/robot_lab/configuration.rb +143 -0
  118. data/lib/robot_lab/error.rb +32 -0
  119. data/lib/robot_lab/errors.rb +70 -0
  120. data/lib/robot_lab/history/active_record_adapter.rb +146 -0
  121. data/lib/robot_lab/history/config.rb +115 -0
  122. data/lib/robot_lab/history/thread_manager.rb +93 -0
  123. data/lib/robot_lab/mcp/client.rb +210 -0
  124. data/lib/robot_lab/mcp/server.rb +84 -0
  125. data/lib/robot_lab/mcp/transports/base.rb +56 -0
  126. data/lib/robot_lab/mcp/transports/sse.rb +117 -0
  127. data/lib/robot_lab/mcp/transports/stdio.rb +133 -0
  128. data/lib/robot_lab/mcp/transports/streamable_http.rb +139 -0
  129. data/lib/robot_lab/mcp/transports/websocket.rb +108 -0
  130. data/lib/robot_lab/memory.rb +882 -0
  131. data/lib/robot_lab/memory_change.rb +123 -0
  132. data/lib/robot_lab/message.rb +357 -0
  133. data/lib/robot_lab/network.rb +350 -0
  134. data/lib/robot_lab/rails/engine.rb +29 -0
  135. data/lib/robot_lab/rails/railtie.rb +42 -0
  136. data/lib/robot_lab/robot.rb +560 -0
  137. data/lib/robot_lab/robot_result.rb +205 -0
  138. data/lib/robot_lab/robotic_model.rb +324 -0
  139. data/lib/robot_lab/state_proxy.rb +188 -0
  140. data/lib/robot_lab/streaming/context.rb +144 -0
  141. data/lib/robot_lab/streaming/events.rb +95 -0
  142. data/lib/robot_lab/streaming/sequence_counter.rb +48 -0
  143. data/lib/robot_lab/task.rb +117 -0
  144. data/lib/robot_lab/tool.rb +223 -0
  145. data/lib/robot_lab/tool_config.rb +112 -0
  146. data/lib/robot_lab/tool_manifest.rb +234 -0
  147. data/lib/robot_lab/user_message.rb +118 -0
  148. data/lib/robot_lab/version.rb +5 -0
  149. data/lib/robot_lab/waiter.rb +73 -0
  150. data/lib/robot_lab.rb +195 -0
  151. data/mkdocs.yml +214 -0
  152. data/sig/robot_lab.rbs +4 -0
  153. metadata +442 -0
@@ -0,0 +1,193 @@
1
+ # Basic Chat
2
+
3
+ A simple conversational robot example.
4
+
5
+ ## Overview
6
+
7
+ This example demonstrates the minimal setup for a conversational robot that can respond to user messages.
8
+
9
+ ## Complete Example
10
+
11
+ ```ruby
12
+ #!/usr/bin/env ruby
13
+ # examples/basic_chat.rb
14
+
15
+ require "bundler/setup"
16
+ require "robot_lab"
17
+
18
+ # Configure RobotLab
19
+ RobotLab.configure do |config|
20
+ config.default_model = "claude-sonnet-4"
21
+ end
22
+
23
+ # Build a simple assistant
24
+ assistant = RobotLab.build do
25
+ name "assistant"
26
+ description "A helpful conversational assistant"
27
+
28
+ template <<~PROMPT
29
+ You are a helpful, friendly assistant. You provide clear,
30
+ concise answers to questions. Be conversational but informative.
31
+ PROMPT
32
+ end
33
+
34
+ # Simple REPL
35
+ puts "Chat with the assistant (type 'quit' to exit)"
36
+ puts "-" * 50
37
+
38
+ loop do
39
+ print "\nYou: "
40
+ input = gets&.chomp
41
+
42
+ break if input.nil? || input.downcase == "quit"
43
+ next if input.empty?
44
+
45
+ # Create state and run
46
+ state = RobotLab.create_state(message: input)
47
+ result = assistant.run(state: state)
48
+
49
+ # Display response
50
+ response = result.output.first&.content || "No response"
51
+ puts "\nAssistant: #{response}"
52
+ end
53
+
54
+ puts "\nGoodbye!"
55
+ ```
56
+
57
+ ## With Streaming
58
+
59
+ ```ruby
60
+ #!/usr/bin/env ruby
61
+ # examples/streaming_chat.rb
62
+
63
+ require "bundler/setup"
64
+ require "robot_lab"
65
+
66
+ RobotLab.configure do |config|
67
+ config.default_model = "claude-sonnet-4"
68
+ end
69
+
70
+ assistant = RobotLab.build do
71
+ name "assistant"
72
+ template "You are a helpful assistant."
73
+ end
74
+
75
+ puts "Chat with streaming (type 'quit' to exit)"
76
+ puts "-" * 50
77
+
78
+ loop do
79
+ print "\nYou: "
80
+ input = gets&.chomp
81
+
82
+ break if input.nil? || input.downcase == "quit"
83
+ next if input.empty?
84
+
85
+ state = RobotLab.create_state(message: input)
86
+
87
+ print "\nAssistant: "
88
+ assistant.run(state: state) do |event|
89
+ print event.text if event.type == :text_delta
90
+ end
91
+ puts
92
+ end
93
+
94
+ puts "\nGoodbye!"
95
+ ```
96
+
97
+ ## With Conversation History
98
+
99
+ ```ruby
100
+ #!/usr/bin/env ruby
101
+ # examples/chat_with_memory.rb
102
+
103
+ require "bundler/setup"
104
+ require "robot_lab"
105
+
106
+ RobotLab.configure do |config|
107
+ config.default_model = "claude-sonnet-4"
108
+ end
109
+
110
+ assistant = RobotLab.build do
111
+ name "assistant"
112
+ template "You are a helpful assistant with memory of our conversation."
113
+ end
114
+
115
+ # In-memory history store
116
+ HISTORY = {}
117
+
118
+ history_config = RobotLab::History::Config.new(
119
+ create_thread: ->(state:, **) {
120
+ id = SecureRandom.uuid
121
+ HISTORY[id] = []
122
+ { id: id }
123
+ },
124
+ get: ->(thread_id:, **) {
125
+ HISTORY[thread_id] || []
126
+ },
127
+ append_results: ->(thread_id:, new_results:, **) {
128
+ HISTORY[thread_id].concat(new_results.map(&:to_h))
129
+ }
130
+ )
131
+
132
+ network = RobotLab.create_network do
133
+ name "chat"
134
+ history history_config
135
+ add_robot assistant
136
+ end
137
+
138
+ puts "Chat with memory (type 'quit' to exit)"
139
+ puts "-" * 50
140
+
141
+ thread_id = nil
142
+
143
+ loop do
144
+ print "\nYou: "
145
+ input = gets&.chomp
146
+
147
+ break if input.nil? || input.downcase == "quit"
148
+ next if input.empty?
149
+
150
+ message = thread_id ?
151
+ RobotLab::UserMessage.new(input, thread_id: thread_id) :
152
+ input
153
+
154
+ state = RobotLab.create_state(message: message)
155
+ result = network.run(state: state)
156
+
157
+ thread_id ||= result.state.thread_id
158
+
159
+ response = result.last_result&.output&.first&.content || "No response"
160
+ puts "\nAssistant: #{response}"
161
+ end
162
+
163
+ puts "\nGoodbye!"
164
+ ```
165
+
166
+ ## Running
167
+
168
+ ```bash
169
+ # Set API key
170
+ export ANTHROPIC_API_KEY="your-key"
171
+
172
+ # Run basic chat
173
+ ruby examples/basic_chat.rb
174
+
175
+ # Run with streaming
176
+ ruby examples/streaming_chat.rb
177
+
178
+ # Run with memory
179
+ ruby examples/chat_with_memory.rb
180
+ ```
181
+
182
+ ## Key Concepts
183
+
184
+ 1. **Robot Building**: Use `RobotLab.build` with a template
185
+ 2. **State Creation**: Use `RobotLab.create_state` with a message
186
+ 3. **Execution**: Call `robot.run(state: state)`
187
+ 4. **Response**: Access via `result.output.first.content`
188
+
189
+ ## See Also
190
+
191
+ - [Building Robots Guide](../guides/building-robots.md)
192
+ - [Streaming Guide](../guides/streaming.md)
193
+ - [History Guide](../guides/history.md)
@@ -0,0 +1,129 @@
1
+ # Examples
2
+
3
+ Complete working examples demonstrating RobotLab features.
4
+
5
+ ## Overview
6
+
7
+ These examples show how to use RobotLab for common scenarios, from simple chatbots to complex multi-robot systems.
8
+
9
+ ## Examples
10
+
11
+ | Example | Description |
12
+ |---------|-------------|
13
+ | [Basic Chat](basic-chat.md) | Simple conversational robot |
14
+ | [Multi-Robot Network](multi-robot-network.md) | Customer service with routing |
15
+ | [Tool Usage](tool-usage.md) | External API integration |
16
+ | [MCP Server](mcp-server.md) | Creating an MCP tool server |
17
+ | [Rails Application](rails-application.md) | Full Rails integration |
18
+
19
+ ## Quick Links
20
+
21
+ ### Simple Examples
22
+
23
+ - [Hello World Robot](#hello-world)
24
+ - [Robot with Tools](#robot-with-tools)
25
+ - [Network with Routing](#network-with-routing)
26
+
27
+ ### Advanced Examples
28
+
29
+ - [Streaming Responses](basic-chat.md#with-streaming)
30
+ - [Persistent Conversations](basic-chat.md#with-conversation-history)
31
+ - [MCP Integration](mcp-server.md)
32
+
33
+ ## Hello World
34
+
35
+ ```ruby
36
+ require "robot_lab"
37
+
38
+ RobotLab.configure do |config|
39
+ config.default_model = "claude-sonnet-4"
40
+ end
41
+
42
+ robot = RobotLab.build do
43
+ name "greeter"
44
+ template "You are a friendly greeter. Say hello warmly."
45
+ end
46
+
47
+ state = RobotLab.create_state(message: "Hi there!")
48
+ result = robot.run(state: state)
49
+
50
+ puts result.output.first.content
51
+ ```
52
+
53
+ ## Robot with Tools
54
+
55
+ ```ruby
56
+ robot = RobotLab.build do
57
+ name "calculator"
58
+ template "You help with calculations."
59
+
60
+ tool :calculate do
61
+ description "Perform a calculation"
62
+ parameter :expression, type: :string, required: true
63
+ handler { |expression:, **_| eval(expression).to_s }
64
+ end
65
+ end
66
+
67
+ state = RobotLab.create_state(message: "What's 25 * 4?")
68
+ result = robot.run(state: state)
69
+ ```
70
+
71
+ ## Network with Routing
72
+
73
+ ```ruby
74
+ classifier = RobotLab.build do
75
+ name "classifier"
76
+ template "Classify: BILLING, TECHNICAL, or GENERAL"
77
+ end
78
+
79
+ billing = RobotLab.build do
80
+ name "billing"
81
+ template "You handle billing questions."
82
+ end
83
+
84
+ tech = RobotLab.build do
85
+ name "tech"
86
+ template "You handle technical issues."
87
+ end
88
+
89
+ network = RobotLab.create_network do
90
+ name "support"
91
+ add_robot classifier
92
+ add_robot billing
93
+ add_robot tech
94
+
95
+ router ->(args) {
96
+ case args.call_count
97
+ when 0 then :classifier
98
+ when 1
99
+ category = args.last_result&.output&.first&.content&.strip
100
+ category == "BILLING" ? :billing : :tech
101
+ end
102
+ }
103
+ end
104
+
105
+ result = network.run(state: state)
106
+ ```
107
+
108
+ ## Running Examples
109
+
110
+ 1. Install dependencies:
111
+ ```bash
112
+ bundle install
113
+ ```
114
+
115
+ 2. Set API key:
116
+ ```bash
117
+ export ANTHROPIC_API_KEY="your-key"
118
+ ```
119
+
120
+ 3. Run example:
121
+ ```bash
122
+ ruby examples/basic_chat.rb
123
+ ```
124
+
125
+ ## See Also
126
+
127
+ - [Getting Started](../getting-started/index.md)
128
+ - [Guides](../guides/index.md)
129
+ - [API Reference](../api/index.md)
@@ -0,0 +1,290 @@
1
+ # MCP Server
2
+
3
+ Creating and using Model Context Protocol servers.
4
+
5
+ ## Overview
6
+
7
+ This example demonstrates how to create MCP servers to expose tools and how to connect robots to external MCP servers.
8
+
9
+ ## Creating an MCP Server
10
+
11
+ ```ruby
12
+ #!/usr/bin/env ruby
13
+ # examples/mcp_server.rb
14
+
15
+ require "bundler/setup"
16
+ require "robot_lab"
17
+ require "json"
18
+
19
+ # Create an MCP server with database tools
20
+ server = RobotLab::MCP::Server.new(
21
+ name: "database_tools",
22
+ version: "1.0.0"
23
+ )
24
+
25
+ # Mock database
26
+ USERS = {
27
+ "1" => { id: "1", name: "Alice", email: "alice@example.com", plan: "pro" },
28
+ "2" => { id: "2", name: "Bob", email: "bob@example.com", plan: "free" }
29
+ }
30
+
31
+ ORDERS = {
32
+ "ORD001" => { id: "ORD001", user_id: "1", total: 99.99, status: "shipped" },
33
+ "ORD002" => { id: "ORD002", user_id: "1", total: 49.99, status: "pending" },
34
+ "ORD003" => { id: "ORD003", user_id: "2", total: 29.99, status: "delivered" }
35
+ }
36
+
37
+ # Add tools to the server
38
+ server.add_tool(
39
+ name: "get_user",
40
+ description: "Get user by ID",
41
+ parameters: {
42
+ user_id: { type: "string", required: true, description: "User ID" }
43
+ },
44
+ handler: ->(user_id:) {
45
+ user = USERS[user_id]
46
+ user || { error: "User not found" }
47
+ }
48
+ )
49
+
50
+ server.add_tool(
51
+ name: "list_users",
52
+ description: "List all users",
53
+ parameters: {
54
+ plan: { type: "string", enum: ["free", "pro"], description: "Filter by plan" }
55
+ },
56
+ handler: ->(plan: nil) {
57
+ users = USERS.values
58
+ users = users.select { |u| u[:plan] == plan } if plan
59
+ users
60
+ }
61
+ )
62
+
63
+ server.add_tool(
64
+ name: "get_orders",
65
+ description: "Get orders for a user",
66
+ parameters: {
67
+ user_id: { type: "string", required: true },
68
+ status: { type: "string", enum: ["pending", "shipped", "delivered"] }
69
+ },
70
+ handler: ->(user_id:, status: nil) {
71
+ orders = ORDERS.values.select { |o| o[:user_id] == user_id }
72
+ orders = orders.select { |o| o[:status] == status } if status
73
+ orders
74
+ }
75
+ )
76
+
77
+ server.add_tool(
78
+ name: "update_order_status",
79
+ description: "Update an order's status",
80
+ parameters: {
81
+ order_id: { type: "string", required: true },
82
+ status: { type: "string", required: true, enum: ["pending", "shipped", "delivered"] }
83
+ },
84
+ handler: ->(order_id:, status:) {
85
+ order = ORDERS[order_id]
86
+ return { error: "Order not found" } unless order
87
+ order[:status] = status
88
+ { success: true, order: order }
89
+ }
90
+ )
91
+
92
+ # Start the server (stdio for local use)
93
+ puts "Starting MCP server..."
94
+ server.start(transport: :stdio)
95
+ ```
96
+
97
+ ## Using MCP Server in Robot
98
+
99
+ ```ruby
100
+ #!/usr/bin/env ruby
101
+ # examples/mcp_client.rb
102
+
103
+ require "bundler/setup"
104
+ require "robot_lab"
105
+
106
+ RobotLab.configure do |config|
107
+ config.default_model = "claude-sonnet-4"
108
+ end
109
+
110
+ # Robot that uses the MCP server
111
+ admin_bot = RobotLab.build do
112
+ name "admin_assistant"
113
+ description "Helps with administrative tasks"
114
+
115
+ template <<~PROMPT
116
+ You are an administrative assistant with access to user and order data.
117
+ Help users look up information and manage orders.
118
+ PROMPT
119
+
120
+ mcp [
121
+ {
122
+ name: "database",
123
+ transport: {
124
+ type: "stdio",
125
+ command: "ruby",
126
+ args: ["examples/mcp_server.rb"]
127
+ }
128
+ }
129
+ ]
130
+ end
131
+
132
+ # Interactive session
133
+ puts "Admin Assistant (uses MCP server)"
134
+ puts "-" * 50
135
+
136
+ state = RobotLab.create_state(message: "List all pro users and their orders")
137
+
138
+ admin_bot.run(state: state) do |event|
139
+ case event.type
140
+ when :text_delta
141
+ print event.text
142
+ when :tool_call
143
+ puts "\n[MCP: #{event.name}]"
144
+ end
145
+ end
146
+
147
+ puts
148
+ admin_bot.disconnect
149
+ ```
150
+
151
+ ## Network with MCP
152
+
153
+ ```ruby
154
+ # examples/network_with_mcp.rb
155
+
156
+ network = RobotLab.create_network do
157
+ name "support_with_mcp"
158
+
159
+ # MCP servers available to all robots
160
+ mcp [
161
+ {
162
+ name: "database",
163
+ transport: { type: "stdio", command: "ruby examples/mcp_server.rb" }
164
+ },
165
+ {
166
+ name: "filesystem",
167
+ transport: {
168
+ type: "stdio",
169
+ command: "npx",
170
+ args: ["@modelcontextprotocol/server-filesystem", "/data"]
171
+ }
172
+ }
173
+ ]
174
+
175
+ add_robot RobotLab.build {
176
+ name "data_analyst"
177
+ template "You analyze user data."
178
+ mcp :inherit # Uses network's MCP servers
179
+ }
180
+
181
+ add_robot RobotLab.build {
182
+ name "file_manager"
183
+ template "You manage files."
184
+ mcp :inherit
185
+ tools %w[read_file list_directory] # Only these MCP tools
186
+ }
187
+ end
188
+ ```
189
+
190
+ ## HTTP MCP Server
191
+
192
+ ```ruby
193
+ #!/usr/bin/env ruby
194
+ # examples/http_mcp_server.rb
195
+
196
+ require "robot_lab"
197
+ require "sinatra"
198
+
199
+ server = RobotLab::MCP::Server.new(name: "api_tools")
200
+
201
+ server.add_tool(
202
+ name: "get_stats",
203
+ description: "Get system statistics",
204
+ parameters: {},
205
+ handler: -> {
206
+ {
207
+ uptime: `uptime`.strip,
208
+ memory: `free -m 2>/dev/null || vm_stat`.strip,
209
+ time: Time.now.iso8601
210
+ }
211
+ }
212
+ )
213
+
214
+ # Sinatra endpoint for MCP
215
+ post "/mcp" do
216
+ content_type :json
217
+ request_body = JSON.parse(request.body.read)
218
+ response = server.handle_request(request_body)
219
+ response.to_json
220
+ end
221
+
222
+ # Run: ruby examples/http_mcp_server.rb
223
+ # Connect with HTTP transport
224
+ ```
225
+
226
+ ## Connecting to HTTP Server
227
+
228
+ ```ruby
229
+ robot = RobotLab.build do
230
+ name "remote_assistant"
231
+ template "You have access to remote tools."
232
+
233
+ mcp [
234
+ {
235
+ name: "remote",
236
+ transport: {
237
+ type: "http",
238
+ url: "https://mcp.example.com/mcp",
239
+ headers: { "Authorization" => "Bearer #{ENV['MCP_TOKEN']}" }
240
+ }
241
+ }
242
+ ]
243
+ end
244
+ ```
245
+
246
+ ## WebSocket Server
247
+
248
+ ```ruby
249
+ #!/usr/bin/env ruby
250
+ # examples/websocket_mcp_server.rb
251
+
252
+ require "robot_lab"
253
+
254
+ server = RobotLab::MCP::Server.new(name: "realtime_tools")
255
+
256
+ server.add_tool(
257
+ name: "subscribe_events",
258
+ description: "Subscribe to real-time events",
259
+ parameters: { channel: { type: "string", required: true } },
260
+ handler: ->(channel:) { { subscribed: channel } }
261
+ )
262
+
263
+ # Start WebSocket server
264
+ server.start(transport: :websocket, port: 8765)
265
+ ```
266
+
267
+ ## Running
268
+
269
+ ```bash
270
+ # Start MCP server in one terminal
271
+ ruby examples/mcp_server.rb
272
+
273
+ # Run client in another terminal
274
+ export ANTHROPIC_API_KEY="your-key"
275
+ ruby examples/mcp_client.rb
276
+ ```
277
+
278
+ ## Key Concepts
279
+
280
+ 1. **Server Creation**: Use `RobotLab::MCP::Server.new`
281
+ 2. **Tool Registration**: Add tools with `server.add_tool`
282
+ 3. **Transport**: Choose stdio, http, websocket, or sse
283
+ 4. **Client Connection**: Configure in robot's `mcp` block
284
+ 5. **Tool Filtering**: Use `tools` whitelist for security
285
+
286
+ ## See Also
287
+
288
+ - [MCP Integration Guide](../guides/mcp-integration.md)
289
+ - [MCP API Reference](../api/mcp/index.md)
290
+ - [Transports](../api/mcp/transports.md)