robot_lab 0.0.1 → 0.0.4
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.
- checksums.yaml +4 -4
- data/.github/workflows/deploy-github-pages.yml +9 -9
- data/.irbrc +6 -0
- data/CHANGELOG.md +90 -0
- data/README.md +203 -46
- data/Rakefile +70 -1
- data/docs/api/core/index.md +12 -0
- data/docs/api/core/robot.md +478 -130
- data/docs/api/core/tool.md +205 -209
- data/docs/api/history/active-record-adapter.md +174 -94
- data/docs/api/history/config.md +186 -93
- data/docs/api/history/index.md +57 -61
- data/docs/api/history/thread-manager.md +123 -73
- data/docs/api/mcp/client.md +119 -48
- data/docs/api/mcp/index.md +75 -60
- data/docs/api/mcp/server.md +120 -136
- data/docs/api/mcp/transports.md +172 -184
- data/docs/api/streaming/context.md +157 -74
- data/docs/api/streaming/events.md +114 -166
- data/docs/api/streaming/index.md +74 -72
- data/docs/architecture/core-concepts.md +361 -112
- data/docs/architecture/index.md +97 -59
- data/docs/architecture/message-flow.md +138 -129
- data/docs/architecture/network-orchestration.md +197 -50
- data/docs/architecture/robot-execution.md +199 -146
- data/docs/architecture/state-management.md +255 -187
- data/docs/concepts.md +312 -48
- data/docs/examples/basic-chat.md +89 -77
- data/docs/examples/index.md +222 -47
- data/docs/examples/mcp-server.md +207 -203
- data/docs/examples/multi-robot-network.md +129 -35
- data/docs/examples/rails-application.md +159 -160
- data/docs/examples/tool-usage.md +295 -204
- data/docs/getting-started/configuration.md +275 -162
- data/docs/getting-started/index.md +1 -1
- data/docs/getting-started/installation.md +22 -13
- data/docs/getting-started/quick-start.md +166 -121
- data/docs/guides/building-robots.md +417 -212
- data/docs/guides/creating-networks.md +94 -24
- data/docs/guides/mcp-integration.md +152 -113
- data/docs/guides/memory.md +220 -164
- data/docs/guides/streaming.md +80 -110
- data/docs/guides/using-tools.md +259 -212
- data/docs/index.md +50 -37
- data/examples/01_simple_robot.rb +6 -9
- data/examples/02_tools.rb +6 -9
- data/examples/03_network.rb +13 -14
- data/examples/04_mcp.rb +5 -8
- data/examples/05_streaming.rb +5 -8
- data/examples/06_prompt_templates.rb +42 -37
- data/examples/07_network_memory.rb +13 -14
- data/examples/08_llm_config.rb +140 -0
- data/examples/09_chaining.rb +223 -0
- data/examples/10_memory.rb +331 -0
- data/examples/11_network_introspection.rb +230 -0
- data/examples/12_message_bus.rb +74 -0
- data/examples/13_spawn.rb +90 -0
- data/examples/14_rusty_circuit/comic.rb +143 -0
- data/examples/14_rusty_circuit/display.rb +203 -0
- data/examples/14_rusty_circuit/heckler.rb +57 -0
- data/examples/14_rusty_circuit/open_mic.rb +121 -0
- data/examples/14_rusty_circuit/prompts/open_mic_comic.md +20 -0
- data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +23 -0
- data/examples/14_rusty_circuit/prompts/open_mic_scout.md +20 -0
- data/examples/14_rusty_circuit/scout.rb +173 -0
- data/examples/14_rusty_circuit/scout_notes.md +89 -0
- data/examples/14_rusty_circuit/show.log +234 -0
- data/examples/15_memory_network_and_bus/editor_in_chief.rb +24 -0
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +206 -0
- data/examples/15_memory_network_and_bus/linux_writer.rb +80 -0
- data/examples/15_memory_network_and_bus/os_editor.rb +46 -0
- data/examples/15_memory_network_and_bus/os_writer.rb +46 -0
- data/examples/15_memory_network_and_bus/output/combined_article.md +13 -0
- data/examples/15_memory_network_and_bus/output/final_article.md +15 -0
- data/examples/15_memory_network_and_bus/output/linux_draft.md +5 -0
- data/examples/15_memory_network_and_bus/output/mac_draft.md +7 -0
- data/examples/15_memory_network_and_bus/output/memory.json +13 -0
- data/examples/15_memory_network_and_bus/output/revision_1.md +19 -0
- data/examples/15_memory_network_and_bus/output/revision_2.md +15 -0
- data/examples/15_memory_network_and_bus/output/windows_draft.md +7 -0
- data/examples/15_memory_network_and_bus/prompts/os_advocate.md +13 -0
- data/examples/15_memory_network_and_bus/prompts/os_chief.md +13 -0
- data/examples/15_memory_network_and_bus/prompts/os_editor.md +13 -0
- data/examples/README.md +197 -0
- data/examples/prompts/{assistant/system.txt.erb → assistant.md} +3 -0
- data/examples/prompts/{billing/system.txt.erb → billing.md} +3 -0
- data/examples/prompts/{classifier/system.txt.erb → classifier.md} +3 -0
- data/examples/prompts/comedian.md +6 -0
- data/examples/prompts/comedy_critic.md +10 -0
- data/examples/prompts/configurable.md +9 -0
- data/examples/prompts/dispatcher.md +12 -0
- data/examples/prompts/{entity_extractor/system.txt.erb → entity_extractor.md} +3 -0
- data/examples/prompts/{escalation/system.txt.erb → escalation.md} +7 -0
- data/examples/prompts/frontmatter_mcp_test.md +9 -0
- data/examples/prompts/frontmatter_named_test.md +5 -0
- data/examples/prompts/frontmatter_tools_test.md +6 -0
- data/examples/prompts/{general/system.txt.erb → general.md} +3 -0
- data/examples/prompts/{github_assistant/system.txt.erb → github_assistant.md} +8 -0
- data/examples/prompts/{helper/system.txt.erb → helper.md} +3 -0
- data/examples/prompts/{keyword_extractor/system.txt.erb → keyword_extractor.md} +3 -0
- data/examples/prompts/llm_config_demo.md +20 -0
- data/examples/prompts/{order_support/system.txt.erb → order_support.md} +8 -0
- data/examples/prompts/os_advocate.md +13 -0
- data/examples/prompts/os_chief.md +13 -0
- data/examples/prompts/os_editor.md +13 -0
- data/examples/prompts/{product_support/system.txt.erb → product_support.md} +7 -0
- data/examples/prompts/{sentiment_analyzer/system.txt.erb → sentiment_analyzer.md} +3 -0
- data/examples/prompts/{synthesizer/system.txt.erb → synthesizer.md} +3 -0
- data/examples/prompts/{technical/system.txt.erb → technical.md} +3 -0
- data/examples/prompts/{triage/system.txt.erb → triage.md} +6 -0
- data/lib/generators/robot_lab/templates/initializer.rb.tt +1 -1
- data/lib/robot_lab/adapters/openai.rb +2 -1
- data/lib/robot_lab/ask_user.rb +75 -0
- data/lib/robot_lab/config/defaults.yml +121 -0
- data/lib/robot_lab/config.rb +183 -0
- data/lib/robot_lab/error.rb +6 -0
- data/lib/robot_lab/mcp/client.rb +1 -1
- data/lib/robot_lab/memory.rb +2 -2
- data/lib/robot_lab/robot.rb +523 -249
- data/lib/robot_lab/robot_message.rb +44 -0
- data/lib/robot_lab/robot_result.rb +1 -0
- data/lib/robot_lab/robotic_model.rb +1 -1
- data/lib/robot_lab/streaming/context.rb +1 -1
- data/lib/robot_lab/tool.rb +108 -172
- data/lib/robot_lab/tool_config.rb +1 -1
- data/lib/robot_lab/tool_manifest.rb +2 -18
- data/lib/robot_lab/version.rb +1 -1
- data/lib/robot_lab.rb +66 -55
- metadata +107 -116
- data/examples/prompts/assistant/user.txt.erb +0 -1
- data/examples/prompts/billing/user.txt.erb +0 -1
- data/examples/prompts/classifier/user.txt.erb +0 -1
- data/examples/prompts/entity_extractor/user.txt.erb +0 -3
- data/examples/prompts/escalation/user.txt.erb +0 -34
- data/examples/prompts/general/user.txt.erb +0 -1
- data/examples/prompts/github_assistant/user.txt.erb +0 -1
- data/examples/prompts/helper/user.txt.erb +0 -1
- data/examples/prompts/keyword_extractor/user.txt.erb +0 -3
- data/examples/prompts/order_support/user.txt.erb +0 -22
- data/examples/prompts/product_support/user.txt.erb +0 -32
- data/examples/prompts/sentiment_analyzer/user.txt.erb +0 -3
- data/examples/prompts/synthesizer/user.txt.erb +0 -15
- data/examples/prompts/technical/user.txt.erb +0 -1
- data/examples/prompts/triage/user.txt.erb +0 -17
- data/lib/robot_lab/configuration.rb +0 -143
data/docs/api/mcp/index.md
CHANGED
|
@@ -4,108 +4,123 @@ Integration with MCP servers for extended tool capabilities.
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
MCP allows robots to connect to external tool servers, extending their capabilities without modifying robot code.
|
|
7
|
+
MCP allows robots to connect to external tool servers, extending their capabilities without modifying robot code. RobotLab provides an MCP client that communicates with MCP-compliant servers over multiple transport types.
|
|
8
8
|
|
|
9
9
|
```ruby
|
|
10
|
-
robot =
|
|
11
|
-
name "developer"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
mcp [
|
|
10
|
+
robot = Robot.new(
|
|
11
|
+
name: "developer",
|
|
12
|
+
system_prompt: "You help with coding tasks.",
|
|
13
|
+
mcp: [
|
|
15
14
|
{
|
|
16
15
|
name: "filesystem",
|
|
17
16
|
transport: { type: "stdio", command: "npx @modelcontextprotocol/server-filesystem" }
|
|
18
17
|
}
|
|
19
18
|
]
|
|
20
|
-
|
|
19
|
+
)
|
|
21
20
|
```
|
|
22
21
|
|
|
23
22
|
## Components
|
|
24
23
|
|
|
25
24
|
| Component | Description |
|
|
26
25
|
|-----------|-------------|
|
|
27
|
-
| [Client](client.md) | Connects to MCP servers |
|
|
28
|
-
| [Server](server.md) |
|
|
29
|
-
| [Transports](transports.md) | Communication methods |
|
|
26
|
+
| [Client](client.md) | Connects to MCP servers, lists tools, calls tools |
|
|
27
|
+
| [Server](server.md) | Server configuration data structure |
|
|
28
|
+
| [Transports](transports.md) | Communication methods (stdio, WebSocket, SSE, HTTP) |
|
|
30
29
|
|
|
31
30
|
## Quick Start
|
|
32
31
|
|
|
33
|
-
### Using MCP
|
|
32
|
+
### Using MCP with a Robot
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
network = RobotLab.create_network do
|
|
37
|
-
name "with_mcp"
|
|
34
|
+
Pass MCP server configurations via the `mcp:` parameter when creating a robot:
|
|
38
35
|
|
|
39
|
-
|
|
36
|
+
```ruby
|
|
37
|
+
robot = Robot.new(
|
|
38
|
+
name: "assistant",
|
|
39
|
+
template: :assistant,
|
|
40
|
+
mcp: [
|
|
40
41
|
{ name: "github", transport: { type: "stdio", command: "mcp-server-github" } }
|
|
41
42
|
]
|
|
43
|
+
)
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
template "You help with GitHub tasks."
|
|
46
|
-
mcp :inherit # Use network's MCP servers
|
|
47
|
-
}
|
|
48
|
-
end
|
|
45
|
+
result = robot.run("List my open pull requests")
|
|
46
|
+
result.last_text_content
|
|
49
47
|
```
|
|
50
48
|
|
|
51
|
-
###
|
|
49
|
+
### MCP in Networks
|
|
50
|
+
|
|
51
|
+
Robots in a network can inherit MCP servers from the network or define their own:
|
|
52
52
|
|
|
53
53
|
```ruby
|
|
54
|
-
|
|
54
|
+
network_mcp = [
|
|
55
|
+
{ name: "github", transport: { type: "stdio", command: "mcp-server-github" } }
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
robot = Robot.new(
|
|
59
|
+
name: "assistant",
|
|
60
|
+
template: :assistant,
|
|
61
|
+
mcp: :inherit # Use network's MCP servers
|
|
62
|
+
)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Direct Client Usage
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
handler: ->(id:) { User.find(id).to_h }
|
|
67
|
+
```ruby
|
|
68
|
+
client = RobotLab::MCP::Client.new(
|
|
69
|
+
name: "filesystem",
|
|
70
|
+
transport: { type: "stdio", command: "mcp-server-filesystem", args: ["--root", "/data"] }
|
|
61
71
|
)
|
|
62
72
|
|
|
63
|
-
|
|
73
|
+
client.connect
|
|
74
|
+
tools = client.list_tools
|
|
75
|
+
result = client.call_tool("readFile", { path: "/data/config.yml" })
|
|
76
|
+
client.disconnect
|
|
64
77
|
```
|
|
65
78
|
|
|
66
79
|
## Transport Types
|
|
67
80
|
|
|
68
|
-
| Type | Use Case |
|
|
69
|
-
|
|
70
|
-
| `stdio` | Local command execution |
|
|
71
|
-
| `websocket` | Real-time bidirectional |
|
|
72
|
-
| `sse` | Server-sent events |
|
|
73
|
-
| `http` | HTTP request/response |
|
|
81
|
+
| Type | Config Key | Use Case |
|
|
82
|
+
|------|------------|----------|
|
|
83
|
+
| `stdio` | `"stdio"` | Local command/subprocess execution |
|
|
84
|
+
| `websocket` | `"ws"` or `"websocket"` | Real-time bidirectional communication |
|
|
85
|
+
| `sse` | `"sse"` | Server-sent events streaming |
|
|
86
|
+
| `streamable-http` | `"streamable-http"` or `"http"` | HTTP request/response with session support |
|
|
74
87
|
|
|
75
|
-
##
|
|
88
|
+
## MCP Parameter Values
|
|
76
89
|
|
|
77
|
-
|
|
90
|
+
The `mcp:` parameter on a Robot accepts three types of values:
|
|
78
91
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
end
|
|
85
|
-
```
|
|
92
|
+
| Value | Meaning |
|
|
93
|
+
|-------|---------|
|
|
94
|
+
| `:none` | No MCP servers (explicitly disabled) |
|
|
95
|
+
| `:inherit` | Use the network's MCP servers |
|
|
96
|
+
| `Array<Hash>` | Explicit list of server configurations |
|
|
86
97
|
|
|
87
|
-
|
|
98
|
+
Each server configuration hash requires:
|
|
88
99
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
```
|
|
100
|
+
| Key | Type | Description |
|
|
101
|
+
|-----|------|-------------|
|
|
102
|
+
| `name` | `String` | Unique server identifier |
|
|
103
|
+
| `transport` | `Hash` | Transport configuration (must include `type`) |
|
|
104
|
+
|
|
105
|
+
## Error Handling
|
|
106
|
+
|
|
107
|
+
MCP operations raise `RobotLab::MCPError` when:
|
|
98
108
|
|
|
99
|
-
|
|
109
|
+
- Connection to a server fails
|
|
110
|
+
- A request is made without an active connection
|
|
111
|
+
- An unsupported transport type is specified
|
|
100
112
|
|
|
101
113
|
```ruby
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
114
|
+
begin
|
|
115
|
+
client.connect
|
|
116
|
+
client.call_tool("unknown_tool", {})
|
|
117
|
+
rescue RobotLab::MCPError => e
|
|
118
|
+
puts "MCP error: #{e.message}"
|
|
105
119
|
end
|
|
106
120
|
```
|
|
107
121
|
|
|
108
122
|
## See Also
|
|
109
123
|
|
|
110
|
-
- [MCP
|
|
111
|
-
- [
|
|
124
|
+
- [MCP Client](client.md)
|
|
125
|
+
- [MCP Server](server.md)
|
|
126
|
+
- [Transports](transports.md)
|
data/docs/api/mcp/server.md
CHANGED
|
@@ -1,221 +1,205 @@
|
|
|
1
|
-
# MCP Server
|
|
1
|
+
# MCP Server Configuration
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Data structure for MCP server connection configuration.
|
|
4
4
|
|
|
5
5
|
## Class: `RobotLab::MCP::Server`
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
server = RobotLab::MCP::Server.new(name: "my_tools")
|
|
7
|
+
`Server` is a configuration object that defines how to connect to an MCP server. It holds the server name and transport settings, and validates the configuration on construction.
|
|
9
8
|
|
|
10
|
-
server.
|
|
11
|
-
name: "get_time",
|
|
12
|
-
description: "Get current time",
|
|
13
|
-
handler: ->(**_) { Time.now.iso8601 }
|
|
14
|
-
)
|
|
9
|
+
This is **not** an MCP server implementation -- it is the configuration used by `MCP::Client` to establish a connection to an external MCP server.
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
```ruby
|
|
12
|
+
server = RobotLab::MCP::Server.new(
|
|
13
|
+
name: "filesystem",
|
|
14
|
+
transport: { type: "stdio", command: "mcp-server-filesystem", args: ["--root", "/data"] }
|
|
15
|
+
)
|
|
17
16
|
```
|
|
18
17
|
|
|
19
18
|
## Constructor
|
|
20
19
|
|
|
21
20
|
```ruby
|
|
22
|
-
Server.new(name:,
|
|
21
|
+
Server.new(name:, transport:)
|
|
23
22
|
```
|
|
24
23
|
|
|
25
24
|
**Parameters:**
|
|
26
25
|
|
|
27
26
|
| Name | Type | Description |
|
|
28
27
|
|------|------|-------------|
|
|
29
|
-
| `name` | `String` |
|
|
30
|
-
| `
|
|
28
|
+
| `name` | `String` | Unique server identifier |
|
|
29
|
+
| `transport` | `Hash` | Transport configuration (must include `type`) |
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
**Raises:** `ArgumentError` if:
|
|
32
|
+
- The transport type is not one of the valid types
|
|
33
|
+
- A stdio transport is missing the `:command` key
|
|
34
|
+
- A network transport (ws, websocket, sse, streamable-http, http) is missing the `:url` key
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
## Valid Transport Types
|
|
35
37
|
|
|
36
38
|
```ruby
|
|
37
|
-
|
|
39
|
+
RobotLab::MCP::Server::VALID_TRANSPORT_TYPES
|
|
40
|
+
# => ["stdio", "sse", "ws", "websocket", "streamable-http", "http"]
|
|
38
41
|
```
|
|
39
42
|
|
|
40
|
-
|
|
43
|
+
## Attributes
|
|
41
44
|
|
|
42
|
-
###
|
|
45
|
+
### name
|
|
43
46
|
|
|
44
47
|
```ruby
|
|
45
|
-
server.
|
|
48
|
+
server.name # => String
|
|
46
49
|
```
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
The server identifier string.
|
|
49
52
|
|
|
50
|
-
###
|
|
53
|
+
### transport
|
|
51
54
|
|
|
52
55
|
```ruby
|
|
53
|
-
server.
|
|
56
|
+
server.transport # => Hash
|
|
54
57
|
```
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
The normalized transport configuration hash (keys are symbols, type is downcased).
|
|
57
60
|
|
|
58
61
|
## Methods
|
|
59
62
|
|
|
60
|
-
###
|
|
63
|
+
### transport_type
|
|
61
64
|
|
|
62
65
|
```ruby
|
|
63
|
-
server.
|
|
64
|
-
name:,
|
|
65
|
-
description:,
|
|
66
|
-
parameters: {},
|
|
67
|
-
handler:
|
|
68
|
-
)
|
|
66
|
+
server.transport_type # => String
|
|
69
67
|
```
|
|
70
68
|
|
|
71
|
-
|
|
69
|
+
Returns the transport type string (e.g., `"stdio"`, `"ws"`, `"sse"`).
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
| Name | Type | Description |
|
|
76
|
-
|------|------|-------------|
|
|
77
|
-
| `name` | `String` | Tool name |
|
|
78
|
-
| `description` | `String` | Tool description |
|
|
79
|
-
| `parameters` | `Hash` | Parameter schema |
|
|
80
|
-
| `handler` | `Proc` | Execution function |
|
|
81
|
-
|
|
82
|
-
### remove_tool
|
|
71
|
+
### to_h
|
|
83
72
|
|
|
84
73
|
```ruby
|
|
85
|
-
server.
|
|
74
|
+
server.to_h # => { name: "...", transport: { ... } }
|
|
86
75
|
```
|
|
87
76
|
|
|
88
|
-
|
|
77
|
+
Converts the server configuration to a hash representation.
|
|
78
|
+
|
|
79
|
+
## Transport Configuration Options
|
|
89
80
|
|
|
90
|
-
###
|
|
81
|
+
### Stdio Transport
|
|
82
|
+
|
|
83
|
+
For local MCP servers running as subprocesses:
|
|
91
84
|
|
|
92
85
|
```ruby
|
|
93
|
-
|
|
86
|
+
Server.new(
|
|
87
|
+
name: "filesystem",
|
|
88
|
+
transport: {
|
|
89
|
+
type: "stdio",
|
|
90
|
+
command: "mcp-server-filesystem", # Required
|
|
91
|
+
args: ["--root", "/data"], # Optional
|
|
92
|
+
env: { "DEBUG" => "true" } # Optional
|
|
93
|
+
}
|
|
94
|
+
)
|
|
94
95
|
```
|
|
95
96
|
|
|
96
|
-
|
|
97
|
+
| Key | Type | Required | Description |
|
|
98
|
+
|-----|------|----------|-------------|
|
|
99
|
+
| `type` | `String` | Yes | Must be `"stdio"` |
|
|
100
|
+
| `command` | `String` | Yes | Executable command |
|
|
101
|
+
| `args` | `Array<String>` | No | Command arguments |
|
|
102
|
+
| `env` | `Hash` | No | Environment variables |
|
|
97
103
|
|
|
98
|
-
|
|
104
|
+
### WebSocket Transport
|
|
99
105
|
|
|
100
|
-
|
|
101
|
-
|-----------|---------|
|
|
102
|
-
| `:stdio` | None |
|
|
103
|
-
| `:websocket` | `port:`, `host:` |
|
|
104
|
-
| `:sse` | `port:`, `host:`, `path:` |
|
|
105
|
-
| `:http` | `port:`, `host:`, `path:` |
|
|
106
|
-
|
|
107
|
-
### stop
|
|
106
|
+
For bidirectional real-time communication:
|
|
108
107
|
|
|
109
108
|
```ruby
|
|
110
|
-
|
|
109
|
+
Server.new(
|
|
110
|
+
name: "neon",
|
|
111
|
+
transport: {
|
|
112
|
+
type: "ws",
|
|
113
|
+
url: "ws://localhost:8080" # Required
|
|
114
|
+
}
|
|
115
|
+
)
|
|
111
116
|
```
|
|
112
117
|
|
|
113
|
-
|
|
118
|
+
| Key | Type | Required | Description |
|
|
119
|
+
|-----|------|----------|-------------|
|
|
120
|
+
| `type` | `String` | Yes | `"ws"` or `"websocket"` |
|
|
121
|
+
| `url` | `String` | Yes | WebSocket endpoint URL |
|
|
114
122
|
|
|
115
|
-
|
|
123
|
+
### SSE Transport
|
|
116
124
|
|
|
117
|
-
|
|
125
|
+
For server-sent events streaming:
|
|
118
126
|
|
|
119
127
|
```ruby
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
message: { type: "string", required: true }
|
|
127
|
-
},
|
|
128
|
-
handler: ->(message:) { message }
|
|
128
|
+
Server.new(
|
|
129
|
+
name: "streaming",
|
|
130
|
+
transport: {
|
|
131
|
+
type: "sse",
|
|
132
|
+
url: "http://localhost:8080/sse" # Required
|
|
133
|
+
}
|
|
129
134
|
)
|
|
130
|
-
|
|
131
|
-
server.start(transport: :stdio)
|
|
132
135
|
```
|
|
133
136
|
|
|
134
|
-
|
|
137
|
+
| Key | Type | Required | Description |
|
|
138
|
+
|-----|------|----------|-------------|
|
|
139
|
+
| `type` | `String` | Yes | Must be `"sse"` |
|
|
140
|
+
| `url` | `String` | Yes | SSE endpoint URL |
|
|
135
141
|
|
|
136
|
-
|
|
137
|
-
server = RobotLab::MCP::Server.new(name: "database")
|
|
138
|
-
|
|
139
|
-
server.add_tool(
|
|
140
|
-
name: "query_users",
|
|
141
|
-
description: "Query users by criteria",
|
|
142
|
-
parameters: {
|
|
143
|
-
status: { type: "string", enum: ["active", "inactive"] },
|
|
144
|
-
limit: { type: "integer", default: 10 }
|
|
145
|
-
},
|
|
146
|
-
handler: ->(status: nil, limit: 10) {
|
|
147
|
-
scope = User.all
|
|
148
|
-
scope = scope.where(status: status) if status
|
|
149
|
-
scope.limit(limit).map(&:to_h)
|
|
150
|
-
}
|
|
151
|
-
)
|
|
142
|
+
### Streamable HTTP Transport
|
|
152
143
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
144
|
+
For HTTP-based communication with session management:
|
|
145
|
+
|
|
146
|
+
```ruby
|
|
147
|
+
Server.new(
|
|
148
|
+
name: "api",
|
|
149
|
+
transport: {
|
|
150
|
+
type: "streamable-http",
|
|
151
|
+
url: "https://server.smithery.ai/neon/mcp", # Required
|
|
152
|
+
session_id: "abc123", # Optional
|
|
153
|
+
auth_provider: -> { "Bearer #{token}" } # Optional
|
|
162
154
|
}
|
|
163
155
|
)
|
|
164
|
-
|
|
165
|
-
server.start(transport: :websocket, port: 8080)
|
|
166
156
|
```
|
|
167
157
|
|
|
168
|
-
|
|
158
|
+
| Key | Type | Required | Description |
|
|
159
|
+
|-----|------|----------|-------------|
|
|
160
|
+
| `type` | `String` | Yes | `"streamable-http"` or `"http"` |
|
|
161
|
+
| `url` | `String` | Yes | HTTP endpoint URL |
|
|
162
|
+
| `session_id` | `String` | No | Session identifier |
|
|
163
|
+
| `auth_provider` | `Proc` | No | Authentication callback returning auth header value |
|
|
169
164
|
|
|
170
|
-
|
|
171
|
-
# Convert existing robot tools to MCP server
|
|
172
|
-
robot = RobotLab.build do
|
|
173
|
-
name "assistant"
|
|
174
|
-
|
|
175
|
-
tool :calculate do
|
|
176
|
-
description "Perform calculation"
|
|
177
|
-
parameter :expression, type: :string, required: true
|
|
178
|
-
handler { |expression:, **_| eval(expression) }
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
server = RobotLab::MCP::Server.from_robot(robot)
|
|
183
|
-
server.start(transport: :stdio)
|
|
184
|
-
```
|
|
165
|
+
## Examples
|
|
185
166
|
|
|
186
|
-
###
|
|
167
|
+
### Multiple Server Configurations
|
|
187
168
|
|
|
188
169
|
```ruby
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
170
|
+
servers = [
|
|
171
|
+
{
|
|
172
|
+
name: "filesystem",
|
|
173
|
+
transport: { type: "stdio", command: "mcp-server-filesystem", args: ["/data"] }
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: "github",
|
|
177
|
+
transport: { type: "stdio", command: "mcp-server-github" }
|
|
196
178
|
},
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
179
|
+
{
|
|
180
|
+
name: "database",
|
|
181
|
+
transport: { type: "ws", url: "ws://localhost:9090" }
|
|
200
182
|
}
|
|
201
|
-
|
|
183
|
+
]
|
|
202
184
|
|
|
203
|
-
|
|
185
|
+
# Pass directly to a robot
|
|
186
|
+
robot = Robot.new(
|
|
187
|
+
name: "dev_assistant",
|
|
188
|
+
system_prompt: "You help with development tasks.",
|
|
189
|
+
mcp: servers
|
|
190
|
+
)
|
|
204
191
|
```
|
|
205
192
|
|
|
206
|
-
###
|
|
193
|
+
### Creating a Client from a Server
|
|
207
194
|
|
|
208
195
|
```ruby
|
|
209
|
-
server = RobotLab::MCP::Server.new(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
uri: "file://config",
|
|
213
|
-
name: "Configuration",
|
|
214
|
-
description: "Application configuration",
|
|
215
|
-
handler: -> { File.read("config.yml") }
|
|
196
|
+
server = RobotLab::MCP::Server.new(
|
|
197
|
+
name: "tools",
|
|
198
|
+
transport: { type: "ws", url: "ws://localhost:8080" }
|
|
216
199
|
)
|
|
217
200
|
|
|
218
|
-
|
|
201
|
+
client = RobotLab::MCP::Client.new(server)
|
|
202
|
+
client.connect
|
|
219
203
|
```
|
|
220
204
|
|
|
221
205
|
## See Also
|