Skip to content

Releases: bookedsolidtech/discord-ops

v0.25.0

Choose a tag to compare

@himerus himerus released this 13 Jul 01:37
be3ed83

Minor Changes

  • 5e85094: discord-ops setup now writes .mcp.json and configures the coordination board.
    • The wizard offers to write (or merge into) a .mcp.json in the current
      directory, so Claude Code loads discord-ops for the project with one command
      — no hand-editing. It references the project's token env var by name (never a
      raw token) and preserves any other MCP servers already configured.
    • Each project can pick a coordination note-board channel during setup; the
      wizard shows the channel the smart fallback resolves to and only writes an
      explicit board_channel when you override it.

v0.24.0

Choose a tag to compare

@himerus himerus released this 12 Jul 23:31
957556d

Minor Changes

  • 8a589a6: Add read-side primitives for bi-directional agent-to-agent communication over Discord.

    • get_message — fetch a single message by ID with reply linkage (reply_to), pin state, edit timestamp, thread info (has_thread/thread_id), and the author's bot flag, so an agent can re-check a message it posted earlier.
    • get_reactions — read who reacted to a message and with what emoji (with per-user bot flags), so an agent can detect acks, claims, and blocks left by humans or peer agents. Supports an emoji filter and a per-emoji user limit.
    • get_replies — collect direct replies to a message by scanning messages posted after it, with scanned/last_scanned_id pagination fields and an after resume cursor.
    • get_messages now includes reply_to on every returned message so reply chains are visible in bulk reads.
    • send_message now returns message_id (alongside the existing id) so agents can capture it and poll for responses later.
    • The new read tools are included in the monitoring, readonly, and messaging tool profiles.
  • ad0831a: Coordination platform expansion: four new tool suites (15 tools, 67 total).

    • Personas — one bot, unlimited posting identities via per-message webhook
      overrides: create_persona, send_as, list_personas. No new bot
      applications, no developer-portal work; webhook tokens never appear in
      results.
    • Polls — native Discord polls as structured consensus: send_poll,
      get_poll_results (per-answer voter lists with bot flags and pagination),
      end_poll (idempotent, destructive-flagged).
    • Workflowforward_message (immutable cross-channel snapshots for
      escalation) and forum channels as agent work queues: create_forum_post,
      list_forum_posts, update_forum_post (tags by name as status labels,
      archive to close).
    • Botops — bot self-management without the developer portal:
      set_bot_nick, update_application (description, SSRF-guarded icon
      upload, tags, install params), and application emoji CRUD returning
      add_reaction-ready identifiers.
    • Profiles: monitoring gains send_as/send_poll/get_poll_results;
      readonly gains the new read tools; messaging gains
      send_as/forward_message.
  • e943136: Real-time event sidecar and security hardening for the coordination suites.

    • Gateway sidecardiscord-ops listen opens a gateway connection per bot
      token and streams message_create/reaction_add events to a local JSONL
      sink; the new get_events tool reads that sink with a last_seq cursor
      (mirroring get_replies) and zero Discord API calls per poll, reporting
      sink_active so agents fall back to get_messages when the sidecar is down.
      The sink is created 0600 (dir 0700), refuses symlinked or traversal
      paths, and writes one JSON.stringify object per line.
    • Botopsinteractions_endpoint_url is removed from update_application
      (a control-plane field an agent must never be able to redirect); the tool now
      documents that its edits are application-global.
    • Personas — reserved authority names (system, admin, moderator,
      owner, …) are blocked, with zero-width/obfuscation normalization, to blunt
      impersonation.
    • Sanitizer — the webhook-URL redaction now covers discordapp.com,
      canary/ptb subdomains, and version-prefixed API paths, and returned (not just
      thrown) error results are sanitized before they reach the audit log.
  • a74fd13: Project note board — directed, durable note-passing across concurrent sessions.

    • leave_note posts a directed note to a project's shared board channel,
      addressed to a session id, a role/name, or all, with tags for filtering.
    • get_notes reads the board with recipient/sender/tag/unresolved filters
      and an after cursor — the first call an agent makes on startup to pick up
      hand-offs and see what other sessions have done.
    • resolve_note marks a note handled (✅) with an optional reply, so open
      hand-offs drop off the unresolved list.
    • list_sessions reports which sessions are active on a project (derived
      from note activity), so concurrent sessions on the same codebase can
      coordinate instead of colliding.
    • New board_channel project config field selects the board, with a fallback
      chain (board/agent-board alias → agent-logsbackchannel
      default_channel). Session identity comes from DISCORD_OPS_SESSION or an
      auto-derived id. The note tools are included in the monitoring profile.
    • New docs/project-onboarding.md walks a project through adopting the full
      system.

