loading…
Search for a command to run...
loading…
A Discord MCP server with multi-guild project routing, enabling messaging, moderation, and notification management across multiple Discord servers via natural l
A Discord MCP server with multi-guild project routing, enabling messaging, moderation, and notification management across multiple Discord servers via natural language.
Agency-grade Discord MCP server with multi-guild project routing.
send_message({ project: "my-app", channel: "builds" }) instead of raw channel IDsci_build, deploy, error) to channels per projectraw: true for plain textsend_embed fetches Open Graph metadata server-side and renders rich link previewsdiscord-ops validate detects duplicate guilds, missing tokens, invalid channel refs without connecting to DiscordDISCORD_OPS_HTTP_TOKEN with constant-time comparisondiscord-ops setup supports single-bot and multi-bot configuration# Install
npm install -g discord-ops
# Interactive setup (creates ~/.discord-ops.json)
discord-ops setup
# Or manual setup
export DISCORD_TOKEN="your-bot-token"
discord-ops health
# Start MCP server (stdio)
discord-ops
# Start MCP server (HTTP/SSE)
discord-ops serve --port 3000
Add to your project's .mcp.json. Use npx with @latest so every session automatically uses the latest published release — without it, npx may serve a stale cached version indefinitely:
{
"mcpServers": {
"discord-ops": {
"command": "npx",
"args": ["-y", "discord-ops@latest"],
"env": {
"DISCORD_TOKEN": "${DISCORD_TOKEN}"
}
}
}
}
The ${VAR} syntax is Claude Code's native env var interpolation — it reads the value from your shell environment at startup. Export your bot token in ~/.zshrc (or .bashrc) and it will be available to all projects without hardcoding it in any file.
When each project has its own bot, pass all token env vars and let ~/.discord-ops.json handle which project uses which:
{
"mcpServers": {
"discord-ops": {
"command": "npx",
"args": ["-y", "discord-ops@latest"],
"env": {
"ORG_A_DISCORD_TOKEN": "${ORG_A_DISCORD_TOKEN}",
"ORG_B_DISCORD_TOKEN": "${ORG_B_DISCORD_TOKEN}"
}
}
}
}
Each project in ~/.discord-ops.json declares "token_env": "ORG_A_DISCORD_TOKEN" and discord-ops routes automatically. No default DISCORD_TOKEN needed when all projects have token_env set.
If all your projects share one bot, just pass that token:
{
"mcpServers": {
"discord-ops": {
"command": "npx",
"args": ["-y", "discord-ops@latest"],
"env": {
"DISCORD_TOKEN": "${DISCORD_TOKEN}"
}
}
}
}
If another tool already claims DISCORD_TOKEN, use DISCORD_OPS_TOKEN_ENV to point at a different name:
{
"mcpServers": {
"discord-ops": {
"command": "npx",
"args": ["-y", "discord-ops@latest"],
"env": {
"DISCORD_OPS_TOKEN_ENV": "MY_BOT_TOKEN",
"MY_BOT_TOKEN": "${MY_BOT_TOKEN}"
}
}
}
}
The killer feature: route messages by project name and channel alias instead of raw IDs.
~/.discord-ops.json){
"projects": {
"my-app": {
"guild_id": "123456789012345678",
"channels": {
"dev": "CHANNEL_ID",
"builds": "CHANNEL_ID",
"alerts": "CHANNEL_ID",
"releases": "CHANNEL_ID"
},
"default_channel": "dev"
}
},
"default_project": "my-app",
"notification_routing": {
"ci_build": "builds",
"deploy": "builds",
"release": "releases",
"error": "alerts",
"dev": "dev"
}
}
Projects can specify their own bot token via token_env:
{
"projects": {
"org-a": {
"guild_id": "111111111111111111",
"channels": { "dev": "CHANNEL_ID" },
"default_channel": "dev",
"token_env": "ORG_A_DISCORD_TOKEN"
},
"org-b": {
"guild_id": "222222222222222222",
"channels": { "dev": "CHANNEL_ID" },
"default_channel": "dev",
"token_env": "ORG_B_DISCORD_TOKEN"
}
}
}
When all projects have token_env, the default DISCORD_TOKEN is optional. Each project connects with its own bot.
Give bots names, roles, and per-channel assignment. This is ideal when your Discord server runs multiple bots with distinct personas (e.g., a community helper vs. a tech ops bot).
{
"bots": {
"claire": {
"name": "Claire",
"role": "Community helper",
"description": "Handles support and community channels",
"token_env": "CLAIRE_TOKEN",
"default_profile": "messaging"
},
"courier": {
"name": "Clarity Courier",
"role": "Technical operations",
"token_env": "COURIER_TOKEN",
"default_profile": "full"
}
},
"projects": {
"clarity-house": {
"guild_id": "123456789012345678",
"bot": "courier",
"channels": {
"general": "111111111111111111",
"support": { "id": "222222222222222222", "bot": "claire" },
"dev-ops": "333333333333333333",
"ai-testing": { "id": "444444444444444444", "bot": "claire" }
},
"default_channel": "dev-ops",
"tool_profile": "full"
}
}
}
How it works:
bots — named bot definitions with identity metadata and token_envproject.bot — default bot for the project (all channels use this bot unless overridden)bot override — individual channels can use a different bot: { "id": "...", "bot": "claire" }default_profile — per-bot tool profile (restricts which tools a bot can use at runtime)token_env → default DISCORD_TOKENbot: { name, role } metadata for agent contextbots is optional; channels accept both "ID" and { "id": "ID", "bot": "name" } formatsUse list_bots to see all configured bots, their project assignments, channel overrides, and connection status.
Configure project owners so that releases, errors, and alerts automatically prepend @mentions. This ensures the right people are always paged for critical events without hardcoding mentions in every message.
{
"projects": {
"my-app": {
"guild_id": "123456789012345678",
"channels": { "releases": "CHANNEL_ID", "alerts": "CHANNEL_ID" },
"owners": ["820027414902079548"],
"notify_owners_on": ["release", "error", "alert"]
}
}
}
notify_owners_on values: any notification type (release, error, alert, ci_build, deploy, etc.)
Safety: "dev" is hardcoded to never trigger owner pings regardless of config — dev noise stays quiet.
When a send_message or send_embed call uses a matching notification_type, the owner mentions are automatically prepended to the message. No other changes needed.
The channel param accepts a channel name or snowflake ID anywhere a channel is needed. Resolution happens in four layers:
"builds" hits the builds alias in your project config"build" or "blds" resolves to the closest alias"general" resolves even with no configured aliasThis means you can pass channel: "general" and it will work even for channels that aren't in your config. You can also pass a raw snowflake ID directly — channel: "1234567890" bypasses alias resolution entirely.
.discord-ops.json in repo root){
"project": "my-app",
"notification_routing": {
"ci_build": "builds",
"deploy": "builds"
}
}
# By project + channel alias
send_message({ project: "my-app", channel: "builds", content: "Build passed!" })
# By notification type (auto-routed to channel, owner pinged if configured)
send_message({ project: "my-app", notification_type: "release", content: "v1.0.0 shipped" })
# Direct channel ID (always works)
send_message({ channel_id: "123456789", content: "Hello" })
# Channel by name (live lookup — no alias needed)
send_message({ project: "my-app", channel: "general", content: "Hello" })
send_message automatically wraps messages in a polished embed with a color bar, description, and timestamp. Pass raw: true to send plain text instead.
# Branded embed (default)
send_message({ project: "my-app", channel: "dev", content: "Deploy complete" })
# Plain text
send_message({ project: "my-app", channel: "dev", content: "pong", raw: true })
send_embed fetches Open Graph metadata server-side from any URL and renders a rich preview embed. All OG fields can be overridden.
send_embed({
url: "https://www.npmjs.com/package/discord-ops/v/0.14.0",
project: "my-app",
channel: "releases",
title: "discord-ops v0.14.0",
description: "Owner pings, smart channel resolution, category editing",
color: 5763719,
footer: "Released April 3, 2026"
})
Useful for sharing GitHub PRs, npm releases, blog posts, or any URL with rich previews — the bot fetches the metadata so Discord's CDN doesn't cache-bust client-side unfurls.
| Tool | Description |
|---|---|
send_message |
Send a message with project routing (auto-embed by default) |
send_embed |
Fetch OG metadata from a URL and post a rich embed |
get_messages |
Fetch recent messages (supports ISO 8601 timestamps) |
edit_message |
Edit a bot message |
delete_message |
Delete a message |
add_reaction |
React to a message |
pin_message |
Pin a message in a channel |
unpin_message |
Unpin a message |
search_messages |
Search messages by content, author, or date range |
send_template |
Send a styled embed using a built-in template |
list_templates |
List available templates with required variables |
notify_owners |
Ping project owners based on notification type |
| Tool | Description |
|---|---|
list_channels |
List guild channels |
get_channel |
Get channel details |
create_channel |
Create a channel |
edit_channel |
Edit channel name, topic, category, or position (text, voice, and categories) |
delete_channel |
Delete a channel |
purge_messages |
Bulk-delete messages (max 100, < 14 days old) |
set_slowmode |
Set or disable slowmode |
move_channel |
Move a channel to a different category or position |
set_permissions |
Set channel permission overrides for a role or member |
| Tool | Description |
|---|---|
kick_member |
Kick a member from a guild |
ban_member |
Ban a user from a guild |
unban_member |
Unban a user |
timeout_member |
Timeout (mute) a member |
| Tool | Description |
|---|---|
list_roles |
List guild roles |
create_role |
Create a new role |
edit_role |
Edit role properties |
delete_role |
Delete a role |
assign_role |
Add or remove a role from a member |
| Tool | Description |
|---|---|
create_webhook |
Create a webhook on a channel |
get_webhook |
Get webhook details |
list_webhooks |
List webhooks for a guild or channel |
edit_webhook |
Edit webhook properties |
delete_webhook |
Delete a webhook |
execute_webhook |
Send a message via webhook |
| Tool | Description |
|---|---|
query_audit_log |
Query guild audit log with filters |
| Tool | Description |
|---|---|
list_guilds |
List bot's guilds |
get_guild |
Get guild details |
get_invites |
Get all active invites for a guild |
create_invite |
Create an invite link for a channel |
list_members |
List guild members |
get_member |
Get member details |
| Tool | Description |
|---|---|
create_thread |
Create a thread |
list_threads |
List active threads |
archive_thread |
Archive (and optionally lock) a thread |
| Tool | Description |
|---|---|
health_check |
Bot status, version, connected guilds, and permission audit |
list_projects |
List all projects with guild mappings, token status, and validation |
list_bots |
List all bot personas with project assignments and channel overrides |
Load only the tools an agent needs. Reduces schema token overhead by up to 85% for narrow use cases.
| Profile | Tools | Description |
|---|---|---|
full |
49 | All tools (default) |
monitoring |
7 | get_messages, send_message, add_reaction, create_thread, health_check, list_projects, list_bots |
readonly |
7 | get_messages, list_channels, list_members, get_guild, health_check, list_projects, list_bots |
moderation |
7 | get_messages, kick_member, ban_member, timeout_member, delete_message, purge_messages, query_audit_log |
messaging |
5 | add_reaction, delete_message, edit_message, get_messages, send_message |
channels |
7 | create_channel, delete_channel, edit_channel, get_channel, list_channels, purge_messages, set_slowmode |
webhooks |
6 | create_webhook, delete_webhook, edit_webhook, execute_webhook, get_webhook, list_webhooks |
# Via CLI flag
discord-ops --profile monitoring
# Load specific tools
discord-ops --tools "send_message,send_template,health_check"
# Combined (profile as base + add tools)
discord-ops --profile readonly --tools "send_message"
Profiles can be set per project in ~/.discord-ops.json so each agent gets only what it needs:
{
"projects": {
"my-app": {
"guild_id": "123456789012345678",
"channels": { "dev": "CHANNEL_ID", "alerts": "CHANNEL_ID" },
"tool_profile": "monitoring",
"tool_profile_add": ["send_message"],
"tool_profile_remove": ["list_members"]
}
}
}
tool_profile — base profile to use for this projecttool_profile_add — add tools not included in the base profiletool_profile_remove — remove tools from the base profilediscord-ops Start MCP server (stdio transport)
discord-ops serve Start MCP server (HTTP/SSE transport)
discord-ops run <tool> --args '{…}' Run any tool directly (no AI/MCP required)
discord-ops setup Interactive setup wizard (single + multi-bot)
discord-ops health Run health check + permission audit
discord-ops validate Validate config without connecting to Discord
discord-ops --profile Load a built-in tool profile (monitoring/readonly/moderation/full)
discord-ops --tools Load specific tools by name (comma-separated)
discord-ops --dry-run Simulate destructive operations
discord-ops --help Show help
discord-ops --version Show version
run — call any tool without an AI agentThe run subcommand executes any discord-ops tool directly from the shell — no MCP client, no AI. Pass all tool input as a single JSON string via --args.
# Send a plain message
npx discord-ops@latest run send_message \
--args '{"project":"my-app","channel":"general","content":"Deployment complete."}'
# Send a rich release announcement
npx discord-ops@latest run send_template \
--args '{
"project": "my-app",
"channel": "releases",
"template": "release",
"vars": {
"name": "my-app",
"version": "v1.2.0",
"author_name": "My Org",
"highlights": "• New feature A\n• Bug fix B",
"npm": "my-app@latest",
"npm_url": "https://www.npmjs.com/package/my-app",
"link": "https://github.com/my-org/my-app/releases/tag/v1.2.0",
"footer": "Published 2026-04-03"
}
}'
Any tool name accepted by the MCP server works here — send_message, send_template, send_embed, list_channels, etc. The same input schema applies; validation errors are printed with field paths and exit code 1.
| Variable | Required | Description |
|---|---|---|
DISCORD_TOKEN |
No* | Default Discord bot token (*required unless all projects have token_env) |
DISCORD_OPS_TOKEN_ENV |
No | Override which env var holds the default token (default: DISCORD_TOKEN) |
<PROJECT>_TOKEN |
No | Per-project bot tokens (configured via token_env in project config) |
DISCORD_OPS_CONFIG |
No | Path to global config file, or inline JSON string (default: ~/.discord-ops.json) |
DISCORD_OPS_LOG_LEVEL |
No | debug, info, warn, error (default: info) |
DISCORD_OPS_DRY_RUN |
No | Enable dry-run mode (any truthy value) |
DRY_RUN |
No | Enable dry-run mode (any truthy value, alias) |
DISCORD_OPS_HTTP_TOKEN |
No | Bearer token for HTTP transport authentication (strongly recommended) |
bot override, use that bot's token_envbot, use that bot's token_envtoken_env — project's own token env varDISCORD_TOKEN (or custom via DISCORD_OPS_TOKEN_ENV)If DISCORD_OPS_TOKEN_ENV is set, its value names the env var holding the default token (e.g., DISCORD_OPS_TOKEN_ENV=MY_BOT_TOKEN reads MY_BOT_TOKEN). If all projects have token_env or bot set, no default token is needed.
Use discord-ops run in GitHub Actions (or any CI) to post rich Discord notifications after a publish, deploy, or build — no AI agent required.
In CI you typically have one bot token and one project. Pass a minimal config as an inline JSON string via DISCORD_OPS_CONFIG. No file writing needed.
When storing as a GitHub secret, minify to a single line — multiline strings break secret injection. The shape (pretty-printed for readability):
{
"projects": {
"my-app": {
"guild_id": "123456789012345678",
"channels": {
"releases": "987654321098765432",
"builds": "111222333444555666"
},
"default_channel": "releases"
}
},
"default_project": "my-app"
}
token_env needed — omitting it means the project uses DISCORD_TOKEN (the default).owners and notify_owners_on are optional — include them if you want owner pings on errors.Store two secrets in your repo:
BOOKED_DISCORD_BOT_TOKEN — your bot tokenDISCORD_OPS_CONFIG — the config JSON minified to a single line (multiline strings break GitHub secrets){"projects":{"my-app":{"guild_id":"123456789012345678","channels":{"releases":"987654321098765432"},"default_channel":"releases"}},"default_project":"my-app"}
- name: Notify Discord
run: |
npx discord-ops@latest run send_template --args '{
"project": "my-app",
"channel": "releases",
"template": "release",
"vars": {
"name": "my-app",
"version": "${{ steps.version.outputs.version }}",
"author_name": "My Org",
"highlights": "${{ steps.changelog.outputs.highlights }}",
"npm": "my-app@latest",
"npm_url": "https://www.npmjs.com/package/my-app",
"link": "${{ steps.release.outputs.url }}",
"footer": "Published ${{ steps.date.outputs.date }}"
}
}'
env:
DISCORD_TOKEN: ${{ secrets.BOOKED_DISCORD_BOT_TOKEN }}
DISCORD_OPS_CONFIG: ${{ secrets.DISCORD_OPS_CONFIG }}
DISCORD_TOKEN is the default token variable — no additional configuration needed. The bot token from your secret is used directly.
When running discord-ops serve, the HTTP endpoint is unauthenticated by default with a loud startup warning. Set DISCORD_OPS_HTTP_TOKEN to require bearer auth:
DISCORD_OPS_HTTP_TOKEN=your-secret-token discord-ops serve --port 3000
All requests must include:
Authorization: Bearer your-secret-token
The health endpoint (GET /health) is always exempt from auth — load balancers and Docker healthchecks can reach it without a token.
Token comparison uses constant-time comparison to prevent timing attacks.
Enable dry-run to simulate destructive operations (delete, ban, kick, etc.) without actually calling the Discord API:
# Via CLI flag
discord-ops --dry-run
# Via environment variable
DISCORD_OPS_DRY_RUN=1 discord-ops
# Via env alias
DRY_RUN=true discord-ops
In dry-run mode, destructive tools return a simulated success response showing what would have happened.
23 built-in templates with cutting-edge Discord features. Use send_template with project routing.
Features across all templates:
author_name + author_icon at the top| Template | Description | Key Features |
|---|---|---|
release |
Version release with install + link buttons | Author, link buttons, clickable title |
deploy |
Deploy success/failure with logs button | Footer icon, view/logs buttons |
ci_build |
CI result with build link button | Footer icon, clickable title |
incident |
Incident alert with severity colors | Discord timestamps, status page button |
incident_resolved |
Resolution with postmortem button | Discord timestamps, postmortem link |
maintenance |
Maintenance with live timezone countdowns | Discord timestamps, countdown, status button |
status_update |
Service status (operational/degraded/outage) | Footer icon, dashboard button |
review |
PR review with diff stats + PR button | Clickable title, additions/deletions |
dashboard |
Multi-embed service status board (up to 9 svc) | Multi-embed, per-service color cards |
oncall |
On-call handoff with shift timestamps | Discord timestamps, runbook button |
alert |
Configurable alert (info/warn/error/critical) | Level-based colors, metric thresholds |
| Template | Description | Key Features |
|---|---|---|
celebration |
Celebrate wins with images | Author, thumbnail, image |
welcome |
Welcome members with onboarding buttons | Discord timestamps, handbook/onboarding links |
shoutout |
Recognize work with avatar thumbnail | Thumbnail, nomination attribution |
quote |
Block-quoted inspirational text | Block quote formatting, author avatar |
announcement |
Announcement with deadline countdown | Discord timestamps, countdown, link button |
changelog |
Changelog with 7 section types | Deprecated, performance, security sections |
milestone |
Milestone with target date countdown | Discord timestamps, progress tracking |
tip |
Pro tip with syntax-highlighted code | Language-specific code blocks, doc button |
poll |
Native Discord poll with vote tracking | Native poll API, multiselect, duration |
progress |
Visual progress bar with deadline | Unicode progress bar, countdown |
standup |
Daily standup summary | Yesterday/today/blockers sections |
retro |
Sprint retrospective | Went-well/improve/actions, velocity |
Release announcement:
send_template({
template: "release",
vars: {
version: "v0.14.0",
name: "discord-ops",
highlights: "• Owner pings\n• Smart channel resolution\n• Category channel editing",
npm: "npm install [email protected]",
npm_url: "https://www.npmjs.com/package/discord-ops/v/0.14.0",
link: "https://github.com/bookedsolidtech/discord-ops/pull/20",
footer: "Released April 3, 2026",
author_name: "Booked Solid Technology"
},
project: "my-app",
channel: "releases"
})
Native Discord Poll:
send_template({
template: "poll",
vars: {
question: "Best language for MCP servers?",
options: "TypeScript|Rust|Go|Python",
duration: "48",
multiselect: "true"
},
project: "my-app",
channel: "dev"
})
Multi-Embed Status Dashboard:
send_template({
template: "dashboard",
vars: {
services: "API|Database|CDN|Auth|Queue",
statuses: "operational|operational|degraded|operational|outage",
title: "Production Status",
url: "https://status.example.com"
},
project: "my-app",
channel: "alerts"
})
On-call handoff:
send_template({
template: "oncall",
vars: {
outgoing: "alice",
incoming: "bob",
shift_start: "2026-04-04T09:00:00Z",
notes: "Payment service latency elevated — watch grafana/d/payments",
active_incidents: "INC-342: elevated error rate on /checkout",
runbook_url: "https://wiki.example.com/oncall",
mention: "<@BOB_USER_ID>"
},
project: "my-app",
channel: "team-chat"
})
All templates support project routing (project, channel, notification_type, channel_id) and author branding (author_name, author_icon).
Full ~/.discord-ops.json schema with all options:
{
"bots": {
"my-bot": {
"name": "My Bot",
"role": "General purpose",
"description": "Handles all operations",
"token_env": "MY_BOT_TOKEN",
"default_profile": "full"
}
},
"projects": {
"my-app": {
"guild_id": "123456789012345678",
"token_env": "MY_APP_DISCORD_TOKEN",
"bot": "my-bot",
"channels": {
"dev": "CHANNEL_ID",
"builds": "CHANNEL_ID",
"releases": "CHANNEL_ID",
"alerts": "CHANNEL_ID",
"support": { "id": "CHANNEL_ID", "bot": "my-bot" }
},
"default_channel": "dev",
"owners": ["USER_SNOWFLAKE_ID"],
"notify_owners_on": ["release", "error", "alert"],
"tool_profile": "full",
"profile_add": [],
"profile_remove": [],
"notification_routing": {
"ci_build": "builds",
"deploy": "builds",
"release": "releases",
"error": "alerts"
}
}
},
"default_project": "my-app",
"notification_routing": {
"ci_build": "builds",
"deploy": "builds",
"release": "releases",
"error": "alerts",
"dev": "dev"
}
}
Global fields:
| Field | Description |
|---|---|
bots |
Named bot personas with name, role, description, token_env, default_profile |
default_project |
Project used when no project param is provided |
notification_routing |
Global notification type → channel alias routing |
Project fields:
| Field | Description |
|---|---|
guild_id |
Discord server (guild) snowflake ID |
token_env |
Env var name for this project's bot token |
bot |
Default bot persona for this project (references a key in bots) |
channels |
Alias → channel ID or { id, bot } map; channel: "builds" resolves here first |
default_channel |
Channel used when no channel param is provided |
owners |
User snowflake IDs to mention on matching notification types |
notify_owners_on |
Notification types that trigger owner pings ("dev" never pings) |
tool_profile |
Base tool profile for this project (full, monitoring, etc.) — enforced at runtime |
profile_add |
Additional tools to load on top of the base profile |
profile_remove |
Tools to exclude from the base profile |
notification_routing |
Per-project override of global notification → channel routing |
Per-project profiles are enforced at runtime — all tools stay registered on the MCP server, but tool calls are filtered when the resolved project or bot has a profile set. This means agents can discover all tools via MCP schema, but per-project restrictions are applied on each call.
Run discord-ops validate to check your config without connecting to Discord. It detects:
token_env values (env var not set)project.bot, channel bot) pointing to undefined botsdefault_profile or tool_profile valuestoken_env environment variablesdefault_channel referencing a nonexistent aliasdefault_project pointing to a nonexistent project"No token available for project X" The project needs a token. Either:
token_env env var (e.g., export ORG_A_TOKEN=...)DISCORD_TOKENDISCORD_OPS_TOKEN_ENV to point at a custom env varBot can't access a guild
If a project uses token_env for a different bot, that bot must be invited to the project's guild. Run discord-ops health to see which guilds each bot can access.
Migrating from single-bot to multi-bot
token_env to projects that need their own botdiscord-ops validate to verifydiscord-ops health to test connectionsToken rotation
Update the env var value and restart the MCP server. No config changes needed — token_env reads from the environment at runtime.
Channel not found
Channel resolution tries 4 layers in order: exact alias → fuzzy alias → live Discord name lookup → error. If a channel is still not found, verify the bot has access to the channel and list_channels returns it.
git clone https://github.com/bookedsolidtech/discord-ops.git
cd discord-ops
npm install
npm run build
npm test
# Local CI
./scripts/act-ci.sh --local
MIT
Выполни в терминале:
claude mcp add discord-ops -- npx Безопасность
Низкий рискАвтоматическая эвристика по публичным данным — не гарантия безопасности.