I built tools that let an AI assistant find research, check draft writing, and make controlled content changes.
I built five tools backed by Notion. They retrieve research, check draft text, and write changes under explicit rules. Model Context Protocol, or MCP, connects the assistant to these tools.
I explored how explicit rules can limit what an AI assistant reads and changes.
I wanted the assistant to work within clear rules for my content, research, and writing style.
I separated the tools into three jobs: find information, check writing, and make an allowed change. Claude chooses a tool; the tool enforces its rules.
Claude calls the tools. The tools do not make their own AI requests.
Pattern, name, role. Each tool is one file. Inputs are validated on every call with Zod.
index.html. Auto-numbers the project. Supports a "preview-only" mode (dry_run).The traces below are real. The card on the home page that linked you here was generated by the third tool call in this sequence.
{
"brief": "AI engineering, restrained,
design-engineer aesthetic,
signal-orange-friendly",
"limit": 4
}the candidate I picked { "name": "Bone-White Editorial — Signal Accents", "hexes": [ "#F4F0E8", "#C8102E", "#111111", "#E8601C", "#D4CAAD" ], "notes": "The benchmark. Bone-white carrier with a hot-red signal. Signal orange as the one controlled disruption..." }
Five custom Claude tools I built to extend my own creative workflow — find ideas in my vault, suggest a color palette, check copy in my voice, scaffold a new project page, save a new idea. The tools hand Claude the options; Claude does the picking and the writing. Proves: AI tool design, server engineering, and the idea of encoding taste as rules rather than agents.
{
"verdict": "ship",
"violation_count": 0,
"violations": [],
"note": "Heuristics passed.
Consider whether the copy actually
says something — heuristics
don't catch empty."
}ship means the rule-based checks found nothing — no hedge words, no filler transitions, no marketing warmth, no repeated phrases, no oversize sentences. The note states the limit: rules can't catch empty writing. That's why the tool doesn't rewrite. Rewriting is a tone judgment; rule-checking is enforcement.
@@ around line 1688 @@ - </div> + + <!-- Project 008 — Content & Research Automation (ACTIVE) --> + <a href="008-six-percent-mcp.html" class="exhibit-card live reveal" aria-label="Open Project 008 — Content & Research Automation"> + <div class="exhibit-art" aria-hidden="true"> + <div class="exhibit-art-num">008</div> + <div class="exhibit-art-glow"></div> + <div class="exhibit-art-icon">⌬</div> + </div> + <div class="exhibit-plaque"> + <div class="exhibit-plaque-num">Project 008 · MCP</div> + <div class="exhibit-plaque-title">Six Percent <span style="color:var(--signal);">MCP</span></div> + <div class="exhibit-plaque-medium">@modelcontextprotocol/sdk · Node ESM · Notion API · Zod</div> + <div class="exhibit-plaque-desc"> + [the description that just passed voice_check] + </div> + <div class="exhibit-before-after"> + <span class="ex-before">AI As Wrapper</span> + <span class="ex-arrow">→</span> + <span class="ex-after">Tools Returning Contracts</span> + </div> + <div class="exhibit-op-tags"> + <span class="ex-op-tag">// MCP</span> + <span class="ex-op-tag">// Tool Design</span> + <span class="ex-op-tag">// Claude Engineering</span> + </div> + </div> + <div class="exhibit-floor"></div> + </a> + + </div>
index.html — the project-gallery container — and inserts the new card just before it closes. Indentation matches the existing cards. The new project number is auto-detected by scanning for the existing <!-- Project NNN --> markers. dry_run returns the change as a preview, not a write — so Claude can review it before approving. After approval, the same call (without dry_run) wrote the card you saw on the home page.
The voice rules from my project's instructions, encoded as plain-text patterns. Read aloud: hedge words, filler transitions, marketing warmth. The tool flags every match with the exact excerpt and a one-line suggestion.