2
go.mod
2
go.mod
@@ -28,7 +28,7 @@ require (
|
|||||||
go.gearno.de/x/ref v0.0.0-20240502200927-d74926fcb14c
|
go.gearno.de/x/ref v0.0.0-20240502200927-d74926fcb14c
|
||||||
go.opentelemetry.io/otel v1.38.0
|
go.opentelemetry.io/otel v1.38.0
|
||||||
go.opentelemetry.io/otel/trace v1.38.0
|
go.opentelemetry.io/otel/trace v1.38.0
|
||||||
go.probo.inc/mcpgen v0.0.0-20251120181856-7af25b57c072
|
go.probo.inc/mcpgen v0.0.0-20251123193256-f77e7775c058
|
||||||
golang.org/x/crypto v0.45.0
|
golang.org/x/crypto v0.45.0
|
||||||
golang.org/x/image v0.33.0
|
golang.org/x/image v0.33.0
|
||||||
golang.org/x/sync v0.18.0
|
golang.org/x/sync v0.18.0
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -245,8 +245,8 @@ go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJr
|
|||||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||||
go.probo.inc/mcpgen v0.0.0-20251120181856-7af25b57c072 h1:cDcrtdjfFK6bOC/feYvSRxFH2w89ZvbrdWmywHpNfEo=
|
go.probo.inc/mcpgen v0.0.0-20251123193256-f77e7775c058 h1:zRiWKVVJZCDDolmVedKm0xdQlJQXvLzgFEDu/s20jYs=
|
||||||
go.probo.inc/mcpgen v0.0.0-20251120181856-7af25b57c072/go.mod h1:HunWQGqLdMocExJh4tWaX7p+uRZ9GlKvBvOXHaFW6vM=
|
go.probo.inc/mcpgen v0.0.0-20251123193256-f77e7775c058/go.mod h1:HunWQGqLdMocExJh4tWaX7p+uRZ9GlKvBvOXHaFW6vM=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||||
|
|||||||
@@ -192,3 +192,103 @@ func (r *Resolver) AddPeopleTool(ctx context.Context, req *mcp.CallToolRequest,
|
|||||||
People: types.NewPeople(people),
|
People: types.NewPeople(people),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Resolver) ListRisksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRisksInput) (*mcp.CallToolResult, types.ListRisksOutput, error) {
|
||||||
|
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionListRisks)
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, input.OrganizationID)
|
||||||
|
|
||||||
|
pageOrderBy := page.OrderBy[coredata.RiskOrderField]{
|
||||||
|
Field: coredata.RiskOrderFieldCreatedAt,
|
||||||
|
Direction: page.OrderDirectionDesc,
|
||||||
|
}
|
||||||
|
if input.OrderBy != nil {
|
||||||
|
pageOrderBy = page.OrderBy[coredata.RiskOrderField]{
|
||||||
|
Field: input.OrderBy.Field,
|
||||||
|
Direction: input.OrderBy.Direction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
||||||
|
|
||||||
|
var riskFilter = coredata.NewRiskFilter(nil, nil)
|
||||||
|
if input.Filter != nil {
|
||||||
|
riskFilter = coredata.NewRiskFilter(input.Filter.Query, &input.Filter.SnapshotID)
|
||||||
|
}
|
||||||
|
|
||||||
|
page, err := prb.Risks.ListForOrganizationID(ctx, input.OrganizationID, cursor, riskFilter)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot list organization risks: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, types.NewListRisksOutput(page), nil
|
||||||
|
}
|
||||||
|
func (r *Resolver) GetRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskInput) (*mcp.CallToolResult, types.GetRiskOutput, error) {
|
||||||
|
r.MustBeAuthorized(ctx, input.ID, authz.ActionGet)
|
||||||
|
|
||||||
|
prb := r.ProboService(ctx, input.ID)
|
||||||
|
|
||||||
|
risk, err := prb.Risks.Get(ctx, input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, types.GetRiskOutput{}, fmt.Errorf("failed to get risk: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, types.GetRiskOutput{
|
||||||
|
Risk: types.NewRisk(risk),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (r *Resolver) AddRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskInput) (*mcp.CallToolResult, types.AddRiskOutput, error) {
|
||||||
|
r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateRisk)
|
||||||
|
|
||||||
|
svc := r.ProboService(ctx, input.OrganizationID)
|
||||||
|
|
||||||
|
risk, err := svc.Risks.Create(
|
||||||
|
ctx,
|
||||||
|
probo.CreateRiskRequest{
|
||||||
|
OrganizationID: input.OrganizationID,
|
||||||
|
Name: input.Name,
|
||||||
|
Description: input.Description,
|
||||||
|
Category: input.Category,
|
||||||
|
Treatment: input.Treatment,
|
||||||
|
InherentLikelihood: input.InherentLikelihood,
|
||||||
|
InherentImpact: input.InherentImpact,
|
||||||
|
ResidualLikelihood: input.ResidualLikelihood,
|
||||||
|
ResidualImpact: input.ResidualImpact,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, types.AddRiskOutput{}, fmt.Errorf("failed to create risk: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, types.AddRiskOutput{
|
||||||
|
Risk: types.NewRisk(risk),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (r *Resolver) UpdateRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskInput) (*mcp.CallToolResult, types.UpdateRiskOutput, error) {
|
||||||
|
r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateRisk)
|
||||||
|
|
||||||
|
svc := r.ProboService(ctx, input.ID)
|
||||||
|
|
||||||
|
risk, err := svc.Risks.Update(
|
||||||
|
ctx,
|
||||||
|
probo.UpdateRiskRequest{
|
||||||
|
ID: input.ID,
|
||||||
|
Name: input.Name,
|
||||||
|
Description: UnwrapOmittable(input.Description),
|
||||||
|
Category: input.Category,
|
||||||
|
Treatment: input.Treatment,
|
||||||
|
OwnerID: UnwrapOmittable(input.OwnerID),
|
||||||
|
InherentLikelihood: input.InherentLikelihood,
|
||||||
|
InherentImpact: input.InherentImpact,
|
||||||
|
ResidualLikelihood: input.ResidualLikelihood,
|
||||||
|
ResidualImpact: input.ResidualImpact,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, types.UpdateRiskOutput{}, fmt.Errorf("failed to update risk: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, types.UpdateRiskOutput{
|
||||||
|
Risk: types.NewRisk(risk),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ type ResolverInterface interface {
|
|||||||
UpdateVendorTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateVendorInput) (*mcp.CallToolResult, types.UpdateVendorOutput, error)
|
UpdateVendorTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateVendorInput) (*mcp.CallToolResult, types.UpdateVendorOutput, error)
|
||||||
GetPeopleTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetPeopleInput) (*mcp.CallToolResult, types.GetPeopleOutput, error)
|
GetPeopleTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetPeopleInput) (*mcp.CallToolResult, types.GetPeopleOutput, error)
|
||||||
AddPeopleTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddPeopleInput) (*mcp.CallToolResult, types.AddPeopleOutput, error)
|
AddPeopleTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddPeopleInput) (*mcp.CallToolResult, types.AddPeopleOutput, error)
|
||||||
|
ListRisksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRisksInput) (*mcp.CallToolResult, types.ListRisksOutput, error)
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new MCP server instance with all handlers registered.
|
// New creates a new MCP server instance with all handlers registered.
|
||||||
@@ -106,4 +110,44 @@ func registerToolHandlers(server *mcp.Server, resolver ResolverInterface) {
|
|||||||
},
|
},
|
||||||
resolver.AddPeopleTool,
|
resolver.AddPeopleTool,
|
||||||
)
|
)
|
||||||
|
mcp.AddTool(
|
||||||
|
server,
|
||||||
|
&mcp.Tool{
|
||||||
|
Name: "listRisks",
|
||||||
|
Description: "List all risks for the organization",
|
||||||
|
InputSchema: types.ListRisksToolInputSchema,
|
||||||
|
OutputSchema: types.ListRisksToolOutputSchema,
|
||||||
|
},
|
||||||
|
resolver.ListRisksTool,
|
||||||
|
)
|
||||||
|
mcp.AddTool(
|
||||||
|
server,
|
||||||
|
&mcp.Tool{
|
||||||
|
Name: "getRisk",
|
||||||
|
Description: "Get a risk by ID",
|
||||||
|
InputSchema: types.GetRiskToolInputSchema,
|
||||||
|
OutputSchema: types.GetRiskToolOutputSchema,
|
||||||
|
},
|
||||||
|
resolver.GetRiskTool,
|
||||||
|
)
|
||||||
|
mcp.AddTool(
|
||||||
|
server,
|
||||||
|
&mcp.Tool{
|
||||||
|
Name: "addRisk",
|
||||||
|
Description: "Add a new risk to the organization",
|
||||||
|
InputSchema: types.AddRiskToolInputSchema,
|
||||||
|
OutputSchema: types.AddRiskToolOutputSchema,
|
||||||
|
},
|
||||||
|
resolver.AddRiskTool,
|
||||||
|
)
|
||||||
|
mcp.AddTool(
|
||||||
|
server,
|
||||||
|
&mcp.Tool{
|
||||||
|
Name: "updateRisk",
|
||||||
|
Description: "Update an existing risk",
|
||||||
|
InputSchema: types.UpdateRiskToolInputSchema,
|
||||||
|
OutputSchema: types.UpdateRiskToolOutputSchema,
|
||||||
|
},
|
||||||
|
resolver.UpdateRiskTool,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -397,6 +397,280 @@ components:
|
|||||||
people:
|
people:
|
||||||
$ref: "#/components/schemas/People"
|
$ref: "#/components/schemas/People"
|
||||||
|
|
||||||
|
RiskOrderField:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- CREATED_AT
|
||||||
|
- UPDATED_AT
|
||||||
|
- NAME
|
||||||
|
- CATEGORY
|
||||||
|
- TREATMENT
|
||||||
|
- INHERENT_RISK_SCORE
|
||||||
|
- RESIDUAL_RISK_SCORE
|
||||||
|
- OWNER_FULL_NAME
|
||||||
|
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.RiskOrderField
|
||||||
|
|
||||||
|
RiskOrderBy:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- field
|
||||||
|
- direction
|
||||||
|
properties:
|
||||||
|
field:
|
||||||
|
$ref: "#/components/schemas/RiskOrderField"
|
||||||
|
description: Risk order field
|
||||||
|
direction:
|
||||||
|
$ref: "#/components/schemas/OrderDirection"
|
||||||
|
description: Risk order direction
|
||||||
|
|
||||||
|
RiskTreatment:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- MITIGATED
|
||||||
|
- ACCEPTED
|
||||||
|
- AVOIDED
|
||||||
|
- TRANSFERRED
|
||||||
|
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.RiskTreatment
|
||||||
|
|
||||||
|
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:
|
||||||
|
id:
|
||||||
|
$ref: "#/components/schemas/GID"
|
||||||
|
description: Risk ID
|
||||||
|
organization_id:
|
||||||
|
$ref: "#/components/schemas/GID"
|
||||||
|
description: Organization ID
|
||||||
|
snapshot_id:
|
||||||
|
type:
|
||||||
|
- string
|
||||||
|
- "null"
|
||||||
|
description: Snapshot ID
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: Risk name
|
||||||
|
description:
|
||||||
|
type:
|
||||||
|
- string
|
||||||
|
- "null"
|
||||||
|
description: Risk description
|
||||||
|
category:
|
||||||
|
type: string
|
||||||
|
description: Risk category
|
||||||
|
treatment:
|
||||||
|
$ref: "#/components/schemas/RiskTreatment"
|
||||||
|
description: Risk treatment
|
||||||
|
inherent_likelihood:
|
||||||
|
type: integer
|
||||||
|
description: Inherent likelihood
|
||||||
|
inherent_impact:
|
||||||
|
type: integer
|
||||||
|
description: Inherent impact
|
||||||
|
inherent_risk_score:
|
||||||
|
type: integer
|
||||||
|
description: Inherent risk score
|
||||||
|
residual_likelihood:
|
||||||
|
type: integer
|
||||||
|
description: Residual likelihood
|
||||||
|
residual_impact:
|
||||||
|
type: integer
|
||||||
|
description: Residual impact
|
||||||
|
residual_risk_score:
|
||||||
|
type: integer
|
||||||
|
description: Residual risk score
|
||||||
|
note:
|
||||||
|
type: string
|
||||||
|
description: Risk note
|
||||||
|
owner_id:
|
||||||
|
type:
|
||||||
|
- string
|
||||||
|
- "null"
|
||||||
|
description: Owner ID
|
||||||
|
created_at:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
description: Creation timestamp
|
||||||
|
updated_at:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
description: Update timestamp
|
||||||
|
|
||||||
|
ListRisksInput:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- organization_id
|
||||||
|
properties:
|
||||||
|
organization_id:
|
||||||
|
$ref: "#/components/schemas/GID"
|
||||||
|
description: Organization ID
|
||||||
|
order_by:
|
||||||
|
$ref: "#/components/schemas/RiskOrderBy"
|
||||||
|
description: Risk 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
|
||||||
|
snapshot_id:
|
||||||
|
$ref: "#/components/schemas/GID"
|
||||||
|
description: Snapshot ID
|
||||||
|
|
||||||
|
ListRisksOutput:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- risks
|
||||||
|
properties:
|
||||||
|
next_cursor:
|
||||||
|
$ref: "#/components/schemas/CursorKey"
|
||||||
|
description: Next cursor
|
||||||
|
risks:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/Risk"
|
||||||
|
|
||||||
|
GetRiskInput:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
$ref: "#/components/schemas/GID"
|
||||||
|
description: Risk ID
|
||||||
|
|
||||||
|
GetRiskOutput:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- risk
|
||||||
|
properties:
|
||||||
|
risk:
|
||||||
|
$ref: "#/components/schemas/Risk"
|
||||||
|
|
||||||
|
AddRiskInput:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- organization_id
|
||||||
|
- name
|
||||||
|
- category
|
||||||
|
- treatment
|
||||||
|
- inherent_likelihood
|
||||||
|
- inherent_impact
|
||||||
|
properties:
|
||||||
|
organization_id:
|
||||||
|
$ref: "#/components/schemas/GID"
|
||||||
|
description: Organization ID
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: Risk name
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
description: Risk description
|
||||||
|
category:
|
||||||
|
type: string
|
||||||
|
description: Risk category
|
||||||
|
owner_id:
|
||||||
|
$ref: "#/components/schemas/GID"
|
||||||
|
description: Owner ID
|
||||||
|
treatment:
|
||||||
|
$ref: "#/components/schemas/RiskTreatment"
|
||||||
|
description: Risk treatment
|
||||||
|
inherent_likelihood:
|
||||||
|
type: integer
|
||||||
|
description: Inherent likelihood
|
||||||
|
inherent_impact:
|
||||||
|
type: integer
|
||||||
|
description: Inherent impact
|
||||||
|
residual_likelihood:
|
||||||
|
type: integer
|
||||||
|
description: Residual likelihood
|
||||||
|
residual_impact:
|
||||||
|
type: integer
|
||||||
|
description: Residual impact
|
||||||
|
note:
|
||||||
|
type: string
|
||||||
|
description: Risk note
|
||||||
|
|
||||||
|
AddRiskOutput:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- risk
|
||||||
|
properties:
|
||||||
|
risk:
|
||||||
|
$ref: "#/components/schemas/Risk"
|
||||||
|
|
||||||
|
UpdateRiskInput:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
$ref: "#/components/schemas/GID"
|
||||||
|
description: Risk ID
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: Risk name
|
||||||
|
description:
|
||||||
|
type: ["string", "null"]
|
||||||
|
description: Risk description
|
||||||
|
go.probo.inc/mcpgen/omittable: true
|
||||||
|
category:
|
||||||
|
type: string
|
||||||
|
description: Risk category
|
||||||
|
owner_id:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
$ref: "#/components/schemas/GID"
|
||||||
|
- type: "null"
|
||||||
|
description: Owner ID
|
||||||
|
go.probo.inc/mcpgen/omittable: true
|
||||||
|
treatment:
|
||||||
|
$ref: "#/components/schemas/RiskTreatment"
|
||||||
|
description: Risk treatment
|
||||||
|
inherent_likelihood:
|
||||||
|
type: integer
|
||||||
|
description: Inherent likelihood
|
||||||
|
inherent_impact:
|
||||||
|
type: integer
|
||||||
|
description: Inherent impact
|
||||||
|
residual_likelihood:
|
||||||
|
type: integer
|
||||||
|
description: Residual likelihood
|
||||||
|
residual_impact:
|
||||||
|
type: integer
|
||||||
|
description: Residual impact
|
||||||
|
note:
|
||||||
|
type: string
|
||||||
|
description: Risk note
|
||||||
|
|
||||||
|
UpdateRiskOutput:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- risk
|
||||||
|
properties:
|
||||||
|
risk:
|
||||||
|
$ref: "#/components/schemas/Risk"
|
||||||
|
|
||||||
tools:
|
tools:
|
||||||
- name: listOrganizations
|
- name: listOrganizations
|
||||||
description: List all organizations the user has access to
|
description: List all organizations the user has access to
|
||||||
@@ -447,3 +721,31 @@ tools:
|
|||||||
$ref: "#/components/schemas/AddPeopleInput"
|
$ref: "#/components/schemas/AddPeopleInput"
|
||||||
outputSchema:
|
outputSchema:
|
||||||
$ref: "#/components/schemas/AddPeopleOutput"
|
$ref: "#/components/schemas/AddPeopleOutput"
|
||||||
|
- name: listRisks
|
||||||
|
description: List all risks for the organization
|
||||||
|
readonly: true
|
||||||
|
inputSchema:
|
||||||
|
$ref: "#/components/schemas/ListRisksInput"
|
||||||
|
outputSchema:
|
||||||
|
$ref: "#/components/schemas/ListRisksOutput"
|
||||||
|
- name: getRisk
|
||||||
|
description: Get a risk by ID
|
||||||
|
readonly: true
|
||||||
|
inputSchema:
|
||||||
|
$ref: "#/components/schemas/GetRiskInput"
|
||||||
|
outputSchema:
|
||||||
|
$ref: "#/components/schemas/GetRiskOutput"
|
||||||
|
- name: addRisk
|
||||||
|
description: Add a new risk to the organization
|
||||||
|
readonly: false
|
||||||
|
inputSchema:
|
||||||
|
$ref: "#/components/schemas/AddRiskInput"
|
||||||
|
outputSchema:
|
||||||
|
$ref: "#/components/schemas/AddRiskOutput"
|
||||||
|
- name: updateRisk
|
||||||
|
description: Update an existing risk
|
||||||
|
readonly: false
|
||||||
|
inputSchema:
|
||||||
|
$ref: "#/components/schemas/UpdateRiskInput"
|
||||||
|
outputSchema:
|
||||||
|
$ref: "#/components/schemas/UpdateRiskOutput"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func NewCursor[O page.OrderField](
|
func NewCursor[O page.OrderField](
|
||||||
first *int64,
|
first *int,
|
||||||
after *page.CursorKey,
|
after *page.CursorKey,
|
||||||
orderBy page.OrderBy[O],
|
orderBy page.OrderBy[O],
|
||||||
) *page.Cursor[O] {
|
) *page.Cursor[O] {
|
||||||
|
|||||||
50
pkg/server/api/mcp/v1/types/risk.go
Normal file
50
pkg/server/api/mcp/v1/types/risk.go
Normal 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 NewRisk(r *coredata.Risk) *Risk {
|
||||||
|
return &Risk{
|
||||||
|
ID: r.ID,
|
||||||
|
Name: r.Name,
|
||||||
|
Description: r.Description,
|
||||||
|
Category: r.Category,
|
||||||
|
Treatment: r.Treatment,
|
||||||
|
InherentLikelihood: r.InherentLikelihood,
|
||||||
|
InherentImpact: r.InherentImpact,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListRisksOutput(riskPage *page.Page[*coredata.Risk, coredata.RiskOrderField]) ListRisksOutput {
|
||||||
|
risks := make([]*Risk, 0, len(riskPage.Data))
|
||||||
|
for _, v := range riskPage.Data {
|
||||||
|
risks = append(risks, NewRisk(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
var nextCursor *page.CursorKey
|
||||||
|
if len(riskPage.Data) > 0 {
|
||||||
|
cursorKey := riskPage.Data[len(riskPage.Data)-1].CursorKey(riskPage.Cursor.OrderBy.Field)
|
||||||
|
nextCursor = &cursorKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return ListRisksOutput{
|
||||||
|
NextCursor: nextCursor,
|
||||||
|
Risks: risks,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,16 +14,24 @@ import (
|
|||||||
var (
|
var (
|
||||||
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"}}}`)
|
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"}}}}}`)
|
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"}}}`)
|
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"}}}}}`)
|
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"}}}}}`)
|
||||||
GetPeopleToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`)
|
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"}}}}}`)
|
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"}}}}}`)
|
||||||
ListOrganizationsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"organization_id":{"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"}}}}}}`)
|
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"}}}`)
|
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"}}}`)
|
||||||
ListPeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"next_cursor":{"type":"string","format":"string"},"people":{"type":"array","items":{"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"}}}}}}`)
|
ListPeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"next_cursor":{"type":"string","format":"string"},"people":{"type":"array","items":{"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"}}}}}}`)
|
||||||
|
ListRisksToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id"],"properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"query":{"type":"string","description":"Search query"},"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","CATEGORY","TREATMENT","INHERENT_RISK_SCORE","RESIDUAL_RISK_SCORE","OWNER_FULL_NAME"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`)
|
||||||
|
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"}}}`)
|
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"}}}}}}`)
|
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"}}}}}}`)
|
||||||
|
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"}}}`)
|
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"}}}}}`)
|
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"}}}}}`)
|
||||||
)
|
)
|
||||||
@@ -53,6 +61,37 @@ type AddPeopleOutput struct {
|
|||||||
People *People `json:"people"`
|
People *People `json:"people"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddRiskInput represents the schema
|
||||||
|
type AddRiskInput struct {
|
||||||
|
// Risk category
|
||||||
|
Category string `json:"category"`
|
||||||
|
// Risk description
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
// Inherent impact
|
||||||
|
InherentImpact int `json:"inherent_impact"`
|
||||||
|
// Inherent likelihood
|
||||||
|
InherentLikelihood int `json:"inherent_likelihood"`
|
||||||
|
// Risk name
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Risk note
|
||||||
|
Note *string `json:"note,omitempty"`
|
||||||
|
// Organization ID
|
||||||
|
OrganizationID gid.GID `json:"organization_id"`
|
||||||
|
// Owner ID
|
||||||
|
OwnerID *gid.GID `json:"owner_id,omitempty"`
|
||||||
|
// Residual impact
|
||||||
|
ResidualImpact *int `json:"residual_impact,omitempty"`
|
||||||
|
// Residual likelihood
|
||||||
|
ResidualLikelihood *int `json:"residual_likelihood,omitempty"`
|
||||||
|
// Risk treatment
|
||||||
|
Treatment coredata.RiskTreatment `json:"treatment"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRiskOutput represents the schema
|
||||||
|
type AddRiskOutput struct {
|
||||||
|
Risk *Risk `json:"risk"`
|
||||||
|
}
|
||||||
|
|
||||||
// AddVendorInput represents the schema
|
// AddVendorInput represents the schema
|
||||||
type AddVendorInput struct {
|
type AddVendorInput struct {
|
||||||
// Creation timestamp
|
// Creation timestamp
|
||||||
@@ -83,6 +122,17 @@ type GetPeopleOutput struct {
|
|||||||
People *People `json:"people"`
|
People *People `json:"people"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRiskInput represents the schema
|
||||||
|
type GetRiskInput struct {
|
||||||
|
// Risk ID
|
||||||
|
ID gid.GID `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRiskOutput represents the schema
|
||||||
|
type GetRiskOutput struct {
|
||||||
|
Risk *Risk `json:"risk"`
|
||||||
|
}
|
||||||
|
|
||||||
// ListOrganizationsInput represents the schema
|
// ListOrganizationsInput represents the schema
|
||||||
type ListOrganizationsInput struct {
|
type ListOrganizationsInput struct {
|
||||||
// Organization ID
|
// Organization ID
|
||||||
@@ -104,7 +154,7 @@ type ListPeopleInput struct {
|
|||||||
// Organization ID
|
// Organization ID
|
||||||
OrganizationID gid.GID `json:"organization_id"`
|
OrganizationID gid.GID `json:"organization_id"`
|
||||||
// Page size
|
// Page size
|
||||||
Size *int64 `json:"size,omitempty"`
|
Size *int `json:"size,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListPeopleOutput represents the schema
|
// ListPeopleOutput represents the schema
|
||||||
@@ -114,6 +164,26 @@ type ListPeopleOutput struct {
|
|||||||
People []*People `json:"people"`
|
People []*People `json:"people"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListRisksInput represents the schema
|
||||||
|
type ListRisksInput struct {
|
||||||
|
// Page cursor
|
||||||
|
Cursor *page.CursorKey `json:"cursor,omitempty"`
|
||||||
|
Filter *ListRisksInputFilter `json:"filter,omitempty"`
|
||||||
|
// Risk order by
|
||||||
|
OrderBy *RiskOrderBy `json:"order_by,omitempty"`
|
||||||
|
// Organization ID
|
||||||
|
OrganizationID gid.GID `json:"organization_id"`
|
||||||
|
// Page size
|
||||||
|
Size *int `json:"size,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRisksOutput represents the schema
|
||||||
|
type ListRisksOutput struct {
|
||||||
|
// Next cursor
|
||||||
|
NextCursor *page.CursorKey `json:"next_cursor,omitempty"`
|
||||||
|
Risks []*Risk `json:"risks"`
|
||||||
|
}
|
||||||
|
|
||||||
// ListVendorsInput represents the schema
|
// ListVendorsInput represents the schema
|
||||||
type ListVendorsInput struct {
|
type ListVendorsInput struct {
|
||||||
// Page cursor
|
// Page cursor
|
||||||
@@ -124,7 +194,7 @@ type ListVendorsInput struct {
|
|||||||
// Organization ID
|
// Organization ID
|
||||||
OrganizationID gid.GID `json:"organization_id"`
|
OrganizationID gid.GID `json:"organization_id"`
|
||||||
// Page size
|
// Page size
|
||||||
Size *int64 `json:"size,omitempty"`
|
Size *int `json:"size,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListVendorsOutput represents the schema
|
// ListVendorsOutput represents the schema
|
||||||
@@ -182,6 +252,83 @@ type PeopleOrderBy struct {
|
|||||||
Field coredata.PeopleOrderField `json:"field"`
|
Field coredata.PeopleOrderField `json:"field"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Risk represents the schema
|
||||||
|
type Risk struct {
|
||||||
|
// Risk category
|
||||||
|
Category string `json:"category"`
|
||||||
|
// Creation timestamp
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
// Risk description
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
// Risk ID
|
||||||
|
ID gid.GID `json:"id"`
|
||||||
|
// Inherent impact
|
||||||
|
InherentImpact int `json:"inherent_impact"`
|
||||||
|
// Inherent likelihood
|
||||||
|
InherentLikelihood int `json:"inherent_likelihood"`
|
||||||
|
// Inherent risk score
|
||||||
|
InherentRiskScore int `json:"inherent_risk_score"`
|
||||||
|
// Risk name
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Risk note
|
||||||
|
Note string `json:"note"`
|
||||||
|
// Organization ID
|
||||||
|
OrganizationID gid.GID `json:"organization_id"`
|
||||||
|
// Owner ID
|
||||||
|
OwnerID *string `json:"owner_id,omitempty"`
|
||||||
|
// Residual impact
|
||||||
|
ResidualImpact int `json:"residual_impact"`
|
||||||
|
// Residual likelihood
|
||||||
|
ResidualLikelihood int `json:"residual_likelihood"`
|
||||||
|
// Residual risk score
|
||||||
|
ResidualRiskScore int `json:"residual_risk_score"`
|
||||||
|
// Snapshot ID
|
||||||
|
SnapshotID *string `json:"snapshot_id,omitempty"`
|
||||||
|
// Risk treatment
|
||||||
|
Treatment coredata.RiskTreatment `json:"treatment"`
|
||||||
|
// Update timestamp
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RiskOrderBy represents the schema
|
||||||
|
type RiskOrderBy struct {
|
||||||
|
// Risk order direction
|
||||||
|
Direction page.OrderDirection `json:"direction"`
|
||||||
|
// Risk order field
|
||||||
|
Field coredata.RiskOrderField `json:"field"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateRiskInput represents the schema
|
||||||
|
type UpdateRiskInput struct {
|
||||||
|
// Risk category
|
||||||
|
Category *string `json:"category,omitempty"`
|
||||||
|
// Risk description
|
||||||
|
Description mcp.Omittable[*string] `json:"description,omitempty"`
|
||||||
|
// Risk ID
|
||||||
|
ID gid.GID `json:"id"`
|
||||||
|
// Inherent impact
|
||||||
|
InherentImpact *int `json:"inherent_impact,omitempty"`
|
||||||
|
// Inherent likelihood
|
||||||
|
InherentLikelihood *int `json:"inherent_likelihood,omitempty"`
|
||||||
|
// Risk name
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
// Risk note
|
||||||
|
Note *string `json:"note,omitempty"`
|
||||||
|
// Owner ID
|
||||||
|
OwnerID mcp.Omittable[*gid.GID] `json:"owner_id,omitempty"`
|
||||||
|
// Residual impact
|
||||||
|
ResidualImpact *int `json:"residual_impact,omitempty"`
|
||||||
|
// Residual likelihood
|
||||||
|
ResidualLikelihood *int `json:"residual_likelihood,omitempty"`
|
||||||
|
// Risk treatment
|
||||||
|
Treatment *coredata.RiskTreatment `json:"treatment,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateRiskOutput represents the schema
|
||||||
|
type UpdateRiskOutput struct {
|
||||||
|
Risk *Risk `json:"risk"`
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateVendorInput represents the schema
|
// UpdateVendorInput represents the schema
|
||||||
type UpdateVendorInput struct {
|
type UpdateVendorInput struct {
|
||||||
// Vendor description
|
// Vendor description
|
||||||
@@ -227,6 +374,14 @@ type ListPeopleInputFilter struct {
|
|||||||
ExcludeContractEnded *bool `json:"exclude_contract_ended,omitempty"`
|
ExcludeContractEnded *bool `json:"exclude_contract_ended,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListRisksInputFilter represents the schema
|
||||||
|
type ListRisksInputFilter struct {
|
||||||
|
// Search query
|
||||||
|
Query *string `json:"query,omitempty"`
|
||||||
|
// Snapshot ID
|
||||||
|
SnapshotID *gid.GID `json:"snapshot_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// ListVendorsInputFilter represents the schema
|
// ListVendorsInputFilter represents the schema
|
||||||
type ListVendorsInputFilter struct {
|
type ListVendorsInputFilter struct {
|
||||||
// Snapshot ID
|
// Snapshot ID
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
"go.gearno.de/kit/log"
|
"go.gearno.de/kit/log"
|
||||||
|
mcpgenmcp "go.probo.inc/mcpgen/mcp"
|
||||||
"go.probo.inc/probo/pkg/auth"
|
"go.probo.inc/probo/pkg/auth"
|
||||||
"go.probo.inc/probo/pkg/authz"
|
"go.probo.inc/probo/pkg/authz"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
@@ -65,3 +66,11 @@ func NewMux(logger *log.Logger, proboSvc *probo.Service, authSvc *auth.Service,
|
|||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UnwrapOmittable[T any](field mcpgenmcp.Omittable[T]) *T {
|
||||||
|
if !field.IsSet() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value, _ := field.Value()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user