discourse-mcp/AGENTS.md
Sam d2c737de9d
FEATURE: add support for topic editing (#37)
* FEATURE: add support for topic editing

- supports tagging/categorising/changing title on an existing topic
- added linting

* version bump

* avoid uses of any where possible

no new features just consistency / maintainability

* - simpler agents md
- improved docs
- better parsing for auth pairs
- clear write access checks
- better testing of tool lists
2026-01-20 18:13:10 +11:00

2.9 KiB

AGENTS.md — Discourse MCP

MCP server exposing Discourse forum capabilities as tools/resources for AI agents. Entry: src/index.tsdist/index.js (binary: discourse-mcp). Node >= 24.

SDLC Commands

pnpm build       # Compile TypeScript to dist/
pnpm typecheck   # Type-check only (no emit)
pnpm lint        # Run ESLint on src/
pnpm test        # Run tests (requires build first)
pnpm clean       # Remove dist/

Source Map

Area Files
Entry/CLI src/index.ts
HTTP client src/http/client.ts
Tool registry src/tools/registry.ts
Resource registry src/resources/registry.ts
Built-in tools src/tools/builtin/*
Remote tools src/tools/remote/tool_exec_api.ts
Utilities src/util/*.ts (logger, redact, json_response)

Key Patterns

Tool Implementation

  • Tools live in src/tools/builtin/ as individual files
  • Each tool exports a registration function called by src/tools/registry.ts
  • All tools return strict JSON (no Markdown) with isError: true on failure
  • Write tools require --allow_writes flag and matching auth_pairs entry

Resources

  • URI-addressable read-only data (categories, tags, groups, channels, drafts)
  • Registered in src/resources/registry.ts

HTTP Layer

  • Client in src/http/client.ts handles auth, retries (429/5xx), caching
  • User-Agent: Discourse-MCP/0.x
  • Write tools enforce ~1 req/sec rate limit

Configuration

  • CLI flags validated via Zod in src/index.ts
  • Auth via --auth_pairs JSON (API keys or User API keys)
  • --site <url> tethers to single site, hides discourse_select_site tool

Testing

  • Tests in src/test/ use Node's built-in test runner
  • Build before running tests: pnpm build && pnpm test

Adding a New Tool

  1. Create src/tools/builtin/<name>.ts
  2. Export a RegisterFn function
  3. Import and call it in src/tools/registry.ts

Minimal template:

import { z } from "zod";
import type { RegisterFn } from "../types.js";
import { jsonResponse, jsonError } from "../../util/json_response.js";

export const registerMyTool: RegisterFn = (server, ctx, opts) => {
  if (!opts.allowWrites) return; // omit for read-only tools

  server.registerTool(
    "discourse_my_tool",
    {
      title: "My Tool",
      description: "Does X. Returns JSON with Y.",
      inputSchema: z.object({ id: z.number() }).shape,
    },
    async (args) => {
      const { client } = ctx.siteState.ensureSelectedSite();
      try {
        const data = await client.get(`/endpoint.json`);
        return jsonResponse(data);
      } catch (e: any) {
        return jsonError(`Failed: ${e?.message}`);
      }
    }
  );
};

Key helpers:

  • jsonResponse(data) — success response
  • jsonError(msg) — error with isError: true
  • paginatedResponse(name, items, meta) — for lists
  • rateLimit(key) — throttle writes (call before mutations)
  • ctx.siteState.ensureSelectedSite() — get { base, client }