Add list attendees to mcp meetings

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2026-02-16 14:07:27 +01:00
parent 3a42307896
commit 1d1a0b6208
5 changed files with 111 additions and 0 deletions

View File

@@ -1956,3 +1956,23 @@ func (r *Resolver) DeleteRiskTool(ctx context.Context, req *mcp.CallToolRequest,
DeletedRiskID: input.ID,
}, nil
}
func (r *Resolver) ListMeetingAttendeesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeetingAttendeesInput) (*mcp.CallToolResult, types.ListMeetingAttendeesOutput, error) {
r.MustAuthorize(ctx, input.MeetingID, probo.ActionMeetingGet)
svc := r.ProboService(ctx, input.MeetingID)
attendees, err := svc.Meetings.GetAttendees(ctx, input.MeetingID)
if err != nil {
return nil, types.ListMeetingAttendeesOutput{}, fmt.Errorf("failed to list meeting attendees: %w", err)
}
profiles := make([]*types.Profile, 0, len(attendees))
for _, a := range attendees {
profiles = append(profiles, types.NewProfile(a))
}
return nil, types.ListMeetingAttendeesOutput{
Attendees: profiles,
}, nil
}

View File

@@ -95,6 +95,7 @@ type ResolverInterface interface {
AddMeetingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddMeetingInput) (*mcp.CallToolResult, types.AddMeetingOutput, error)
UpdateMeetingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateMeetingInput) (*mcp.CallToolResult, types.UpdateMeetingOutput, error)
DeleteMeetingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteMeetingInput) (*mcp.CallToolResult, types.DeleteMeetingOutput, error)
ListMeetingAttendeesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeetingAttendeesInput) (*mcp.CallToolResult, types.ListMeetingAttendeesOutput, error)
}
// New creates a new MCP server instance with all handlers registered.
@@ -1120,6 +1121,20 @@ func registerToolHandlers(server *mcp.Server, resolver ResolverInterface) {
},
resolver.DeleteMeetingTool,
)
mcp.AddTool(
server,
&mcp.Tool{
Name: "listMeetingAttendees",
Description: "List all attendees for a meeting",
InputSchema: types.ListMeetingAttendeesToolInputSchema,
OutputSchema: types.ListMeetingAttendeesToolOutputSchema,
Annotations: &mcp.ToolAnnotations{
ReadOnlyHint: true,
IdempotentHint: true,
},
},
resolver.ListMeetingAttendeesTool,
)
}
func boolPtr(b bool) *bool {

View File

@@ -4354,6 +4354,26 @@ components:
$ref: "#/components/schemas/GID"
description: Deleted meeting ID
ListMeetingAttendeesInput:
type: object
required:
- meeting_id
properties:
meeting_id:
$ref: "#/components/schemas/GID"
description: Meeting ID
ListMeetingAttendeesOutput:
type: object
required:
- attendees
properties:
attendees:
type: array
items:
$ref: "#/components/schemas/Profile"
description: List of attendee profiles
tools:
- name: listOrganizations
description: List all organizations the user has access to
@@ -5075,3 +5095,12 @@ tools:
$ref: "#/components/schemas/DeleteMeetingInput"
outputSchema:
$ref: "#/components/schemas/DeleteMeetingOutput"
- name: listMeetingAttendees
description: List all attendees for a meeting
hints:
readonly: true
idempotent: true
inputSchema:
$ref: "#/components/schemas/ListMeetingAttendeesInput"
outputSchema:
$ref: "#/components/schemas/ListMeetingAttendeesOutput"

View File

@@ -0,0 +1,33 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package types
import "go.probo.inc/probo/pkg/coredata"
func NewProfile(p *coredata.MembershipProfile) *Profile {
return &Profile{
ID: p.ID,
OrganizationID: p.OrganizationID,
FullName: p.FullName,
EmailAddress: p.EmailAddress,
AdditionalEmailAddresses: p.AdditionalEmailAddresses,
Kind: p.Kind,
Position: p.Position,
ContractStartDate: p.ContractStartDate,
ContractEndDate: p.ContractEndDate,
CreatedAt: p.CreatedAt,
UpdatedAt: p.UpdatedAt,
}
}

View File

@@ -119,6 +119,8 @@ var (
ListFrameworksToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"frameworks":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["frameworks"]}`)
ListMeasuresToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"query":{"type":"string","description":"Search query"},"state":{"type":"string","enum":["NOT_STARTED","IN_PROGRESS","NOT_APPLICABLE","IMPLEMENTED"]}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","NAME"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
ListMeasuresToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"measures":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string","description":"Measure category"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Measure description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Measure name"},"state":{"type":"string","enum":["NOT_STARTED","IN_PROGRESS","NOT_APPLICABLE","IMPLEMENTED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","category","name","state","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["measures"]}`)
ListMeetingAttendeesToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"meeting_id":{"type":"string","format":"string"}},"required":["meeting_id"]}`)
ListMeetingAttendeesToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"attendees":{"type":"array","items":{"type":"object","properties":{"additional_email_addresses":{"type":"array","items":{"type":"string","format":"string"},"description":"Additional email addresses"},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"email_address":{"type":"string","format":"string"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"description":"Position"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","full_name","email_address","additional_email_addresses","kind","created_at","updated_at"]},"description":"List of attendee profiles"}},"required":["attendees"]}`)
ListMeetingsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","DATE","NAME"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
ListMeetingsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"meetings":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"date":{"type":"string","description":"Meeting date","format":"date-time"},"id":{"type":"string","format":"string"},"minutes":{"description":"Meeting minutes","anyOf":[{"type":"string","description":"Meeting minutes"},{"type":"null","description":"No minutes"}]},"name":{"type":"string","description":"Meeting name"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","name","date","created_at","updated_at"]},"description":"List of meetings"},"next_cursor":{"description":"Next page cursor","anyOf":[{"type":"string","format":"string"},{"type":"null"}]}},"required":["meetings"]}`)
ListNonconformitiesToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"snapshot_id":{"type":"string","format":"string"}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","REFERENCE_ID","DATE_IDENTIFIED","DUE_DATE","STATUS"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
@@ -1642,6 +1644,18 @@ type ListMeasuresOutput struct {
NextCursor *page.CursorKey `json:"next_cursor,omitempty"`
}
// ListMeetingAttendeesInput represents the schema
type ListMeetingAttendeesInput struct {
// Meeting ID
MeetingID gid.GID `json:"meeting_id"`
}
// ListMeetingAttendeesOutput represents the schema
type ListMeetingAttendeesOutput struct {
// List of attendee profiles
Attendees []*Profile `json:"attendees"`
}
// ListMeetingsInput represents the schema
type ListMeetingsInput struct {
// Page cursor