diff --git a/pkg/server/api/mcp/v1/schema.resolvers.go b/pkg/server/api/mcp/v1/schema.resolvers.go index 0e09258f2..2f860842c 100644 --- a/pkg/server/api/mcp/v1/schema.resolvers.go +++ b/pkg/server/api/mcp/v1/schema.resolvers.go @@ -771,3 +771,107 @@ func (r *Resolver) UpdateNonconformityTool(ctx context.Context, req *mcp.CallToo Nonconformity: types.NewNonconformity(nonconformity), }, nil } + +func (r *Resolver) ListObligationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListObligationsInput) (*mcp.CallToolResult, types.ListObligationsOutput, error) { + r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionListObligations) + + prb := r.ProboService(ctx, input.OrganizationID) + + pageOrderBy := page.OrderBy[coredata.ObligationOrderField]{ + Field: coredata.ObligationOrderFieldCreatedAt, + Direction: page.OrderDirectionDesc, + } + if input.OrderBy != nil { + pageOrderBy = page.OrderBy[coredata.ObligationOrderField]{ + Field: input.OrderBy.Field, + Direction: input.OrderBy.Direction, + } + } + + cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy) + + var obligationFilter = coredata.NewObligationFilter(nil) + if input.Filter != nil { + obligationFilter = coredata.NewObligationFilter(&input.Filter.SnapshotID) + } + + page, err := prb.Obligations.ListForOrganizationID(ctx, input.OrganizationID, cursor, obligationFilter) + if err != nil { + panic(fmt.Errorf("cannot list organization obligations: %w", err)) + } + + return nil, types.NewListObligationsOutput(page), nil +} + +func (r *Resolver) GetObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetObligationInput) (*mcp.CallToolResult, types.GetObligationOutput, error) { + r.MustBeAuthorized(ctx, input.ID, authz.ActionGet) + + prb := r.ProboService(ctx, input.ID) + + obligation, err := prb.Obligations.Get(ctx, input.ID) + if err != nil { + return nil, types.GetObligationOutput{}, fmt.Errorf("failed to get obligation: %w", err) + } + + return nil, types.GetObligationOutput{ + Obligation: types.NewObligation(obligation), + }, nil +} + +func (r *Resolver) AddObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddObligationInput) (*mcp.CallToolResult, types.AddObligationOutput, error) { + r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateObligation) + + svc := r.ProboService(ctx, input.OrganizationID) + + obligation, err := svc.Obligations.Create( + ctx, + &probo.CreateObligationRequest{ + OrganizationID: input.OrganizationID, + Area: input.Area, + Source: input.Source, + Requirement: input.Requirement, + ActionsToBeImplemented: input.ActionsToBeImplemented, + Regulator: input.Regulator, + OwnerID: input.OwnerID, + LastReviewDate: input.LastReviewDate, + DueDate: input.DueDate, + Status: input.Status, + }, + ) + if err != nil { + return nil, types.AddObligationOutput{}, fmt.Errorf("failed to create obligation: %w", err) + } + + return nil, types.AddObligationOutput{ + Obligation: types.NewObligation(obligation), + }, nil +} + +func (r *Resolver) UpdateObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateObligationInput) (*mcp.CallToolResult, types.UpdateObligationOutput, error) { + r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateObligation) + + svc := r.ProboService(ctx, input.ID) + + obligation, err := svc.Obligations.Update( + ctx, + &probo.UpdateObligationRequest{ + ID: input.ID, + Area: UnwrapOmittable(input.Area), + Source: UnwrapOmittable(input.Source), + Requirement: UnwrapOmittable(input.Requirement), + ActionsToBeImplemented: UnwrapOmittable(input.ActionsToBeImplemented), + Regulator: UnwrapOmittable(input.Regulator), + OwnerID: input.OwnerID, + LastReviewDate: UnwrapOmittable(input.LastReviewDate), + DueDate: UnwrapOmittable(input.DueDate), + Status: input.Status, + }, + ) + if err != nil { + return nil, types.UpdateObligationOutput{}, fmt.Errorf("failed to update obligation: %w", err) + } + + return nil, types.UpdateObligationOutput{ + Obligation: types.NewObligation(obligation), + }, nil +} diff --git a/pkg/server/api/mcp/v1/server/server.go b/pkg/server/api/mcp/v1/server/server.go index aef494f0d..7d109e48f 100644 --- a/pkg/server/api/mcp/v1/server/server.go +++ b/pkg/server/api/mcp/v1/server/server.go @@ -41,6 +41,10 @@ type ResolverInterface interface { GetNonconformityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetNonconformityInput) (*mcp.CallToolResult, types.GetNonconformityOutput, error) AddNonconformityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddNonconformityInput) (*mcp.CallToolResult, types.AddNonconformityOutput, error) UpdateNonconformityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateNonconformityInput) (*mcp.CallToolResult, types.UpdateNonconformityOutput, error) + ListObligationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListObligationsInput) (*mcp.CallToolResult, types.ListObligationsOutput, error) + GetObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetObligationInput) (*mcp.CallToolResult, types.GetObligationOutput, error) + AddObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddObligationInput) (*mcp.CallToolResult, types.AddObligationOutput, error) + UpdateObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateObligationInput) (*mcp.CallToolResult, types.UpdateObligationOutput, error) } // New creates a new MCP server instance with all handlers registered. @@ -370,4 +374,44 @@ func registerToolHandlers(server *mcp.Server, resolver ResolverInterface) { }, resolver.UpdateNonconformityTool, ) + mcp.AddTool( + server, + &mcp.Tool{ + Name: "listObligations", + Description: "List all obligations for the organization", + InputSchema: types.ListObligationsToolInputSchema, + OutputSchema: types.ListObligationsToolOutputSchema, + }, + resolver.ListObligationsTool, + ) + mcp.AddTool( + server, + &mcp.Tool{ + Name: "getObligation", + Description: "Get an obligation by ID", + InputSchema: types.GetObligationToolInputSchema, + OutputSchema: types.GetObligationToolOutputSchema, + }, + resolver.GetObligationTool, + ) + mcp.AddTool( + server, + &mcp.Tool{ + Name: "addObligation", + Description: "Add a new obligation to the organization", + InputSchema: types.AddObligationToolInputSchema, + OutputSchema: types.AddObligationToolOutputSchema, + }, + resolver.AddObligationTool, + ) + mcp.AddTool( + server, + &mcp.Tool{ + Name: "updateObligation", + Description: "Update an existing obligation", + InputSchema: types.UpdateObligationToolInputSchema, + OutputSchema: types.UpdateObligationToolOutputSchema, + }, + resolver.UpdateObligationTool, + ) } diff --git a/pkg/server/api/mcp/v1/specification.yaml b/pkg/server/api/mcp/v1/specification.yaml index b5f5f989c..c85360b83 100644 --- a/pkg/server/api/mcp/v1/specification.yaml +++ b/pkg/server/api/mcp/v1/specification.yaml @@ -1683,6 +1683,282 @@ components: nonconformity: $ref: "#/components/schemas/Nonconformity" + ObligationStatus: + type: string + enum: + - NON_COMPLIANT + - PARTIALLY_COMPLIANT + - COMPLIANT + go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.ObligationStatus + + ObligationOrderField: + type: string + enum: + - CREATED_AT + - LAST_REVIEW_DATE + - DUE_DATE + - STATUS + go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.ObligationOrderField + + ObligationOrderBy: + type: object + required: + - field + - direction + properties: + field: + $ref: "#/components/schemas/ObligationOrderField" + description: Obligation order field + direction: + $ref: "#/components/schemas/OrderDirection" + description: Obligation order direction + + Obligation: + type: object + required: + - id + - organization_id + - owner_id + - status + - created_at + - updated_at + properties: + id: + $ref: "#/components/schemas/GID" + description: Obligation ID + organization_id: + $ref: "#/components/schemas/GID" + description: Organization ID + snapshot_id: + anyOf: + - $ref: "#/components/schemas/GID" + description: Snapshot ID + - type: "null" + description: No snapshot + description: Snapshot ID + source_id: + type: + - string + - "null" + description: Source ID + area: + type: + - string + - "null" + description: Area + source: + type: + - string + - "null" + description: Source + requirement: + type: + - string + - "null" + description: Requirement + actions_to_be_implemented: + type: + - string + - "null" + description: Actions to be implemented + regulator: + type: + - string + - "null" + description: Regulator + owner_id: + $ref: "#/components/schemas/GID" + description: Owner ID + last_review_date: + type: + - string + - "null" + format: date-time + description: Last review date + due_date: + type: + - string + - "null" + format: date-time + description: Due date + status: + $ref: "#/components/schemas/ObligationStatus" + description: Status + created_at: + type: string + format: date-time + description: Creation timestamp + updated_at: + type: string + format: date-time + description: Update timestamp + + ListObligationsInput: + type: object + required: + - organization_id + properties: + organization_id: + $ref: "#/components/schemas/GID" + description: Organization ID + order_by: + $ref: "#/components/schemas/ObligationOrderBy" + description: Obligation order by + size: + type: integer + description: Page size + cursor: + $ref: "#/components/schemas/CursorKey" + description: Page cursor + filter: + type: object + properties: + snapshot_id: + $ref: "#/components/schemas/GID" + description: Snapshot ID + + ListObligationsOutput: + type: object + required: + - obligations + properties: + next_cursor: + $ref: "#/components/schemas/CursorKey" + description: Next cursor + obligations: + type: array + items: + $ref: "#/components/schemas/Obligation" + + GetObligationInput: + type: object + required: + - id + properties: + id: + $ref: "#/components/schemas/GID" + description: Obligation ID + + GetObligationOutput: + type: object + required: + - obligation + properties: + obligation: + $ref: "#/components/schemas/Obligation" + + AddObligationInput: + type: object + required: + - organization_id + - owner_id + - status + properties: + organization_id: + $ref: "#/components/schemas/GID" + description: Organization ID + area: + type: string + description: Area + source: + type: string + description: Source + requirement: + type: string + description: Requirement + actions_to_be_implemented: + type: string + description: Actions to be implemented + regulator: + type: string + description: Regulator + owner_id: + $ref: "#/components/schemas/GID" + description: Owner ID + last_review_date: + type: string + format: date-time + description: Last review date + due_date: + type: string + format: date-time + description: Due date + status: + anyOf: + - $ref: "#/components/schemas/ObligationStatus" + description: Obligation status + - type: "null" + description: No status + description: Status + + AddObligationOutput: + type: object + required: + - obligation + properties: + obligation: + $ref: "#/components/schemas/Obligation" + + UpdateObligationInput: + type: object + required: + - id + properties: + id: + $ref: "#/components/schemas/GID" + description: Obligation ID + area: + type: ["string", "null"] + description: Area + go.probo.inc/mcpgen/omittable: true + source: + type: ["string", "null"] + description: Source + go.probo.inc/mcpgen/omittable: true + requirement: + type: ["string", "null"] + description: Requirement + go.probo.inc/mcpgen/omittable: true + actions_to_be_implemented: + type: ["string", "null"] + description: Actions to be implemented + go.probo.inc/mcpgen/omittable: true + regulator: + type: ["string", "null"] + description: Regulator + go.probo.inc/mcpgen/omittable: true + owner_id: + anyOf: + - type: string + $ref: "#/components/schemas/GID" + - type: "null" + description: Owner ID + last_review_date: + type: ["string", "null"] + format: date-time + description: Last review date + go.probo.inc/mcpgen/omittable: true + due_date: + type: ["string", "null"] + format: date-time + description: Due date + go.probo.inc/mcpgen/omittable: true + status: + anyOf: + - $ref: "#/components/schemas/ObligationStatus" + description: Obligation status + - type: "null" + description: No status + description: Status + + UpdateObligationOutput: + type: object + required: + - obligation + properties: + obligation: + $ref: "#/components/schemas/Obligation" + tools: - name: listOrganizations description: List all organizations the user has access to @@ -1901,3 +2177,31 @@ tools: $ref: "#/components/schemas/UpdateNonconformityInput" outputSchema: $ref: "#/components/schemas/UpdateNonconformityOutput" + - name: listObligations + description: List all obligations for the organization + readonly: true + inputSchema: + $ref: "#/components/schemas/ListObligationsInput" + outputSchema: + $ref: "#/components/schemas/ListObligationsOutput" + - name: getObligation + description: Get an obligation by ID + readonly: true + inputSchema: + $ref: "#/components/schemas/GetObligationInput" + outputSchema: + $ref: "#/components/schemas/GetObligationOutput" + - name: addObligation + description: Add a new obligation to the organization + readonly: false + inputSchema: + $ref: "#/components/schemas/AddObligationInput" + outputSchema: + $ref: "#/components/schemas/AddObligationOutput" + - name: updateObligation + description: Update an existing obligation + readonly: false + inputSchema: + $ref: "#/components/schemas/UpdateObligationInput" + outputSchema: + $ref: "#/components/schemas/UpdateObligationOutput" diff --git a/pkg/server/api/mcp/v1/types/obligation.go b/pkg/server/api/mcp/v1/types/obligation.go new file mode 100644 index 000000000..cc3c0e342 --- /dev/null +++ b/pkg/server/api/mcp/v1/types/obligation.go @@ -0,0 +1,57 @@ +// Copyright (c) 2025 Probo Inc . +// +// 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" + "go.probo.inc/probo/pkg/page" +) + +func NewObligation(o *coredata.Obligation) *Obligation { + return &Obligation{ + ID: o.ID, + OrganizationID: o.OrganizationID, + SnapshotID: o.SnapshotID, + Area: o.Area, + Source: o.Source, + Requirement: o.Requirement, + ActionsToBeImplemented: o.ActionsToBeImplemented, + Regulator: o.Regulator, + OwnerID: o.OwnerID, + LastReviewDate: o.LastReviewDate, + DueDate: o.DueDate, + Status: o.Status, + CreatedAt: o.CreatedAt, + UpdatedAt: o.UpdatedAt, + } +} + +func NewListObligationsOutput(obligationPage *page.Page[*coredata.Obligation, coredata.ObligationOrderField]) ListObligationsOutput { + obligations := make([]*Obligation, 0, len(obligationPage.Data)) + for _, v := range obligationPage.Data { + obligations = append(obligations, NewObligation(v)) + } + + var nextCursor *page.CursorKey + if len(obligationPage.Data) > 0 { + cursorKey := obligationPage.Data[len(obligationPage.Data)-1].CursorKey(obligationPage.Cursor.OrderBy.Field) + nextCursor = &cursorKey + } + + return ListObligationsOutput{ + NextCursor: nextCursor, + Obligations: obligations, + } +} diff --git a/pkg/server/api/mcp/v1/types/types.go b/pkg/server/api/mcp/v1/types/types.go index fe9a38212..b3d83fbce 100644 --- a/pkg/server/api/mcp/v1/types/types.go +++ b/pkg/server/api/mcp/v1/types/types.go @@ -22,6 +22,8 @@ var ( AddMeasureToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["measure"],"properties":{"measure":{"type":"object","required":["id","category","name","state","created_at","updated_at"],"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"}}}}}`) AddNonconformityToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","reference_id","audit_id","root_cause","owner_id","status"],"properties":{"audit_id":{"type":"string","format":"string"},"corrective_action":{"type":"string","description":"Corrective action"},"date_identified":{"type":"string","description":"Date identified","format":"date-time"},"description":{"type":"string","description":"Description"},"due_date":{"type":"string","description":"Due date","format":"date-time"},"effectiveness_check":{"type":"string","description":"Effectiveness check"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"reference_id":{"type":"string","description":"Reference ID"},"root_cause":{"type":"string","description":"Root cause"},"status":{"description":"Status","anyOf":[{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},{"type":"null","description":"No status"}]}}}`) AddNonconformityToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["nonconformity"],"properties":{"nonconformity":{"type":"object","required":["id","organization_id","reference_id","audit_id","root_cause","owner_id","status","created_at","updated_at"],"properties":{"audit_id":{"type":"string","format":"string"},"corrective_action":{"description":"Corrective action"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"date_identified":{"description":"Date identified","format":"date-time"},"description":{"description":"Description"},"due_date":{"description":"Due date","format":"date-time"},"effectiveness_check":{"description":"Effectiveness check"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"reference_id":{"type":"string","description":"Reference ID"},"root_cause":{"type":"string","description":"Root cause"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) + AddObligationToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","owner_id","status"],"properties":{"actions_to_be_implemented":{"type":"string","description":"Actions to be implemented"},"area":{"type":"string","description":"Area"},"due_date":{"type":"string","description":"Due date","format":"date-time"},"last_review_date":{"type":"string","description":"Last review date","format":"date-time"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"regulator":{"type":"string","description":"Regulator"},"requirement":{"type":"string","description":"Requirement"},"source":{"type":"string","description":"Source"},"status":{"description":"Status","anyOf":[{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},{"type":"null","description":"No status"}]}}}`) + AddObligationToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["obligation"],"properties":{"obligation":{"type":"object","required":["id","organization_id","owner_id","status","created_at","updated_at"],"properties":{"actions_to_be_implemented":{"description":"Actions to be implemented"},"area":{"description":"Area"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"due_date":{"description":"Due date","format":"date-time"},"id":{"type":"string","format":"string"},"last_review_date":{"description":"Last review date","format":"date-time"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"regulator":{"description":"Regulator"},"requirement":{"description":"Requirement"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) AddPeopleToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","full_name","primary_email_address","kind"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string"}},"contract_end_date":{"type":"string","description":"Contract end date","format":"date-time"},"contract_start_date":{"type":"string","description":"Contract start date","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"type":"string","description":"Position"},"primary_email_address":{"type":"string","description":"Primary email address"}}}`) AddPeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"people":{"type":"object","required":["id","organization_id","full_name","primary_email_address","additional_email_addresses","kind","created_at","updated_at"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string"}},"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"},"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"},"primary_email_address":{"type":"string","description":"Primary email address"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) AddRiskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","name","category","treatment","inherent_likelihood","inherent_impact"],"properties":{"category":{"type":"string","description":"Risk category"},"description":{"type":"string","description":"Risk description"},"inherent_impact":{"type":"integer","description":"Inherent impact"},"inherent_likelihood":{"type":"integer","description":"Inherent likelihood"},"name":{"type":"string","description":"Risk name"},"note":{"type":"string","description":"Risk note"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"residual_impact":{"type":"integer","description":"Residual impact"},"residual_likelihood":{"type":"integer","description":"Residual likelihood"},"treatment":{"type":"string","enum":["MITIGATED","ACCEPTED","AVOIDED","TRANSFERRED"]}}}`) @@ -38,6 +40,8 @@ var ( GetMeasureToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["measure"],"properties":{"measure":{"type":"object","required":["id","category","name","state","created_at","updated_at"],"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"}}}}}`) GetNonconformityToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`) GetNonconformityToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["nonconformity"],"properties":{"nonconformity":{"type":"object","required":["id","organization_id","reference_id","audit_id","root_cause","owner_id","status","created_at","updated_at"],"properties":{"audit_id":{"type":"string","format":"string"},"corrective_action":{"description":"Corrective action"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"date_identified":{"description":"Date identified","format":"date-time"},"description":{"description":"Description"},"due_date":{"description":"Due date","format":"date-time"},"effectiveness_check":{"description":"Effectiveness check"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"reference_id":{"type":"string","description":"Reference ID"},"root_cause":{"type":"string","description":"Root cause"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) + GetObligationToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`) + GetObligationToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["obligation"],"properties":{"obligation":{"type":"object","required":["id","organization_id","owner_id","status","created_at","updated_at"],"properties":{"actions_to_be_implemented":{"description":"Actions to be implemented"},"area":{"description":"Area"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"due_date":{"description":"Due date","format":"date-time"},"id":{"type":"string","format":"string"},"last_review_date":{"description":"Last review date","format":"date-time"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"regulator":{"description":"Regulator"},"requirement":{"description":"Requirement"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) GetPeopleToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`) GetPeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"people":{"type":"object","required":["id","organization_id","full_name","primary_email_address","additional_email_addresses","kind","created_at","updated_at"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string"}},"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"},"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"},"primary_email_address":{"type":"string","description":"Primary email address"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) GetRiskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`) @@ -52,6 +56,8 @@ var ( ListMeasuresToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["measures"],"properties":{"measures":{"type":"array","items":{"type":"object","required":["id","category","name","state","created_at","updated_at"],"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"}}}},"next_cursor":{"type":"string","format":"string"}}}`) ListNonconformitiesToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id"],"properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"snapshot_id":{"type":"string","format":"string"}}},"order_by":{"type":"object","required":["field","direction"],"properties":{"direction":{"type":"string","enum":["asc","desc"]},"field":{"type":"string","enum":["CREATED_AT","REFERENCE_ID","DATE_IDENTIFIED","DUE_DATE","STATUS"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`) ListNonconformitiesToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["nonconformities"],"properties":{"next_cursor":{"type":"string","format":"string"},"nonconformities":{"type":"array","items":{"type":"object","required":["id","organization_id","reference_id","audit_id","root_cause","owner_id","status","created_at","updated_at"],"properties":{"audit_id":{"type":"string","format":"string"},"corrective_action":{"description":"Corrective action"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"date_identified":{"description":"Date identified","format":"date-time"},"description":{"description":"Description"},"due_date":{"description":"Due date","format":"date-time"},"effectiveness_check":{"description":"Effectiveness check"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"reference_id":{"type":"string","description":"Reference ID"},"root_cause":{"type":"string","description":"Root cause"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}}`) + ListObligationsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id"],"properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"snapshot_id":{"type":"string","format":"string"}}},"order_by":{"type":"object","required":["field","direction"],"properties":{"direction":{"type":"string","enum":["asc","desc"]},"field":{"type":"string","enum":["CREATED_AT","LAST_REVIEW_DATE","DUE_DATE","STATUS"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`) + ListObligationsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["obligations"],"properties":{"next_cursor":{"type":"string","format":"string"},"obligations":{"type":"array","items":{"type":"object","required":["id","organization_id","owner_id","status","created_at","updated_at"],"properties":{"actions_to_be_implemented":{"description":"Actions to be implemented"},"area":{"description":"Area"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"due_date":{"description":"Due date","format":"date-time"},"id":{"type":"string","format":"string"},"last_review_date":{"description":"Last review date","format":"date-time"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"regulator":{"description":"Regulator"},"requirement":{"description":"Requirement"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}}`) ListOrganizationsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"organization_id":{"type":"string","format":"string"}}}`) ListOrganizationsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"organizations":{"type":"array","items":{"type":"object","required":["id","name","description","created_at","updated_at"],"properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Organization description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Organization name"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}}`) ListPeopleToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id"],"properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"exclude_contract_ended":{"type":"boolean","description":"Exclude people with ended contracts"}}},"order_by":{"type":"object","required":["field","direction"],"properties":{"direction":{"type":"string","enum":["asc","desc"]},"field":{"type":"string","enum":["CREATED_AT","FULL_NAME","KIND"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`) @@ -70,6 +76,8 @@ var ( UpdateMeasureToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["measure"],"properties":{"measure":{"type":"object","required":["id","category","name","state","created_at","updated_at"],"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"}}}}}`) UpdateNonconformityToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"audit_id":{"description":"Audit ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"corrective_action":{"description":"Corrective action"},"date_identified":{"description":"Date identified","format":"date-time"},"description":{"description":"Description"},"due_date":{"description":"Due date","format":"date-time"},"effectiveness_check":{"description":"Effectiveness check"},"id":{"type":"string","format":"string"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"reference_id":{"type":"string","description":"Reference ID"},"root_cause":{"type":"string","description":"Root cause"},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]}}}`) UpdateNonconformityToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["nonconformity"],"properties":{"nonconformity":{"type":"object","required":["id","organization_id","reference_id","audit_id","root_cause","owner_id","status","created_at","updated_at"],"properties":{"audit_id":{"type":"string","format":"string"},"corrective_action":{"description":"Corrective action"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"date_identified":{"description":"Date identified","format":"date-time"},"description":{"description":"Description"},"due_date":{"description":"Due date","format":"date-time"},"effectiveness_check":{"description":"Effectiveness check"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"reference_id":{"type":"string","description":"Reference ID"},"root_cause":{"type":"string","description":"Root cause"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) + UpdateObligationToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"actions_to_be_implemented":{"description":"Actions to be implemented"},"area":{"description":"Area"},"due_date":{"description":"Due date","format":"date-time"},"id":{"type":"string","format":"string"},"last_review_date":{"description":"Last review date","format":"date-time"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"regulator":{"description":"Regulator"},"requirement":{"description":"Requirement"},"source":{"description":"Source"},"status":{"description":"Status","anyOf":[{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},{"type":"null","description":"No status"}]}}}`) + UpdateObligationToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["obligation"],"properties":{"obligation":{"type":"object","required":["id","organization_id","owner_id","status","created_at","updated_at"],"properties":{"actions_to_be_implemented":{"description":"Actions to be implemented"},"area":{"description":"Area"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"due_date":{"description":"Due date","format":"date-time"},"id":{"type":"string","format":"string"},"last_review_date":{"description":"Last review date","format":"date-time"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"regulator":{"description":"Regulator"},"requirement":{"description":"Requirement"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) UpdateRiskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"category":{"type":"string","description":"Risk category"},"description":{"description":"Risk description"},"id":{"type":"string","format":"string"},"inherent_impact":{"type":"integer","description":"Inherent impact"},"inherent_likelihood":{"type":"integer","description":"Inherent likelihood"},"name":{"type":"string","description":"Risk name"},"note":{"type":"string","description":"Risk note"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"residual_impact":{"type":"integer","description":"Residual impact"},"residual_likelihood":{"type":"integer","description":"Residual likelihood"},"treatment":{"type":"string","enum":["MITIGATED","ACCEPTED","AVOIDED","TRANSFERRED"]}}}`) UpdateRiskToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["risk"],"properties":{"risk":{"type":"object","required":["id","organization_id","name","category","treatment","inherent_likelihood","inherent_impact","inherent_risk_score","residual_likelihood","residual_impact","residual_risk_score","note","created_at","updated_at"],"properties":{"category":{"type":"string","description":"Risk category"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Risk description"},"id":{"type":"string","format":"string"},"inherent_impact":{"type":"integer","description":"Inherent impact"},"inherent_likelihood":{"type":"integer","description":"Inherent likelihood"},"inherent_risk_score":{"type":"integer","description":"Inherent risk score"},"name":{"type":"string","description":"Risk name"},"note":{"type":"string","description":"Risk note"},"organization_id":{"type":"string","format":"string"},"owner_id":{"description":"Owner ID"},"residual_impact":{"type":"integer","description":"Residual impact"},"residual_likelihood":{"type":"integer","description":"Residual likelihood"},"residual_risk_score":{"type":"integer","description":"Residual risk score"},"snapshot_id":{"description":"Snapshot ID"},"treatment":{"type":"string","enum":["MITIGATED","ACCEPTED","AVOIDED","TRANSFERRED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) UpdateVendorToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"description":{"type":"string","description":"Vendor description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Vendor name"}}}`) @@ -181,6 +189,35 @@ type AddNonconformityOutput struct { Nonconformity *Nonconformity `json:"nonconformity"` } +// AddObligationInput represents the schema +type AddObligationInput struct { + // Actions to be implemented + ActionsToBeImplemented *string `json:"actions_to_be_implemented,omitempty"` + // Area + Area *string `json:"area,omitempty"` + // Due date + DueDate *time.Time `json:"due_date,omitempty"` + // Last review date + LastReviewDate *time.Time `json:"last_review_date,omitempty"` + // Organization ID + OrganizationID gid.GID `json:"organization_id"` + // Owner ID + OwnerID gid.GID `json:"owner_id"` + // Regulator + Regulator *string `json:"regulator,omitempty"` + // Requirement + Requirement *string `json:"requirement,omitempty"` + // Source + Source *string `json:"source,omitempty"` + // Status + Status *coredata.ObligationStatus `json:"status"` +} + +// AddObligationOutput represents the schema +type AddObligationOutput struct { + Obligation *Obligation `json:"obligation"` +} + // AddPeopleInput represents the schema type AddPeopleInput struct { // Additional email addresses @@ -395,6 +432,17 @@ type GetNonconformityOutput struct { Nonconformity *Nonconformity `json:"nonconformity"` } +// GetObligationInput represents the schema +type GetObligationInput struct { + // Obligation ID + ID gid.GID `json:"id"` +} + +// GetObligationOutput represents the schema +type GetObligationOutput struct { + Obligation *Obligation `json:"obligation"` +} + // GetPeopleInput represents the schema type GetPeopleInput struct { // People ID @@ -516,6 +564,26 @@ type ListNonconformitiesOutput struct { Nonconformities []*Nonconformity `json:"nonconformities"` } +// ListObligationsInput represents the schema +type ListObligationsInput struct { + // Page cursor + Cursor *page.CursorKey `json:"cursor,omitempty"` + Filter *ListObligationsInputFilter `json:"filter,omitempty"` + // Obligation order by + OrderBy *ObligationOrderBy `json:"order_by,omitempty"` + // Organization ID + OrganizationID gid.GID `json:"organization_id"` + // Page size + Size *int `json:"size,omitempty"` +} + +// ListObligationsOutput represents the schema +type ListObligationsOutput struct { + // Next cursor + NextCursor *page.CursorKey `json:"next_cursor,omitempty"` + Obligations []*Obligation `json:"obligations"` +} + // ListOrganizationsInput represents the schema type ListOrganizationsInput struct { // Organization ID @@ -655,6 +723,48 @@ type NonconformityOrderBy struct { Field coredata.NonconformityOrderField `json:"field"` } +// Obligation represents the schema +type Obligation struct { + // Actions to be implemented + ActionsToBeImplemented *string `json:"actions_to_be_implemented,omitempty"` + // Area + Area *string `json:"area,omitempty"` + // Creation timestamp + CreatedAt time.Time `json:"created_at"` + // Due date + DueDate *time.Time `json:"due_date,omitempty"` + // Obligation ID + ID gid.GID `json:"id"` + // Last review date + LastReviewDate *time.Time `json:"last_review_date,omitempty"` + // Organization ID + OrganizationID gid.GID `json:"organization_id"` + // Owner ID + OwnerID gid.GID `json:"owner_id"` + // Regulator + Regulator *string `json:"regulator,omitempty"` + // Requirement + Requirement *string `json:"requirement,omitempty"` + // Snapshot ID + SnapshotID *gid.GID `json:"snapshot_id,omitempty"` + // Source + Source *string `json:"source,omitempty"` + // Source ID + SourceID *string `json:"source_id,omitempty"` + // Status + Status coredata.ObligationStatus `json:"status"` + // Update timestamp + UpdatedAt time.Time `json:"updated_at"` +} + +// ObligationOrderBy represents the schema +type ObligationOrderBy struct { + // Obligation order direction + Direction page.OrderDirection `json:"direction"` + // Obligation order field + Field coredata.ObligationOrderField `json:"field"` +} + // Organization represents the schema type Organization struct { // Creation timestamp @@ -856,6 +966,35 @@ type UpdateNonconformityOutput struct { Nonconformity *Nonconformity `json:"nonconformity"` } +// UpdateObligationInput represents the schema +type UpdateObligationInput struct { + // Actions to be implemented + ActionsToBeImplemented mcp.Omittable[*string] `json:"actions_to_be_implemented,omitempty"` + // Area + Area mcp.Omittable[*string] `json:"area,omitempty"` + // Due date + DueDate mcp.Omittable[*time.Time] `json:"due_date,omitempty"` + // Obligation ID + ID gid.GID `json:"id"` + // Last review date + LastReviewDate mcp.Omittable[*time.Time] `json:"last_review_date,omitempty"` + // Owner ID + OwnerID *gid.GID `json:"owner_id,omitempty"` + // Regulator + Regulator mcp.Omittable[*string] `json:"regulator,omitempty"` + // Requirement + Requirement mcp.Omittable[*string] `json:"requirement,omitempty"` + // Source + Source mcp.Omittable[*string] `json:"source,omitempty"` + // Status + Status *coredata.ObligationStatus `json:"status,omitempty"` +} + +// UpdateObligationOutput represents the schema +type UpdateObligationOutput struct { + Obligation *Obligation `json:"obligation"` +} + // UpdateRiskInput represents the schema type UpdateRiskInput struct { // Risk category @@ -952,6 +1091,12 @@ type ListNonconformitiesInputFilter struct { SnapshotID *gid.GID `json:"snapshot_id,omitempty"` } +// ListObligationsInputFilter represents the schema +type ListObligationsInputFilter struct { + // Snapshot ID + SnapshotID *gid.GID `json:"snapshot_id,omitempty"` +} + // ListPeopleInputFilter represents the schema type ListPeopleInputFilter struct { // Exclude people with ended contracts