Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@
"Bash(uv run --project ~/.claude/magpie/vetted-ops vetted-op-read *)",
"Bash(uvx --from ~/.claude/magpie/vetted-ops vetted-op-read *)",
"mcp__claude_ai_Gmail__get_thread",
"mcp__claude_ai_Gmail__search_threads",
"mcp__gmail-plaintext__create_draft",
"mcp__ponymail__search_list",
"mcp__ponymail__auth_status",
"mcp__ponymail__get_thread",
"mcp__ponymail__get_email",
Expand Down
18 changes: 9 additions & 9 deletions docs/setup/secure-agent-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -696,17 +696,17 @@ The full block below is the two merged, annotated.
"Bash(uv run --project ~/.claude/magpie/vetted-ops vetted-op-read *)",
"Bash(uvx --from ~/.claude/magpie/vetted-ops vetted-op-read *)", // same dispatcher, the form bulk gatherer agents use
// Read-only MCP tools the security skills call on every sync / import /
// triage run. Without these, each archive or mailbox read prompts, and a
// bulk sync fans out into hundreds of prompts. Write tools stay off this
// list (drafts, logins, label/thread mutations keep their prompt), with
// one exception: gmail-plaintext `create_draft` only creates an unsent
// draft the operator reviews in Gmail.
"mcp__ponymail__search_list", "mcp__ponymail__get_thread", "mcp__ponymail__get_email",
// triage run. Without these, each read of a named thread or message
// prompts, and a bulk sync fans out into hundreds of prompts. Whole-mailbox
// and whole-list searches stay off this list, as do write tools (drafts,
// logins, label/thread mutations): these sessions read untrusted reports,
// so the operator sees those calls.
"mcp__ponymail__get_thread", "mcp__ponymail__get_email",
"mcp__ponymail__get_source", "mcp__ponymail__list_lists", "mcp__ponymail__list_restrictions",
"mcp__ponymail__auth_status",
"mcp__claude_ai_Gmail__search_threads", "mcp__claude_ai_Gmail__get_thread",
"mcp__claude_ai_Gmail__get_message", "mcp__claude_ai_Gmail__list_drafts", "mcp__claude_ai_Gmail__get_draft",
"mcp__gmail-plaintext__create_draft", "mcp__gmail-plaintext__check_auth",
"mcp__claude_ai_Gmail__get_thread", "mcp__claude_ai_Gmail__get_message",
"mcp__claude_ai_Gmail__list_drafts", "mcp__claude_ai_Gmail__get_draft",
"mcp__gmail-plaintext__check_auth",
"mcp__apache-projects__get_committee", "mcp__apache-projects__get_group_members",
"mcp__apache-projects__get_person", "mcp__apache-projects__search_people",
"mcp__apache-projects__project_stats", "mcp__apache-projects__get_releases",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
"security": frozenset(
{
"mcp__claude_ai_Gmail__get_thread",
"mcp__claude_ai_Gmail__search_threads",
"mcp__claude_ai_Gmail__list_drafts",
"mcp__claude_ai_Gmail__list_labels",
}
Expand All @@ -112,7 +111,6 @@
"ASF": {
"security": frozenset(
{
"mcp__ponymail__search_list",
"mcp__ponymail__auth_status",
"mcp__ponymail__get_thread",
"mcp__ponymail__get_email",
Expand Down
9 changes: 4 additions & 5 deletions plugins/magpie-setup/skills/setup/family-mcp-allows.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
"instead of granted to everyone. setup adopt/upgrade write the allows for the families in",
".apache-magpie.lock into the committed .claude/settings.json (a derived key, like",
"enabledPlugins); reconciliation adds the allows for families installed only on one machine",
"to .claude/settings.local.json. List read-only or draft-only tools only: a tool that sends,",
"posts or deletes stays behind the harness prompt and never belongs here.",
"to .claude/settings.local.json. List tools that read one named item or report state only:",
"a tool that sends, posts or deletes, creates a draft, or searches a whole mailbox or list",
"stays behind the harness prompt and never belongs here, because these sessions read",
"untrusted content and the operator should see those calls.",
"The claude_ai_Gmail entries are reads; drafting goes through gmail-plaintext, which writes",
"plain text with no tracking links."
],
Expand All @@ -32,7 +34,6 @@
],
"tools": [
"get_thread",
"search_threads",
"get_message",
"list_drafts",
"get_draft"
Expand All @@ -44,7 +45,6 @@
"security"
],
"tools": [
"create_draft",
"check_auth"
]
},
Expand All @@ -55,7 +55,6 @@
"security"
],
"tools": [
"search_list",
"auth_status",
"get_thread",
"get_email",
Expand Down
8 changes: 4 additions & 4 deletions plugins/magpie-setup/skills/setup/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -1746,10 +1746,10 @@ Same hands-off contract as 9c — **surface, do not run**:
is then usable by **any** agent session on the machine, Magpie-related
or not (see [`tools/gmail/oauth-draft/README.md` → MCP server](../../../../tools/gmail/oauth-draft/README.md#mcp-server)).
3. **Reflect the outcome** in the recommended permission allow-list
(add `mcp__gmail-plaintext__create_draft` alongside the Gmail read
tools — see [`verify.md`](verify.md) check 8d). It only ever creates
**unsent** drafts the human reviews and sends, so allow-listing it
avoids a prompt on every draft.
(add `mcp__gmail-plaintext__check_auth` alongside the Gmail read
tools — see [`verify.md`](verify.md) check 8d). Leave
`mcp__gmail-plaintext__create_draft` off it: each draft keeps its
harness prompt, so the operator sees it being created.
4. **Tell the operator what to do next**, as a numbered list:
1. Run the `claude mcp add gmail-plaintext …` command above.
2. Restart the agent, so the `mcp__gmail-plaintext__*` tools load.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@
for installs that do not carry the framework source (see `isolated.py`).
"""

FRAMEWORK_FINGERPRINT = "sha256:362e4711c8e0274f"
FRAMEWORK_FINGERPRINT = "sha256:3814a0293e38b051"
3 changes: 0 additions & 3 deletions plugins/magpie-setup/skills/setup/verify.md
Original file line number Diff line number Diff line change
Expand Up @@ -677,12 +677,9 @@ adopter opted into via

- **`security` family** —
- `mcp__claude_ai_Gmail__get_thread`
- `mcp__claude_ai_Gmail__search_threads`
- `mcp__claude_ai_Gmail__list_drafts`
- `mcp__claude_ai_Gmail__list_labels`
- `mcp__gmail-plaintext__create_draft`
- and, only when `project.md` declares `organization: ASF` (they are ASF services):
- `mcp__ponymail__search_list`
- `mcp__ponymail__auth_status`
- `mcp__ponymail__get_thread`
- `mcp__ponymail__get_email`
Expand Down
2 changes: 0 additions & 2 deletions tools/permission-audit/src/permission_audit/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
"security": frozenset(
{
"mcp__claude_ai_Gmail__get_thread",
"mcp__claude_ai_Gmail__search_threads",
"mcp__claude_ai_Gmail__list_drafts",
"mcp__claude_ai_Gmail__list_labels",
}
Expand All @@ -112,7 +111,6 @@
"ASF": {
"security": frozenset(
{
"mcp__ponymail__search_list",
"mcp__ponymail__auth_status",
"mcp__ponymail__get_thread",
"mcp__ponymail__get_email",
Expand Down
10 changes: 5 additions & 5 deletions tools/permission-audit/tests/test_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
def test_empty_allow_only_misses_recommended():
result = audit_settings(allow_list=[], families=["security"])
assert result.forbidden == []
# lychee (default family "") + 4 generic security entries = 5
assert len(result.missing_recommended) == 5
# lychee (default family "") + 3 generic security entries = 4
assert len(result.missing_recommended) == 4


def test_forbidden_python_wildcard_flagged_with_pointer():
Expand Down Expand Up @@ -73,7 +73,7 @@ def test_default_family_always_included_even_when_not_requested():
def test_asf_only_recommendations_need_the_asf_organization():
"""PonyMail, the ASF project directory and Vulnogram are ASF services."""
asf_only = {
"mcp__ponymail__search_list",
"mcp__ponymail__get_thread",
"mcp__apache-projects__get_person",
"Bash(vulnogram-api-record-fetch *)",
}
Expand All @@ -83,5 +83,5 @@ def test_asf_only_recommendations_need_the_asf_organization():
assert not asf_only & elsewhere
assert not asf_only & independent
assert asf_only <= asf
# lychee + 4 generic + 11 ASF security entries
assert len(asf) == 16
# lychee + 3 generic + 10 ASF security entries
assert len(asf) == 14
3 changes: 0 additions & 3 deletions tools/sandbox-lint/expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@
"Bash(gh browse *)",
"Bash(gh auth status)",
"mcp__claude_ai_Gmail__get_thread",
"mcp__claude_ai_Gmail__search_threads",
"mcp__gmail-plaintext__create_draft",
"mcp__ponymail__search_list",
"mcp__ponymail__auth_status",
"mcp__ponymail__get_thread",
"mcp__ponymail__get_email",
Expand Down
Loading