Files
Space-Banane bc42508849
CI / Build & Test (push) Successful in 17s
feat: add polls, deep-dive, ticket messages, and mod API key tools
- New polls.ts: 13 tools covering full poll lifecycle (create/list/get/
  update/delete/vote/like/dislike/review) and poll comments
- news.ts: get_deep_dive and regenerate_deep_dive for AI analysis
- tickets.ts: create_ticket_message with internal-note and attachment support
- moderation.ts: list/update/revoke mod-managed user API keys
- user.ts: list_my_polls and list_my_poll_votes
- Bump server version to 1.2.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 22:31:48 +02:00

11 KiB

CLAUDE.md — BetterNews MCP Server

Stdio MCP server (@modelcontextprotocol/sdk) that exposes the BetterNews API as tools. Auth: BETTERNEWS_API_KEY env var, sent as Authorization: Bearer on every request.


Source Files

File Purpose
src/index.ts Entry point. Imports all register functions and calls them against server and client.
src/client.ts BetterNewsClientget/post/patch/delete wrappers with auth header and error handling.
src/utils.ts handleTool(fn) — wraps a handler, catches errors, returns { content: [{ type:"text", text }] }.
src/tools/news.ts 24 news tools
src/tools/comments.ts 6 comment tools
src/tools/sources.ts 7 source tools
src/tools/user.ts 9 user/profile tools
src/tools/moderation.ts 14 moderation tools
src/tools/tickets.ts 6 support ticket tools
src/tools/blog.ts 7 blog tools
src/tools/api-keys.ts 4 API key tools
src/tools/sessions.ts 3 session tools
src/tools/discussions.ts 13 discussion channel tools
src/tools/polls.ts 13 poll tools

Complete Tool Index

Format: tool_name → file → METHOD /api/route → minimum auth

News — tools/news.ts

Tool Route Auth
get_top_news GET /api/news/top public
list_news GET /api/news optional
get_news_item GET /api/news/{id} optional
search_news GET /api/news/search optional
get_similar_news GET /api/news/{id}/similar optional
list_topics GET /api/news/topics public
get_news_item_stats GET /api/news/{id}/stats owner or Mod/Admin
check_duplicates GET /api/news/{id}/check-duplicates news:moderate
create_news_item POST /api/news news:write
update_news_item PATCH /api/news/{id} news:write
delete_news_item DELETE /api/news/{id} owner or Admin
submit_news_item POST /api/news/{id}/submit news:write (owner)
review_news_item POST /api/news/{id}/review news:moderate
like_news_item POST /api/news/{id}/like news:write
dislike_news_item POST /api/news/{id}/dislike news:write
bookmark_news_item POST /api/news/{id}/bookmark bookmarks:write
publish_news_item POST /api/news/{id}/publish news:moderate
unpublish_news_item POST /api/news/{id}/unpublish news:moderate
republish_news_item POST /api/news/{id}/republish news:moderate
archive_news_item POST /api/news/{id}/archive news:moderate (owner)
direct_publish_news_item POST /api/news/{id}/direct-publish news:moderate
direct_create_publish_news_item POST /api/news/direct news:moderate
get_deep_dive GET /api/news/{id}/deep-dive optional
regenerate_deep_dive POST /api/news/{id}/deep-dive/regenerate news:moderate Mod/Admin

Comments — tools/comments.ts

Tool Route Auth
list_comments GET /api/news/{id}/comments optional; sort: top/most_disliked/new/oldest
create_comment POST /api/news/{id}/comments news:comment + email verified
delete_comment DELETE /api/news/{id}/comments/{commentId} owner or news:comment Mod/Admin
like_comment POST /api/news/{id}/comments/{commentId}/like news:comment
dislike_comment POST /api/news/{id}/comments/{commentId}/dislike news:comment
hide_comment PATCH /api/news/{id}/comments/{commentId} news:moderate Mod/Admin

Sources — tools/sources.ts

Tool Route Auth
list_sources GET /api/sources sources:read
get_source GET /api/sources/{id} sources:read
create_source POST /api/sources sources:write Mod/Admin
update_source PATCH /api/sources/{id} sources:write Mod/Admin
list_source_submissions GET /api/news/{id}/sources news:read
submit_source POST /api/news/{id}/sources news:write
review_source_submission POST /api/news/{id}/sources/{submissionId}/review news:moderate

User — tools/user.ts

Tool Route Auth
get_current_user GET /api/user/whoami user:profile
get_user_profile GET /api/users/{username} public
list_my_news GET /api/user/news user:profile
list_my_source_submissions GET /api/user/source-submissions user:profile
list_bookmarks GET /api/user/bookmarks bookmarks:write
update_profile PATCH /api/user/profile user:profile
update_privacy_settings PATCH /api/user/privacy user:profile
list_my_polls GET /api/user/polls user:profile
list_my_poll_votes GET /api/user/poll-votes user:profile

Moderation — tools/moderation.ts

