mcpeasy 0.1.0 → 0.3.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.claudeignore +0 -3
  3. data/.mcp.json +19 -1
  4. data/CHANGELOG.md +59 -0
  5. data/CLAUDE.md +19 -5
  6. data/README.md +19 -3
  7. data/lib/mcpeasy/cli.rb +62 -10
  8. data/lib/mcpeasy/config.rb +22 -1
  9. data/lib/mcpeasy/setup.rb +1 -0
  10. data/lib/mcpeasy/version.rb +1 -1
  11. data/lib/utilities/gcal/README.md +11 -3
  12. data/lib/utilities/gcal/cli.rb +110 -108
  13. data/lib/utilities/gcal/mcp.rb +463 -308
  14. data/lib/utilities/gcal/service.rb +312 -0
  15. data/lib/utilities/gdrive/README.md +3 -3
  16. data/lib/utilities/gdrive/cli.rb +98 -96
  17. data/lib/utilities/gdrive/mcp.rb +290 -288
  18. data/lib/utilities/gdrive/service.rb +293 -0
  19. data/lib/utilities/gmail/README.md +278 -0
  20. data/lib/utilities/gmail/cli.rb +264 -0
  21. data/lib/utilities/gmail/mcp.rb +846 -0
  22. data/lib/utilities/gmail/service.rb +547 -0
  23. data/lib/utilities/gmeet/cli.rb +131 -129
  24. data/lib/utilities/gmeet/mcp.rb +374 -372
  25. data/lib/utilities/gmeet/service.rb +411 -0
  26. data/lib/utilities/notion/README.md +287 -0
  27. data/lib/utilities/notion/cli.rb +245 -0
  28. data/lib/utilities/notion/mcp.rb +607 -0
  29. data/lib/utilities/notion/service.rb +327 -0
  30. data/lib/utilities/slack/README.md +3 -3
  31. data/lib/utilities/slack/cli.rb +69 -54
  32. data/lib/utilities/slack/mcp.rb +277 -226
  33. data/lib/utilities/slack/service.rb +134 -0
  34. data/mcpeasy.gemspec +6 -1
  35. metadata +87 -10
  36. data/env.template +0 -11
  37. data/lib/utilities/gcal/gcal_tool.rb +0 -308
  38. data/lib/utilities/gdrive/gdrive_tool.rb +0 -291
  39. data/lib/utilities/gmeet/gmeet_tool.rb +0 -407
  40. data/lib/utilities/slack/slack_tool.rb +0 -119
  41. data/logs/.keep +0 -0
@@ -2,156 +2,158 @@
2
2
 
3
3
  require "bundler/setup"
4
4
  require "thor"
5
- require_relative "gmeet_tool"
5
+ require_relative "service"
6
6
 
7
- class GmeetCLI < Thor
8
- desc "test", "Test the Google Calendar API connection"
9
- def test
10
- response = tool.test_connection
7
+ module Gmeet
8
+ class CLI < Thor
9
+ desc "test", "Test the Google Calendar API connection"
10
+ def test
11
+ response = tool.test_connection
11
12
 
12
- if response[:ok]
13
- puts "✅ Successfully connected to Google Calendar"
14
- puts " User: #{response[:user]} (#{response[:email]})"
15
- else
16
- warn "❌ Connection test failed"
13
+ if response[:ok]
14
+ puts "✅ Successfully connected to Google Calendar"
15
+ puts " User: #{response[:user]} (#{response[:email]})"
16
+ else
17
+ warn "❌ Connection test failed"
18
+ end
19
+ rescue RuntimeError => e
20
+ puts "❌ Failed to connect to Google Calendar: #{e.message}"
21
+ exit 1
17
22
  end
18
- rescue RuntimeError => e
19
- puts "❌ Failed to connect to Google Calendar: #{e.message}"
20
- exit 1
21
- end
22
23
 
