Skip to main content
Glama
manalejandro

CF ActivityPub MCP

by manalejandro

CF ActivityPub MCP

English | Español

License: MIT Version PRs Welcome Cloudflare Workers MCP

A remote Model Context Protocol server that lets AI assistants administer a CF ActivityPub instance through its administration API — fully hosted on Cloudflare Workers.

Overview

CF ActivityPub MCP is the administration companion for CF ActivityPub Next, the Mastodon-compatible ActivityPub server built for Cloudflare Workers.

Point it at your instance with the same ADMIN_TOKEN operator secret, connect any MCP-capable assistant, and manage accounts, reports, federation rules, relays, media cache, settings and more through natural conversation. The worker:

  • Exposes the full administration surface as 35 well-described MCP tools.

  • Includes Centinela, an AI watchdog running on Cloudflare Durable Objects that reviews the instance on a schedule, asks Workers AI for an analysis and can propose or execute guarded actions.

  • Speaks Streamable HTTP (/mcp, JSON responses) and an SSE-shaped endpoint (/sse) for clients that require it.

  • Requires its own bearer token (MCP_AUTH_TOKEN) on every MCP request, independent from the instance token.

  • Publishes a public landing page and a /health JSON report with live metrics, including the Sentinel state.

  • Runs with Cloudflare observability (traces, logs and real-time issues) enabled.

  • Deploys to a custom domain with a single wrangler deploy.

The MCP never stores instance data: every tool call is a thin, authenticated proxy to the CF ActivityPub admin API, which keeps its own audit trail. Centinela stores only its own configuration, run history and decisions inside its Durable Object.

Related MCP server: BYOB MCP Server

Architecture

Layer

Technology

Runtime

Cloudflare Workers

MCP transport

Agents SDK createMcpHandler (stateless, MCP SDK v2)

Protocols

Streamable HTTP + SSE response shaping, JSON-RPC 2.0

Authentication

Bearer token (MCP_AUTH_TOKEN) with constant-time comparison

Upstream

CF ActivityPub admin API (ADMIN_TOKEN)

AI Sentinel

Cloudflare Durable Objects (SQLite-backed) + Agents SDK scheduling + Workers AI

Observability

Workers Logs, Traces and Issues

Language

TypeScript, Zod schemas

Endpoints

Path

Method

Auth

Description

/

GET

Public

Landing page with live health metrics

/health

GET

Public

JSON health report (worker + instance)

/mcp

POST

Bearer

Streamable HTTP MCP endpoint; JSON by default, SSE when needed

/sse

POST

Bearer

SSE-shaped MCP endpoint for SSE-first clients

/mcp, /sse

OPTIONS

Public

CORS preflight handled by the MCP handler

Modern protocol revisions (2026-07-28) receive JSON responses; legacy clients are served through the stateless compatibility lane. The deprecated HTTP+SSE session transport (a long-lived GET /sse stream plus POST /messages) is intentionally not implemented — point legacy clients at /mcp (or use a proxy such as mcp-remote).

Requirements

  • A deployed CF ActivityPub Next instance with ADMIN_TOKEN configured (wrangler secret put ADMIN_TOKEN in that project).

  • A Cloudflare account with the domain you want to use. Centinela additionally uses Workers AI (available on the free plan with a daily neuron allowance) and one Durable Object.

  • Node.js 20+ and npm.

Quick start

# 1. Install dependencies
npm install

# 2. Configure the instance URL (and optionally the custom domain)
#    Edit `vars` in wrangler.jsonc: ACTIVITYPUB_URL=https://social.example.com

# 3. Create the two secrets
npx wrangler secret put ADMIN_TOKEN      # same value as the instance's ADMIN_TOKEN
npx wrangler secret put MCP_AUTH_TOKEN   # openssl rand -hex 32

# 4. Local development
npm run dev

# 5. Deploy
npm run deploy

For local development, copy .dev.vars.example to .dev.vars and fill in both tokens.

Configuration

Plain-text variables (vars in wrangler.jsonc)

Variable

Required

Description

ACTIVITYPUB_URL

Yes

Public base URL of the CF ActivityPub instance, e.g. https://social.example.com

MCP_SERVER_NAME

No

Name reported by the MCP server (default cf-activitypub-mcp)

MCP_SERVER_VERSION

No

Version reported by the MCP server (default 1.0.0)

MCP_ALLOWED_HOSTNAMES

No

Comma-separated Host allowlist for the MCP endpoints. Localhost and workers.dev are always accepted when unset

MCP_ALLOWED_ORIGINS

No

Comma-separated browser Origin allowlist, or * when an upstream layer validates origins. Only needed for browser-based MCP clients

The SENTINEL_* variables that seed Centinela are documented in AI Sentinel (Centinela).

Secrets (wrangler secret put)

Secret

Description

