actionmcp 0.103.0 → 0.104.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: 0b98e5c438f85bfe710dbe07d1b9cc2a12d7347b4fc200c66a0492f380615599
4
- data.tar.gz: 921adb81f040f14533248ce6c52b142a85d8445299e19a83501171b344601c11
3
+ metadata.gz: 6cfb5ce2385d840e5a70a47707ff2a684b2b1129ab19e55869832cff57286619
4
+ data.tar.gz: aedeccd60db4263d29eee4da2d051d5910978c50951765dc7ec6b83cb1c2c6c9
5
5
  SHA512:
6
- metadata.gz: 9aee10304fc9e926a34805c760545adb565b5a19dd7fe59e445ed938d82b2e92e9e7d8e5762db2a5dfc12a844fdbbfb9b84ed7a15f2879703fe7c83b6eb29ec2
7
- data.tar.gz: 4b35888139f56c100415e64f495e61efcd43eac2652bf99b1dfbf1ae269fb317d19fad9f0a1ee99b8a19d1e2a36dd3d1818d4ff76a67456f7e9c7edc21457fb7
6
+ metadata.gz: c6fe8f1b667633f25e566df67f6c8da36d652ef993eb568b8c73b23fd46bb85c3c096560b91c62056bc00325fd1daa23aba789d960697007b5d28881ce02d292
7
+ data.tar.gz: dc9a41f5f340b09e11c551d64857239501341602731136686f508e3f8fa22558e9f10392941887c20f2ae6cbd7f1174d87fa4b371142e90bcbd3e0bfe8b90353
data/README.md CHANGED
@@ -470,6 +470,12 @@ module Tron
470
470
  config.action_mcp.version = "1.2.3" # defaults to "0.0.1"
471
471
  config.action_mcp.logging_enabled = true # defaults to true
472
472
  config.action_mcp.logging_level = :info # defaults to :info, can be :debug, :info, :warn, :error, :fatal
473
+
474
+ # Server instructions - helps LLMs understand the server's purpose
475
+ config.action_mcp.server_instructions = [
476
+ "Use this server to access and control Tron system programs",
477
+ "Helpful for managing system processes and user data"
478
+ ]
473
479
  end
474
480
  end
475
481
  ```
@@ -521,6 +527,35 @@ production:
521
527
  max_queue: 500 # Maximum number of tasks that can be queued
522
528
  ```
523
529
 
530
+ ### Server Instructions
531
+
532
+ Server instructions help LLMs understand **what your server is for** and **when to use it**. They describe the server's purpose and goal, not technical details like rate limits or authentication (tools are self-documented via their own descriptions).
533
+
534
+ Instructions are returned at the top level of the MCP initialization response.
535
+
536
+ You can configure server instructions in your `config/mcp.yml` file:
537
+
538
+ ```yaml
539
+ shared:
540
+ # Describe the server's purpose - helps LLMs know when to use this server
541
+ server_instructions:
542
+ - "Use this server to manage Fizzy project tickets and workflows"
543
+ - "Helpful for tracking bugs, features, and sprint planning"
544
+
545
+ development:
546
+ # Development-specific purpose description
547
+ server_instructions:
548
+ - "Development server for testing Fizzy integration"
549
+ - "Use for prototyping ticket management workflows"
550
+
551
+ production:
552
+ # Production-specific purpose description
553
+ server_instructions:
554
+ - "Production Fizzy server for managing live project data"
555
+ ```
556
+
557
+ Instructions are sent as a single string (joined by newlines) at the top level of the initialization response, helping LLMs understand your server's purpose.
558
+
524
559
  #### SolidMCP (Database-backed, Recommended)
525
560
 
526
561
  For SolidMCP, add it to your Gemfile:
@@ -140,11 +140,15 @@ module ActionMCP
140
140
  end
141
141
 
142
142
  def server_capabilities_payload
