Skip to content

Add instructions support to MCP::Server #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,11 @@ You can use the `Server#handle_json` method to handle requests.

```ruby
class ApplicationController < ActionController::Base

def index
server = MCP::Server.new(
name: "my_server",
version: "1.0.0",
instructions: "A simple MCP server with custom tools and prompts",
tools: [SomeTool, AnotherTool],
prompts: [MyPrompt],
server_context: { user_id: current_user.id },
Expand Down
12 changes: 10 additions & 2 deletions lib/mcp/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ def initialize(method_name)

include Instrumentation

attr_accessor :name, :version, :tools, :prompts, :resources, :server_context, :configuration, :capabilities, :transport
attr_accessor :name, :version, :instructions, :tools, :prompts, :resources, :server_context, :configuration, :capabilities, :transport

def initialize(
name: "model_context_protocol",
version: DEFAULT_VERSION,
instructions: nil,
tools: [],
prompts: [],
resources: [],
Expand All @@ -47,13 +48,19 @@ def initialize(
)
@name = name
@version = version
@instructions = instructions
@tools = tools.to_h { |t| [t.name_value, t] }
@prompts = prompts.to_h { |p| [p.name_value, p] }
@resources = resources
@resource_templates = resource_templates
@resource_index = index_resources_by_uri(resources)
@server_context = server_context
@configuration = MCP.configuration.merge(configuration)
if @configuration.protocol_version == "2024-11-05" && @instructions
message = "`instructions` supported by protocol version 2025-03-26 or higher"
raise ArgumentError, message
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If accepting the instructions parameter with the older "2024-11-05" protocol version is considered preferable, this logic could be removed as it only introduces unnecessary complexity.


@capabilities = capabilities || default_capabilities

@handlers = {
Expand Down Expand Up @@ -218,7 +225,8 @@ def init(request)
protocolVersion: configuration.protocol_version,
capabilities: capabilities,
serverInfo: server_info,
}
instructions: instructions,
}.compact
end

def list_tools(request)
Expand Down
29 changes: 29 additions & 0 deletions test/mcp/server_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ServerTest < ActiveSupport::TestCase
@server = Server.new(
name: @server_name,
version: "1.2.3",
instructions: "Optional instructions for the client",
tools: [@tool, @tool_that_raises],
prompts: [@prompt],
resources: [@resource],
Expand Down Expand Up @@ -124,6 +125,7 @@ class ServerTest < ActiveSupport::TestCase
name: @server_name,
version: "1.2.3",
},
instructions: "Optional instructions for the client",
},
}

Expand Down Expand Up @@ -739,6 +741,33 @@ def call(message:, server_context: nil)
assert_equal Server::DEFAULT_VERSION, response[:result][:serverInfo][:version]
end

test "server uses instructions when not configured" do
server = Server.new(name: "test_server")
request = {
jsonrpc: "2.0",
method: "initialize",
id: 1,
}

response = server.handle(request)
refute response[:result].key?(:instructions)
end

test "server uses instructions when configured with protocol version 2025-03-26" do
configuration = Configuration.new(protocol_version: "2025-03-26")
server = Server.new(name: "test_server", instructions: "The server instructions.", configuration: configuration)
assert_equal("The server instructions.", server.instructions)
end

test "raises error if instructions are used with protocol version 2024-11-05" do
configuration = Configuration.new(protocol_version: "2024-11-05")

exception = assert_raises(ArgumentError) do
Server.new(name: "test_server", instructions: "The server instructions.", configuration: configuration)
end
assert_equal("`instructions` supported by protocol version 2025-03-26 or higher", exception.message)
end

test "#define_tool adds a tool to the server" do
@server.define_tool(
name: "defined_tool",
Expand Down