ADMIN_TOKEN

The operator secret of the CF ActivityPub instance. Grants full administrator access to its API

MCP_AUTH_TOKEN

Bearer token that MCP clients must present on /mcp and /sse. Generate with openssl rand -hex 32

Authentication

Two independent credentials are involved:

  1. MCP clients → this worker. Every request to /mcp or /sse must include Authorization: Bearer <MCP_AUTH_TOKEN>. Requests are rejected with 401 otherwise, and the endpoint is closed with 503 when the secret is not configured. Token comparison hashes both values before comparing to avoid timing leaks.

  2. This worker → the ActivityPub instance. Tool calls send Authorization: Bearer <ADMIN_TOKEN> to the instance admin API. The instance validates it with its own admin-auth logic and writes every mutation to the moderation log.

Rotate each token independently: changing MCP_AUTH_TOKEN only affects MCP access; changing ADMIN_TOKEN must be done in both workers.

Connecting an MCP client

Claude Desktop (via mcp-remote)

{
	"mcpServers": {
		"cf-activitypub": {
			"command": "npx",
			"args": [
				"mcp-remote",
				"https://mcp.example.com/mcp",
				"--header",
				"Authorization: Bearer <MCP_AUTH_TOKEN>"
			]
		}
	}
}

Clients with native remote transport (Cursor, VS Code, others)

{
	"mcpServers": {
		"cf-activitypub": {
			"url": "https://mcp.example.com/mcp",
			"headers": {
				"Authorization": "Bearer <MCP_AUTH_TOKEN>"
			}
		}
	}
}

Use https://mcp.example.com/sse instead of /mcp when a client explicitly requires an SSE endpoint.

MCP Inspector

npx @modelcontextprotocol/inspector
# Transport: Streamable HTTP
# URL:       https://mcp.example.com/mcp
# Header:    Authorization: Bearer <MCP_AUTH_TOKEN>

Tools

The server exposes 35 tools, grouped by administrative domain. Destructive actions (delete, reject, suspend, demote, purge, clear_all, remove, dismiss) require an explicit confirm: true argument, so an assistant cannot destroy data by accident.

Overview and health

Tool

Description

check_instance_health

Reachability and latency of the instance plus its public metadata

get_instance_info

Full public instance payload (version, languages, limits, registration policy)

get_instance_overview

Combined summary: metadata, account/report/moderation/federation/relay totals and media cache stats

Instance settings

Tool

Description

get_instance_settings

Rules, policies, languages and registration settings

update_instance_settings

Updates any subset of the settings above

Accounts and moderation

Tool

Description

list_accounts

Search/filter local and remote accounts (status, role, locality, query)

get_account

One account with moderation flags, role and profile

moderate_account

approve, unapprove, reject, silence, unsilence, suspend, unsuspend, promote, demote, delete

verify_account

Forces a rel="me" verification refresh

search

Federated search for accounts, statuses, hashtags and collections

Reports

Tool

Description

list_reports

Abuse reports with statuses, accounts and notes

get_report

One report ticket

manage_report

resolve, dismiss, reopen, delete, add_note

Federation

Tool

Description

list_domain_blocks

Instance-wide domain blocks

manage_domain_block

block / unblock a domain (severity, media/report rejection, comments)

list_instances

Federation registry with status filters

manage_instance

add, refresh, reset, suspend, unsuspend, purge

list_relays

Subscribed ActivityPub relays

manage_relay

add, enable, disable, remove

Content and policy

Tool

Description

list_licenses

License catalogue (FEP-6757)

manage_license

add, update, delete

list_emojis

Custom emojis, including disabled ones

manage_emoji

upload (URL or base64), enable/disable, delete

manage_announcement

create / delete instance announcements

Operations

Tool

Description

get_media_cache

Cache statistics, most served entries and effective config

manage_media_cache

enforce_budget, purge

list_email_blocks

Blocked mailboxes (canonical email hashes)

manage_email_block

block / unblock a mailbox

get_moderation_log

Audit trail with target/action filters

manage_moderation_log

delete_entry, clear_all

AI Sentinel (Centinela)

Tool

Description

get_sentinel_status

Configuration, AI usage ledger, last run, next check and decision totals

configure_sentinel

Mode, interval, model, thresholds, allow-list, protected domains, webhook

run_sentinel_check

Runs an analysis immediately (respects the current mode)

get_sentinel_decisions

Decision history with status, target, confidence and result

clear_sentinel_decisions

Deletes the decision and run history (requires confirmation)

Known limitations

  • manage_report with action: "add_note" needs an OAuth token owned by a local actor; the shared ADMIN_TOKEN cannot author notes and the instance answers 401.

  • Announcement listing is actor-only on the instance, so this MCP can create and delete announcements but not list them.

  • The MCP never exposes the instance database directly; it is limited to what the admin API supports.

