aia 0.9.21 → 0.9.23

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: 2d974eb8f23ef8b3af71447951101047c7bdf04a203d4690655b8bfbe940fb2f
4
- data.tar.gz: d63ff74f8837d642a454e116e2efb29f5a57d2d3e37a0e1181378d93d15f4660
3
+ metadata.gz: 38ae30b2341fb1e96738601b0c7cac5459772217d005aa5e22f18ecde270e2e0
4
+ data.tar.gz: 34555fad44d99436b4171887c0804c88f88e6fdc572e8a2d05476f485b0b80c6
5
5
  SHA512:
6
- metadata.gz: 1c20c13f8d2c80abcc1dafc0401d6bfb3c1c1045ff4dc0821b3de256ba59241938a076f0cb74583758e1bbadd2e31cd933a2137440eee1a78e4adea794e66ea6
7
- data.tar.gz: f7b6d1301362e22ccb3ef07956f5a9fe3766504ec23a2df82b420ab330b2e628406a1ce98b43dced48ab4142d49ccc5f7737f6fef0e9c9bded5d4ecda8626c8a
6
+ metadata.gz: 67182004edf9443ad3fc9190c1d57daa18c8f997d0425fa642e6f4c0c94d74490a1943ae1f79e7b18f55f65c0237a8fba31e765b750c374c8885926cbc08ca62
7
+ data.tar.gz: 3a86c4b7734a955180e7282a5462f7cda7ff83d1eac49c7106e63a69eaf9554a318ef2195ef61c4a61aec2340be6fdac8d19fd0d6a681f450e6c6c55b7c02940
data/.version CHANGED
@@ -1 +1 @@
1
- 0.9.21
1
+ 0.9.23
data/CHANGELOG.md CHANGED
@@ -1,6 +1,55 @@
1
1
  # Changelog
2
2
  ## [Unreleased]
3
3
 
4
+ ## [0.9.23] 2025-12-06
5
+
6
+ ### New Features
7
+ - **MCP Server Configuration**: Added native support for defining MCP (Model Context Protocol) servers in the config file
8
+ - Configure MCP servers in `~/.aia/config.yml` under the `mcp_servers` key
9
+ - Supports `name`, `command`, `args`, `env`, and `timeout` options per server
10
+ - Automatic PATH resolution for commands (no absolute paths required)
11
+ - Configurable timeouts for slow-starting servers (default: 8000ms)
12
+ - Environment variable support for MCP server processes
13
+
14
+ ### Improvements
15
+ - **Robot Display**: Added MCP server names to the robot ASCII art display
16
+ - Shows "MCP: server1, server2, ..." when MCP servers are configured
17
+
18
+ ### Technical Changes
19
+ - Added `load_mcp_servers` method to `lib/aia/config/base.rb` for automatic MCP client registration
20
+ - Added `resolve_command_path` method for PATH-based command resolution
21
+ - Added `mcp_servers?` and `mcp_server_names` helper methods to `lib/aia/utility.rb`
22
+ - Fixed `OpenStruct.merge` to skip nil values, preventing config file values from being overwritten
23
+ - Added `mcp_servers: nil` default to prevent merge issues with empty arrays
24
+
25
+ ### Configuration Example
26
+ ```yaml
27
+ # ~/.aia/config.yml
28
+ :mcp_servers:
29
+ - name: "my-server"
30
+ command: "my_mcp_server.rb"
31
+ args: ["stdio"]
32
+ timeout: 30000
33
+ env:
34
+ MY_VAR: "value"
35
+ ```
36
+
37
+ ## [0.9.22] 2025-11-12
38
+
39
+ ### Bug Fixes
40
+ - **TEST SUITE**: Fixed all Mocha test isolation issues causing stub contamination between tests
41
+ - Added proper teardown methods with `super` calls to 13 test files to ensure Mocha cleanup
42
+ - Fixed PromptHandlerTest missing teardown and config fields (erb, shell, roles_dir)
43
+ - Fixed ModelsDirectiveTest to use consistent stubbing approach instead of mixing real and stubbed config
44
+ - Fixed MultiModelIsolationTest to use stubs instead of direct instance variable manipulation
45
+ - Fixed AIAIntegrationTest, ChatProcessorServiceTest, ContextManagerTest, DirectiveProcessorTest, RubyLLMAdapterTest, SessionTest, LocalProvidersTest, UtilityTest, AIAMockingTest, and AIAPropertyBasedTest to include proper Mocha cleanup
46
+ - Test results improved from 2 failures, 2 errors to 0 failures, 0 errors (325 runs, 1018 assertions)
47
+
48
+ ### Technical Changes
49
+ - Enhanced test isolation by ensuring all tests using Mocha stubs properly clean up via `super` in teardown
50
+ - Standardized stub usage pattern across test suite for consistency
51
+ - Eliminated stub leakage that caused "unexpected invocation" and "AIA was instantiated in one test but receiving invocations in another" errors
52
+
4
53
  ## [0.9.21] 2025-10-08
