toolchest 0.3.5 → 0.3.7

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: db7d29ec671adac8f24512bf3d190dedb55250dfd846b31c5906feac16771130
4
- data.tar.gz: a3c7414f1c60e5997942fdacfa70ee3a368e6a0cd2b237eab2b1d187351cb10d
3
+ metadata.gz: 4ee7ad9222681a140d6978cbe7f9f8ffccbc87409f8fc67b361625049fa1d7fa
4
+ data.tar.gz: de305206530622d0e29ad038e5de13fb872ca7758a25e4266271240463077909
5
5
  SHA512:
6
- metadata.gz: 68779c02c513ba5dc8052407a015de6fddda8e44c5aa6add4daeb204eb08fe7b41b997a6a2791e90b62ab1dc558d467d3ad722cbee5baca32fccbe7a04692203
7
- data.tar.gz: d63e96b09cdf89b09a31e902b593f55b4399ab347c5af3daa033c50c03054c654e0338fe2f9eb31544f19522e65bb1c30f9181c33a040e14a2c26dbf91b5371c
6
+ metadata.gz: 3f6945c51b3a496589c4f0f5f582b7582b59a3d2b4e422bece7b3c81f40ec3e56e6994860dd6a018d09851c8a80b2437179c4a2d155160b5440a0e6fe01a42a0
7
+ data.tar.gz: 274c31289b34696fb6f8b7c5469ebe9d627d94880aa57b9b7fd1834f0eca9706078a75e64917198bb966f153f18547fddb276f4ffd6151a5cb2fa8732e3b147e
data/LLMS.txt CHANGED
@@ -374,6 +374,9 @@ config.required_scopes = ["orders:read"] # always granted, can't uncheck
374
374
  config.allowed_scopes_for do |user, requested| # per-user gating (default: show all)
375
375
  user.admin? ? requested : requested - ["admin:write"]
376
376
  end
377
+ config.authorize_link do |user| # block user from linking (OAuth only, default: allow all)
378
+ !user.banned?
379
+ end
377
380
  ```
378
381
 
379
382
  ## Resources and prompts
data/README.md CHANGED
@@ -523,10 +523,23 @@ config.required_scopes = ["orders:read"]
523
523
  config.allowed_scopes_for do |user, requested_scopes|
524
524
  user.admin? ? requested_scopes : requested_scopes - ["admin:write"]
525
525
  end
526
+
526
527
  ```
527
528
 
528
529
  Scopes hidden by `allowed_scopes_for` never appear on the consent screen and can't be granted even if the POST is tampered with.
529
530
 
531
+ ### Blocking users from linking
532
+
533
+ Gate who can link an MCP client to their account with `authorize_link`. If it returns falsy, the user is redirected with `access_denied` before they ever see a consent screen.
534
+
535
+ ```ruby
536
+ config.authorize_link do |user|
537
+ !user.banned?
538
+ end
539
+ ```
540
+
541
+ Only applies when using `auth: :oauth`. For `auth: :token` or custom strategies, gate access in your own authentication layer.
542
+
530
543
  ## Multi-mount
531
544
 
532
545
  Separate MCP endpoints, different auth, different toolboxes:
@@ -11,6 +11,16 @@ module Toolchest
11
11
  @optional = toolchest_config.optional_scopes
12
12
  @original_scope = requested_scopes.join(" ")
13
13
 
14
+ unless toolchest_config.authorize_link?(@current_resource_owner)
15
+ redirect_url = build_redirect(params[:redirect_uri],
16
+ error: "access_denied",
17
+ error_description: "User is not authorized to connect",
18
+ state: params[:state]
19
+ )
20
+ redirect_to redirect_url, allow_other_host: true
21
+ return
22
+ end
23
+
14
24
  requested = requested_scopes
15
25
  allowed = toolchest_config.resolve_allowed_scopes(@current_resource_owner, requested)
16
26
  known = toolchest_config.scopes.keys
@@ -36,6 +46,16 @@ module Toolchest
36
46
 
37
47
  # POST /mcp/oauth/authorize — approve and redirect with code
38
48
  def create
49
+ unless toolchest_config.authorize_link?(@current_resource_owner)
50
+ redirect_url = build_redirect(params[:redirect_uri],
51
+ error: "access_denied",
52
+ error_description: "User is not authorized to connect",
53
+ state: params[:state]
54
+ )
55
+ redirect_to redirect_url, allow_other_host: true
56
+ return
57
+ end
58
+
39
59
  requested = original_requested_scopes
40
60
  allowed = toolchest_config.resolve_allowed_scopes(@current_resource_owner, requested)
41
61
  known = toolchest_config.scopes.keys
@@ -37,14 +37,9 @@ module Toolchest
37
37
  # Returns [mount_path, config] or renders 404 and returns [nil, nil].
38
38
  def resolve_mount
39
39
  if params[:rest].present?
40
- # Suffixed path (RFC 8414) — must match a configured mount exactly.
41
40
  path = "/#{params[:rest]}"
42
41
  key = Toolchest.mount_keys.find { |k| Toolchest.configuration(k).mount_path == path }
43
- unless key
44
- head :not_found
45
- return [nil, nil]
46
- end
47
- return [path, Toolchest.configuration(key)]
42
+ return [path, Toolchest.configuration(key)] if key
48
43
  end
49
44
 
50
45
  # No suffix (e.g. Cursor). Use default_oauth_mount if set.
@@ -19,7 +19,7 @@ module Toolchest
19
19
  end
20
20
  end
21
21
 
22
- def create_migration
22
+ def copy_migration
23
23
  case strategy
24
24
  when "token"
25
25
  migration_template "create_toolchest_tokens.rb.tt",
data/lib/toolchest/app.rb CHANGED
@@ -17,6 +17,12 @@ module Toolchest
17
17
  def call(env)
18
18
  Engine.ensure_initialized!
19
19
  env["toolchest.mount_key"] = @mount_key.to_s
20
+
21
+ cfg = Toolchest.configuration(@mount_key)
22
+ if cfg.mount_path.nil? && env["SCRIPT_NAME"].present?
23
+ cfg.mount_path = env["SCRIPT_NAME"]
24
+ end
25
+
20
26
  @router.call(env)
21
27
  end
22
28
 
@@ -23,6 +23,7 @@ module Toolchest
23
23
  @optional_scopes = false
24
24
  @required_scopes = []
25
25
  @allowed_scopes_for_block = nil
26
+ @authorize_link_block = nil
26
27
  @additional_view_paths = []
27
28
  @access_token_expires_in = 7200
28
29
  @toolboxes = nil
@@ -52,6 +53,19 @@ module Toolchest
52
53
  @authenticate_block.call(token)
53
54
  end
54
55
 
56
+ def authorize_link(&block)
57
+ if block
58
+ @authorize_link_block = block
59
+ else
60
+ @authorize_link_block
61
+ end
62
+ end
63
+
64
+ def authorize_link?(user)
65
+ return true unless @authorize_link_block
66
+ @authorize_link_block.call(user)
67
+ end
68
+
55
69
  def allowed_scopes_for(&block)
56
70
  if block
57
71
  @allowed_scopes_for_block = block
@@ -1,3 +1,3 @@
1
1
  module Toolchest
2
- VERSION = "0.3.5"
2
+ VERSION = "0.3.7"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toolchest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nora