AI Sentinel (Centinela)

Centinela is an autonomous watchdog that lives in a SQLite-backed Durable Object and wakes up on a schedule managed by the Agents SDK (backed by Durable Object alarms).

On every check it:

  1. Collects a compact snapshot through the admin API: instance health, counters, pending registrations, open reports, problem federated instances, domain blocks, media cache pressure and the recent moderation log.

  2. Asks Workers AI (JSON mode) for a structured analysis: summary, severity, findings and proposed actions.

  3. Applies deterministic guardrails in code — not in the prompt — and then records, proposes or executes the surviving actions depending on the configured mode.

Modes

Mode

Behavior

observe

Analyses and records findings only. Nothing is proposed or executed.

suggest

Records proposed actions so the operator can review them, but never calls the instance API.

enforce

Executes actions that pass every guardrail.

enforce is powerful: start in observe, review the decision history, then move to suggest and only then to enforce with a narrow allow-list.

Guardrails

  • Action allow-list. Only resolve_report, dismiss_report, silence_account, suspend_account, block_domain and enforce_media_cache exist, and the operator chooses which are enabled.

  • Per-action confidence floors combined with the configured minConfidence (for example, suspending an account or blocking a domain requires ≥ 0.9 by default).

  • Per-run budget. At most maxActionsPerRun actions are executed per check.

  • Daily neuron budget. The Sentinel estimates the neuron cost of every Workers AI call from the provider token counts and the official per-model rates. When dailyNeuronBudget is reached (UTC day, matching Cloudflare's reset at 00:00 UTC), scheduled checks are skipped and recorded until the next day. Set it to 0 for unlimited usage.

  • Cooldowns. The same action against the same target is not repeated within cooldownHours (24 by default).

  • Protected targets. Administrators and moderators can never be silenced or suspended; protected domains can never be blocked; already-blocked domains and already-moderated accounts are skipped.

  • Prompt-injection defense. Report comments, registration reasons and display names are treated as untrusted data, and the guardrails run in code so a manipulated model cannot exceed its mandate.

  • Audit trail. Every run and decision is stored in the Durable Object with status observed, proposed, blocked, executed or failed.

Configuration

The agent is seeded on first boot from wrangler.jsonc variables and can then be reconfigured live through configure_sentinel:

Variable

Default

Description

SENTINEL_ENABLED

false

Start the periodic schedule

SENTINEL_MODE

observe

observe, suggest or enforce

SENTINEL_INTERVAL_SECONDS

900

Seconds between checks (60 – 86400)

SENTINEL_MODEL

@cf/meta/llama-3.3-70b-instruct-fp8-fast

Workers AI model

SENTINEL_MAX_ACTIONS

3

Hard cap of executed actions per run

SENTINEL_MIN_CONFIDENCE

0.8

Minimum model confidence

SENTINEL_COOLDOWN_HOURS

24

Cooldown window per action+target

SENTINEL_DAILY_NEURON_BUDGET

10000

Workers AI budget in neurons per UTC day (0 = unlimited)

SENTINEL_ALLOWED_ACTIONS

all actions

Comma-separated allow-list

SENTINEL_PROTECTED_DOMAINS

empty

Domains the Sentinel must never act against

SENTINEL_NOTIFY_WEBHOOK

empty

HTTPS webhook that receives a JSON summary after each run

A typical first configuration from an MCP client:

configure_sentinel { "enabled": true, "mode": "suggest", "interval_seconds": 3600, "daily_neuron_budget": 10000 }
run_sentinel_check {}
get_sentinel_decisions { "limit": 20 }

get_sentinel_status reports the live ledger: usage.neuronsUsed, usage.dailyNeuronBudget, usage.remaining, usage.runs and token totals for the current UTC day. The budget is a safety valve, not an exact invoice: usage is estimated from the token counts the model returns (or from text length when the model omits them) and the published per-model rates.

Local development: the local simulator cannot execute Workers AI bindings, so Sentinel checks in wrangler dev are recorded as errors and do not consume neurons. Deploy the worker (or use wrangler dev --remote with a publicly reachable ACTIVITYPUB_URL) to exercise the model.

Centinela complements the instance's own Guardian: the Guardian moderates content inside CF ActivityPub, while Centinela watches the instance as an operator would and acts through the admin API. Both keep their own audit trails.

Health and landing page

  • GET / renders a public landing page linking to both repositories and showing live metrics (worker status, instance status, latency, active users, tool count and Sentinel mode).

  • GET /health returns the same data as JSON, suitable for uptime monitors:

{
	"status": "ok",
	"service": { "name": "cf-activitypub-mcp", "version": "1.0.0", "tools": 35, "authentication": "bearer" },
	"instance": { "url": "https://social.example.com", "reachable": true, "latency_ms": 42, "users": 128 },
	"sentinel": { "enabled": true, "mode": "suggest", "last_run_at": "2026-10-04T04:00:00.000Z", "last_run_status": "ok", "decisions_total": 12, "neurons_today": 843, "daily_neuron_budget": 10000 }
}

No secrets or administrative details are exposed by either endpoint. The Sentinel section is read through its Durable Object and cached for a minute so health polling does not keep the agent awake.

Security

  • Fail closed. MCP endpoints refuse to serve when MCP_AUTH_TOKEN is missing.

  • Least privilege. The MCP only knows the instance admin API; it cannot reach Cloudflare account resources.

  • Auditability. Every mutation performed through the MCP is recorded by the instance in its moderation log; Centinela keeps its own decision history.

  • Confirmation guards. Destructive tools require confirm: true; the model must be told explicitly.

  • Sentinel guardrails. The AI never executes an action outside the allow-list, below the confidence floor, over the per-run budget or against protected accounts and domains. Guardrails run in code, not in the prompt.

  • Prompt-injection defense. Snapshot content is treated as untrusted data and never as instructions.

  • Constant-time token comparison. Candidate and expected tokens are hashed and compared with an XOR accumulator.

  • Origin/Host allowlists. Optional MCP_ALLOWED_ORIGINS / MCP_ALLOWED_HOSTNAMES restrict browser and Host access.

  • Source maps. upload_source_maps keeps stack traces readable in the dashboard without shipping them to clients.

If you find a security issue, please open a private report through GitHub rather than a public issue.

Development

Script

Purpose

npm run dev

Start the local Workers dev server

npm run deploy

Deploy to Cloudflare (custom domain from wrangler.jsonc)

npm test

Run the Vitest suite inside the Workers runtime

npm run test:watch

Watch mode

npm run typecheck

Strict TypeScript check

npm run cf-typegen

Regenerate worker-configuration.d.ts after binding changes

Project structure

src/
  index.ts                  Worker entry: routing, auth, endpoints, DO export
  config.ts                 Environment parsing and defaults
  auth.ts                   Bearer authentication and secret comparison
  activitypub/
    client.ts               Authenticated client for the instance API
    types.ts                Shared API payload shapes
  mcp/
    server.ts               MCP server factory and tool catalogue
    context.ts              Per-request tool context (lazy clients + env)
    result.ts               Tool result helpers
    tools/                  One module per administrative domain
  sentinel/
    agent.ts                Centinela: SQLite-backed Durable Object agent
    analyze.ts              Workers AI prompt and structured analysis
    snapshot.ts             Instance snapshot collection
    policy.ts               Deterministic guardrails and settings validation
    defaults.ts             Environment-seeded configuration
    types.ts                Sentinel types and action catalogue
  web/
    health.ts               Health report collection (includes Sentinel)
    index-page.ts           Public landing page renderer
test/
  index.spec.ts             Worker routes and MCP protocol tests
  config.spec.ts            Config and auth unit tests
  client.spec.ts            ActivityPub client unit tests
  sentinel.spec.ts          Sentinel policy, analysis and Durable Object tests

Deployment notes

  1. Set routes[0].pattern in wrangler.jsonc to your subdomain (for example mcp.example.com). Wrangler creates the DNS record and certificate automatically on deploy.

  2. Set ACTIVITYPUB_URL to the public URL of your instance.

  3. Configure both secrets with wrangler secret put.

  4. Run npm run deploy, then open https://mcp.example.com/ to verify the health metrics.

  5. Observability is already enabled: traces, logs and real-time issues are available in the Cloudflare dashboard under the worker's Observability tab.

The first deploy applies the v1 migration and creates the SQLite-backed SentinelAgent Durable Object class. The MCP tool endpoints themselves stay stateless and work entirely through the instance API; only Centinela uses Durable Object storage, Workers AI and alarms.

License

MIT © 2026 manalejandro

CF ActivityPub MCP is not affiliated with Cloudflare, Inc. or the Mastodon project. The author is not responsible for the use of this software, nor for any charges Cloudflare may apply.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables AI assistants to manage Cloudflare resources through natural language, including DNS records, zone management, Workers KV storage, cache purging, and analytics. Supports comprehensive Cloudflare operations with secure API token authentication.
    13
    2
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to dynamically discover and invoke containerized tools that can be registered at runtime without redeployment. Built on Cloudflare Workers with scale-to-zero containers for secure, isolated tool execution.
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    An MCP server that gives AI agents full admin control over Discord servers with 59 tools for messaging, moderation, roles, channels, forums, reactions, files, and more, deployed on Cloudflare Workers.
    6
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to administrate WHMCS installations through the External API, providing ~50 tools for clients, billing, orders, services, domains, support, and aggregators with safety features and governance.
    25 npm
    3
    ISC