lex-microsoft_teams 0.6.49 → 0.6.50
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 +4 -4
- data/CHANGELOG.md +15 -0
- data/lib/legion/extensions/microsoft_teams/runners/app_installations.rb +17 -7
- data/lib/legion/extensions/microsoft_teams/runners/call_events.rb +70 -11
- data/lib/legion/extensions/microsoft_teams/runners/channel_messages.rb +67 -12
- data/lib/legion/extensions/microsoft_teams/runners/channels.rb +12 -4
- data/lib/legion/extensions/microsoft_teams/runners/chats.rb +42 -6
- data/lib/legion/extensions/microsoft_teams/runners/files.rb +72 -9
- data/lib/legion/extensions/microsoft_teams/runners/meeting_artifacts.rb +32 -5
- data/lib/legion/extensions/microsoft_teams/runners/meetings.rb +34 -4
- data/lib/legion/extensions/microsoft_teams/runners/messages.rb +73 -15
- data/lib/legion/extensions/microsoft_teams/runners/people.rb +14 -2
- data/lib/legion/extensions/microsoft_teams/runners/teams.rb +46 -8
- data/lib/legion/extensions/microsoft_teams/runners/transcripts.rb +35 -6
- data/lib/legion/extensions/microsoft_teams/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 35010357ecbf55560b6957ae2467c5975eec04056da102a34b1d4c870a0f1ce3
|
|
4
|
+
data.tar.gz: 38d375c241ba2691948bf6d80f275410f0a1003e0e7456852f3bc2ca1bf4acce
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ae71a656141975e85dc7b5e294e99d7d5a1f67a34e57feea943f177d4bf1c31224ef462adc5140163f6cb028ca1fede816fa713c25185522d8718fe01631a0af
|
|
7
|
+
data.tar.gz: b2e865c65531f7d464d7f058c2e8d965b1ca96643ca15bee7a6018c0dd260d7477771b0418404f9a6dd0ef8fc8dd983d8c68d0a06704fb2432af031d377150d6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.50] - 2026-05-27
|
|
4
|
+
### Added
|
|
5
|
+
- Full OData query parameter support across all Graph API runner methods per Microsoft Graph REST v1.0 docs
|
|
6
|
+
- `max_pages` pagination parameter on all list endpoints — follows `@odata.nextLink` automatically to fetch multiple pages in a single call
|
|
7
|
+
- `$top` exposed in MCP inputs for: list_chat_messages, list_chats, list_channel_messages, list_channel_message_replies, list_message_replies, list_team_members, list_meetings, list_drive_items, list_team_drive_items, list_call_sessions, list_session_segments, list_meeting_artifacts, list_transcripts
|
|
8
|
+
- `$orderby` support for list_chat_messages (lastModifiedDateTime desc, createdDateTime desc) and list_chats (lastMessagePreview/createdDateTime desc)
|
|
9
|
+
- `$filter` support for list_chat_messages, list_chats, list_channels, list_joined_teams, list_team_members, list_meetings, list_drive_items, list_people
|
|
10
|
+
- `$expand` support for list_chats (members, lastMessagePreview), list_channel_messages (replies), list_installed_apps_for_user, list_installed_apps_in_chat, list_call_sessions (segments)
|
|
11
|
+
- `$select` support for list_channels, list_joined_teams, list_drive_items, list_team_drive_items, list_call_sessions, list_people
|
|
12
|
+
- `$search` support for list_people
|
|
13
|
+
- `format` (vtt/docx) exposed in MCP inputs for get_transcript_content
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Per-page size capped at Graph API maximum (50 for messages/chats, 200 for drive items) regardless of `top` value passed
|
|
17
|
+
|
|
3
18
|
## [0.6.48] - 2026-05-18
|
|
4
19
|
### Added
|
|
5
20
|
- Definition DSL declarations across all runners for proper tool discovery and MCP exposure
|
|
@@ -15,29 +15,39 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_installed_apps_for_user,
|
|
18
|
-
desc: 'List Teams apps installed for a user',
|
|
18
|
+
desc: 'List Teams apps installed for a user with expand support',
|
|
19
19
|
mcp_prefix: 'teams.list_installed_apps_for_user',
|
|
20
20
|
mcp_category: 'teams_apps',
|
|
21
21
|
mcp_tier: :low,
|
|
22
22
|
idempotent: true,
|
|
23
|
+
inputs: { properties: { expand: { type: 'string',
|
|
24
|
+
description: 'Expand related entities (e.g. teamsApp)' } },
|
|
25
|
+
required: [] },
|
|
23
26
|
trigger_words: %w[apps installed]
|
|
24
27
|
|
|
25
|
-
def list_installed_apps_for_user(user_id: 'me', **)
|
|
26
|
-
|
|
28
|
+
def list_installed_apps_for_user(user_id: 'me', expand: nil, **)
|
|
29
|
+
params = {}
|
|
30
|
+
params['$expand'] = expand if expand
|
|
31
|
+
response = graph_connection(**).get("#{user_path(user_id)}/teamwork/installedApps", params)
|
|
27
32
|
{ result: response.body }
|
|
28
33
|
end
|
|
29
34
|
|
|
30
35
|
definition :list_installed_apps_in_chat,
|
|
31
|
-
desc: 'List Teams apps installed in a specific chat',
|
|
36
|
+
desc: 'List Teams apps installed in a specific chat with expand support',
|
|
32
37
|
mcp_prefix: 'teams.list_installed_apps_in_chat',
|
|
33
38
|
mcp_category: 'teams_apps',
|
|
34
39
|
mcp_tier: :low,
|
|
35
40
|
idempotent: true,
|
|
36
|
-
inputs: { properties: { chat_id: { type: 'string' }
|
|
41
|
+
inputs: { properties: { chat_id: { type: 'string' },
|
|
42
|
+
expand: { type: 'string',
|
|
43
|
+
description: 'Expand related entities (e.g. teamsApp)' } },
|
|
44
|
+
required: ['chat_id'] },
|
|
37
45
|
trigger_words: %w[apps chat]
|
|
38
46
|
|
|
39
|
-
def list_installed_apps_in_chat(chat_id:, **)
|
|
40
|
-
|
|
47
|
+
def list_installed_apps_in_chat(chat_id:, expand: nil, **)
|
|
48
|
+
params = {}
|
|
49
|
+
params['$expand'] = expand if expand
|
|
50
|
+
response = graph_connection(**).get("chats/#{chat_id}/installedApps", params)
|
|
41
51
|
{ result: response.body }
|
|
42
52
|
end
|
|
43
53
|
|
|
@@ -15,17 +15,50 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_call_sessions,
|
|
18
|
-
desc: 'List sessions for a Teams call record',
|
|
18
|
+
desc: 'List sessions for a Teams call record with pagination and expand',
|
|
19
19
|
mcp_prefix: 'teams.list_call_sessions',
|
|
20
20
|
mcp_category: 'teams_calls',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
|
-
inputs: { properties: { call_id:
|
|
23
|
+
inputs: { properties: { call_id: { type: 'string' },
|
|
24
|
+
top: { type: 'integer',
|
|
25
|
+
description: 'Sessions per page (default 50)' },
|
|
26
|
+
max_pages: { type: 'integer',
|
|
27
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
28
|
+
expand: { type: 'string',
|
|
29
|
+
description: 'Expand related entities (e.g. segments)' },
|
|
30
|
+
select: { type: 'string',
|
|
31
|
+
description: 'Comma-separated fields to return' } },
|
|
32
|
+
required: ['call_id'] },
|
|
24
33
|
trigger_words: %w[sessions calls records]
|
|
25
34
|
|
|
26
|
-
def list_call_sessions(call_id:, **)
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
def list_call_sessions(call_id:, top: 50, max_pages: 1, expand: nil, select: nil, **)
|
|
36
|
+
params = { '$top' => top }
|
|
37
|
+
params['$expand'] = expand if expand
|
|
38
|
+
params['$select'] = select if select
|
|
39
|
+
conn = graph_connection(**)
|
|
40
|
+
response = conn.get("communications/callRecords/#{call_id}/sessions", params)
|
|
41
|
+
body = response.body
|
|
42
|
+
|
|
43
|
+
return { result: body } if max_pages <= 1
|
|
44
|
+
|
|
45
|
+
all_values = Array(body['value'] || body[:value])
|
|
46
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
47
|
+
pages_fetched = 1
|
|
48
|
+
|
|
49
|
+
while next_link && pages_fetched < max_pages
|
|
50
|
+
response = conn.get(next_link)
|
|
51
|
+
page_body = response.body
|
|
52
|
+
items = page_body['value'] || page_body[:value]
|
|
53
|
+
all_values.concat(Array(items)) if items
|
|
54
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
55
|
+
pages_fetched += 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
59
|
+
'value' => all_values }
|
|
60
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
61
|
+
{ result: result }
|
|
29
62
|
end
|
|
30
63
|
|
|
31
64
|
definition :get_call_session,
|
|
@@ -47,21 +80,47 @@ module Legion
|
|
|
47
80
|
end
|
|
48
81
|
|
|
49
82
|
definition :list_session_segments,
|
|
50
|
-
desc: 'List segments for a session in a Teams call record',
|
|
83
|
+
desc: 'List segments for a session in a Teams call record with pagination',
|
|
51
84
|
mcp_prefix: 'teams.list_session_segments',
|
|
52
85
|
mcp_category: 'teams_calls',
|
|
53
86
|
mcp_tier: :standard,
|
|
54
87
|
idempotent: true,
|
|
55
88
|
inputs: { properties: { call_id: { type: 'string' },
|
|
56
|
-
session_id: { type: 'string' }
|
|
89
|
+
session_id: { type: 'string' },
|
|
90
|
+
top: { type: 'integer',
|
|
91
|
+
description: 'Segments per page (default 50)' },
|
|
92
|
+
max_pages: { type: 'integer',
|
|
93
|
+
description: 'Maximum pages to fetch (default 1)' } },
|
|
57
94
|
required: %w[call_id session_id] },
|
|
58
95
|
trigger_words: %w[segments pstn]
|
|
59
96
|
|
|
60
|
-
def list_session_segments(call_id:, session_id:, **)
|
|
61
|
-
|
|
62
|
-
|
|
97
|
+
def list_session_segments(call_id:, session_id:, top: 50, max_pages: 1, **)
|
|
98
|
+
params = { '$top' => top }
|
|
99
|
+
conn = graph_connection(**)
|
|
100
|
+
response = conn.get(
|
|
101
|
+
"communications/callRecords/#{call_id}/sessions/#{session_id}/segments", params
|
|
63
102
|
)
|
|
64
|
-
|
|
103
|
+
body = response.body
|
|
104
|
+
|
|
105
|
+
return { result: body } if max_pages <= 1
|
|
106
|
+
|
|
107
|
+
all_values = Array(body['value'] || body[:value])
|
|
108
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
109
|
+
pages_fetched = 1
|
|
110
|
+
|
|
111
|
+
while next_link && pages_fetched < max_pages
|
|
112
|
+
response = conn.get(next_link)
|
|
113
|
+
page_body = response.body
|
|
114
|
+
items = page_body['value'] || page_body[:value]
|
|
115
|
+
all_values.concat(Array(items)) if items
|
|
116
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
117
|
+
pages_fetched += 1
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
121
|
+
'value' => all_values }
|
|
122
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
123
|
+
{ result: result }
|
|
65
124
|
end
|
|
66
125
|
|
|
67
126
|
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
@@ -15,20 +15,49 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_channel_messages,
|
|
18
|
-
desc: 'List messages posted in a Teams channel',
|
|
18
|
+
desc: 'List messages posted in a Teams channel with pagination and expand support',
|
|
19
19
|
mcp_prefix: 'teams.list_channel_messages',
|
|
20
20
|
mcp_category: 'teams_channel_messages',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
23
|
inputs: { properties: { team_id: { type: 'string' },
|
|
24
|
-
channel_id: { type: 'string' }
|
|
24
|
+
channel_id: { type: 'string' },
|
|
25
|
+
top: { type: 'integer',
|
|
26
|
+
description: 'Messages per page (default 20, max 50)' },
|
|
27
|
+
max_pages: { type: 'integer',
|
|
28
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
29
|
+
expand: { type: 'string',
|
|
30
|
+
description: 'Expand related entities (e.g. replies)' } },
|
|
25
31
|
required: %w[team_id channel_id] },
|
|
26
32
|
trigger_words: %w[channel history posts feed]
|
|
27
33
|
|
|
28
|
-
def list_channel_messages(team_id:, channel_id:, top: 50, **)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
def list_channel_messages(team_id:, channel_id:, top: 50, max_pages: 1, expand: nil, **)
|
|
35
|
+
per_page = [top, 50].min
|
|
36
|
+
params = { '$top' => per_page }
|
|
37
|
+
params['$expand'] = expand if expand
|
|
38
|
+
conn = graph_connection(**)
|
|
39
|
+
response = conn.get("teams/#{team_id}/channels/#{channel_id}/messages", params)
|
|
40
|
+
body = response.body
|
|
41
|
+
|
|
42
|
+
return { result: body } if max_pages <= 1
|
|
43
|
+
|
|
44
|
+
all_values = Array(body['value'] || body[:value])
|
|
45
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
46
|
+
pages_fetched = 1
|
|
47
|
+
|
|
48
|
+
while next_link && pages_fetched < max_pages
|
|
49
|
+
response = conn.get(next_link)
|
|
50
|
+
page_body = response.body
|
|
51
|
+
items = page_body['value'] || page_body[:value]
|
|
52
|
+
all_values.concat(Array(items)) if items
|
|
53
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
54
|
+
pages_fetched += 1
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
58
|
+
'value' => all_values }
|
|
59
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
60
|
+
{ result: result }
|
|
32
61
|
end
|
|
33
62
|
|
|
34
63
|
definition :get_channel_message,
|
|
@@ -89,23 +118,49 @@ module Legion
|
|
|
89
118
|
end
|
|
90
119
|
|
|
91
120
|
definition :list_channel_message_replies,
|
|
92
|
-
desc: 'List replies in a Teams channel message thread',
|
|
121
|
+
desc: 'List replies in a Teams channel message thread with pagination',
|
|
93
122
|
mcp_prefix: 'teams.list_channel_message_replies',
|
|
94
123
|
mcp_category: 'teams_channel_messages',
|
|
95
124
|
mcp_tier: :standard,
|
|
96
125
|
idempotent: true,
|
|
97
126
|
inputs: { properties: { team_id: { type: 'string' },
|
|
98
127
|
channel_id: { type: 'string' },
|
|
99
|
-
message_id: { type: 'string' }
|
|
128
|
+
message_id: { type: 'string' },
|
|
129
|
+
top: { type: 'integer',
|
|
130
|
+
description: 'Replies per page (default 50, max 50)' },
|
|
131
|
+
max_pages: { type: 'integer',
|
|
132
|
+
description: 'Maximum pages to fetch (default 1)' } },
|
|
100
133
|
required: %w[team_id channel_id message_id] },
|
|
101
134
|
trigger_words: %w[replies thread]
|
|
102
135
|
|
|
103
|
-
def list_channel_message_replies(team_id:, channel_id:, message_id:, top: 50, **)
|
|
104
|
-
|
|
105
|
-
|
|
136
|
+
def list_channel_message_replies(team_id:, channel_id:, message_id:, top: 50, max_pages: 1, **)
|
|
137
|
+
per_page = [top, 50].min
|
|
138
|
+
params = { '$top' => per_page }
|
|
139
|
+
conn = graph_connection(**)
|
|
140
|
+
response = conn.get(
|
|
106
141
|
"teams/#{team_id}/channels/#{channel_id}/messages/#{message_id}/replies", params
|
|
107
142
|
)
|
|
108
|
-
|
|
143
|
+
body = response.body
|
|
144
|
+
|
|
145
|
+
return { result: body } if max_pages <= 1
|
|
146
|
+
|
|
147
|
+
all_values = Array(body['value'] || body[:value])
|
|
148
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
149
|
+
pages_fetched = 1
|
|
150
|
+
|
|
151
|
+
while next_link && pages_fetched < max_pages
|
|
152
|
+
response = conn.get(next_link)
|
|
153
|
+
page_body = response.body
|
|
154
|
+
items = page_body['value'] || page_body[:value]
|
|
155
|
+
all_values.concat(Array(items)) if items
|
|
156
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
157
|
+
pages_fetched += 1
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
161
|
+
'value' => all_values }
|
|
162
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
163
|
+
{ result: result }
|
|
109
164
|
end
|
|
110
165
|
|
|
111
166
|
definition :edit_channel_message,
|
|
@@ -15,16 +15,24 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_channels,
|
|
18
|
-
desc: 'List channels in a Team',
|
|
18
|
+
desc: 'List channels in a Team with optional filtering and select',
|
|
19
19
|
mcp_prefix: 'teams.list_channels',
|
|
20
20
|
mcp_category: 'teams_channels',
|
|
21
21
|
mcp_tier: :low,
|
|
22
22
|
idempotent: true,
|
|
23
|
-
inputs: { properties: { team_id: { type: 'string' }
|
|
23
|
+
inputs: { properties: { team_id: { type: 'string' },
|
|
24
|
+
filter: { type: 'string',
|
|
25
|
+
description: 'OData $filter (e.g. membershipType eq \'standard\')' },
|
|
26
|
+
select: { type: 'string',
|
|
27
|
+
description: 'Comma-separated fields to return' } },
|
|
28
|
+
required: ['team_id'] },
|
|
24
29
|
trigger_words: %w[channels list]
|
|
25
30
|
|
|
26
|
-
def list_channels(team_id:, **)
|
|
27
|
-
|
|
31
|
+
def list_channels(team_id:, filter: nil, select: nil, **)
|
|
32
|
+
params = {}
|
|
33
|
+
params['$filter'] = filter if filter
|
|
34
|
+
params['$select'] = select if select
|
|
35
|
+
response = graph_connection(**).get("teams/#{team_id}/channels", params)
|
|
28
36
|
{ result: response.body }
|
|
29
37
|
end
|
|
30
38
|
|
|
@@ -15,18 +15,54 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_chats,
|
|
18
|
-
desc: 'List Teams chats for the current user',
|
|
18
|
+
desc: 'List Teams chats for the current user with pagination, filtering, and expand support',
|
|
19
19
|
mcp_prefix: 'teams.list_chats',
|
|
20
20
|
mcp_category: 'teams_chat',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
|
+
inputs: { properties: { top: { type: 'integer',
|
|
24
|
+
description: 'Number of chats per page (default 50, max 50)' },
|
|
25
|
+
max_pages: { type: 'integer',
|
|
26
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
27
|
+
expand: { type: 'string',
|
|
28
|
+
description: 'Expand related entities: members, lastMessagePreview' },
|
|
29
|
+
filter: { type: 'string',
|
|
30
|
+
description: 'OData $filter expression (e.g. chatType eq \'group\')' },
|
|
31
|
+
orderby: { type: 'string',
|
|
32
|
+
description: 'Sort order (e.g. lastMessagePreview/createdDateTime desc)' } },
|
|
33
|
+
required: [] },
|
|
23
34
|
trigger_words: %w[chats conversations]
|
|
24
35
|
|
|
25
|
-
def list_chats(user_id: 'me', top: 50, **)
|
|
26
|
-
log.debug "list_chats(user_id: #{user_id}, top: #{top})"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
def list_chats(user_id: 'me', top: 50, max_pages: 1, expand: nil, filter: nil, orderby: nil, **)
|
|
37
|
+
log.debug "list_chats(user_id: #{user_id}, top: #{top}, max_pages: #{max_pages})"
|
|
38
|
+
per_page = [top, 50].min
|
|
39
|
+
params = { '$top' => per_page }
|
|
40
|
+
params['$expand'] = expand if expand
|
|
41
|
+
params['$filter'] = filter if filter
|
|
42
|
+
params['$orderby'] = orderby if orderby
|
|
43
|
+
conn = graph_connection(**)
|
|
44
|
+
response = conn.get("#{user_path(user_id)}/chats", params)
|
|
45
|
+
body = response.body
|
|
46
|
+
|
|
47
|
+
return { result: body } if max_pages <= 1
|
|
48
|
+
|
|
49
|
+
all_values = Array(body['value'] || body[:value])
|
|
50
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
51
|
+
pages_fetched = 1
|
|
52
|
+
|
|
53
|
+
while next_link && pages_fetched < max_pages
|
|
54
|
+
response = conn.get(next_link)
|
|
55
|
+
page_body = response.body
|
|
56
|
+
items = page_body['value'] || page_body[:value]
|
|
57
|
+
all_values.concat(Array(items)) if items
|
|
58
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
59
|
+
pages_fetched += 1
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
63
|
+
'value' => all_values }
|
|
64
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
65
|
+
{ result: result }
|
|
30
66
|
end
|
|
31
67
|
|
|
32
68
|
definition :get_chat,
|
|
@@ -15,17 +15,50 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_drive_items,
|
|
18
|
-
desc: 'List files in the root of a user\'s OneDrive',
|
|
18
|
+
desc: 'List files in the root of a user\'s OneDrive with pagination and filtering',
|
|
19
19
|
mcp_prefix: 'teams.list_drive_items',
|
|
20
20
|
mcp_category: 'teams_files',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
|
+
inputs: { properties: { top: { type: 'integer',
|
|
24
|
+
description: 'Items per page (default 200)' },
|
|
25
|
+
max_pages: { type: 'integer',
|
|
26
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
27
|
+
select: { type: 'string',
|
|
28
|
+
description: 'Comma-separated fields to return' },
|
|
29
|
+
filter: { type: 'string',
|
|
30
|
+
description: 'OData $filter expression' } },
|
|
31
|
+
required: [] },
|
|
23
32
|
trigger_words: %w[files drive onedrive]
|
|
24
33
|
|
|
25
|
-
def list_drive_items(user_id: 'me', **)
|
|
34
|
+
def list_drive_items(user_id: 'me', top: 200, max_pages: 1, select: nil, filter: nil, **)
|
|
26
35
|
log.debug "list_drive_items(user_id: #{user_id})"
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
params = { '$top' => top }
|
|
37
|
+
params['$select'] = select if select
|
|
38
|
+
params['$filter'] = filter if filter
|
|
39
|
+
conn = graph_connection(**)
|
|
40
|
+
response = conn.get("#{user_path(user_id)}/drive/root/children", params)
|
|
41
|
+
body = response.body
|
|
42
|
+
|
|
43
|
+
return { result: body } if max_pages <= 1
|
|
44
|
+
|
|
45
|
+
all_values = Array(body['value'] || body[:value])
|
|
46
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
47
|
+
pages_fetched = 1
|
|
48
|
+
|
|
49
|
+
while next_link && pages_fetched < max_pages
|
|
50
|
+
response = conn.get(next_link)
|
|
51
|
+
page_body = response.body
|
|
52
|
+
items = page_body['value'] || page_body[:value]
|
|
53
|
+
all_values.concat(Array(items)) if items
|
|
54
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
55
|
+
pages_fetched += 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
59
|
+
'value' => all_values }
|
|
60
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
61
|
+
{ result: result }
|
|
29
62
|
end
|
|
30
63
|
|
|
31
64
|
definition :get_drive_item,
|
|
@@ -59,18 +92,48 @@ module Legion
|
|
|
59
92
|
end
|
|
60
93
|
|
|
61
94
|
definition :list_team_drive_items,
|
|
62
|
-
desc: 'List files in a Team\'s SharePoint document library',
|
|
95
|
+
desc: 'List files in a Team\'s SharePoint document library with pagination',
|
|
63
96
|
mcp_prefix: 'teams.list_team_drive_items',
|
|
64
97
|
mcp_category: 'teams_files',
|
|
65
98
|
mcp_tier: :standard,
|
|
66
99
|
idempotent: true,
|
|
67
|
-
inputs: { properties: { team_id:
|
|
100
|
+
inputs: { properties: { team_id: { type: 'string' },
|
|
101
|
+
top: { type: 'integer',
|
|
102
|
+
description: 'Items per page (default 200)' },
|
|
103
|
+
max_pages: { type: 'integer',
|
|
104
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
105
|
+
select: { type: 'string',
|
|
106
|
+
description: 'Comma-separated fields to return' } },
|
|
107
|
+
required: ['team_id'] },
|
|
68
108
|
trigger_words: %w[sharepoint documents team]
|
|
69
109
|
|
|
70
|
-
def list_team_drive_items(team_id:, **)
|
|
110
|
+
def list_team_drive_items(team_id:, top: 200, max_pages: 1, select: nil, **)
|
|
71
111
|
log.debug "list_team_drive_items(team_id: #{team_id})"
|
|
72
|
-
|
|
73
|
-
|
|
112
|
+
params = { '$top' => top }
|
|
113
|
+
params['$select'] = select if select
|
|
114
|
+
conn = graph_connection(**)
|
|
115
|
+
response = conn.get("teams/#{team_id}/drive/root/children", params)
|
|
116
|
+
body = response.body
|
|
117
|
+
|
|
118
|
+
return { result: body } if max_pages <= 1
|
|
119
|
+
|
|
120
|
+
all_values = Array(body['value'] || body[:value])
|
|
121
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
122
|
+
pages_fetched = 1
|
|
123
|
+
|
|
124
|
+
while next_link && pages_fetched < max_pages
|
|
125
|
+
response = conn.get(next_link)
|
|
126
|
+
page_body = response.body
|
|
127
|
+
items = page_body['value'] || page_body[:value]
|
|
128
|
+
all_values.concat(Array(items)) if items
|
|
129
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
130
|
+
pages_fetched += 1
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
134
|
+
'value' => all_values }
|
|
135
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
136
|
+
{ result: result }
|
|
74
137
|
end
|
|
75
138
|
|
|
76
139
|
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
@@ -15,17 +15,44 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_meeting_artifacts,
|
|
18
|
-
desc: 'List artifacts (recordings, whiteboards) for an online meeting',
|
|
18
|
+
desc: 'List artifacts (recordings, whiteboards) for an online meeting with pagination',
|
|
19
19
|
mcp_prefix: 'teams.list_meeting_artifacts',
|
|
20
20
|
mcp_category: 'teams_meetings',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
|
-
inputs: { properties: { meeting_id: { type: 'string' }
|
|
23
|
+
inputs: { properties: { meeting_id: { type: 'string' },
|
|
24
|
+
top: { type: 'integer',
|
|
25
|
+
description: 'Artifacts per page (default 50)' },
|
|
26
|
+
max_pages: { type: 'integer',
|
|
27
|
+
description: 'Maximum pages to fetch (default 1)' } },
|
|
28
|
+
required: ['meeting_id'] },
|
|
24
29
|
trigger_words: %w[artifacts recordings whiteboards]
|
|
25
30
|
|
|
26
|
-
def list_meeting_artifacts(meeting_id:, user_id: 'me', **)
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
def list_meeting_artifacts(meeting_id:, user_id: 'me', top: 50, max_pages: 1, **)
|
|
32
|
+
params = { '$top' => top }
|
|
33
|
+
conn = graph_connection(**)
|
|
34
|
+
response = conn.get("#{user_path(user_id)}/onlineMeetings/#{meeting_id}/artifacts", params)
|
|
35
|
+
body = response.body
|
|
36
|
+
|
|
37
|
+
return { result: body } if max_pages <= 1
|
|
38
|
+
|
|
39
|
+
all_values = Array(body['value'] || body[:value])
|
|
40
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
41
|
+
pages_fetched = 1
|
|
42
|
+
|
|
43
|
+
while next_link && pages_fetched < max_pages
|
|
44
|
+
response = conn.get(next_link)
|
|
45
|
+
page_body = response.body
|
|
46
|
+
items = page_body['value'] || page_body[:value]
|
|
47
|
+
all_values.concat(Array(items)) if items
|
|
48
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
49
|
+
pages_fetched += 1
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
53
|
+
'value' => all_values }
|
|
54
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
55
|
+
{ result: result }
|
|
29
56
|
end
|
|
30
57
|
|
|
31
58
|
definition :get_meeting_artifact,
|
|
@@ -15,16 +15,46 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_meetings,
|
|
18
|
-
desc: 'List online meetings for the current user',
|
|
18
|
+
desc: 'List online meetings for the current user with pagination and filtering',
|
|
19
19
|
mcp_prefix: 'teams.list_meetings',
|
|
20
20
|
mcp_category: 'teams_meetings',
|
|
21
21
|
mcp_tier: :low,
|
|
22
22
|
idempotent: true,
|
|
23
|
+
inputs: { properties: { top: { type: 'integer',
|
|
24
|
+
description: 'Meetings per page (default 50)' },
|
|
25
|
+
max_pages: { type: 'integer',
|
|
26
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
27
|
+
filter: { type: 'string',
|
|
28
|
+
description: 'OData $filter expression' } },
|
|
29
|
+
required: [] },
|
|
23
30
|
trigger_words: %w[meetings upcoming calendar]
|
|
24
31
|
|
|
25
|
-
def list_meetings(user_id: 'me', **)
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
def list_meetings(user_id: 'me', top: 50, max_pages: 1, filter: nil, **)
|
|
33
|
+
params = { '$top' => top }
|
|
34
|
+
params['$filter'] = filter if filter
|
|
35
|
+
conn = graph_connection(**)
|
|
36
|
+
response = conn.get("#{user_path(user_id)}/onlineMeetings", params)
|
|
37
|
+
body = response.body
|
|
38
|
+
|
|
39
|
+
return { result: body } if max_pages <= 1
|
|
40
|
+
|
|
41
|
+
all_values = Array(body['value'] || body[:value])
|
|
42
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
43
|
+
pages_fetched = 1
|
|
44
|
+
|
|
45
|
+
while next_link && pages_fetched < max_pages
|
|
46
|
+
response = conn.get(next_link)
|
|
47
|
+
page_body = response.body
|
|
48
|
+
items = page_body['value'] || page_body[:value]
|
|
49
|
+
all_values.concat(Array(items)) if items
|
|
50
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
51
|
+
pages_fetched += 1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
55
|
+
'value' => all_values }
|
|
56
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
57
|
+
{ result: result }
|
|
28
58
|
end
|
|
29
59
|
|
|
30
60
|
definition :get_meeting,
|
|
@@ -15,21 +15,53 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_chat_messages,
|
|
18
|
-
desc: 'List messages in a Teams chat thread',
|
|
18
|
+
desc: 'List messages in a Teams chat thread with pagination, ordering, and filtering',
|
|
19
19
|
mcp_prefix: 'teams.list_chat_messages',
|
|
20
20
|
mcp_category: 'teams_messages',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
|
-
inputs: { properties: { chat_id:
|
|
24
|
-
|
|
23
|
+
inputs: { properties: { chat_id: { type: 'string',
|
|
24
|
+
description: 'Teams chat ID' },
|
|
25
|
+
top: { type: 'integer',
|
|
26
|
+
description: 'Messages per page (default 50, max 50)' },
|
|
27
|
+
max_pages: { type: 'integer',
|
|
28
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
29
|
+
orderby: { type: 'string',
|
|
30
|
+
description: 'Sort order: lastModifiedDateTime desc or createdDateTime desc' },
|
|
31
|
+
filter: { type: 'string',
|
|
32
|
+
description: 'OData $filter on lastModifiedDateTime or createdDateTime' } },
|
|
25
33
|
required: ['chat_id'] },
|
|
26
34
|
trigger_words: %w[messages history read]
|
|
27
35
|
|
|
28
|
-
def list_chat_messages(chat_id:, top: 50, **)
|
|
29
|
-
log.debug "list_chat_messages(chat_id: #{chat_id}, top: #{top})"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
def list_chat_messages(chat_id:, top: 50, max_pages: 1, orderby: nil, filter: nil, **)
|
|
37
|
+
log.debug "list_chat_messages(chat_id: #{chat_id}, top: #{top}, max_pages: #{max_pages})"
|
|
38
|
+
per_page = [top, 50].min
|
|
39
|
+
params = { '$top' => per_page }
|
|
40
|
+
params['$orderby'] = orderby if orderby
|
|
41
|
+
params['$filter'] = filter if filter
|
|
42
|
+
conn = graph_connection(**)
|
|
43
|
+
response = conn.get("chats/#{chat_id}/messages", params)
|
|
44
|
+
body = response.body
|
|
45
|
+
|
|
46
|
+
return { result: body } if max_pages <= 1
|
|
47
|
+
|
|
48
|
+
all_values = Array(body['value'] || body[:value])
|
|
49
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
50
|
+
pages_fetched = 1
|
|
51
|
+
|
|
52
|
+
while next_link && pages_fetched < max_pages
|
|
53
|
+
response = conn.get(next_link)
|
|
54
|
+
page_body = response.body
|
|
55
|
+
items = page_body['value'] || page_body[:value]
|
|
56
|
+
all_values.concat(Array(items)) if items
|
|
57
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
58
|
+
pages_fetched += 1
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
62
|
+
'value' => all_values }
|
|
63
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
64
|
+
{ result: result }
|
|
33
65
|
end
|
|
34
66
|
|
|
35
67
|
definition :get_chat_message,
|
|
@@ -89,21 +121,47 @@ module Legion
|
|
|
89
121
|
end
|
|
90
122
|
|
|
91
123
|
definition :list_message_replies,
|
|
92
|
-
desc: 'List replies to a message in a Teams chat',
|
|
124
|
+
desc: 'List replies to a message in a Teams chat with pagination support',
|
|
93
125
|
mcp_prefix: 'teams.list_message_replies',
|
|
94
126
|
mcp_category: 'teams_messages',
|
|
95
127
|
mcp_tier: :standard,
|
|
96
128
|
idempotent: true,
|
|
97
129
|
inputs: { properties: { chat_id: { type: 'string' },
|
|
98
|
-
message_id: { type: 'string' }
|
|
130
|
+
message_id: { type: 'string' },
|
|
131
|
+
top: { type: 'integer',
|
|
132
|
+
description: 'Number of replies to return per page (default 50)' },
|
|
133
|
+
max_pages: { type: 'integer',
|
|
134
|
+
description: 'Maximum pages to fetch (default 1)' } },
|
|
99
135
|
required: %w[chat_id message_id] },
|
|
100
136
|
trigger_words: %w[replies thread]
|
|
101
137
|
|
|
102
|
-
def list_message_replies(chat_id:, message_id:, top: 50, **)
|
|
103
|
-
log.debug "list_message_replies(chat_id: #{chat_id}, message_id: #{message_id}, top: #{top})"
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
138
|
+
def list_message_replies(chat_id:, message_id:, top: 50, max_pages: 1, **)
|
|
139
|
+
log.debug "list_message_replies(chat_id: #{chat_id}, message_id: #{message_id}, top: #{top}, max_pages: #{max_pages})"
|
|
140
|
+
per_page = [top, 50].min
|
|
141
|
+
params = { '$top' => per_page }
|
|
142
|
+
conn = graph_connection(**)
|
|
143
|
+
response = conn.get("chats/#{chat_id}/messages/#{message_id}/replies", params)
|
|
144
|
+
body = response.body
|
|
145
|
+
|
|
146
|
+
return { result: body } if max_pages <= 1
|
|
147
|
+
|
|
148
|
+
all_values = Array(body['value'] || body[:value])
|
|
149
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
150
|
+
pages_fetched = 1
|
|
151
|
+
|
|
152
|
+
while next_link && pages_fetched < max_pages
|
|
153
|
+
response = conn.get(next_link)
|
|
154
|
+
page_body = response.body
|
|
155
|
+
items = page_body['value'] || page_body[:value]
|
|
156
|
+
all_values.concat(Array(items)) if items
|
|
157
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
158
|
+
pages_fetched += 1
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
162
|
+
'value' => all_values }
|
|
163
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
164
|
+
{ result: result }
|
|
107
165
|
end
|
|
108
166
|
|
|
109
167
|
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
@@ -32,16 +32,28 @@ module Legion
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
definition :list_people,
|
|
35
|
-
desc: 'List people relevant to the current user
|
|
35
|
+
desc: 'List people relevant to the current user with search and filter support',
|
|
36
36
|
mcp_prefix: 'teams.list_people',
|
|
37
37
|
mcp_category: 'teams_people',
|
|
38
38
|
mcp_tier: :standard,
|
|
39
39
|
idempotent: true,
|
|
40
|
+
inputs: { properties: { top: { type: 'integer',
|
|
41
|
+
description: 'Number of people to return (default 25)' },
|
|
42
|
+
search: { type: 'string',
|
|
43
|
+
description: 'Search term to find people by name or email' },
|
|
44
|
+
filter: { type: 'string',
|
|
45
|
+
description: 'OData $filter expression' },
|
|
46
|
+
select: { type: 'string',
|
|
47
|
+
description: 'Comma-separated fields to return' } },
|
|
48
|
+
required: [] },
|
|
40
49
|
trigger_words: %w[people colleagues contacts]
|
|
41
50
|
|
|
42
|
-
def list_people(user_id: 'me', top: 25, **)
|
|
51
|
+
def list_people(user_id: 'me', top: 25, search: nil, filter: nil, select: nil, **)
|
|
43
52
|
log.debug("People#list_people user_id=#{user_id} top=#{top}")
|
|
44
53
|
params = { '$top' => top }
|
|
54
|
+
params['$search'] = "\"#{search}\"" if search
|
|
55
|
+
params['$filter'] = filter if filter
|
|
56
|
+
params['$select'] = select if select
|
|
45
57
|
response = graph_connection(**).get("#{user_path(user_id)}/people", params)
|
|
46
58
|
{ result: response.body }
|
|
47
59
|
rescue StandardError => e
|
|
@@ -15,15 +15,23 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_joined_teams,
|
|
18
|
-
desc: 'List Teams the current user has joined',
|
|
18
|
+
desc: 'List Teams the current user has joined with optional filtering and select',
|
|
19
19
|
mcp_prefix: 'teams.list_joined_teams',
|
|
20
20
|
mcp_category: 'teams_teams',
|
|
21
21
|
mcp_tier: :low,
|
|
22
22
|
idempotent: true,
|
|
23
|
+
inputs: { properties: { filter: { type: 'string',
|
|
24
|
+
description: 'OData $filter expression' },
|
|
25
|
+
select: { type: 'string',
|
|
26
|
+
description: 'Comma-separated fields to return' } },
|
|
27
|
+
required: [] },
|
|
23
28
|
trigger_words: %w[teams joined membership]
|
|
24
29
|
|
|
25
|
-
def list_joined_teams(user_id: 'me', **)
|
|
26
|
-
|
|
30
|
+
def list_joined_teams(user_id: 'me', filter: nil, select: nil, **)
|
|
31
|
+
params = {}
|
|
32
|
+
params['$filter'] = filter if filter
|
|
33
|
+
params['$select'] = select if select
|
|
34
|
+
response = graph_connection(**).get("#{user_path(user_id)}/joinedTeams", params)
|
|
27
35
|
{ result: response.body }
|
|
28
36
|
end
|
|
29
37
|
|
|
@@ -42,17 +50,47 @@ module Legion
|
|
|
42
50
|
end
|
|
43
51
|
|
|
44
52
|
definition :list_team_members,
|
|
45
|
-
desc: 'List members of a Team',
|
|
53
|
+
desc: 'List members of a Team with pagination',
|
|
46
54
|
mcp_prefix: 'teams.list_team_members',
|
|
47
55
|
mcp_category: 'teams_teams',
|
|
48
56
|
mcp_tier: :standard,
|
|
49
57
|
idempotent: true,
|
|
50
|
-
inputs: { properties: { team_id:
|
|
58
|
+
inputs: { properties: { team_id: { type: 'string' },
|
|
59
|
+
top: { type: 'integer',
|
|
60
|
+
description: 'Members per page (default 100)' },
|
|
61
|
+
max_pages: { type: 'integer',
|
|
62
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
63
|
+
filter: { type: 'string',
|
|
64
|
+
description: 'OData $filter expression' } },
|
|
65
|
+
required: ['team_id'] },
|
|
51
66
|
trigger_words: %w[members roster]
|
|
52
67
|
|
|
53
|
-
def list_team_members(team_id:, **)
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
def list_team_members(team_id:, top: 100, max_pages: 1, filter: nil, **)
|
|
69
|
+
params = { '$top' => top }
|
|
70
|
+
params['$filter'] = filter if filter
|
|
71
|
+
conn = graph_connection(**)
|
|
72
|
+
response = conn.get("teams/#{team_id}/members", params)
|
|
73
|
+
body = response.body
|
|
74
|
+
|
|
75
|
+
return { result: body } if max_pages <= 1
|
|
76
|
+
|
|
77
|
+
all_values = Array(body['value'] || body[:value])
|
|
78
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
79
|
+
pages_fetched = 1
|
|
80
|
+
|
|
81
|
+
while next_link && pages_fetched < max_pages
|
|
82
|
+
response = conn.get(next_link)
|
|
83
|
+
page_body = response.body
|
|
84
|
+
items = page_body['value'] || page_body[:value]
|
|
85
|
+
all_values.concat(Array(items)) if items
|
|
86
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
87
|
+
pages_fetched += 1
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
91
|
+
'value' => all_values }
|
|
92
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
93
|
+
{ result: result }
|
|
56
94
|
end
|
|
57
95
|
|
|
58
96
|
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
@@ -20,17 +20,44 @@ module Legion
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
definition :list_transcripts,
|
|
23
|
-
desc: 'List transcripts for an online meeting',
|
|
23
|
+
desc: 'List transcripts for an online meeting with pagination',
|
|
24
24
|
mcp_prefix: 'teams.list_transcripts',
|
|
25
25
|
mcp_category: 'teams_meetings',
|
|
26
26
|
mcp_tier: :standard,
|
|
27
27
|
idempotent: true,
|
|
28
|
-
inputs: { properties: { meeting_id: { type: 'string' }
|
|
28
|
+
inputs: { properties: { meeting_id: { type: 'string' },
|
|
29
|
+
top: { type: 'integer',
|
|
30
|
+
description: 'Transcripts per page (default 50)' },
|
|
31
|
+
max_pages: { type: 'integer',
|
|
32
|
+
description: 'Maximum pages to fetch (default 1)' } },
|
|
33
|
+
required: ['meeting_id'] },
|
|
29
34
|
trigger_words: ['transcripts']
|
|
30
35
|
|
|
31
|
-
def list_transcripts(meeting_id:, user_id: 'me', **)
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
def list_transcripts(meeting_id:, user_id: 'me', top: 50, max_pages: 1, **)
|
|
37
|
+
params = { '$top' => top }
|
|
38
|
+
conn = graph_connection(**)
|
|
39
|
+
response = conn.get("#{user_path(user_id)}/onlineMeetings/#{meeting_id}/transcripts", params)
|
|
40
|
+
body = response.body
|
|
41
|
+
|
|
42
|
+
return { result: body } if max_pages <= 1
|
|
43
|
+
|
|
44
|
+
all_values = Array(body['value'] || body[:value])
|
|
45
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
46
|
+
pages_fetched = 1
|
|
47
|
+
|
|
48
|
+
while next_link && pages_fetched < max_pages
|
|
49
|
+
response = conn.get(next_link)
|
|
50
|
+
page_body = response.body
|
|
51
|
+
items = page_body['value'] || page_body[:value]
|
|
52
|
+
all_values.concat(Array(items)) if items
|
|
53
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
54
|
+
pages_fetched += 1
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
58
|
+
'value' => all_values }
|
|
59
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
60
|
+
{ result: result }
|
|
34
61
|
end
|
|
35
62
|
|
|
36
63
|
definition :get_transcript,
|
|
@@ -58,7 +85,9 @@ module Legion
|
|
|
58
85
|
mcp_tier: :standard,
|
|
59
86
|
idempotent: true,
|
|
60
87
|
inputs: { properties: { meeting_id: { type: 'string' },
|
|
61
|
-
transcript_id: { type: 'string' }
|
|
88
|
+
transcript_id: { type: 'string' },
|
|
89
|
+
format: { type: 'string',
|
|
90
|
+
description: 'Output format: vtt (default) or docx' } },
|
|
62
91
|
required: %w[meeting_id transcript_id] },
|
|
63
92
|
trigger_words: %w[content vtt text read]
|
|
64
93
|
|