23
- desc "meetings", "List Google Meet meetings"
24
- method_option :start_date, type: :string, aliases: "-s", desc: "Start date (YYYY-MM-DD)"
25
- method_option :end_date, type: :string, aliases: "-e", desc: "End date (YYYY-MM-DD)"
26
- method_option :max_results, type: :numeric, default: 20, aliases: "-n", desc: "Max number of meetings"
27
- method_option :calendar_id, type: :string, aliases: "-c", desc: "Calendar ID (default: primary)"
28
- def meetings
29
- result = tool.list_meetings(
30
- start_date: options[:start_date],
31
- end_date: options[:end_date],
32
- max_results: options[:max_results],
33
- calendar_id: options[:calendar_id] || "primary"
34
- )
35
- meetings = result[:meetings]
24
+ desc "meetings", "List Google Meet meetings"
25
+ method_option :start_date, type: :string, aliases: "-s", desc: "Start date (YYYY-MM-DD)"
26
+ method_option :end_date, type: :string, aliases: "-e", desc: "End date (YYYY-MM-DD)"
27
+ method_option :max_results, type: :numeric, default: 20, aliases: "-n", desc: "Max number of meetings"
28
+ method_option :calendar_id, type: :string, aliases: "-c", desc: "Calendar ID (default: primary)"
29
+ def meetings
30
+ result = tool.list_meetings(
31
+ start_date: options[:start_date],
32
+ end_date: options[:end_date],
33
+ max_results: options[:max_results],
34
+ calendar_id: options[:calendar_id] || "primary"
35
+ )
36
+ meetings = result[:meetings]
36
37
 
37
- if meetings.empty?
38
- puts "🎥 No Google Meet meetings found for the specified date range"
39
- else
40
- puts "🎥 Found #{result[:count]} Google Meet meeting(s):"
41
- meetings.each_with_index do |meeting, index|
42
- puts " #{index + 1}. #{meeting[:summary] || "No title"}"
43
- puts " Start: #{format_datetime(meeting[:start])}"
44
- puts " End: #{format_datetime(meeting[:end])}"
45
- puts " Description: #{meeting[:description]}" if meeting[:description]
46
- puts " Location: #{meeting[:location]}" if meeting[:location]
47
- puts " Attendees: #{meeting[:attendees].join(", ")}" if meeting[:attendees]&.any?
48
- puts " Meet Link: #{meeting[:meet_link]}"
49
- puts " Calendar Link: #{meeting[:html_link]}"
50
- puts
38
+ if meetings.empty?
39
+ puts "🎥 No Google Meet meetings found for the specified date range"
40
+ else
41
+ puts "🎥 Found #{result[:count]} Google Meet meeting(s):"
42
+ meetings.each_with_index do |meeting, index|
43
+ puts " #{index + 1}. #{meeting[:summary] || "No title"}"
44
+ puts " Start: #{format_datetime(meeting[:start])}"
45
+ puts " End: #{format_datetime(meeting[:end])}"
46
+ puts " Description: #{meeting[:description]}" if meeting[:description]
47
+ puts " Location: #{meeting[:location]}" if meeting[:location]
48
+ puts " Attendees: #{meeting[:attendees].join(", ")}" if meeting[:attendees]&.any?
49
+ puts " Meet Link: #{meeting[:meet_link]}"
50
+ puts " Calendar Link: #{meeting[:html_link]}"
51
+ puts
52
+ end
51
53
  end
54
+ rescue RuntimeError => e
55
+ warn "❌ Failed to list meetings: #{e.message}"
56
+ exit 1
52
57
  end
53
- rescue RuntimeError => e
54
- warn "❌ Failed to list meetings: #{e.message}"
55
- exit 1
56
- end
57
58
 
58
- desc "upcoming", "List upcoming Google Meet meetings"
59
- method_option :max_results, type: :numeric, default: 10, aliases: "-n", desc: "Max number of meetings"
60
- method_option :calendar_id, type: :string, aliases: "-c", desc: "Calendar ID (default: primary)"
61
- def upcoming
62
- result = tool.upcoming_meetings(
63
- max_results: options[:max_results],
64
- calendar_id: options[:calendar_id] || "primary"
65
- )
66
- meetings = result[:meetings]
59
+ desc "upcoming", "List upcoming Google Meet meetings"
60
+ method_option :max_results, type: :numeric, default: 10, aliases: "-n", desc: "Max number of meetings"
61
+ method_option :calendar_id, type: :string, aliases: "-c", desc: "Calendar ID (default: primary)"
62
+ def upcoming
63
+ result = tool.upcoming_meetings(
64
+ max_results: options[:max_results],
65
+ calendar_id: options[:calendar_id] || "primary"
66
+ )
67
+ meetings = result[:meetings]
67
68
 
