aurora-actr 0.3.1__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.
- aurora/__init__.py +11 -0
- aurora/cli/__init__.py +42 -0
- aurora/cli/py.typed +0 -0
- aurora/context_code/__init__.py +42 -0
- aurora/context_code/py.typed +0 -0
- aurora/core/__init__.py +56 -0
- aurora/core/py.typed +0 -0
- aurora/mcp/__init__.py +10 -0
- aurora/mcp/config.py +116 -0
- aurora/mcp/server.py +385 -0
- aurora/mcp/tools.py +1198 -0
- aurora/reasoning/__init__.py +42 -0
- aurora/reasoning/py.typed +0 -0
- aurora/scripts/__init__.py +1 -0
- aurora/scripts/uninstall.py +105 -0
- aurora/soar/__init__.py +42 -0
- aurora/soar/py.typed +0 -0
- aurora/testing/__init__.py +42 -0
- aurora/testing/py.typed +0 -0
- aurora_actr-0.3.1.dist-info/METADATA +480 -0
- aurora_actr-0.3.1.dist-info/RECORD +24 -0
- aurora_actr-0.3.1.dist-info/WHEEL +5 -0
- aurora_actr-0.3.1.dist-info/entry_points.txt +4 -0
- aurora_actr-0.3.1.dist-info/top_level.txt +1 -0
aurora/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AURORA Namespace Package
|
|
3
|
+
|
|
4
|
+
This namespace package provides unified access to all AURORA components
|
|
5
|
+
through a single import path: aurora.core, aurora.context_code, etc.
|
|
6
|
+
|
|
7
|
+
This is a PEP 420 implicit namespace package that aggregates the
|
|
8
|
+
individual aurora-* packages into a unified namespace.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
|
aurora/cli/__init__.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Aurora CLI Namespace Package
|
|
3
|
+
|
|
4
|
+
Provides transparent access to aurora_cli package through the aurora.cli namespace.
|
|
5
|
+
This enables imports like:
|
|
6
|
+
from aurora.cli.config import Config
|
|
7
|
+
from aurora.cli.commands.init import init_command
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import importlib
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Pre-populate sys.modules with all known submodules to enable direct imports
|
|
15
|
+
_SUBMODULES = ["commands", "config", "errors", "escalation", "execution", "main", "memory_manager"]
|
|
16
|
+
|
|
17
|
+
for _submodule_name in _SUBMODULES:
|
|
18
|
+
_original = f"aurora_cli.{_submodule_name}"
|
|
19
|
+
_namespace = f"aurora.cli.{_submodule_name}"
|
|
20
|
+
try:
|
|
21
|
+
if _original not in sys.modules:
|
|
22
|
+
_module = importlib.import_module(_original)
|
|
23
|
+
else:
|
|
24
|
+
_module = sys.modules[_original]
|
|
25
|
+
sys.modules[_namespace] = _module
|
|
26
|
+
except ImportError:
|
|
27
|
+
pass # Submodule may not exist yet
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def __getattr__(name):
|
|
31
|
+
"""Dynamically import submodules from aurora_cli when accessed."""
|
|
32
|
+
original_module_name = f"aurora_cli.{name}"
|
|
33
|
+
try:
|
|
34
|
+
module = importlib.import_module(original_module_name)
|
|
35
|
+
sys.modules[f"aurora.cli.{name}"] = module
|
|
36
|
+
return module
|
|
37
|
+
except ImportError:
|
|
38
|
+
raise AttributeError(f"module 'aurora.cli' has no attribute '{name}'")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# Re-export all public members
|
|
42
|
+
from aurora_cli import * # noqa: E402, F401, F403, I001
|
aurora/cli/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Aurora Context Code Namespace Package
|
|
3
|
+
|
|
4
|
+
Provides transparent access to aurora_context_code package through the aurora.context_code namespace.
|
|
5
|
+
This enables imports like:
|
|
6
|
+
from aurora.context_code.semantic.hybrid_retriever import HybridRetriever
|
|
7
|
+
from aurora.context_code.parser import PythonParser
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import importlib
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Pre-populate sys.modules with all known submodules to enable direct imports
|
|
15
|
+
_SUBMODULES = ["languages", "parser", "registry", "semantic"]
|
|
16
|
+
|
|
17
|
+
for _submodule_name in _SUBMODULES:
|
|
18
|
+
_original = f"aurora_context_code.{_submodule_name}"
|
|
19
|
+
_namespace = f"aurora.context_code.{_submodule_name}"
|
|
20
|
+
try:
|
|
21
|
+
if _original not in sys.modules:
|
|
22
|
+
_module = importlib.import_module(_original)
|
|
23
|
+
else:
|
|
24
|
+
_module = sys.modules[_original]
|
|
25
|
+
sys.modules[_namespace] = _module
|
|
26
|
+
except ImportError:
|
|
27
|
+
pass # Submodule may not exist yet
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def __getattr__(name):
|
|
31
|
+
"""Dynamically import submodules from aurora_context_code when accessed."""
|
|
32
|
+
original_module_name = f"aurora_context_code.{name}"
|
|
33
|
+
try:
|
|
34
|
+
module = importlib.import_module(original_module_name)
|
|
35
|
+
sys.modules[f"aurora.context_code.{name}"] = module
|
|
36
|
+
return module
|
|
37
|
+
except ImportError:
|
|
38
|
+
raise AttributeError(f"module 'aurora.context_code' has no attribute '{name}'")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# Re-export all public members
|
|
42
|
+
from aurora_context_code import * # noqa: E402, F401, F403, I001
|
|
File without changes
|
aurora/core/__init__.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Aurora Core Namespace Package
|
|
3
|
+
|
|
4
|
+
Provides transparent access to aurora_core package through the aurora.core namespace.
|
|
5
|
+
This enables imports like:
|
|
6
|
+
from aurora.core.store import SQLiteStore
|
|
7
|
+
from aurora.core.chunks.base import Chunk
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import importlib
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Pre-populate sys.modules with all known submodules to enable direct imports
|
|
15
|
+
_SUBMODULES = [
|
|
16
|
+
"store",
|
|
17
|
+
"chunks",
|
|
18
|
+
"activation",
|
|
19
|
+
"budget",
|
|
20
|
+
"config",
|
|
21
|
+
"context",
|
|
22
|
+
"logging",
|
|
23
|
+
"optimization",
|
|
24
|
+
"resilience",
|
|
25
|
+
"types",
|
|
26
|
+
"exceptions",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
for _submodule_name in _SUBMODULES:
|
|
30
|
+
_original = f"aurora_core.{_submodule_name}"
|
|
31
|
+
_namespace = f"aurora.core.{_submodule_name}"
|
|
32
|
+
try:
|
|
33
|
+
if _original not in sys.modules:
|
|
34
|
+
_module = importlib.import_module(_original)
|
|
35
|
+
else:
|
|
36
|
+
_module = sys.modules[_original]
|
|
37
|
+
sys.modules[_namespace] = _module
|
|
38
|
+
except ImportError:
|
|
39
|
+
pass # Submodule may not exist yet
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def __getattr__(name):
|
|
43
|
+
"""Dynamically import submodules from aurora_core when accessed."""
|
|
44
|
+
# Map aurora.core.store -> aurora_core.store
|
|
45
|
+
original_module_name = f"aurora_core.{name}"
|
|
46
|
+
try:
|
|
47
|
+
module = importlib.import_module(original_module_name)
|
|
48
|
+
# Cache in sys.modules under both names
|
|
49
|
+
sys.modules[f"aurora.core.{name}"] = module
|
|
50
|
+
return module
|
|
51
|
+
except ImportError:
|
|
52
|
+
raise AttributeError(f"module 'aurora.core' has no attribute '{name}'")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# Re-export all public aurora_core members at the package level
|
|
56
|
+
from aurora_core import * # noqa: E402, F401, F403, I001
|
aurora/core/py.typed
ADDED
|
File without changes
|
aurora/mcp/__init__.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AURORA MCP Server - Model Context Protocol Integration.
|
|
3
|
+
|
|
4
|
+
This module provides FastMCP server implementation for integrating AURORA
|
|
5
|
+
with Claude Desktop and other MCP clients.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = "0.2.0"
|
|
9
|
+
|
|
10
|
+
__all__ = ["server", "tools", "config"]
|
aurora/mcp/config.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AURORA MCP Configuration and Logging.
|
|
3
|
+
|
|
4
|
+
This module provides logging configuration for MCP tools with performance metrics.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import time
|
|
9
|
+
from collections.abc import Callable
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from functools import wraps
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def setup_mcp_logging(log_file: str = "~/.aurora/mcp.log") -> logging.Logger:
|
|
17
|
+
"""
|
|
18
|
+
Setup MCP logging with performance metrics.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
log_file: Path to log file (default: ~/.aurora/mcp.log)
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Configured logger instance
|
|
25
|
+
"""
|
|
26
|
+
# Expand user path
|
|
27
|
+
log_path = Path(log_file).expanduser()
|
|
28
|
+
|
|
29
|
+
# Ensure directory exists
|
|
30
|
+
log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
31
|
+
|
|
32
|
+
# Create logger
|
|
33
|
+
logger = logging.getLogger("aurora.mcp")
|
|
34
|
+
logger.setLevel(logging.INFO)
|
|
35
|
+
|
|
36
|
+
# Remove existing handlers
|
|
37
|
+
logger.handlers = []
|
|
38
|
+
|
|
39
|
+
# File handler with custom format
|
|
40
|
+
file_handler = logging.FileHandler(str(log_path))
|
|
41
|
+
file_handler.setLevel(logging.INFO)
|
|
42
|
+
|
|
43
|
+
# Custom format: [timestamp] level tool_name metric1=value1 metric2=value2
|
|
44
|
+
formatter = logging.Formatter(
|
|
45
|
+
"[%(asctime)s] %(levelname)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S"
|
|
46
|
+
)
|
|
47
|
+
file_handler.setFormatter(formatter)
|
|
48
|
+
|
|
49
|
+
logger.addHandler(file_handler)
|
|
50
|
+
|
|
51
|
+
return logger
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def log_performance(tool_name: str) -> Callable:
|
|
55
|
+
"""
|
|
56
|
+
Decorator to log performance metrics for MCP tools.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
tool_name: Name of the MCP tool being logged
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Decorator function
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
@log_performance("aurora_search")
|
|
66
|
+
def aurora_search(query: str, limit: int = 10) -> str:
|
|
67
|
+
...
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
def decorator(func: Callable) -> Callable:
|
|
71
|
+
@wraps(func)
|
|
72
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
73
|
+
# Get logger
|
|
74
|
+
logger = logging.getLogger("aurora.mcp")
|
|
75
|
+
|
|
76
|
+
# Record start time
|
|
77
|
+
start_time = time.time()
|
|
78
|
+
|
|
79
|
+
# Extract relevant parameters for logging
|
|
80
|
+
params = []
|
|
81
|
+
if args:
|
|
82
|
+
# First arg is usually 'self', skip it
|
|
83
|
+
if len(args) > 1:
|
|
84
|
+
params.append(f"arg={args[1]}")
|
|
85
|
+
for key, value in kwargs.items():
|
|
86
|
+
params.append(f"{key}={value}")
|
|
87
|
+
|
|
88
|
+
param_str = " ".join(params) if params else "no_params"
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
# Execute function
|
|
92
|
+
result = func(*args, **kwargs)
|
|
93
|
+
|
|
94
|
+
# Calculate duration
|
|
95
|
+
duration_ms = (time.time() - start_time) * 1000
|
|
96
|
+
|
|
97
|
+
# Log success
|
|
98
|
+
logger.info(f"{tool_name} {param_str} latency={duration_ms:.1f}ms status=success")
|
|
99
|
+
|
|
100
|
+
return result
|
|
101
|
+
|
|
102
|
+
except Exception as e:
|
|
103
|
+
# Calculate duration
|
|
104
|
+
duration_ms = (time.time() - start_time) * 1000
|
|
105
|
+
|
|
106
|
+
# Log error
|
|
107
|
+
logger.error(
|
|
108
|
+
f"{tool_name} {param_str} latency={duration_ms:.1f}ms status=error error={str(e)}"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Re-raise exception
|
|
112
|
+
raise
|
|
113
|
+
|
|
114
|
+
return wrapper
|
|
115
|
+
|
|
116
|
+
return decorator
|
aurora/mcp/server.py
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
AURORA MCP Server - FastMCP implementation.
|
|
4
|
+
|
|
5
|
+
Provides Model Context Protocol server for AURORA codebase indexing and search.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import argparse
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
from fastmcp import FastMCP
|
|
16
|
+
except ImportError:
|
|
17
|
+
print("Error: FastMCP not installed. Install with: pip install fastmcp", file=sys.stderr)
|
|
18
|
+
sys.exit(1)
|
|
19
|
+
|
|
20
|
+
from aurora.mcp.tools import AuroraMCPTools
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AuroraMCPServer:
|
|
24
|
+
"""MCP Server for AURORA codebase tools."""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self, db_path: str | None = None, config_path: str | None = None, test_mode: bool = False
|
|
28
|
+
):
|
|
29
|
+
"""
|
|
30
|
+
Initialize AURORA MCP Server.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
db_path: Path to SQLite database (default: ~/.aurora/memory.db)
|
|
34
|
+
config_path: Path to AURORA config file (default: ~/.aurora/config.json)
|
|
35
|
+
test_mode: If True, skip FastMCP initialization (for testing)
|
|
36
|
+
"""
|
|
37
|
+
self.db_path = db_path or str(Path.home() / ".aurora" / "memory.db")
|
|
38
|
+
self.config_path = config_path or str(Path.home() / ".aurora" / "config.json")
|
|
39
|
+
self.test_mode = test_mode
|
|
40
|
+
|
|
41
|
+
# Initialize tools
|
|
42
|
+
self.tools = AuroraMCPTools(self.db_path, self.config_path)
|
|
43
|
+
|
|
44
|
+
# Initialize FastMCP server only if not in test mode
|
|
45
|
+
if not test_mode:
|
|
46
|
+
self.mcp = FastMCP("aurora")
|
|
47
|
+
# Register tools
|
|
48
|
+
self._register_tools()
|
|
49
|
+
else:
|
|
50
|
+
self.mcp = None
|
|
51
|
+
|
|
52
|
+
def _register_tools(self) -> None:
|
|
53
|
+
"""Register MCP tools with the server."""
|
|
54
|
+
|
|
55
|
+
@self.mcp.tool()
|
|
56
|
+
def aurora_search(query: str, limit: int = 10) -> str:
|
|
57
|
+
"""
|
|
58
|
+
Search AURORA indexed codebase.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
query: Search query string
|
|
62
|
+
limit: Maximum number of results (default: 10)
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
JSON string with search results
|
|
66
|
+
"""
|
|
67
|
+
return self.tools.aurora_search(query, limit)
|
|
68
|
+
|
|
69
|
+
@self.mcp.tool()
|
|
70
|
+
def aurora_index(path: str, pattern: str = "*.py") -> str:
|
|
71
|
+
"""
|
|
72
|
+
Index codebase directory.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
path: Directory path to index
|
|
76
|
+
pattern: File pattern to match (default: *.py)
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
JSON string with indexing stats
|
|
80
|
+
"""
|
|
81
|
+
return self.tools.aurora_index(path, pattern)
|
|
82
|
+
|
|
83
|
+
@self.mcp.tool()
|
|
84
|
+
def aurora_context(file_path: str, function: str | None = None) -> str:
|
|
85
|
+
"""
|
|
86
|
+
Get code context from file.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
file_path: Path to source file
|
|
90
|
+
function: Optional function name to extract
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
String with code content
|
|
94
|
+
"""
|
|
95
|
+
return self.tools.aurora_context(file_path, function)
|
|
96
|
+
|
|
97
|
+
@self.mcp.tool()
|
|
98
|
+
def aurora_related(chunk_id: str, max_hops: int = 2) -> str:
|
|
99
|
+
"""
|
|
100
|
+
Find related code chunks using ACT-R spreading activation.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
chunk_id: Source chunk ID
|
|
104
|
+
max_hops: Maximum relationship hops (default: 2)
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
JSON string with related chunks and activation scores
|
|
108
|
+
"""
|
|
109
|
+
return self.tools.aurora_related(chunk_id, max_hops)
|
|
110
|
+
|
|
111
|
+
@self.mcp.tool()
|
|
112
|
+
def aurora_query(
|
|
113
|
+
query: str,
|
|
114
|
+
limit: int = 10,
|
|
115
|
+
type_filter: str | None = None,
|
|
116
|
+
verbose: bool = False,
|
|
117
|
+
) -> str:
|
|
118
|
+
"""
|
|
119
|
+
Retrieve relevant context from AURORA memory without LLM inference.
|
|
120
|
+
|
|
121
|
+
This tool provides intelligent context retrieval with complexity assessment
|
|
122
|
+
and confidence scoring. It returns structured context for the host LLM
|
|
123
|
+
(Claude Code CLI) to reason about, rather than calling external LLM APIs.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
query: Natural language query string (required)
|
|
127
|
+
limit: Maximum number of chunks to retrieve (default: 10)
|
|
128
|
+
type_filter: Filter by memory type - "code", "reas", "know", or None (default: None)
|
|
129
|
+
verbose: Include detailed metadata in response (default: False)
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
JSON string with:
|
|
133
|
+
- context: Retrieved memory chunks with content, metadata, and relevance scores
|
|
134
|
+
- assessment: Complexity assessment and retrieval confidence score
|
|
135
|
+
- metadata: Database stats and result counts
|
|
136
|
+
|
|
137
|
+
Examples:
|
|
138
|
+
Basic retrieval:
|
|
139
|
+
aurora_query("What is a Python decorator?")
|
|
140
|
+
|
|
141
|
+
Type-filtered retrieval:
|
|
142
|
+
aurora_query("async patterns", type_filter="code", limit=5)
|
|
143
|
+
|
|
144
|
+
Detailed metadata:
|
|
145
|
+
aurora_query("SOAR pipeline", verbose=True)
|
|
146
|
+
|
|
147
|
+
Note:
|
|
148
|
+
No API key required. This tool runs inside Claude Code CLI which
|
|
149
|
+
provides the LLM reasoning capabilities. For standalone usage with
|
|
150
|
+
LLM responses, use the CLI command: $ aur query "your question"
|
|
151
|
+
"""
|
|
152
|
+
return self.tools.aurora_query(query, limit, type_filter, verbose)
|
|
153
|
+
|
|
154
|
+
@self.mcp.tool()
|
|
155
|
+
def aurora_get(index: int) -> str:
|
|
156
|
+
"""
|
|
157
|
+
Retrieve a full chunk by index from the last search results.
|
|
158
|
+
|
|
159
|
+
This tool allows you to get the complete content of a specific result
|
|
160
|
+
from your last aurora_search or aurora_query call. Results are numbered
|
|
161
|
+
starting from 1 (1-indexed).
|
|
162
|
+
|
|
163
|
+
Workflow:
|
|
164
|
+
1. Call aurora_search or aurora_query to get numbered results
|
|
165
|
+
2. Review the list and choose which result you want
|
|
166
|
+
3. Call aurora_get(N) to retrieve the full chunk for result N
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
index: 1-indexed position in last search results (must be >= 1)
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
JSON string with:
|
|
173
|
+
- chunk: Complete chunk with all metadata (id, type, content, file_path, etc.)
|
|
174
|
+
- metadata: Index position and total count
|
|
175
|
+
|
|
176
|
+
Examples:
|
|
177
|
+
After aurora_search("async patterns"):
|
|
178
|
+
aurora_get(1) # Get first result
|
|
179
|
+
aurora_get(3) # Get third result
|
|
180
|
+
|
|
181
|
+
Note:
|
|
182
|
+
Session cache expires after 10 minutes. Results are stored per-session
|
|
183
|
+
and cleared when a new search is performed.
|
|
184
|
+
"""
|
|
185
|
+
return self.tools.aurora_get(index)
|
|
186
|
+
|
|
187
|
+
@self.mcp.tool()
|
|
188
|
+
def aurora_list_agents() -> str:
|
|
189
|
+
"""
|
|
190
|
+
List all discovered agents from configured sources.
|
|
191
|
+
|
|
192
|
+
Use this tool to browse, discover, and find available agents. Returns
|
|
193
|
+
a complete inventory of all agents accessible in the current environment.
|
|
194
|
+
|
|
195
|
+
Primary action keywords: list, show, get, fetch, retrieve, browse, discover
|
|
196
|
+
Domain keywords: agents, specialists, experts, roles, personas, subagents, assistants
|
|
197
|
+
Context keywords: available, registered, defined, configured, ready, accessible, discovered
|
|
198
|
+
Use case keywords: what, which, who, all, every, complete, inventory, catalog
|
|
199
|
+
|
|
200
|
+
No API key required. Local agent directory listing only.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
JSON array of agents containing:
|
|
204
|
+
- id: Agent identifier (kebab-case)
|
|
205
|
+
- title: Agent role/title
|
|
206
|
+
- source_path: Path to agent markdown file
|
|
207
|
+
- when_to_use: Guidance on when to invoke this agent
|
|
208
|
+
|
|
209
|
+
Examples:
|
|
210
|
+
# List all available agents
|
|
211
|
+
aurora_list_agents()
|
|
212
|
+
|
|
213
|
+
# After listing, you can:
|
|
214
|
+
# - Use aurora_search_agents() to filter by keyword
|
|
215
|
+
# - Use aurora_show_agent(id) to view full agent details
|
|
216
|
+
"""
|
|
217
|
+
return self.tools.aurora_list_agents()
|
|
218
|
+
|
|
219
|
+
@self.mcp.tool()
|
|
220
|
+
def aurora_search_agents(query: str) -> str:
|
|
221
|
+
"""
|
|
222
|
+
Search agents by keyword with relevance scoring.
|
|
223
|
+
|
|
224
|
+
Use this tool to find, search, discover, and filter agents by keywords.
|
|
225
|
+
Returns matching agents sorted by relevance score (0.0-1.0).
|
|
226
|
+
|
|
227
|
+
Primary action keywords: search, find, discover, filter, locate, identify, match
|
|
228
|
+
Domain keywords: agent, specialist, expert, role, persona, subagent, assistant
|
|
229
|
+
Context keywords: for, with, about, related, relevant, matching, suitable
|
|
230
|
+
Use case keywords: help, assist, guide, when, which, who, best, right
|
|
231
|
+
|
|
232
|
+
Uses substring matching to search agent id, title, and when_to_use fields.
|
|
233
|
+
No API key required. Local substring-based search only.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
query: Search query string (required, non-empty)
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
JSON array of matching agents containing:
|
|
240
|
+
- id: Agent identifier
|
|
241
|
+
- title: Agent role/title
|
|
242
|
+
- source_path: Path to agent markdown file
|
|
243
|
+
- when_to_use: When to use guidance
|
|
244
|
+
- relevance_score: Match score from 0.0 to 1.0
|
|
245
|
+
|
|
246
|
+
Examples:
|
|
247
|
+
# Search for testing-related agents
|
|
248
|
+
aurora_search_agents("test")
|
|
249
|
+
|
|
250
|
+
# Find agents for code review
|
|
251
|
+
aurora_search_agents("review")
|
|
252
|
+
|
|
253
|
+
# Discover quality assurance specialists
|
|
254
|
+
aurora_search_agents("quality")
|
|
255
|
+
|
|
256
|
+
Note:
|
|
257
|
+
Returns empty array if no matches found. Results sorted by relevance
|
|
258
|
+
score descending (best matches first).
|
|
259
|
+
"""
|
|
260
|
+
return self.tools.aurora_search_agents(query)
|
|
261
|
+
|
|
262
|
+
@self.mcp.tool()
|
|
263
|
+
def aurora_show_agent(agent_id: str) -> str:
|
|
264
|
+
"""
|
|
265
|
+
Show full agent details including complete markdown content.
|
|
266
|
+
|
|
267
|
+
Use this tool to retrieve, view, get, fetch, or display full details for
|
|
268
|
+
a specific agent by ID. Returns complete agent information including the
|
|
269
|
+
entire markdown file content with instructions and examples.
|
|
270
|
+
|
|
271
|
+
Primary action keywords: show, get, retrieve, fetch, view, display, read, load
|
|
272
|
+
Domain keywords: agent, specialist, expert, role, persona, details, info
|
|
273
|
+
Context keywords: full, complete, entire, whole, detailed, comprehensive
|
|
274
|
+
Use case keywords: about, details, information, content, instructions, guide
|
|
275
|
+
|
|
276
|
+
No API key required. Reads local agent markdown file only.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
agent_id: Agent identifier (required, non-empty, kebab-case)
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
JSON with full agent details:
|
|
283
|
+
- id: Agent identifier
|
|
284
|
+
- title: Agent role/title
|
|
285
|
+
- source_path: Path to agent markdown file
|
|
286
|
+
- when_to_use: When to use guidance
|
|
287
|
+
- content: Complete markdown file content
|
|
288
|
+
|
|
289
|
+
Or error JSON if agent not found:
|
|
290
|
+
- error: "Agent not found"
|
|
291
|
+
- agent_id: The requested agent ID
|
|
292
|
+
|
|
293
|
+
Examples:
|
|
294
|
+
# Show full details for QA test architect
|
|
295
|
+
aurora_show_agent("qa-test-architect")
|
|
296
|
+
|
|
297
|
+
# Get complete information for full stack developer
|
|
298
|
+
aurora_show_agent("full-stack-dev")
|
|
299
|
+
|
|
300
|
+
# View orchestrator agent details
|
|
301
|
+
aurora_show_agent("orchestrator")
|
|
302
|
+
|
|
303
|
+
Note:
|
|
304
|
+
Use aurora_list_agents() or aurora_search_agents() to discover
|
|
305
|
+
available agent IDs first.
|
|
306
|
+
"""
|
|
307
|
+
return self.tools.aurora_show_agent(agent_id)
|
|
308
|
+
|
|
309
|
+
def run(self) -> None:
|
|
310
|
+
"""Run the MCP server."""
|
|
311
|
+
self.mcp.run()
|
|
312
|
+
|
|
313
|
+
def list_tools(self) -> None:
|
|
314
|
+
"""List all available tools (for testing)."""
|
|
315
|
+
print("AURORA MCP Server - Available Tools:")
|
|
316
|
+
print("=" * 50)
|
|
317
|
+
|
|
318
|
+
# Get registered tools from FastMCP
|
|
319
|
+
tools = [
|
|
320
|
+
("aurora_search", "Search indexed codebase with semantic + keyword search"),
|
|
321
|
+
("aurora_index", "Index a directory of code files"),
|
|
322
|
+
("aurora_context", "Retrieve code context from a specific file/function"),
|
|
323
|
+
("aurora_related", "Find related code using ACT-R spreading activation"),
|
|
324
|
+
("aurora_query", "Retrieve relevant context without LLM inference"),
|
|
325
|
+
("aurora_get", "Get full chunk by index from last search results"),
|
|
326
|
+
("aurora_list_agents", "List all discovered agents from configured sources"),
|
|
327
|
+
("aurora_search_agents", "Search agents by keyword with relevance scoring"),
|
|
328
|
+
("aurora_show_agent", "Show full agent details including markdown content"),
|
|
329
|
+
]
|
|
330
|
+
|
|
331
|
+
for name, description in tools:
|
|
332
|
+
print(f"\n{name}:")
|
|
333
|
+
print(f" {description}")
|
|
334
|
+
|
|
335
|
+
print("\n" + "=" * 50)
|
|
336
|
+
print(f"Database: {self.db_path}")
|
|
337
|
+
print(f"Config: {self.config_path}")
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def main() -> None:
|
|
341
|
+
"""Main entry point for MCP server CLI."""
|
|
342
|
+
parser = argparse.ArgumentParser(
|
|
343
|
+
description="AURORA MCP Server - Model Context Protocol integration",
|
|
344
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
parser.add_argument(
|
|
348
|
+
"--db-path",
|
|
349
|
+
type=str,
|
|
350
|
+
help="Path to SQLite database (default: ~/.aurora/memory.db)",
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
parser.add_argument(
|
|
354
|
+
"--config",
|
|
355
|
+
type=str,
|
|
356
|
+
help="Path to AURORA config file (default: ~/.aurora/config.json)",
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
parser.add_argument(
|
|
360
|
+
"--test",
|
|
361
|
+
action="store_true",
|
|
362
|
+
help="Test mode: start server and list available tools",
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
args = parser.parse_args()
|
|
366
|
+
|
|
367
|
+
# Create server instance
|
|
368
|
+
server = AuroraMCPServer(db_path=args.db_path, config_path=args.config, test_mode=args.test)
|
|
369
|
+
|
|
370
|
+
if args.test:
|
|
371
|
+
print("AURORA MCP Server - Test Mode")
|
|
372
|
+
print("=" * 50)
|
|
373
|
+
server.list_tools()
|
|
374
|
+
print("\nTest mode complete. Server initialized successfully!")
|
|
375
|
+
sys.exit(0)
|
|
376
|
+
|
|
377
|
+
# Run server
|
|
378
|
+
print("Starting AURORA MCP Server...")
|
|
379
|
+
print(f"Database: {server.db_path}")
|
|
380
|
+
print(f"Config: {server.config_path}")
|
|
381
|
+
server.run()
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
if __name__ == "__main__":
|
|
385
|
+
main()
|