From 5917c6a17bdc084f50966fab21f3311576c47337 Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Sun, 23 Nov 2025 21:19:39 +0100 Subject: [PATCH] Add assets tools Signed-off-by: Bryan Frimin --- pkg/server/api/mcp/v1/schema.resolvers.go | 107 ++++++++++ pkg/server/api/mcp/v1/server/server.go | 44 ++++ pkg/server/api/mcp/v1/specification.yaml | 239 ++++++++++++++++++++++ pkg/server/api/mcp/v1/types/asset.go | 52 +++++ pkg/server/api/mcp/v1/types/types.go | 123 +++++++++++ 5 files changed, 565 insertions(+) create mode 100644 pkg/server/api/mcp/v1/types/asset.go diff --git a/pkg/server/api/mcp/v1/schema.resolvers.go b/pkg/server/api/mcp/v1/schema.resolvers.go index 679f94c2a..2ee3ca339 100644 --- a/pkg/server/api/mcp/v1/schema.resolvers.go +++ b/pkg/server/api/mcp/v1/schema.resolvers.go @@ -223,6 +223,7 @@ func (r *Resolver) ListRisksTool(ctx context.Context, req *mcp.CallToolRequest, 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) @@ -237,6 +238,7 @@ func (r *Resolver) GetRiskTool(ctx context.Context, req *mcp.CallToolRequest, in 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) @@ -264,6 +266,7 @@ func (r *Resolver) AddRiskTool(ctx context.Context, req *mcp.CallToolRequest, in 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) @@ -323,6 +326,7 @@ func (r *Resolver) ListMeasuresTool(ctx context.Context, req *mcp.CallToolReques 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) @@ -337,6 +341,7 @@ func (r *Resolver) GetMeasureTool(ctx context.Context, req *mcp.CallToolRequest, 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) @@ -359,6 +364,7 @@ func (r *Resolver) AddMeasureTool(ctx context.Context, req *mcp.CallToolRequest, 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) @@ -408,6 +414,7 @@ func (r *Resolver) ListFrameworksTool(ctx context.Context, req *mcp.CallToolRequ return nil, types.NewListFrameworksOutput(page), nil } + func (r *Resolver) GetFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetFrameworkInput) (*mcp.CallToolResult, types.GetFrameworkOutput, error) { r.MustBeAuthorized(ctx, input.ID, authz.ActionGet) @@ -422,6 +429,7 @@ func (r *Resolver) GetFrameworkTool(ctx context.Context, req *mcp.CallToolReques Framework: types.NewFramework(framework), }, nil } + func (r *Resolver) AddFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddFrameworkInput) (*mcp.CallToolResult, types.AddFrameworkOutput, error) { r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateFramework) @@ -443,6 +451,7 @@ func (r *Resolver) AddFrameworkTool(ctx context.Context, req *mcp.CallToolReques Framework: types.NewFramework(framework), }, nil } + func (r *Resolver) UpdateFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateFrameworkInput) (*mcp.CallToolResult, types.UpdateFrameworkOutput, error) { r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateFramework) @@ -464,3 +473,101 @@ func (r *Resolver) UpdateFrameworkTool(ctx context.Context, req *mcp.CallToolReq Framework: types.NewFramework(framework), }, nil } + +func (r *Resolver) ListAssetsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAssetsInput) (*mcp.CallToolResult, types.ListAssetsOutput, error) { + r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionListAssets) + + prb := r.ProboService(ctx, input.OrganizationID) + + pageOrderBy := page.OrderBy[coredata.AssetOrderField]{ + Field: coredata.AssetOrderFieldCreatedAt, + Direction: page.OrderDirectionDesc, + } + if input.OrderBy != nil { + pageOrderBy = page.OrderBy[coredata.AssetOrderField]{ + Field: input.OrderBy.Field, + Direction: input.OrderBy.Direction, + } + } + + cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy) + + var assetFilter = coredata.NewAssetFilter(nil) + if input.Filter != nil { + assetFilter = coredata.NewAssetFilter(&input.Filter.SnapshotID) + } + + page, err := prb.Assets.ListForOrganizationID(ctx, input.OrganizationID, cursor, assetFilter) + if err != nil { + panic(fmt.Errorf("cannot list organization assets: %w", err)) + } + + return nil, types.NewListAssetsOutput(page), nil +} + +func (r *Resolver) GetAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAssetInput) (*mcp.CallToolResult, types.GetAssetOutput, error) { + r.MustBeAuthorized(ctx, input.ID, authz.ActionGet) + + prb := r.ProboService(ctx, input.ID) + + asset, err := prb.Assets.Get(ctx, input.ID) + if err != nil { + return nil, types.GetAssetOutput{}, fmt.Errorf("failed to get asset: %w", err) + } + + return nil, types.GetAssetOutput{ + Asset: types.NewAsset(asset), + }, nil +} + +func (r *Resolver) AddAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAssetInput) (*mcp.CallToolResult, types.AddAssetOutput, error) { + r.MustBeAuthorized(ctx, input.OrganizationID, authz.ActionCreateAsset) + + svc := r.ProboService(ctx, input.OrganizationID) + + asset, err := svc.Assets.Create( + ctx, + probo.CreateAssetRequest{ + OrganizationID: input.OrganizationID, + Name: input.Name, + Amount: input.Amount, + OwnerID: input.OwnerID, + AssetType: input.AssetType, + DataTypesStored: input.DataTypesStored, + VendorIDs: input.VendorIds, + }, + ) + if err != nil { + return nil, types.AddAssetOutput{}, fmt.Errorf("failed to create asset: %w", err) + } + + return nil, types.AddAssetOutput{ + Asset: types.NewAsset(asset), + }, nil +} + +func (r *Resolver) UpdateAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAssetInput) (*mcp.CallToolResult, types.UpdateAssetOutput, error) { + r.MustBeAuthorized(ctx, input.ID, authz.ActionUpdateAsset) + + svc := r.ProboService(ctx, input.ID) + + asset, err := svc.Assets.Update( + ctx, + probo.UpdateAssetRequest{ + ID: input.ID, + Name: input.Name, + Amount: input.Amount, + OwnerID: input.OwnerID, + AssetType: input.AssetType, + DataTypesStored: input.DataTypesStored, + VendorIDs: input.VendorIds, + }, + ) + if err != nil { + return nil, types.UpdateAssetOutput{}, fmt.Errorf("failed to update asset: %w", err) + } + + return nil, types.UpdateAssetOutput{ + Asset: types.NewAsset(asset), + }, nil +} diff --git a/pkg/server/api/mcp/v1/server/server.go b/pkg/server/api/mcp/v1/server/server.go index c781b25c5..6d9e32a06 100644 --- a/pkg/server/api/mcp/v1/server/server.go +++ b/pkg/server/api/mcp/v1/server/server.go @@ -29,6 +29,10 @@ type ResolverInterface interface { GetFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetFrameworkInput) (*mcp.CallToolResult, types.GetFrameworkOutput, error) AddFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddFrameworkInput) (*mcp.CallToolResult, types.AddFrameworkOutput, error) UpdateFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateFrameworkInput) (*mcp.CallToolResult, types.UpdateFrameworkOutput, error) + ListAssetsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAssetsInput) (*mcp.CallToolResult, types.ListAssetsOutput, error) + GetAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAssetInput) (*mcp.CallToolResult, types.GetAssetOutput, error) + AddAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAssetInput) (*mcp.CallToolResult, types.AddAssetOutput, error) + UpdateAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAssetInput) (*mcp.CallToolResult, types.UpdateAssetOutput, error) } // New creates a new MCP server instance with all handlers registered. @@ -238,4 +242,44 @@ func registerToolHandlers(server *mcp.Server, resolver ResolverInterface) { }, resolver.UpdateFrameworkTool, ) + mcp.AddTool( + server, + &mcp.Tool{ + Name: "listAssets", + Description: "List all assets for the organization", + InputSchema: types.ListAssetsToolInputSchema, + OutputSchema: types.ListAssetsToolOutputSchema, + }, + resolver.ListAssetsTool, + ) + mcp.AddTool( + server, + &mcp.Tool{ + Name: "getAsset", + Description: "Get an asset by ID", + InputSchema: types.GetAssetToolInputSchema, + OutputSchema: types.GetAssetToolOutputSchema, + }, + resolver.GetAssetTool, + ) + mcp.AddTool( + server, + &mcp.Tool{ + Name: "addAsset", + Description: "Add a new asset to the organization", + InputSchema: types.AddAssetToolInputSchema, + OutputSchema: types.AddAssetToolOutputSchema, + }, + resolver.AddAssetTool, + ) + mcp.AddTool( + server, + &mcp.Tool{ + Name: "updateAsset", + Description: "Update an existing asset", + InputSchema: types.UpdateAssetToolInputSchema, + OutputSchema: types.UpdateAssetToolOutputSchema, + }, + resolver.UpdateAssetTool, + ) } diff --git a/pkg/server/api/mcp/v1/specification.yaml b/pkg/server/api/mcp/v1/specification.yaml index bf990bfe7..66dda021e 100644 --- a/pkg/server/api/mcp/v1/specification.yaml +++ b/pkg/server/api/mcp/v1/specification.yaml @@ -998,6 +998,217 @@ components: framework: $ref: "#/components/schemas/Framework" + AssetType: + type: string + enum: + - PHYSICAL + - VIRTUAL + go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.AssetType + + AssetOrderField: + type: string + enum: + - CREATED_AT + - AMOUNT + go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.AssetOrderField + + AssetOrderBy: + type: object + required: + - field + - direction + properties: + field: + $ref: "#/components/schemas/AssetOrderField" + description: Asset order field + direction: + $ref: "#/components/schemas/OrderDirection" + description: Asset order direction + + Asset: + type: object + required: + - id + - organization_id + - name + - amount + - owner_id + - asset_type + - data_types_stored + - created_at + - updated_at + properties: + id: + $ref: "#/components/schemas/GID" + description: Asset ID + organization_id: + $ref: "#/components/schemas/GID" + description: Organization ID + snapshot_id: + type: + - string + - "null" + description: Snapshot ID + name: + type: string + description: Asset name + amount: + type: integer + description: Asset amount + owner_id: + $ref: "#/components/schemas/GID" + description: Owner ID + asset_type: + $ref: "#/components/schemas/AssetType" + description: Asset type + data_types_stored: + type: string + description: Data types stored + created_at: + type: string + format: date-time + description: Creation timestamp + updated_at: + type: string + format: date-time + description: Update timestamp + + ListAssetsInput: + type: object + required: + - organization_id + properties: + organization_id: + $ref: "#/components/schemas/GID" + description: Organization ID + order_by: + $ref: "#/components/schemas/AssetOrderBy" + description: Asset order by + size: + type: integer + description: Page size + cursor: + $ref: "#/components/schemas/CursorKey" + description: Page cursor + filter: + type: object + properties: + snapshot_id: + $ref: "#/components/schemas/GID" + description: Snapshot ID + + ListAssetsOutput: + type: object + required: + - assets + properties: + next_cursor: + $ref: "#/components/schemas/CursorKey" + description: Next cursor + assets: + type: array + items: + $ref: "#/components/schemas/Asset" + + GetAssetInput: + type: object + required: + - id + properties: + id: + $ref: "#/components/schemas/GID" + description: Asset ID + + GetAssetOutput: + type: object + required: + - asset + properties: + asset: + $ref: "#/components/schemas/Asset" + + AddAssetInput: + type: object + required: + - organization_id + - name + - amount + - owner_id + - asset_type + - data_types_stored + properties: + organization_id: + $ref: "#/components/schemas/GID" + description: Organization ID + name: + type: string + description: Asset name + amount: + type: integer + description: Asset amount + owner_id: + $ref: "#/components/schemas/GID" + description: Owner ID + asset_type: + $ref: "#/components/schemas/AssetType" + description: Asset type + data_types_stored: + type: string + description: Data types stored + vendor_ids: + type: array + items: + $ref: "#/components/schemas/GID" + description: Vendor IDs + + AddAssetOutput: + type: object + required: + - asset + properties: + asset: + $ref: "#/components/schemas/Asset" + + UpdateAssetInput: + type: object + required: + - id + properties: + id: + $ref: "#/components/schemas/GID" + description: Asset ID + name: + type: string + description: Asset name + amount: + type: integer + description: Asset amount + owner_id: + anyOf: + - type: string + $ref: "#/components/schemas/GID" + - type: "null" + description: Owner ID + asset_type: + $ref: "#/components/schemas/AssetType" + description: Asset type + data_types_stored: + type: string + description: Data types stored + vendor_ids: + type: array + items: + $ref: "#/components/schemas/GID" + description: Vendor IDs + + UpdateAssetOutput: + type: object + required: + - asset + properties: + asset: + $ref: "#/components/schemas/Asset" + tools: - name: listOrganizations description: List all organizations the user has access to @@ -1132,3 +1343,31 @@ tools: $ref: "#/components/schemas/UpdateFrameworkInput" outputSchema: $ref: "#/components/schemas/UpdateFrameworkOutput" + - name: listAssets + description: List all assets for the organization + readonly: true + inputSchema: + $ref: "#/components/schemas/ListAssetsInput" + outputSchema: + $ref: "#/components/schemas/ListAssetsOutput" + - name: getAsset + description: Get an asset by ID + readonly: true + inputSchema: + $ref: "#/components/schemas/GetAssetInput" + outputSchema: + $ref: "#/components/schemas/GetAssetOutput" + - name: addAsset + description: Add a new asset to the organization + readonly: false + inputSchema: + $ref: "#/components/schemas/AddAssetInput" + outputSchema: + $ref: "#/components/schemas/AddAssetOutput" + - name: updateAsset + description: Update an existing asset + readonly: false + inputSchema: + $ref: "#/components/schemas/UpdateAssetInput" + outputSchema: + $ref: "#/components/schemas/UpdateAssetOutput" diff --git a/pkg/server/api/mcp/v1/types/asset.go b/pkg/server/api/mcp/v1/types/asset.go new file mode 100644 index 000000000..93163f5f2 --- /dev/null +++ b/pkg/server/api/mcp/v1/types/asset.go @@ -0,0 +1,52 @@ +// Copyright (c) 2025 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +package types + +import ( + "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/page" +) + +func NewAsset(a *coredata.Asset) *Asset { + return &Asset{ + ID: a.ID, + Name: a.Name, + Amount: a.Amount, + OwnerID: a.OwnerID, + OrganizationID: a.OrganizationID, + AssetType: a.AssetType, + DataTypesStored: a.DataTypesStored, + CreatedAt: a.CreatedAt, + UpdatedAt: a.UpdatedAt, + } +} + +func NewListAssetsOutput(assetPage *page.Page[*coredata.Asset, coredata.AssetOrderField]) ListAssetsOutput { + assets := make([]*Asset, 0, len(assetPage.Data)) + for _, v := range assetPage.Data { + assets = append(assets, NewAsset(v)) + } + + var nextCursor *page.CursorKey + if len(assetPage.Data) > 0 { + cursorKey := assetPage.Data[len(assetPage.Data)-1].CursorKey(assetPage.Cursor.OrderBy.Field) + nextCursor = &cursorKey + } + + return ListAssetsOutput{ + NextCursor: nextCursor, + Assets: assets, + } +} diff --git a/pkg/server/api/mcp/v1/types/types.go b/pkg/server/api/mcp/v1/types/types.go index 9fc9554ce..8859c50a6 100644 --- a/pkg/server/api/mcp/v1/types/types.go +++ b/pkg/server/api/mcp/v1/types/types.go @@ -12,6 +12,8 @@ import ( // Tool input schemas var ( + AddAssetToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","name","amount","owner_id","asset_type","data_types_stored"],"properties":{"amount":{"type":"integer","description":"Asset amount"},"asset_type":{"type":"string","enum":["PHYSICAL","VIRTUAL"]},"data_types_stored":{"type":"string","description":"Data types stored"},"name":{"type":"string","description":"Asset name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"vendor_ids":{"type":"array","description":"Vendor IDs","items":{"type":"string","format":"string"}}}}`) + AddAssetToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["asset"],"properties":{"asset":{"type":"object","required":["id","organization_id","name","amount","owner_id","asset_type","data_types_stored","created_at","updated_at"],"properties":{"amount":{"type":"integer","description":"Asset amount"},"asset_type":{"type":"string","enum":["PHYSICAL","VIRTUAL"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_types_stored":{"type":"string","description":"Data types stored"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Asset name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) AddFrameworkToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","name"],"properties":{"description":{"type":"string","description":"Framework description"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"}}}`) AddFrameworkToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["framework"],"properties":{"framework":{"type":"object","required":["id","organization_id","name","created_at","updated_at"],"properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) 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"}}}`) @@ -22,6 +24,8 @@ var ( 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"}}}}}`) + GetAssetToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`) + GetAssetToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["asset"],"properties":{"asset":{"type":"object","required":["id","organization_id","name","amount","owner_id","asset_type","data_types_stored","created_at","updated_at"],"properties":{"amount":{"type":"integer","description":"Asset amount"},"asset_type":{"type":"string","enum":["PHYSICAL","VIRTUAL"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_types_stored":{"type":"string","description":"Data types stored"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Asset name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) GetFrameworkToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`) GetFrameworkToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["framework"],"properties":{"framework":{"type":"object","required":["id","organization_id","name","created_at","updated_at"],"properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) GetMeasureToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`) @@ -30,6 +34,8 @@ var ( 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"}}}}}`) + ListAssetsToolInputSchema = 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","AMOUNT"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`) + ListAssetsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["assets"],"properties":{"assets":{"type":"array","items":{"type":"object","required":["id","organization_id","name","amount","owner_id","asset_type","data_types_stored","created_at","updated_at"],"properties":{"amount":{"type":"integer","description":"Asset amount"},"asset_type":{"type":"string","enum":["PHYSICAL","VIRTUAL"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_types_stored":{"type":"string","description":"Data types stored"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Asset name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}},"next_cursor":{"type":"string","format":"string"}}}`) ListFrameworksToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id"],"properties":{"cursor":{"type":"string","format":"string"},"order_by":{"type":"object","required":["field","direction"],"properties":{"direction":{"type":"string","enum":["asc","desc"]},"field":{"type":"string","enum":["CREATED_AT"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`) ListFrameworksToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["frameworks"],"properties":{"frameworks":{"type":"array","items":{"type":"object","required":["id","organization_id","name","created_at","updated_at"],"properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}},"next_cursor":{"type":"string","format":"string"}}}`) 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"}}}`) @@ -42,6 +48,8 @@ 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"}}}}}}`) + UpdateAssetToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"amount":{"type":"integer","description":"Asset amount"},"asset_type":{"type":"string","enum":["PHYSICAL","VIRTUAL"]},"data_types_stored":{"type":"string","description":"Data types stored"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Asset name"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"vendor_ids":{"type":"array","description":"Vendor IDs","items":{"type":"string","format":"string"}}}}`) + UpdateAssetToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["asset"],"properties":{"asset":{"type":"object","required":["id","organization_id","name","amount","owner_id","asset_type","data_types_stored","created_at","updated_at"],"properties":{"amount":{"type":"integer","description":"Asset amount"},"asset_type":{"type":"string","enum":["PHYSICAL","VIRTUAL"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_types_stored":{"type":"string","description":"Data types stored"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Asset name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) UpdateFrameworkToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"}}}`) UpdateFrameworkToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["framework"],"properties":{"framework":{"type":"object","required":["id","organization_id","name","created_at","updated_at"],"properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Framework description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Framework name"},"organization_id":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`) 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"]}}}`) @@ -52,6 +60,29 @@ var ( 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"}}}}}`) ) +// AddAssetInput represents the schema +type AddAssetInput struct { + // Asset amount + Amount int `json:"amount"` + // Asset type + AssetType coredata.AssetType `json:"asset_type"` + // Data types stored + DataTypesStored string `json:"data_types_stored"` + // Asset name + Name string `json:"name"` + // Organization ID + OrganizationID gid.GID `json:"organization_id"` + // Owner ID + OwnerID gid.GID `json:"owner_id"` + // Vendor IDs + VendorIds []gid.GID `json:"vendor_ids,omitempty"` +} + +// AddAssetOutput represents the schema +type AddAssetOutput struct { + Asset *Asset `json:"asset"` +} + // AddFrameworkInput represents the schema type AddFrameworkInput struct { // Framework description @@ -159,6 +190,38 @@ type AddVendorOutput struct { Vendor *Vendor `json:"vendor"` } +// Asset represents the schema +type Asset struct { + // Asset amount + Amount int `json:"amount"` + // Asset type + AssetType coredata.AssetType `json:"asset_type"` + // Creation timestamp + CreatedAt time.Time `json:"created_at"` + // Data types stored + DataTypesStored string `json:"data_types_stored"` + // Asset ID + ID gid.GID `json:"id"` + // Asset name + Name string `json:"name"` + // Organization ID + OrganizationID gid.GID `json:"organization_id"` + // Owner ID + OwnerID gid.GID `json:"owner_id"` + // Snapshot ID + SnapshotID *string `json:"snapshot_id,omitempty"` + // Update timestamp + UpdatedAt time.Time `json:"updated_at"` +} + +// AssetOrderBy represents the schema +type AssetOrderBy struct { + // Asset order direction + Direction page.OrderDirection `json:"direction"` + // Asset order field + Field coredata.AssetOrderField `json:"field"` +} + // Framework represents the schema type Framework struct { // Creation timestamp @@ -183,6 +246,17 @@ type FrameworkOrderBy struct { Field coredata.FrameworkOrderField `json:"field"` } +// GetAssetInput represents the schema +type GetAssetInput struct { + // Asset ID + ID gid.GID `json:"id"` +} + +// GetAssetOutput represents the schema +type GetAssetOutput struct { + Asset *Asset `json:"asset"` +} + // GetFrameworkInput represents the schema type GetFrameworkInput struct { // Framework ID @@ -227,6 +301,26 @@ type GetRiskOutput struct { Risk *Risk `json:"risk"` } +// ListAssetsInput represents the schema +type ListAssetsInput struct { + // Page cursor + Cursor *page.CursorKey `json:"cursor,omitempty"` + Filter *ListAssetsInputFilter `json:"filter,omitempty"` + // Asset order by + OrderBy *AssetOrderBy `json:"order_by,omitempty"` + // Organization ID + OrganizationID gid.GID `json:"organization_id"` + // Page size + Size *int `json:"size,omitempty"` +} + +// ListAssetsOutput represents the schema +type ListAssetsOutput struct { + Assets []*Asset `json:"assets"` + // Next cursor + NextCursor *page.CursorKey `json:"next_cursor,omitempty"` +} + // ListFrameworksInput represents the schema type ListFrameworksInput struct { // Page cursor @@ -457,6 +551,29 @@ type RiskOrderBy struct { Field coredata.RiskOrderField `json:"field"` } +// UpdateAssetInput represents the schema +type UpdateAssetInput struct { + // Asset amount + Amount *int `json:"amount,omitempty"` + // Asset type + AssetType *coredata.AssetType `json:"asset_type,omitempty"` + // Data types stored + DataTypesStored *string `json:"data_types_stored,omitempty"` + // Asset ID + ID gid.GID `json:"id"` + // Asset name + Name *string `json:"name,omitempty"` + // Owner ID + OwnerID *gid.GID `json:"owner_id,omitempty"` + // Vendor IDs + VendorIds []gid.GID `json:"vendor_ids,omitempty"` +} + +// UpdateAssetOutput represents the schema +type UpdateAssetOutput struct { + Asset *Asset `json:"asset"` +} + // UpdateFrameworkInput represents the schema type UpdateFrameworkInput struct { // Framework description @@ -561,6 +678,12 @@ type VendorOrderBy struct { Field coredata.VendorOrderField `json:"field"` } +// ListAssetsInputFilter represents the schema +type ListAssetsInputFilter struct { + // Snapshot ID + SnapshotID *gid.GID `json:"snapshot_id,omitempty"` +} + // ListMeasuresInputFilter represents the schema type ListMeasuresInputFilter struct { // Search query