Patch Changes

  • 5f4cdcc: Fix validateConfig() treating missing token_env as fatal error in multi-org setups

    When a global ~/.discord-ops.json contains projects from multiple organizations, the server
    previously failed to start if any project had a missing token_env — even if that project
    belonged to a completely different org irrelevant to the current context.

    loadConfig() now warns about unavailable projects and starts successfully as long as at
    least one project has a valid token. Only if all projects lack tokens does startup fail.

    validateConfig() likewise downgrades per-project missing token_env from errors to warnings,
    since the server can still serve other projects.

v0.23.3

Choose a tag to compare

@himerus himerus released this 20 May 00:57
78df563

Patch Changes

  • 4faf83d: fix(release): pin npm to 11.5.1 for OIDC trusted-publishing auth

    The previous corepack-based install activated npm 10.9.7 (corepack's
    npm@latest alias is stale), which supports --provenance for sigstore
    attestation but lacks native trusted-publishing OIDC auth. The publish
    PUT to the registry therefore went out unauthenticated and was rejected
    with a misleading E404. Pinning to npm 11.5.1 ensures both provenance
    signing and TP auth function correctly.

v0.23.0

Choose a tag to compare

@himerus himerus released this 11 Apr 23:35
d07f860

Minor Changes

  • bbc870b: Multi-bot architecture: bot personas, per-channel bot assignment, and per-project tool profile enforcement.

    Bot personas: Named bots with identity metadata (name, role, description) configured in a top-level bots section. Each bot references a token_env and can have a default_profile restricting which tools it can use.

    Channel-level bot assignment: Channels accept { "id": "...", "bot": "bot-name" } to override which bot operates in that channel. Token resolution follows: channel bot → project bot → project token_env → default token.

    Per-project tool profile enforcement: Runtime gate in the MCP server checks per-project tool_profile and per-bot default_profile on every tool call. Tools not in the effective profile return an error. Supports profile_add/profile_remove overrides.

    New tool: list_bots — returns all configured bot personas with project assignments, channel overrides, and connection status. Does not expose token values.

    Validation: discord-ops validate now checks bot references, profile names, and bot token availability.

    Backwards compatible — existing configs without bots work unchanged. Channels accept both plain snowflake strings and { id, bot } objects.

v0.22.0

Choose a tag to compare

@himerus himerus released this 11 Apr 18:09
03d981c

Minor Changes

  • a7f7218: Engineering audit remediation: 32 findings fixed across 5 epics.

    Breaking: get_messages now returns full embed and attachment objects instead of counts. embeds changes from number to array, attachments from number to array. Update consumers checking embeds > 0 to embeds.length > 0.

    New tools: send_template, list_templates, pin_message, unpin_message, notify_owners, get_invites (42 → 48 tools).

    CLI: setup, run, validate subcommands now wired. Flags --allow-unauthenticated, --profile, --tools, --dry-run, --args accepted. Version reads from package.json dynamically.

    Bug fixes: list_threads respects archived param. timeout_member marked destructive. resolveTarget returns undefined instead of "" for missing guild. Permission pre-flight logs errors.

    Security: SSRF DNS pinning prevents rebinding. Template URL vars validated. X-Forwarded-For parsed right-to-left. Per-project rate limit buckets. Extended reserved IP blocking. Token hashing for cache keys. IP counter hard cap.

    Code quality: Dead code removed. TTLCache max-size eviction. Profile tool name validation at startup. Rate limiter bucket pruning.

v0.21.2

Choose a tag to compare

@himerus himerus released this 11 Apr 02:21
6efd7a8

Patch Changes

  • 58be846: Enforce snowflakeId schema on all Snowflake ID parameters (channel_id, guild_id, author_id) in search_messages and send_embed tools. Previously these used bare z.string() which lacked the ^\d{17,20}$ pattern validation, causing callers that pass 19-digit integer IDs to hit type coercion errors.

v0.21.1

Choose a tag to compare

@himerus himerus released this 06 Apr 21:40
e8d68ca

Patch Changes

  • e34f143: Add messaging, channels, and webhooks tool profiles; consolidate duplicate filterTools implementation; improve HTTP transport branch coverage (70.45% → 88.88%)

v0.21.0

Choose a tag to compare

@himerus himerus released this 06 Apr 14:38
204dd74

Minor Changes

  • b1d687e: Add discord-ops init CLI subcommand for non-interactive scaffolding of per-project .discord-ops.json config files. Accepts --project, --guild-id, --token-env, --channel, --force, and --default flags. Runs without a Discord connection.
  • b1d687e: Add max_pages parameter to search_messages (1–5, default 1). When set above 1, the tool paginates through results using the before cursor and returns up to max_pages × 100 messages. Response now includes has_more: boolean to indicate further pages exist.
  • b1d687e: Add initial_message parameter to create_thread. When provided, the message is posted into the thread immediately after creation, eliminating the need for a follow-up send_message call.

