datagrout-conduit 0.1.0
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 +7 -0
- data/README.md +303 -0
- data/lib/datagrout_conduit/client.rb +601 -0
- data/lib/datagrout_conduit/errors.rb +56 -0
- data/lib/datagrout_conduit/identity.rb +175 -0
- data/lib/datagrout_conduit/oauth.rb +85 -0
- data/lib/datagrout_conduit/registration.rb +220 -0
- data/lib/datagrout_conduit/transport/base.rb +158 -0
- data/lib/datagrout_conduit/transport/jsonrpc.rb +36 -0
- data/lib/datagrout_conduit/transport/mcp.rb +107 -0
- data/lib/datagrout_conduit/types.rb +142 -0
- data/lib/datagrout_conduit/version.rb +5 -0
- data/lib/datagrout_conduit.rb +53 -0
- metadata +145 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8fcac4a1dc9cdb77ca7e0b1b75eb44fcacf867966312e05f21b93c0cba63a6cb
|
|
4
|
+
data.tar.gz: 7faa4fc8a6c23fb5eee90fb07b2cd02caee23245bc68899d297a32d693c1b464
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: cca7ceddb65cb22cd3283659a6b44a792e683f4c57d93f9fe49226f00a71890fc59237f97c1cf13d56849febc453f7a0d84cd2ca4cfba5e967222a268c46f2b5
|
|
7
|
+
data.tar.gz: 95ab6ae19cf9a6a1b23b9444f7063fb0bcdd64d1a407af589bd00c543eb349aec98226dcfcba06598a879a6150578fbbf872fc358b84c4b9da38f55f45530228
|
data/README.md
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# DataGrout Conduit SDK for Ruby
|
|
2
|
+
|
|
3
|
+
Production-ready MCP client with mTLS, OAuth 2.1, and semantic discovery.
|
|
4
|
+
|
|
5
|
+
Connect to remote MCP and JSONRPC servers, invoke tools, discover capabilities with natural language, and track costs — all with enterprise-grade security.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add to your Gemfile:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem "datagrout-conduit", "~> 0.1"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or install directly:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
gem install datagrout-conduit
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require "datagrout_conduit"
|
|
25
|
+
|
|
26
|
+
# Create a client
|
|
27
|
+
client = DatagroutConduit::Client.new(
|
|
28
|
+
url: "https://gateway.datagrout.ai/servers/{uuid}/mcp",
|
|
29
|
+
auth: { bearer: "your-token" }
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Connect and initialize the MCP session
|
|
33
|
+
client.connect
|
|
34
|
+
|
|
35
|
+
# List available tools
|
|
36
|
+
tools = client.list_tools
|
|
37
|
+
puts "Found #{tools.size} tools"
|
|
38
|
+
|
|
39
|
+
# Call a tool
|
|
40
|
+
result = client.call_tool("salesforce@1/get_lead@1", { id: "123" })
|
|
41
|
+
puts result
|
|
42
|
+
|
|
43
|
+
# Disconnect
|
|
44
|
+
client.disconnect
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Authentication
|
|
48
|
+
|
|
49
|
+
### Bearer Token
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
client = DatagroutConduit::Client.new(
|
|
53
|
+
url: "https://gateway.datagrout.ai/servers/{uuid}/mcp",
|
|
54
|
+
auth: { bearer: "your-token" }
|
|
55
|
+
)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### API Key
|
|
59
|
+
|
|
60
|
+
```ruby
|
|
61
|
+
client = DatagroutConduit::Client.new(
|
|
62
|
+
url: "https://gateway.datagrout.ai/servers/{uuid}/mcp",
|
|
63
|
+
auth: { api_key: "your-api-key" }
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### OAuth 2.1 (Client Credentials)
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
provider = DatagroutConduit::OAuth::TokenProvider.new(
|
|
71
|
+
client_id: "my_client_id",
|
|
72
|
+
client_secret: "my_client_secret",
|
|
73
|
+
token_endpoint: "https://app.datagrout.ai/servers/{uuid}/oauth/token"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
client = DatagroutConduit::Client.new(
|
|
77
|
+
url: "https://gateway.datagrout.ai/servers/{uuid}/mcp",
|
|
78
|
+
auth: { oauth: provider }
|
|
79
|
+
)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The token endpoint is auto-derived from MCP URLs — `/mcp` becomes `/oauth/token`. Tokens are cached and refreshed 60 seconds before expiry.
|
|
83
|
+
|
|
84
|
+
### mTLS (Mutual TLS)
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
# Auto-discover identity from standard locations
|
|
88
|
+
identity = DatagroutConduit::Identity.try_discover
|
|
89
|
+
|
|
90
|
+
# Or load explicitly
|
|
91
|
+
identity = DatagroutConduit::Identity.from_paths("cert.pem", "key.pem", ca_path: "ca.pem")
|
|
92
|
+
|
|
93
|
+
# Or from PEM strings
|
|
94
|
+
identity = DatagroutConduit::Identity.from_pem(cert_pem, key_pem, ca_pem: ca_pem)
|
|
95
|
+
|
|
96
|
+
# Or from environment variables
|
|
97
|
+
identity = DatagroutConduit::Identity.from_env
|
|
98
|
+
|
|
99
|
+
client = DatagroutConduit::Client.new(
|
|
100
|
+
url: "https://gateway.datagrout.ai/servers/{uuid}/mcp",
|
|
101
|
+
identity: identity
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Identity auto-discovery order:
|
|
106
|
+
|
|
107
|
+
1. `override_dir` (if provided)
|
|
108
|
+
2. `CONDUIT_MTLS_CERT` + `CONDUIT_MTLS_KEY` env vars
|
|
109
|
+
3. `CONDUIT_IDENTITY_DIR` env var
|
|
110
|
+
4. `~/.conduit/identity.pem` + `identity_key.pem`
|
|
111
|
+
5. `.conduit/` relative to cwd
|
|
112
|
+
|
|
113
|
+
For DataGrout URLs, identity discovery happens automatically.
|
|
114
|
+
|
|
115
|
+
### Identity Registration & Bootstrap
|
|
116
|
+
|
|
117
|
+
Bootstrap a new mTLS identity with a one-time access token:
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
client = DatagroutConduit::Client.bootstrap_identity(
|
|
121
|
+
url: "https://gateway.datagrout.ai/servers/{uuid}/mcp",
|
|
122
|
+
auth_token: "your-one-time-token",
|
|
123
|
+
name: "my-agent"
|
|
124
|
+
)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Or with OAuth client credentials:
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
client = DatagroutConduit::Client.bootstrap_identity_oauth(
|
|
131
|
+
url: "https://gateway.datagrout.ai/servers/{uuid}/mcp",
|
|
132
|
+
client_id: "id",
|
|
133
|
+
client_secret: "secret",
|
|
134
|
+
name: "my-agent"
|
|
135
|
+
)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
After bootstrap, subsequent runs auto-discover the saved identity — no tokens needed.
|
|
139
|
+
|
|
140
|
+
You can also use the registration class directly:
|
|
141
|
+
|
|
142
|
+
```ruby
|
|
143
|
+
private_pem, public_pem = DatagroutConduit::Registration.generate_keypair
|
|
144
|
+
response = DatagroutConduit::Registration.register_identity(public_pem, auth_token: "token")
|
|
145
|
+
paths = DatagroutConduit::Registration.save_identity(response.cert_pem, private_pem, "~/.conduit", ca_pem: response.ca_cert_pem)
|
|
146
|
+
ca_pem = DatagroutConduit::Registration.fetch_ca_cert
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Transports
|
|
150
|
+
|
|
151
|
+
### MCP (default)
|
|
152
|
+
|
|
153
|
+
```ruby
|
|
154
|
+
client = DatagroutConduit::Client.new(
|
|
155
|
+
url: "https://gateway.datagrout.ai/servers/{uuid}/mcp",
|
|
156
|
+
auth: { bearer: "token" },
|
|
157
|
+
transport: :mcp
|
|
158
|
+
)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### JSONRPC
|
|
162
|
+
|
|
163
|
+
```ruby
|
|
164
|
+
client = DatagroutConduit::Client.new(
|
|
165
|
+
url: "https://gateway.datagrout.ai/servers/{uuid}/jsonrpc",
|
|
166
|
+
auth: { bearer: "token" },
|
|
167
|
+
transport: :jsonrpc
|
|
168
|
+
)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Both transports send JSON-RPC 2.0 requests via HTTP POST. MCP uses the MCP Streamable HTTP framing. Both configure Faraday SSL with mTLS client certificates when an identity is present.
|
|
172
|
+
|
|
173
|
+
## Standard MCP Methods
|
|
174
|
+
|
|
175
|
+
```ruby
|
|
176
|
+
client.connect
|
|
177
|
+
|
|
178
|
+
# Tools
|
|
179
|
+
tools = client.list_tools
|
|
180
|
+
result = client.call_tool("tool-name", { arg: "value" })
|
|
181
|
+
|
|
182
|
+
# Resources
|
|
183
|
+
resources = client.list_resources
|
|
184
|
+
content = client.read_resource("resource://uri")
|
|
185
|
+
|
|
186
|
+
# Prompts
|
|
187
|
+
prompts = client.list_prompts
|
|
188
|
+
messages = client.get_prompt("prompt-name", { key: "value" })
|
|
189
|
+
|
|
190
|
+
client.disconnect
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## DataGrout Extensions
|
|
194
|
+
|
|
195
|
+
### Semantic Discovery
|
|
196
|
+
|
|
197
|
+
Find tools by natural language — 10-100x more token-efficient than listing all tools.
|
|
198
|
+
|
|
199
|
+
```ruby
|
|
200
|
+
results = client.discover(goal: "find unpaid invoices", limit: 10)
|
|
201
|
+
results.tools.each do |tool|
|
|
202
|
+
puts "#{tool.name} (score: #{tool.score})"
|
|
203
|
+
end
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Intelligent Tool Execution
|
|
207
|
+
|
|
208
|
+
```ruby
|
|
209
|
+
result = client.perform("salesforce@1/get_lead@1", { email: "john@example.com" }, demux: false)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Guided Workflows
|
|
213
|
+
|
|
214
|
+
```ruby
|
|
215
|
+
session = client.guide(goal: "create invoice from lead")
|
|
216
|
+
puts session.status # => "in_progress"
|
|
217
|
+
puts session.options # => available choices
|
|
218
|
+
|
|
219
|
+
session = session.choose("option_a")
|
|
220
|
+
result = session.complete # => final result when status == "completed"
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Flow Orchestration
|
|
224
|
+
|
|
225
|
+
```ruby
|
|
226
|
+
plan = [
|
|
227
|
+
{ "tool" => "get_lead", "args" => { "email" => "john@example.com" } },
|
|
228
|
+
{ "tool" => "create_invoice", "args" => { "lead_id" => "$prev.id" } }
|
|
229
|
+
]
|
|
230
|
+
result = client.flow_into(plan)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Prism Focus
|
|
234
|
+
|
|
235
|
+
```ruby
|
|
236
|
+
result = client.prism_focus(data: raw_data, lens: "summary")
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Cost Estimation
|
|
240
|
+
|
|
241
|
+
```ruby
|
|
242
|
+
estimate = client.estimate_cost("salesforce@1/get_lead@1", { id: "123" })
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Cost Tracking
|
|
246
|
+
|
|
247
|
+
Every tool-call result from DataGrout includes a cost receipt:
|
|
248
|
+
|
|
249
|
+
```ruby
|
|
250
|
+
result = client.call_tool("salesforce@1/get_lead@1", { id: "123" })
|
|
251
|
+
|
|
252
|
+
meta = DatagroutConduit.extract_meta(result)
|
|
253
|
+
if meta
|
|
254
|
+
puts "Credits charged: #{meta.receipt.net_credits}"
|
|
255
|
+
puts "Receipt ID: #{meta.receipt.receipt_id}"
|
|
256
|
+
puts "Balance: #{meta.receipt.balance_after}"
|
|
257
|
+
|
|
258
|
+
if meta.receipt.byok.enabled
|
|
259
|
+
puts "BYOK discount: #{meta.receipt.byok.discount_applied}"
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Behaviors
|
|
265
|
+
|
|
266
|
+
- **DataGrout URL detection**: `DatagroutConduit.dg_url?(url)` returns `true` for `datagrout.ai` or `datagrout.dev` domains
|
|
267
|
+
- **Intelligent interface**: Automatically enabled for DG URLs — `list_tools` filters to non-`@` tools (DG semantic tools only). Disable with `use_intelligent_interface: false`
|
|
268
|
+
- **Auto mTLS**: DG URLs automatically attempt identity discovery
|
|
269
|
+
- **DG extension warnings**: Non-DG URLs log a one-time warning when DG-specific methods are called
|
|
270
|
+
- **Default transport**: `:mcp`
|
|
271
|
+
|
|
272
|
+
## Error Handling
|
|
273
|
+
|
|
274
|
+
```ruby
|
|
275
|
+
begin
|
|
276
|
+
client.list_tools
|
|
277
|
+
rescue DatagroutConduit::NotInitializedError
|
|
278
|
+
client.connect
|
|
279
|
+
retry
|
|
280
|
+
rescue DatagroutConduit::McpError => e
|
|
281
|
+
puts "MCP error #{e.code}: #{e.message}"
|
|
282
|
+
rescue DatagroutConduit::RateLimitedError => e
|
|
283
|
+
puts "Rate limited: #{e.used}/#{e.limit}"
|
|
284
|
+
rescue DatagroutConduit::AuthError => e
|
|
285
|
+
puts "Authentication failed: #{e.message}"
|
|
286
|
+
rescue DatagroutConduit::ConnectionError => e
|
|
287
|
+
puts "Connection error: #{e.message}"
|
|
288
|
+
rescue DatagroutConduit::ConfigError => e
|
|
289
|
+
puts "Configuration error: #{e.message}"
|
|
290
|
+
end
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Links
|
|
294
|
+
|
|
295
|
+
- [DataGrout Library](https://library.datagrout.ai) — Browse and discover integrations
|
|
296
|
+
- [Security](https://app.datagrout.ai/security) — Security documentation
|
|
297
|
+
- [MCP Inspector](https://app.datagrout.ai/inspector) — Interactive MCP testing
|
|
298
|
+
- [JSONRPC Inspector](https://app.datagrout.ai/jsonrpc-inspector) — Interactive JSONRPC testing
|
|
299
|
+
- [Labs Papers](https://datagrout.ai/labs) — Research and whitepapers
|
|
300
|
+
|
|
301
|
+
## License
|
|
302
|
+
|
|
303
|
+
MIT License. Copyright (c) DataGrout.
|