143
- {
143
+ payload = {
144
144
  protocolVersion: protocol_version || ActionMCP::DEFAULT_PROTOCOL_VERSION,
145
145
  serverInfo: server_info,
146
146
  capabilities: server_capabilities
147
147
  }
148
+ # Add instructions at top level if configured
149
+ instructions = ActionMCP.configuration.instructions
150
+ payload[:instructions] = instructions if instructions
151
+ payload
148
152
  end
149
153
 
150
154
  def server_capabilities
@@ -359,10 +363,7 @@ module ActionMCP
359
363
 
360
364
  # This will keep the version and name of the server when this session was created
361
365
  def set_server_info
362
- self.server_info = {
363
- name: ActionMCP.configuration.name,
364
- version: ActionMCP.configuration.version
365
- }
366
+ self.server_info = ActionMCP.configuration.server_info
366
367
  end
367
368
 
368
369
  # This can be overridden by the application in future versions
@@ -49,7 +49,9 @@ module ActionMCP
49
49
  :tasks_list_enabled,
50
50
  :tasks_cancel_enabled,
51
51
  # --- Schema Validation Options ---
52
- :validate_structured_content
52
+ :validate_structured_content,
53
+ # --- Allowed identity keys for gateway ---
54
+ :allowed_identity_keys
53
55
 
54
56
  def initialize
55
57
  @logging_enabled = false
@@ -74,6 +76,9 @@ module ActionMCP
74
76
  # Schema validation - disabled by default for backward compatibility
75
77
  @validate_structured_content = false
76
78
 
79
+ # Server instructions - empty by default
80
+ @server_instructions = []
81
+
77
82
  # Gateway - resolved lazily to account for Zeitwerk autoloading
78
83
  @gateway_class_name = nil
79
84
 
@@ -81,6 +86,11 @@ module ActionMCP
81
86
  @session_store_type = Rails.env.production? ? :active_record : :volatile
82
87
  @client_session_store_type = nil # defaults to session_store_type
83
88
  @server_session_store_type = nil # defaults to session_store_type
89
+
90
+ # Whitelist of allowed identity attribute names to prevent method shadowing
91
+ # and unauthorized attribute assignment. Extend this list if you use custom
92
+ # identifier names in your GatewayIdentifier implementations.
93
+ @allowed_identity_keys = %w[user api_key jwt bearer token account session].freeze
84
94
  end
85
95
 
86
96
  def name
@@ -91,6 +101,34 @@ module ActionMCP
91
101
  @version || (has_rails_version ? Rails.application.version.to_s : "0.0.1")
92
102
  end
93
103
 
104
+ # Server information (name and version only)
105
+ def server_info
106
+ {
107
+ name: name,
108
+ version: version
109
+ }
110
+ end
111
+
112
+ # Instructions for LLMs about the server's purpose (joined as string for MCP payload)
113
+ def instructions
114
+ return nil if server_instructions.nil? || server_instructions.empty?
115
+
116
+ server_instructions.join("\n")
117
+ end
118
+
119
+ # Custom getter/setter to ensure array elements are strings
120
+ def server_instructions
121
+ @server_instructions
122
+ end
123
+
124
+ def server_instructions=(value)
125
+ @server_instructions = parse_instructions(value)
126
+ end
127
+
128
+ def allowed_identity_keys=(value)
129
+ @allowed_identity_keys = Array(value).map(&:to_s).freeze
130
+ end
131
+
94
132
  def gateway_class
95
133
  # Resolve gateway class lazily to account for Zeitwerk autoloading
96
134
  # This allows ApplicationGateway to be loaded from app/mcp even if the
@@ -343,9 +381,14 @@ module ActionMCP
343
381
  @client_session_store_type = config["client_session_store_type"].to_sym
344
382
  end
345
383
 
346
- return unless config["server_session_store_type"]
384
+ if config["server_session_store_type"]
385
+ @server_session_store_type = config["server_session_store_type"].to_sym
386
+ end
347
387
 
348
- @server_session_store_type = config["server_session_store_type"].to_sym
388
+ # Extract server instructions
389
+ if config["server_instructions"]
390
+ @server_instructions = parse_instructions(config["server_instructions"])
391
+ end
349
392
  end
350
393
 
351
394
  def should_include_all?(type)
@@ -364,6 +407,10 @@ module ActionMCP
364
407
  false
365
408
  end
366
409
 
410
+ def parse_instructions(instructions)
411
+ Array(instructions).map(&:to_s)
412
+ end
413
+
367
414
  def ensure_mcp_components_loaded
368
415
  # Only load if we haven't loaded yet - but in development, always reload
369
416
  return if @mcp_components_loaded && !Rails.env.development?
@@ -4,11 +4,6 @@ module ActionMCP
4
4
  class UnauthorizedError < StandardError; end
5
5
 
6
6
  class Gateway
7
- # Whitelist of allowed identity attribute names to prevent method shadowing
8
- # and unauthorized attribute assignment. Extend this list if you use custom
9
- # identifier names in your GatewayIdentifier implementations.
10
- ALLOWED_IDENTITY_KEYS = %w[user api_key jwt bearer token account session].freeze
11
-
12
7
  class << self
13
8
  # pluck in one or many GatewayIdentifier classes
14
9
  def identified_by(*klasses)
@@ -78,9 +73,9 @@ module ActionMCP
78
73
  name_str = name.to_s
79
74
 
80
75
  # Validate identity key against whitelist to prevent method shadowing
81
- unless ALLOWED_IDENTITY_KEYS.include?(name_str)
76
+ unless allowed_identity_keys.include?(name_str)
82
77
  raise ArgumentError, "Invalid identity key: '#{name_str}'. " \
83
- "Allowed keys: #{ALLOWED_IDENTITY_KEYS.join(', ')}"
78
+ "Allowed keys: #{allowed_identity_keys.join(', ')}"
84
79
  end
85
80
 
86
81
  # define accessor on the fly
@@ -114,5 +109,9 @@ module ActionMCP
114
109
  def apply_profile_from_authentication(identities)
115
110
  # Default: do nothing. Override in subclass if you want profile switching.
116
111
  end
112
+
113
+ def allowed_identity_keys
114
+ ActionMCP.configuration.allowed_identity_keys
115
+ end
117
116
  end
118
117
  end
@@ -128,11 +128,15 @@ module ActionMCP
128
128
 
129
129
  # Capability methods
130
130
  def server_capabilities_payload
131
- {
131
+ payload = {
132
132
  protocolVersion: ActionMCP::LATEST_VERSION,
133
133
  serverInfo: server_info,
134
134
  capabilities: server_capabilities
135
135
  }
136
+ # Add instructions at top level if configured
137
+ instructions = ActionMCP.configuration.instructions
138
+ payload[:instructions] = instructions if instructions
139
+ payload
136
140
  end
137
141
 
138
142
  def set_protocol_version(version)
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative "gem_version"
4
4
  module ActionMCP
5
- VERSION = "0.103.0"
5
+ VERSION = "0.104.1"
6
6
 
7
7
  class << self
8
8
  alias version gem_version
@@ -22,14 +22,14 @@ class <%= class_name %> < ActionMCP::GatewayIdentifier
22
22
  private
23
23
 
24
24
  # Add any custom helper methods here
25
- #
25
+ #
26
26
  # Example helper methods:
27
- #
27
+ #
28
28
  # def extract_credentials_from_request
29
29
  # # Custom extraction logic
30
30
  # end
31
- #
31
+ #
32
32
  # def validate_credentials(credentials)
33
33
  # # Custom validation logic
34
34
  # end
35
- end
35
+ end
@@ -16,6 +16,11 @@ shared:
16
16
  # Server-specific session store type (falls back to session_store_type if not specified)
17
17
  # server_session_store_type: active_record
18
18
 
19
+ # Server instructions - helps LLMs understand the server's purpose
20
+ # Describe what the server is for, not technical details (tools are self-documented)
21
+ # server_instructions:
22
+ # - "Use this server to manage project tickets and workflows"
23
+ # - "Helpful for tracking bugs, features, and sprint planning"
19
24
 
20
25
  # MCP capability profiles
21
26
  profiles:
@@ -46,6 +51,11 @@ development:
46
51
  # Use simple pub/sub adapter for development
47
52
  adapter: simple
48
53
 
54
+ # Development-specific purpose description
55
+ # server_instructions:
56
+ # - "Development server for testing your MCP integration"
57
+ # - "Use for prototyping and experimenting with tools"
58
+
49
59
  # Session store examples for development
50
60
  # Use volatile client sessions for faster development
51
61
  # client_session_store_type: volatile
@@ -106,4 +116,4 @@ production:
106
116
  # channel_prefix: my_mcp_app_production
107
117
  # min_threads: 10 # Minimum number of threads in the pool
108
118
  # max_threads: 20 # Maximum number of threads in the pool
109
- # max_queue: 500 # Maximum number of tasks that can be queued
119
+ # max_queue: 500 # Maximum number of tasks that can be queued
@@ -34,12 +34,12 @@ class <%= class_name %> < ApplicationMCPTool
34
34
 
35
35
  # Uncomment to allow additional properties beyond those defined above:
36
36
  # additional_properties true # Allow any additional properties
37
- # additional_properties false # Explicitly disallow additional properties
37
+ # additional_properties false # Explicitly disallow additional properties
38
38
  # additional_properties({"type" => "string"}) # Allow additional properties but restrict to strings
39
39
 
40
40
  def perform
41
41
  render(text: "Processing <%= properties.map { |p| p[:name] }.join(', ') %>")
42
-
42
+
43
43
  # If additional_properties is enabled, you can access extra parameters:
44
44
  # extra_params = additional_params
45
45
  # extra_params.each do |key, value|
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.103.0
4
+ version: 0.104.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih