nia-mcp-server 1.0.23__py3-none-any.whl → 1.0.25__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nia-mcp-server might be problematic. Click here for more details.
- nia_mcp_server/__init__.py +1 -1
- nia_mcp_server/api_client.py +10 -2
- nia_mcp_server/server.py +102 -167
- {nia_mcp_server-1.0.23.dist-info → nia_mcp_server-1.0.25.dist-info}/METADATA +1 -1
- {nia_mcp_server-1.0.23.dist-info → nia_mcp_server-1.0.25.dist-info}/RECORD +8 -8
- {nia_mcp_server-1.0.23.dist-info → nia_mcp_server-1.0.25.dist-info}/WHEEL +0 -0
- {nia_mcp_server-1.0.23.dist-info → nia_mcp_server-1.0.25.dist-info}/entry_points.txt +0 -0
- {nia_mcp_server-1.0.23.dist-info → nia_mcp_server-1.0.25.dist-info}/licenses/LICENSE +0 -0
nia_mcp_server/__init__.py
CHANGED
nia_mcp_server/api_client.py
CHANGED
|
@@ -28,7 +28,7 @@ class NIAApiClient:
|
|
|
28
28
|
self.client = httpx.AsyncClient(
|
|
29
29
|
headers={
|
|
30
30
|
"Authorization": f"Bearer {api_key}",
|
|
31
|
-
"User-Agent": "nia-mcp-server/1.0.
|
|
31
|
+
"User-Agent": "nia-mcp-server/1.0.25",
|
|
32
32
|
"Content-Type": "application/json"
|
|
33
33
|
},
|
|
34
34
|
timeout=720.0 # 12 minute timeout for deep research operations
|
|
@@ -926,7 +926,9 @@ class NIAApiClient:
|
|
|
926
926
|
content: str,
|
|
927
927
|
agent_source: str,
|
|
928
928
|
tags: List[str] = None,
|
|
929
|
-
metadata: Dict[str, Any] = None
|
|
929
|
+
metadata: Dict[str, Any] = None,
|
|
930
|
+
nia_references: Optional[Dict[str, Any]] = None,
|
|
931
|
+
edited_files: Optional[List[Dict[str, Any]]] = None
|
|
930
932
|
) -> Dict[str, Any]:
|
|
931
933
|
"""Save a conversation context for cross-agent sharing."""
|
|
932
934
|
try:
|
|
@@ -939,6 +941,12 @@ class NIAApiClient:
|
|
|
939
941
|
"metadata": metadata or {}
|
|
940
942
|
}
|
|
941
943
|
|
|
944
|
+
# Add new structured fields if provided
|
|
945
|
+
if nia_references is not None:
|
|
946
|
+
payload["nia_references"] = nia_references
|
|
947
|
+
if edited_files is not None:
|
|
948
|
+
payload["edited_files"] = edited_files
|
|
949
|
+
|
|
942
950
|
response = await self.client.post(
|
|
943
951
|
f"{self.base_url}/v2/contexts",
|
|
944
952
|
json=payload
|
nia_mcp_server/server.py
CHANGED
|
@@ -2826,160 +2826,6 @@ async def nia_package_search_read_file(
|
|
|
2826
2826
|
f"- The line range is valid (1-based, max 200 lines)"
|
|
2827
2827
|
)]
|
|
2828
2828
|
|
|
2829
|
-
# @mcp.tool()
|
|
2830
|
-
async def visualize_codebase(
|
|
2831
|
-
repository: str
|
|
2832
|
-
) -> List[TextContent]:
|
|
2833
|
-
"""
|
|
2834
|
-
Open the graph visualization for an indexed repository in a browser.
|
|
2835
|
-
|
|
2836
|
-
This tool launches a browser with the interactive graph visualization
|
|
2837
|
-
that shows the code structure, relationships, and dependencies of
|
|
2838
|
-
the indexed codebase.
|
|
2839
|
-
|
|
2840
|
-
Args:
|
|
2841
|
-
repository: Repository in owner/repo format (e.g., "facebook/react")
|
|
2842
|
-
|
|
2843
|
-
Returns:
|
|
2844
|
-
Status message with the URL that was opened
|
|
2845
|
-
|
|
2846
|
-
Examples:
|
|
2847
|
-
- visualize_codebase("facebook/react")
|
|
2848
|
-
- visualize_codebase("langchain-ai/langchain")
|
|
2849
|
-
"""
|
|
2850
|
-
try:
|
|
2851
|
-
client = await ensure_api_client()
|
|
2852
|
-
|
|
2853
|
-
logger.info(f"Looking up repository: {repository}")
|
|
2854
|
-
|
|
2855
|
-
# List all repositories to find the matching one
|
|
2856
|
-
repositories = await client.list_repositories()
|
|
2857
|
-
|
|
2858
|
-
# Find the repository by name
|
|
2859
|
-
matching_repo = None
|
|
2860
|
-
for repo in repositories:
|
|
2861
|
-
if repo.get("repository") == repository:
|
|
2862
|
-
matching_repo = repo
|
|
2863
|
-
break
|
|
2864
|
-
|
|
2865
|
-
if not matching_repo:
|
|
2866
|
-
# Try case-insensitive match as fallback
|
|
2867
|
-
repository_lower = repository.lower()
|
|
2868
|
-
for repo in repositories:
|
|
2869
|
-
if repo.get("repository", "").lower() == repository_lower:
|
|
2870
|
-
matching_repo = repo
|
|
2871
|
-
break
|
|
2872
|
-
|
|
2873
|
-
if not matching_repo:
|
|
2874
|
-
return [TextContent(
|
|
2875
|
-
type="text",
|
|
2876
|
-
text=f"❌ Repository '{repository}' not found.\n\n"
|
|
2877
|
-
f"Available repositories:\n" +
|
|
2878
|
-
"\n".join(f"- {r.get('repository')}" for r in repositories if r.get('repository')) +
|
|
2879
|
-
"\n\nUse `list_repositories` to see all indexed repositories."
|
|
2880
|
-
)]
|
|
2881
|
-
|
|
2882
|
-
# Check if the repository is fully indexed
|
|
2883
|
-
status = matching_repo.get("status", "unknown")
|
|
2884
|
-
# Use the actual project ID if available, fall back to repository_id
|
|
2885
|
-
repository_id = matching_repo.get("id") or matching_repo.get("repository_id")
|
|
2886
|
-
|
|
2887
|
-
if not repository_id:
|
|
2888
|
-
return [TextContent(
|
|
2889
|
-
type="text",
|
|
2890
|
-
text=f"❌ No repository ID found for '{repository}'. This may be a data inconsistency."
|
|
2891
|
-
)]
|
|
2892
|
-
|
|
2893
|
-
if status != "completed":
|
|
2894
|
-
warning_msg = f"⚠️ Note: Repository '{repository}' is currently {status}.\n"
|
|
2895
|
-
if status == "indexing":
|
|
2896
|
-
warning_msg += "The visualization may show incomplete data.\n\n"
|
|
2897
|
-
elif status == "error":
|
|
2898
|
-
error_msg = matching_repo.get("error", "Unknown error")
|
|
2899
|
-
warning_msg += f"Error: {error_msg}\n\n"
|
|
2900
|
-
else:
|
|
2901
|
-
warning_msg += "The visualization may not be available.\n\n"
|
|
2902
|
-
else:
|
|
2903
|
-
warning_msg = ""
|
|
2904
|
-
|
|
2905
|
-
# Determine the base URL based on the API URL
|
|
2906
|
-
api_base_url = client.base_url
|
|
2907
|
-
if "localhost" in api_base_url or "127.0.0.1" in api_base_url:
|
|
2908
|
-
# Local development
|
|
2909
|
-
app_base_url = "http://localhost:3000"
|
|
2910
|
-
else:
|
|
2911
|
-
# Production
|
|
2912
|
-
app_base_url = "https://app.trynia.ai"
|
|
2913
|
-
|
|
2914
|
-
# Construct the visualization URL
|
|
2915
|
-
visualization_url = f"{app_base_url}/visualize/{repository_id}"
|
|
2916
|
-
|
|
2917
|
-
# Try to open the browser
|
|
2918
|
-
try:
|
|
2919
|
-
webbrowser.open(visualization_url)
|
|
2920
|
-
browser_opened = True
|
|
2921
|
-
open_msg = "✅ Opening graph visualization in your default browser..."
|
|
2922
|
-
except Exception as e:
|
|
2923
|
-
logger.warning(f"Failed to open browser: {e}")
|
|
2924
|
-
browser_opened = False
|
|
2925
|
-
open_msg = "⚠️ Could not automatically open browser."
|
|
2926
|
-
|
|
2927
|
-
# Format the response
|
|
2928
|
-
response_lines = [
|
|
2929
|
-
f"# Graph Visualization: {repository}",
|
|
2930
|
-
"",
|
|
2931
|
-
warning_msg if warning_msg else "",
|
|
2932
|
-
open_msg,
|
|
2933
|
-
"",
|
|
2934
|
-
f"**URL:** {visualization_url}",
|
|
2935
|
-
"",
|
|
2936
|
-
]
|
|
2937
|
-
|
|
2938
|
-
if matching_repo.get("display_name"):
|
|
2939
|
-
response_lines.append(f"**Display Name:** {matching_repo['display_name']}")
|
|
2940
|
-
|
|
2941
|
-
response_lines.extend([
|
|
2942
|
-
f"**Branch:** {matching_repo.get('branch', 'main')}",
|
|
2943
|
-
f"**Status:** {status}",
|
|
2944
|
-
"",
|
|
2945
|
-
"## Features Available:",
|
|
2946
|
-
"- 🔍 Interactive force-directed graph",
|
|
2947
|
-
"- 🎨 Color-coded node types (functions, classes, files, etc.)",
|
|
2948
|
-
"- 🔗 Relationship visualization (calls, imports, inherits, etc.)",
|
|
2949
|
-
"- 💬 Click on any node to chat with that specific code element",
|
|
2950
|
-
"- 🔎 Search and filter capabilities",
|
|
2951
|
-
"- 📊 Graph statistics and insights"
|
|
2952
|
-
])
|
|
2953
|
-
|
|
2954
|
-
if not browser_opened:
|
|
2955
|
-
response_lines.extend([
|
|
2956
|
-
"",
|
|
2957
|
-
"**Manual Access:**",
|
|
2958
|
-
f"Copy and paste this URL into your browser: {visualization_url}"
|
|
2959
|
-
])
|
|
2960
|
-
|
|
2961
|
-
return [TextContent(
|
|
2962
|
-
type="text",
|
|
2963
|
-
text="\n".join(response_lines)
|
|
2964
|
-
)]
|
|
2965
|
-
|
|
2966
|
-
except APIError as e:
|
|
2967
|
-
logger.error(f"API Error in visualize_codebase: {e}")
|
|
2968
|
-
if e.status_code == 403 or "free tier limit" in str(e).lower():
|
|
2969
|
-
return [TextContent(
|
|
2970
|
-
type="text",
|
|
2971
|
-
text=f"❌ {str(e)}\n\n💡 Tip: Upgrade to Pro at https://trynia.ai/billing for unlimited access."
|
|
2972
|
-
)]
|
|
2973
|
-
else:
|
|
2974
|
-
return [TextContent(type="text", text=f"❌ {str(e)}")]
|
|
2975
|
-
except Exception as e:
|
|
2976
|
-
logger.error(f"Error in visualize_codebase: {e}")
|
|
2977
|
-
return [TextContent(
|
|
2978
|
-
type="text",
|
|
2979
|
-
text=f"❌ Error opening visualization: {str(e)}"
|
|
2980
|
-
)]
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
2829
|
@mcp.tool()
|
|
2984
2830
|
async def nia_bug_report(
|
|
2985
2831
|
description: str,
|
|
@@ -3094,7 +2940,9 @@ async def save_context(
|
|
|
3094
2940
|
content: str,
|
|
3095
2941
|
agent_source: str,
|
|
3096
2942
|
tags: Optional[List[str]] = None,
|
|
3097
|
-
metadata: Optional[dict] = None
|
|
2943
|
+
metadata: Optional[dict] = None,
|
|
2944
|
+
nia_references: Optional[dict] = None,
|
|
2945
|
+
edited_files: Optional[List[dict]] = None
|
|
3098
2946
|
) -> List[TextContent]:
|
|
3099
2947
|
"""
|
|
3100
2948
|
Save a conversation context for cross-agent sharing.
|
|
@@ -3108,8 +2956,16 @@ async def save_context(
|
|
|
3108
2956
|
summary: Brief summary of the conversation (10-1000 characters)
|
|
3109
2957
|
content: Full conversation context - the agent should compact the conversation history but keep all important parts togethers, as well as code snippets. No excuses.
|
|
3110
2958
|
agent_source: Which agent is creating this context (e.g., "cursor", "claude-code", "windsurf")
|
|
3111
|
-
tags: Optional list of searchable tags
|
|
2959
|
+
tags: Optional list of searchable tags
|
|
3112
2960
|
metadata: Optional metadata like file paths, repositories discussed, etc.
|
|
2961
|
+
nia_references: Structured data about NIA resources used during conversation
|
|
2962
|
+
Format: {
|
|
2963
|
+
"indexed_resources": [{"identifier": "owner/repo", "resource_type": "repository", "purpose": "Used for authentication patterns"}],
|
|
2964
|
+
"search_queries": [{"query": "JWT implementation", "query_type": "codebase", "resources_searched": ["owner/repo"], "key_findings": "Found JWT utils in auth folder"}],
|
|
2965
|
+
"session_summary": "Used NIA to explore authentication patterns and API design"
|
|
2966
|
+
}
|
|
2967
|
+
edited_files: List of files that were modified during conversation
|
|
2968
|
+
Format: [{"file_path": "src/auth.ts", "operation": "modified", "changes_description": "Added JWT validation", "key_changes": ["Added validate() function"]}]
|
|
3113
2969
|
|
|
3114
2970
|
Returns:
|
|
3115
2971
|
Confirmation of successful context save with context ID
|
|
@@ -3121,7 +2977,11 @@ async def save_context(
|
|
|
3121
2977
|
content="User asked about implementing streaming... [agent should include conversation]",
|
|
3122
2978
|
agent_source="cursor",
|
|
3123
2979
|
tags=["streaming", "ai-sdk", "implementation"],
|
|
3124
|
-
|
|
2980
|
+
nia_references={
|
|
2981
|
+
"indexed_resources": [{"identifier": "vercel/ai", "resource_type": "repository", "purpose": "Reference for streaming implementation"}],
|
|
2982
|
+
"search_queries": [{"query": "streaming API", "query_type": "documentation", "key_findings": "Found useChat hook with streaming"}]
|
|
2983
|
+
},
|
|
2984
|
+
edited_files=[{"file_path": "src/chat.ts", "operation": "created", "changes_description": "Added streaming chat component"}]
|
|
3125
2985
|
)
|
|
3126
2986
|
"""
|
|
3127
2987
|
try:
|
|
@@ -3144,9 +3004,6 @@ async def save_context(
|
|
|
3144
3004
|
if not agent_source or not agent_source.strip():
|
|
3145
3005
|
return [TextContent(type="text", text="❌ Error: Agent source is required")]
|
|
3146
3006
|
|
|
3147
|
-
if tags and len(tags) > 10:
|
|
3148
|
-
return [TextContent(type="text", text="❌ Error: Maximum 10 tags allowed")]
|
|
3149
|
-
|
|
3150
3007
|
client = await ensure_api_client()
|
|
3151
3008
|
|
|
3152
3009
|
logger.info(f"Saving context: title='{title}', agent={agent_source}, content_length={len(content)}")
|
|
@@ -3157,7 +3014,9 @@ async def save_context(
|
|
|
3157
3014
|
content=content,
|
|
3158
3015
|
agent_source=agent_source.strip(),
|
|
3159
3016
|
tags=tags or [],
|
|
3160
|
-
metadata=metadata or {}
|
|
3017
|
+
metadata=metadata or {},
|
|
3018
|
+
nia_references=nia_references,
|
|
3019
|
+
edited_files=edited_files or []
|
|
3161
3020
|
)
|
|
3162
3021
|
|
|
3163
3022
|
context_id = result.get("id")
|
|
@@ -3360,10 +3219,81 @@ async def retrieve_context(context_id: str) -> List[TextContent]:
|
|
|
3360
3219
|
|
|
3361
3220
|
response += f"\n📝 **Summary:**\n{context['summary']}\n\n"
|
|
3362
3221
|
|
|
3222
|
+
# Add NIA References - CRITICAL for context handoffs
|
|
3223
|
+
# Use 'or {}' to handle cases where nia_references is None (not just missing)
|
|
3224
|
+
nia_references = context.get('nia_references') or {}
|
|
3225
|
+
if nia_references:
|
|
3226
|
+
response += "🧠 **NIA RESOURCES USED - RECOMMENDED ACTIONS:**\n"
|
|
3227
|
+
|
|
3228
|
+
indexed_resources = nia_references.get('indexed_resources', [])
|
|
3229
|
+
if indexed_resources:
|
|
3230
|
+
response += "**📦 Re-index these resources:**\n"
|
|
3231
|
+
for resource in indexed_resources:
|
|
3232
|
+
identifier = resource.get('identifier', 'Unknown')
|
|
3233
|
+
resource_type = resource.get('resource_type', 'unknown')
|
|
3234
|
+
purpose = resource.get('purpose', 'No purpose specified')
|
|
3235
|
+
|
|
3236
|
+
if resource_type == 'repository':
|
|
3237
|
+
response += f"• `Index {identifier}` - {purpose}\n"
|
|
3238
|
+
elif resource_type == 'documentation':
|
|
3239
|
+
response += f"• `Index documentation {identifier}` - {purpose}\n"
|
|
3240
|
+
else:
|
|
3241
|
+
response += f"• `Index {identifier}` ({resource_type}) - {purpose}\n"
|
|
3242
|
+
response += "\n"
|
|
3243
|
+
|
|
3244
|
+
search_queries = nia_references.get('search_queries', [])
|
|
3245
|
+
if search_queries:
|
|
3246
|
+
response += "**🔍 Useful search queries to re-run:**\n"
|
|
3247
|
+
for query in search_queries:
|
|
3248
|
+
query_text = query.get('query', 'Unknown query')
|
|
3249
|
+
query_type = query.get('query_type', 'search')
|
|
3250
|
+
key_findings = query.get('key_findings', 'No findings specified')
|
|
3251
|
+
resources_searched = query.get('resources_searched', [])
|
|
3252
|
+
|
|
3253
|
+
response += f"• **Query:** `{query_text}` ({query_type})\n"
|
|
3254
|
+
if resources_searched:
|
|
3255
|
+
response += f" **Resources:** {', '.join(resources_searched)}\n"
|
|
3256
|
+
response += f" **Key Findings:** {key_findings}\n"
|
|
3257
|
+
response += "\n"
|
|
3258
|
+
|
|
3259
|
+
session_summary = nia_references.get('session_summary')
|
|
3260
|
+
if session_summary:
|
|
3261
|
+
response += f"**📋 NIA Session Summary:** {session_summary}\n\n"
|
|
3262
|
+
|
|
3263
|
+
# Add Edited Files - CRITICAL for code handoffs
|
|
3264
|
+
# Use 'or []' to handle cases where edited_files is None (not just missing)
|
|
3265
|
+
edited_files = context.get('edited_files') or []
|
|
3266
|
+
if edited_files:
|
|
3267
|
+
response += "📝 **FILES MODIFIED - READ THESE TO GET UP TO SPEED:**\n"
|
|
3268
|
+
for file_info in edited_files:
|
|
3269
|
+
file_path = file_info.get('file_path', 'Unknown file')
|
|
3270
|
+
operation = file_info.get('operation', 'modified')
|
|
3271
|
+
changes_desc = file_info.get('changes_description', 'No description')
|
|
3272
|
+
key_changes = file_info.get('key_changes', [])
|
|
3273
|
+
language = file_info.get('language', '')
|
|
3274
|
+
|
|
3275
|
+
operation_emoji = {
|
|
3276
|
+
'created': '🆕',
|
|
3277
|
+
'modified': '✏️',
|
|
3278
|
+
'deleted': '🗑️'
|
|
3279
|
+
}.get(operation, '📄')
|
|
3280
|
+
|
|
3281
|
+
response += f"• {operation_emoji} **`{file_path}`** ({operation})\n"
|
|
3282
|
+
response += f" **Changes:** {changes_desc}\n"
|
|
3283
|
+
|
|
3284
|
+
if key_changes:
|
|
3285
|
+
response += f" **Key Changes:** {', '.join(key_changes)}\n"
|
|
3286
|
+
if language:
|
|
3287
|
+
response += f" **Language:** {language}\n"
|
|
3288
|
+
|
|
3289
|
+
response += f" **💡 Action:** Read this file with: `Read {file_path}`\n"
|
|
3290
|
+
response += "\n"
|
|
3291
|
+
|
|
3363
3292
|
# Add metadata if available
|
|
3364
|
-
|
|
3293
|
+
# Use 'or {}' to handle cases where metadata is None (not just missing)
|
|
3294
|
+
metadata = context.get('metadata') or {}
|
|
3365
3295
|
if metadata:
|
|
3366
|
-
response += f"📊 **Metadata:**\n"
|
|
3296
|
+
response += f"📊 **Additional Metadata:**\n"
|
|
3367
3297
|
for key, value in metadata.items():
|
|
3368
3298
|
if isinstance(value, list):
|
|
3369
3299
|
response += f"• **{key}:** {', '.join(map(str, value))}\n"
|
|
@@ -3374,10 +3304,15 @@ async def retrieve_context(context_id: str) -> List[TextContent]:
|
|
|
3374
3304
|
response += f"📄 **Full Context:**\n\n{context['content']}\n\n"
|
|
3375
3305
|
|
|
3376
3306
|
response += f"---\n"
|
|
3377
|
-
response += f"
|
|
3378
|
-
response += f"• This context was created by {context['agent_source']}
|
|
3379
|
-
|
|
3380
|
-
|
|
3307
|
+
response += f"🚀 **NEXT STEPS FOR SEAMLESS HANDOFF:**\n"
|
|
3308
|
+
response += f"• This context was created by **{context['agent_source']}**\n"
|
|
3309
|
+
|
|
3310
|
+
if nia_references.get('search_queries'):
|
|
3311
|
+
response += f"• **RECOMMENDED:** Re-run the search queries to get the same insights\n"
|
|
3312
|
+
if edited_files:
|
|
3313
|
+
response += f"• **ESSENTIAL:** Read the modified files above to understand code changes\n"
|
|
3314
|
+
|
|
3315
|
+
response += f"• Use the summary and full context to understand the strategic planning\n"
|
|
3381
3316
|
|
|
3382
3317
|
return [TextContent(type="text", text=response)]
|
|
3383
3318
|
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
nia_mcp_server/__init__.py,sha256=
|
|
1
|
+
nia_mcp_server/__init__.py,sha256=_IbmZ23vCb-dFXG91RhQmFhM7IbSunVkuUJH0sPLZDg,87
|
|
2
2
|
nia_mcp_server/__main__.py,sha256=YQSpFtDeKp18r8mKr084cHnRFV4416_EKCu9FTM8_ik,394
|
|
3
|
-
nia_mcp_server/api_client.py,sha256=
|
|
3
|
+
nia_mcp_server/api_client.py,sha256=zXeJQAbvwVsAWgyeEko_5kEm8VIilcpcnGg5qMKFBnU,41546
|
|
4
4
|
nia_mcp_server/cli.py,sha256=32VSPNIocXtDgVBDZNZsxvj3kytBn54_a1pIE84vOdY,1834
|
|
5
5
|
nia_mcp_server/profiles.py,sha256=2DD8PFRr5Ij4IK4sPUz0mH8aKjkrEtkKLC1R0iki2bA,7221
|
|
6
6
|
nia_mcp_server/project_init.py,sha256=T0-ziJhofL4L8APwnM43BLhxtlmOHaYH-V9PF2yXLw4,7138
|
|
7
7
|
nia_mcp_server/rule_transformer.py,sha256=wCxoQ1Kl_rI9mUFnh9kG5iCXYU4QInrmFQOReZfAFVo,11000
|
|
8
|
-
nia_mcp_server/server.py,sha256=
|
|
8
|
+
nia_mcp_server/server.py,sha256=oyFSz0xqMl57m-3I7oL0dzGjRAtBzB0dWa0VcqRy5hw,156571
|
|
9
9
|
nia_mcp_server/setup.py,sha256=nJXVY8NHGtWROtoH8DW-3uOgyuPs4F9dW0cNhcbCLrM,5355
|
|
10
10
|
nia_mcp_server/assets/rules/claude_rules.md,sha256=HNL5GJMUbFxSpNbIAJUQWqAywjMl4lf530I1in69aNY,7380
|
|
11
11
|
nia_mcp_server/assets/rules/cursor_rules.md,sha256=hd6lhzNrK1ULQUYIEVeOnyKnuLKq4hmwZPbMqGUI1Lk,1720
|
|
12
12
|
nia_mcp_server/assets/rules/nia_rules.md,sha256=l6sx000uqoczoHYqOPp4hnNgyfpnhvO9NyT0fVx5nU0,8059
|
|
13
13
|
nia_mcp_server/assets/rules/vscode_rules.md,sha256=fqn4aJO_bhftaCGkVoquruQHf3EaREQJQWHXq6a4FOk,6967
|
|
14
14
|
nia_mcp_server/assets/rules/windsurf_rules.md,sha256=PzU2as5gaiVsV6PAzg8T_-GR7VCyRQGMjAHcSzYF_ms,3354
|
|
15
|
-
nia_mcp_server-1.0.
|
|
16
|
-
nia_mcp_server-1.0.
|
|
17
|
-
nia_mcp_server-1.0.
|
|
18
|
-
nia_mcp_server-1.0.
|
|
19
|
-
nia_mcp_server-1.0.
|
|
15
|
+
nia_mcp_server-1.0.25.dist-info/METADATA,sha256=tsMmAI_cehFBGhWmw1FeXco_WFFJziTnBnI57HG7Tdk,1324
|
|
16
|
+
nia_mcp_server-1.0.25.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
17
|
+
nia_mcp_server-1.0.25.dist-info/entry_points.txt,sha256=V74FQEp48pfWxPCl7B9mihtqvIJNVjCSbRfCz4ww77I,64
|
|
18
|
+
nia_mcp_server-1.0.25.dist-info/licenses/LICENSE,sha256=IrdVKi3bsiB2MTLM26MltBRpwyNi-8P6Cy0EnmAN76A,1557
|
|
19
|
+
nia_mcp_server-1.0.25.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|