Introduction
Mikuji is a proactive MCP server. Instead of waiting for your agent to ask, a local daemon watches your world and pushes the right context the moment it matters.
A normal MCP server is passive. It exposes tools and resources, then sits idle until the agent decides to call one. That puts the burden of knowing what to ask and when entirely on the model. Anything the agent never thinks to request stays invisible.
Mikuji inverts that. It runs continuously, observes sources you point it at, evaluates each change against your policies, and delivers a proposal through whatever channel the host supports.
How it differs from a plain MCP server
The whole design hangs on one inversion: the server moves first. Everything else makes that safe.
- Direction. Proactive push with a pull fallback, instead of pull only.
- Triggers. Filesystem, git, GitHub, SQL polling, log tailing, webhooks, and a context inbox.
- Decisioning. A YAML policy engine scores events and applies gates before anything reaches you.
- Delivery. Capability-negotiated per host, so Mikuji only uses channels the agent truly supports.
- Audit. Every decision and delivery is written to a tamper-evident hash chain.
Architecture at a glance
Mikuji is a small monorepo. The daemon is the heart; the connector is the thin bridge your agent speaks to.
Installation
Mikuji needs Node 22 or newer. The daemon runs with npx, no global install required.
# start the local daemon (binds to 127.0.0.1:7777) $ npx mikuji-daemon
The daemon creates its data directory at ~/.mikuji on first run and applies migrations automatically. Override it with MIKUJI_DATA_DIR.
Quickstart
Three steps: start the daemon, point your agent at the connector, then drop in a policy.
Connect your agent
$ claude mcp add mikuji -- npx mikuji-mcp connect
Write your first policy
Policies live as YAML files. This one watches for large pull requests you opened and proposes a review.
rule: nudge_on_review_request when: watcher: github event: pr.review_requested predicate: "payload.reviewer = $me" do: action: PROPOSE context: "PR #{{payload.pr.number}} needs review" priority: high cooldown: 1h quiet_hours_respect: true
Core concepts
Five pieces carry every push from the outside world to your agent. Each is independent and testable on its own.
Watchers
A watcher turns a source of change into a stream of typed events. You configure watchers per project; the daemon supervises their lifecycle.
Policy DSL
A policy is a small YAML document with four parts: when selects an event type, where filters its fields, decide shapes the proposal, and gates decide whether it is allowed to reach you right now.
Delivery layer
When a decision survives its gates, the dispatcher picks a channel. During the MCP handshake the connector reports what the host supports, so Mikuji uses elicitation, a logging notification, or a resource update, and falls back to a pull tool when the host stays quiet.
Audit chain
Every decision and delivery is appended to a hash-linked log, where each entry includes the hash of the one before it. If a record is altered after the fact, the chain no longer verifies, so the history is tamper-evident by construction.
CLI
Mikuji ships two binaries. The daemon runs once per machine; the connector runs once per agent.
--daemon <ws-url>.# 1. start the daemon $ npx mikuji-daemon # 2. connect your agent $ claude mcp add mikuji -- npx -y mikuji-mcp connect
Configuration
Bootstrap config resolves in order: defaults, then ~/.mikuji/config.json, then environment variables.
PUT /api/settings/:key without a restart.REST and WebSocket
The daemon exposes one server on port 7777: a CORS-enabled REST API for the dashboard, the webhook ingress, and the connector WebSocket.
GET /api/statusbus stats, watcher health, and connected hosts.GET, POST /api/watcherslist and create watchers;PATCH,/enable,/disable, andDELETEmanage one.GET, POST /api/policiesandPOST /api/policies/testto dry-run a rule.GET /api/events,/api/decisions,/api/pushesthe history.GET /api/auditand/api/audit/verifythe chain and its integrity check.GET, PUT /api/settingsread and write runtime settings.POST /watch/:namethe generic webhook ingress.WS /connectorthe bridge each connector dials.