Add measures tools

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2025-11-23 21:03:21 +01:00
parent fa97a8e9c6
commit 963fbd8eab
5 changed files with 501 additions and 0 deletions

View File

@@ -292,3 +292,93 @@ func (r *Resolver) UpdateRiskTool(ctx context.Context, req *mcp.CallToolRequest,
Risk: types.NewRisk(risk),
}, nil
}
func (r *Resolver) ListMeasuresTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasuresInput) (*mcp.CallToolResult, types.ListMeasuresOutput, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionListMeasures)
prb := r.ProboService(ctx, input.OrganizationID)
pageOrderBy := page.OrderBy[coredata.MeasureOrderField]{
Field: coredata.MeasureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.MeasureOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
var measureFilter = coredata.NewMeasureFilter(nil, nil)
if input.Filter != nil {
measureFilter = coredata.NewMeasureFilter(input.Filter.Query, input.Filter.State)
}
page, err := prb.Measures.ListForOrganizationID(ctx, input.OrganizationID, cursor, measureFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization measures: %w", err))
}
return nil, types.NewListMeasuresOutput(page), nil
}
func (r *Resolver) GetMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetMeasureInput) (*mcp.CallToolResult, types.GetMeasureOutput, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionGet)
prb := r.ProboService(ctx, input.ID)
measure, err := prb.Measures.Get(ctx, input.ID)
if err != nil {
return nil, types.GetMeasureOutput{}, fmt.Errorf("failed to get measure: %w", err)
}
return nil, types.GetMeasureOutput{
Measure: types.NewMeasure(measure),
}, nil
}
func (r *Resolver) AddMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddMeasureInput) (*mcp.CallToolResult, types.AddMeasureOutput, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateMeasure)
svc := r.ProboService(ctx, input.OrganizationID)
measure, err := svc.Measures.Create(
ctx,
probo.CreateMeasureRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
Category: input.Category,
},
)
if err != nil {
return nil, types.AddMeasureOutput{}, fmt.Errorf("failed to create measure: %w", err)
}
return nil, types.AddMeasureOutput{
Measure: types.NewMeasure(measure),
}, nil
}
func (r *Resolver) UpdateMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateMeasureInput) (*mcp.CallToolResult, types.UpdateMeasureOutput, error) {
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateMeasure)
svc := r.ProboService(ctx, input.ID)
measure, err := svc.Measures.Update(
ctx,
probo.UpdateMeasureRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
Category: input.Category,
State: input.State,
},
)
if err != nil {
return nil, types.UpdateMeasureOutput{}, fmt.Errorf("failed to update measure: %w", err)
}
return nil, types.UpdateMeasureOutput{
Measure: types.NewMeasure(measure),
}, nil
}

View File

@@ -21,6 +21,10 @@ type ResolverInterface interface {
GetRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskInput) (*mcp.CallToolResult, types.GetRiskOutput, error)
AddRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskInput) (*mcp.CallToolResult, types.AddRiskOutput, error)
UpdateRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskInput) (*mcp.CallToolResult, types.UpdateRiskOutput, error)
ListMeasuresTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasuresInput) (*mcp.CallToolResult, types.ListMeasuresOutput, error)
GetMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetMeasureInput) (*mcp.CallToolResult, types.GetMeasureOutput, error)
AddMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddMeasureInput) (*mcp.CallToolResult, types.AddMeasureOutput, error)
UpdateMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateMeasureInput) (*mcp.CallToolResult, types.UpdateMeasureOutput, error)
}
// New creates a new MCP server instance with all handlers registered.
@@ -150,4 +154,44 @@ func registerToolHandlers(server *mcp.Server, resolver ResolverInterface) {
},
resolver.UpdateRiskTool,
)
mcp.AddTool(
server,
&mcp.Tool{
Name: "listMeasures",
Description: "List all measures for the organization",
InputSchema: types.ListMeasuresToolInputSchema,
OutputSchema: types.ListMeasuresToolOutputSchema,
},
resolver.ListMeasuresTool,
)
mcp.AddTool(
server,
&mcp.Tool{
Name: "getMeasure",
Description: "Get a measure by ID",
InputSchema: types.GetMeasureToolInputSchema,
OutputSchema: types.GetMeasureToolOutputSchema,
},
resolver.GetMeasureTool,
)
mcp.AddTool(
server,
&mcp.Tool{
Name: "addMeasure",
Description: "Add a new measure to the organization",
InputSchema: types.AddMeasureToolInputSchema,
OutputSchema: types.AddMeasureToolOutputSchema,
},
resolver.AddMeasureTool,
)
mcp.AddTool(
server,
&mcp.Tool{
Name: "updateMeasure",
Description: "Update an existing measure",
InputSchema: types.UpdateMeasureToolInputSchema,
OutputSchema: types.UpdateMeasureToolOutputSchema,
},
resolver.UpdateMeasureTool,
)
}