5
54
  ### Bug Fixes
6
55
  - **Checkpoint Directive Output**: Fixed `//checkpoint` directive to return empty string instead of status message (lib/aia/directives/configuration.rb:155)
data/README.md CHANGED
@@ -100,6 +100,7 @@ For more information on AIA visit these locations:
100
100
  - [Example Workflow](#example-workflow)
101
101
  - [Roles and System Prompts](#roles-and-system-prompts)
102
102
  - [RubyLLM::Tool Support](#rubyllmtool-support)
103
+ - [MCP Server Configuration](#mcp-server-configuration)
103
104
  - [Examples & Tips](#examples--tips)
104
105
  - [Practical Examples](#practical-examples)
105
106
  - [Code Review Prompt](#code-review-prompt)
@@ -922,6 +923,170 @@ aia --tools examples/tools/mcp/imcp.rb --chat
922
923
 
923
924
  These MCP clients require the `ruby_llm-mcp` gem and provide access to external services and data sources through the Model Context Protocol.
924
925
 
926
+ ### MCP Server Configuration
927
+
928
+ AIA supports defining MCP (Model Context Protocol) servers directly in your configuration file. This allows MCP tools to be automatically loaded at startup without needing to specify them on the command line each time.
929
+
930
+ #### Configuration Format
931
+
932
+ Add MCP servers to your `~/.aia/config.yml` file:
933
+
934
+ ```yaml
935
+ :mcp_servers:
936
+ - name: "server-name"
937
+ command: "server_command"
938
+ args: ["arg1", "arg2"]
939
+ timeout: 30000 # milliseconds (default: 8000)
940
+ env:
941
+ ENV_VAR: "value"
942
+ ```
943
+
944
+ #### Configuration Options
945
+
946
+ | Option | Required | Default | Description |
947
+ |--------|----------|---------|-------------|
948
+ | `name` | Yes | - | Unique identifier for the MCP server |
949
+ | `command` | Yes | - | Executable command (absolute path or found in PATH) |
950
+ | `args` | No | `[]` | Array of command-line arguments |
951
+ | `timeout` | No | `8000` | Connection timeout in milliseconds |
952
+ | `env` | No | `{}` | Environment variables for the server process |
953
+
954
+ #### Example: GitHub MCP Server
955
+
956
+ The GitHub MCP server provides access to GitHub repositories, issues, pull requests, and more:
957
+
958
+ ```yaml
959
+ # ~/.aia/config.yml
960
+ :mcp_servers:
961
+ - name: "github"
962
+ command: "github-mcp-server"
963
+ args: ["stdio"]
964
+ timeout: 15000
965
+ env:
966
+ GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_your_token_here"
967
+ ```
968
+
969
+ **Setup:**
970
+ ```bash
971
+ # Install GitHub MCP server (macOS)
972
+ brew install github-mcp-server
973
+
974
+ # Or via npm
975
+ npm install -g @anthropic/github-mcp-server
976
+
977
+ # Set your GitHub token (recommended: use environment variable instead of config)
978
+ export GITHUB_PERSONAL_ACCESS_TOKEN="ghp_your_token_here"
979
+ ```
980
+
981
+ #### Example: Hierarchical Temporal Memory (HTM)
982
+
983
+ ```shell
984
+ gem install htm
985
+ ```
986
+
987
+ See the [full HTM documentation](https://madbomber.github.io/htm) for database configuration and system environment variable usage.
988
+
989
+ A custom Ruby-based MCP server for accessing database-backed long term memory:
990
+
991
+ ```yaml
992
+ # ~/.aia/config.yml
993
+ :mcp_servers:
994
+ - name: "htm"
995
+ command: "htm_mcp.rb"
996
+ args: ["stdio"]
997
+ timeout: 30000
998
+ env:
999
+ HTM_DBURL: "postgres://localhost:5432/htm_development"
1000
+ ...
1001
+ ```
1002
+
1003
+ **Notes:**
1004
+ - The `command` can be just the executable name if it's in your PATH
1005
+ - AIA automatically resolves command paths, so you don't need absolute paths
1006
+ - Environment variables in the `env` section are passed only to that MCP server process
1007
+
1008
+ #### Example: Multiple MCP Servers
1009
+
1010
+ You can configure multiple MCP servers to provide different capabilities:
1011
+
1012
+ ```yaml
1013
+ # ~/.aia/config.yml
1014
+ :mcp_servers:
1015
+ - name: "github"
1016
+ command: "github-mcp-server"
1017
+ args: ["stdio"]
1018
+ env:
1019
+ GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_your_token_here"
1020
+
1021
+ - name: "htm"
1022
+ command: "htm_mcp.rb"
1023
+ args: ["stdio"]
1024
+ timeout: 30000
1025
+ env:
1026
+ HTM_DBURL: "postgres://localhost:5432/htm_development"
1027
+
1028
+ - name: "filesystem"
1029
+ command: "filesystem-mcp-server"
1030
+ args: ["stdio", "--root", "/Users/me/projects"]
1031
+ ```
1032
+
1033
+ #### Verifying MCP Server Configuration
1034
+
1035
+ When MCP servers are configured, AIA displays them in the startup robot:
1036
+
1037
+ ```
1038
+ , ,
1039
+ (\____/) AI Assistant (v0.9.23) is Online
1040
+ (_oo_) gpt-4o-mini (supports tools)
1041
+ (O) using ruby_llm (v1.9.0 MCP v0.6.1)
1042
+ __||__ \) model db was last refreshed on
1043
+ [/______\] / 2025-06-03
1044
+ / \__AI__/ \/ You can share my tools
1045
+ / /__\ MCP: github, htm
1046
+ (\ /____\
1047
+ ```
1048
+
1049
+ Use the `//tools` directive in chat mode to see all available tools including those from MCP servers:
1050
+
1051
+ ```bash
1052
+ aia --chat
1053
+ > //tools
1054
+
1055
+ Available Tools:
1056
+ - github_create_issue: Create a new GitHub issue
1057
+ - github_list_repos: List repositories for the authenticated user
1058
+ - htm_query: Execute a query against the HTM database
1059
+ - htm_insert: Insert a record into HTM
1060
+ ...
1061
+ ```
1062
+
1063
+ #### Troubleshooting MCP Servers
1064
+
1065
+ If an MCP server fails to load, AIA will display a warning:
1066
+
1067
+ ```
1068
+ WARNING: MCP server 'github' command not found: github-mcp-server
1069
+ WARNING: MCP server entry missing name or command: {...}
1070
+ ERROR: Failed to load MCP server 'htm': Connection timeout
1071
+ ```
1072
+
1073
+ **Common Issues:**
1074
+
1075
+ | Problem | Solution |
1076
+ |---------|----------|
1077
+ | Command not found | Ensure the command is in your PATH or use absolute path |
1078
+ | Connection timeout | Increase the `timeout` value |
1079
+ | Missing environment variables | Add required env vars to the `env` section |
1080
+ | Server hangs on startup | Check that all required environment variables are set |
1081
+
1082
+ **Debug Mode:**
1083
+
1084
+ Enable debug mode to see detailed MCP server loading information:
1085
+
1086
+ ```bash
1087
+ aia --debug --chat
1088
+ ```
1089
+
925
1090
  **Shared Tools Collection:**
926
1091
  AIA can use the [shared_tools gem](https://github.com/madbomber/shared_tools) which provides a curated collection of commonly-used tools (aka functions) via the --require option.
927
1092
 
@@ -140,6 +140,7 @@ module AIA
140
140
  config = tailor_the_config(config)
141
141
  load_libraries(config)
142
142
  load_tools(config)
143
+ load_mcp_servers(config)
143
144
 
144
145
  if config.dump_file
145
146
  dump_config(config, config.dump_file)
@@ -192,6 +193,64 @@ module AIA
192
193
  exit(1) if exit_on_error
193
194
  end
194
195
 
196
+ def load_mcp_servers(config)
197
+ servers = config.mcp_servers
198
+
199
+ return config if servers.nil? || (servers.respond_to?(:empty?) && servers.empty?)
200
+
201
+ servers.each do |server|
202
+ name = server[:name] || server["name"]
203
+ command = server[:command] || server["command"]
204
+ args = server[:args] || server["args"] || []
205
+ env = server[:env] || server["env"] || {}
206
+ timeout = server[:timeout] || server["timeout"] || 8000 # default 8 seconds in ms
207
+
208
+ unless name && command
209
+ STDERR.puts "WARNING: MCP server entry missing name or command: #{server.inspect}"
210
+ next
211
+ end
212
+
213
+ # Resolve command path if not absolute
214
+ resolved_command = resolve_command_path(command)
215
+ unless resolved_command
216
+ STDERR.puts "WARNING: MCP server '#{name}' command not found: #{command}"
217
+ next
218
+ end
219
+
220
+ begin
221
+ RubyLLM::MCP.add_client(
222
+ name: name,
223
+ transport_type: :stdio,
224
+ request_timeout: timeout,
225
+ config: {
226
+ command: resolved_command,
227
+ args: args,
228
+ env: env
229
+ }
230
+ )
231
+ rescue => e
232
+ STDERR.puts "ERROR: Failed to load MCP server '#{name}': #{e.message}"
233
+ end
234
+ end
235
+
236
+ config
237
+ end
238
+
239
+ def resolve_command_path(command)
240
+ # If already absolute path, verify it exists
241
+ if command.start_with?('/')
242
+ return File.executable?(command) ? command : nil
243
+ end
244
+
245
+ # Search in PATH
246
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
247
+ full_path = File.join(dir, command)
248
+ return full_path if File.executable?(full_path)
249
+ end
250
+
251
+ nil
252
+ end
253
+
195
254
  # envar values are always String object so need other config
196
255
  # layers to know the prompter type for each key's value
197
256
  def envar_options(default, cli_config)
@@ -82,6 +82,9 @@ module AIA
82
82
 
83
83
  # Ruby libraries to require for Ruby binding
84
84
  require_libs: [],
85
+
86
+ # MCP Servers (nil means not configured, set in config file)
87
+ mcp_servers: nil,
85
88
  }).freeze
86
89
  end
87
90
  end
@@ -34,10 +34,15 @@ module AIA
34
34
  current_models = AIA.config.model
35
35
  current_models = [current_models] if current_models.is_a?(String)
36
36
 
37
- using_local_provider = current_models.any? { |m| m.start_with?('ollama/', 'lms/') }
37
+ # Extract model names (handles both String and Hash formats)
38
+ model_names = current_models.map do |m|
39
+ m.is_a?(Hash) ? m[:model] : m
40
+ end
41
+
42
+ using_local_provider = model_names.any? { |m| m.start_with?('ollama/', 'lms/') }
38
43
 
39
44
  if using_local_provider
40
- show_local_models(current_models, args)
45
+ show_local_models(model_names, args)
41
46
  else
42
47
  show_rubyllm_models(args)
43
48
  end
data/lib/aia/utility.rb CHANGED
@@ -13,6 +13,15 @@ module AIA
13
13
  AIA.config&.tool_paths && !AIA.config.tool_paths.empty?
14
14
  end
15
15
 
16
+ def mcp_servers?
17
+ AIA.config&.mcp_servers && !AIA.config.mcp_servers.empty?
18
+ end
19
+
20
+ def mcp_server_names
21
+ return [] unless mcp_servers?
22
+ AIA.config.mcp_servers.map { |s| s[:name] || s["name"] }.compact
23
+ end
24
+
16
25
  def supports_tools?
17
26
  AIA.config&.client&.model&.supports_functions? || false
18
27
  end
@@ -46,6 +55,8 @@ module AIA
46
55
  'unknown-model'
47
56
  end
48
57
 
58
+ mcp_line = mcp_servers? ? "MCP: #{mcp_server_names.join(', ')}" : ''
59
+
49
60
  puts <<-ROBOT
50
61
 
51
62
  , ,
@@ -55,7 +66,7 @@ module AIA
55
66
  __||__ \\) model db was last refreshed on
56
67
  [/______\\] / #{AIA.config&.last_refresh || 'unknown'}
57
68
  / \\__AI__/ \\/ #{user_tools? ? 'I will also use your tools' : (tools? ? 'You can share my tools' : 'I did not bring any tools')}
58
- / /__\\
69
+ / /__\\ #{mcp_line}
59
70
  (\\ /____\\ #{user_tools? && tools? ? 'My Toolbox contains:' : ''}
60
71
  ROBOT
61
72
  if user_tools? && tools?
data/lib/aia.rb CHANGED
@@ -7,9 +7,8 @@
7
7
  require 'ruby_llm'
8
8
  require 'ruby_llm/mcp'
9
9
 
10
- # FIXME: Actually fix ruby_llm; this is supposed to a temporary fix for the issues
11
- # discovered with shared_tools/ruby_llm/mcp/github_mcp_server
12
- RubyLLM::MCP.support_complex_parameters!
10
+ # NOTE: Complex parameters are now supported natively in ruby_llm-mcp >= 0.8.0
11
+ # The support_complex_parameters! method has been removed.
13
12
 
14
13
  require 'prompt_manager'
15
14
 
@@ -21,7 +21,11 @@ class OpenStruct
21
21
  end
22
22
 
23
23
  # Sets value in result OpenStruct, handling nested OpenStruct and Hash objects
24
+ # Skip nil values to avoid overwriting existing values with nil
24
25
  def self.set_value(result, key, value)
26
+ # Skip nil values - don't overwrite existing values with nil
27
+ return if value.nil?
28
+
25
29
  if value.is_a?(OpenStruct) || value.is_a?(Hash)
26
30
  current_value = result[key]
27
31
  current_value = {} if current_value.nil?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.21
4
+ version: 0.9.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dewayne VanHoozer
@@ -99,28 +99,28 @@ dependencies:
99
99
  requirements:
100
100
  - - ">="
101
101
  - !ruby/object:Gem::Version
102
- version: 1.5.1
102
+ version: 1.9.1
103
103
  type: :runtime
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - ">="
108
108
  - !ruby/object:Gem::Version
109
- version: 1.5.1
109
+ version: 1.9.1
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: ruby_llm-mcp
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - ">="
115
115
  - !ruby/object:Gem::Version
116
- version: 0.6.1
116
+ version: 0.8.0
117
117
  type: :runtime
118
118
  prerelease: false
119
119
  version_requirements: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - ">="
122
122
  - !ruby/object:Gem::Version
123
- version: 0.6.1
123
+ version: 0.8.0
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: reline
126
126
  requirement: !ruby/object:Gem::Requirement
@@ -477,7 +477,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
477
477
  - !ruby/object:Gem::Version
478
478
  version: '0'
479
479
  requirements: []
480
- rubygems_version: 3.7.2
480
+ rubygems_version: 4.0.0
481
481
  specification_version: 4
482
482
  summary: Multi-model AI CLI with dynamic prompts, consensus responses, shell & Ruby
483
483
  integration, and seamless chat workflows.