nia-mcp-server 1.0.13__tar.gz → 1.0.15__tar.gz
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 nia-mcp-server might be problematic. Click here for more details.
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/PKG-INFO +1 -1
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/pyproject.toml +1 -1
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/__init__.py +1 -1
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/api_client.py +45 -9
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/assets/rules/nia_rules.md +44 -5
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/server.py +68 -31
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/.gitignore +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/ARCHITECTURE.md +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/LICENSE +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/README.md +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/nia_analytics.log +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/nia_mcp_server.log +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/__main__.py +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/assets/rules/claude_rules.md +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/assets/rules/cursor_rules.md +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/assets/rules/vscode_rules.md +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/assets/rules/windsurf_rules.md +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/cli.py +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/profiles.py +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/project_init.py +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/rule_transformer.py +0 -0
- {nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/setup.py +0 -0
|
@@ -75,7 +75,7 @@ class NIAApiClient:
|
|
|
75
75
|
"lifetime limit",
|
|
76
76
|
"no chat credits",
|
|
77
77
|
"free api requests",
|
|
78
|
-
"
|
|
78
|
+
"3 free",
|
|
79
79
|
"usage limit",
|
|
80
80
|
]
|
|
81
81
|
):
|
|
@@ -99,7 +99,7 @@ class NIAApiClient:
|
|
|
99
99
|
for phrase in [
|
|
100
100
|
"lifetime limit",
|
|
101
101
|
"free api requests",
|
|
102
|
-
"
|
|
102
|
+
"3 free",
|
|
103
103
|
"usage limit",
|
|
104
104
|
]
|
|
105
105
|
):
|
|
@@ -159,15 +159,33 @@ class NIAApiClient:
|
|
|
159
159
|
async def index_repository(self, repo_url: str, branch: str = None) -> Dict[str, Any]:
|
|
160
160
|
"""Index a GitHub repository."""
|
|
161
161
|
try:
|
|
162
|
-
#
|
|
162
|
+
# Handle different input formats
|
|
163
163
|
if "github.com" in repo_url:
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
# Remove query parameters and fragments
|
|
165
|
+
clean_url = repo_url.split('?')[0].split('#')[0]
|
|
166
|
+
|
|
167
|
+
# Check if it's a folder URL (contains /tree/)
|
|
168
|
+
if "/tree/" in clean_url:
|
|
169
|
+
# Extract everything after github.com/
|
|
170
|
+
parts = clean_url.split('github.com/', 1)
|
|
171
|
+
if len(parts) > 1:
|
|
172
|
+
repository_path = parts[1].rstrip('/')
|
|
173
|
+
else:
|
|
174
|
+
repository_path = repo_url
|
|
175
|
+
else:
|
|
176
|
+
# Regular repo URL - extract owner/repo
|
|
177
|
+
parts = clean_url.rstrip('/').split('/')
|
|
178
|
+
if len(parts) >= 2:
|
|
179
|
+
repo_name = parts[-1].rstrip('.git') # Remove .git suffix
|
|
180
|
+
repository_path = f"{parts[-2]}/{repo_name}"
|
|
181
|
+
else:
|
|
182
|
+
repository_path = repo_url
|
|
166
183
|
else:
|
|
167
|
-
|
|
184
|
+
# Assume it's already in the right format
|
|
185
|
+
repository_path = repo_url
|
|
168
186
|
|
|
169
187
|
payload = {
|
|
170
|
-
"repository":
|
|
188
|
+
"repository": repository_path,
|
|
171
189
|
"branch": branch
|
|
172
190
|
}
|
|
173
191
|
|
|
@@ -191,11 +209,29 @@ class NIAApiClient:
|
|
|
191
209
|
# First, list all repositories to find the matching one
|
|
192
210
|
repos = await self.list_repositories()
|
|
193
211
|
|
|
212
|
+
# Extract base repository path for matching
|
|
213
|
+
# Handle both "owner/repo" and "owner/repo/folder" formats
|
|
214
|
+
base_repo = owner_repo
|
|
215
|
+
if owner_repo.count('/') > 1:
|
|
216
|
+
# This might be a folder path like "owner/repo/folder"
|
|
217
|
+
# Extract just the owner/repo part
|
|
218
|
+
parts = owner_repo.split('/')
|
|
219
|
+
base_repo = f"{parts[0]}/{parts[1]}"
|
|
220
|
+
|
|
194
221
|
# Look for a repository matching this owner/repo
|
|
195
222
|
matching_repo = None
|
|
196
223
|
for repo in repos:
|
|
197
|
-
|
|
198
|
-
|
|
224
|
+
repo_path = repo.get("repository", "")
|
|
225
|
+
# Check exact match first
|
|
226
|
+
if repo_path == owner_repo:
|
|
227
|
+
matching_repo = repo
|
|
228
|
+
break
|
|
229
|
+
# Then check if it's the base repository
|
|
230
|
+
elif repo_path == base_repo:
|
|
231
|
+
matching_repo = repo
|
|
232
|
+
break
|
|
233
|
+
# Also check if the stored repo is a folder path that starts with our base
|
|
234
|
+
elif repo_path.startswith(base_repo + "/"):
|
|
199
235
|
matching_repo = repo
|
|
200
236
|
break
|
|
201
237
|
|
{nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/assets/rules/nia_rules.md
RENAMED
|
@@ -29,25 +29,60 @@ Note: Nia is just "Nia" - not an acronym. It's the name of the knowledge search
|
|
|
29
29
|
- Structured output needs (tables, lists)
|
|
30
30
|
- Questions with "best", "which is better", "compare"
|
|
31
31
|
|
|
32
|
-
### 3.
|
|
32
|
+
### 3. Repository Identifier Formats
|
|
33
|
+
|
|
34
|
+
#### Understanding Repository Paths
|
|
35
|
+
When using `search_codebase`, repositories can be specified in different formats:
|
|
36
|
+
|
|
37
|
+
1. **Full Repository Format**: `owner/repo`
|
|
38
|
+
- Example: `facebook/react`
|
|
39
|
+
- Use this when the entire repository was indexed
|
|
40
|
+
|
|
41
|
+
2. **Folder-Specific Format**: `owner/repo/tree/branch/folder`
|
|
42
|
+
- Example: `PostHog/posthog/tree/master/docs`
|
|
43
|
+
- Use this EXACT format when a specific folder was indexed
|
|
44
|
+
- This format appears in `list_repositories` output - copy it exactly!
|
|
45
|
+
|
|
46
|
+
#### Important Rules:
|
|
47
|
+
- **Always check `list_repositories` first** to see the exact format
|
|
48
|
+
- **Copy the repository identifier exactly** as shown in the list
|
|
49
|
+
- **Don't modify folder paths** - if it shows `owner/repo/tree/branch/folder`, use that exact string
|
|
50
|
+
- **Don't assume** - a repository indexed as a folder won't work with just `owner/repo`
|
|
51
|
+
|
|
52
|
+
#### Examples:
|
|
53
|
+
```python
|
|
54
|
+
# Wrong - trying to use base repo when folder was indexed
|
|
55
|
+
search_codebase("What is Flox?", ["PostHog/posthog"]) # ❌ Won't find folder-indexed content
|
|
56
|
+
|
|
57
|
+
# Right - using exact format from list_repositories
|
|
58
|
+
search_codebase("What is Flox?", ["PostHog/posthog/tree/master/docs"]) # ✅ Searches the indexed folder
|
|
59
|
+
|
|
60
|
+
# Wrong - modifying the path
|
|
61
|
+
search_codebase("LLM guide", ["mcp-use/mcp-use/docs"]) # ❌ Missing /tree/main/ part
|
|
62
|
+
|
|
63
|
+
# Right - exact format
|
|
64
|
+
search_codebase("LLM guide", ["mcp-use/mcp-use/tree/main/docs"]) # ✅ Correct format
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 4. Query Optimization
|
|
33
68
|
- **Use natural language queries** - Form complete questions, not just keywords
|
|
34
69
|
- **Be specific and detailed** - "How does authentication work in NextAuth.js?" not "auth nextauth"
|
|
35
70
|
- **Include context** - Mention specific technologies, frameworks, or use cases
|
|
36
71
|
- **Leverage repository context** - Specify repositories when searching indexed codebases
|
|
37
72
|
|
|
38
|
-
###
|
|
39
|
-
- **Handle rate limits gracefully** - Free tier has
|
|
73
|
+
### 5. API Usage Best Practices
|
|
74
|
+
- **Handle rate limits gracefully** - Free tier has 3 indexing operations limit
|
|
40
75
|
- **Cache results mentally** - Avoid redundant searches in the same conversation
|
|
41
76
|
- **Batch operations** - Index multiple related repositories together
|
|
42
77
|
- **Monitor status efficiently** - Check status periodically, not continuously
|
|
43
78
|
|
|
44
|
-
###
|
|
79
|
+
### 6. Result Interpretation
|
|
45
80
|
- **Provide actionable next steps** - Always suggest how to use the results
|
|
46
81
|
- **Extract indexable content** - Identify repositories and docs from search results
|
|
47
82
|
- **Format for readability** - Use markdown formatting for clear presentation
|
|
48
83
|
- **Include sources** - Always show where information comes from
|
|
49
84
|
|
|
50
|
-
###
|
|
85
|
+
### 7. Error Handling
|
|
51
86
|
- **Explain API limits clearly** - Help users understand free tier limitations
|
|
52
87
|
- **Suggest alternatives** - Provide workarounds when hitting limits
|
|
53
88
|
- **Report issues helpfully** - Include enough context for debugging
|
|
@@ -63,8 +98,12 @@ Note: Nia is just "Nia" - not an acronym. It's the name of the knowledge search
|
|
|
63
98
|
|
|
64
99
|
### Pattern 2: Codebase Understanding
|
|
65
100
|
1. Check if repository is already indexed with `list_repositories`
|
|
101
|
+
- Note the EXACT repository format shown (especially for folder paths)
|
|
102
|
+
- Example output: "PostHog/posthog/tree/master/docs" (not just "PostHog/posthog")
|
|
66
103
|
2. If not indexed, use `index_repository` and wait for completion
|
|
67
104
|
3. Use `search_codebase` with specific technical questions
|
|
105
|
+
- Use the EXACT repository identifier from step 1
|
|
106
|
+
- Don't modify or simplify folder paths
|
|
68
107
|
4. Include code snippets and file references in responses
|
|
69
108
|
|
|
70
109
|
### Pattern 3: Documentation Search
|
|
@@ -83,7 +83,7 @@ async def index_repository(
|
|
|
83
83
|
Index a GitHub repository for intelligent code search.
|
|
84
84
|
|
|
85
85
|
Args:
|
|
86
|
-
repo_url: GitHub repository URL (e.g., https://github.com/owner/repo)
|
|
86
|
+
repo_url: GitHub repository URL (e.g., https://github.com/owner/repo or https://github.com/owner/repo/tree/branch)
|
|
87
87
|
branch: Branch to index (optional, defaults to main branch)
|
|
88
88
|
|
|
89
89
|
Returns:
|
|
@@ -121,11 +121,11 @@ async def index_repository(
|
|
|
121
121
|
|
|
122
122
|
except APIError as e:
|
|
123
123
|
logger.error(f"API Error indexing repository: {e} (status_code={e.status_code}, detail={e.detail})")
|
|
124
|
-
if e.status_code == 403 or "free tier limit" in str(e).lower() or "
|
|
125
|
-
if e.detail and "
|
|
124
|
+
if e.status_code == 403 or "free tier limit" in str(e).lower() or "indexing operations" in str(e).lower():
|
|
125
|
+
if e.detail and "3 free indexing operations" in e.detail:
|
|
126
126
|
return [TextContent(
|
|
127
127
|
type="text",
|
|
128
|
-
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited
|
|
128
|
+
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited indexing."
|
|
129
129
|
)]
|
|
130
130
|
else:
|
|
131
131
|
return [TextContent(
|
|
@@ -137,10 +137,10 @@ async def index_repository(
|
|
|
137
137
|
except Exception as e:
|
|
138
138
|
logger.error(f"Unexpected error indexing repository: {e}")
|
|
139
139
|
error_msg = str(e)
|
|
140
|
-
if "
|
|
140
|
+
if "indexing operations" in error_msg.lower() or "lifetime limit" in error_msg.lower():
|
|
141
141
|
return [TextContent(
|
|
142
142
|
type="text",
|
|
143
|
-
text=f"❌ {error_msg}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited
|
|
143
|
+
text=f"❌ {error_msg}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited indexing."
|
|
144
144
|
)]
|
|
145
145
|
return [TextContent(
|
|
146
146
|
type="text",
|
|
@@ -158,11 +158,26 @@ async def search_codebase(
|
|
|
158
158
|
|
|
159
159
|
Args:
|
|
160
160
|
query: Natural language search query. Don't just use keywords or unstrctured query, make a comprehensive question to get the best results possible.
|
|
161
|
-
repositories: List of repositories to search (owner/repo
|
|
161
|
+
repositories: List of repositories to search (owner/repo or owner/repo/tree/branch if indexed differently before).
|
|
162
|
+
- "owner/repo" - Search entire repository (e.g., "facebook/react")
|
|
163
|
+
- "owner/repo/tree/branch/folder" - Search specific folder indexed separately
|
|
164
|
+
(e.g., "PostHog/posthog/tree/master/docs")
|
|
165
|
+
Use the EXACT format shown in list_repositories output for folder-indexed repos.
|
|
166
|
+
If not specified, searches all indexed repos.
|
|
162
167
|
include_sources: Whether to include source code in results
|
|
163
168
|
|
|
164
169
|
Returns:
|
|
165
170
|
Search results with relevant code snippets and explanations
|
|
171
|
+
|
|
172
|
+
Examples:
|
|
173
|
+
# Search all indexed repositories
|
|
174
|
+
search_codebase("How does authentication work?")
|
|
175
|
+
|
|
176
|
+
# Search specific repository
|
|
177
|
+
search_codebase("How to create custom hooks?", ["facebook/react"])
|
|
178
|
+
|
|
179
|
+
# Search folder-indexed repository (use exact format from list_repositories)
|
|
180
|
+
search_codebase("What is Flox?", ["PostHog/posthog/tree/master/docs"])
|
|
166
181
|
"""
|
|
167
182
|
try:
|
|
168
183
|
client = await ensure_api_client()
|
|
@@ -279,11 +294,11 @@ async def search_codebase(
|
|
|
279
294
|
|
|
280
295
|
except APIError as e:
|
|
281
296
|
logger.error(f"API Error searching codebase: {e} (status_code={e.status_code}, detail={e.detail})")
|
|
282
|
-
if e.status_code == 403 or "free tier limit" in str(e).lower() or "
|
|
283
|
-
if e.detail and "
|
|
297
|
+
if e.status_code == 403 or "free tier limit" in str(e).lower() or "indexing operations" in str(e).lower():
|
|
298
|
+
if e.detail and "3 free indexing operations" in e.detail:
|
|
284
299
|
return [TextContent(
|
|
285
300
|
type="text",
|
|
286
|
-
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited
|
|
301
|
+
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited indexing."
|
|
287
302
|
)]
|
|
288
303
|
else:
|
|
289
304
|
return [TextContent(
|
|
@@ -295,10 +310,10 @@ async def search_codebase(
|
|
|
295
310
|
except Exception as e:
|
|
296
311
|
logger.error(f"Unexpected error searching codebase: {e}")
|
|
297
312
|
error_msg = str(e)
|
|
298
|
-
if "
|
|
313
|
+
if "indexing operations" in error_msg.lower() or "lifetime limit" in error_msg.lower():
|
|
299
314
|
return [TextContent(
|
|
300
315
|
type="text",
|
|
301
|
-
text=f"❌ {error_msg}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited
|
|
316
|
+
text=f"❌ {error_msg}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited indexing."
|
|
302
317
|
)]
|
|
303
318
|
return [TextContent(
|
|
304
319
|
type="text",
|
|
@@ -419,7 +434,7 @@ async def search_documentation(
|
|
|
419
434
|
logger.error(f"API Error searching documentation: {e}")
|
|
420
435
|
error_msg = f"❌ {str(e)}"
|
|
421
436
|
if e.status_code == 403 and "lifetime limit" in str(e).lower():
|
|
422
|
-
error_msg += "\n\n💡 Tip: You've reached the free tier limit of
|
|
437
|
+
error_msg += "\n\n💡 Tip: You've reached the free tier limit of 3 indexing operations. Upgrade to Pro for unlimited access."
|
|
423
438
|
return [TextContent(type="text", text=error_msg)]
|
|
424
439
|
except Exception as e:
|
|
425
440
|
logger.error(f"Error searching documentation: {e}")
|
|
@@ -451,6 +466,9 @@ async def list_repositories() -> List[TextContent]:
|
|
|
451
466
|
# Format repository list
|
|
452
467
|
lines = ["# Indexed Repositories\n"]
|
|
453
468
|
|
|
469
|
+
# Check if any repositories have folder paths (contain /tree/)
|
|
470
|
+
has_folder_repos = any('/tree/' in repo.get('repository', '') for repo in repositories)
|
|
471
|
+
|
|
454
472
|
for repo in repositories:
|
|
455
473
|
status_icon = "✅" if repo.get("status") == "completed" else "⏳"
|
|
456
474
|
|
|
@@ -470,18 +488,36 @@ async def list_repositories() -> List[TextContent]:
|
|
|
470
488
|
lines.append(f"- **Indexed:** {repo['indexed_at']}")
|
|
471
489
|
if repo.get("error"):
|
|
472
490
|
lines.append(f"- **Error:** {repo['error']}")
|
|
491
|
+
|
|
492
|
+
# Add usage hint for completed repositories
|
|
493
|
+
if repo.get("status") == "completed":
|
|
494
|
+
lines.append(f"- **Usage:** `search_codebase(query, [\"{repo_name}\"])`")
|
|
495
|
+
|
|
496
|
+
# Add general usage instructions at the end
|
|
497
|
+
lines.extend([
|
|
498
|
+
"\n---",
|
|
499
|
+
"\n## Usage Tips",
|
|
500
|
+
"- To search all repositories: `search_codebase(\"your query\")`",
|
|
501
|
+
"- To search specific repository: `search_codebase(\"your query\", [\"owner/repo\"])`"
|
|
502
|
+
])
|
|
503
|
+
|
|
504
|
+
if has_folder_repos:
|
|
505
|
+
lines.extend([
|
|
506
|
+
"- For folder-indexed repositories: Use the EXACT repository path shown above",
|
|
507
|
+
" Example: `search_codebase(\"query\", [\"owner/repo/tree/branch/folder\"])`"
|
|
508
|
+
])
|
|
473
509
|
|
|
474
510
|
return [TextContent(type="text", text="\n".join(lines))]
|
|
475
511
|
|
|
476
512
|
except APIError as e:
|
|
477
513
|
logger.error(f"API Error listing repositories: {e} (status_code={e.status_code}, detail={e.detail})")
|
|
478
514
|
# Check for free tier limit errors
|
|
479
|
-
if e.status_code == 403 or "free tier limit" in str(e).lower() or "
|
|
515
|
+
if e.status_code == 403 or "free tier limit" in str(e).lower() or "indexing operations" in str(e).lower():
|
|
480
516
|
# Extract the specific limit message
|
|
481
|
-
if e.detail and "
|
|
517
|
+
if e.detail and "3 free indexing operations" in e.detail:
|
|
482
518
|
return [TextContent(
|
|
483
519
|
type="text",
|
|
484
|
-
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited
|
|
520
|
+
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited indexing."
|
|
485
521
|
)]
|
|
486
522
|
else:
|
|
487
523
|
return [TextContent(
|
|
@@ -494,10 +530,10 @@ async def list_repositories() -> List[TextContent]:
|
|
|
494
530
|
logger.error(f"Unexpected error listing repositories (type={type(e).__name__}): {e}")
|
|
495
531
|
# Check if this looks like an API limit error that wasn't caught properly
|
|
496
532
|
error_msg = str(e)
|
|
497
|
-
if "
|
|
533
|
+
if "indexing operations" in error_msg.lower() or "lifetime limit" in error_msg.lower():
|
|
498
534
|
return [TextContent(
|
|
499
535
|
type="text",
|
|
500
|
-
text=f"❌ {error_msg}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited
|
|
536
|
+
text=f"❌ {error_msg}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited indexing."
|
|
501
537
|
)]
|
|
502
538
|
return [TextContent(
|
|
503
539
|
type="text",
|
|
@@ -558,7 +594,7 @@ async def check_repository_status(repository: str) -> List[TextContent]:
|
|
|
558
594
|
logger.error(f"API Error checking repository status: {e}")
|
|
559
595
|
error_msg = f"❌ {str(e)}"
|
|
560
596
|
if e.status_code == 403 and "lifetime limit" in str(e).lower():
|
|
561
|
-
error_msg += "\n\n💡 Tip: You've reached the free tier limit of
|
|
597
|
+
error_msg += "\n\n💡 Tip: You've reached the free tier limit of 3 indexing operations. Upgrade to Pro for unlimited access."
|
|
562
598
|
return [TextContent(type="text", text=error_msg)]
|
|
563
599
|
except Exception as e:
|
|
564
600
|
logger.error(f"Error checking repository status: {e}")
|
|
@@ -603,7 +639,8 @@ async def index_documentation(
|
|
|
603
639
|
- When started indexing, prompt users to either use check_documentation_status tool or go to app.trynia.ai to check the status.
|
|
604
640
|
- By default, crawls the entire domain (up to 10,000 pages)
|
|
605
641
|
- Use exclude_patterns to filter out unwanted sections like blogs, changelogs, etc.
|
|
606
|
-
-
|
|
642
|
+
- If you want to search a specific folder, use the EXACT repository path shown above
|
|
643
|
+
- Example: `search_codebase(\"query\", [\"owner/repo/tree/branch/folder\"])`
|
|
607
644
|
"""
|
|
608
645
|
try:
|
|
609
646
|
client = await ensure_api_client()
|
|
@@ -645,7 +682,7 @@ async def index_documentation(
|
|
|
645
682
|
logger.error(f"API Error indexing documentation: {e}")
|
|
646
683
|
error_msg = f"❌ {str(e)}"
|
|
647
684
|
if e.status_code == 403 and "lifetime limit" in str(e).lower():
|
|
648
|
-
error_msg += "\n\n💡 Tip: You've reached the free tier limit of
|
|
685
|
+
error_msg += "\n\n💡 Tip: You've reached the free tier limit of 3 indexing operations. Upgrade to Pro for unlimited access."
|
|
649
686
|
return [TextContent(type="text", text=error_msg)]
|
|
650
687
|
except Exception as e:
|
|
651
688
|
logger.error(f"Error indexing documentation: {e}")
|
|
@@ -704,7 +741,7 @@ async def list_documentation() -> List[TextContent]:
|
|
|
704
741
|
logger.error(f"API Error listing documentation: {e}")
|
|
705
742
|
error_msg = f"❌ {str(e)}"
|
|
706
743
|
if e.status_code == 403 and "lifetime limit" in str(e).lower():
|
|
707
|
-
error_msg += "\n\n💡 Tip: You've reached the free tier limit of
|
|
744
|
+
error_msg += "\n\n💡 Tip: You've reached the free tier limit of 3 indexing operations. Upgrade to Pro for unlimited access."
|
|
708
745
|
return [TextContent(type="text", text=error_msg)]
|
|
709
746
|
except Exception as e:
|
|
710
747
|
logger.error(f"Error listing documentation: {e}")
|
|
@@ -770,7 +807,7 @@ async def check_documentation_status(source_id: str) -> List[TextContent]:
|
|
|
770
807
|
logger.error(f"API Error checking documentation status: {e}")
|
|
771
808
|
error_msg = f"❌ {str(e)}"
|
|
772
809
|
if e.status_code == 403 and "lifetime limit" in str(e).lower():
|
|
773
|
-
error_msg += "\n\n💡 Tip: You've reached the free tier limit of
|
|
810
|
+
error_msg += "\n\n💡 Tip: You've reached the free tier limit of 3 indexing operations. Upgrade to Pro for unlimited access."
|
|
774
811
|
return [TextContent(type="text", text=error_msg)]
|
|
775
812
|
except Exception as e:
|
|
776
813
|
logger.error(f"Error checking documentation status: {e}")
|
|
@@ -809,7 +846,7 @@ async def delete_documentation(source_id: str) -> List[TextContent]:
|
|
|
809
846
|
logger.error(f"API Error deleting documentation: {e}")
|
|
810
847
|
error_msg = f"❌ {str(e)}"
|
|
811
848
|
if e.status_code == 403 and "lifetime limit" in str(e).lower():
|
|
812
|
-
error_msg += "\n\n💡 Tip: You've reached the free tier limit of
|
|
849
|
+
error_msg += "\n\n💡 Tip: You've reached the free tier limit of 3 indexing operations. Upgrade to Pro for unlimited access."
|
|
813
850
|
return [TextContent(type="text", text=error_msg)]
|
|
814
851
|
except Exception as e:
|
|
815
852
|
logger.error(f"Error deleting documentation: {e}")
|
|
@@ -848,7 +885,7 @@ async def delete_repository(repository: str) -> List[TextContent]:
|
|
|
848
885
|
logger.error(f"API Error deleting repository: {e}")
|
|
849
886
|
error_msg = f"❌ {str(e)}"
|
|
850
887
|
if e.status_code == 403 and "lifetime limit" in str(e).lower():
|
|
851
|
-
error_msg += "\n\n💡 Tip: You've reached the free tier limit of
|
|
888
|
+
error_msg += "\n\n💡 Tip: You've reached the free tier limit of 3 indexing operations. Upgrade to Pro for unlimited access."
|
|
852
889
|
return [TextContent(type="text", text=error_msg)]
|
|
853
890
|
except Exception as e:
|
|
854
891
|
logger.error(f"Error deleting repository: {e}")
|
|
@@ -1099,11 +1136,11 @@ async def nia_web_search(
|
|
|
1099
1136
|
|
|
1100
1137
|
except APIError as e:
|
|
1101
1138
|
logger.error(f"API Error in web search: {e}")
|
|
1102
|
-
if e.status_code == 403 or "free tier limit" in str(e).lower() or "
|
|
1103
|
-
if e.detail and "
|
|
1139
|
+
if e.status_code == 403 or "free tier limit" in str(e).lower() or "indexing operations" in str(e).lower():
|
|
1140
|
+
if e.detail and "3 free indexing operations" in e.detail:
|
|
1104
1141
|
return [TextContent(
|
|
1105
1142
|
type="text",
|
|
1106
|
-
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited
|
|
1143
|
+
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited indexing."
|
|
1107
1144
|
)]
|
|
1108
1145
|
else:
|
|
1109
1146
|
return [TextContent(
|
|
@@ -1278,11 +1315,11 @@ async def nia_deep_research_agent(
|
|
|
1278
1315
|
|
|
1279
1316
|
except APIError as e:
|
|
1280
1317
|
logger.error(f"API Error in deep research: {e}")
|
|
1281
|
-
if e.status_code == 403 or "free tier limit" in str(e).lower() or "
|
|
1282
|
-
if e.detail and "
|
|
1318
|
+
if e.status_code == 403 or "free tier limit" in str(e).lower() or "indexing operations" in str(e).lower():
|
|
1319
|
+
if e.detail and "3 free indexing operations" in e.detail:
|
|
1283
1320
|
return [TextContent(
|
|
1284
1321
|
type="text",
|
|
1285
|
-
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited
|
|
1322
|
+
text=f"❌ {e.detail}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited indexing."
|
|
1286
1323
|
)]
|
|
1287
1324
|
else:
|
|
1288
1325
|
return [TextContent(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/assets/rules/claude_rules.md
RENAMED
|
File without changes
|
{nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/assets/rules/cursor_rules.md
RENAMED
|
File without changes
|
{nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/assets/rules/vscode_rules.md
RENAMED
|
File without changes
|
{nia_mcp_server-1.0.13 → nia_mcp_server-1.0.15}/src/nia_mcp_server/assets/rules/windsurf_rules.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|