Skip to content

Commit e7ba165

Browse files
luiseimanclaude
andcommitted
fix(mcp): complete all 4 MCP templates to github-level quality
postgres: - Fix false claim that server is read-only by design — it executes arbitrary SQL - Rewrite rules.md with real SQL safety: hard stops for DROP/TRUNCATE/DDL, confirm-before-DML, no UPDATE/DELETE without WHERE, production environment detection, connection pooling guidance - permissions.json: correct _comment to document the tool-level limit of the MCP permissions system (SQL-level restriction is behavioral via rules.md) supabase: - Add _verified_with: @supabase/mcp-server-supabase@0.7.0 to config.json - Add _read_only_variant note documenting --read-only flag - rules.md: add "Read-only mode for production" section — documents --read-only as hard enforcement layer for production tokens with exact args example redis: - permissions.json: add config_set, config_rewrite, shutdown to deny list (config_set can change maxmemory/bind/requirepass at runtime; shutdown terminates the process) - rules.md: expand hard stops section with rationale for each denied operation slack: - permissions.json: add update_message, archive_channel, set_channel_purpose, set_channel_topic to deny; add add_reaction to allow - rules.md: full rewrite — add editing rules (bot-only), privacy guidance for private channels, channel scope policy ("which channel(s)?"), hard stops with rationale for each denied operation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent fd21816 commit e7ba165

8 files changed

Lines changed: 139 additions & 36 deletions

File tree

mcp/postgres/permissions.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"_template": "claude-kit/mcp/postgres",
3-
"_comment": "The official postgres MCP server (@modelcontextprotocol/server-postgres) is read-only by design — it only exposes query (SELECT). This permissions file documents that posture and adds no deny entries beyond what the server already enforces.",
3+
"_comment": "The @modelcontextprotocol/server-postgres 'query' tool executes arbitrary SQL — it is NOT read-only by design. SQL-level restrictions (no DDL, no unguarded DML) cannot be enforced via the permissions system (which only blocks tool calls by name, not SQL content). Enforcement is via rules.md. The allow list restricts which tools Claude may call; write protection is behavioral, governed by rules.md.",
44
"allow": [
55
"mcp__postgres__query",
66
"mcp__postgres__list_tables",

mcp/postgres/rules.md

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,69 @@ globs: "**/*.sql,**/migrations/**,**/models/**,**/db/**"
55
# PostgreSQL MCP Rules
66

77
## Server posture
8-
The official postgres MCP server is read-only — it only executes SELECT queries.
9-
Use it for schema exploration and data inspection, not for mutations.
108

11-
## Safe operations (call freely)
9+
The official `@modelcontextprotocol/server-postgres` exposes a `query` tool that executes
10+
**arbitrary SQL** — SELECT, INSERT, UPDATE, DELETE, and DDL. It does NOT enforce read-only.
11+
The permissions system cannot block specific SQL patterns — it only blocks tool calls by name.
12+
SQL safety is entirely governed by these rules. Follow them without exception.
13+
14+
## Safe operations — call freely
15+
1216
- `list_tables`: enumerate schema
13-
- `describe_table`: inspect columns, types, constraints
14-
- `query`: SELECT statements only — the server enforces this
17+
- `describe_table`: inspect columns, types, constraints, indexes
18+
- `query` with SELECT: data inspection — no confirmation needed
19+
- Always add `LIMIT` when querying unknown table sizes (default: `LIMIT 100`)
20+
- Use explicit column lists — avoid `SELECT *` on wide tables
21+
- When exploring foreign keys, use `describe_table` first
22+
23+
## DML — confirm before executing
24+
25+
Before any INSERT, UPDATE, or DELETE:
26+
1. Show the complete SQL statement
27+
2. State the expected row count (run a SELECT COUNT WHERE first if unknown)
28+
3. State whether the operation is reversible (no transaction → not reversible)
29+
4. Wait for explicit user confirmation
30+
31+
**Never run UPDATE or DELETE without a WHERE clause.** If no WHERE clause is intended,
32+
say so explicitly and require double confirmation: "This will affect ALL rows in the table."
33+
34+
## DDL — hard stops
35+
36+
Never execute any of the following without the user typing the command explicitly
37+
(not just saying "yes, go ahead"):
1538

16-
## Query hygiene
17-
- Always add LIMIT when querying unknown table sizes (default: LIMIT 100)
18-
- Use explicit column lists in SELECT — avoid `SELECT *` on wide tables
19-
- When exploring foreign keys or relationships, use `describe_table` first
39+
- `DROP TABLE` / `DROP TABLE IF EXISTS`
40+
- `DROP DATABASE` / `DROP SCHEMA`
41+
- `TRUNCATE` / `TRUNCATE TABLE`
42+
- `ALTER TABLE ... DROP COLUMN`
43+
- `ALTER TABLE ... DROP CONSTRAINT`
2044

21-
## Mutations belong elsewhere
22-
For INSERT, UPDATE, DELETE, or DDL:
23-
- Use the Supabase MCP template if on Supabase (see mcp/supabase/)
24-
- Use local psql / migration tooling for schema changes
25-
- Never ask the user to "just run this in psql" without showing the full statement first
45+
For these operations: stop, show the full statement, explain the irreversibility, and
46+
instruct the user to run it manually via psql or their migration tool.
47+
48+
## Migrations
49+
50+
- Use SQL mutations through migration files, not through MCP `query` directly
51+
- Exception: exploratory SELECT queries and development seed data are fine via MCP
52+
- For schema changes in any non-local environment: stop and refer to migration tooling
2653

2754
## Environment awareness
28-
- Development DB: standard inspection workflow
29-
- Staging/production DB: always state which environment you are connecting to before any query
30-
- If DATABASE_URL points to production: treat even read operations as sensitive (may contain PII)
55+
56+
Before any DML or DDL, identify the environment from DATABASE_URL:
57+
58+
- **Local / development** (`localhost`, `127.0.0.1`, `*.local`): standard confirmation flow
59+
- **Staging** (`staging`, `stage`, `stg` in host or DB name): standard confirmation flow
60+
- **Production** (`prod`, `production`, `live`, or any RDS/Cloud SQL endpoint without clear staging marker):
61+
- Treat even SELECT as sensitive (may contain PII)
62+
- DML: stop and refuse — tell the user to run manually
63+
- DDL: always refuse
64+
- State the environment explicitly before every query: "Connecting to **PRODUCTION**"
65+
66+
If DATABASE_URL is ambiguous (no clear env marker), ask before any write operation.
67+
68+
## Connection pooling
69+
70+
If DATABASE_URL uses PgBouncer or similar pooler:
71+
- Avoid SET statements and advisory locks — they break under transaction pooling mode
72+
- Avoid multi-statement transactions in a single `query` call under session pooling
73+
- Prefer explicit single-statement queries

mcp/redis/permissions.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
"mcp__redis__flushdb",
2323
"mcp__redis__flushall",
2424
"mcp__redis__debug",
25-
"mcp__redis__config_resetstat"
25+
"mcp__redis__config_set",
26+
"mcp__redis__config_rewrite",
27+
"mcp__redis__config_resetstat",
28+
"mcp__redis__shutdown"
2629
]
2730
}

