spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

Add mcp-context-warning plugin to warn about high MCP context usageBrowse files
This plugin warns users when their MCP servers are consuming significant
context (>20k tokens). Many users don't realize MCP servers take up context
space, which can lead to unexpectedly fast context exhaustion.

The plugin:
- Runs a SessionStart hook to check MCP configurations
- Estimates token usage based on server and tool counts
- Shows a warning with server breakdown if estimated usage > 20k tokens
- Provides guidance on how to disable unused MCP servers

Slack thread: https://anthropic.slack.com/archives/C07VBSHV7EV/p1765989316572149
Claude authored on Dec 17, 2025 parent 4392352 · commit cad256936034
4 changed files+201 -0compared with 4392352
M.claude-plugin/marketplace.json
Aplugins/mcp-context-warning/.claude-plugin/plugin.json
Aplugins/mcp-context-warning/hooks/check_mcp_context.py
Aplugins/mcp-context-warning/hooks/hooks.json
@@ -103,6 +103,17 @@
103103 "category": "learning"
104104 },
105105 {
106+ "name": "mcp-context-warning",
107+ "description": "Warns users when MCP servers are consuming significant context (>20k tokens), helping prevent unexpected context exhaustion",
108+ "version": "1.0.0",
109+ "author": {
110+ "name": "Anthropic",
111+ "email": "support@anthropic.com"
112+ },
113+ "source": "./plugins/mcp-context-warning",
114+ "category": "productivity"
115+ },
116+ {
106117 "name": "plugin-dev",
107118 "description": "Comprehensive toolkit for developing Claude Code plugins. Includes 7 expert skills covering hooks, MCP integration, commands, agents, and best practices. AI-assisted plugin creation and validation.",
108119 "version": "0.1.0",
@@ -1,0 +1,9 @@
1+{
2+ "name": "mcp-context-warning",
3+ "version": "1.0.0",
4+ "description": "Warns users when MCP servers are consuming significant context (>20k tokens), helping prevent unexpected context exhaustion",
5+ "author": {
6+ "name": "Anthropic",
7+ "email": "support@anthropic.com"
8+ }
9+}
@@ -1,0 +1,164 @@
1+#!/usr/bin/env python3
2+"""
3+MCP Context Warning Hook for Claude Code
4+
5+This hook runs at session start and warns users when their MCP servers
6+are consuming significant context (>20k tokens). This helps users understand
7+why they might be burning through context quickly.
8+"""
9+
10+import json
11+import os
12+import sys
13+from pathlib import Path
14+
15+# Threshold in tokens for showing a warning
16+TOKEN_WARNING_THRESHOLD = 20000
17+
18+# Estimated tokens per MCP tool (based on real-world data:
19+# Asana: ~836/tool, Gmail: ~833/tool, Google Calendar: ~1867/tool, Google Drive: ~1260/tool)
20+# Using 1000 as a conservative average
21+TOKENS_PER_TOOL_ESTIMATE = 1000
22+
23+# Base overhead per MCP server (connection info, auth, etc.)
24+BASE_TOKENS_PER_SERVER = 500
25+
26+
27+def find_mcp_configs(cwd: str) -> list[tuple[str, dict]]:
28+ """
29+ Find all MCP configuration files that might be loaded.
30+
31+ Returns list of (path, config) tuples.
32+ """
33+ configs = []
34+
35+ # Check project-level .mcp.json
36+ project_mcp = Path(cwd) / ".mcp.json"
37+ if project_mcp.exists():
38+ try:
39+ with open(project_mcp) as f:
40+ configs.append((str(project_mcp), json.load(f)))
41+ except (json.JSONDecodeError, IOError):
42+ pass
43+
44+ # Check user-level MCP config (~/.claude/.mcp.json)
45+ user_mcp = Path.home() / ".claude" / ".mcp.json"
46+ if user_mcp.exists():
47+ try:
48+ with open(user_mcp) as f:
49+ configs.append((str(user_mcp), json.load(f)))
50+ except (json.JSONDecodeError, IOError):
51+ pass
52+
53+ return configs
54+
55+
56+def count_servers_and_estimate_tools(configs: list[tuple[str, dict]]) -> tuple[dict, int]:
57+ """
58+ Count MCP servers and estimate their tool counts.
59+
60+ Returns (server_info dict, total_estimated_tokens).
61+ """
62+ server_info = {}
63+
64+ for path, config in configs:
65+ # MCP config format: {"mcpServers": {"server-name": {...}}}
66+ mcp_servers = config.get("mcpServers", {})
67+
68+ for server_name, server_config in mcp_servers.items():
69+ if server_name in server_info:
70+ continue # Skip duplicates
71+
72+ # Try to get tool count from config if available
73+ # Otherwise use a default estimate
74+ tool_count = server_config.get("toolCount", 10) # Default 10 tools
75+
76+ server_info[server_name] = {
77+ "source": path,
78+ "estimated_tools": tool_count,
79+ }
80+
81+ # Calculate total estimated tokens
82+ total_tokens = 0
83+ for server_name, info in server_info.items():
84+ server_tokens = BASE_TOKENS_PER_SERVER + (info["estimated_tools"] * TOKENS_PER_TOOL_ESTIMATE)
85+ info["estimated_tokens"] = server_tokens
86+ total_tokens += server_tokens
87+
88+ return server_info, total_tokens
89+
90+
91+def format_warning_message(server_info: dict, total_tokens: int) -> str:
92+ """Format a warning message about MCP context usage."""
93+
94+ # Build server breakdown table
95+ lines = [
96+ f"Your MCP servers are using an estimated ~{total_tokens:,} tokens of context.",
97+ "",
98+ "Server breakdown:",
99+ ]
100+
101+ # Sort servers by token usage (highest first)
102+ sorted_servers = sorted(
103+ server_info.items(),
104+ key=lambda x: x[1]["estimated_tokens"],
105+ reverse=True
106+ )
107+
108+ for server_name, info in sorted_servers:
109+ tokens = info["estimated_tokens"]
110+ tools = info["estimated_tools"]
111+ lines.append(f" - {server_name}: ~{tokens:,} tokens ({tools} tools)")
112+
113+ lines.extend([
114+ "",
115+ "Consider disabling MCP servers you're not actively using to conserve context.",
116+ "You can manage MCP servers with `/mcp disable <server-name>` or by editing .mcp.json.",
117+ ])
118+
119+ return "\n".join(lines)
120+
121+
122+def main():
123+ """Main hook function."""
124+ # Read input from stdin
125+ try:
126+ raw_input = sys.stdin.read()
127+ input_data = json.loads(raw_input) if raw_input.strip() else {}
128+ except json.JSONDecodeError:
129+ # If we can't parse input, exit silently
130+ sys.exit(0)
131+
132+ # Get current working directory from hook input or environment
133+ cwd = input_data.get("cwd", os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd()))
134+
135+ # Find MCP configurations
136+ configs = find_mcp_configs(cwd)
137+
138+ if not configs:
139+ # No MCP configs found, nothing to warn about
140+ sys.exit(0)
141+
142+ # Count servers and estimate tokens
143+ server_info, total_tokens = count_servers_and_estimate_tools(configs)
144+
145+ if not server_info:
146+ # No servers configured
147+ sys.exit(0)
148+
149+ # Check if we're over the warning threshold
150+ if total_tokens >= TOKEN_WARNING_THRESHOLD:
151+ warning_message = format_warning_message(server_info, total_tokens)
152+
153+ # Output JSON with systemMessage for Claude to see
154+ output = {
155+ "continue": True,
156+ "systemMessage": warning_message
157+ }
158+ print(json.dumps(output))
159+
160+ sys.exit(0)
161+
162+
163+if __name__ == "__main__":
164+ main()
@@ -1,0 +1,17 @@
1+{
2+ "description": "Warns users when MCP servers consume significant context (>20k tokens)",
3+ "hooks": {
4+ "SessionStart": [
5+ {
6+ "matcher": "*",
7+ "hooks": [
8+ {
9+ "type": "command",
10+ "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/check_mcp_context.py",
11+ "timeout": 10
12+ }
13+ ]
14+ }
15+ ]
16+ }
17+}