View File

@@ -671,6 +671,186 @@ components:
risk:
$ref: "#/components/schemas/Risk"
MeasureState:
type: string
enum:
- NOT_STARTED
- IN_PROGRESS
- NOT_APPLICABLE
- IMPLEMENTED
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.MeasureState
MeasureOrderField:
type: string
enum:
- CREATED_AT
- NAME
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.MeasureOrderField
MeasureOrderBy:
type: object
required:
- field
- direction
properties:
field:
$ref: "#/components/schemas/MeasureOrderField"
description: Measure order field
direction:
$ref: "#/components/schemas/OrderDirection"
description: Measure order direction
Measure:
type: object
required:
- id
- category
- name
- state
- created_at
- updated_at
properties:
id:
$ref: "#/components/schemas/GID"
description: Measure ID
category:
type: string
description: Measure category
name:
type: string
description: Measure name
description:
type:
- string
- "null"
description: Measure description
state:
$ref: "#/components/schemas/MeasureState"
description: Measure state
created_at:
type: string
format: date-time
description: Creation timestamp
updated_at:
type: string
format: date-time
description: Update timestamp
ListMeasuresInput:
type: object
required:
- organization_id
properties:
organization_id:
$ref: "#/components/schemas/GID"
description: Organization ID
order_by:
$ref: "#/components/schemas/MeasureOrderBy"
description: Measure order by
size:
type: integer
description: Page size
cursor:
$ref: "#/components/schemas/CursorKey"
description: Page cursor
filter:
type: object
properties:
query:
type: string
description: Search query
state:
$ref: "#/components/schemas/MeasureState"
description: Measure state filter
ListMeasuresOutput:
type: object
required:
- measures
properties:
next_cursor:
$ref: "#/components/schemas/CursorKey"
description: Next cursor
measures:
type: array
items:
$ref: "#/components/schemas/Measure"
GetMeasureInput:
type: object
required:
- id
properties:
id:
$ref: "#/components/schemas/GID"
description: Measure ID
GetMeasureOutput:
type: object
required:
- measure
properties:
measure:
$ref: "#/components/schemas/Measure"
AddMeasureInput:
type: object
required:
- organization_id
- name
- category
properties:
organization_id:
$ref: "#/components/schemas/GID"
description: Organization ID
name:
type: string
description: Measure name
description:
type: string
description: Measure description
category:
type: string
description: Measure category
AddMeasureOutput:
type: object
required:
- measure
properties:
measure:
$ref: "#/components/schemas/Measure"
UpdateMeasureInput:
type: object
required:
- id
properties:
id:
$ref: "#/components/schemas/GID"
description: Measure ID
name:
type: string
description: Measure name
description:
type: ["string", "null"]
description: Measure description
go.probo.inc/mcpgen/omittable: true
category:
type: string
description: Measure category
state:
$ref: "#/components/schemas/MeasureState"
description: Measure state
UpdateMeasureOutput:
type: object
required:
- measure
properties:
measure:
$ref: "#/components/schemas/Measure"
tools:
- name: listOrganizations
description: List all organizations the user has access to
@@ -749,3 +929,31 @@ tools:
$ref: "#/components/schemas/UpdateRiskInput"
outputSchema:
$ref: "#/components/schemas/UpdateRiskOutput"
- name: listMeasures
description: List all measures for the organization
readonly: true
inputSchema:
$ref: "#/components/schemas/ListMeasuresInput"
outputSchema:
$ref: "#/components/schemas/ListMeasuresOutput"
- name: getMeasure
description: Get a measure by ID
readonly: true
inputSchema:
$ref: "#/components/schemas/GetMeasureInput"
outputSchema:
$ref: "#/components/schemas/GetMeasureOutput"
- name: addMeasure
description: Add a new measure to the organization
readonly: false
inputSchema:
$ref: "#/components/schemas/AddMeasureInput"
outputSchema:
$ref: "#/components/schemas/AddMeasureOutput"
- name: updateMeasure
description: Update an existing measure
readonly: false
inputSchema:
$ref: "#/components/schemas/UpdateMeasureInput"
outputSchema:
$ref: "#/components/schemas/UpdateMeasureOutput"