mcp/redis/rules.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ Before any SET, DEL, EXPIRE, XADD, or consumer group operation:
2828
4. Wait for explicit confirmation
2929

3030
## Hard stops (always denied)
31-
- `flushdb` / `flushall` — data destruction. Never call.
32-
- `debug` / `config resetstat` — operational risk.
31+
- `flushdb` / `flushall` — destroys all keys in DB or entire instance. Never call.
32+
- `config set` / `config rewrite` — runtime server config changes (maxmemory, bind, requirepass). Can permanently alter server behavior or expose the instance. Never call.
33+
- `shutdown` — terminates the Redis process. Never call.
34+
- `debug` / `config resetstat` — operational risk, no legitimate use case via MCP.
3335

3436
## Redis Streams guidance (SOMA pattern)
3537
- Use XADD with MAXLEN ~ N to prevent unbounded stream growth in high-frequency producers

mcp/slack/permissions.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
{
22
"_template": "claude-kit/mcp/slack",
3-
"_comment": "Read operations auto-allowed. Sending messages requires user prompt — messages sent via bot are visible to the whole channel/recipient.",
3+
"_comment": "Read operations auto-allowed. Sending, editing, and reacting to messages requires user prompt — actions are visible to other users. Destructive and administrative operations always denied.",
44
"allow": [
55
"mcp__slack__list_channels",
66
"mcp__slack__get_channel_history",
77
"mcp__slack__get_thread_replies",
88
"mcp__slack__search_messages",
99
"mcp__slack__get_users",
10-
"mcp__slack__get_user_profile"
10+
"mcp__slack__get_user_profile",
11+
"mcp__slack__add_reaction"
1112
],
1213
"deny": [
1314
"mcp__slack__delete_message",
14-
"mcp__slack__kick_user_from_channel"
15+
"mcp__slack__update_message",
16+
"mcp__slack__kick_user_from_channel",
17+
"mcp__slack__archive_channel",
18+
"mcp__slack__set_channel_purpose",
19+
"mcp__slack__set_channel_topic"
1520
]
1621
}

mcp/slack/rules.md

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,60 @@ globs: "**/*"
44

55
# Slack MCP Rules
66

7-
## Read operations (call freely)
8-
- `list_channels`, `get_channel_history`, `get_thread_replies`: message inspection
7+
## Read operations — call freely
8+
- `list_channels`: workspace channel index
9+
- `get_channel_history`: recent messages in a channel
10+
- `get_thread_replies`: thread inspection
911
- `search_messages`: find relevant discussions
1012
- `get_users`, `get_user_profile`: team directory lookup
1113