68
- if meetings.empty?
69
- puts "🎥 No upcoming Google Meet meetings found in the next 24 hours"
70
- else
71
- puts "🎥 Found #{result[:count]} upcoming Google Meet meeting(s):"
72
- meetings.each_with_index do |meeting, index|
73
- puts " #{index + 1}. #{meeting[:summary] || "No title"}"
74
- puts " Start: #{format_datetime(meeting[:start])} (#{meeting[:time_until_start]})"
75
- puts " End: #{format_datetime(meeting[:end])}"
76
- puts " Description: #{meeting[:description]}" if meeting[:description]
77
- puts " Location: #{meeting[:location]}" if meeting[:location]
78
- puts " Attendees: #{meeting[:attendees].join(", ")}" if meeting[:attendees]&.any?
79
- puts " Meet Link: #{meeting[:meet_link]}"
80
- puts " Calendar Link: #{meeting[:html_link]}"
81
- puts
69
+ if meetings.empty?
70
+ puts "🎥 No upcoming Google Meet meetings found in the next 24 hours"
71
+ else
72
+ puts "🎥 Found #{result[:count]} upcoming Google Meet meeting(s):"
73
+ meetings.each_with_index do |meeting, index|
74
+ puts " #{index + 1}. #{meeting[:summary] || "No title"}"
75
+ puts " Start: #{format_datetime(meeting[:start])} (#{meeting[:time_until_start]})"
76
+ puts " End: #{format_datetime(meeting[:end])}"
77
+ puts " Description: #{meeting[:description]}" if meeting[:description]
78
+ puts " Location: #{meeting[:location]}" if meeting[:location]
79
+ puts " Attendees: #{meeting[:attendees].join(", ")}" if meeting[:attendees]&.any?
80
+ puts " Meet Link: #{meeting[:meet_link]}"
81
+ puts " Calendar Link: #{meeting[:html_link]}"
82
+ puts
83
+ end
82
84
  end
85
+ rescue RuntimeError => e
86
+ warn "❌ Failed to list upcoming meetings: #{e.message}"
87
+ exit 1
83
88
  end
84
- rescue RuntimeError => e
85
- warn "❌ Failed to list upcoming meetings: #{e.message}"
86
- exit 1
87
- end
88
89
 
89
- desc "search QUERY", "Search for Google Meet meetings by text content"
90
- method_option :start_date, type: :string, aliases: "-s", desc: "Start date (YYYY-MM-DD)"
91
- method_option :end_date, type: :string, aliases: "-e", desc: "End date (YYYY-MM-DD)"
92
- method_option :max_results, type: :numeric, default: 10, aliases: "-n", desc: "Max number of meetings"
93
- def search(query)
94
- result = tool.search_meetings(
95
- query,
96
- start_date: options[:start_date],
97
- end_date: options[:end_date],
98
- max_results: options[:max_results]
99
- )
100
- meetings = result[:meetings]
90
+ desc "search QUERY", "Search for Google Meet meetings by text content"
91
+ method_option :start_date, type: :string, aliases: "-s", desc: "Start date (YYYY-MM-DD)"
92
+ method_option :end_date, type: :string, aliases: "-e", desc: "End date (YYYY-MM-DD)"
93
+ method_option :max_results, type: :numeric, default: 10, aliases: "-n", desc: "Max number of meetings"
94
+ def search(query)
95
+ result = tool.search_meetings(
96
+ query,
97
+ start_date: options[:start_date],
98
+ end_date: options[:end_date],
99
+ max_results: options[:max_results]
100
+ )
101
+ meetings = result[:meetings]
101
102
 