Tool Route Auth
get_mod_queue GET /api/mod/queue mod:queue Mod/Admin
get_mod_stats GET /api/mod/stats mod:stats Mod/Admin
list_mod_users GET /api/mod/users mod:users Admin
get_mod_user GET /api/mod/users/{userId} mod:users Admin
change_user_role PATCH /api/mod/users/{userId}/role mod:users Admin
ban_user POST /api/mod/users/{userId}/ban mod:users Admin
unban_user DELETE /api/mod/users/{userId}/ban mod:users Admin
shadowban_user PATCH /api/mod/users/{userId}/shadowban mod:users Admin
create_mod_user POST /api/mod/users mod:users Admin
list_all_tickets GET /api/mod/tickets mod:queue Mod/Admin
list_mod_comments GET /api/mod/comments mod:queue Mod/Admin
list_mod_user_api_keys GET /api/mod/users/{userId}/api-keys mod:users Admin
update_mod_user_api_key PATCH /api/mod/users/{userId}/api-keys/{keyId} mod:users Admin
revoke_mod_user_api_key DELETE /api/mod/users/{userId}/api-keys/{keyId} mod:users Admin

Tickets — tools/tickets.ts

Tool Route Auth
list_my_tickets GET /api/tickets tickets:read
get_ticket GET /api/tickets/{id} tickets:read owner or Mod/Admin
create_ticket POST /api/tickets tickets:write
reply_to_ticket POST /api/tickets/{id}/reply tickets:write
create_ticket_message POST /api/tickets/{id}/messages tickets:write / tickets:moderate
update_ticket_status PATCH /api/tickets/{id}/status tickets:moderate Mod/Admin

Blog — tools/blog.ts

Tool Route Auth
list_blog_posts GET /api/blog optional; Mod/Admin see drafts
get_blog_post GET /api/blog/{slug} optional; Mod/Admin see drafts
create_blog_post POST /api/blog blog:write Mod/Admin
update_blog_post PATCH /api/blog/{id} blog:write Mod/Admin
delete_blog_post DELETE /api/blog/{id} blog:write Mod/Admin
publish_blog_post POST /api/blog/{id}/publish blog:write Mod/Admin
unpublish_blog_post POST /api/blog/{id}/unpublish blog:write Mod/Admin

API Keys — tools/api-keys.ts

Tool Route Auth
list_api_keys GET /api/user/api-keys user:apikeys
create_api_key POST /api/user/api-keys cookie session only
update_api_key PATCH /api/user/api-keys/{keyId} user:apikeys
revoke_api_key DELETE /api/user/api-keys/{keyId} user:apikeys

Sessions — tools/sessions.ts

Tool Route Auth
list_sessions GET /api/user/sessions cookie session only
revoke_all_sessions DELETE /api/user/sessions cookie session only
revoke_session DELETE /api/user/sessions/{sessionId} cookie session only

Discussions — tools/discussions.ts

Tool Route Auth
list_discussions GET /api/discussions optional; Mod/Admin see all statuses
propose_discussion POST /api/discussions User+ (3/hour rate limit)
get_discussion GET /api/discussions/{id} optional; Mod/Admin see pending/rejected
update_discussion PATCH /api/discussions/{id} Mod/Admin
delete_discussion DELETE /api/discussions/{id} Admin
list_discussion_messages GET /api/discussions/{id}/messages optional; cursor via before ISO timestamp
delete_discussion_message DELETE /api/discussions/{id}/messages/{messageId} owner or Mod/Admin
pin_discussion_message POST /api/discussions/{id}/messages/{messageId}/pin Mod/Admin
list_discussion_bans GET /api/discussions/{id}/bans Mod/Admin
ban_discussion_user POST /api/discussions/{id}/bans Mod/Admin
unban_discussion_user DELETE /api/discussions/{id}/bans/{userId} Mod/Admin
list_mod_discussions GET /api/mod/discussions Mod/Admin
review_discussion POST /api/mod/discussions/{id}/review Mod/Admin

Polls — tools/polls.ts

Tool Route Auth
list_polls GET /api/polls optional; non-published statuses require Mod/Admin
create_poll POST /api/polls polls:write + email verified
get_poll GET /api/polls/{id} optional; non-published only for author or Mod/Admin
update_poll PATCH /api/polls/{id} polls:write (owner) or polls:moderate (Mod/Admin)
delete_poll DELETE /api/polls/{id} polls:write (owner pending_review only) or Mod/Admin
vote_poll POST /api/polls/{id}/vote polls:write
like_poll POST /api/polls/{id}/like polls:write
dislike_poll POST /api/polls/{id}/dislike polls:write
review_poll POST /api/polls/{id}/review polls:moderate Mod/Admin
list_poll_comments GET /api/polls/{id}/comments optional
create_poll_comment POST /api/polls/{id}/comments polls:comment + email verified
hide_poll_comment PATCH /api/polls/{id}/comments/{commentId} polls:moderate Mod/Admin
delete_poll_comment DELETE /api/polls/{id}/comments/{commentId} owner or polls:comment Mod/Admin

Adding a New Tool

  1. Find or create the right src/tools/<category>.ts file.
  2. Add a server.tool(name, description, zodSchema, handleTool(async (args) => { ... })) call inside the register function.
  3. If creating a new file, export function registerXxxTools(server, client) and call it in src/index.ts.
  4. Run pnpm build — a clean exit means no type errors.

Pattern (copy from any existing tool):

server.tool(
    "tool_name",
    "One-line description. Mention required scope.",
    {
        id: z.string().uuid().describe("..."),
    },
    handleTool(async ({ id }) => {
        const data = await client.get<unknown>(`/api/route/${id}`);
        return JSON.stringify(data, null, 2);
    }),
);

Query params: pass as second arg to client.get(url, params) — undefined values are stripped. Body params: pass as second arg to client.post/patch(url, body).


Build & Validate

pnpm build        # tsc — must exit 0 before committing
pnpm test         # vitest unit tests for client + utils

No pre-push script; just pnpm build is the gate.