things-mcp 0.1.1 → 0.1.2

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: e31d578d8f6cb134b0d9b326d9178bc2b65c5eb83ceae17da565f033361877da
4
- data.tar.gz: 251493afb608cc788e59d2fc9ec383fbbfc6abd47ee1b6f252f9cc317450e87f
3
+ metadata.gz: 66584b39e6d5286abeb4a75f08f029bab5c7c1b7b7f42129ee12986086fa7927
4
+ data.tar.gz: bb7603686e15d0dc366f746e263dbb99cebb00ce35377e8ae49fb7f468658dc0
5
5
  SHA512:
6
- metadata.gz: 68faf189bd64f1e6e11eb4e68099abc9b65f64ffbffb0b0057efff92f019de56e169b38f8b5fd32dc40f0735435a62a3a2a6cfe97a1c480da1009c40c151a8b3
7
- data.tar.gz: 25e5e7bb0e01c27265af90f70174da40d320d1bc89193e31f5a0965d9fa970422d2edbc85996579e0e50a196ad6aa1c41fd6f99f7c310637d6a90f253ff83d60
6
+ metadata.gz: 5ff846805290fb8e7e628b8809855c2538852be5f0ea69766d176fa6065081ae93af010b2958c68bdc4ce5014f580375939701bf7964a1d915ea3d72d0d5f30e
7
+ data.tar.gz: 8450f45b5c44b9cf8a37762e48cb7c4fe2b64a6e409ebcd2603036726c49535ad862b9ded6796dc13788694562c10e1406ec7547c7364c1bfa1d91b61312b8e9
data/bin/test_connection CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
- require_relative "../lib/things_mcp"
4
+ $LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
5
+ require "things_mcp"
6
6
 
7
7
  puts "Testing Things MCP Ruby Server"
8
8
  puts "=" * 40
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
- require_relative "../lib/things_mcp/server"
4
+ lib = File.expand_path("../lib", __dir__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require "things_mcp/server"
6
7
 
7
8
  # Run the MCP server
8
9
  ThingsMcp::Server.new.run
@@ -303,7 +303,18 @@ module ThingsMcp
303
303
  private
304
304
 
305
305
  def find_database_path
306
- group_containers_dir = "#{Dir.home}/Library/Group Containers"
306
+ # Use actual user's home directory, not the process owner's
307
+ actual_home = ENV["HOME"] || Dir.home
308
+ # If running as root, try to find the real user's home directory
309
+ if actual_home == "/var/root" && ENV["SUDO_USER"]
310
+ actual_home = "/Users/#{ENV["SUDO_USER"]}"
311
+ elsif actual_home == "/var/root"
312
+ # Fallback: look for the most recent user directory
313
+ user_dirs = Dir.glob("/Users/*").select { |d| File.directory?(d) && !File.basename(d).start_with?(".") }
314
+ actual_home = user_dirs.max_by { |d| File.mtime(d) } if user_dirs.any?
315
+ end
316
+
317
+ group_containers_dir = "#{actual_home}/Library/Group Containers"
307
318
 
308
319
  # Find Things-specific directories to avoid permission issues
309
320
  things_dirs = Dir.glob("#{group_containers_dir}/*").select do |dir|
@@ -311,11 +322,24 @@ module ThingsMcp
311
322
  end
312
323
 
313
324
  things_dirs.each do |things_dir|
314
- pattern = "#{things_dir}/*/*/main.sqlite"
315
- matches = Dir.glob(pattern)
325
+ # First try to find the current database (not in Backups folder)
326
+ current_pattern = "#{things_dir}/*/Things Database.thingsdatabase/main.sqlite"
327
+ current_matches = Dir.glob(current_pattern).reject { |path| path.include?("/Backups/") }
328
+
329
+ unless current_matches.empty?
330
+ return current_matches.first
331
+ end
316
332
 
317
- return matches.first unless matches.empty?
333
+ # Fallback: look for any main.sqlite but exclude backups
334
+ fallback_pattern = "#{things_dir}/*/*/main.sqlite"
335
+ fallback_matches = Dir.glob(fallback_pattern).reject { |path| path.include?("/Backups/") }
336
+
337
+ unless fallback_matches.empty?
338
+ return fallback_matches.first
339
+ end
318
340
  end
341
+
342
+ nil
319
343
  end
320
344
 
321
345
  def todo_columns
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "json"
4
- require_relative "database"
5
- require_relative "url_scheme"
6
- require_relative "formatters"
4
+ require "things_mcp/database"
5
+ require "things_mcp/url_scheme"
6
+ require "things_mcp/formatters"
7
7
 
8
8
  module ThingsMcp
9
9
  # Tool call handlers for MCP server
@@ -3,10 +3,10 @@
3
3
  require "mcp"
4
4
  require "mcp/transports/stdio"
5
5
  require "logger"
6
- require_relative "tools"
7
- require_relative "handlers"
8
- require_relative "database"
9
- require_relative "url_scheme"
6
+ require "things_mcp/tools"
7
+ require "things_mcp/handlers"
8
+ require "things_mcp/database"
9
+ require "things_mcp/url_scheme"
10
10
 
11
11
  module ThingsMcp
12
12
  # MCP server implementation for Things 3 integration
@@ -95,7 +95,7 @@ module ThingsMcp
95
95
  required: tool_def[:inputSchema][:required],
96
96
  )
97
97
 
98
- define_singleton_method(:call) do |_server_context:, **arguments|
98
+ define_singleton_method(:call) do |server_context:, **arguments|
99
99
  # Convert symbol keys to string keys for consistent access
100
100
  string_arguments = arguments.transform_keys(&:to_s)
101
101
  result = ThingsMcp::Handlers.handle_tool_call(name, string_arguments)
@@ -107,12 +107,15 @@ module ThingsMcp
107
107
  },
108
108
  ])
109
109
  rescue => e
110
- MCP::Tool::Response.new([
111
- {
112
- type: "text",
113
- text: "Error: #{e.message}",
114
- },
115
- ])
110
+ # Log the full error to stderr for debugging
111
+ $stderr.puts "ERROR in tool #{name}: #{e.class}: #{e.message}"
112
+ $stderr.puts "Arguments: #{string_arguments.inspect}"
113
+ $stderr.puts "Backtrace:"
114
+ e.backtrace.each { |line| $stderr.puts " #{line}" }
115
+ $stderr.flush
116
+
117
+ # Also raise the error so MCP can handle it properly
118
+ raise e
116
119
  end
117
120
  end
118
121
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ThingsMcp
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/things_mcp.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "mcp"
4
- require_relative "things_mcp/server"
5
- require_relative "things_mcp/database"
6
- require_relative "things_mcp/handlers"
7
- require_relative "things_mcp/tools"
8
- require_relative "things_mcp/url_scheme"
9
- require_relative "things_mcp/formatters"
4
+ require "things_mcp/server"
5
+ require "things_mcp/database"
6
+ require "things_mcp/handlers"
7
+ require "things_mcp/tools"
8
+ require "things_mcp/url_scheme"
9
+ require "things_mcp/formatters"
10
10
 
11
11
  # ThingsMcp provides a Model Context Protocol (MCP) server for Things 3
12
12
  #
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: things-mcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hakan Ensari