spree_mcp 6.0.2 → 6.0.3
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/lib/spree/mcp/server.rb +21 -1
- data/lib/spree/mcp/tool_adapter.rb +22 -32
- metadata +8 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 38b6ba2f07815f146329db7be4d30c9f9c29190842c14370f014a17de3ea848d
|
|
4
|
+
data.tar.gz: 03747b1df8ed398e5270fecf40cc95299c36ce4dc871858518a9d32619e6c09c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 33197fbccf535cf54d96da786657eccfe56b7bfde60d1d85b49817f320726b4c7462aceb4d798638c50e4f751da7978648356c5ffe4b1ef6522cd8981bac65a7
|
|
7
|
+
data.tar.gz: ab0d70fff092c0fa0fa3129e6af285d53e623e81681d38553b1cca0db8be5f07ae556c94dfea2abe576dc6a883bd457b5cf19dc76cc6ef9b225dbcc6b38c853a
|
data/lib/spree/mcp/server.rb
CHANGED
|
@@ -9,6 +9,22 @@ module Spree
|
|
|
9
9
|
# request) is not what mounts this. An ordinary admin API controller does,
|
|
10
10
|
# and hands the JSON-RPC message to {MCP::Server#handle_json}.
|
|
11
11
|
module Server
|
|
12
|
+
# The protocol server, plus the 6.0.0 tool names kept callable through
|
|
13
|
+
# 6.0.x. They answer `tools/call` but are not in `tools/list`: a client
|
|
14
|
+
# that learned one keeps working, and a new one is shown only the
|
|
15
|
+
# current names. The gem lists `@tools` and looks a call up through
|
|
16
|
+
# `#tools`, so an unknown name is resolved there, only when called.
|
|
17
|
+
class AdminServer < ::MCP::Server
|
|
18
|
+
# @param resolver [#call] name => MCP tool class, or nil
|
|
19
|
+
attr_writer :resolver
|
|
20
|
+
|
|
21
|
+
def tools
|
|
22
|
+
resolver = @resolver
|
|
23
|
+
lookup = Hash.new { |_tools, name| resolver&.call(name) }
|
|
24
|
+
lookup.merge!(super)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
12
28
|
# What the model is told about using this server at discovery, so it
|
|
13
29
|
# reaches for the discovery tools before guessing at names and filters.
|
|
14
30
|
INSTRUCTIONS = <<~TEXT.freeze
|
|
@@ -47,7 +63,7 @@ module Spree
|
|
|
47
63
|
# @param context [Spree::AgentTools::Context] who is asking, and where
|
|
48
64
|
# @return [MCP::Server]
|
|
49
65
|
def for(context)
|
|
50
|
-
server =
|
|
66
|
+
server = AdminServer.new(
|
|
51
67
|
name: 'spree-admin',
|
|
52
68
|
title: "#{context.store.name} (Spree admin)",
|
|
53
69
|
version: Spree.version,
|
|
@@ -56,6 +72,10 @@ module Spree
|
|
|
56
72
|
server_context: { store_id: context.store.id }
|
|
57
73
|
)
|
|
58
74
|
|
|
75
|
+
server.resolver = lambda do |name|
|
|
76
|
+
tool = Spree.admin_agent_tools.find_for(name, context)
|
|
77
|
+
ToolAdapter.build(tool) if tool
|
|
78
|
+
end
|
|
59
79
|
register_resources(server, context)
|
|
60
80
|
server
|
|
61
81
|
end
|
|
@@ -24,36 +24,35 @@ module Spree
|
|
|
24
24
|
) { |**arguments| adapter.respond(tool, arguments) }
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
# The tool's
|
|
27
|
+
# The tool's arguments as the gem's schema object, built once per tool
|
|
28
|
+
# class. Building one deep-copies and validates the schema, and an
|
|
29
|
+
# action tool's schema is a whole request body: done on every request
|
|
30
|
+
# for every tool, it was most of what answering `tools/list` cost.
|
|
31
|
+
# Keyed weakly by the tool class, so a class replaced on a code reload
|
|
32
|
+
# is let go with its schema.
|
|
28
33
|
#
|
|
29
34
|
# @param tool [Spree::AgentTool]
|
|
30
|
-
# @return [
|
|
35
|
+
# @return [MCP::Tool::InputSchema]
|
|
31
36
|
def input_schema(tool)
|
|
32
|
-
|
|
33
|
-
property = { type: json_type(options[:type]) }
|
|
34
|
-
property[:description] = options[:description] if options[:description].present?
|
|
35
|
-
# An array must say what it holds: a client validating arguments
|
|
36
|
-
# against the schema refuses the call otherwise.
|
|
37
|
-
property[:items] = { type: json_type(options[:items] || :string) } if property[:type] == 'array'
|
|
38
|
-
|
|
39
|
-
[name.to_s, property]
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
{
|
|
43
|
-
type: 'object',
|
|
44
|
-
properties: properties,
|
|
45
|
-
required: tool.params.select { |_name, options| options[:required] }.keys.map(&:to_s)
|
|
46
|
-
}
|
|
37
|
+
schemas[tool.class] ||= ::MCP::Tool::InputSchema.new(tool.class.input_schema)
|
|
47
38
|
end
|
|
48
39
|
|
|
49
40
|
# Clients that gate confirmation on annotations rather than on a
|
|
50
|
-
# server's word need
|
|
51
|
-
# `destructiveHint` to true, so a
|
|
52
|
-
# confirmed like a deletion.
|
|
41
|
+
# server's word need every hint set explicitly: the protocol defaults
|
|
42
|
+
# `destructiveHint` and `openWorldHint` to true, so a tool that says
|
|
43
|
+
# nothing would be confirmed like a deletion that leaves the store.
|
|
44
|
+
# Every write runs the same workflow the dashboard does, which can
|
|
45
|
+
# email, charge a gateway or fire webhooks, so writes are open-world
|
|
46
|
+
# and reads are not.
|
|
53
47
|
#
|
|
54
48
|
# @return [Hash]
|
|
55
49
|
def annotations(tool)
|
|
56
|
-
{
|
|
50
|
+
{
|
|
51
|
+
read_only_hint: !tool.mutating?,
|
|
52
|
+
destructive_hint: tool.destructive?,
|
|
53
|
+
idempotent_hint: !tool.mutating?,
|
|
54
|
+
open_world_hint: tool.mutating?
|
|
55
|
+
}
|
|
57
56
|
end
|
|
58
57
|
|
|
59
58
|
# A tool answers with a plain hash. A hash carrying `:error` is the
|
|
@@ -88,17 +87,8 @@ module Spree
|
|
|
88
87
|
|
|
89
88
|
private
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def json_type(type)
|
|
94
|
-
case type&.to_sym
|
|
95
|
-
when :boolean then 'boolean'
|
|
96
|
-
when :integer then 'integer'
|
|
97
|
-
when :number, :float, :decimal then 'number'
|
|
98
|
-
when :object, :hash then 'object'
|
|
99
|
-
when :array then 'array'
|
|
100
|
-
else 'string'
|
|
101
|
-
end
|
|
90
|
+
def schemas
|
|
91
|
+
@schemas ||= ObjectSpace::WeakKeyMap.new
|
|
102
92
|
end
|
|
103
93
|
|
|
104
94
|
# A line the client can show beside its confirmation prompt, and the
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_mcp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.0.
|
|
4
|
+
version: 6.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vendo Connect Inc.
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2026-11-
|
|
12
|
+
date: 2026-11-05 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: spree_core
|
|
@@ -17,28 +17,28 @@ dependencies:
|
|
|
17
17
|
requirements:
|
|
18
18
|
- - '='
|
|
19
19
|
- !ruby/object:Gem::Version
|
|
20
|
-
version: 6.0.
|
|
20
|
+
version: 6.0.3
|
|
21
21
|
type: :runtime
|
|
22
22
|
prerelease: false
|
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
|
24
24
|
requirements:
|
|
25
25
|
- - '='
|
|
26
26
|
- !ruby/object:Gem::Version
|
|
27
|
-
version: 6.0.
|
|
27
|
+
version: 6.0.3
|
|
28
28
|
- !ruby/object:Gem::Dependency
|
|
29
29
|
name: spree_api
|
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
|
31
31
|
requirements:
|
|
32
32
|
- - '='
|
|
33
33
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: 6.0.
|
|
34
|
+
version: 6.0.3
|
|
35
35
|
type: :runtime
|
|
36
36
|
prerelease: false
|
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
|
38
38
|
requirements:
|
|
39
39
|
- - '='
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
|
-
version: 6.0.
|
|
41
|
+
version: 6.0.3
|
|
42
42
|
- !ruby/object:Gem::Dependency
|
|
43
43
|
name: mcp
|
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -76,9 +76,9 @@ licenses:
|
|
|
76
76
|
- MIT
|
|
77
77
|
metadata:
|
|
78
78
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
|
79
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v6.0.
|
|
79
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v6.0.3
|
|
80
80
|
documentation_uri: https://spreecommerce.org/docs/
|
|
81
|
-
source_code_uri: https://github.com/spree/spree/tree/v6.0.
|
|
81
|
+
source_code_uri: https://github.com/spree/spree/tree/v6.0.3
|
|
82
82
|
post_install_message:
|
|
83
83
|
rdoc_options: []
|
|
84
84
|
require_paths:
|