vector_mcp 0.1.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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +210 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/lib/vector_mcp/definitions.rb +81 -0
- data/lib/vector_mcp/errors.rb +138 -0
- data/lib/vector_mcp/handlers/core.rb +289 -0
- data/lib/vector_mcp/server.rb +521 -0
- data/lib/vector_mcp/session.rb +67 -0
- data/lib/vector_mcp/transport/sse.rb +663 -0
- data/lib/vector_mcp/transport/stdio.rb +258 -0
- data/lib/vector_mcp/util.rb +113 -0
- data/lib/vector_mcp/version.rb +6 -0
- data/lib/vector_mcp.rb +65 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f97bb6519db2c4d1b5e7cbac2a47954714aaa8e65f3cf797054c43cfc782255c
|
4
|
+
data.tar.gz: 5188e19bed4e4114729d6ea482361a0ad5adffddf0c400dd6081e7370037eb73
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 04af736a5887198f5d4d24e16d37689dce473872fc3a4c6448f0bdc8aaf49ff06a1f076827725978ad4f71f8a89906a9ab1dc336a91d2d176302a91a8726183d
|
7
|
+
data.tar.gz: 1386b745783db291622c0aec7b8108c966089e40c114b37386b2fc9e041df100ba19b927353edcac7ece880f0682cc8c37457e51e35d842936fef3dc4aa5447c
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 Sergio Bayona
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
# VectorMCP
|
2
|
+
|
3
|
+
<!-- Badges (Add URLs later) -->
|
4
|
+
[](https://badge.fury.io/rb/vector_mcp)
|
5
|
+
[](https://sergiobayona.github.io/vector_mcp/)
|
6
|
+
[](https://github.com/sergiobayona/vector_mcp/actions/workflows/ruby.yml)
|
7
|
+
[](https://qlty.sh/gh/sergiobayona/projects/vector_mcp)
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
9
|
+
|
10
|
+
VectorMCP provides server-side tools for implementing the [Model Context Protocol (MCP)](https://modelcontext.dev/) in Ruby applications. MCP is a specification for how Large Language Models (LLMs) can discover and interact with external tools, resources, and prompts provided by separate applications (MCP Servers).
|
11
|
+
|
12
|
+
This library allows you to easily create MCP servers that expose your application's capabilities (like functions, data sources, or predefined prompt templates) to compatible LLM clients (e.g., Claude Desktop App, custom clients).
|
13
|
+
|
14
|
+
## Features
|
15
|
+
|
16
|
+
* **MCP Specification Adherence:** Implements core server-side aspects of the MCP specification.
|
17
|
+
* **Tools:** Define and register custom tools (functions) that the LLM can invoke.
|
18
|
+
* **Resources:** Expose data sources (files, database results, API outputs) for the LLM to read.
|
19
|
+
* **Prompts:** Provide structured prompt templates the LLM can request and use.
|
20
|
+
* **Transport:**
|
21
|
+
* **Stdio (stable):** Simple transport using standard input/output, ideal for process-based servers.
|
22
|
+
* **SSE (work-in-progress):** Server-Sent Events support is under active development and currently unavailable.
|
23
|
+
* **Extensible Handlers:** Provides default handlers for core MCP methods, which can be overridden.
|
24
|
+
* **Clear Error Handling:** Custom error classes mapping to JSON-RPC/MCP error codes.
|
25
|
+
* **Ruby-like API:** Uses blocks for registering handlers, following idiomatic Ruby patterns.
|
26
|
+
|
27
|
+
## Installation
|
28
|
+
|
29
|
+
Add this line to your application's Gemfile:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
gem 'vector_mcp'
|
33
|
+
```
|
34
|
+
|
35
|
+
And then execute:
|
36
|
+
|
37
|
+
```bash
|
38
|
+
$ bundle install
|
39
|
+
```
|
40
|
+
|
41
|
+
Or install it yourself as:
|
42
|
+
|
43
|
+
```bash
|
44
|
+
$ gem install vector_mcp
|
45
|
+
```
|
46
|
+
|
47
|
+
> ⚠️ **Heads-up:** SSE transport is not yet supported in the released gem. When it lands it will require additional gems (`async`, `async-http`, `falcon`, `rack`).
|
48
|
+
|
49
|
+
## Quick Start
|
50
|
+
|
51
|
+
This example creates a simple server that runs over standard input/output and provides one tool.
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
require 'vector_mcp'
|
55
|
+
|
56
|
+
# Create a server
|
57
|
+
server = VectorMCP.new('Echo Server')
|
58
|
+
|
59
|
+
# Register a single "echo" tool
|
60
|
+
server.register_tool(
|
61
|
+
name: 'echo',
|
62
|
+
description: 'Returns whatever message you send.',
|
63
|
+
input_schema: {
|
64
|
+
type: 'object',
|
65
|
+
properties: { message: { type: 'string' } },
|
66
|
+
required: ['message']
|
67
|
+
}
|
68
|
+
) { |args, _session| args['message'] }
|
69
|
+
|
70
|
+
# Start listening on STDIN/STDOUT (default transport)
|
71
|
+
server.run
|
72
|
+
```
|
73
|
+
|
74
|
+
**To run this:**
|
75
|
+
|
76
|
+
1. Save it as `my_server.rb`.
|
77
|
+
2. Run `ruby my_server.rb`.
|
78
|
+
3. The server now waits for **newline-delimited JSON-RPC objects** on **STDIN** and writes responses to **STDOUT**.
|
79
|
+
|
80
|
+
You have two easy ways to talk to it:
|
81
|
+
|
82
|
+
**a. Interactive (paste a line, press Enter)**
|
83
|
+
|
84
|
+
```bash
|
85
|
+
$ ruby my_server.rb
|
86
|
+
# paste the JSON below, press ↵, observe the response
|
87
|
+
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}
|
88
|
+
{"jsonrpc":"2.0","method":"initialized"}
|
89
|
+
# etc.
|
90
|
+
```
|
91
|
+
|
92
|
+
**b. Scripted (pipe a series of echo / printf commands)**
|
93
|
+
|
94
|
+
```bash
|
95
|
+
{
|
96
|
+
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"CLI","version":"0.1"}}}';
|
97
|
+
printf '%s\n' '{"jsonrpc":"2.0","method":"initialized"}';
|
98
|
+
printf '%s\n' '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}';
|
99
|
+
printf '%s\n' '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"echo","arguments":{"message":"Hello VectorMCP!"}}}';
|
100
|
+
} | ruby my_server.rb | jq # jq formats the JSON responses
|
101
|
+
```
|
102
|
+
|
103
|
+
Each request **must be on a single line and terminated by a newline** so the server knows where the message ends.
|
104
|
+
|
105
|
+
Below are the same requests shown individually:
|
106
|
+
|
107
|
+
```jsonc
|
108
|
+
// 1. Initialize (client → server)
|
109
|
+
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"ManualClient","version":"0.1"}}}
|
110
|
+
|
111
|
+
// 2. Initialized notification (client → server, no id)
|
112
|
+
{"jsonrpc":"2.0","method":"initialized"}
|
113
|
+
|
114
|
+
// 3. List available tools (client → server)
|
115
|
+
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
|
116
|
+
|
117
|
+
// 4. Call the echo tool (client → server)
|
118
|
+
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"echo","arguments":{"message":"Hello VectorMCP!"}}}
|
119
|
+
```
|
120
|
+
|
121
|
+
## Usage
|
122
|
+
|
123
|
+
### Creating a Server
|
124
|
+
|
125
|
+
Instantiate the server using the factory method:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
require 'vector_mcp'
|
129
|
+
|
130
|
+
server = VectorMCP.new(
|
131
|
+
name: "MyAwesomeServer",
|
132
|
+
version: "2.1.0",
|
133
|
+
log_level: Logger::DEBUG # Optional: Default is INFO
|
134
|
+
)
|
135
|
+
```
|
136
|
+
|
137
|
+
### Registering Tools
|
138
|
+
|
139
|
+
Tools are functions your server exposes. Use `register_tool` with a block.
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
server.register_tool(
|
143
|
+
name: "calculate_sum",
|
144
|
+
description: "Adds two numbers together.",
|
145
|
+
input_schema: {
|
146
|
+
type: "object",
|
147
|
+
properties: {
|
148
|
+
a: { type: "number", description: "First number" },
|
149
|
+
b: { type: "number", description: "Second number" }
|
150
|
+
},
|
151
|
+
required: ["a", "b"]
|
152
|
+
}
|
153
|
+
) do |args, session|
|
154
|
+
# args is a hash like { "a" => 10, "b" => 5 }
|
155
|
+
# session object provides session context (e.g., session.initialized?)
|
156
|
+
sum = (args["a"] || 0) + (args["b"] || 0)
|
157
|
+
"The sum is: #{sum}" # Return value is converted to {type: "text", text: ...}
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
* The input_schema must be a Hash representing a valid JSON Schema object describing the tool's expected arguments.
|
162
|
+
* The block receives the arguments hash and the VectorMCP::Session object.
|
163
|
+
* The **session** object represents the client connection that invoked the tool. It lets you:
|
164
|
+
* Inspect the client's `clientInfo` and declared `capabilities` (e.g. `session.client_info['name']`).
|
165
|
+
* Store or look up per-connection state (authentication, rate-limiting, feature flags).
|
166
|
+
* Send follow-up notifications or streaming updates back only to that client.
|
167
|
+
* Check whether the session is already `initialized?` before doing expensive work.
|
168
|
+
|
169
|
+
Passing `session` up-front means tool authors can make use of this context today; if you don't need it, simply ignore the parameter (Ruby will accept extra block parameters).
|
170
|
+
* The block's return value is automatically converted into the MCP `content` array format by `VectorMCP::Util.convert_to_mcp_content`. You can return:
|
171
|
+
* A `String`: Becomes `{ type: 'text', text: '...' }`.
|
172
|
+
* A `Hash` matching the MCP content structure (`{ type: 'text', ... }`, `{ type: 'image', ... }`, etc.): Used as is.
|
173
|
+
* Other `Hash` objects: JSON-encoded into `{ type: 'text', text: '...', mimeType: 'application/json' }`.
|
174
|
+
* Binary String (`Encoding::ASCII_8BIT`): Base64-encoded into `{ type: 'blob', blob: '...', mimeType: 'application/octet-stream' }`.
|
175
|
+
* An `Array` of the above: Each element is converted and combined.
|
176
|
+
* Other objects: Converted using `to_s` into `{ type: 'text', text: '...' }`.
|
177
|
+
|
178
|
+
### Registering Resources
|
179
|
+
|
180
|
+
Resources provide data that the client can read.
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
server.register_resource(
|
184
|
+
uri: "memory://status", # Unique URI for this resource
|
185
|
+
name: "Server Status",
|
186
|
+
description: "Provides the current server status.",
|
187
|
+
mime_type: "application/json" # Optional: Defaults to text/plain
|
188
|
+
) do |session|
|
189
|
+
# Handler block receives the session object
|
190
|
+
{
|
191
|
+
status: "OK",
|
192
|
+
uptime: Time.now - server_start_time, # Example value
|
193
|
+
initialized: session.initialized?
|
194
|
+
} # Hash will be JSON encoded due to mime_type
|
195
|
+
end
|
196
|
+
|
197
|
+
# Resource returning binary data
|
198
|
+
server.register_resource(
|
199
|
+
uri: "file://logo.png",
|
200
|
+
name: "Logo Image",
|
201
|
+
description: "The server's logo.",
|
202
|
+
mime_type: "image/png"
|
203
|
+
) do |session|
|
204
|
+
# IMPORTANT: Return binary data as a string with ASCII-8BIT encoding
|
205
|
+
File.binread("path/to/logo.png")
|
206
|
+
end
|
207
|
+
```
|
208
|
+
|
209
|
+
* The block receives the `VectorMCP::Session` object.
|
210
|
+
* Return `String` for text, or a binary `
|
data/bin/console
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "vector_mcp"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
require "irb"
|
11
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
|
5
|
+
module VectorMCP
|
6
|
+
# This module contains Struct definitions for Tools, Resources, and Prompts
|
7
|
+
# that a VectorMCP::Server can provide.
|
8
|
+
module Definitions
|
9
|
+
# Represents a tool that can be executed by the AI model.
|
10
|
+
#
|
11
|
+
# @!attribute name [rw] String
|
12
|
+
# The unique name of the tool.
|
13
|
+
# @!attribute description [rw] String
|
14
|
+
# A human-readable description of what the tool does.
|
15
|
+
# @!attribute input_schema [rw] Hash
|
16
|
+
# A JSON Schema object describing the expected input for the tool.
|
17
|
+
# @!attribute handler [rw] Proc
|
18
|
+
# A callable (e.g., a Proc or lambda) that executes the tool's logic.
|
19
|
+
# It receives the tool input (a Hash) as its argument.
|
20
|
+
# The input hash structure should match the input_schema.
|
21
|
+
Tool = Struct.new(:name, :description, :input_schema, :handler) do
|
22
|
+
# Converts the tool to its MCP definition hash.
|
23
|
+
# @return [Hash] A hash representing the tool in MCP format.
|
24
|
+
def as_mcp_definition
|
25
|
+
{
|
26
|
+
name: name,
|
27
|
+
description: description,
|
28
|
+
inputSchema: input_schema # Expected to be a Hash representing JSON Schema
|
29
|
+
}.compact # Remove nil values
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Represents a resource (context or data) that can be provided to the AI model or user.
|
34
|
+
#
|
35
|
+
# @!attribute uri [rw] URI, String
|
36
|
+
# The unique URI identifying the resource.
|
37
|
+
# @!attribute name [rw] String
|
38
|
+
# A human-readable name for the resource.
|
39
|
+
# @!attribute description [rw] String
|
40
|
+
# A description of the resource content.
|
41
|
+
# @!attribute mime_type [rw] String
|
42
|
+
# The MIME type of the resource content (e.g., "text/plain", "application/json").
|
43
|
+
# @!attribute handler [rw] Proc
|
44
|
+
# A callable that returns the content of the resource. It may receive parameters from the request (e.g., for dynamic resources).
|
45
|
+
Resource = Struct.new(:uri, :name, :description, :mime_type, :handler) do
|
46
|
+
# Converts the resource to its MCP definition hash.
|
47
|
+
# @return [Hash] A hash representing the resource in MCP format.
|
48
|
+
def as_mcp_definition
|
49
|
+
{
|
50
|
+
uri: uri.to_s,
|
51
|
+
name: name,
|
52
|
+
description: description,
|
53
|
+
mimeType: mime_type
|
54
|
+
}.compact
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Represents a prompt or templated message workflow for users or AI models.
|
59
|
+
#
|
60
|
+
# @!attribute name [rw] String
|
61
|
+
# The unique name of the prompt.
|
62
|
+
# @!attribute description [rw] String
|
63
|
+
# A human-readable description of the prompt.
|
64
|
+
# @!attribute arguments [rw] Array<Hash>
|
65
|
+
# An array of argument definitions for the prompt, where each hash can contain
|
66
|
+
# `:name`, `:description`, and `:required` (Boolean).
|
67
|
+
# @!attribute handler [rw] Proc
|
68
|
+
# A callable that generates the prompt content. It receives a hash of arguments, validated against the prompt's argument definitions.
|
69
|
+
Prompt = Struct.new(:name, :description, :arguments, :handler) do
|
70
|
+
# Converts the prompt to its MCP definition hash.
|
71
|
+
# @return [Hash] A hash representing the prompt in MCP format.
|
72
|
+
def as_mcp_definition
|
73
|
+
{
|
74
|
+
name: name,
|
75
|
+
description: description,
|
76
|
+
arguments: arguments # Expected to be an array of { name:, description:, required: } hashes
|
77
|
+
}.compact
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VectorMCP
|
4
|
+
# Base error class for all VectorMCP specific errors.
|
5
|
+
class Error < StandardError; end
|
6
|
+
|
7
|
+
# Base class for **all** JSON-RPC 2.0 errors that the VectorMCP library can
|
8
|
+
# emit. It mirrors the structure defined by the JSON-RPC spec and adds a
|
9
|
+
# flexible `details` field that implementers may use to attach structured,
|
10
|
+
# implementation-specific metadata to an error payload.
|
11
|
+
#
|
12
|
+
# @!attribute [r] code
|
13
|
+
# @return [Integer] The JSON-RPC error code.
|
14
|
+
# @!attribute [r] message
|
15
|
+
# @return [String] A short description of the error.
|
16
|
+
# @!attribute [rw] request_id
|
17
|
+
# @return [String, Integer, nil] The ID of the request that caused this error, if applicable.
|
18
|
+
# @!attribute [r] details
|
19
|
+
# @return [Hash, nil] Additional implementation-specific details for the error (optional).
|
20
|
+
class ProtocolError < Error
|
21
|
+
attr_accessor :request_id
|
22
|
+
attr_reader :code, :message, :details
|
23
|
+
|
24
|
+
# Initializes a new ProtocolError.
|
25
|
+
#
|
26
|
+
# @param message [String] The error message.
|
27
|
+
# @param code [Integer] The JSON-RPC error code.
|
28
|
+
# @param details [Hash, nil] Additional details for the error (optional).
|
29
|
+
# @param request_id [String, Integer, nil] The ID of the originating request.
|
30
|
+
def initialize(message, code: -32_600, details: nil, request_id: nil)
|
31
|
+
VectorMCP.logger.debug("Initializing ProtocolError with code: #{code}")
|
32
|
+
@code = code
|
33
|
+
@message = message
|
34
|
+
@details = details # NOTE: `data` in JSON-RPC is often used for this purpose.
|
35
|
+
@request_id = request_id
|
36
|
+
super(message)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Standard JSON-RPC error classes
|
41
|
+
|
42
|
+
# Represents a JSON-RPC Parse error (-32700).
|
43
|
+
# Indicates invalid JSON was received by the server.
|
44
|
+
class ParseError < ProtocolError
|
45
|
+
# @param message [String] The error message.
|
46
|
+
# @param details [Hash, nil] Additional details for the error (optional).
|
47
|
+
# @param request_id [String, Integer, nil] The ID of the originating request.
|
48
|
+
def initialize(message = "Parse error", details: nil, request_id: nil)
|
49
|
+
super(message, code: -32_700, details: details, request_id: request_id)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Represents a JSON-RPC Invalid Request error (-32600).
|
54
|
+
# Indicates the JSON sent is not a valid Request object.
|
55
|
+
class InvalidRequestError < ProtocolError
|
56
|
+
# @param message [String] The error message.
|
57
|
+
# @param details [Hash, nil] Additional details for the error (optional).
|
58
|
+
# @param request_id [String, Integer, nil] The ID of the originating request.
|
59
|
+
def initialize(message = "Invalid Request", details: nil, request_id: nil)
|
60
|
+
super(message, code: -32_600, details: details, request_id: request_id)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Represents a JSON-RPC Method Not Found error (-32601).
|
65
|
+
# Indicates the method does not exist or is not available.
|
66
|
+
class MethodNotFoundError < ProtocolError
|
67
|
+
# @param method [String] The name of the method that was not found.
|
68
|
+
# @param details [Hash, nil] Additional details for the error (optional).
|
69
|
+
# @param request_id [String, Integer, nil] The ID of the originating request.
|
70
|
+
def initialize(method, details: nil, request_id: nil)
|
71
|
+
details ||= { method_name: method }
|
72
|
+
super("Method not found: #{method}", code: -32_601, details: details, request_id: request_id)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Represents a JSON-RPC Invalid Params error (-32602).
|
77
|
+
# Indicates invalid method parameter(s).
|
78
|
+
class InvalidParamsError < ProtocolError
|
79
|
+
# @param message [String] The error message.
|
80
|
+
# @param details [Hash, nil] Additional details for the error (optional).
|
81
|
+
# @param request_id [String, Integer, nil] The ID of the originating request.
|
82
|
+
def initialize(message = "Invalid params", details: nil, request_id: nil)
|
83
|
+
super(message, code: -32_602, details: details, request_id: request_id)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Represents a JSON-RPC Internal error (-32603).
|
88
|
+
# Indicates an internal error in the JSON-RPC server.
|
89
|
+
class InternalError < ProtocolError
|
90
|
+
# @param message [String] The error message.
|
91
|
+
# @param details [Hash, nil] Additional details for the error (optional).
|
92
|
+
# @param request_id [String, Integer, nil] The ID of the originating request.
|
93
|
+
def initialize(message = "Internal error", details: nil, request_id: nil)
|
94
|
+
super(message, code: -32_603, details: details, request_id: request_id)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Represents a JSON-RPC server-defined error (codes -32000 to -32099).
|
99
|
+
class ServerError < ProtocolError
|
100
|
+
# @param message [String] The error message.
|
101
|
+
# @param code [Integer] The server-defined error code. Must be between -32099 and -32000. If the
|
102
|
+
# supplied value falls outside this range it will be coerced to **-32000** in order to comply
|
103
|
+
# with the JSON-RPC 2.0 specification.
|
104
|
+
# @param details [Hash, nil] Additional details for the error (optional).
|
105
|
+
# @param request_id [String, Integer, nil] The ID of the originating request.
|
106
|
+
def initialize(message = "Server error", code: -32_000, details: nil, request_id: nil)
|
107
|
+
VectorMCP.logger.debug("Initializing ServerError with code: #{code}")
|
108
|
+
unless (-32_099..-32_000).cover?(code)
|
109
|
+
warn "Server error code #{code} is outside of the reserved range (-32099 to -32000). Using -32000 instead."
|
110
|
+
code = -32_000
|
111
|
+
end
|
112
|
+
super
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Represents an error indicating a request was received before server initialization completed (-32002).
|
117
|
+
class InitializationError < ServerError
|
118
|
+
# @param message [String] The error message.
|
119
|
+
# @param details [Hash, nil] Additional details for the error (optional).
|
120
|
+
# @param request_id [String, Integer, nil] The ID of the originating request.
|
121
|
+
def initialize(message = "Server not initialized", details: nil, request_id: nil)
|
122
|
+
super(message, code: -32_002, details: details, request_id: request_id)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Represents an error indicating a requested resource or entity was not found (-32001).
|
127
|
+
# Note: This uses a code typically outside the strict JSON-RPC server error range,
|
128
|
+
# but is common in practice for "Not Found" scenarios.
|
129
|
+
class NotFoundError < ProtocolError
|
130
|
+
# @param message [String] The error message.
|
131
|
+
# @param details [Hash, nil] Additional details for the error (optional).
|
132
|
+
# @param request_id [String, Integer, nil] The ID of the originating request.
|
133
|
+
def initialize(message = "Not Found", details: nil, request_id: nil)
|
134
|
+
VectorMCP.logger.debug("Initializing NotFoundError with code: -32001")
|
135
|
+
super(message, code: -32_001, details: details, request_id: request_id)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|