hub_kernel-mcp 0.3.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 921598b05d30bf9e211477dbc575f7e59a8cde2487bdaa935e13242c7a80b5e7
4
- data.tar.gz: d3e4111ecee2b448bee1120f7f9653b06c31bfd50d6a5143d622626fe42e7cc5
3
+ metadata.gz: 90fe375e57411dd604b4bbcd46776ba7d3f64b829ab6d79c5ad9b0de4a14c1cd
4
+ data.tar.gz: eefdf79205bb8a4b8a5be1ec171dc4eac15316bede5f3ad3069efe3f1a2301d0
5
5
  SHA512:
6
- metadata.gz: eeb8295b220d5cdc288ba99e991eeced8e0e5be262d7052a95715a4703e886ddb5db31f2369234a093fd2858ff08e89a2910a388c531121710058f09fbd83612
7
- data.tar.gz: 73f9ce82ab316a2dbf92b912ba0676f871d311975b4f297c7cdb8a0e263c722c954c53705a23a779038494e7a1b2e48a1ffea254389c6ff2f64c0c8e1e624446
6
+ metadata.gz: 2d964c38b18504184297666e94174507baf671c754dfd131b428be747efb337574e32292c331c7f23908edbc9a11dd44e46414a0e141c1d41a9e9d04e043c24c
7
+ data.tar.gz: 6a98d684583139acc2ace28041202f55f59d19cc06ec894dbd5929101502fecdd91b8904aa356a56690e2a609d9637df0c0bf61232bcd7db194b42ff2e314044
data/README.md CHANGED
@@ -21,9 +21,16 @@ serves:
21
21
  ```ruby
22
22
  Rails.application.config.to_prepare do
23
23
  HubKernel::Interface.hubs = [ Supplies, { "money" => Billing::Ledger } ]
24
+ HubKernel::Mcp.check!
24
25
  end
25
26
  ```
26
27
 
28
+ `HubKernel::Mcp.check!` raises `HubKernel::Mcp::UnservableHubError` naming every problem
29
+ in one error. It names each problem hub_kernel-interface's own check finds in the served
30
+ list, a served name holding two underscores in a row, and a tool whose name holds a
31
+ character other than a letter, a digit, an underscore or a hyphen or is longer than 64
32
+ characters. Inside `to_prepare` it runs again after every code reload.
33
+
27
34
  Mount the engine:
28
35
 
29
36
  ```ruby
@@ -58,10 +65,13 @@ give, and returns the method's answer as JSON text:
58
65
  { "content": [ { "type": "text", "text": "\"soap costs 3\"" } ], "isError": false }
59
66
  ```
60
67
 
61
- A hub's refusal, or a value the method requires and the call left out, comes back as a tool
62
- error carrying the reason, with `isError` set. A tool the caller may not call, a tool that does
63
- not exist, and a tool naming a hub the host does not serve are all answered with the same
64
- JSON-RPC error, code -32602, `Unknown tool: <name>`.
68
+ A hub's refusal, a value the method requires and the call left out, a value the method is not
69
+ listed with, and a record the call names that does not exist each come back as a tool error
70
+ carrying the reason, with `isError` set. The last two reasons come from hub_kernel-interface, so
71
+ they read the same in every interface gem, such as `price_of does not take colour` and
72
+ `No item has the id 9`. A tool the caller may not call, a tool that does not exist, and a tool
73
+ naming a hub the host does not serve are all answered with the same JSON-RPC error, code
74
+ -32602, `Unknown tool: <name>`, whatever values the call sends.
65
75
 
66
76
  A caller the host's sign-in refuses is refused before any hub is asked.
67
77
 
@@ -38,12 +38,18 @@ module HubKernel
38
38
  def called
39
39
  served_name, method_name = tool_name.split("__", 2)
40
40
  hub = HubKernel::Interface.find(served_name) || raise(UnknownTool)
41
+ raise UnknownTool unless hub.exposed(method_name)
42
+ HubKernel::Interface::CallReasons.refuse_unlisted_values(hub, method_name, values: arguments, person: caller_person, account: caller_account)
41
43
  answer = hub.call_exposed(method_name, values: arguments, person: caller_person, account: caller_account)
42
44
  { content: [ { type: "text", text: answer.to_json } ], isError: false }
43
45
  rescue HubKernel::Refused, HubKernel::MissingArgumentError => refusal
44
- { content: [ { type: "text", text: refusal.message } ], isError: true }
46
+ tool_error(refusal.message)
47
+ rescue ActiveRecord::RecordNotFound => missing
48
+ tool_error(HubKernel::Interface::CallReasons.missing_record(missing))
45
49
  end
46
50
 
51
+ def tool_error(reason) = { content: [ { type: "text", text: reason } ], isError: true }
52
+
47
53
  def tool_name = params.dig(:params, :name).to_s
48
54
 
49
55
  def arguments = params.dig(:params, :arguments)&.to_unsafe_h.to_h.deep_symbolize_keys
@@ -1,5 +1,5 @@
1
1
  module HubKernel
2
2
  module Mcp
3
- VERSION = "0.3.0"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
@@ -4,8 +4,46 @@ require "hub_kernel/mcp/engine"
4
4
 
5
5
  module HubKernel
6
6
  module Mcp
7
+ UnservableHubError = HubKernel::Interface::UnservableHubError
8
+
7
9
  mattr_accessor :base_controller, default: "ActionController::API"
8
10
  mattr_accessor :person_method
9
11
  mattr_accessor :account_method
12
+
13
+ def self.check!
14
+ problems = shared_problems + doubled_underscores + unlisted_characters + long_names
15
+ raise UnservableHubError, problems.join("\n") if problems.any?
16
+ end
17
+
18
+ def self.shared_problems
19
+ HubKernel::Interface.check!
20
+ []
21
+ rescue UnservableHubError => error
22
+ error.message.split("\n")
23
+ end
24
+
25
+ def self.doubled_underscores
26
+ HubKernel::Interface.served.select { |name, _hub| name.include?("__") }.map do |name, hub|
27
+ "#{hub.name} is served at #{name}, which holds two underscores in a row"
28
+ end
29
+ end
30
+
31
+ def self.unlisted_characters
32
+ tool_names.grep_v(/\A[A-Za-z0-9_-]*\z/).map do |name|
33
+ "The tool #{name} holds a character other than a letter, a digit, an underscore or a hyphen"
34
+ end
35
+ end
36
+
37
+ def self.long_names
38
+ tool_names.select { |name| name.length > 64 }.map { |name| "The tool #{name} is longer than 64 characters" }
39
+ end
40
+
41
+ def self.tool_names
42
+ HubKernel::Interface.served.select { |_name, hub| hub.respond_to?(:exposures) }.flat_map do |served_name, hub|
43
+ hub.exposures.map { |exposure| "#{served_name}__#{exposure.name}" }
44
+ end
45
+ end
46
+
47
+ private_class_method :shared_problems, :doubled_underscores, :unlisted_characters, :long_names, :tool_names
10
48
  end
11
49
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hub_kernel-mcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tylercschneider
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '0.3'
32
+ version: '0.6'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '0.3'
39
+ version: '0.6'
40
40
  description: hub_kernel-mcp serves the methods every hub a host serves exposes as
41
41
  MCP tools at one address, with every call going through the host's sign-in, permission
42
42
  check and account scope.