Patch Changes

  • f5441f0: Fix audit log redaction to recurse into arrays of objects. Previously, sensitive keys inside array elements (e.g. embed fields with a token or webhook_url key) passed through unredacted.
  • 774d97b: Restrict CORS Access-Control-Allow-Origin from wildcard * to http://localhost by default. The HTTP transport now accepts an allowedOrigin option (and --allowed-origin CLI flag) to configure the allowed origin explicitly, preventing arbitrary web pages from fingerprinting the /health endpoint or establishing unauthenticated SSE connections.
  • 3e7faab: Make guild_id optional in execute_webhook. The parameter was declared required but never used in the handler body. Callers that omit it no longer receive a validation error, while existing callers that provide it continue to work unchanged.
  • b1d687e: Enforce auth token requirement on HTTP serve mode startup. The server now refuses to start without DISCORD_OPS_HTTP_TOKEN unless --allow-unauthenticated is explicitly passed, preventing accidental unauthenticated exposure of the bot API.
  • bcc2627: Add trustProxy option to HTTP transport for proxy-aware per-IP rate limiting. When enabled, extracts the real client IP from the leftmost non-private address in X-Forwarded-For instead of using req.socket.remoteAddress. Defaults to false so existing behavior is unchanged.
  • eca9978: Add standard security response headers to HTTP transport. All non-OPTIONS responses now include X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy: default-src 'none', and Referrer-Policy: no-referrer. OPTIONS preflight responses are intentionally excluded.
  • 3b82f09: Fix SSRF vulnerability in og-fetch: resolve hostname via DNS before fetching and re-validate the resolved IP against the blocklist to prevent DNS rebinding attacks. Also adds 100.64.0.0/10 (shared address space) and 198.18.0.0/15 (benchmarking) to the blocked ranges.
  • c27e2f4: Validate embed image and URL fields against private/reserved IP ranges before passing to Discord API. Caller-supplied image_url in send_embed and all URL fields in execute_webhook embeds (url, image.url, thumbnail.url, author.url, author.icon_url, avatar_url) are now checked with isPublicHttpUrl() to prevent SSRF via Discord's CDN proxy.

v0.20.2

Choose a tag to compare

@himerus himerus released this 03 Apr 22:55
b60f27d

Patch Changes

  • 09596d6: Fix port range validation, rate-limiter stats aggregation, and invite channel consistency
    • CLI: --port now rejects out-of-range values (negative, zero, >65535) with a clear message; previously only NaN and falsy values were caught
    • RateLimiter.stats(): returns the max-used bucket instead of the sum across all buckets, making used/limit a meaningful per-bucket pressure ratio rather than a misleading aggregate
    • create_invite: switched from getChannel (text-only) to getAnyChannel so voice and stage channels are now supported; aligns with the server-layer permission pre-check which already used getAnyChannel
    • SSRF: block 0.0.0.0 (unspecified IPv4, routes to localhost on many systems) and :: (IPv6 unspecified address) in OG metadata fetcher

v0.20.1

Choose a tag to compare

@himerus himerus released this 03 Apr 21:29
9174c38

Patch Changes

  • 5f65f23: Security hardening and type safety improvements (v0.20.0 audit follow-up)

    SSRF protection (og-fetch)

    • Block HTTP redirect following — redirect: "manual" prevents redirects to private IPs
    • Full 127.0.0.0/8 loopback range blocked (was only 127.0.0.1)
    • IPv4-mapped IPv6 addresses (::ffff:x.x.x.x) now blocked, handling both dotted-decimal and hex-normalized URL parser forms
    • OG regex patterns pre-compiled at module load instead of per-call

    Type safety

    • All 48 tool definitions migrated to defineTool<T>() factory — handle input parameters are now strongly typed via z.infer<TSchema>
    • Fixed 4 latent type bugs exposed by stricter typing: notification_type fields now use NotificationType enum; role color correctly cast to ColorResolvable

    Config resilience

    • loadGlobalConfig() now throws on corrupt/invalid config files instead of silently returning empty config

    HTTP transport

    • ipCounters map pruned every 60s to prevent unbounded memory growth from unique IPs

    Test coverage

    • New server-perm-check.test.ts: 6 tests covering the perm pre-flight block in server.ts
    • TOKEN_ENV format validation tests (8 cases)
    • Audit redaction assertion fixed — now verifies [REDACTED] appears in log output
    • 10 new og-fetch tests: redirect blocking, 127.x.x.x range, IPv4-mapped IPv6, ::1