actionmcp 0.100.0 → 0.100.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9b01884f2ba4ded4a59d6c235583edbd00dae36da78215da26a1fbf83039838f
4
- data.tar.gz: c97745755f33ece7ce05a4a2a904cde23e3fe67c3f1ecf9ee0cc962e6bdc9177
3
+ metadata.gz: 5df97e0bdac66054109edabe63756d639e74bb3068d70d4028bd990b2bee8442
4
+ data.tar.gz: db73f42cf5307f09e3b4484799057fc10ee4a5341efa58aef99ab25be82abc4c
5
5
  SHA512:
6
- metadata.gz: 545540e721a557860d9263873c841fd703afd1ea9bed05ea489b738c5a81594cc6f560fdf3959d6d9ff992b3e4b247eb8efead8f5f234946429903b00ce06a96
7
- data.tar.gz: 8c4a3d2abe05b4f65b26e6dfdd751350973e029341c8ed8bb1e3f880a046477afd59ce236a71d6e607dd82ab3220eaac1c3ee462c7c8861c1ec79a814eaa42ca
6
+ metadata.gz: 0fa54e67f4f7c5e60ba16bd708557534e3b374e19e16d8456289e269e3649c4117407d5e6b4c2ce5c3645476084ab7444e81681a7a900953b4d25da50e534ddc
7
+ data.tar.gz: 1b783e0ddb8c502cf9438049b7f88c74a89e2bb8e48fdd795789741a7de77b12507412c4b66116b299f7a6b7c75b0279bddf787c6ca522e246e66bee139dd694
data/README.md CHANGED
@@ -219,6 +219,111 @@ sum_tool = CalculateSumTool.new(a: 5, b: 10)
219
219
  result = sum_tool.call
