Investigate security events and manage the allow/deny lists an analyst acts on.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Archive a list entry so it stops matching. Reversible with castle_unarchive_list_item. Castle: DELETE /v1/lists/{list_id}/items/{id}/archive.
The item to archive.
The list holding the item.
The server marks this tool as destructive. Running it may delete or overwrite data on the server or in any account you connected with your headers.
Archive a list entry so it stops matching. Reversible with castle_unarchive_list_item. Castle: DELETE /v1/lists/{list_id}/items/{id}/archive.
| Argument | Type | Description |
|---|---|---|
| item_id* | string | The item to archive. |
| list_id* | string | The list holding the item. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"list_id",
"item_id"
],
"properties": {
"item_id": {
"type": "string",
"description": "The item to archive."
},
"list_id": {
"type": "string",
"description": "The list holding the item."
}
}
}Count the entries in one list, with the same optional filters as the search. Read-only despite being a POST. Castle: POST /v1/lists/{list_id}/items/count.
| Argument | Type | Description |
|---|---|---|
| filters | array | Optional {field, op, value} filters over the items. |
| list_id* | string | The list to count. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"list_id"
],
"properties": {
"filters": {
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"description": "Optional {field, op, value} filters over the items."
},
"list_id": {
"type": "string",
"description": "The list to count."
}
}
}Create a new allow or deny list. primary_field is the event field its entries match on, e.g. ip or user.email. Castle: POST /v1/lists.
| Argument | Type | Description |
|---|---|---|
| name* | string | The list name. |
| color* | string | Dashboard colour label, e.g. $red, $green, $blue — Castle requires one. |
| description | string | What this list is for. |
| primary_field* | string | The event field entries match on, e.g. ip or user.email. |
| secondary_field | string | An optional second field entries also carry. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"name",
"color",
"primary_field"
],
"properties": {
"name": {
"type": "string",
"description": "The list name."
},
"color": {
"type": "string",
"description": "Dashboard colour label, e.g. $red, $green, $blue — Castle requires one."
},
"description": {
"type": "string",
"description": "What this list is for."
},
"primary_field": {
"type": "string",
"description": "The event field entries match on, e.g. ip or user.email."
},
"secondary_field": {
"type": "string",
"description": "An optional second field entries also carry."
}
}
}Add an entry to a list — for example block an IP or an email. This changes live policy behaviour. Castle: POST /v1/lists/{list_id}/items.
| Argument | Type | Description |
|---|---|---|
| comment | string | Why this entry was added. |
| list_id* | string | The list to add to. |
| author_type* | string | What kind of actor is adding this entry. |
| primary_value* | string | The value to add, matching the list's primary_field. |
| secondary_value | string | Value for the list's secondary_field. |
| auto_archives_at | string | ISO-8601 time to archive the entry automatically. |
| author_identifier* | string | Who is adding it, e.g. the analyst's email address. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"list_id",
"primary_value",
"author_type",
"author_identifier"
],
"properties": {
"comment": {
"type": "string",
"description": "Why this entry was added."
},
"list_id": {
"type": "string",
"description": "The list to add to."
},
"author_type": {
"enum": [
"$analyst_email",
"$castle_dashboard_user",
"$castle_policy",
"$user",
"$user_email",
"$other"
],
"type": "string",
"description": "What kind of actor is adding this entry."
},
"primary_value": {
"type": "string",
"description": "The value to add, matching the list's primary_field."
},
"secondary_value": {
"type": "string",
"description": "Value for the list's secondary_field."
},
"auto_archives_at": {
"type": "string",
"description": "ISO-8601 time to archive the entry automatically."
},
"author_identifier": {
"type": "string",
"description": "Who is adding it, e.g. the analyst's email address."
}
}
}List the event fields you can filter and group on, with their types. Read this first — the other query tools need real field names. Castle: GET /v1/events/schema.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}Fetch a single list with its primary and secondary field definitions. Castle: GET /v1/lists/{id}.
| Argument | Type | Description |
|---|---|---|
| list_id* | string | The list's id. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"list_id"
],
"properties": {
"list_id": {
"type": "string",
"description": "The list's id."
}
}
}Fetch a single list entry — its value, who added it, the comment and its archive time. Castle: GET /v1/lists/{list_id}/items/{id}.
| Argument | Type | Description |
|---|---|---|
| item_id* | string | The item's id. |
| list_id* | string | The list holding the item. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"list_id",
"item_id"
],
"properties": {
"item_id": {
"type": "string",
"description": "The item's id."
},
"list_id": {
"type": "string",
"description": "The list holding the item."
}
}
}Aggregate matching events by one or more fields — the fast way to see which IPs, devices or countries dominate a spike. Read-only despite being a POST. Castle: POST /v1/events/group.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| filters* | array | Castle query filters, ANDed together. Each is {field, op, value} — e.g. {"field":"user.email","op":"$eq","value":"[email protected]"}. Operators: $eq, $neq, $in, $nin, $like, $nlike, $contains, $ncontains, $starts_with, $nstarts_with, $ends_with, $nends_with, $matches, $nmatches, $ip_range, $nip_range, $relative_range (value {gt,gteq,lt,lteq} in seconds ago), $range, $exists. Call castle_get_events_schema first to see the available field names. |
| results_size | integer | Results per page, 1-100. |
| group_by_fields* | array | Fields to group by, e.g. ["ip", "user.email"]. Names come from the event schema. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"filters",
"group_by_fields"
],
"properties": {
"page": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based page number."
},
"filters": {
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"description": "Castle query filters, ANDed together. Each is {field, op, value} — e.g. {\"field\":\"user.email\",\"op\":\"$eq\",\"value\":\"[email protected]\"}. Operators: $eq, $neq, $in, $nin, $like, $nlike, $contains, $ncontains, $starts_with, $nstarts_with, $ends_with, $nends_with, $matches, $nmatches, $ip_range, $nip_range, $relative_range (value {gt,gteq,lt,lteq} in seconds ago), $range, $exists. Call castle_get_events_schema first to see the available field names."
},
"results_size": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Results per page, 1-100."
},
"group_by_fields": {
"type": "array",
"items": {
"type": "string"
},
"description": "Fields to group by, e.g. [\"ip\", \"user.email\"]. Names come from the event schema."
}
}
}Query the security event stream — logins, registrations, transactions and their risk verdicts. Read-only despite being a POST: Castle takes the query in the body. Castle: POST /v1/events/query.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| columns | array | Only return these event fields. |
| filters* | array | Castle query filters, ANDed together. Each is {field, op, value} — e.g. {"field":"user.email","op":"$eq","value":"[email protected]"}. Operators: $eq, $neq, $in, $nin, $like, $nlike, $contains, $ncontains, $starts_with, $nstarts_with, $ends_with, $nends_with, $matches, $nmatches, $ip_range, $nip_range, $relative_range (value {gt,gteq,lt,lteq} in seconds ago), $range, $exists. Call castle_get_events_schema first to see the available field names. |
| query_type | string | Return matching records, just a count, or both. Defaults to records. |
| results_size | integer | Results per page, 1-100. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"filters"
],
"properties": {
"page": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based page number."
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "Only return these event fields."
},
"filters": {
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"description": "Castle query filters, ANDed together. Each is {field, op, value} — e.g. {\"field\":\"user.email\",\"op\":\"$eq\",\"value\":\"[email protected]\"}. Operators: $eq, $neq, $in, $nin, $like, $nlike, $contains, $ncontains, $starts_with, $nstarts_with, $ends_with, $nends_with, $matches, $nmatches, $ip_range, $nip_range, $relative_range (value {gt,gteq,lt,lteq} in seconds ago), $range, $exists. Call castle_get_events_schema first to see the available field names."
},
"query_type": {
"enum": [
"$records",
"$count",
"$records_with_count"
],
"type": "string",
"description": "Return matching records, just a count, or both. Defaults to records."
},
"results_size": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Results per page, 1-100."
}
}
}Search the entries of one list — the blocked IPs, emails or device ids it holds. Read-only despite being a POST. Castle: POST /v1/lists/{list_id}/items/query.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| filters | array | Optional {field, op, value} filters over the items. |
| list_id* | string | The list to search. |
| results_size | integer | Results per page, 1-100. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"list_id"
],
"properties": {
"page": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based page number."
},
"filters": {
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"description": "Optional {field, op, value} filters over the items."
},
"list_id": {
"type": "string",
"description": "The list to search."
},
"results_size": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Results per page, 1-100."
}
}
}Find the allow/deny lists defined in the environment. Read-only despite being a POST. Castle: POST /v1/lists/query.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| filters | array | Optional {field, op, value} filters over the lists themselves. |
| results_size | integer | Results per page, 1-100. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"page": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based page number."
},
"filters": {
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"description": "Optional {field, op, value} filters over the lists themselves."
},
"results_size": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Results per page, 1-100."
}
}
}Restore a previously archived list entry so it matches again. Castle: PUT /v1/lists/{list_id}/items/{id}/unarchive.
| Argument | Type | Description |
|---|---|---|
| item_id* | string | The item to restore. |
| list_id* | string | The list holding the item. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"list_id",
"item_id"
],
"properties": {
"item_id": {
"type": "string",
"description": "The item to restore."
},
"list_id": {
"type": "string",
"description": "The list holding the item."
}
}
}Rename a list or change its colour or description. Castle: PUT /v1/lists/{id}.
| Argument | Type | Description |
|---|---|---|
| name | string | New name. |
| color | string | New colour label. |
| list_id* | string | The list to update. |
| description | string | New description. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"list_id"
],
"properties": {
"name": {
"type": "string",
"description": "New name."
},
"color": {
"type": "string",
"description": "New colour label."
},
"list_id": {
"type": "string",
"description": "The list to update."
},
"description": {
"type": "string",
"description": "New description."
}
}
}Change the comment on a list entry. Castle: PUT /v1/lists/{list_id}/items/{id}.
| Argument | Type | Description |
|---|---|---|
| comment* | string | The new comment. |
| item_id* | string | The item to update. |
| list_id* | string | The list holding the item. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"list_id",
"item_id",
"comment"
],
"properties": {
"comment": {
"type": "string",
"description": "The new comment."
},
"item_id": {
"type": "string",
"description": "The item to update."
},
"list_id": {
"type": "string",
"description": "The list holding the item."
}
}
}