-
Notifications
You must be signed in to change notification settings - Fork 5.8k
elastic_security: AI-optimized MCP actions #21824
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
michelle0927
wants to merge
13
commits into
master
Choose a base branch
from
issue-21664-elastic-security
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,418
−6
Open
Changes from 9 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
ed59aaa
feat(elastic_security): AI-optimized MCP actions
michelle0927 00c42b7
fix(elastic_security): add missing trailing newline to package.json
michelle0927 9a021b3
fix(elastic_security): address PR review feedback
michelle0927 d8c78f2
fix(elastic_security): add missing concrete examples to id/ruleId/fie…
michelle0927 1d30fd3
fix(elastic_security): guard against changing a rule's type on update
michelle0927 ea6f0c1
fix(elastic_security): block additionalFields from overriding dedicat…
michelle0927 6c270ab
Merge branch 'master' into issue-21664-elastic-security
vetrivigneshwaran 2f8e2ef
fix(elastic_security): additional PR review fixes
michelle0927 00902e4
Merge branch 'issue-21664-elastic-security' of https://github.com/Pip…
michelle0927 17c7c53
docs(elastic_security): clarify additionalFields read-only field hand…
michelle0927 1ef1284
Merge branch 'master' into issue-21664-elastic-security
vetrivigneshwaran e531216
fix(elastic_security): fix data-loss bug, URL encoding, and prototype…
michelle0927 ae5d3cf
add ai: "optimized"
michelle0927 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
50 changes: 50 additions & 0 deletions
50
components/elastic_security/actions/add-case-comment/add-case-comment.mjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| // x-pd-ai: optimized | ||
| import elasticSecurity from "../../elastic_security.app.mjs"; | ||
| import { | ||
| CASE_COMMENT_TYPE_USER, CASE_OWNER, | ||
| } from "../../common/constants.mjs"; | ||
|
|
||
| export default { | ||
| key: "elastic_security-add-case-comment", | ||
| name: "Add Case Comment", | ||
| description: "Add a user comment to an Elastic Security case via POST /api/cases/{caseId}/comments." | ||
| + " Use this to log investigation notes or updates on a case without changing its status or fields — use **Create or Update Case** for that." | ||
| + " Run **Find Cases** first to obtain a valid case ID." | ||
| + " Example: calling with `caseId: \"a1c1...\"` and `comment: \"Confirmed unauthorized access via badge logs.\"` returns the updated case object with `totalComment` incremented and the new comment in `comments`." | ||
| + " [See the documentation](https://www.elastic.co/docs/api/doc/kibana/operation/operation-addcasecommentdefaultspace)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| annotations: { | ||
| readOnlyHint: false, | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| }, | ||
| props: { | ||
| elasticSecurity, | ||
| caseId: { | ||
| propDefinition: [ | ||
| elasticSecurity, | ||
| "caseId", | ||
| ], | ||
| description: "The ID of the case to comment on. Run **Find Cases** first to obtain valid case IDs.", | ||
| }, | ||
| comment: { | ||
| type: "string", | ||
| label: "Comment", | ||
| description: "The text of the user comment to add.", | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const response = await this.elasticSecurity.addCaseComment({ | ||
| $, | ||
| caseId: this.caseId, | ||
| data: { | ||
| type: CASE_COMMENT_TYPE_USER, | ||
| comment: this.comment, | ||
| owner: CASE_OWNER, | ||
| }, | ||
| }); | ||
| $.export("$summary", `Added comment to case ${this.caseId}`); | ||
| return response; | ||
| }, | ||
| }; |
154 changes: 154 additions & 0 deletions
154
components/elastic_security/actions/create-or-update-case/create-or-update-case.mjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| // x-pd-ai: optimized | ||
| import { ConfigurationError } from "@pipedream/platform"; | ||
| import elasticSecurity from "../../elastic_security.app.mjs"; | ||
| import { | ||
| CASE_OWNER, DEFAULT_CASE_CONNECTOR, | ||
| } from "../../common/constants.mjs"; | ||
|
|
||
| export default { | ||
| key: "elastic_security-create-or-update-case", | ||
| name: "Create or Update Case", | ||
| description: "Create a new Elastic Security case, or update an existing one when `caseId` is provided, via POST /api/cases or PATCH /api/cases." | ||
| + " Use this to open a new case, or to edit a case's title, description, severity, tags, category, assignees, or status." | ||
| + " When `caseId` is provided, the tool fetches the case's current `version` internally before updating — never guess or supply a version yourself." | ||
| + " Run **Find Cases** first to obtain a `caseId` for updates. Use **Add Case Comment** to attach comments instead of this tool." | ||
| + " `title` and `description` are required when creating (no `caseId`)." | ||
| + " Example: calling with `title: \"Perimeter Breach\"`, `description: \"...\"`, `severity: \"high\"` returns `{ id: \"a1c1...\", title: \"Perimeter Breach\", status: \"open\", version: \"Wzc1LDFd\", ... }`; calling again with that `caseId` and `status: \"closed\"` returns the same case updated." | ||
| + " [See the create documentation](https://www.elastic.co/docs/api/doc/kibana/operation/operation-createcasedefaultspace) and the [update documentation](https://www.elastic.co/docs/api/doc/kibana/operation/operation-updatecasedefaultspace)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| annotations: { | ||
| readOnlyHint: false, | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| }, | ||
| props: { | ||
| elasticSecurity, | ||
| caseId: { | ||
| propDefinition: [ | ||
| elasticSecurity, | ||
| "caseId", | ||
| ], | ||
| description: "The ID of an existing case to update. Omit this to create a new case instead. Run **Find Cases** first to obtain valid case IDs.", | ||
| optional: true, | ||
| }, | ||
| title: { | ||
| type: "string", | ||
| label: "Title", | ||
| description: "Case title (max 160 characters). Required when creating a new case (no `caseId`).", | ||
| optional: true, | ||
| }, | ||
| description: { | ||
| type: "string", | ||
| label: "Description", | ||
| description: "Case description (max 30000 characters). Required when creating a new case (no `caseId`).", | ||
| optional: true, | ||
| }, | ||
| severity: { | ||
| propDefinition: [ | ||
| elasticSecurity, | ||
| "severity", | ||
| ], | ||
| description: "Case severity. One of: `low`, `medium`, `high`, `critical`.", | ||
| optional: true, | ||
| }, | ||
| status: { | ||
| propDefinition: [ | ||
| elasticSecurity, | ||
| "status", | ||
| ], | ||
| description: "New case status. Only applies when updating an existing case (`caseId` provided) — the create API has no status field.", | ||
| optional: true, | ||
| }, | ||
| tags: { | ||
| propDefinition: [ | ||
| elasticSecurity, | ||
| "tags", | ||
| ], | ||
| description: "Tags to apply to the case. Run **List Tags** first to reuse existing tags instead of creating near-duplicates. On update, this replaces the case's existing tag set entirely.", | ||
| optional: true, | ||
| }, | ||
| category: { | ||
| type: "string", | ||
| label: "Category", | ||
| description: "Case category (max 50 characters).", | ||
| optional: true, | ||
| }, | ||
| assignees: { | ||
| type: "string[]", | ||
| label: "Assignees", | ||
| description: "User profile IDs to assign to the case (max 10). Example: `[\"u_abc123\"]`. Run **Find Assignable Users** first to discover valid `profile_uid` values. On update, this replaces the case's existing assignee set entirely.", | ||
| optional: true, | ||
| }, | ||
| syncAlerts: { | ||
| type: "boolean", | ||
| label: "Sync Alerts", | ||
| description: "Whether to sync the status of attached alerts with the case status. Defaults to `true` on create.", | ||
| optional: true, | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const assignees = this.assignees | ||
| ? this.assignees.map((uid) => ({ | ||
| uid, | ||
| })) | ||
| : undefined; | ||
|
|
||
| if (!this.caseId) { | ||
| if (!this.title || !this.description) { | ||
| throw new ConfigurationError("`title` and `description` are required when creating a new case (no `caseId` provided)."); | ||
| } | ||
| const response = await this.elasticSecurity.createCase({ | ||
| $, | ||
| data: { | ||
| title: this.title, | ||
| description: this.description, | ||
| severity: this.severity, | ||
| tags: this.tags ?? [], | ||
| category: this.category, | ||
| assignees, | ||
| settings: { | ||
| syncAlerts: this.syncAlerts ?? true, | ||
| }, | ||
| connector: DEFAULT_CASE_CONNECTOR, | ||
| owner: CASE_OWNER, | ||
| }, | ||
| }); | ||
| $.export("$summary", `Created case "${response.title}" (${response.id})`); | ||
| return response; | ||
| } | ||
|
|
||
| const current = await this.elasticSecurity.getCase({ | ||
| $, | ||
| caseId: this.caseId, | ||
| }); | ||
| const response = await this.elasticSecurity.updateCase({ | ||
| $, | ||
| data: { | ||
| cases: [ | ||
| { | ||
| id: this.caseId, | ||
| version: current.version, | ||
| title: this.title, | ||
| description: this.description, | ||
| severity: this.severity, | ||
| status: this.status, | ||
| tags: this.tags, | ||
| category: this.category, | ||
| assignees, | ||
| settings: this.syncAlerts === undefined | ||
| ? undefined | ||
| : { | ||
| syncAlerts: this.syncAlerts, | ||
| }, | ||
| }, | ||
| ], | ||
| }, | ||
| }); | ||
| const [ | ||
| updated, | ||
| ] = response; | ||
| $.export("$summary", `Updated case "${updated.title}" (${updated.id})`); | ||
| return updated; | ||
| }, | ||
| }; | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.