mcp-inspector 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1d4704c72568b86082e74cc0c70052fec7e4a4d6e31b0f8fad00e42e76af5b63
4
+ data.tar.gz: fcb8bba16641850e3af1720ff8d9111a7c94ad325e5f063afc9685760bec8590
5
+ SHA512:
6
+ metadata.gz: 896468351dee78dc3402113c403b80c92dcfa9388c90bce33b27835e31cd95a544efc36c1e70d0496390bb2009a085438ff92e6dcd85975e4b80e1a212cd58d4
7
+ data.tar.gz: 3ae68d16805d58016150e1fdfc02cf48cf80a7b2080fbc73bcf8c038539759ea52146782503168e33fbbdbda454bfc0d7cda9ae8a1f84100aa3bd14d6ad1c179
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/README.md ADDED
@@ -0,0 +1,261 @@
1
+ # MCP Inspector
2
+
3
+ A Ruby gem that provides a command-line tool for connecting to and inspecting MCP (Model Context Protocol) servers. The tool allows you to list and execute tools, read resources, and get prompts from MCP servers with JSON output by default.
4
+
5
+ ## Features
6
+
7
+ - **Multi-transport support**: Connect to MCP servers via stdio, SSE, or WebSocket
8
+ - **Command-based CLI**: Execute operations without persistent sessions
9
+ - **JSON configuration**: Configure multiple servers in a single JSON file
10
+ - **Structured output**: All output in JSON format for easy parsing and automation
11
+ - **Three-layer architecture**: Designed for future web adaptation
12
+
13
+ ## Installation
14
+
15
+ Install the gem by executing:
16
+
17
+ ```bash
18
+ gem install mcp-inspector
19
+ ```
20
+
21
+ Or add it to your Gemfile:
22
+
23
+ ```ruby
24
+ gem 'mcp-inspector'
25
+ ```
26
+
27
+ Then execute:
28
+
29
+ ```bash
30
+ bundle install
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ 1. **Create a configuration file:**
36
+
37
+ ```bash
38
+ mcp-inspector config init
39
+ ```
40
+
41
+ This creates `~/.mcp-inspector.json` with example server configurations.
42
+
43
+ 2. **List available servers:**
44
+
45
+ ```bash
46
+ mcp-inspector config list
47
+ ```
48
+
49
+ 3. **List tools from a server:**
50
+
51
+ ```bash
52
+ mcp-inspector list tools --server filesystem-server
53
+ ```
54
+
55
+ 4. **Execute a tool:**
56
+
57
+ ```bash
58
+ mcp-inspector execute read_file --server filesystem-server --args '{"path": "/tmp/test.txt"}'
59
+ ```
60
+
61
+ ## Configuration
62
+
63
+ The tool looks for configuration files in this order:
64
+
65
+ 1. Custom path via `--config` flag
66
+ 2. `./.mcp-inspector.json` (project config)
67
+ 3. `~/.mcp-inspector.json` (user config)
68
+
69
+ ### Configuration Format
70
+
71
+ ```json
72
+ {
73
+ "servers": [
74
+ {
75
+ "name": "filesystem-server",
76
+ "transport": "stdio",
77
+ "command": ["npx", "-y", "@modelcontextprotocol/server-filesystem"],
78
+ "args": ["/tmp"],
79
+ "env": {}
80
+ },
81
+ {
82
+ "name": "github-server",
83
+ "transport": "stdio",
84
+ "command": ["npx", "-y", "@modelcontextprotocol/server-github"],
85
+ "env": {
86
+ "GITHUB_TOKEN": "${GITHUB_TOKEN}"
87
+ }
88
+ },
89
+ {
90
+ "name": "http-server",
91
+ "transport": "sse",
92
+ "url": "http://localhost:8080/sse"
93
+ }
94
+ ],
95
+ "defaults": {
96
+ "output": "json",
97
+ "pretty": true
98
+ }
99
+ }
100
+ ```
101
+
102
+ ### Transport Types
103
+
104
+ - **stdio**: Run a command and communicate via stdin/stdout
105
+ - **sse**: Connect to Server-Sent Events endpoint
106
+ - **websocket**: Connect to WebSocket endpoint
107
+
108
+ ## Usage
109
+
110
+ ### Global Options
111
+
112
+ - `--config PATH`: Path to config file
113
+ - `--server NAME`: Server name from config (required)
114
+ - `--output FORMAT`: Output format (json)
115
+ - `--pretty`: Pretty print output (default: true)
116
+ - `--no-pretty`: Disable pretty printing
117
+
118
+ ### Commands
119
+
120
+ #### List Resources
121
+
122
+ ```bash
123
+ # List all tools
124
+ mcp-inspector list tools --server myserver
125
+
126
+ # List all resources
127
+ mcp-inspector list resources --server myserver
128
+
129
+ # List all prompts
130
+ mcp-inspector list prompts --server myserver
131
+ ```
132
+
133
+ #### Execute Operations
134
+
135
+ ```bash
136
+ # Execute a tool
137
+ mcp-inspector execute tool_name --server myserver --args '{"key": "value"}'
138
+
139
+ # Read a resource
140
+ mcp-inspector read file:///path/to/file --server myserver
141
+
142
+ # Get a prompt
143
+ mcp-inspector prompt prompt_name --server myserver --args '{"key": "value"}'
144
+ ```
145
+
146
+ #### Server Information
147
+
148
+ ```bash
149
+ # Show server info and capabilities
150
+ mcp-inspector info --server myserver
151
+ ```
152
+
153
+ #### Configuration Management
154
+
155
+ ```bash
156
+ # List configured servers
157
+ mcp-inspector config list
158
+
159
+ # Show server configuration
160
+ mcp-inspector config show myserver
161
+
162
+ # Create example config file
163
+ mcp-inspector config init [path]
164
+ ```
165
+
166
+ ### Output Format
167
+
168
+ All commands return JSON with a consistent structure:
169
+
170
+ ```json
171
+ {
172
+ "status": "success",
173
+ "data": {
174
+ "tools": [...],
175
+ "count": 3
176
+ },
177
+ "metadata": {
178
+ "operation": "list_tools",
179
+ "server": "filesystem-server",
180
+ "timestamp": "2024-01-01T12:00:00Z"
181
+ }
182
+ }
183
+ ```
184
+
185
+ Error responses:
186
+
187
+ ```json
188
+ {
189
+ "status": "error",
190
+ "error": {
191
+ "type": "ConnectionError",
192
+ "message": "Failed to connect to server"
193
+ },
194
+ "metadata": {
195
+ "operation": "list_tools",
196
+ "server": "filesystem-server",
197
+ "timestamp": "2024-01-01T12:00:00Z"
198
+ }
199
+ }
200
+ ```
201
+
202
+ ## Examples
203
+
204
+ ### Filesystem Server
205
+
206
+ ```bash
207
+ # List files in a directory
208
+ mcp-inspector list tools --server filesystem-server
209
+
210
+ # Read a file
211
+ mcp-inspector execute read_file --server filesystem-server --args '{"path": "/tmp/example.txt"}'
212
+
213
+ # Write to a file
214
+ mcp-inspector execute write_file --server filesystem-server --args '{"path": "/tmp/output.txt", "content": "Hello World"}'
215
+ ```
216
+
217
+ ### GitHub Server
218
+
219
+ ```bash
220
+ # List repository information
221
+ mcp-inspector list resources --server github-server
222
+
223
+ # Search repositories
224
+ mcp-inspector execute search_repositories --server github-server --args '{"query": "ruby mcp"}'
225
+ ```
226
+
227
+ ## Architecture
228
+
229
+ The gem uses a three-layer architecture:
230
+
231
+ 1. **Transport Layer**: Handles connections to MCP servers
232
+ 2. **Data Layer**: Manages configuration and input/output processing
233
+ 3. **Presentation Layer**: Formats output for display
234
+
235
+ This design makes it easy to add new output formats or adapt for web interfaces in the future.
236
+
237
+ ## Development
238
+
239
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
240
+
241
+ To install this gem onto your local machine, run `bundle exec rake install`.
242
+
243
+ ### Running Tests
244
+
245
+ ```bash
246
+ bundle exec rspec
247
+ ```
248
+
249
+ ### Building the Gem
250
+
251
+ ```bash
252
+ gem build mcp-inspector.gemspec
253
+ ```
254
+
255
+ ## Contributing
256
+
257
+ Bug reports and pull requests are welcome on GitHub at https://github.com/anthropics/mcp-inspector.
258
+
259
+ ## License
260
+
261
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,28 @@
1
+ {
2
+ "servers": [
3
+ {
4
+ "name": "filesystem-server",
5
+ "transport": "stdio",
6
+ "command": ["npx", "-y", "@modelcontextprotocol/server-filesystem"],
7
+ "args": ["/tmp"],
8
+ "env": {}
9
+ },
10
+ {
11
+ "name": "github-server",
12
+ "transport": "stdio",
13
+ "command": ["npx", "-y", "@modelcontextprotocol/server-github"],
14
+ "env": {
15
+ "GITHUB_TOKEN": "${GITHUB_TOKEN}"
16
+ }
17
+ },
18
+ {
19
+ "name": "http-server",
20
+ "transport": "sse",
21
+ "url": "http://localhost:8080/sse"
22
+ }
23
+ ],
24
+ "defaults": {
25
+ "output": "json",
26
+ "pretty": true
27
+ }
28
+ }
data/exe/mcp-inspector ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../lib/mcp_inspector"
5
+
6
+ begin
7
+ MCPInspector::CLI.start(ARGV)
8
+ rescue Interrupt
9
+ puts "\nInterrupted"
10
+ exit(130)
11
+ rescue => e
12
+ warn "Error: #{e.message}"
13
+ exit(1)
14
+ end
@@ -0,0 +1,257 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require_relative "data/config_manager"
5
+ require_relative "data/input_adapter"
6
+ require_relative "data/output_adapter"
7
+ require_relative "transport/base_adapter"
8
+ require_relative "transport/client_adapter"
9
+ require_relative "transport/server_config"
10
+ require_relative "presentation/base_formatter"
11
+ require_relative "presentation/json_formatter"
12
+
13
+ module MCPInspector
14
+ class CLI < Thor
15
+ class << self
16
+ def exit_on_failure?
17
+ true
18
+ end
19
+ end
20
+
21
+ class_option :config, type: :string, desc: "Path to config file"
22
+ class_option :server, type: :string, desc: "Server name from config"
23
+ class_option :output, type: :string, default: "json", desc: "Output format (json)"
24
+ class_option :pretty, type: :boolean, default: true, desc: "Pretty print output"
25
+ class_option :no_pretty, type: :boolean, desc: "Disable pretty printing"
26
+
27
+ def initialize(args = [], local_options = {}, config = {})
28
+ super
29
+ setup_global_options
30
+ end
31
+
32
+ desc "list TYPE", "List MCP server resources (tools, resources, prompts)"
33
+ def list(type)
34
+ case type
35
+ when "tools"
36
+ list_tools
37
+ when "resources"
38
+ list_resources
39
+ when "prompts"
40
+ list_prompts
41
+ else
42
+ warn "Invalid list type '#{type}'. Valid options: tools, resources, prompts"
43
+ exit(1)
44
+ end
45
+ end
46
+
47
+ desc "execute TOOL_NAME", "Execute a tool on the MCP server"
48
+ option :args, type: :string, desc: "JSON arguments for the tool", default: "{}"
49
+ def execute(tool_name)
50
+ with_server_connection do |adapter, output_adapter|
51
+ input_adapter = MCPInspector::Data::InputAdapter.new
52
+ input_adapter.validate_tool_name!(tool_name)
53
+
54
+ arguments = input_adapter.parse_json_arguments(options[:args])
55
+ result = adapter.execute_tool(tool_name, arguments)
56
+
57
+ metadata = build_metadata("execute_tool", tool_name)
58
+ output_adapter.output_tool_result(result, metadata)
59
+ end
60
+ rescue => e
61
+ handle_error(e)
62
+ end
63
+
64
+ desc "read RESOURCE_URI", "Read a resource from the MCP server"
65
+ def read(resource_uri)
66
+ with_server_connection do |adapter, output_adapter|
67
+ input_adapter = MCPInspector::Data::InputAdapter.new
68
+ input_adapter.validate_resource_uri!(resource_uri)
69
+
70
+ content = adapter.read_resource(resource_uri)
71
+
72
+ metadata = build_metadata("read_resource", resource_uri)
73
+ output_adapter.output_resource_content(content, metadata)
74
+ end
75
+ rescue => e
76
+ handle_error(e)
77
+ end
78
+
79
+ desc "prompt PROMPT_NAME", "Get a prompt from the MCP server"
80
+ option :args, type: :string, desc: "JSON arguments for the prompt", default: "{}"
81
+ def prompt(prompt_name)
82
+ with_server_connection do |adapter, output_adapter|
83
+ input_adapter = MCPInspector::Data::InputAdapter.new
84
+ input_adapter.validate_prompt_name!(prompt_name)
85
+
86
+ arguments = input_adapter.parse_json_arguments(options[:args])
87
+ result = adapter.get_prompt(prompt_name, arguments)
88
+
89
+ metadata = build_metadata("get_prompt", prompt_name)
90
+ output_adapter.output_prompt_result(result, metadata)
91
+ end
92
+ rescue => e
93
+ handle_error(e)
94
+ end
95
+
96
+ desc "info", "Show server connection details and capabilities"
97
+ def info
98
+ with_server_connection do |adapter, output_adapter|
99
+ server_info = adapter.server_info
100
+
101
+ metadata = build_metadata("server_info")
102
+ output_adapter.output_server_info(server_info, metadata)
103
+ end
104
+ rescue => e
105
+ handle_error(e)
106
+ end
107
+
108
+ desc "config ACTION [NAME]", "Manage configuration (list, show SERVER_NAME, init [PATH])"
109
+ def config(action, name_or_path = nil)
110
+ case action
111
+ when "list"
112
+ config_list
113
+ when "show"
114
+ config_show(name_or_path)
115
+ when "init"
116
+ config_init(name_or_path)
117
+ else
118
+ warn "Invalid config action '#{action}'. Valid options: list, show, init"
119
+ exit(1)
120
+ end
121
+ end
122
+
123
+ private
124
+
125
+ def setup_global_options
126
+ # Handle --no-pretty flag
127
+ if options[:no_pretty]
128
+ @pretty_print = false
129
+ else
130
+ @pretty_print = options.fetch(:pretty, true)
131
+ end
132
+ end
133
+
134
+ def with_server_connection
135
+ ensure_server_specified!
136
+ config_manager = load_config_manager
137
+ server_config = config_manager.find_server(options[:server])
138
+
139
+ adapter = MCPInspector::Transport::ClientAdapter.new
140
+ output_adapter = create_output_adapter
141
+
142
+ begin
143
+ adapter.connect(server_config)
144
+ yield adapter, output_adapter
145
+ ensure
146
+ adapter.disconnect if adapter.connected?
147
+ end
148
+ end
149
+
150
+ def load_config_manager
151
+ MCPInspector::Data::ConfigManager.new(config_path: options[:config])
152
+ rescue MCPInspector::Data::ConfigManager::ConfigError => e
153
+ if e.message.include?("No configuration file found")
154
+ suggest_config_creation
155
+ end
156
+ raise
157
+ end
158
+
159
+ def suggest_config_creation
160
+ warn "Tip: Create a configuration file with:"
161
+ warn " mcp-inspector config init"
162
+ end
163
+
164
+ def create_output_adapter
165
+ MCPInspector::Data::OutputAdapter.new(
166
+ format: options[:output],
167
+ pretty: @pretty_print
168
+ )
169
+ end
170
+
171
+ def build_metadata(operation, target = nil)
172
+ metadata = {
173
+ operation: operation,
174
+ server: options[:server]
175
+ }
176
+
177
+ metadata[:target] = target if target
178
+ metadata
179
+ end
180
+
181
+ def handle_error(error)
182
+ output_adapter = create_output_adapter
183
+ metadata = build_metadata("error")
184
+ output_adapter.output_error(error, metadata)
185
+ exit(1)
186
+ end
187
+
188
+ def ensure_server_specified!
189
+ unless options[:server]
190
+ warn "Error: --server option is required for this command"
191
+ exit(1)
192
+ end
193
+ end
194
+
195
+ def list_tools
196
+ with_server_connection do |adapter, output_adapter|
197
+ tools = adapter.list_tools
198
+
199
+ metadata = build_metadata("list_tools")
200
+ output_adapter.output_tools_list(tools, metadata)
201
+ end
202
+ end
203
+
204
+ def list_resources
205
+ with_server_connection do |adapter, output_adapter|
206
+ resources = adapter.list_resources
207
+
208
+ metadata = build_metadata("list_resources")
209
+ output_adapter.output_resources_list(resources, metadata)
210
+ end
211
+ end
212
+
213
+ def list_prompts
214
+ with_server_connection do |adapter, output_adapter|
215
+ prompts = adapter.list_prompts
216
+
217
+ metadata = build_metadata("list_prompts")
218
+ output_adapter.output_prompts_list(prompts, metadata)
219
+ end
220
+ end
221
+
222
+ def config_list
223
+ config_manager = load_config_manager
224
+ output_adapter = create_output_adapter
225
+
226
+ metadata = build_metadata("config_list")
227
+ output_adapter.output_config_list(config_manager.servers, metadata)
228
+ end
229
+
230
+ def config_show(server_name)
231
+ unless server_name
232
+ warn "Server name is required for 'config show'"
233
+ exit(1)
234
+ end
235
+
236
+ config_manager = load_config_manager
237
+ server_config = config_manager.find_server(server_name)
238
+ output_adapter = create_output_adapter
239
+
240
+ metadata = build_metadata("config_show", server_name)
241
+ output_adapter.output_config_details(server_config, metadata)
242
+ end
243
+
244
+ def config_init(path = nil)
245
+ path ||= MCPInspector::Data::ConfigManager::DEFAULT_USER_CONFIG_PATH
246
+
247
+ if File.exist?(path)
248
+ warn "Configuration file already exists: #{path}"
249
+ exit(1)
250
+ end
251
+
252
+ created_path = MCPInspector::Data::ConfigManager.create_example_config(path)
253
+ puts "Created example configuration file: #{created_path}"
254
+ puts "Edit this file to configure your MCP servers."
255
+ end
256
+ end
257
+ end