220
220
  ```
221
221
 
222
+ #### Structured output (output_schema)
223
+
224
+ Advertise a JSON Schema for your tool's structuredContent and return machine-validated results alongside any text output.
225
+
226
+ ```ruby
227
+ class PriceQuoteTool < ApplicationMCPTool
228
+ tool_name "price_quote"
229
+ description "Return a structured price quote"
230
+
231
+ property :sku, type: "string", description: "SKU to price", required: true
232
+
233
+ output_schema do
234
+ string :sku, required: true, description: "SKU that was priced"
235
+ number :price_cents, required: true, description: "Total price in cents"
236
+ object :meta do
237
+ string :currency, required: true, enum: %w[USD EUR GBP]
238
+ boolean :cached, default: false
239
+ end
240
+ end
241
+
242
+ def perform
243
+ price_cents = lookup_price_cents(sku) # Implement your lookup
244
+
245
+ render structured: { sku: sku,
246
+ price_cents: price_cents,
247
+ meta: { currency: "USD", cached: false } }
248
+ end
249
+ end
250
+ ```
251
+
252
+ The schema is included in the tool definition, and the `structured` payload is emitted as `structuredContent` in the response while remaining compatible with text/audio/image renders.
253
+
254
+ #### Returning resource links from a tool
255
+
256
+ When you want to hand back a URI instead of embedding the payload, use the built-in `render_resource_link`, which produces the MCP `resource_link` content type.
257
+
258
+ ```ruby
259
+ class ReportLinkTool < ApplicationMCPTool
260
+ tool_name "report_link"
261
+ description "Return a downloadable report link"
262
+
263
+ property :report_id, type: "string", required: true
264
+
265
+ def perform
266
+ render_resource_link(
267
+ uri: "reports://#{report_id}.json",
268
+ name: "Report #{report_id}",
269
+ description: "Downloadable JSON for report #{report_id}",
270
+ mime_type: "application/json"
271
+ )
272
+ end
273
+ end
274
+ ```
275
+
276
+ Clients can resolve the URI with a separate `resources/read` call, keeping tool responses lightweight while still discoverable.
277
+
278
+ #### Task-augmented tools (async execution with progress)
279
+
280
+ Use MCP Tasks when work might take seconds/minutes. Advertise task support with `task_required!` (or `task_optional!`) and let callers opt in by sending `_meta.task` on `tools/call`. While running as a task, you can emit progress updates with `report_progress!`.
281
+
282
+ ```ruby
283
+ class BatchIndexTool < ApplicationMCPTool
284
+ tool_name "batch_index"
285
+ description "Index many items asynchronously with progress updates"
286
+
287
+ task_required! # advertise that this tool is intended to run as a task
288
+ property :items, type: "array_string", description: "Items to index", required: true
289
+
290
+ def perform
291
+ total = items.length
292
+ items.each_with_index do |item, idx|
293
+ index_item(item) # your indexing logic
294
+
295
+ percent = ((idx + 1) * 100.0 / total).round
296
+ report_progress!(percent: percent, message: "Indexed #{idx + 1}/#{total}")
297
+ end
298
+
299
+ render(text: "Indexed #{total} items")
300
+ end
301
+
302
+ private
303
+
304
+ def index_item(item)
305
+ # Implement your indexing logic here
306
+ end
307
+ end
308
+ ```
309
+
310
+ Call it as a task from a client by adding `_meta.task` (creates a Task record and runs the tool via `ToolExecutionJob`):
311
+
312
+ ```json
313
+ {
314
+ "jsonrpc": "2.0",
315
+ "id": 1,
316
+ "method": "tools/call",
317
+ "params": {
318
+ "name": "batch_index",
319
+ "arguments": { "items": ["a", "b", "c"] },
320
+ "_meta": { "task": { "ttl": 120000, "pollInterval": 2000 } }
321
+ }
322
+ }
323
+ ```
324
+
325
+ Poll task status with `tasks/get` or fetch the result when finished with `tasks/result`. Use `tasks/cancel` to stop non-terminal tasks.
326
+
222
327
  ### ActionMCP::ResourceTemplate
223
328
 
224
329
  `ActionMCP::ResourceTemplate` facilitates the creation of URI templates for dynamic resources that LLMs can access.
@@ -311,6 +416,10 @@ ActionMCP provides comprehensive documentation across multiple specialized guide
311
416
  - Transport configuration and connection handling
312
417
  - Tool, prompt, and resource collections
313
418
  - Production deployment patterns
419
+ - **[🔐 GATEWAY.md](GATEWAY.md)** - Authentication gateway guide
420
+ - Implementing `ApplicationGateway`
421
+ - Identifier handling via `ActionMCP::Current`
422
+ - Auth patterns, error handling, and hardening tips
314
423
 
315
424
  ### Protocol & Technical Details
316
425
  - **[🚀 The Hitchhiker's Guide to MCP](The_Hitchhikers_Guide_to_MCP.md)** - Protocol versions and migration
@@ -27,7 +27,7 @@ module ActionMCP
27
27
  @session = step(:validate_session, @task)
28
28
  return unless @session
29
29
 
30
- @tool = step(:prepare_tool, @session, tool_name, arguments)
30
+ @tool = step(:prepare_tool, @session, tool_name, arguments, @task)
31
31
  return unless @tool
32
32
 
33
33
  step(:execute_tool) do
@@ -60,7 +60,7 @@ module ActionMCP
60
60
  session
61
61
  end
62
62
 
63
- def prepare_tool(session, tool_name, arguments)
63
+ def prepare_tool(session, tool_name, arguments, task)
64
64
  tool_class = session.registered_tools.find { |t| t.tool_name == tool_name }
65
65
  unless tool_class
66
66
  @task.update(status_message: "Tool '#{tool_name}' not found")
@@ -76,6 +76,8 @@ module ActionMCP
76
76
  params: @task.request_params
77
77
  }
78
78
  })
79
+ # Enable report_progress! inside the tool during task-augmented runs
80
+ tool.instance_variable_set(:@_task, task)
79
81
 
80
82
  tool
81
83
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative "gem_version"
4
4
  module ActionMCP
5
- VERSION = "0.100.0"
5
+ VERSION = "0.100.1"
6
6
 
7
7
  class << self
8
8
  alias version gem_version
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionmcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.100.0
4
+ version: 0.100.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih