mcp-researchpowerpack-http 3.10.0

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.
Files changed (127) hide show
  1. package/README.md +124 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +227 -0
  5. package/dist/index.js.map +7 -0
  6. package/dist/mcp-use.json +7 -0
  7. package/dist/src/clients/github.d.ts +83 -0
  8. package/dist/src/clients/github.d.ts.map +1 -0
  9. package/dist/src/clients/github.js +370 -0
  10. package/dist/src/clients/github.js.map +7 -0
  11. package/dist/src/clients/reddit.d.ts +60 -0
  12. package/dist/src/clients/reddit.d.ts.map +1 -0
  13. package/dist/src/clients/reddit.js +287 -0
  14. package/dist/src/clients/reddit.js.map +7 -0
  15. package/dist/src/clients/research.d.ts +67 -0
  16. package/dist/src/clients/research.d.ts.map +1 -0
  17. package/dist/src/clients/research.js +282 -0
  18. package/dist/src/clients/research.js.map +7 -0
  19. package/dist/src/clients/scraper.d.ts +72 -0
  20. package/dist/src/clients/scraper.d.ts.map +1 -0
  21. package/dist/src/clients/scraper.js +327 -0
  22. package/dist/src/clients/scraper.js.map +7 -0
  23. package/dist/src/clients/search.d.ts +57 -0
  24. package/dist/src/clients/search.d.ts.map +1 -0
  25. package/dist/src/clients/search.js +218 -0
  26. package/dist/src/clients/search.js.map +7 -0
  27. package/dist/src/config/index.d.ts +93 -0
  28. package/dist/src/config/index.d.ts.map +1 -0
  29. package/dist/src/config/index.js +218 -0
  30. package/dist/src/config/index.js.map +7 -0
  31. package/dist/src/schemas/deep-research.d.ts +40 -0
  32. package/dist/src/schemas/deep-research.d.ts.map +1 -0
  33. package/dist/src/schemas/deep-research.js +216 -0
  34. package/dist/src/schemas/deep-research.js.map +7 -0
  35. package/dist/src/schemas/github-score.d.ts +50 -0
  36. package/dist/src/schemas/github-score.d.ts.map +1 -0
  37. package/dist/src/schemas/github-score.js +58 -0
  38. package/dist/src/schemas/github-score.js.map +7 -0
  39. package/dist/src/schemas/scrape-links.d.ts +23 -0
  40. package/dist/src/schemas/scrape-links.d.ts.map +1 -0
  41. package/dist/src/schemas/scrape-links.js +32 -0
  42. package/dist/src/schemas/scrape-links.js.map +7 -0
  43. package/dist/src/schemas/web-search.d.ts +18 -0
  44. package/dist/src/schemas/web-search.d.ts.map +1 -0
  45. package/dist/src/schemas/web-search.js +28 -0
  46. package/dist/src/schemas/web-search.js.map +7 -0
  47. package/dist/src/scoring/github-quality.d.ts +142 -0
  48. package/dist/src/scoring/github-quality.d.ts.map +1 -0
  49. package/dist/src/scoring/github-quality.js +202 -0
  50. package/dist/src/scoring/github-quality.js.map +7 -0
  51. package/dist/src/services/file-attachment.d.ts +30 -0
  52. package/dist/src/services/file-attachment.d.ts.map +1 -0
  53. package/dist/src/services/file-attachment.js +205 -0
  54. package/dist/src/services/file-attachment.js.map +7 -0
  55. package/dist/src/services/llm-processor.d.ts +29 -0
  56. package/dist/src/services/llm-processor.d.ts.map +1 -0
  57. package/dist/src/services/llm-processor.js +206 -0
  58. package/dist/src/services/llm-processor.js.map +7 -0
  59. package/dist/src/services/markdown-cleaner.d.ts +8 -0
  60. package/dist/src/services/markdown-cleaner.d.ts.map +1 -0
  61. package/dist/src/services/markdown-cleaner.js +63 -0
  62. package/dist/src/services/markdown-cleaner.js.map +7 -0
  63. package/dist/src/tools/github-score.d.ts +12 -0
  64. package/dist/src/tools/github-score.d.ts.map +1 -0
  65. package/dist/src/tools/github-score.js +306 -0
  66. package/dist/src/tools/github-score.js.map +7 -0
  67. package/dist/src/tools/mcp-helpers.d.ts +27 -0
  68. package/dist/src/tools/mcp-helpers.d.ts.map +1 -0
  69. package/dist/src/tools/mcp-helpers.js +47 -0
  70. package/dist/src/tools/mcp-helpers.js.map +7 -0
  71. package/dist/src/tools/reddit.d.ts +54 -0
  72. package/dist/src/tools/reddit.d.ts.map +1 -0
  73. package/dist/src/tools/reddit.js +498 -0
  74. package/dist/src/tools/reddit.js.map +7 -0
  75. package/dist/src/tools/registry.d.ts +3 -0
  76. package/dist/src/tools/registry.d.ts.map +1 -0
  77. package/dist/src/tools/registry.js +17 -0
  78. package/dist/src/tools/registry.js.map +7 -0
  79. package/dist/src/tools/research.d.ts +14 -0
  80. package/dist/src/tools/research.d.ts.map +1 -0
  81. package/dist/src/tools/research.js +250 -0
  82. package/dist/src/tools/research.js.map +7 -0
  83. package/dist/src/tools/scrape.d.ts +14 -0
  84. package/dist/src/tools/scrape.d.ts.map +1 -0
  85. package/dist/src/tools/scrape.js +290 -0
  86. package/dist/src/tools/scrape.js.map +7 -0
  87. package/dist/src/tools/search.d.ts +10 -0
  88. package/dist/src/tools/search.d.ts.map +1 -0
  89. package/dist/src/tools/search.js +197 -0
  90. package/dist/src/tools/search.js.map +7 -0
  91. package/dist/src/tools/utils.d.ts +105 -0
  92. package/dist/src/tools/utils.d.ts.map +1 -0
  93. package/dist/src/tools/utils.js +96 -0
  94. package/dist/src/tools/utils.js.map +7 -0
  95. package/dist/src/utils/concurrency.d.ts +28 -0
  96. package/dist/src/utils/concurrency.d.ts.map +1 -0
  97. package/dist/src/utils/concurrency.js +62 -0
  98. package/dist/src/utils/concurrency.js.map +7 -0
  99. package/dist/src/utils/errors.d.ts +95 -0
  100. package/dist/src/utils/errors.d.ts.map +1 -0
  101. package/dist/src/utils/errors.js +289 -0
  102. package/dist/src/utils/errors.js.map +7 -0
  103. package/dist/src/utils/logger.d.ts +33 -0
  104. package/dist/src/utils/logger.d.ts.map +1 -0
  105. package/dist/src/utils/logger.js +41 -0
  106. package/dist/src/utils/logger.js.map +7 -0
  107. package/dist/src/utils/markdown-formatter.d.ts +5 -0
  108. package/dist/src/utils/markdown-formatter.d.ts.map +1 -0
  109. package/dist/src/utils/markdown-formatter.js +15 -0
  110. package/dist/src/utils/markdown-formatter.js.map +7 -0
  111. package/dist/src/utils/response.d.ts +83 -0
  112. package/dist/src/utils/response.d.ts.map +1 -0
  113. package/dist/src/utils/response.js +109 -0
  114. package/dist/src/utils/response.js.map +7 -0
  115. package/dist/src/utils/retry.d.ts +43 -0
  116. package/dist/src/utils/retry.d.ts.map +1 -0
  117. package/dist/src/utils/retry.js +37 -0
  118. package/dist/src/utils/retry.js.map +7 -0
  119. package/dist/src/utils/url-aggregator.d.ts +92 -0
  120. package/dist/src/utils/url-aggregator.d.ts.map +1 -0
  121. package/dist/src/utils/url-aggregator.js +357 -0
  122. package/dist/src/utils/url-aggregator.js.map +7 -0
  123. package/dist/src/version.d.ts +28 -0
  124. package/dist/src/version.d.ts.map +1 -0
  125. package/dist/src/version.js +32 -0
  126. package/dist/src/version.js.map +7 -0
  127. package/package.json +73 -0