102
- if meetings.empty?
103
- puts "🔍 No Google Meet meetings found matching '#{query}'"
104
- else
105
- puts "🔍 Found #{result[:count]} Google Meet meeting(s) matching '#{query}':"
106
- meetings.each_with_index do |meeting, index|
107
- puts " #{index + 1}. #{meeting[:summary] || "No title"}"
108
- puts " Start: #{format_datetime(meeting[:start])}"
109
- puts " End: #{format_datetime(meeting[:end])}"
110
- puts " Description: #{meeting[:description]}" if meeting[:description]
111
- puts " Location: #{meeting[:location]}" if meeting[:location]
112
- puts " Meet Link: #{meeting[:meet_link]}"
113
- puts " Calendar Link: #{meeting[:html_link]}"
114
- puts
103
+ if meetings.empty?
104
+ puts "🔍 No Google Meet meetings found matching '#{query}'"
105
+ else
106
+ puts "🔍 Found #{result[:count]} Google Meet meeting(s) matching '#{query}':"
107
+ meetings.each_with_index do |meeting, index|
108
+ puts " #{index + 1}. #{meeting[:summary] || "No title"}"
109
+ puts " Start: #{format_datetime(meeting[:start])}"
110
+ puts " End: #{format_datetime(meeting[:end])}"
111
+ puts " Description: #{meeting[:description]}" if meeting[:description]
112
+ puts " Location: #{meeting[:location]}" if meeting[:location]
113
+ puts " Meet Link: #{meeting[:meet_link]}"
114
+ puts " Calendar Link: #{meeting[:html_link]}"
115
+ puts
116
+ end
115
117
  end
118
+ rescue RuntimeError => e
119
+ warn "❌ Failed to search meetings: #{e.message}"
120
+ exit 1
116
121
  end
117
- rescue RuntimeError => e
118
- warn "❌ Failed to search meetings: #{e.message}"
119
- exit 1
120
- end
121
122
 
122
- desc "url EVENT_ID", "Get the Google Meet URL for a specific event"
123
- method_option :calendar_id, type: :string, aliases: "-c", desc: "Calendar ID (default: primary)"
124
- def url(event_id)
125
- result = tool.get_meeting_url(event_id, calendar_id: options[:calendar_id] || "primary")
123
+ desc "url EVENT_ID", "Get the Google Meet URL for a specific event"
124
+ method_option :calendar_id, type: :string, aliases: "-c", desc: "Calendar ID (default: primary)"
125
+ def url(event_id)
126
+ result = tool.get_meeting_url(event_id, calendar_id: options[:calendar_id] || "primary")
126
127
 
127
- puts "🎥 #{result[:summary] || "Meeting"}"
128
- puts " Start: #{format_datetime(result[:start])}"
129
- puts " End: #{format_datetime(result[:end])}"
130
- puts " Meet Link: #{result[:meet_link]}"
131
- puts " Event ID: #{result[:event_id]}"
132
- rescue RuntimeError => e
133
- warn "❌ Failed to get meeting URL: #{e.message}"
134
- exit 1
135
- end
128
+ puts "🎥 #{result[:summary] || "Meeting"}"
129
+ puts " Start: #{format_datetime(result[:start])}"
130
+ puts " End: #{format_datetime(result[:end])}"
131
+ puts " Meet Link: #{result[:meet_link]}"
132
+ puts " Event ID: #{result[:event_id]}"
133
+ rescue RuntimeError => e
134
+ warn "❌ Failed to get meeting URL: #{e.message}"
135
+ exit 1
136
+ end
136
137
 
137
- private
138
+ private
138
139
 
139
- def tool
140
- @tool ||= GmeetTool.new
141
- end
140
+ def tool
141
+ @tool ||= Service.new
142
+ end
142
143
 
143
- def format_datetime(datetime_info)
144
- return "Unknown" unless datetime_info
144
+ def format_datetime(datetime_info)
145
+ return "Unknown" unless datetime_info
145
146
 
146
- if datetime_info[:date]
147
- # All-day event
148
- datetime_info[:date]
149
- elsif datetime_info[:date_time]
150
- # Specific time event
151
- time = Time.parse(datetime_info[:date_time])
152
- time.strftime("%Y-%m-%d %H:%M")
153
- else
154
- "Unknown"
147
+ if datetime_info[:date]
148
+ # All-day event
149
+ datetime_info[:date]
150
+ elsif datetime_info[:date_time]
151
+ # Specific time event
152
+ time = Time.parse(datetime_info[:date_time])
153
+ time.strftime("%Y-%m-%d %H:%M")
154
+ else
155
+ "Unknown"
156
+ end
155
157
  end
156
158
  end
157
159
  end