12-
## Sending messages — always show draft first
14+
## Sending messages — show draft first
15+
1316
Before calling `post_message` or `reply_to_thread`:
1417
1. Show the full message text as a draft
15-
2. Confirm the target channel or thread
16-
3. Wait for explicit approval — sent messages are visible to others and cannot be unsent easily
18+
2. Confirm the target channel or thread (name + ID)
19+
3. Wait for explicit approval — sent messages are immediately visible to others
20+
21+
Before `add_reaction`: state the emoji and target message. Reactions are visible and
22+
accumulate — don't add reactions automatically without user intent.
1723

1824
## Format and tone
1925
- Never add emojis unless the user includes them in the draft
20-
- Never use @here or @channel in automated messages without explicit instruction
21-
- Keep automated/bot messages clearly distinguishable from human messages
26+
- Never use `@here`, `@channel`, or `@everyone` in automated messages without explicit instruction
27+
- Bot messages must be distinguishable from human messages — never impersonate a user
28+
- Markdown formatting (bold, code blocks) is acceptable; decorative formatting is not
29+
30+
## Editing messages
31+
32+
`update_message` is denied by default. If re-enabled:
33+
- Only edit bot-authored messages — never edit messages posted by a human user
34+
- Show the before/after diff before calling
35+
- Require explicit user approval
2236

2337
## Privacy
38+
2439
- Do not log or store message content from `get_channel_history` beyond the current task
25-
- Do not share content from private channels in responses unless directly relevant to the task
26-
- User profiles may contain personal info — use only for context, never expose unnecessarily
40+
- Private channels (`is_private: true`): only read if the user explicitly navigated to them —
41+
do not proactively scan private channels during workspace exploration
42+
- User profiles may contain personal info (phone, email, timezone) — use only for
43+
task context, never surface unnecessarily
44+
- Never forward channel content to external services during an MCP session
2745

2846
## Hard stops
29-
- `delete_message`: only on bot-authored messages. Never delete messages from other users.
30-
- `kick_user_from_channel`: always denied — administrative actions belong in the Slack UI.
47+
48+
- `delete_message`: denied by default. If re-enabled, only on bot-authored messages,
49+
require explicit confirmation, and never delete in bulk.
50+
- `update_message`: denied by default (editing messages from others is irreversible from
51+
the recipient's perspective).
52+
- `kick_user_from_channel`: always denied — administrative actions belong in the Slack UI
53+
or via the Slack admin API with proper audit trail.
54+
- `archive_channel`: always denied — permanently removes a channel from active use.
55+
Requires workspace admin review.
56+
- `set_channel_purpose` / `set_channel_topic`: always denied — channel metadata changes
57+
affect all members and should be intentional, not side effects of an automated session.
58+
59+
## Channel scope
60+
61+
When asked to "check Slack" or "look at Slack", default to the channels the user
62+
explicitly names. Do not iterate over all channels or read channel history broadly.
63+
Ask: "Which channel(s) should I check?"

mcp/supabase/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
22
"_template": "claude-kit/mcp/supabase",
3-
"_verified_with": "@supabase/mcp-server-supabase@0.x",
3+
"_verified_with": "@supabase/mcp-server-supabase@0.7.0",
44
"_install": "Merge the 'supabase' key into mcpServers in ~/.claude/settings.json. Set SUPABASE_ACCESS_TOKEN env var (create at supabase.com/dashboard/account/tokens).",
55
"_note": "This template uses the Supabase management API server, which operates on projects and their schema. For direct SQL on a specific project, combine with mcp/postgres/ using the project's DATABASE_URL.",
6+
"_read_only_variant": "For production read-only access, add '--read-only' to args. This restricts the server to non-destructive operations only.",
67
"supabase": {
78
"type": "stdio",
89
"command": "npx",

mcp/supabase/rules.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,19 @@ Any operation that modifies schema or data requires showing the full operation a
3535
- When creating or modifying tables, always ask: "Should this table have Row Level Security enabled?"
3636
- Never disable RLS on an existing table without explicit user instruction
3737
- Review Edge Function code for secrets before deploying — never log tokens or keys
38+
39+
## Read-only mode for production
40+
41+
The server supports a `--read-only` flag that restricts it to non-destructive operations.
42+
Recommended pattern:
43+
44+
- **Development/staging config**: use the standard template (no `--read-only`)
45+
- **Production config**: add `"--read-only"` to the `args` array in mcpServers
46+
47+
```json
48+
"args": ["-y", "@supabase/mcp-server-supabase@0.7.0", "--access-token", "${SUPABASE_ACCESS_TOKEN}", "--read-only"]
49+
```
50+
51+
With `--read-only`, `apply_migration`, `execute_sql` (writes), `create_branch`, and
52+
`merge_branch` are unavailable at the server level — not just behavioral restrictions.
53+
Use this as a hard enforcement layer for production access tokens.

0 commit comments

Comments
 (0)