stravinsky 0.2.38__py3-none-any.whl → 0.2.52__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of stravinsky might be problematic. Click here for more details.
- mcp_bridge/__init__.py +1 -1
- mcp_bridge/auth/token_refresh.py +130 -0
- mcp_bridge/hooks/__init__.py +18 -1
- mcp_bridge/hooks/manager.py +50 -0
- mcp_bridge/hooks/parallel_enforcer.py +127 -0
- mcp_bridge/hooks/pre_compact.py +224 -0
- mcp_bridge/hooks/preemptive_compaction.py +81 -7
- mcp_bridge/hooks/session_idle.py +116 -0
- mcp_bridge/native_hooks/todo_delegation.py +54 -0
- mcp_bridge/prompts/__init__.py +3 -1
- mcp_bridge/prompts/dewey.py +30 -20
- mcp_bridge/prompts/explore.py +46 -8
- mcp_bridge/prompts/planner.py +222 -0
- mcp_bridge/prompts/stravinsky.py +107 -28
- mcp_bridge/server.py +64 -9
- mcp_bridge/server_tools.py +159 -32
- mcp_bridge/tools/agent_manager.py +199 -111
- mcp_bridge/tools/background_tasks.py +2 -1
- mcp_bridge/tools/model_invoke.py +194 -46
- {stravinsky-0.2.38.dist-info → stravinsky-0.2.52.dist-info}/METADATA +1 -1
- {stravinsky-0.2.38.dist-info → stravinsky-0.2.52.dist-info}/RECORD +23 -17
- {stravinsky-0.2.38.dist-info → stravinsky-0.2.52.dist-info}/WHEEL +0 -0
- {stravinsky-0.2.38.dist-info → stravinsky-0.2.52.dist-info}/entry_points.txt +0 -0
|
@@ -4,7 +4,7 @@ Preemptive Context Compaction Hook.
|
|
|
4
4
|
Proactively compresses context BEFORE hitting limits by:
|
|
5
5
|
- Tracking estimated token usage
|
|
6
6
|
- Triggering compaction at 70% capacity (not waiting for errors)
|
|
7
|
-
- Using DCP -> Truncate -> Summarize pipeline
|
|
7
|
+
- Using DCP -> Truncate -> Summarize pipeline with gemini-3-flash
|
|
8
8
|
- Registered as pre_model_invoke hook
|
|
9
9
|
"""
|
|
10
10
|
|
|
@@ -14,6 +14,9 @@ from typing import Any, Dict, Optional
|
|
|
14
14
|
|
|
15
15
|
logger = logging.getLogger(__name__)
|
|
16
16
|
|
|
17
|
+
# Flag to prevent recursive summarization calls
|
|
18
|
+
_in_summarization = False
|
|
19
|
+
|
|
17
20
|
# Token estimation constants
|
|
18
21
|
CHARS_PER_TOKEN = 4 # Rough estimate for English text
|
|
19
22
|
MAX_CONTEXT_TOKENS = 200000 # Claude's context window
|
|
@@ -112,6 +115,60 @@ CRITICAL_WARNING = """
|
|
|
112
115
|
> 3. Reference TASK_STATE.md in new session for continuity
|
|
113
116
|
"""
|
|
114
117
|
|
|
118
|
+
SUMMARIZATION_PROMPT = """Summarize the following context concisely while preserving:
|
|
119
|
+
1. Key technical decisions and their rationale
|
|
120
|
+
2. Important code patterns and file paths mentioned
|
|
121
|
+
3. Current task state and pending items
|
|
122
|
+
4. Any errors or warnings that need attention
|
|
123
|
+
|
|
124
|
+
Keep the summary under 2000 characters. Use bullet points for clarity.
|
|
125
|
+
|
|
126
|
+
CONTEXT TO SUMMARIZE:
|
|
127
|
+
{content}"""
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
async def summarize_with_gemini(token_store: Any, content: str) -> str:
|
|
131
|
+
"""
|
|
132
|
+
Use gemini-3-flash to summarize context for compaction.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
token_store: Token store for Gemini authentication
|
|
136
|
+
content: The content to summarize
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Summarized content or original if summarization fails
|
|
140
|
+
"""
|
|
141
|
+
global _in_summarization
|
|
142
|
+
|
|
143
|
+
if not token_store:
|
|
144
|
+
logger.warning("[PreemptiveCompaction] No token_store available, skipping summarization")
|
|
145
|
+
return content
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
# Import here to avoid circular imports
|
|
149
|
+
from mcp_bridge.tools.model_invoke import invoke_gemini
|
|
150
|
+
|
|
151
|
+
_in_summarization = True
|
|
152
|
+
|
|
153
|
+
prompt = SUMMARIZATION_PROMPT.format(content=content[:50000]) # Limit input size
|
|
154
|
+
|
|
155
|
+
summary = await invoke_gemini(
|
|
156
|
+
token_store=token_store,
|
|
157
|
+
prompt=prompt,
|
|
158
|
+
model="gemini-3-flash",
|
|
159
|
+
max_tokens=2000,
|
|
160
|
+
temperature=0.3,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
logger.info(f"[PreemptiveCompaction] Summarized {len(content)} chars -> {len(summary)} chars")
|
|
164
|
+
return summary
|
|
165
|
+
|
|
166
|
+
except Exception as e:
|
|
167
|
+
logger.error(f"[PreemptiveCompaction] Summarization failed: {e}")
|
|
168
|
+
return content # Fall back to original content
|
|
169
|
+
finally:
|
|
170
|
+
_in_summarization = False
|
|
171
|
+
|
|
115
172
|
|
|
116
173
|
async def preemptive_compaction_hook(params: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
117
174
|
"""
|
|
@@ -119,11 +176,18 @@ async def preemptive_compaction_hook(params: Dict[str, Any]) -> Optional[Dict[st
|
|
|
119
176
|
|
|
120
177
|
Uses a multi-tier strategy:
|
|
121
178
|
- Below 70%: No action
|
|
122
|
-
- 70-85%: Apply DCP truncation
|
|
123
|
-
- Above 85%: Apply aggressive truncation
|
|
179
|
+
- 70-85%: Apply DCP truncation + gemini-3-flash summarization
|
|
180
|
+
- Above 85%: Apply aggressive truncation + gemini-3-flash summarization
|
|
124
181
|
"""
|
|
182
|
+
global _in_summarization
|
|
183
|
+
|
|
184
|
+
# Prevent recursive calls (when this hook triggers summarization via gemini)
|
|
185
|
+
if _in_summarization:
|
|
186
|
+
return None
|
|
187
|
+
|
|
125
188
|
prompt = params.get("prompt", "")
|
|
126
189
|
prompt_length = len(prompt)
|
|
190
|
+
token_store = params.get("token_store") # May be None if not provided
|
|
127
191
|
|
|
128
192
|
# Skip if already optimized recently
|
|
129
193
|
if "[PREEMPTIVE CONTEXT OPTIMIZATION]" in prompt or "[CRITICAL - CONTEXT WINDOW" in prompt:
|
|
@@ -132,25 +196,35 @@ async def preemptive_compaction_hook(params: Dict[str, Any]) -> Optional[Dict[st
|
|
|
132
196
|
usage = calculate_usage_percentage(prompt)
|
|
133
197
|
|
|
134
198
|
if prompt_length >= WARNING_CHAR_THRESHOLD:
|
|
135
|
-
# Critical level - aggressive truncation
|
|
199
|
+
# Critical level - aggressive truncation + summarization
|
|
136
200
|
logger.warning(f"[PreemptiveCompaction] Critical context usage: {usage:.1f}%")
|
|
137
201
|
|
|
138
202
|
truncated = apply_dcp_truncation(prompt, target_reduction=0.4)
|
|
203
|
+
|
|
204
|
+
# Use gemini-3-flash to summarize the truncated middle section
|
|
205
|
+
if token_store:
|
|
206
|
+
truncated = await summarize_with_gemini(token_store, truncated)
|
|
207
|
+
|
|
139
208
|
notice = CRITICAL_WARNING.format(usage=usage)
|
|
140
209
|
params["prompt"] = notice + truncated
|
|
141
210
|
|
|
142
|
-
logger.info(f"[PreemptiveCompaction] Applied aggressive
|
|
211
|
+
logger.info(f"[PreemptiveCompaction] Applied aggressive compaction: {len(prompt)} -> {len(truncated)} chars")
|
|
143
212
|
return params
|
|
144
213
|
|
|
145
214
|
elif prompt_length >= PREEMPTIVE_CHAR_THRESHOLD:
|
|
146
|
-
# Preemptive level - moderate truncation
|
|
215
|
+
# Preemptive level - moderate truncation + summarization
|
|
147
216
|
logger.info(f"[PreemptiveCompaction] Preemptive compaction at {usage:.1f}%")
|
|
148
217
|
|
|
149
218
|
truncated = apply_dcp_truncation(prompt, target_reduction=0.3)
|
|
219
|
+
|
|
220
|
+
# Use gemini-3-flash to summarize the truncated content
|
|
221
|
+
if token_store:
|
|
222
|
+
truncated = await summarize_with_gemini(token_store, truncated)
|
|
223
|
+
|
|
150
224
|
notice = PREEMPTIVE_COMPACTION_NOTICE.format(usage=usage)
|
|
151
225
|
params["prompt"] = notice + truncated
|
|
152
226
|
|
|
153
|
-
logger.info(f"[PreemptiveCompaction] Applied moderate
|
|
227
|
+
logger.info(f"[PreemptiveCompaction] Applied moderate compaction: {len(prompt)} -> {len(truncated)} chars")
|
|
154
228
|
return params
|
|
155
229
|
|
|
156
230
|
# Below threshold, no action needed
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Session Idle Hook - Stop Hook Implementation.
|
|
3
|
+
|
|
4
|
+
Detects when session becomes idle with incomplete todos and injects
|
|
5
|
+
a continuation prompt to force task completion.
|
|
6
|
+
|
|
7
|
+
Based on oh-my-opencode's todo-continuation-enforcer pattern.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from typing import Any, Dict, Optional
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
# Continuation prompt injected when session is idle with incomplete todos
|
|
16
|
+
TODO_CONTINUATION_PROMPT = """
|
|
17
|
+
[SYSTEM REMINDER - TODO CONTINUATION]
|
|
18
|
+
|
|
19
|
+
You have incomplete tasks in your todo list. Continue working on the next pending task.
|
|
20
|
+
|
|
21
|
+
RULES:
|
|
22
|
+
- Proceed immediately without asking for permission
|
|
23
|
+
- Mark the current task as in_progress before starting
|
|
24
|
+
- Mark each task complete when finished
|
|
25
|
+
- Do NOT stop until all tasks are done
|
|
26
|
+
- If blocked, create a new task describing what needs to be resolved
|
|
27
|
+
|
|
28
|
+
STATUS CHECK:
|
|
29
|
+
Use TodoWrite to check your current task status and continue with the next pending item.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
# Track sessions to prevent duplicate injections
|
|
33
|
+
_idle_sessions: Dict[str, bool] = {}
|
|
34
|
+
_last_activity: Dict[str, float] = {}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def session_idle_hook(params: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
38
|
+
"""
|
|
39
|
+
Pre-model-invoke hook that detects idle sessions with incomplete todos.
|
|
40
|
+
|
|
41
|
+
Checks if:
|
|
42
|
+
1. The conversation has pending todos
|
|
43
|
+
2. The session has been idle (no recent tool calls)
|
|
44
|
+
3. A continuation hasn't already been injected
|
|
45
|
+
|
|
46
|
+
If all conditions met, injects TODO_CONTINUATION_PROMPT.
|
|
47
|
+
"""
|
|
48
|
+
import time
|
|
49
|
+
|
|
50
|
+
prompt = params.get("prompt", "")
|
|
51
|
+
session_id = params.get("session_id", "default")
|
|
52
|
+
|
|
53
|
+
# Skip if already contains continuation reminder
|
|
54
|
+
if "[SYSTEM REMINDER - TODO CONTINUATION]" in prompt:
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
# Skip if this is a fresh prompt (user just typed something)
|
|
58
|
+
if params.get("is_user_message", False):
|
|
59
|
+
_last_activity[session_id] = time.time()
|
|
60
|
+
_idle_sessions[session_id] = False
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
# Check for pending todos in the prompt/context
|
|
64
|
+
has_pending_todos = _detect_pending_todos(prompt)
|
|
65
|
+
|
|
66
|
+
if not has_pending_todos:
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
# Check idle threshold (2 seconds of no activity)
|
|
70
|
+
current_time = time.time()
|
|
71
|
+
last_activity = _last_activity.get(session_id, current_time)
|
|
72
|
+
idle_seconds = current_time - last_activity
|
|
73
|
+
|
|
74
|
+
if idle_seconds < 2.0:
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
# Check if already injected for this idle period
|
|
78
|
+
if _idle_sessions.get(session_id, False):
|
|
79
|
+
return None
|
|
80
|
+
|
|
81
|
+
# Mark as injected and inject continuation
|
|
82
|
+
_idle_sessions[session_id] = True
|
|
83
|
+
logger.info(f"[SessionIdleHook] Injecting TODO continuation for session {session_id}")
|
|
84
|
+
|
|
85
|
+
modified_prompt = prompt + "\n\n" + TODO_CONTINUATION_PROMPT
|
|
86
|
+
|
|
87
|
+
return {**params, "prompt": modified_prompt}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _detect_pending_todos(prompt: str) -> bool:
|
|
91
|
+
"""
|
|
92
|
+
Detect if there are pending todos in the conversation.
|
|
93
|
+
|
|
94
|
+
Looks for patterns like:
|
|
95
|
+
- [pending] or status: pending
|
|
96
|
+
- TodoWrite with pending items
|
|
97
|
+
- Incomplete task lists
|
|
98
|
+
"""
|
|
99
|
+
pending_patterns = [
|
|
100
|
+
"[pending]",
|
|
101
|
+
"status: pending",
|
|
102
|
+
'"status": "pending"',
|
|
103
|
+
"pending tasks",
|
|
104
|
+
"incomplete tasks",
|
|
105
|
+
"remaining todos",
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
prompt_lower = prompt.lower()
|
|
109
|
+
return any(pattern.lower() in prompt_lower for pattern in pending_patterns)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def reset_session(session_id: str = "default"):
|
|
113
|
+
"""Reset idle state for a session (call when user provides new input)."""
|
|
114
|
+
_idle_sessions[session_id] = False
|
|
115
|
+
import time
|
|
116
|
+
_last_activity[session_id] = time.time()
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
PostToolUse hook for TodoWrite: Enforces parallel delegation.
|
|
4
|
+
|
|
5
|
+
After TodoWrite is called, this hook injects a reminder to spawn
|
|
6
|
+
parallel Task agents for all independent TODOs.
|
|
7
|
+
"""
|
|
8
|
+
import json
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def main():
|
|
13
|
+
# Read hook input from stdin
|
|
14
|
+
try:
|
|
15
|
+
hook_input = json.load(sys.stdin)
|
|
16
|
+
except (json.JSONDecodeError, EOFError):
|
|
17
|
+
return 0
|
|
18
|
+
|
|
19
|
+
tool_name = hook_input.get("tool_name", "")
|
|
20
|
+
|
|
21
|
+
if tool_name != "TodoWrite":
|
|
22
|
+
return 0
|
|
23
|
+
|
|
24
|
+
# Get the todos that were just written
|
|
25
|
+
tool_input = hook_input.get("tool_input", {})
|
|
26
|
+
todos = tool_input.get("todos", [])
|
|
27
|
+
|
|
28
|
+
# Count pending todos
|
|
29
|
+
pending_count = sum(1 for t in todos if t.get("status") == "pending")
|
|
30
|
+
|
|
31
|
+
if pending_count < 2:
|
|
32
|
+
return 0
|
|
33
|
+
|
|
34
|
+
# Output the parallel delegation reminder
|
|
35
|
+
reminder = f"""
|
|
36
|
+
[PARALLEL DELEGATION REQUIRED]
|
|
37
|
+
|
|
38
|
+
You just created {pending_count} pending TODOs. Before your NEXT response:
|
|
39
|
+
|
|
40
|
+
1. Identify which TODOs are INDEPENDENT (can run simultaneously)
|
|
41
|
+
2. For EACH independent TODO, spawn a Task agent:
|
|
42
|
+
Task(subagent_type="Explore", prompt="[TODO details]", run_in_background=true)
|
|
43
|
+
3. Fire ALL Task calls in ONE response - do NOT wait between them
|
|
44
|
+
4. Do NOT mark any TODO as in_progress until agents return
|
|
45
|
+
|
|
46
|
+
WRONG: Create TODO list -> Mark TODO 1 in_progress -> Work -> Complete -> Repeat
|
|
47
|
+
CORRECT: Create TODO list -> Spawn Task for each -> Collect results -> Mark complete
|
|
48
|
+
"""
|
|
49
|
+
print(reminder)
|
|
50
|
+
return 0
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __name__ == "__main__":
|
|
54
|
+
sys.exit(main())
|
mcp_bridge/prompts/__init__.py
CHANGED
|
@@ -6,13 +6,15 @@ from . import explore
|
|
|
6
6
|
from . import frontend
|
|
7
7
|
from . import document_writer
|
|
8
8
|
from . import multimodal
|
|
9
|
+
from . import planner
|
|
9
10
|
|
|
10
11
|
__all__ = [
|
|
11
12
|
"stravinsky",
|
|
12
|
-
"delphi",
|
|
13
|
+
"delphi",
|
|
13
14
|
"dewey",
|
|
14
15
|
"explore",
|
|
15
16
|
"frontend",
|
|
16
17
|
"document_writer",
|
|
17
18
|
"multimodal",
|
|
19
|
+
"planner",
|
|
18
20
|
]
|
mcp_bridge/prompts/dewey.py
CHANGED
|
@@ -50,8 +50,8 @@ Classify EVERY request into one of these categories before taking action:
|
|
|
50
50
|
|
|
51
51
|
| Type | Trigger Examples | Tools |
|
|
52
52
|
|------|------------------|-------|
|
|
53
|
-
| **TYPE A: CONCEPTUAL** | "How do I use X?", "Best practice for Y?" |
|
|
54
|
-
| **TYPE B: IMPLEMENTATION** | "How does X implement Y?", "Show me source of Z" | gh clone + read + blame |
|
|
53
|
+
| **TYPE A: CONCEPTUAL** | "How do I use X?", "Best practice for Y?" | exa websearch + grep-app GitHub search (parallel) |
|
|
54
|
+
| **TYPE B: IMPLEMENTATION** | "How does X implement Y?", "Show me source of Z" | gh clone + ast-grep + read + blame |
|
|
55
55
|
| **TYPE C: CONTEXT** | "Why was this changed?", "History of X?" | gh issues/prs + git log/blame |
|
|
56
56
|
| **TYPE D: COMPREHENSIVE** | Complex/ambiguous requests | ALL tools in parallel |
|
|
57
57
|
|
|
@@ -64,12 +64,15 @@ Classify EVERY request into one of these categories before taking action:
|
|
|
64
64
|
|
|
65
65
|
**Execute in parallel (3+ calls)**:
|
|
66
66
|
```
|
|
67
|
-
Tool 1:
|
|
68
|
-
|
|
69
|
-
Tool
|
|
67
|
+
Tool 1: mcp__MCP_DOCKER__web_search_exa(query="library-name topic 2026", num_results=5)
|
|
68
|
+
-> Current articles, blog posts, best practices (ALWAYS use Exa instead of native WebSearch)
|
|
69
|
+
Tool 2: mcp__grep-app__searchCode(query="library-name implementation pattern")
|
|
70
|
+
-> Real GitHub code examples with permalinks
|
|
71
|
+
Tool 3: gh search repos "library-name" --sort stars --limit 5
|
|
72
|
+
-> Popular repositories for reference
|
|
70
73
|
```
|
|
71
74
|
|
|
72
|
-
**Output**:
|
|
75
|
+
**Output**: Synthesize with evidence links (Exa URLs + GitHub permalinks).
|
|
73
76
|
|
|
74
77
|
---
|
|
75
78
|
|
|
@@ -85,8 +88,8 @@ Step 2: Get commit SHA for permalinks
|
|
|
85
88
|
cd ${TMPDIR:-/tmp}/repo-name && git rev-parse HEAD
|
|
86
89
|
|
|
87
90
|
Step 3: Find the implementation
|
|
88
|
-
-
|
|
89
|
-
-
|
|
91
|
+
- mcp__ast-grep__find_code(pattern="function $NAME", language="typescript") for structural search
|
|
92
|
+
- grep_search for function/class names
|
|
90
93
|
- Read the specific file
|
|
91
94
|
- git blame for context if needed
|
|
92
95
|
|
|
@@ -97,9 +100,9 @@ Step 4: Construct permalink
|
|
|
97
100
|
**Parallel acceleration (4+ calls)**:
|
|
98
101
|
```
|
|
99
102
|
Tool 1: gh repo clone owner/repo ${TMPDIR:-/tmp}/repo -- --depth 1
|
|
100
|
-
Tool 2:
|
|
103
|
+
Tool 2: mcp__grep-app__searchCode(query="repo:owner/repo function_name")
|
|
101
104
|
Tool 3: gh api repos/owner/repo/commits/HEAD --jq '.sha'
|
|
102
|
-
Tool 4:
|
|
105
|
+
Tool 4: mcp__MCP_DOCKER__web_search_exa(query="library-name function_name documentation 2026")
|
|
103
106
|
```
|
|
104
107
|
|
|
105
108
|
---
|
|
@@ -131,13 +134,15 @@ gh api repos/owner/repo/pulls/<number>/files
|
|
|
131
134
|
|
|
132
135
|
**Execute ALL in parallel (6+ calls)**:
|
|
133
136
|
```
|
|
134
|
-
//
|
|
135
|
-
Tool 1:
|
|
136
|
-
Tool 2: Web search ("topic recent updates 2025")
|
|
137
|
+
// Web Search (ALWAYS use Exa)
|
|
138
|
+
Tool 1: mcp__MCP_DOCKER__web_search_exa(query="topic recent updates 2026", num_results=10)
|
|
137
139
|
|
|
138
|
-
// Code Search
|
|
139
|
-
Tool
|
|
140
|
-
Tool
|
|
140
|
+
// GitHub Code Search
|
|
141
|
+
Tool 2: mcp__grep-app__searchCode(query="topic implementation pattern")
|
|
142
|
+
Tool 3: mcp__grep-app__searchCode(query="topic usage example")
|
|
143
|
+
|
|
144
|
+
// AST Pattern Search
|
|
145
|
+
Tool 4: mcp__ast-grep__find_code(pattern="$PATTERN", language="typescript")
|
|
141
146
|
|
|
142
147
|
// Source Analysis
|
|
143
148
|
Tool 5: gh repo clone owner/repo ${TMPDIR:-/tmp}/repo -- --depth 1
|
|
@@ -182,15 +187,20 @@ https://github.com/tanstack/query/blob/abc123def/packages/react-query/src/useQue
|
|
|
182
187
|
|
|
183
188
|
---
|
|
184
189
|
|
|
185
|
-
## TOOL REFERENCE (Stravinsky Tools)
|
|
190
|
+
## TOOL REFERENCE (Stravinsky + MCP DOCKER Tools)
|
|
186
191
|
|
|
187
192
|
### Primary Tools by Purpose
|
|
188
193
|
|
|
189
194
|
| Purpose | Tool | Usage |
|
|
190
195
|
|---------|------|-------|
|
|
191
|
-
| **
|
|
192
|
-
| **
|
|
193
|
-
| **File
|
|
196
|
+
| **Web Search** | `mcp__MCP_DOCKER__web_search_exa` | **ALWAYS use instead of native WebSearch** - Real-time web search for current articles, docs, tutorials |
|
|
197
|
+
| **GitHub Code Search** | `mcp__grep-app__searchCode` | Search across public GitHub repositories - returns permalinks |
|
|
198
|
+
| **GitHub File Fetch** | `mcp__grep-app__github_file` | Fetch specific file from GitHub repo |
|
|
199
|
+
| **AST Pattern Search** | `mcp__ast-grep__find_code` | Structural code search across 25+ languages with AST awareness |
|
|
200
|
+
| **AST Replace** | `mcp__ast-grep__replace` | AST-aware code refactoring and replacement |
|
|
201
|
+
| **Local Code Search** | `grep_search` | Pattern-based search in local/cloned repos (uses ripgrep) |
|
|
202
|
+
| **Local AST Search** | `ast_grep_search` | AST search in cloned repos |
|
|
203
|
+
| **File Glob** | `glob_files` | Find files by pattern |
|
|
194
204
|
| **Clone Repo** | gh CLI | `gh repo clone owner/repo ${TMPDIR:-/tmp}/name -- --depth 1` |
|
|
195
205
|
| **Issues/PRs** | gh CLI | `gh search issues/prs "query" --repo owner/repo` |
|
|
196
206
|
| **View Issue/PR** | gh CLI | `gh issue/pr view <num> --repo owner/repo --comments` |
|
mcp_bridge/prompts/explore.py
CHANGED
|
@@ -96,14 +96,52 @@ Your response has **FAILED** if:
|
|
|
96
96
|
- **No emojis**: Keep output clean and parseable
|
|
97
97
|
- **No file creation**: Report findings as message text, never write files
|
|
98
98
|
|
|
99
|
-
## Tool Strategy
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
- **Semantic search** (definitions, references):
|
|
103
|
-
- **Structural patterns** (function shapes, class structures): ast_grep_search
|
|
104
|
-
- **Text patterns** (strings, comments, logs):
|
|
105
|
-
- **File patterns** (find by name/extension):
|
|
106
|
-
- **History/evolution** (when added, who changed): git commands
|
|
99
|
+
## Tool Strategy & Available Tools
|
|
100
|
+
|
|
101
|
+
### Local Codebase Tools
|
|
102
|
+
- **Semantic search** (definitions, references): `lsp_goto_definition`, `lsp_find_references`, `lsp_workspace_symbols`
|
|
103
|
+
- **Structural patterns** (function shapes, class structures): `ast_grep_search` (local), `mcp__ast-grep__find_code` (enhanced)
|
|
104
|
+
- **Text patterns** (strings, comments, logs): `grep_search` (local ripgrep)
|
|
105
|
+
- **File patterns** (find by name/extension): `glob_files`
|
|
106
|
+
- **History/evolution** (when added, who changed): git commands (`git log`, `git blame`)
|
|
107
|
+
|
|
108
|
+
### MCP DOCKER Enhanced Tools (ALWAYS prefer these when searching)
|
|
109
|
+
- **`mcp__MCP_DOCKER__web_search_exa`**: Real-time web search for documentation, articles, best practices
|
|
110
|
+
- Use when: Researching external libraries, finding current tutorials, checking API docs
|
|
111
|
+
- Example: `mcp__MCP_DOCKER__web_search_exa(query="library-name best practices 2026", num_results=5)`
|
|
112
|
+
|
|
113
|
+
### GitHub Code Search (MCP grep-app)
|
|
114
|
+
- **`mcp__grep-app__searchCode`**: Search across ALL public GitHub repositories
|
|
115
|
+
- Use when: Finding implementation examples, usage patterns, community solutions
|
|
116
|
+
- Returns: GitHub permalinks with full context
|
|
117
|
+
- Example: `mcp__grep-app__searchCode(query="repo:owner/repo pattern")`
|
|
118
|
+
- **`mcp__grep-app__github_file`**: Fetch specific files from GitHub repos
|
|
119
|
+
- Use when: Need to read implementation from remote repo
|
|
120
|
+
- Example: `mcp__grep-app__github_file(owner="facebook", repo="react", path="src/hooks/useEffect.ts")`
|
|
121
|
+
|
|
122
|
+
### AST-Aware Search (MCP ast-grep)
|
|
123
|
+
- **`mcp__ast-grep__find_code`**: Structural code search across 25+ languages
|
|
124
|
+
- Use when: Finding code patterns by structure, not just text
|
|
125
|
+
- Supports: TypeScript, Python, Rust, Go, Java, JavaScript, and 20+ more
|
|
126
|
+
- Example: `mcp__ast-grep__find_code(pattern="function $NAME($$$ARGS) { $$$ }", language="typescript")`
|
|
127
|
+
- **`mcp__ast-grep__find_code_by_rule`**: Advanced AST search with YAML rules
|
|
128
|
+
- Use when: Complex pattern matching with constraints
|
|
129
|
+
- Example: Find all async functions that don't handle errors
|
|
130
|
+
|
|
131
|
+
### Parallel Search Strategy
|
|
132
|
+
|
|
133
|
+
**ALWAYS spawn 4-6 tools in parallel** for comprehensive search:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
# Example: "Find authentication implementation"
|
|
137
|
+
Parallel execution:
|
|
138
|
+
1. lsp_workspace_symbols(query="auth")
|
|
139
|
+
2. mcp__ast-grep__find_code(pattern="function $AUTH", language="typescript")
|
|
140
|
+
3. mcp__grep-app__searchCode(query="repo:your-org/repo authentication")
|
|
141
|
+
4. grep_search(pattern="authenticate|login|verify")
|
|
142
|
+
5. glob_files(pattern="**/*auth*.ts")
|
|
143
|
+
6. mcp__MCP_DOCKER__web_search_exa(query="library-name authentication implementation 2026")
|
|
144
|
+
```
|
|
107
145
|
|
|
108
146
|
Flood with parallel calls. Cross-validate findings across multiple tools."""
|
|
109
147
|
|