Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,22 @@ npm run build

### Tools

- **Projects / profiles / risk policies**: `list_projects`, `get_project`, `create_project`, `update_project`, `delete_project`, `create_project_from_code`, `list_profiles`, `list_risk_policies`, `get_risk_policy`
- **Applications**: `list_applications`, `get_application`, `create_application`, `update_application`
- **Business units**: `list_business_units`, `get_business_unit`
- **Countermeasures**: `list_countermeasures`, `get_countermeasure`, `update_countermeasure`, `add_countermeasure_note`, `get_task_status_choices`
- **Surveys**: `get_project_survey`, `get_survey_answers_for_project`, `update_project_survey`, `find_survey_answers`, `set_project_survey_by_text`, `add_survey_answers_by_text`, `remove_survey_answers_by_text`, `commit_survey_draft`, `add_survey_question_comment`
- **Scans**: `list_scan_connections`, `scan_repository`, `get_scan_status`, `list_scans`
- **Diagrams**: `list_project_diagrams`, `get_diagram`, `create_diagram`, `update_diagram`, `delete_diagram`
- **Reports / Cube**: `list_advanced_reports`, `get_advanced_report`, `update_advanced_report`, `run_advanced_report`, `create_advanced_report`, `execute_cube_query`
- **Users**: `list_users`, `get_user`, `get_current_user`
- **Generic**: `test_connection`, `api_request`
- **Toolset selection**: default is **compact**. Set `SDE_TOOLSET=full` to expose the legacy toolset.
- **Note**: diagrams and reporting tools are not exposed.
- **Compact tools (default)**:
- `project`, `application`, `business_unit`, `project_survey`, `project_countermeasures`, `library_search`
- plus **Generic**: `test_connection`, `api_request`
- **Legacy tools (when `SDE_TOOLSET=full`)**:
- **Projects**: `list_projects`, `get_project`, `create_project`, `update_project`, `create_project_from_code`
- **Library search**: `library_search` (supports countermeasures, threats, components, weaknesses, profiles, risk policies, answers, countermeasure statuses, countermeasure how-tos)
- **Applications**: `list_applications`, `get_application`, `create_application`, `update_application`
- **Business units**: `list_business_units`, `get_business_unit`, `create_business_unit`, `update_business_unit`
- **Countermeasures**: `list_countermeasures`, `get_countermeasure`, `update_countermeasure`, `add_countermeasure_note`, `get_task_status_choices`
- **Surveys**: `get_project_survey`, `get_survey_answers_for_project`, `update_project_survey`, `find_survey_answers`, `set_project_survey_by_text`, `add_survey_answers_by_text`, `remove_survey_answers_by_text`, `commit_survey_draft`, `add_survey_question_comment`
- **Scans**: `list_scan_connections`, `scan_repository`, `get_scan_status`, `list_scans`
- **Users**: `list_users`, `get_user`, `get_current_user`
- **Library**: `library_search`
- **Generic**: `test_connection`, `api_request`

### Notes

Expand Down
62 changes: 34 additions & 28 deletions SUPPORTED_PROMPTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,25 @@ This document lists all supported prompts for the SD Elements MCP Server, organi

## Business Units

### create_business_unit

- Create a new business unit called Platform
- Add a business unit for Security with default risk policy 29
- Create business unit named API Team

### get_business_unit

- Get business unit 123
- Get business unit information for ID 123
- Show me details for business unit 123
- What's business unit 123?

### update_business_unit

- Update business unit 123 name to Platform
- Modify business unit 123 to include all users
- Update business unit 123 default risk policy to 29

### list_business_units

- List all business units
Expand Down Expand Up @@ -162,6 +174,28 @@ This document lists all supported prompts for the SD Elements MCP Server, organi

---

## Library

### library_search

- Search the library for authentication countermeasures
- Find threats related to SQL injection
- Search library components for "API gateway"
- Look up weaknesses about broken access control
- List available project profiles
- Find profiles for mobile applications
- List all risk policies
- Show me all available risk policies
- What risk policies are available?
- Get me a list of risk policies
- Get risk policy 5
- Show me details for risk policy 3
- What is risk policy 2?
- List library answers for programming languages
- Search library answers for "web application"

---

## Projects

### create_project
Expand All @@ -184,13 +218,6 @@ This document lists all supported prompts for the SD Elements MCP Server, organi
- Scan repository and create project
- Set up a project by scanning the code repository

### delete_project

- Archive project 456 as it's been completed
- Delete project 456
- Remove project 456 from the system
- Remove the deprecated project 456

### get_project

- Get details for project 123
Expand All @@ -202,27 +229,6 @@ This document lists all supported prompts for the SD Elements MCP Server, organi
- What's the security posture of project 123?
- What's the status of project 123?

### list_profiles

- List all profiles
- Show me all available profiles
- Show me the available project profiles
- What profiles are available?
- What security profiles are available?

### list_risk_policies

- List all risk policies
- Show me all available risk policies
- What risk policies are available?
- Get me a list of risk policies

### get_risk_policy

- Get risk policy 5
- Show me details for risk policy 3
- What is risk policy 2?

### list_projects

- Can you show me all active projects?
Expand Down
6 changes: 2 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ function hasArgFlag(flag: string): boolean {
return process.argv.includes(flag);
}

