agentleFS
Agentic-AssetsAgentic-Assets/apple-mail-mcp/AGENTS.md

apple-mail-mcp

AGENTS.md0 starsChanged 4 months agoMITView on GitHub

Navigation hub for apple-mail-mcp: one Python MCP server (41 tools, fastmcp==3.4.1) shipped as PyPI package (mcp-apple-mail), shared Claude Code, Codex, and Cursor plugin runtime (plugin/), Claude Desktop/Cowork .plugin, and Claude Desktop .mcpb (apple-mail-mcpb/). Marketplace entries: .claude-plugin/marketplace.json for Claude Code and .agents/plugins/marketplace.json for Codex Desktop/CLI. Cursor uses its distinct plugin-local adapter; local Cursor Agent acceptance has passed, while Cursor marketplace/UI admission remains a separate distribution check. The collected-test count is single-sourced in tools/expected_test_count.txt (the dev-check/release gate fails on drift and prints…

  • Installs packages

The file

We split this AGENTS.md into the rules it gives an agent

7 rules. About 0 are common, 4 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Commit counts, timings, and redacted samples instead.

    line 11
  2. Distinctive:

    Keep client-specific schemas separate, and do not infer marketplace/UI support from a static manifest or local adapter test.

    line 35
  3. Very specific:

    If you change distribution, version, or filenames: re-run bash tools/gates/dev-check.sh release and verify …

    line 50
  4. Distinctive:

    Use plugin-dev experts for plugin, MCP, marketplace, and skill work when they are available.

    line 66
  5. Distinctive:

    Do not solo large plugin or perf workstreams without at least one plugin-dev expert pass unless the current host or task lane makes those …

    line 74
  6. Distinctive:

    A merged branch is not a released version: If the change carries a version bump, closing out means merge → tag → GitHub Release, and the …

    line 125
  7. Very specific:

    Repo agent skills: Add under .agents/skills/<name>/.

    line 145

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

AGENTS.md

Navigation hub for apple-mail-mcp: one Python MCP server (41 tools, fastmcp==3.4.1) shipped as PyPI package (mcp-apple-mail), shared Claude Code, Codex, and Cursor plugin runtime (plugin/), Claude Desktop/Cowork .plugin, and Claude Desktop .mcpb (apple-mail-mcpb/). Marketplace entries: .claude-plugin/marketplace.json for Claude Code and .agents/plugins/marketplace.json for Codex Desktop/CLI. Cursor uses its distinct plugin-local adapter; local Cursor Agent acceptance has passed, while Cursor marketplace/UI admission remains a separate distribution check. The collected-test count is single-sourced in tools/expected_test_count.txt (the dev-check/release gate fails on drift and prints the new number); recount with PYTEST_ADDOPTS='' .venv/bin/pytest --collect-only tests.

This repo is PUBLIC. Check what you commit.

Agentic-Assets/apple-mail-mcp is a public GitHub repo. Commits, branches, PR and issue comments, and release artifacts are world-readable the moment they are pushed, and a force-push does not unpublish them.

The point of this codebase is reading real mailboxes, so real mail data is always one live test away from the working tree. Never commit: real email addresses or contact details · real subjects, bodies, snippets, or Message-ID headers · account UUIDs, server hostnames, or mailbox URLs · absolute /Users/<name>/... paths, session scratch paths, or session IDs · secrets, tokens, or cookies · live-test output pasted verbatim.

Commit counts, timings, and redacted samples instead. Fixtures use synthetic addresses (sender@example.com). A number measured from a real mailbox is publishable; the message it came from is not.

This is enforced, not advisory. tools/validators/validate_no_committed_identity.py scans every tracked text file and exits non-zero on a new email address at a non-placeholder domain, an absolute /Users/<name>/... path, or an uppercase account UUID. It runs in bash tools/gates/dev-check.sh (default and release tiers), so it runs on every commit through the pre-commit hook. Run it yourself before committing docs, tasks/ artifacts, test fixtures, or anything carrying live-test output:

python3 tools/validators/validate_no_committed_identity.py

Hits that are already published are grandfathered per file in that validator's KNOWN_IDENTITY_HITS ratchet. Lowering a count is always a valid change; raising one is not — redact instead (synthetic address, elided path, placeholder UUID). Reserved and clearly synthetic placeholder domains never fire, so sender@example.com stays legal. Carry this constraint into every subagent prompt that writes files or commits.

Marketplace identity boundary

tools/marketplace_identity.json is the machine-readable source-repository contract. The primary Agentic Assets marketplace is Agentic-Assets/Agentic-Assets-Marketplace, with marketplace ID agentic-assets, selector apple-mail@agentic-assets, and promoted payload destination plugins/apple-mail. This repository owns the editable plugin/ source. The marketplace admits only immutable, allowlisted payload snapshots from signed source tags and owns promotion policy, evidence, and attestations.

The root .claude-plugin/marketplace.json and .agents/plugins/marketplace.json remain standalone development/public compatibility catalogs named apple-mail-mcp, with selector apple-mail@apple-mail-mcp. Never rename those catalogs to agentic-assets. Keep client-specific schemas separate, and do not infer marketplace/UI support from a static manifest or local adapter test.

Distribution channels (five install surfaces from one source tree)

A single plugin/ runtime serves Claude Code, Codex, and Cursor plugin installs; bash tools/gates/build-artifacts.sh emits the Claude Desktop upload artifacts. Drift between manifests and artifacts has caused real installer failures; tools/validators/validate_manifests.py enforces parity and the release gate refuses to ship with any artifact missing or stale.

SurfaceInstall targetFormat
apple-mail-plugin.zipClaude Code standalone compatibility marketplace (claude plugin install apple-mail@apple-mail-mcp)Plain zip, .claude-plugin/plugin.json at zip root; the central marketplace promotes the corresponding payload separately
apple-mail.pluginClaude Desktop Cowork → Customize → Add plugin → Upload pluginByte-identical copy of the .zip, .plugin extension is what the Cowork UI accepts
apple-mail-mcp-v{VERSION}.mcpbClaude Desktop chat extension via "Add Custom Plugin" / "Install from file"DXT bundle (mcpb pack), manifest.json at zip root
.agents/plugins/marketplace.json + plugin/.codex-plugin/plugin.jsonCodex Desktop/CLI standalone compatibility marketplace (codex plugin add apple-mail@apple-mail-mcp)GitHub marketplace checkout points at shared ./plugin runtime with plugin/.mcp.json
plugin/.cursor-plugin/plugin.json + plugin/mcp.jsonCursor plugin and local MCP adapterSeparate draft-safe Cursor adapter; local Cursor Agent acceptance passed, while marketplace/UI admission remains separate

If you change distribution, version, or filenames: re-run bash tools/gates/dev-check.sh release and verify tests/infra/test_validate_manifests.py covers the change. Never ship a .plugin whose bytes differ from the .zip — the validator and local release tests treat that as a hard error.

Full detail: docs/CLAUDE-conventions.md § Distribution channels.

Agent orchestration (required)

When the host exposes this repo's subagent tools, use subagents for both research and implementation, not just exploration. Delegate real fixes, tests, docs, and live verification to subagents; the lead agent orchestrates and reviews. If the host, task owner, or safety lane forbids subagents, do the work directly and state that constraint in the handoff.

WhenSubagent
Code changes, tests, docsgeneralPurpose
Codebase search / file discoveryexplore
pytest, live CLI, shell tasksshell
Independent workstreamsRun subagents in parallel
Dependent steps (e.g. perf gates before tool edits)Run subagents sequentially

Use plugin-dev experts for plugin, MCP, marketplace, and skill work when they are available; invoke before and after substantive changes:

ExpertUse for
plugin-dev:plugin-validatorManifest drift, tool counts, marketplace readiness
plugin-dev:skill-reviewerBundled skill descriptions, trigger overlap, safety language
Skills: plugin-dev:mcp-integration, plugin-dev:plugin-structure, mcp-builderMCP server design, .mcp.json / plugin.json, tool quality

Do not solo large plugin or perf workstreams without at least one plugin-dev expert pass unless the current host or task lane makes those experts unavailable; in that case, document the gap and run the repo's local validation gates.

Run code-simplifier:code-simplifier regularly — after any non-trivial change to tools, backend, helpers, or tests. Especially after refactors that touched many sites (e.g. capability-token / structured-error / bounded-scan work). Behavior must be preserved; the simplifier collapses duplication, drops dead branches, and tightens names. Trigger it as part of every "ready to ship" pass alongside plugin-validator and skill-reviewer, and any time a file grows past ~600 LOC or a helper sprouts >3 near-copies.

Module line budget (automated): the local hooks, dev-check.sh, and validate_manifests.py warn on modules over 600 LOC in plugin/apple_mail_mcp/ and tools/, and fail if a tracked file grows past its baseline (tests/fixtures/module_line_budget/baseline.json). Detail: docs/CLAUDE-conventions.md § Module line budget · tools/CLAUDE.md § check_module_line_budget.py.

When working in…

AreaRead
Plugin wrapper, start_mcp.sh, manifestsplugin/docs/CLAUDE.md
Package entry, core/, server.py, cli/plugin/apple_mail_mcp/CLAUDE.md
Individual MCP toolsplugin/apple_mail_mcp/tools/CLAUDE.md
Skills (11 workflow skills)plugin/skills/CLAUDE.md
Tests & mocking AppleScripttests/CLAUDE.md
Manifest validation, pre-committools/CLAUDE.md
Live CLI testing, agent workflowsdocs/CLAUDE.md
Deep tool/skill/plugin rulesdocs/CLAUDE-conventions.md
Phase plans & backlogtasks/CLAUDE.md · tasks/todo.md — read tasks/CLAUDE.md § Agent requirements before adding or moving task files
MCPB bundle buildapple-mail-mcpb/CLAUDE.md
Claude Code marketplace manifest.claude-plugin/CLAUDE.md
Codex Desktop/CLI plugin surface.agents/plugins/marketplace.json · plugin/.codex-plugin/plugin.json · plugin/.mcp.json
Cursor plugin surfaceplugin/.cursor-plugin/plugin.json · plugin/mcp.json

Architecture (prose)

Plugin wrapper (plugin/start_mcp.sh, plugin.json) launches Python package (plugin/apple_mail_mcp/: __main__ → import tools/* → register on FastMCP in server.py) which drives Mail.app through core.run_applescript() (stdin osascript, escaped user input, JSON-safe output). Dev venv: repo root .venv/; user plugin venv: plugin/venv/ (install-time only).

Dev setup

python3 -m venv .venv && .venv/bin/pip install -e . pytest
.venv/bin/pytest tests/                    # full suite (count tracked in tools/expected_test_count.txt)
python3 tools/validators/check_module_line_budget.py  # 600 LOC warn report (also runs in dev-check + CI)
bash tools/gates/dev-check.sh                    # manifests + module budget + pytest + test-count gate
.venv/bin/apple-mail quick-check --json    # live Mail smoke (~30s)
.venv/bin/python plugin/apple_mail_mcp.py --read-only

Version bump (release together)

  • pyproject.toml → [project].version
  • plugin/.claude-plugin/plugin.json → version
  • plugin/.codex-plugin/plugin.json → version
  • plugin/.cursor-plugin/plugin.json → version
  • .claude-plugin/marketplace.json → plugins[0].version (not metadata.version)
  • server.json → top-level + packages[0].version
  • apple-mail-mcpb/manifest.json → version

Sync tool-count claims in manifests with find plugin/apple_mail_mcp/tools -name '*.py' | xargs grep -h '^@mcp.tool' | wc -l (recursive: compose/ is a package). Codex marketplace metadata lives in .agents/plugins/marketplace.json and points at ./plugin; Codex MCP wiring lives in plugin/.mcp.json, should keep --draft-safe, and should launch via cwd: "." + ./start_mcp.sh unless a fresh bash tools/gates/validate-codex-plugin.sh runtime smoke proves a different Codex contract. Before shipping, run bash tools/gates/dev-check.sh release; the gate enforces fatal ruff check, ruff format --check, and mypy --strict for plugin/apple_mail_mcp/, then exact plugin zip/MCPB payloads, byte parity between apple-mail-plugin.zip and apple-mail.plugin, package deps/packages, install contracts, source syntax, and artifact freshness. After a signed source tag is pushed, run bash tools/gates/marketplace-handoff.sh vX.Y.Z; it verifies the source handoff and prints the one Marketplace preparation command. Do not add new lint/type tools without asking.

A merged branch is not a released version. If the change carries a version bump, closing out means merge → tag → GitHub Release, and the order is load bearing: the release gate's stamp binds HEAD's commit SHA, not its tree, so a merge commit invalidates a stamp taken on the feature branch even though the tree is identical. Run bash tools/gates/source-release-gate.sh after the merge, on main, then bash tools/gates/create-release-tag.sh (no flags previews without signing), then --confirm-create, then push the tag. Signing needs user.signingkey set and the key loaded in ssh-agent; the key is machine-local and does not travel. Preflight demands a checkout clean of untracked and gitignored files — validate_repo_root.py scans the filesystem, and a stray root uv.lock (written by any uv run whose cwd is inside this tree) fails it despite being gitignored. Attach all three artifacts to the Release; only the .zip is tracked in git. Full procedure: .agents/skills/finalize-apple-mail-mcp/SKILL.md § 10.

Related folders

plugin/apple_mail_mcp/ (source of truth) · plugin/ (shared Claude Code, Codex, and Cursor plugin runtime) · .claude-plugin/ (Claude Code marketplace) · .agents/plugins/ (Codex marketplace) · apple-mail-mcpb/ · tests/ · tools/ · docs/ · tasks/

Repo agent skills: Add under .agents/skills/<name>/; symlink .claude/skills/<name> → ../../.agents/skills/<name> (not .cursor/skills/). Commit and push after adding or moving skills. Inventory, and which vendored skills carry local corrections a re-sync would discard: .agents/skills/README.md. Post-change ship: Invoke finalize-apple-mail-mcp to sync docs, both root hubs (AGENTS.md and CLAUDE.md), and manifests, then commit and push when the user asks.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.