@@ -0,0 +1,216 @@
1
+ import { z } from "zod";
2
+ const fileAttachmentSchema = z.object({
3
+ path: z.string({ error: "deep-research: File path is required" }).min(1, { message: "deep-research: File path cannot be empty" }).describe(
4
+ `**[REQUIRED] Absolute file path to attach.**
5
+
6
+ \u26A0\uFE0F **YOU MUST USE ABSOLUTE PATHS** - e.g., "/Users/john/project/src/utils/auth.ts" NOT "src/utils/auth.ts"
7
+
8
+ The file will be read from the filesystem and included as context for the research question. This is CRITICAL for:
9
+ - Bug investigations (attach the failing code)
10
+ - Code reviews (attach the code to review)
11
+ - Refactoring questions (attach current implementation)
12
+ - Architecture decisions (attach relevant modules)
13
+ - Performance issues (attach the slow code path)
14
+
15
+ **IMPORTANT:** Always use the full absolute path as shown in your IDE or terminal.`
16
+ ),
17
+ start_line: z.number({ error: "deep-research: start_line must be a number" }).int({ message: "deep-research: start_line must be an integer" }).positive({ message: "deep-research: start_line must be a positive integer (1-indexed)" }).optional().describe(
18
+ `**[OPTIONAL] Start line number (1-indexed).**
19
+
20
+ Use this to focus on a specific section of a large file. If omitted, reads from line 1.
21
+ Example: start_line=50 with end_line=100 reads lines 50-100 only.`
22
+ ),
23
+ end_line: z.number({ error: "deep-research: end_line must be a number" }).int({ message: "deep-research: end_line must be an integer" }).positive({ message: "deep-research: end_line must be a positive integer (1-indexed)" }).optional().describe(
24
+ `**[OPTIONAL] End line number (1-indexed).**
25
+
26
+ Use this to limit the scope to relevant code sections. If omitted, reads to end of file.
27
+ For large files (>500 lines), consider specifying a range to focus the research.`
28
+ ),
29
+ description: z.string().optional().describe(
30
+ `**[HIGHLY RECOMMENDED] Comprehensive description of why this file is attached and what to focus on.**
31
+
32
+ \u26A0\uFE0F **THIS IS CRITICAL FOR EFFECTIVE RESEARCH.** Write a detailed description explaining:
33
+
34
+ 1. **What this file is:** "This is the main authentication middleware that handles JWT validation"
35
+ 2. **Why it's relevant:** "The bug occurs when tokens expire during long-running requests"
36
+ 3. **What to focus on:** "Pay attention to the refreshToken() function on lines 45-80"
37
+ 4. **Known issues/context:** "We suspect the race condition happens in the async validation"
38
+ 5. **Related files:** "This interacts with /src/services/token-service.ts for token refresh"
39
+
40
+ **GOOD EXAMPLE:**
41
+ "This is our Redis caching layer (cache-service.ts). The bug manifests as stale data being returned after cache invalidation. Focus on the invalidatePattern() method (lines 120-150) and how it interacts with the pub/sub mechanism. We're using Redis Cluster and suspect the issue is related to cross-node invalidation timing."
42
+
43
+ **BAD EXAMPLE:**
44
+ "cache file" \u2190 Too vague, research will be unfocused`
45
+ )
46
+ }).strict();
47
+ const researchQuestionSchema = z.object({
48
+ question: z.string({ error: "deep-research: Question is required" }).min(10, { message: "deep-research: Question must be at least 10 characters" }).describe(
49
+ `**[REQUIRED] Your research question - MUST follow this structured template:**
50
+
51
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
52
+ \u{1F4CB} **STRUCTURED QUESTION TEMPLATE** (You MUST use this format)
53
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
54
+
55
+ **1. \u{1F3AF} WHAT I NEED:**
56
+ [Clearly state what you're trying to achieve, solve, or understand]
57
+
58
+ **2. \u{1F914} WHY I'M RESEARCHING THIS:**
59
+ [Explain the context - what decision does this inform? What problem are you solving?]
60
+
61
+ **3. \u{1F4DA} WHAT I ALREADY KNOW:**
62
+ [Share your current understanding so research fills gaps, not repeats basics]
63
+
64
+ **4. \u{1F527} HOW I PLAN TO USE THIS:**
65
+ [Describe the practical application - implementation, debugging, architecture, etc.]
66
+
67
+ **5. \u2753 SPECIFIC QUESTIONS (2-5):**
68
+ - Question 1: [Specific, pointed question]
69
+ - Question 2: [Another specific question]
70
+ - Question 3: [etc.]
71
+
72
+ **6. \u{1F310} PRIORITY SOURCES (optional):**
73
+ [Sites/docs to prioritize: "Prefer official React docs, GitHub issues, Stack Overflow"]
74
+
75
+ **7. \u26A1 PRIORITY INFO (optional):**
76
+ [What matters most: "Focus on performance implications" or "Prioritize security best practices"]
77
+
78
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
79
+
80
+ **EXAMPLE FOR BUG INVESTIGATION:**
81
+ "\u{1F3AF} WHAT I NEED: Debug why our WebSocket connections drop after exactly 60 seconds of inactivity.
82
+
83
+ \u{1F914} WHY: Production users are losing real-time updates, causing data sync issues and support tickets.
84
+
85
+ \u{1F4DA} WHAT I KNOW: We use Socket.io v4.6 with Redis adapter. The 60s timeout suggests a proxy/load balancer issue, but we've checked nginx configs.
86
+
87
+ \u{1F527} HOW I'LL USE THIS: Implement the fix in our connection-manager.ts (attached) and update our deployment configs.
88
+
89
+ \u2753 SPECIFIC QUESTIONS:
90
+ 1. What are common causes of exactly 60-second WebSocket timeouts?
91
+ 2. How should Socket.io heartbeat/ping intervals be configured to prevent this?
92
+ 3. Are there AWS ALB-specific settings we need to consider?
93
+ 4. How do other production apps handle WebSocket keep-alive?
94
+
95
+ \u{1F310} PRIORITY: Socket.io official docs, AWS documentation, GitHub issues with similar problems
96
+
97
+ \u26A1 FOCUS: Production-ready solutions, not development workarounds"
98
+
99
+ **EXAMPLE FOR ARCHITECTURE RESEARCH:**
100
+ "\u{1F3AF} WHAT I NEED: Best practices for implementing CQRS pattern with Event Sourcing in Node.js/TypeScript.
101
+
102
+ \u{1F914} WHY: Our monolithic API is hitting scaling limits. We need to separate read/write paths for our order processing system.
103
+
104
+ \u{1F4DA} WHAT I KNOW: Familiar with basic event-driven architecture, used RabbitMQ before. New to full CQRS/ES implementation.
105
+
106
+ \u{1F527} HOW I'LL USE THIS: Design the new order-service architecture, select appropriate libraries, plan migration strategy.
107
+
108
+ \u2753 SPECIFIC QUESTIONS:
109
+ 1. What are the recommended Node.js libraries for CQRS/ES? (Pros/cons of each)
110
+ 2. How should we handle eventual consistency in read models?
111
+ 3. What's the best event store for our scale (~10k events/day)?
112
+ 4. How do we handle schema evolution for events over time?
113
+ 5. What are common pitfalls teams encounter when adopting CQRS/ES?
114
+
115
+ \u{1F310} PRIORITY: Microsoft docs (they coined CQRS), Martin Fowler, real-world case studies
116
+
117
+ \u26A1 FOCUS: Production patterns, not theoretical explanations. Include code examples."`
118
+ ),
119
+ file_attachments: z.array(fileAttachmentSchema).optional().describe(
120
+ `**[CRITICAL FOR BUGS/CODE QUESTIONS] File attachments to include as research context.**
121
+
122
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
123
+ \u26A0\uFE0F **YOU MUST ATTACH FILES WHEN:**
124
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
125
+
126
+ \u2705 **MANDATORY file attachment scenarios:**
127
+ - \u{1F41B} **Bug investigation** \u2192 Attach the buggy code file(s)
128
+ - \u{1F50D} **Code review** \u2192 Attach the code to be reviewed
129
+ - \u267B\uFE0F **Refactoring** \u2192 Attach current implementation
130
+ - \u{1F3D7}\uFE0F **Architecture questions about YOUR code** \u2192 Attach relevant modules
131
+ - \u26A1 **Performance issues** \u2192 Attach the slow code paths
132
+ - \u{1F512} **Security review** \u2192 Attach the security-sensitive code
133
+ - \u{1F9EA} **Testing questions** \u2192 Attach both the code AND test files
134
+ - \u{1F517} **Integration issues** \u2192 Attach files from both sides of the integration
135
+
136
+ \u274C **File attachments NOT needed for:**
137
+ - General concept questions ("What is CQRS?")
138
+ - Technology comparisons ("React vs Vue")
139
+ - Best practices research (unless about your specific code)
140
+ - Documentation lookups
141
+
142
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
143
+ \u{1F4CE} **HOW TO ATTACH FILES:**
144
+ \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
145
+
146
+ **Each attachment requires:**
147
+ 1. \`path\` (REQUIRED): **Absolute path** like "/Users/dev/project/src/auth.ts"
148
+ 2. \`start_line\` (optional): Focus on specific section
149
+ 3. \`end_line\` (optional): Limit scope for large files
150
+ 4. \`description\` (HIGHLY RECOMMENDED): Explain what this file is and why it matters
151
+
152
+ **EXAMPLE - Bug with multiple related files:**
153
+ \`\`\`json
154
+ {
155
+ "question": "\u{1F3AF} WHAT I NEED: Fix the race condition in our order processing...",
156
+ "file_attachments": [
157
+ {
158
+ "path": "/Users/dev/ecommerce/src/services/order-processor.ts",
159
+ "description": "Main order processing service. The race condition occurs in processOrder() when two requests hit simultaneously. Lines 45-120 contain the critical section."
160
+ },
161
+ {
162
+ "path": "/Users/dev/ecommerce/src/repositories/inventory-repo.ts",
163
+ "start_line": 30,
164
+ "end_line": 80,
165
+ "description": "Inventory repository - the decrementStock() method (lines 30-80) is called by order-processor and we suspect it's not properly locked."
166
+ },
167
+ {
168
+ "path": "/Users/dev/ecommerce/src/utils/db-transaction.ts",
169
+ "description": "Our transaction wrapper utility. Need to verify if it properly handles concurrent transactions."
170
+ }
171
+ ]
172
+ }
173
+ \`\`\`
174
+
175
+ **Attach as many files as needed for complete context - there is no limit!**`
176
+ )
177
+ }).strict();
178
+ const deepResearchParamsShape = {
179
+ questions: z.array(researchQuestionSchema, {
180
+ error: "deep-research: Questions must be an array"
181
+ }).min(1, { message: "deep-research: At least 1 question is required (recommend 2-7 for optimal depth)" }).max(10, { message: "deep-research: Maximum 10 questions allowed per batch" }).describe(
182
+ `Array of 1\u201310 research question objects (NOT plain strings \u2014 each item must be {question: string, file_attachments?: [...]}).
183
+
184
+ **TOKEN BUDGET:** 32,000 tokens split dynamically:
185
+ - 1 question: 32,000 tokens (exhaustive deep dive)
186
+ - 2 questions: 16,000 tokens/question
187
+ - 5 questions: 6,400 tokens/question (balanced)
188
+ - 10 questions: 3,200 tokens/question (rapid multi-topic)
189
+
190
+ **STRUCTURE:** Each question should follow the template: WHAT I NEED \u2192 WHY I'M RESEARCHING \u2192 WHAT I ALREADY KNOW \u2192 SPECIFIC QUESTIONS (2\u20135). Attach local files via file_attachments for bug investigations or code-specific research.
191
+
192
+ **USAGE:** All questions run in parallel. More questions = broader but shallower. Group related questions for coherent research. Supply <1 and you get an error; >10 is rejected.`
193
+ )
194
+ };
195
+ const deepResearchParamsSchema = z.object(deepResearchParamsShape).strict();
196
+ const deepResearchQuestionResultSchema = z.object({
197
+ question: z.string().describe("Original research question submitted for this result item."),
198
+ content: z.string().describe("Rendered research answer or error body for this question."),
199
+ success: z.boolean().describe("Whether the question completed successfully."),
200
+ error: z.string().optional().describe("Error message when the question failed."),
201
+ tokensUsed: z.number().int().nonnegative().optional().describe("Total model tokens used for this question when available.")
202
+ }).strict();
203
+ const deepResearchOutputSchema = z.object({
204
+ totalQuestions: z.number().int().nonnegative().describe("Total number of research questions processed in the batch."),
205
+ successful: z.number().int().nonnegative().describe("Number of questions that completed successfully."),
206
+ failed: z.number().int().nonnegative().describe("Number of questions that failed."),
207
+ tokensPerQuestion: z.number().int().nonnegative().describe("Allocated token budget per question."),
208
+ totalTokensUsed: z.number().int().nonnegative().describe("Aggregate tokens consumed across successful questions."),
209
+ results: z.array(deepResearchQuestionResultSchema).describe("Per-question research results including failures when present.")
210
+ }).strict();
211
+ export {
212
+ deepResearchOutputSchema,
213
+ deepResearchParamsSchema,
214
+ deepResearchQuestionResultSchema
215
+ };
216
+ //# sourceMappingURL=deep-research.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/schemas/deep-research.ts"],
4
+ "sourcesContent": ["/**\n * Deep research schema - batch research with dynamic token allocation\n * Enhanced with comprehensive prompting for bugs, programming questions, and general research\n */\n\nimport { z } from 'zod';\n\n// File attachment schema with comprehensive descriptions to guide LLM usage\nconst fileAttachmentSchema = z.object({\n path: z\n .string({ error: 'deep-research: File path is required' })\n .min(1, { message: 'deep-research: File path cannot be empty' })\n .describe(\n `**[REQUIRED] Absolute file path to attach.**\n\n\u26A0\uFE0F **YOU MUST USE ABSOLUTE PATHS** - e.g., \"/Users/john/project/src/utils/auth.ts\" NOT \"src/utils/auth.ts\"\n\nThe file will be read from the filesystem and included as context for the research question. This is CRITICAL for:\n- Bug investigations (attach the failing code)\n- Code reviews (attach the code to review)\n- Refactoring questions (attach current implementation)\n- Architecture decisions (attach relevant modules)\n- Performance issues (attach the slow code path)\n\n**IMPORTANT:** Always use the full absolute path as shown in your IDE or terminal.`\n ),\n start_line: z\n .number({ error: 'deep-research: start_line must be a number' })\n .int({ message: 'deep-research: start_line must be an integer' })\n .positive({ message: 'deep-research: start_line must be a positive integer (1-indexed)' })\n .optional()\n .describe(\n `**[OPTIONAL] Start line number (1-indexed).**\n\nUse this to focus on a specific section of a large file. If omitted, reads from line 1.\nExample: start_line=50 with end_line=100 reads lines 50-100 only.`\n ),\n end_line: z\n .number({ error: 'deep-research: end_line must be a number' })\n .int({ message: 'deep-research: end_line must be an integer' })\n .positive({ message: 'deep-research: end_line must be a positive integer (1-indexed)' })\n .optional()\n .describe(\n `**[OPTIONAL] End line number (1-indexed).**\n\nUse this to limit the scope to relevant code sections. If omitted, reads to end of file.\nFor large files (>500 lines), consider specifying a range to focus the research.`\n ),\n description: z\n .string()\n .optional()\n .describe(\n `**[HIGHLY RECOMMENDED] Comprehensive description of why this file is attached and what to focus on.**\n\n\u26A0\uFE0F **THIS IS CRITICAL FOR EFFECTIVE RESEARCH.** Write a detailed description explaining:\n\n1. **What this file is:** \"This is the main authentication middleware that handles JWT validation\"\n2. **Why it's relevant:** \"The bug occurs when tokens expire during long-running requests\"\n3. **What to focus on:** \"Pay attention to the refreshToken() function on lines 45-80\"\n4. **Known issues/context:** \"We suspect the race condition happens in the async validation\"\n5. **Related files:** \"This interacts with /src/services/token-service.ts for token refresh\"\n\n**GOOD EXAMPLE:**\n\"This is our Redis caching layer (cache-service.ts). The bug manifests as stale data being returned after cache invalidation. Focus on the invalidatePattern() method (lines 120-150) and how it interacts with the pub/sub mechanism. We're using Redis Cluster and suspect the issue is related to cross-node invalidation timing.\"\n\n**BAD EXAMPLE:**\n\"cache file\" \u2190 Too vague, research will be unfocused`\n ),\n}).strict();\n\n// Research question schema with structured template guidance\nconst researchQuestionSchema = z.object({\n question: z\n .string({ error: 'deep-research: Question is required' })\n .min(10, { message: 'deep-research: Question must be at least 10 characters' })\n .describe(\n `**[REQUIRED] Your research question - MUST follow this structured template:**\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\uD83D\uDCCB **STRUCTURED QUESTION TEMPLATE** (You MUST use this format)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n**1. \uD83C\uDFAF WHAT I NEED:**\n[Clearly state what you're trying to achieve, solve, or understand]\n\n**2. \uD83E\uDD14 WHY I'M RESEARCHING THIS:**\n[Explain the context - what decision does this inform? What problem are you solving?]\n\n**3. \uD83D\uDCDA WHAT I ALREADY KNOW:**\n[Share your current understanding so research fills gaps, not repeats basics]\n\n**4. \uD83D\uDD27 HOW I PLAN TO USE THIS:**\n[Describe the practical application - implementation, debugging, architecture, etc.]\n\n**5. \u2753 SPECIFIC QUESTIONS (2-5):**\n- Question 1: [Specific, pointed question]\n- Question 2: [Another specific question]\n- Question 3: [etc.]\n\n**6. \uD83C\uDF10 PRIORITY SOURCES (optional):**\n[Sites/docs to prioritize: \"Prefer official React docs, GitHub issues, Stack Overflow\"]\n\n**7. \u26A1 PRIORITY INFO (optional):**\n[What matters most: \"Focus on performance implications\" or \"Prioritize security best practices\"]\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n**EXAMPLE FOR BUG INVESTIGATION:**\n\"\uD83C\uDFAF WHAT I NEED: Debug why our WebSocket connections drop after exactly 60 seconds of inactivity.\n\n\uD83E\uDD14 WHY: Production users are losing real-time updates, causing data sync issues and support tickets.\n\n\uD83D\uDCDA WHAT I KNOW: We use Socket.io v4.6 with Redis adapter. The 60s timeout suggests a proxy/load balancer issue, but we've checked nginx configs.\n\n\uD83D\uDD27 HOW I'LL USE THIS: Implement the fix in our connection-manager.ts (attached) and update our deployment configs.\n\n\u2753 SPECIFIC QUESTIONS:\n1. What are common causes of exactly 60-second WebSocket timeouts?\n2. How should Socket.io heartbeat/ping intervals be configured to prevent this?\n3. Are there AWS ALB-specific settings we need to consider?\n4. How do other production apps handle WebSocket keep-alive?\n\n\uD83C\uDF10 PRIORITY: Socket.io official docs, AWS documentation, GitHub issues with similar problems\n\n\u26A1 FOCUS: Production-ready solutions, not development workarounds\"\n\n**EXAMPLE FOR ARCHITECTURE RESEARCH:**\n\"\uD83C\uDFAF WHAT I NEED: Best practices for implementing CQRS pattern with Event Sourcing in Node.js/TypeScript.\n\n\uD83E\uDD14 WHY: Our monolithic API is hitting scaling limits. We need to separate read/write paths for our order processing system.\n\n\uD83D\uDCDA WHAT I KNOW: Familiar with basic event-driven architecture, used RabbitMQ before. New to full CQRS/ES implementation.\n\n\uD83D\uDD27 HOW I'LL USE THIS: Design the new order-service architecture, select appropriate libraries, plan migration strategy.\n\n\u2753 SPECIFIC QUESTIONS:\n1. What are the recommended Node.js libraries for CQRS/ES? (Pros/cons of each)\n2. How should we handle eventual consistency in read models?\n3. What's the best event store for our scale (~10k events/day)?\n4. How do we handle schema evolution for events over time?\n5. What are common pitfalls teams encounter when adopting CQRS/ES?\n\n\uD83C\uDF10 PRIORITY: Microsoft docs (they coined CQRS), Martin Fowler, real-world case studies\n\n\u26A1 FOCUS: Production patterns, not theoretical explanations. Include code examples.\"`\n ),\n file_attachments: z\n .array(fileAttachmentSchema)\n .optional()\n .describe(\n `**[CRITICAL FOR BUGS/CODE QUESTIONS] File attachments to include as research context.**\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u26A0\uFE0F **YOU MUST ATTACH FILES WHEN:**\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n\u2705 **MANDATORY file attachment scenarios:**\n- \uD83D\uDC1B **Bug investigation** \u2192 Attach the buggy code file(s)\n- \uD83D\uDD0D **Code review** \u2192 Attach the code to be reviewed\n- \u267B\uFE0F **Refactoring** \u2192 Attach current implementation\n- \uD83C\uDFD7\uFE0F **Architecture questions about YOUR code** \u2192 Attach relevant modules\n- \u26A1 **Performance issues** \u2192 Attach the slow code paths\n- \uD83D\uDD12 **Security review** \u2192 Attach the security-sensitive code\n- \uD83E\uDDEA **Testing questions** \u2192 Attach both the code AND test files\n- \uD83D\uDD17 **Integration issues** \u2192 Attach files from both sides of the integration\n\n\u274C **File attachments NOT needed for:**\n- General concept questions (\"What is CQRS?\")\n- Technology comparisons (\"React vs Vue\")\n- Best practices research (unless about your specific code)\n- Documentation lookups\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\uD83D\uDCCE **HOW TO ATTACH FILES:**\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n**Each attachment requires:**\n1. \\`path\\` (REQUIRED): **Absolute path** like \"/Users/dev/project/src/auth.ts\"\n2. \\`start_line\\` (optional): Focus on specific section\n3. \\`end_line\\` (optional): Limit scope for large files\n4. \\`description\\` (HIGHLY RECOMMENDED): Explain what this file is and why it matters\n\n**EXAMPLE - Bug with multiple related files:**\n\\`\\`\\`json\n{\n \"question\": \"\uD83C\uDFAF WHAT I NEED: Fix the race condition in our order processing...\",\n \"file_attachments\": [\n {\n \"path\": \"/Users/dev/ecommerce/src/services/order-processor.ts\",\n \"description\": \"Main order processing service. The race condition occurs in processOrder() when two requests hit simultaneously. Lines 45-120 contain the critical section.\"\n },\n {\n \"path\": \"/Users/dev/ecommerce/src/repositories/inventory-repo.ts\",\n \"start_line\": 30,\n \"end_line\": 80,\n \"description\": \"Inventory repository - the decrementStock() method (lines 30-80) is called by order-processor and we suspect it's not properly locked.\"\n },\n {\n \"path\": \"/Users/dev/ecommerce/src/utils/db-transaction.ts\",\n \"description\": \"Our transaction wrapper utility. Need to verify if it properly handles concurrent transactions.\"\n }\n ]\n}\n\\`\\`\\`\n\n**Attach as many files as needed for complete context - there is no limit!**`\n ),\n}).strict();\n\n// Shape object for external consumers who need individual field schemas\nconst deepResearchParamsShape = {\n questions: z\n .array(researchQuestionSchema, {\n error: 'deep-research: Questions must be an array',\n })\n .min(1, { message: 'deep-research: At least 1 question is required (recommend 2-7 for optimal depth)' })\n .max(10, { message: 'deep-research: Maximum 10 questions allowed per batch' })\n .describe(\n `Array of 1\u201310 research question objects (NOT plain strings \u2014 each item must be {question: string, file_attachments?: [...]}).\n\n**TOKEN BUDGET:** 32,000 tokens split dynamically:\n- 1 question: 32,000 tokens (exhaustive deep dive)\n- 2 questions: 16,000 tokens/question\n- 5 questions: 6,400 tokens/question (balanced)\n- 10 questions: 3,200 tokens/question (rapid multi-topic)\n\n**STRUCTURE:** Each question should follow the template: WHAT I NEED \u2192 WHY I'M RESEARCHING \u2192 WHAT I ALREADY KNOW \u2192 SPECIFIC QUESTIONS (2\u20135). Attach local files via file_attachments for bug investigations or code-specific research.\n\n**USAGE:** All questions run in parallel. More questions = broader but shallower. Group related questions for coherent research. Supply <1 and you get an error; >10 is rejected.`\n ),\n};\n\nexport const deepResearchParamsSchema = z.object(deepResearchParamsShape).strict();\nexport type DeepResearchParams = z.infer<typeof deepResearchParamsSchema>;\n\nexport const deepResearchQuestionResultSchema = z.object({\n question: z\n .string()\n .describe('Original research question submitted for this result item.'),\n content: z\n .string()\n .describe('Rendered research answer or error body for this question.'),\n success: z\n .boolean()\n .describe('Whether the question completed successfully.'),\n error: z\n .string()\n .optional()\n .describe('Error message when the question failed.'),\n tokensUsed: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe('Total model tokens used for this question when available.'),\n}).strict();\n\nexport const deepResearchOutputSchema = z.object({\n totalQuestions: z\n .number()\n .int()\n .nonnegative()\n .describe('Total number of research questions processed in the batch.'),\n successful: z\n .number()\n .int()\n .nonnegative()\n .describe('Number of questions that completed successfully.'),\n failed: z\n .number()\n .int()\n .nonnegative()\n .describe('Number of questions that failed.'),\n tokensPerQuestion: z\n .number()\n .int()\n .nonnegative()\n .describe('Allocated token budget per question.'),\n totalTokensUsed: z\n .number()\n .int()\n .nonnegative()\n .describe('Aggregate tokens consumed across successful questions.'),\n results: z\n .array(deepResearchQuestionResultSchema)\n .describe('Per-question research results including failures when present.'),\n}).strict();\n\nexport type DeepResearchOutput = z.infer<typeof deepResearchOutputSchema>;\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * GitHub Score Tool — Zod Input/Output Schemas
3
+ */
4
+ import { z } from 'zod';
5
+ export declare const githubScoreParamsSchema: z.ZodObject<{
6
+ keywords: z.ZodArray<z.ZodString>;
7
+ search_mode: z.ZodDefault<z.ZodEnum<{
8
+ AND: "AND";
9
+ OR: "OR";
10
+ }>>;
11
+ min_stars: z.ZodDefault<z.ZodNumber>;
12
+ language: z.ZodOptional<z.ZodString>;
13
+ max_results: z.ZodDefault<z.ZodNumber>;
14
+ sort: z.ZodDefault<z.ZodEnum<{
15
+ stars: "stars";
16
+ updated: "updated";
17
+ score: "score";
18
+ }>>;
19
+ }, z.core.$strict>;
20
+ export type GitHubScoreParams = z.infer<typeof githubScoreParamsSchema>;
21
+ export declare const githubScoreOutputSchema: z.ZodObject<{
22
+ content: z.ZodString;
23
+ metadata: z.ZodObject<{
24
+ query: z.ZodString;
25
+ total_found: z.ZodNumber;
26
+ total_scored: z.ZodNumber;
27
+ failed_scores: z.ZodNumber;
28
+ execution_time_ms: z.ZodNumber;
29
+ api_calls_made: z.ZodNumber;
30
+ }, z.core.$strict>;
31
+ repos: z.ZodArray<z.ZodObject<{
32
+ full_name: z.ZodString;
33
+ url: z.ZodString;
34
+ stars: z.ZodNumber;
35
+ forks: z.ZodNumber;
36
+ open_issues: z.ZodNumber;
37
+ language: z.ZodNullable<z.ZodString>;
38
+ last_push: z.ZodString;
39
+ contributors: z.ZodNumber;
40
+ archived: z.ZodBoolean;
41
+ composite_score: z.ZodNumber;
42
+ maintenance_score: z.ZodNumber;
43
+ community_score: z.ZodNumber;
44
+ discipline_score: z.ZodNumber;
45
+ substance_score: z.ZodNumber;
46
+ flags: z.ZodArray<z.ZodString>;
47
+ }, z.core.$strict>>;
48
+ }, z.core.$strict>;
49
+ export type GitHubScoreOutput = z.infer<typeof githubScoreOutputSchema>;
50
+ //# sourceMappingURL=github-score.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-score.d.ts","sourceRoot":"","sources":["../../../src/schemas/github-score.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAcxB,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;kBA4CzB,CAAC;AAEZ,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAkCxE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAwCzB,CAAC;AAEZ,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { z } from "zod";
2
+ const keywordSchema = z.string({ error: "github-score: Keyword is required" }).min(1, { message: "github-score: Keyword cannot be empty" }).max(256, { message: "github-score: Keyword too long (max 256 characters)" }).describe(
3
+ 'A GitHub search term. Each keyword is used in the GitHub repository search API. Examples: "mcp server", "deep research tool", "langchain agent".'
4
+ );
5
+ const githubScoreParamsSchema = z.object({
6
+ keywords: z.array(keywordSchema).min(1, { message: "github-score: At least 1 keyword required" }).max(10, { message: "github-score: Maximum 10 keywords allowed" }).describe(
7
+ 'Array of 1\u201310 search keywords. Combined with search_mode to form the GitHub search query. Example: ["mcp", "research tool"] with AND mode searches for repos matching both terms.'
8
+ ),
9
+ search_mode: z.enum(["AND", "OR"]).default("AND").describe(
10
+ "How to combine keywords: AND requires all terms present, OR matches any term. Default: AND."
11
+ ),
12
+ min_stars: z.number().int().nonnegative().default(0).describe("Minimum star count filter. Repos with fewer stars are excluded. Default: 0."),
13
+ language: z.string().max(50).optional().describe(
14
+ 'Optional language filter (e.g., "TypeScript", "Python"). Matches the GitHub repository primary language.'
15
+ ),
16
+ max_results: z.number().int().min(1, { message: "github-score: At least 1 result required" }).max(50, { message: "github-score: Maximum 50 results allowed" }).default(20).describe(
17
+ "How many repos to fetch and score. Default: 20, max: 50. More repos = longer execution time (~3 API calls per repo)."
18
+ ),
19
+ sort: z.enum(["stars", "updated", "score"]).default("score").describe(
20
+ 'Sort the output table by: "stars" (raw star count), "updated" (most recently pushed), or "score" (composite quality score). Default: "score".'
21
+ )
22
+ }).strict();
23
+ const repoScoreSchema = z.object({
24
+ full_name: z.string().describe('Full "owner/repo" identifier.'),
25
+ url: z.string().describe("GitHub repository URL."),
26
+ stars: z.number().int().nonnegative().describe("Star count."),
27
+ forks: z.number().int().nonnegative().describe("Fork count."),
28
+ open_issues: z.number().int().nonnegative().describe("Open issue count."),
29
+ language: z.string().nullable().describe("Primary programming language."),
30
+ last_push: z.string().describe("Date of the last push in ISO 8601 format."),
31
+ contributors: z.number().int().nonnegative().describe("Number of contributors (up to 100)."),
32
+ archived: z.boolean().describe("Whether the repo is archived."),
33
+ composite_score: z.number().min(0).max(100).describe('Composite "Gives a Damn" quality score (0\u2013100).'),
34
+ maintenance_score: z.number().min(0).max(1).describe("Maintenance pulse sub-score (0\u20131)."),
35
+ community_score: z.number().min(0).max(1).describe("Community health sub-score (0\u20131)."),
36
+ discipline_score: z.number().min(0).max(1).describe("Engineering discipline sub-score (0\u20131)."),
37
+ substance_score: z.number().min(0).max(1).describe("Code substance sub-score (0\u20131)."),
38
+ flags: z.array(z.string()).describe(
39
+ 'Key quality flags (e.g., "archived", "no-license", "single-maintainer", "active-community").'
40
+ )
41
+ }).strict();
42
+ const githubScoreOutputSchema = z.object({
43
+ content: z.string().describe("Formatted Markdown report with scored repository table and analysis."),
44
+ metadata: z.object({
45
+ query: z.string().describe("The GitHub search query that was executed."),
46
+ total_found: z.number().int().nonnegative().describe("Total repos found by GitHub search."),
47
+ total_scored: z.number().int().nonnegative().describe("Number of repos successfully scored."),
48
+ failed_scores: z.number().int().nonnegative().describe("Number of repos where scoring failed."),
49
+ execution_time_ms: z.number().int().nonnegative().describe("Total execution time in milliseconds."),
50
+ api_calls_made: z.number().int().nonnegative().describe("Total GitHub API calls made.")
51
+ }).strict().describe("Structured metadata about the GitHub score batch."),
52
+ repos: z.array(repoScoreSchema).describe("Array of scored repositories with individual metrics.")
53
+ }).strict();
54
+ export {
55
+ githubScoreOutputSchema,
56
+ githubScoreParamsSchema
57
+ };
58
+ //# sourceMappingURL=github-score.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/schemas/github-score.ts"],
4
+ "sourcesContent": ["/**\n * GitHub Score Tool \u2014 Zod Input/Output Schemas\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Input Schema\n// ============================================================================\n\nconst keywordSchema = z\n .string({ error: 'github-score: Keyword is required' })\n .min(1, { message: 'github-score: Keyword cannot be empty' })\n .max(256, { message: 'github-score: Keyword too long (max 256 characters)' })\n .describe(\n 'A GitHub search term. Each keyword is used in the GitHub repository search API. Examples: \"mcp server\", \"deep research tool\", \"langchain agent\".',\n );\n\nexport const githubScoreParamsSchema = z\n .object({\n keywords: z\n .array(keywordSchema)\n .min(1, { message: 'github-score: At least 1 keyword required' })\n .max(10, { message: 'github-score: Maximum 10 keywords allowed' })\n .describe(\n 'Array of 1\u201310 search keywords. Combined with search_mode to form the GitHub search query. Example: [\"mcp\", \"research tool\"] with AND mode searches for repos matching both terms.',\n ),\n search_mode: z\n .enum(['AND', 'OR'])\n .default('AND')\n .describe(\n 'How to combine keywords: AND requires all terms present, OR matches any term. Default: AND.',\n ),\n min_stars: z\n .number()\n .int()\n .nonnegative()\n .default(0)\n .describe('Minimum star count filter. Repos with fewer stars are excluded. Default: 0.'),\n language: z\n .string()\n .max(50)\n .optional()\n .describe(\n 'Optional language filter (e.g., \"TypeScript\", \"Python\"). Matches the GitHub repository primary language.',\n ),\n max_results: z\n .number()\n .int()\n .min(1, { message: 'github-score: At least 1 result required' })\n .max(50, { message: 'github-score: Maximum 50 results allowed' })\n .default(20)\n .describe(\n 'How many repos to fetch and score. Default: 20, max: 50. More repos = longer execution time (~3 API calls per repo).',\n ),\n sort: z\n .enum(['stars', 'updated', 'score'])\n .default('score')\n .describe(\n 'Sort the output table by: \"stars\" (raw star count), \"updated\" (most recently pushed), or \"score\" (composite quality score). Default: \"score\".',\n ),\n })\n .strict();\n\nexport type GitHubScoreParams = z.infer<typeof githubScoreParamsSchema>;\n\n// ============================================================================\n// Output Schema\n// ============================================================================\n\nconst repoScoreSchema = z\n .object({\n full_name: z.string().describe('Full \"owner/repo\" identifier.'),\n url: z.string().describe('GitHub repository URL.'),\n stars: z.number().int().nonnegative().describe('Star count.'),\n forks: z.number().int().nonnegative().describe('Fork count.'),\n open_issues: z.number().int().nonnegative().describe('Open issue count.'),\n language: z.string().nullable().describe('Primary programming language.'),\n last_push: z.string().describe('Date of the last push in ISO 8601 format.'),\n contributors: z.number().int().nonnegative().describe('Number of contributors (up to 100).'),\n archived: z.boolean().describe('Whether the repo is archived.'),\n composite_score: z\n .number()\n .min(0)\n .max(100)\n .describe('Composite \"Gives a Damn\" quality score (0\u2013100).'),\n maintenance_score: z.number().min(0).max(1).describe('Maintenance pulse sub-score (0\u20131).'),\n community_score: z.number().min(0).max(1).describe('Community health sub-score (0\u20131).'),\n discipline_score: z.number().min(0).max(1).describe('Engineering discipline sub-score (0\u20131).'),\n substance_score: z.number().min(0).max(1).describe('Code substance sub-score (0\u20131).'),\n flags: z\n .array(z.string())\n .describe(\n 'Key quality flags (e.g., \"archived\", \"no-license\", \"single-maintainer\", \"active-community\").',\n ),\n })\n .strict();\n\nexport const githubScoreOutputSchema = z\n .object({\n content: z\n .string()\n .describe('Formatted Markdown report with scored repository table and analysis.'),\n metadata: z\n .object({\n query: z.string().describe('The GitHub search query that was executed.'),\n total_found: z\n .number()\n .int()\n .nonnegative()\n .describe('Total repos found by GitHub search.'),\n total_scored: z\n .number()\n .int()\n .nonnegative()\n .describe('Number of repos successfully scored.'),\n failed_scores: z\n .number()\n .int()\n .nonnegative()\n .describe('Number of repos where scoring failed.'),\n execution_time_ms: z\n .number()\n .int()\n .nonnegative()\n .describe('Total execution time in milliseconds.'),\n api_calls_made: z\n .number()\n .int()\n .nonnegative()\n .describe('Total GitHub API calls made.'),\n })\n .strict()\n .describe('Structured metadata about the GitHub score batch.'),\n repos: z\n .array(repoScoreSchema)\n .describe('Array of scored repositories with individual metrics.'),\n })\n .strict();\n\nexport type GitHubScoreOutput = z.infer<typeof githubScoreOutputSchema>;\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ export declare const scrapeLinksParamsSchema: z.ZodObject<{
3
+ urls: z.ZodArray<z.ZodString>;
4
+ timeout: z.ZodDefault<z.ZodNumber>;
5
+ use_llm: z.ZodDefault<z.ZodBoolean>;
6
+ what_to_extract: z.ZodOptional<z.ZodString>;
7
+ }, z.core.$strict>;
8
+ export type ScrapeLinksParams = z.infer<typeof scrapeLinksParamsSchema>;
9
+ export declare const scrapeLinksOutputSchema: z.ZodObject<{
10
+ content: z.ZodString;
11
+ metadata: z.ZodObject<{
12
+ total_urls: z.ZodNumber;
13
+ successful: z.ZodNumber;
14
+ failed: z.ZodNumber;
15
+ total_credits: z.ZodNumber;
16
+ execution_time_ms: z.ZodNumber;
17
+ tokens_per_url: z.ZodOptional<z.ZodNumber>;
18
+ total_token_budget: z.ZodOptional<z.ZodNumber>;
19
+ batches_processed: z.ZodOptional<z.ZodNumber>;
20
+ }, z.core.$strict>;
21
+ }, z.core.$strict>;
22
+ export type ScrapeLinksOutput = z.infer<typeof scrapeLinksOutputSchema>;
23
+ //# sourceMappingURL=scrape-links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrape-links.d.ts","sourceRoot":"","sources":["../../../src/schemas/scrape-links.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsCxB,eAAO,MAAM,uBAAuB;;;;;kBAA4C,CAAC;AACjF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;kBAiDzB,CAAC;AAEZ,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { z } from "zod";
2
+ const urlSchema = z.string({ error: "scrape-links: URL is required" }).url({ message: "scrape-links: Invalid URL format" }).refine(
3
+ (url) => url.startsWith("http://") || url.startsWith("https://"),
4
+ { message: "scrape-links: URL must use http:// or https:// protocol" }
5
+ ).describe("A fully-qualified HTTP or HTTPS URL to fetch and extract content from.");
6
+ const scrapeLinksParamsShape = {
7
+ urls: z.array(urlSchema, {
8
+ error: "scrape-links: URLs must be an array"
9
+ }).min(1, { message: "scrape-links: At least 1 URL is required" }).max(50, { message: "scrape-links: Maximum 50 URLs allowed per request" }).describe("URLs to scrape (1-50). Recommend 3-5 URLs for balanced depth/breadth. More URLs = broader coverage but fewer tokens per URL. 3 URLs: ~10K tokens each (deep); 10 URLs: ~3K tokens each (balanced); 50 URLs: ~640 tokens each (scan)."),
10
+ timeout: z.number({ error: "scrape-links: Timeout must be a number" }).min(5, { message: "scrape-links: Timeout must be at least 5 seconds" }).max(120, { message: "scrape-links: Timeout cannot exceed 120 seconds" }).default(30).describe("Timeout in seconds for each URL"),
11
+ use_llm: z.boolean({ error: "scrape-links: use_llm must be a boolean" }).default(true).describe("AI extraction enabled by default (requires OPENROUTER_API_KEY). Auto-filters nav/ads/footers, extracts ONLY what you specify. Set false only for raw HTML debugging."),
12
+ what_to_extract: z.string().max(1e3, { message: "scrape-links: Extraction instructions too long (max 1000 characters)" }).optional().describe('Extraction instructions for AI. Will be wrapped with compression prefix+suffix automatically. Formula: "Extract [target1] | [target2] | [target3] with focus on [aspect1], [aspect2]". Min 3 targets with | separator. Be specific (pricing tiers not pricing). Aim 5-10 targets.')
13
+ };
14
+ const scrapeLinksParamsSchema = z.object(scrapeLinksParamsShape).strict();
15
+ const scrapeLinksOutputSchema = z.object({
16
+ content: z.string().describe("Formatted markdown report containing scraped content, failures, and follow-up steps."),
17
+ metadata: z.object({
18
+ total_urls: z.number().int().nonnegative().describe("Total number of input URLs processed."),
19
+ successful: z.number().int().nonnegative().describe("Number of URLs that were fetched successfully."),
20
+ failed: z.number().int().nonnegative().describe("Number of URLs that failed validation or scraping."),
21
+ total_credits: z.number().int().nonnegative().describe("Total external scraping credits consumed."),
22
+ execution_time_ms: z.number().int().nonnegative().describe("Elapsed execution time in milliseconds."),
23
+ tokens_per_url: z.number().int().nonnegative().optional().describe("Allocated LLM token budget per successfully scraped URL."),
24
+ total_token_budget: z.number().int().nonnegative().optional().describe("Overall token budget available for extraction."),
25
+ batches_processed: z.number().int().nonnegative().optional().describe("Number of scrape batches executed.")
26
+ }).strict().describe("Structured metadata about the scrape batch.")
27
+ }).strict();
28
+ export {
29
+ scrapeLinksOutputSchema,
30
+ scrapeLinksParamsSchema
31
+ };
32
+ //# sourceMappingURL=scrape-links.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/schemas/scrape-links.ts"],
4
+ "sourcesContent": ["import { z } from 'zod';\n\n// URL schema with protocol validation\nconst urlSchema = z\n .string({ error: 'scrape-links: URL is required' })\n .url({ message: 'scrape-links: Invalid URL format' })\n .refine(\n url => url.startsWith('http://') || url.startsWith('https://'),\n { message: 'scrape-links: URL must use http:// or https:// protocol' }\n )\n .describe('A fully-qualified HTTP or HTTPS URL to fetch and extract content from.');\n\n// Input schema for scrape-links tool\nconst scrapeLinksParamsShape = {\n urls: z\n .array(urlSchema, {\n error: 'scrape-links: URLs must be an array',\n })\n .min(1, { message: 'scrape-links: At least 1 URL is required' })\n .max(50, { message: 'scrape-links: Maximum 50 URLs allowed per request' })\n .describe('URLs to scrape (1-50). Recommend 3-5 URLs for balanced depth/breadth. More URLs = broader coverage but fewer tokens per URL. 3 URLs: ~10K tokens each (deep); 10 URLs: ~3K tokens each (balanced); 50 URLs: ~640 tokens each (scan).'),\n timeout: z\n .number({ error: 'scrape-links: Timeout must be a number' })\n .min(5, { message: 'scrape-links: Timeout must be at least 5 seconds' })\n .max(120, { message: 'scrape-links: Timeout cannot exceed 120 seconds' })\n .default(30)\n .describe('Timeout in seconds for each URL'),\n use_llm: z\n .boolean({ error: 'scrape-links: use_llm must be a boolean' })\n .default(true)\n .describe('AI extraction enabled by default (requires OPENROUTER_API_KEY). Auto-filters nav/ads/footers, extracts ONLY what you specify. Set false only for raw HTML debugging.'),\n what_to_extract: z\n .string()\n .max(1000, { message: 'scrape-links: Extraction instructions too long (max 1000 characters)' })\n .optional()\n .describe('Extraction instructions for AI. Will be wrapped with compression prefix+suffix automatically. Formula: \"Extract [target1] | [target2] | [target3] with focus on [aspect1], [aspect2]\". Min 3 targets with | separator. Be specific (pricing tiers not pricing). Aim 5-10 targets.'),\n};\n\nexport const scrapeLinksParamsSchema = z.object(scrapeLinksParamsShape).strict();\nexport type ScrapeLinksParams = z.infer<typeof scrapeLinksParamsSchema>;\n\nexport const scrapeLinksOutputSchema = z.object({\n content: z\n .string()\n .describe('Formatted markdown report containing scraped content, failures, and follow-up steps.'),\n metadata: z.object({\n total_urls: z\n .number()\n .int()\n .nonnegative()\n .describe('Total number of input URLs processed.'),\n successful: z\n .number()\n .int()\n .nonnegative()\n .describe('Number of URLs that were fetched successfully.'),\n failed: z\n .number()\n .int()\n .nonnegative()\n .describe('Number of URLs that failed validation or scraping.'),\n total_credits: z\n .number()\n .int()\n .nonnegative()\n .describe('Total external scraping credits consumed.'),\n execution_time_ms: z\n .number()\n .int()\n .nonnegative()\n .describe('Elapsed execution time in milliseconds.'),\n tokens_per_url: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe('Allocated LLM token budget per successfully scraped URL.'),\n total_token_budget: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe('Overall token budget available for extraction.'),\n batches_processed: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe('Number of scrape batches executed.'),\n }).strict().describe('Structured metadata about the scrape batch.'),\n}).strict();\n\nexport type ScrapeLinksOutput = z.infer<typeof scrapeLinksOutputSchema>;\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAGlB,MAAM,YAAY,EACf,OAAO,EAAE,OAAO,gCAAgC,CAAC,EACjD,IAAI,EAAE,SAAS,mCAAmC,CAAC,EACnD;AAAA,EACC,SAAO,IAAI,WAAW,SAAS,KAAK,IAAI,WAAW,UAAU;AAAA,EAC7D,EAAE,SAAS,0DAA0D;AACvE,EACC,SAAS,wEAAwE;AAGpF,MAAM,yBAAyB;AAAA,EAC7B,MAAM,EACH,MAAM,WAAW;AAAA,IAChB,OAAO;AAAA,EACT,CAAC,EACA,IAAI,GAAG,EAAE,SAAS,2CAA2C,CAAC,EAC9D,IAAI,IAAI,EAAE,SAAS,oDAAoD,CAAC,EACxE,SAAS,sOAAsO;AAAA,EAClP,SAAS,EACN,OAAO,EAAE,OAAO,yCAAyC,CAAC,EAC1D,IAAI,GAAG,EAAE,SAAS,mDAAmD,CAAC,EACtE,IAAI,KAAK,EAAE,SAAS,kDAAkD,CAAC,EACvE,QAAQ,EAAE,EACV,SAAS,iCAAiC;AAAA,EAC7C,SAAS,EACN,QAAQ,EAAE,OAAO,0CAA0C,CAAC,EAC5D,QAAQ,IAAI,EACZ,SAAS,sKAAsK;AAAA,EAClL,iBAAiB,EACd,OAAO,EACP,IAAI,KAAM,EAAE,SAAS,uEAAuE,CAAC,EAC7F,SAAS,EACT,SAAS,mRAAmR;AACjS;AAEO,MAAM,0BAA0B,EAAE,OAAO,sBAAsB,EAAE,OAAO;AAGxE,MAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,SAAS,EACN,OAAO,EACP,SAAS,sFAAsF;AAAA,EAClG,UAAU,EAAE,OAAO;AAAA,IACjB,YAAY,EACT,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,uCAAuC;AAAA,IACnD,YAAY,EACT,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,gDAAgD;AAAA,IAC5D,QAAQ,EACL,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,oDAAoD;AAAA,IAChE,eAAe,EACZ,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,2CAA2C;AAAA,IACvD,mBAAmB,EAChB,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,yCAAyC;AAAA,IACrD,gBAAgB,EACb,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,SAAS,0DAA0D;AAAA,IACtE,oBAAoB,EACjB,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,SAAS,gDAAgD;AAAA,IAC5D,mBAAmB,EAChB,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,SAAS,oCAAoC;AAAA,EAClD,CAAC,EAAE,OAAO,EAAE,SAAS,6CAA6C;AACpE,CAAC,EAAE,OAAO;",
6
+ "names": []
7
+ }
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ export declare const webSearchParamsSchema: z.ZodObject<{
3
+ keywords: z.ZodArray<z.ZodString>;
4
+ }, z.core.$strict>;
5
+ export type WebSearchParams = z.infer<typeof webSearchParamsSchema>;
6
+ export declare const webSearchOutputSchema: z.ZodObject<{
7
+ content: z.ZodString;
8
+ metadata: z.ZodObject<{
9
+ total_keywords: z.ZodNumber;
10
+ total_results: z.ZodNumber;
11
+ execution_time_ms: z.ZodNumber;
12
+ total_unique_urls: z.ZodOptional<z.ZodNumber>;
13
+ consensus_url_count: z.ZodOptional<z.ZodNumber>;
14
+ frequency_threshold: z.ZodOptional<z.ZodNumber>;
15
+ }, z.core.$strict>;
16
+ }, z.core.$strict>;
17
+ export type WebSearchOutput = z.infer<typeof webSearchOutputSchema>;
18
+ //# sourceMappingURL=web-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-search.d.ts","sourceRoot":"","sources":["../../../src/schemas/web-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA0BxB,eAAO,MAAM,qBAAqB;;kBAA0C,CAAC;AAC7E,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,qBAAqB;;;;;;;;;;kBAuCvB,CAAC;AAEZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ const keywordSchema = z.string({ error: "web-search: Keyword is required" }).min(1, { message: "web-search: Keyword cannot be empty" }).max(500, { message: "web-search: Keyword too long (max 500 characters)" }).refine(
3
+ (k) => k.trim().length > 0,
4
+ { message: "web-search: Keyword cannot be whitespace only" }
5
+ ).describe('A single Google search query (1\u2013500 chars). Each keyword runs as a separate parallel search. Use varied angles: direct topic, comparisons, "best of" lists, year-specific, site-specific (e.g., "site:github.com topic").');
6
+ const keywordsSchema = z.array(keywordSchema, {
7
+ error: "web-search: Keywords must be an array"
8
+ }).min(1, { message: "web-search: At least 1 keyword required" }).max(100, { message: "web-search: Maximum 100 keywords allowed per request" }).describe("Array of 1\u2013100 search keywords. RECOMMENDED: 3\u20137 for solid consensus ranking, up to 20 for thorough coverage. Each keyword runs as a separate Google search in parallel. Results are aggregated and URLs appearing in multiple searches are flagged as high-confidence consensus matches. Supply <1 and you get an error; >100 is rejected.");
9
+ const webSearchParamsShape = {
10
+ keywords: keywordsSchema
11
+ };
12
+ const webSearchParamsSchema = z.object(webSearchParamsShape).strict();
13
+ const webSearchOutputSchema = z.object({
14
+ content: z.string().describe("Formatted markdown report containing ranked URLs with consensus markers and per-query results."),
15
+ metadata: z.object({
16
+ total_keywords: z.number().int().nonnegative().describe("Total number of keyword queries executed."),
17
+ total_results: z.number().int().nonnegative().describe("Total number of ranked search results included across shown queries."),
18
+ execution_time_ms: z.number().int().nonnegative().describe("Elapsed execution time in milliseconds."),
19
+ total_unique_urls: z.number().int().nonnegative().optional().describe("Unique URL count observed across all searches."),
20
+ consensus_url_count: z.number().int().nonnegative().optional().describe("Count of URLs that met the consensus threshold."),
21
+ frequency_threshold: z.number().int().nonnegative().optional().describe("Minimum frequency required for a URL to be considered consensus.")
22
+ }).strict().describe("Structured metadata about the completed web search batch.")
23
+ }).strict();
24
+ export {
25
+ webSearchOutputSchema,
26
+ webSearchParamsSchema
27
+ };
28
+ //# sourceMappingURL=web-search.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/schemas/web-search.ts"],
4
+ "sourcesContent": ["import { z } from 'zod';\n\n// Keyword schema with validation\nconst keywordSchema = z\n .string({ error: 'web-search: Keyword is required' })\n .min(1, { message: 'web-search: Keyword cannot be empty' })\n .max(500, { message: 'web-search: Keyword too long (max 500 characters)' })\n .refine(\n k => k.trim().length > 0,\n { message: 'web-search: Keyword cannot be whitespace only' }\n )\n .describe('A single Google search query (1\u2013500 chars). Each keyword runs as a separate parallel search. Use varied angles: direct topic, comparisons, \"best of\" lists, year-specific, site-specific (e.g., \"site:github.com topic\").');\n\n// Input schema for web-search tool\nconst keywordsSchema = z\n .array(keywordSchema, {\n error: 'web-search: Keywords must be an array',\n })\n .min(1, { message: 'web-search: At least 1 keyword required' })\n .max(100, { message: 'web-search: Maximum 100 keywords allowed per request' })\n .describe('Array of 1\u2013100 search keywords. RECOMMENDED: 3\u20137 for solid consensus ranking, up to 20 for thorough coverage. Each keyword runs as a separate Google search in parallel. Results are aggregated and URLs appearing in multiple searches are flagged as high-confidence consensus matches. Supply <1 and you get an error; >100 is rejected.');\n\nconst webSearchParamsShape = {\n keywords: keywordsSchema,\n};\n\nexport const webSearchParamsSchema = z.object(webSearchParamsShape).strict();\nexport type WebSearchParams = z.infer<typeof webSearchParamsSchema>;\n\nexport const webSearchOutputSchema = z.object({\n content: z\n .string()\n .describe('Formatted markdown report containing ranked URLs with consensus markers and per-query results.'),\n metadata: z.object({\n total_keywords: z\n .number()\n .int()\n .nonnegative()\n .describe('Total number of keyword queries executed.'),\n total_results: z\n .number()\n .int()\n .nonnegative()\n .describe('Total number of ranked search results included across shown queries.'),\n execution_time_ms: z\n .number()\n .int()\n .nonnegative()\n .describe('Elapsed execution time in milliseconds.'),\n total_unique_urls: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe('Unique URL count observed across all searches.'),\n consensus_url_count: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe('Count of URLs that met the consensus threshold.'),\n frequency_threshold: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe('Minimum frequency required for a URL to be considered consensus.'),\n }).strict().describe('Structured metadata about the completed web search batch.'),\n}).strict();\n\nexport type WebSearchOutput = z.infer<typeof webSearchOutputSchema>;\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAGlB,MAAM,gBAAgB,EACnB,OAAO,EAAE,OAAO,kCAAkC,CAAC,EACnD,IAAI,GAAG,EAAE,SAAS,sCAAsC,CAAC,EACzD,IAAI,KAAK,EAAE,SAAS,oDAAoD,CAAC,EACzE;AAAA,EACC,OAAK,EAAE,KAAK,EAAE,SAAS;AAAA,EACvB,EAAE,SAAS,gDAAgD;AAC7D,EACC,SAAS,gOAA2N;AAGvO,MAAM,iBAAiB,EACpB,MAAM,eAAe;AAAA,EACpB,OAAO;AACT,CAAC,EACA,IAAI,GAAG,EAAE,SAAS,0CAA0C,CAAC,EAC7D,IAAI,KAAK,EAAE,SAAS,uDAAuD,CAAC,EAC5E,SAAS,uVAA6U;AAEzV,MAAM,uBAAuB;AAAA,EAC3B,UAAU;AACZ;AAEO,MAAM,wBAAwB,EAAE,OAAO,oBAAoB,EAAE,OAAO;AAGpE,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,SAAS,EACN,OAAO,EACP,SAAS,gGAAgG;AAAA,EAC5G,UAAU,EAAE,OAAO;AAAA,IACjB,gBAAgB,EACb,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,2CAA2C;AAAA,IACvD,eAAe,EACZ,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,sEAAsE;AAAA,IAClF,mBAAmB,EAChB,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,yCAAyC;AAAA,IACrD,mBAAmB,EAChB,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,SAAS,gDAAgD;AAAA,IAC5D,qBAAqB,EAClB,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,SAAS,iDAAiD;AAAA,IAC7D,qBAAqB,EAClB,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,SAAS,kEAAkE;AAAA,EAChF,CAAC,EAAE,OAAO,EAAE,SAAS,2DAA2D;AAClF,CAAC,EAAE,OAAO;",
6
+ "names": []
7
+ }