View File

@@ -0,0 +1,50 @@
// 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"
"go.probo.inc/probo/pkg/page"
)
func NewMeasure(m *coredata.Measure) *Measure {
return &Measure{
ID: m.ID,
Category: m.Category,
Name: m.Name,
Description: m.Description,
State: m.State,
CreatedAt: m.CreatedAt,
UpdatedAt: m.UpdatedAt,
}
}
func NewListMeasuresOutput(measurePage *page.Page[*coredata.Measure, coredata.MeasureOrderField]) ListMeasuresOutput {
measures := make([]*Measure, 0, len(measurePage.Data))
for _, v := range measurePage.Data {
measures = append(measures, NewMeasure(v))
}
var nextCursor *page.CursorKey
if len(measurePage.Data) > 0 {
cursorKey := measurePage.Data[len(measurePage.Data)-1].CursorKey(measurePage.Cursor.OrderBy.Field)
nextCursor = &cursorKey
}
return ListMeasuresOutput{
NextCursor: nextCursor,
Measures: measures,
}
}

View File

@@ -12,16 +12,22 @@ import (
// Tool input schemas
var (
AddMeasureToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","name","category"],"properties":{"category":{"type":"string","description":"Measure category"},"description":{"type":"string","description":"Measure description"},"name":{"type":"string","description":"Measure name"},"organization_id":{"type":"string","format":"string"}}}`)
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"}}}}}`)
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"]}}}`)
AddRiskToolOutputSchema = 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"}}}}}`)
AddVendorToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","name"],"properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"type":"string","description":"Vendor description"},"name":{"type":"string","description":"Vendor name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}`)
AddVendorToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["vendor"],"properties":{"vendor":{"type":"object","required":["id","name","organization_id","created_at","updated_at"],"properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Vendor description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Vendor name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
GetMeasureToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`)
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"}}}}}`)
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"}}}`)
GetRiskToolOutputSchema = 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"}}}}}`)
ListMeasuresToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id"],"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","required":["field","direction"],"properties":{"direction":{"type":"string","enum":["asc","desc"]},"field":{"type":"string","enum":["CREATED_AT","NAME"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`)
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"}}}`)
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"}}}`)
@@ -30,12 +36,31 @@ var (
ListRisksToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["risks"],"properties":{"next_cursor":{"type":"string","format":"string"},"risks":{"type":"array","items":{"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"}}}}}}`)
ListVendorsToolInputSchema = 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","UPDATED_AT","NAME"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`)
ListVendorsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["vendors"],"properties":{"next_cursor":{"type":"string","format":"string"},"vendors":{"type":"array","items":{"type":"object","required":["id","name","organization_id","created_at","updated_at"],"properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Vendor description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Vendor name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}}`)
UpdateMeasureToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"category":{"type":"string","description":"Measure category"},"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"]}}}`)
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"}}}}}`)
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"}}}`)
UpdateVendorToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["vendor"],"properties":{"vendor":{"type":"object","required":["id","name","organization_id","created_at","updated_at"],"properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Vendor description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Vendor name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
)
// AddMeasureInput represents the schema
type AddMeasureInput struct {
// Measure category
Category string `json:"category"`
// Measure description
Description *string `json:"description,omitempty"`
// Measure name
Name string `json:"name"`
// Organization ID
OrganizationID gid.GID `json:"organization_id"`
}
// AddMeasureOutput represents the schema
type AddMeasureOutput struct {
Measure *Measure `json:"measure"`
}
// AddPeopleInput represents the schema
type AddPeopleInput struct {
// Additional email addresses
@@ -111,6 +136,17 @@ type AddVendorOutput struct {
Vendor *Vendor `json:"vendor"`
}
// GetMeasureInput represents the schema
type GetMeasureInput struct {
// Measure ID
ID gid.GID `json:"id"`
}
// GetMeasureOutput represents the schema
type GetMeasureOutput struct {
Measure *Measure `json:"measure"`
}
// GetPeopleInput represents the schema
type GetPeopleInput struct {
// People ID
@@ -133,6 +169,26 @@ type GetRiskOutput struct {
Risk *Risk `json:"risk"`
}
// ListMeasuresInput represents the schema
type ListMeasuresInput struct {
// Page cursor
Cursor *page.CursorKey `json:"cursor,omitempty"`
Filter *ListMeasuresInputFilter `json:"filter,omitempty"`
// Measure order by
OrderBy *MeasureOrderBy `json:"order_by,omitempty"`
// Organization ID
OrganizationID gid.GID `json:"organization_id"`
// Page size
Size *int `json:"size,omitempty"`
}
// ListMeasuresOutput represents the schema
type ListMeasuresOutput struct {
Measures []*Measure `json:"measures"`
// Next cursor
NextCursor *page.CursorKey `json:"next_cursor,omitempty"`
}
// ListOrganizationsInput represents the schema
type ListOrganizationsInput struct {
// Organization ID
@@ -204,6 +260,32 @@ type ListVendorsOutput struct {
Vendors []*Vendor `json:"vendors"`
}
// Measure represents the schema
type Measure struct {
// Measure category
Category string `json:"category"`
// Creation timestamp
CreatedAt time.Time `json:"created_at"`
// Measure description
Description *string `json:"description,omitempty"`
// Measure ID
ID gid.GID `json:"id"`
// Measure name
Name string `json:"name"`
// Measure state
State coredata.MeasureState `json:"state"`
// Update timestamp
UpdatedAt time.Time `json:"updated_at"`
}
// MeasureOrderBy represents the schema
type MeasureOrderBy struct {
// Measure order direction
Direction page.OrderDirection `json:"direction"`
// Measure order field
Field coredata.MeasureOrderField `json:"field"`
}
// Organization represents the schema
type Organization struct {
// Creation timestamp
@@ -298,6 +380,25 @@ type RiskOrderBy struct {
Field coredata.RiskOrderField `json:"field"`
}
// UpdateMeasureInput represents the schema
type UpdateMeasureInput struct {
// Measure category
Category *string `json:"category,omitempty"`
// Measure description
Description mcp.Omittable[*string] `json:"description,omitempty"`
// Measure ID
ID gid.GID `json:"id"`
// Measure name
Name *string `json:"name,omitempty"`
// Measure state
State *coredata.MeasureState `json:"state,omitempty"`
}
// UpdateMeasureOutput represents the schema
type UpdateMeasureOutput struct {
Measure *Measure `json:"measure"`
}
// UpdateRiskInput represents the schema
type UpdateRiskInput struct {
// Risk category
@@ -368,6 +469,14 @@ type VendorOrderBy struct {
Field coredata.VendorOrderField `json:"field"`
}
// ListMeasuresInputFilter represents the schema
type ListMeasuresInputFilter struct {
// Search query
Query *string `json:"query,omitempty"`
// Measure state filter
State *coredata.MeasureState `json:"state,omitempty"`
}
// ListPeopleInputFilter represents the schema
type ListPeopleInputFilter struct {
// Exclude people with ended contracts