const useHttp = hasArgFlag("--http") || hasNpmConfigFlag("http");

(useHttp ? mainHttp : mainStdio)().catch((err: unknown) => {
const useHttp = hasArgFlag("--http") || hasNpmConfigFlag("http");(useHttp ? mainHttp : mainStdio)().catch((err: unknown) => {
console.error(err);
process.exit(1);
});
});
5 changes: 3 additions & 2 deletions src/tools/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function registerApplicationTools(
"create_application",
{
title: "Create Application",
description: "Create a new application",
description: "Create a new application. Client should ask for confirmation before running.",
inputSchema: z.object({
name: z.string().describe("Name of the application"),
business_unit_id: z.number().describe("ID of the business unit"),
Expand Down Expand Up @@ -92,7 +92,8 @@ export function registerApplicationTools(
"update_application",
{
title: "Update Application",
description: "Update an existing application",
description:
"Update an existing application. Client should ask for confirmation before running.",
inputSchema: z.object({
application_id: z.number().describe("ID of the application to update"),
name: z.string().optional().describe("New name for the application"),
Expand Down
138 changes: 138 additions & 0 deletions src/tools/businessUnits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,144 @@ export function registerBusinessUnitTools(
}
);

// Create business unit
server.registerTool(
"create_business_unit",
{
title: "Create Business Unit",
description:
"Create a new business unit. Client should ask for confirmation before running.",
inputSchema: z.object({
name: z.string().describe("Name of the business unit"),
users: z
.array(z.object({ email: z.string() }))
.optional()
.describe("Users to include in the business unit: [{email}]"),
groups: z
.array(z.object({ id: z.string() }))
.optional()
.describe("Groups to include in the business unit: [{id}]"),
default_users: z
.array(z.object({ email: z.string(), role: z.string().optional() }))
.optional()
.describe("Default user roles: [{email, role}]"),
default_groups: z
.array(z.object({ id: z.string(), role: z.string().optional() }))
.optional()
.describe("Default group roles: [{id, role}]"),
all_users: z
.boolean()
.optional()
.describe("Whether the business unit includes all users"),
persist_phases: z
.boolean()
.optional()
.describe("Persist phases for tasks/weaknesses in this business unit"),
default_risk_policy: z
.number()
.optional()
.describe("Default risk policy ID for this business unit"),
}),
},
async ({
name,
users,
groups,
default_users,
default_groups,
all_users,
persist_phases,
default_risk_policy,
}) => {
const data: Record<string, unknown> = { name };
if (users) data.users = users;
if (groups) data.groups = groups;
if (default_users) data.default_users = default_users;
if (default_groups) data.default_groups = default_groups;
if (all_users !== undefined) data.all_users = all_users;
if (persist_phases !== undefined) data.persist_phases = persist_phases;
if (default_risk_policy !== undefined)
data.default_risk_policy = default_risk_policy;

const result = await client.createBusinessUnit(data);
return jsonToolResult(result);
}
);

// Update business unit
server.registerTool(
"update_business_unit",
{
title: "Update Business Unit",
description:
"Update an existing business unit. Client should ask for confirmation before running.",
inputSchema: z.object({
business_unit_id: z.number().describe("ID of the business unit"),
name: z.string().optional().describe("Business unit name"),
users: z
.array(z.object({ email: z.string() }))
.optional()
.describe("Users to include in the business unit: [{email}]"),
groups: z
.array(z.object({ id: z.string() }))
.optional()
.describe("Groups to include in the business unit: [{id}]"),
default_users: z
.array(z.object({ email: z.string(), role: z.string().optional() }))
.optional()
.describe("Default user roles: [{email, role}]"),
default_groups: z
.array(z.object({ id: z.string(), role: z.string().optional() }))
.optional()
.describe("Default group roles: [{id, role}]"),
all_users: z
.boolean()
.optional()
.describe("Whether the business unit includes all users"),
persist_phases: z
.boolean()
.optional()
.describe("Persist phases for tasks/weaknesses in this business unit"),
default_risk_policy: z
.number()
.optional()
.describe("Default risk policy ID for this business unit"),
}),
},
async ({
business_unit_id,
name,
users,
groups,
default_users,
default_groups,
all_users,
persist_phases,
default_risk_policy,
}) => {
const data: Record<string, unknown> = {};
if (name !== undefined) data.name = name;
if (users !== undefined) data.users = users;
if (groups !== undefined) data.groups = groups;
if (default_users !== undefined) data.default_users = default_users;
if (default_groups !== undefined) data.default_groups = default_groups;
if (all_users !== undefined) data.all_users = all_users;
if (persist_phases !== undefined) data.persist_phases = persist_phases;
if (default_risk_policy !== undefined)
data.default_risk_policy = default_risk_policy;

if (Object.keys(data).length === 0) {
return jsonToolResult({
error:
"No update data provided. Specify at least one field (name, users, groups, default_users, default_groups, all_users, persist_phases, default_risk_policy).",
});
}

const result = await client.updateBusinessUnit(business_unit_id, data);
return jsonToolResult(result);
}
);

// Get business unit
server.registerTool(
"get_business_unit",
Expand Down
Loading
Loading