@crowley/rag-mcp 1.0.5 → 1.1.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.
- package/dist/annotations.d.ts +16 -0
- package/dist/annotations.js +158 -0
- package/dist/context-enrichment.js +7 -0
- package/dist/formatters.d.ts +2 -0
- package/dist/formatters.js +12 -0
- package/dist/index.js +99 -47
- package/dist/schemas.d.ts +97 -0
- package/dist/schemas.js +128 -0
- package/dist/tool-middleware.d.ts +40 -0
- package/dist/tool-middleware.js +216 -0
- package/dist/tool-registry.js +2 -1
- package/dist/tools/advanced.d.ts +2 -2
- package/dist/tools/advanced.js +200 -275
- package/dist/tools/agents.d.ts +2 -2
- package/dist/tools/agents.js +59 -78
- package/dist/tools/analytics.d.ts +2 -2
- package/dist/tools/analytics.js +170 -210
- package/dist/tools/architecture.d.ts +2 -2
- package/dist/tools/architecture.js +506 -669
- package/dist/tools/ask.d.ts +2 -2
- package/dist/tools/ask.js +164 -219
- package/dist/tools/cache.d.ts +2 -2
- package/dist/tools/cache.js +63 -82
- package/dist/tools/clustering.d.ts +2 -2
- package/dist/tools/clustering.js +154 -215
- package/dist/tools/confluence.d.ts +2 -2
- package/dist/tools/confluence.js +80 -116
- package/dist/tools/database.d.ts +2 -2
- package/dist/tools/database.js +303 -380
- package/dist/tools/feedback.d.ts +2 -2
- package/dist/tools/feedback.js +143 -184
- package/dist/tools/guidelines.d.ts +2 -2
- package/dist/tools/guidelines.js +123 -135
- package/dist/tools/indexing.d.ts +2 -2
- package/dist/tools/indexing.js +100 -108
- package/dist/tools/memory.d.ts +2 -2
- package/dist/tools/memory.js +299 -485
- package/dist/tools/pm.d.ts +2 -2
- package/dist/tools/pm.js +367 -615
- package/dist/tools/quality.d.ts +8 -0
- package/dist/tools/quality.js +60 -0
- package/dist/tools/review.d.ts +2 -2
- package/dist/tools/review.js +142 -189
- package/dist/tools/search.d.ts +2 -2
- package/dist/tools/search.js +230 -305
- package/dist/tools/session.d.ts +2 -2
- package/dist/tools/session.js +288 -345
- package/dist/tools/suggestions.d.ts +2 -2
- package/dist/tools/suggestions.js +517 -512
- package/dist/types.d.ts +19 -2
- package/package.json +4 -2
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool annotations map for all MCP tools.
|
|
3
|
+
*
|
|
4
|
+
* Annotations help clients understand tool behaviour:
|
|
5
|
+
* readOnlyHint – tool does NOT modify its environment
|
|
6
|
+
* destructiveHint – tool may delete or irreversibly change data
|
|
7
|
+
* idempotentHint – repeated calls with same args have no extra effect
|
|
8
|
+
* openWorldHint – tool interacts with external entities (RAG API)
|
|
9
|
+
*/
|
|
10
|
+
export interface ToolAnnotations {
|
|
11
|
+
readOnlyHint?: boolean;
|
|
12
|
+
destructiveHint?: boolean;
|
|
13
|
+
idempotentHint?: boolean;
|
|
14
|
+
openWorldHint?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare const TOOL_ANNOTATIONS: Record<string, ToolAnnotations>;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool annotations map for all MCP tools.
|
|
3
|
+
*
|
|
4
|
+
* Annotations help clients understand tool behaviour:
|
|
5
|
+
* readOnlyHint – tool does NOT modify its environment
|
|
6
|
+
* destructiveHint – tool may delete or irreversibly change data
|
|
7
|
+
* idempotentHint – repeated calls with same args have no extra effect
|
|
8
|
+
* openWorldHint – tool interacts with external entities (RAG API)
|
|
9
|
+
*/
|
|
10
|
+
// ── Shorthand presets ───────────────────────────────────────
|
|
11
|
+
/** Read-only, idempotent – the vast majority of tools */
|
|
12
|
+
const RO = {
|
|
13
|
+
readOnlyHint: true,
|
|
14
|
+
destructiveHint: false,
|
|
15
|
+
idempotentHint: true,
|
|
16
|
+
openWorldHint: true,
|
|
17
|
+
};
|
|
18
|
+
/** Mutating but non-destructive (create / append) */
|
|
19
|
+
const MUT = {
|
|
20
|
+
readOnlyHint: false,
|
|
21
|
+
destructiveHint: false,
|
|
22
|
+
idempotentHint: false,
|
|
23
|
+
openWorldHint: true,
|
|
24
|
+
};
|
|
25
|
+
/** Idempotent upsert (record_*, setup_project, validate, promote) */
|
|
26
|
+
const UPSERT = {
|
|
27
|
+
readOnlyHint: false,
|
|
28
|
+
destructiveHint: false,
|
|
29
|
+
idempotentHint: true,
|
|
30
|
+
openWorldHint: true,
|
|
31
|
+
};
|
|
32
|
+
/** Destructive – may delete or irreversibly change data */
|
|
33
|
+
const DESTRUCT = {
|
|
34
|
+
readOnlyHint: false,
|
|
35
|
+
destructiveHint: true,
|
|
36
|
+
idempotentHint: false,
|
|
37
|
+
openWorldHint: true,
|
|
38
|
+
};
|
|
39
|
+
// ── Per-tool annotations ────────────────────────────────────
|
|
40
|
+
export const TOOL_ANNOTATIONS = {
|
|
41
|
+
// ── search (8) ──────────────────────────────────────────
|
|
42
|
+
search_codebase: RO,
|
|
43
|
+
search_similar: RO,
|
|
44
|
+
grouped_search: RO,
|
|
45
|
+
hybrid_search: RO,
|
|
46
|
+
search_docs: RO,
|
|
47
|
+
get_project_stats: RO,
|
|
48
|
+
find_symbol: RO,
|
|
49
|
+
search_graph: RO,
|
|
50
|
+
// ── ask (5) ─────────────────────────────────────────────
|
|
51
|
+
ask_codebase: RO,
|
|
52
|
+
explain_code: RO,
|
|
53
|
+
find_feature: RO,
|
|
54
|
+
analyze_conversation: RO,
|
|
55
|
+
auto_remember: MUT, // creates memory from conversation
|
|
56
|
+
// ── indexing (4) ────────────────────────────────────────
|
|
57
|
+
index_codebase: MUT,
|
|
58
|
+
get_index_status: RO,
|
|
59
|
+
reindex_zero_downtime: MUT,
|
|
60
|
+
list_aliases: RO,
|
|
61
|
+
// ── memory (11) ────────────────────────────────────────
|
|
62
|
+
remember: MUT,
|
|
63
|
+
recall: RO,
|
|
64
|
+
list_memories: RO,
|
|
65
|
+
forget: DESTRUCT,
|
|
66
|
+
update_todo: MUT,
|
|
67
|
+
batch_remember: MUT,
|
|
68
|
+
validate_memory: UPSERT, // idempotent status update
|
|
69
|
+
review_memories: RO,
|
|
70
|
+
promote_memory: UPSERT, // idempotent promotion
|
|
71
|
+
run_quality_gates: MUT, // may update memory status
|
|
72
|
+
memory_maintenance: DESTRUCT, // prunes old memories
|
|
73
|
+
// ── architecture (9) ───────────────────────────────────
|
|
74
|
+
record_adr: UPSERT,
|
|
75
|
+
get_adrs: RO,
|
|
76
|
+
record_pattern: UPSERT,
|
|
77
|
+
get_patterns: RO,
|
|
78
|
+
check_architecture: RO,
|
|
79
|
+
suggest_architecture: RO,
|
|
80
|
+
record_tech_debt: UPSERT,
|
|
81
|
+
get_tech_debt: RO,
|
|
82
|
+
analyze_project_structure: RO,
|
|
83
|
+
// ── database (8) ───────────────────────────────────────
|
|
84
|
+
record_table: UPSERT,
|
|
85
|
+
get_table_info: RO,
|
|
86
|
+
record_db_rule: UPSERT,
|
|
87
|
+
get_db_rules: RO,
|
|
88
|
+
record_enum: UPSERT,
|
|
89
|
+
get_enums: RO,
|
|
90
|
+
check_db_schema: RO,
|
|
91
|
+
suggest_db_schema: RO,
|
|
92
|
+
// ── confluence (4) ─────────────────────────────────────
|
|
93
|
+
search_confluence: RO,
|
|
94
|
+
index_confluence: MUT,
|
|
95
|
+
get_confluence_status: RO,
|
|
96
|
+
list_confluence_spaces: RO,
|
|
97
|
+
// ── pm (7) ─────────────────────────────────────────────
|
|
98
|
+
search_requirements: RO,
|
|
99
|
+
analyze_requirements: RO,
|
|
100
|
+
estimate_feature: RO,
|
|
101
|
+
get_feature_status: RO,
|
|
102
|
+
list_requirements: RO,
|
|
103
|
+
ask_pm: RO,
|
|
104
|
+
generate_spec: RO,
|
|
105
|
+
// ── review (3) ─────────────────────────────────────────
|
|
106
|
+
review_code: RO, // generates review, no side-effects
|
|
107
|
+
generate_tests: RO, // generates test suggestions
|
|
108
|
+
analyze_tests: RO,
|
|
109
|
+
// ── analytics (8) ──────────────────────────────────────
|
|
110
|
+
get_tool_analytics: RO,
|
|
111
|
+
get_knowledge_gaps: RO,
|
|
112
|
+
get_analytics: RO,
|
|
113
|
+
backup_collection: MUT, // creates a backup snapshot
|
|
114
|
+
list_backups: RO,
|
|
115
|
+
enable_quantization: DESTRUCT, // irreversible vector re-encoding
|
|
116
|
+
get_platform_stats: RO,
|
|
117
|
+
get_prediction_stats: RO,
|
|
118
|
+
// ── clustering (4) ─────────────────────────────────────
|
|
119
|
+
cluster_code: RO, // computes clusters, no persistence
|
|
120
|
+
find_duplicates: RO,
|
|
121
|
+
recommend_similar: RO,
|
|
122
|
+
extract_learnings: RO,
|
|
123
|
+
// ── session (7) ────────────────────────────────────────
|
|
124
|
+
summarize_context: RO,
|
|
125
|
+
summarize_changes: RO,
|
|
126
|
+
analyze_usage_patterns: RO,
|
|
127
|
+
get_developer_profile: RO,
|
|
128
|
+
start_session: MUT,
|
|
129
|
+
get_session_context: RO,
|
|
130
|
+
end_session: MUT,
|
|
131
|
+
// ── feedback (4) ───────────────────────────────────────
|
|
132
|
+
feedback_search: MUT, // stores search feedback
|
|
133
|
+
feedback_memory: MUT, // stores memory feedback
|
|
134
|
+
suggest_better_query: RO,
|
|
135
|
+
get_quality_metrics: RO,
|
|
136
|
+
// ── suggestions (7) ────────────────────────────────────
|
|
137
|
+
context_briefing: RO,
|
|
138
|
+
get_contextual_suggestions: RO,
|
|
139
|
+
suggest_related_code: RO,
|
|
140
|
+
suggest_implementation: RO,
|
|
141
|
+
suggest_tests: RO,
|
|
142
|
+
get_code_context: RO,
|
|
143
|
+
setup_project: UPSERT, // writes config (idempotent)
|
|
144
|
+
// ── cache (2) ──────────────────────────────────────────
|
|
145
|
+
get_cache_stats: RO,
|
|
146
|
+
warm_cache: MUT,
|
|
147
|
+
// ── guidelines (1) ─────────────────────────────────────
|
|
148
|
+
get_rag_guidelines: RO,
|
|
149
|
+
// ── advanced (5) ───────────────────────────────────────
|
|
150
|
+
merge_memories: DESTRUCT, // merges → deletes originals
|
|
151
|
+
get_completion_context: RO,
|
|
152
|
+
get_import_suggestions: RO,
|
|
153
|
+
get_type_context: RO,
|
|
154
|
+
get_behavior_patterns: RO,
|
|
155
|
+
// ── agents (2) ─────────────────────────────────────────
|
|
156
|
+
run_agent: MUT, // side-effects depend on agent type
|
|
157
|
+
get_agent_types: RO,
|
|
158
|
+
};
|
|
@@ -101,11 +101,18 @@ export class ContextEnricher {
|
|
|
101
101
|
!result.includes("No results") &&
|
|
102
102
|
!result.includes("not found") &&
|
|
103
103
|
!result.includes("No relevant context found")) {
|
|
104
|
+
// Count approximate results for weighted feedback
|
|
105
|
+
const numbered = result.match(/^\d+\./gm);
|
|
106
|
+
const bullets = result.match(/^[-*] /gm);
|
|
107
|
+
const resultCount = numbered?.length ?? bullets?.length ?? 1;
|
|
104
108
|
ctx.api
|
|
105
109
|
.post("/api/feedback/search", {
|
|
106
110
|
projectName: ctx.projectName,
|
|
107
111
|
query,
|
|
108
112
|
feedbackType: "helpful",
|
|
113
|
+
toolName: name,
|
|
114
|
+
resultCount,
|
|
115
|
+
sessionId: ctx.activeSessionId,
|
|
109
116
|
})
|
|
110
117
|
.catch(() => { });
|
|
111
118
|
}
|
package/dist/formatters.d.ts
CHANGED
|
@@ -39,6 +39,8 @@ export declare function formatNavigationResults(results: Array<{
|
|
|
39
39
|
score: number;
|
|
40
40
|
graphExpanded?: boolean;
|
|
41
41
|
}>): string;
|
|
42
|
+
/** Format pagination footer for list tools */
|
|
43
|
+
export declare function paginationFooter(count: number, limit: number, offset: number): string;
|
|
42
44
|
/** Format a simple list of files with scores */
|
|
43
45
|
export declare function formatFileList(files: Array<{
|
|
44
46
|
file: string;
|
package/dist/formatters.js
CHANGED
|
@@ -80,6 +80,18 @@ export function formatNavigationResults(results) {
|
|
|
80
80
|
return out;
|
|
81
81
|
}).join('\n\n');
|
|
82
82
|
}
|
|
83
|
+
/** Format pagination footer for list tools */
|
|
84
|
+
export function paginationFooter(count, limit, offset) {
|
|
85
|
+
const hasMore = count >= limit;
|
|
86
|
+
if (!hasMore && offset === 0)
|
|
87
|
+
return "";
|
|
88
|
+
let footer = `\n---\n_Showing ${offset + 1}–${offset + count}`;
|
|
89
|
+
if (hasMore) {
|
|
90
|
+
footer += ` | More results available (offset: ${offset + limit})`;
|
|
91
|
+
}
|
|
92
|
+
footer += "_\n";
|
|
93
|
+
return footer;
|
|
94
|
+
}
|
|
83
95
|
/** Format a simple list of files with scores */
|
|
84
96
|
export function formatFileList(files, emptyMessage = "No files found.") {
|
|
85
97
|
if (!files || files.length === 0)
|
package/dist/index.js
CHANGED
|
@@ -10,12 +10,11 @@
|
|
|
10
10
|
* - PROJECT_PATH: Path to project codebase for indexing
|
|
11
11
|
* - RAG_API_URL: URL of the shared RAG API (default: http://localhost:3100)
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
13
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
14
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
15
|
-
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
16
15
|
import { createApiClient } from "./api-client.js";
|
|
17
|
-
import { ToolRegistry } from "./tool-registry.js";
|
|
18
16
|
import { ContextEnricher } from "./context-enrichment.js";
|
|
17
|
+
import { wrapHandler } from "./tool-middleware.js";
|
|
19
18
|
// Tool modules
|
|
20
19
|
import { createSearchTools } from "./tools/search.js";
|
|
21
20
|
import { createAskTools } from "./tools/ask.js";
|
|
@@ -35,6 +34,7 @@ import { createCacheTools } from "./tools/cache.js";
|
|
|
35
34
|
import { createGuidelinesTools } from "./tools/guidelines.js";
|
|
36
35
|
import { createAdvancedTools } from "./tools/advanced.js";
|
|
37
36
|
import { createAgentTools } from "./tools/agents.js";
|
|
37
|
+
import { createQualityTools } from "./tools/quality.js";
|
|
38
38
|
// Configuration from environment
|
|
39
39
|
const PROJECT_NAME = process.env.PROJECT_NAME || "default";
|
|
40
40
|
const PROJECT_PATH = process.env.PROJECT_PATH || process.cwd();
|
|
@@ -51,54 +51,106 @@ const ctx = {
|
|
|
51
51
|
collectionPrefix: COLLECTION_PREFIX,
|
|
52
52
|
enrichmentEnabled: true,
|
|
53
53
|
};
|
|
54
|
-
//
|
|
55
|
-
const registry = new ToolRegistry();
|
|
56
|
-
registry.register(createSearchTools(PROJECT_NAME));
|
|
57
|
-
registry.register(createAskTools(PROJECT_NAME));
|
|
58
|
-
registry.register(createIndexingTools(PROJECT_NAME));
|
|
59
|
-
registry.register(createMemoryTools(PROJECT_NAME));
|
|
60
|
-
registry.register(createArchitectureTools(PROJECT_NAME));
|
|
61
|
-
registry.register(createDatabaseTools(PROJECT_NAME));
|
|
62
|
-
registry.register(createConfluenceTools(PROJECT_NAME));
|
|
63
|
-
registry.register(createPmTools(PROJECT_NAME));
|
|
64
|
-
registry.register(createReviewTools(PROJECT_NAME));
|
|
65
|
-
registry.register(createAnalyticsTools(PROJECT_NAME));
|
|
66
|
-
registry.register(createClusteringTools(PROJECT_NAME));
|
|
67
|
-
registry.register(createSessionTools(PROJECT_NAME, ctx));
|
|
68
|
-
registry.register(createFeedbackTools(PROJECT_NAME));
|
|
69
|
-
registry.register(createSuggestionTools(PROJECT_NAME));
|
|
70
|
-
registry.register(createCacheTools(PROJECT_NAME));
|
|
71
|
-
registry.register(createGuidelinesTools(PROJECT_NAME));
|
|
72
|
-
registry.register(createAdvancedTools(PROJECT_NAME));
|
|
73
|
-
registry.register(createAgentTools(PROJECT_NAME));
|
|
74
|
-
// Initialize context enrichment middleware
|
|
54
|
+
// Context enrichment middleware
|
|
75
55
|
const enricher = new ContextEnricher({
|
|
76
56
|
maxAutoRecall: 3,
|
|
77
57
|
minRelevance: 0.6,
|
|
78
58
|
timeoutMs: 2000,
|
|
79
59
|
});
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
60
|
+
// Collect all tool specs from modules
|
|
61
|
+
const allSpecs = [
|
|
62
|
+
...createSearchTools(PROJECT_NAME),
|
|
63
|
+
...createAskTools(PROJECT_NAME),
|
|
64
|
+
...createIndexingTools(PROJECT_NAME),
|
|
65
|
+
...createMemoryTools(PROJECT_NAME),
|
|
66
|
+
...createArchitectureTools(PROJECT_NAME),
|
|
67
|
+
...createDatabaseTools(PROJECT_NAME),
|
|
68
|
+
...createConfluenceTools(PROJECT_NAME),
|
|
69
|
+
...createPmTools(PROJECT_NAME),
|
|
70
|
+
...createReviewTools(PROJECT_NAME),
|
|
71
|
+
...createAnalyticsTools(PROJECT_NAME),
|
|
72
|
+
...createClusteringTools(PROJECT_NAME),
|
|
73
|
+
...createSessionTools(PROJECT_NAME, ctx),
|
|
74
|
+
...createFeedbackTools(PROJECT_NAME),
|
|
75
|
+
...createSuggestionTools(PROJECT_NAME),
|
|
76
|
+
...createCacheTools(PROJECT_NAME),
|
|
77
|
+
...createGuidelinesTools(PROJECT_NAME),
|
|
78
|
+
...createAdvancedTools(PROJECT_NAME),
|
|
79
|
+
...createAgentTools(PROJECT_NAME),
|
|
80
|
+
...createQualityTools(PROJECT_NAME),
|
|
81
|
+
];
|
|
82
|
+
// Core tools exposed directly to Claude (~35 tools).
|
|
83
|
+
// Hidden tools remain accessible via run_agent (agent runtime calls API directly).
|
|
84
|
+
const CORE_TOOLS = new Set([
|
|
85
|
+
// Search (6)
|
|
86
|
+
"search_codebase",
|
|
87
|
+
"hybrid_search",
|
|
88
|
+
"search_graph",
|
|
89
|
+
"find_symbol",
|
|
90
|
+
"search_docs",
|
|
91
|
+
"find_feature",
|
|
92
|
+
// Ask (2)
|
|
93
|
+
"ask_codebase",
|
|
94
|
+
"explain_code",
|
|
95
|
+
// Index (3)
|
|
96
|
+
"index_codebase",
|
|
97
|
+
"get_index_status",
|
|
98
|
+
"get_project_stats",
|
|
99
|
+
// Memory (7)
|
|
100
|
+
"remember",
|
|
101
|
+
"recall",
|
|
102
|
+
"list_memories",
|
|
103
|
+
"forget",
|
|
104
|
+
"batch_remember",
|
|
105
|
+
"promote_memory",
|
|
106
|
+
"review_memories",
|
|
107
|
+
// Architecture (6)
|
|
108
|
+
"record_adr",
|
|
109
|
+
"get_adrs",
|
|
110
|
+
"record_pattern",
|
|
111
|
+
"get_patterns",
|
|
112
|
+
"record_tech_debt",
|
|
113
|
+
"get_tech_debt",
|
|
114
|
+
// Context (3)
|
|
115
|
+
"context_briefing",
|
|
116
|
+
"smart_dispatch",
|
|
117
|
+
"setup_project",
|
|
118
|
+
// Session (2)
|
|
119
|
+
"start_session",
|
|
120
|
+
"end_session",
|
|
121
|
+
// Confluence (2)
|
|
122
|
+
"search_confluence",
|
|
123
|
+
"index_confluence",
|
|
124
|
+
// DB (4)
|
|
125
|
+
"record_table",
|
|
126
|
+
"get_table_info",
|
|
127
|
+
"check_db_schema",
|
|
128
|
+
"get_db_rules",
|
|
129
|
+
// Agents (1)
|
|
130
|
+
"run_agent",
|
|
131
|
+
]);
|
|
132
|
+
const coreSpecs = allSpecs.filter((s) => CORE_TOOLS.has(s.name));
|
|
133
|
+
// MCP Server (modern McpServer API with native Zod validation)
|
|
134
|
+
const server = new McpServer({ name: `${PROJECT_NAME}-rag`, version: "1.1.0" }, { capabilities: { tools: {} } });
|
|
135
|
+
// Register core tools with McpServer using wrapHandler middleware
|
|
136
|
+
for (const spec of coreSpecs) {
|
|
137
|
+
const wrapped = wrapHandler(spec.name, spec.handler, { enricher, ctx });
|
|
138
|
+
server.registerTool(spec.name, {
|
|
139
|
+
description: spec.description,
|
|
140
|
+
inputSchema: spec.schema,
|
|
141
|
+
...(spec.outputSchema ? { outputSchema: spec.outputSchema } : {}),
|
|
142
|
+
annotations: spec.annotations,
|
|
143
|
+
}, async (args) => {
|
|
144
|
+
const result = await wrapped(args, ctx);
|
|
145
|
+
if (typeof result === "string") {
|
|
146
|
+
return { content: [{ type: "text", text: result }] };
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
content: [{ type: "text", text: result.text }],
|
|
150
|
+
structuredContent: result.structured,
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
}
|
|
102
154
|
// Graceful shutdown: close active session on exit
|
|
103
155
|
async function cleanup() {
|
|
104
156
|
if (ctx.activeSessionId) {
|
|
@@ -122,6 +174,6 @@ async function main() {
|
|
|
122
174
|
const transport = new StdioServerTransport();
|
|
123
175
|
await server.connect(transport);
|
|
124
176
|
console.error(`${PROJECT_NAME} RAG MCP server running (collection prefix: ${COLLECTION_PREFIX})`);
|
|
125
|
-
console.error(`Registered ${
|
|
177
|
+
console.error(`Registered ${coreSpecs.length}/${allSpecs.length} core tools (${allSpecs.length - coreSpecs.length} hidden, accessible via run_agent)`);
|
|
126
178
|
}
|
|
127
179
|
main().catch(console.error);
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common Zod schemas shared across tool modules.
|
|
3
|
+
*
|
|
4
|
+
* Import individual shapes into each tool module when migrating
|
|
5
|
+
* from raw JSON Schema objects to Zod-based inputSchema definitions.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import type { ToolInputSchema } from "./types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Convert a Zod object schema to the MCP ToolInputSchema format.
|
|
11
|
+
* Used during Phase 2 migration while ToolRegistry still expects raw JSON Schema.
|
|
12
|
+
* Phase 3 passes Zod schemas directly to McpServer.registerTool().
|
|
13
|
+
*/
|
|
14
|
+
export declare function zodToInputSchema(schema: z.ZodObject<z.ZodRawShape>): ToolInputSchema;
|
|
15
|
+
export declare const QueryStr: z.ZodString;
|
|
16
|
+
export declare const Limit: z.ZodDefault<z.ZodNumber>;
|
|
17
|
+
export declare const Offset: z.ZodDefault<z.ZodNumber>;
|
|
18
|
+
export declare const FilePath: z.ZodString;
|
|
19
|
+
export declare const FilePaths: z.ZodArray<z.ZodString, "many">;
|
|
20
|
+
export declare const Content: z.ZodString;
|
|
21
|
+
export declare const CollectionSuffix: z.ZodString;
|
|
22
|
+
export declare const MemoryType: z.ZodEnum<["decision", "insight", "pattern", "adr", "tech_debt", "todo", "architecture", "convention", "bug_fix", "optimization"]>;
|
|
23
|
+
export declare const ResponseFormat: z.ZodDefault<z.ZodEnum<["json", "markdown"]>>;
|
|
24
|
+
export declare const Importance: z.ZodDefault<z.ZodEnum<["low", "medium", "high", "critical"]>>;
|
|
25
|
+
export declare const Priority: z.ZodEnum<["low", "medium", "high", "critical"]>;
|
|
26
|
+
export declare const Severity: z.ZodEnum<["low", "medium", "high", "critical"]>;
|
|
27
|
+
export declare const PaginationParams: z.ZodObject<{
|
|
28
|
+
limit: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
29
|
+
offset: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
30
|
+
}, "strip", z.ZodTypeAny, {
|
|
31
|
+
limit?: number | undefined;
|
|
32
|
+
offset?: number | undefined;
|
|
33
|
+
}, {
|
|
34
|
+
limit?: number | undefined;
|
|
35
|
+
offset?: number | undefined;
|
|
36
|
+
}>;
|
|
37
|
+
export declare const SearchFilters: z.ZodOptional<z.ZodObject<{
|
|
38
|
+
file_type: z.ZodOptional<z.ZodString>;
|
|
39
|
+
directory: z.ZodOptional<z.ZodString>;
|
|
40
|
+
}, "strip", z.ZodTypeAny, {
|
|
41
|
+
file_type?: string | undefined;
|
|
42
|
+
directory?: string | undefined;
|
|
43
|
+
}, {
|
|
44
|
+
file_type?: string | undefined;
|
|
45
|
+
directory?: string | undefined;
|
|
46
|
+
}>>;
|
|
47
|
+
export declare const Tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
48
|
+
export declare const Confidence: z.ZodOptional<z.ZodNumber>;
|
|
49
|
+
/** Base shape for search tools: query + optional limit + optional filters */
|
|
50
|
+
export declare const SearchInput: z.ZodObject<{
|
|
51
|
+
query: z.ZodString;
|
|
52
|
+
limit: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
53
|
+
filters: z.ZodOptional<z.ZodObject<{
|
|
54
|
+
file_type: z.ZodOptional<z.ZodString>;
|
|
55
|
+
directory: z.ZodOptional<z.ZodString>;
|
|
56
|
+
}, "strip", z.ZodTypeAny, {
|
|
57
|
+
file_type?: string | undefined;
|
|
58
|
+
directory?: string | undefined;
|
|
59
|
+
}, {
|
|
60
|
+
file_type?: string | undefined;
|
|
61
|
+
directory?: string | undefined;
|
|
62
|
+
}>>;
|
|
63
|
+
}, "strip", z.ZodTypeAny, {
|
|
64
|
+
query: string;
|
|
65
|
+
limit?: number | undefined;
|
|
66
|
+
filters?: {
|
|
67
|
+
file_type?: string | undefined;
|
|
68
|
+
directory?: string | undefined;
|
|
69
|
+
} | undefined;
|
|
70
|
+
}, {
|
|
71
|
+
query: string;
|
|
72
|
+
limit?: number | undefined;
|
|
73
|
+
filters?: {
|
|
74
|
+
file_type?: string | undefined;
|
|
75
|
+
directory?: string | undefined;
|
|
76
|
+
} | undefined;
|
|
77
|
+
}>;
|
|
78
|
+
/** Base shape for memory record tools */
|
|
79
|
+
export declare const MemoryRecordInput: z.ZodObject<{
|
|
80
|
+
content: z.ZodString;
|
|
81
|
+
type: z.ZodEnum<["decision", "insight", "pattern", "adr", "tech_debt", "todo", "architecture", "convention", "bug_fix", "optimization"]>;
|
|
82
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
83
|
+
importance: z.ZodOptional<z.ZodDefault<z.ZodEnum<["low", "medium", "high", "critical"]>>>;
|
|
84
|
+
context: z.ZodOptional<z.ZodString>;
|
|
85
|
+
}, "strip", z.ZodTypeAny, {
|
|
86
|
+
type: "decision" | "insight" | "todo" | "adr" | "pattern" | "architecture" | "tech_debt" | "convention" | "bug_fix" | "optimization";
|
|
87
|
+
content: string;
|
|
88
|
+
context?: string | undefined;
|
|
89
|
+
tags?: string[] | undefined;
|
|
90
|
+
importance?: "low" | "medium" | "high" | "critical" | undefined;
|
|
91
|
+
}, {
|
|
92
|
+
type: "decision" | "insight" | "todo" | "adr" | "pattern" | "architecture" | "tech_debt" | "convention" | "bug_fix" | "optimization";
|
|
93
|
+
content: string;
|
|
94
|
+
context?: string | undefined;
|
|
95
|
+
tags?: string[] | undefined;
|
|
96
|
+
importance?: "low" | "medium" | "high" | "critical" | undefined;
|
|
97
|
+
}>;
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common Zod schemas shared across tool modules.
|
|
3
|
+
*
|
|
4
|
+
* Import individual shapes into each tool module when migrating
|
|
5
|
+
* from raw JSON Schema objects to Zod-based inputSchema definitions.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
9
|
+
// ── JSON Schema conversion ──────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Convert a Zod object schema to the MCP ToolInputSchema format.
|
|
12
|
+
* Used during Phase 2 migration while ToolRegistry still expects raw JSON Schema.
|
|
13
|
+
* Phase 3 passes Zod schemas directly to McpServer.registerTool().
|
|
14
|
+
*/
|
|
15
|
+
export function zodToInputSchema(schema) {
|
|
16
|
+
const jsonSchema = zodToJsonSchema(schema, { target: "openApi3" });
|
|
17
|
+
return {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: (jsonSchema.properties ?? {}),
|
|
20
|
+
...(Array.isArray(jsonSchema.required) && jsonSchema.required.length > 0
|
|
21
|
+
? { required: jsonSchema.required }
|
|
22
|
+
: {}),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// ── Primitives ──────────────────────────────────────────────
|
|
26
|
+
export const QueryStr = z
|
|
27
|
+
.string()
|
|
28
|
+
.min(1)
|
|
29
|
+
.describe("Search query or question");
|
|
30
|
+
export const Limit = z
|
|
31
|
+
.number()
|
|
32
|
+
.int()
|
|
33
|
+
.min(1)
|
|
34
|
+
.max(100)
|
|
35
|
+
.default(20)
|
|
36
|
+
.describe("Maximum results to return");
|
|
37
|
+
export const Offset = z
|
|
38
|
+
.number()
|
|
39
|
+
.int()
|
|
40
|
+
.min(0)
|
|
41
|
+
.default(0)
|
|
42
|
+
.describe("Pagination offset");
|
|
43
|
+
export const FilePath = z
|
|
44
|
+
.string()
|
|
45
|
+
.min(1)
|
|
46
|
+
.describe("File path relative to project root");
|
|
47
|
+
export const FilePaths = z
|
|
48
|
+
.array(FilePath)
|
|
49
|
+
.min(1)
|
|
50
|
+
.describe("List of file paths");
|
|
51
|
+
export const Content = z
|
|
52
|
+
.string()
|
|
53
|
+
.min(1)
|
|
54
|
+
.describe("Text content");
|
|
55
|
+
export const CollectionSuffix = z
|
|
56
|
+
.string()
|
|
57
|
+
.min(1)
|
|
58
|
+
.describe("Collection suffix (e.g. 'codebase', 'docs')");
|
|
59
|
+
// ── Enums ───────────────────────────────────────────────────
|
|
60
|
+
export const MemoryType = z.enum([
|
|
61
|
+
"decision",
|
|
62
|
+
"insight",
|
|
63
|
+
"pattern",
|
|
64
|
+
"adr",
|
|
65
|
+
"tech_debt",
|
|
66
|
+
"todo",
|
|
67
|
+
"architecture",
|
|
68
|
+
"convention",
|
|
69
|
+
"bug_fix",
|
|
70
|
+
"optimization",
|
|
71
|
+
]);
|
|
72
|
+
export const ResponseFormat = z
|
|
73
|
+
.enum(["json", "markdown"])
|
|
74
|
+
.default("markdown")
|
|
75
|
+
.describe("Output format");
|
|
76
|
+
export const Importance = z
|
|
77
|
+
.enum(["low", "medium", "high", "critical"])
|
|
78
|
+
.default("medium")
|
|
79
|
+
.describe("Importance level");
|
|
80
|
+
export const Priority = z
|
|
81
|
+
.enum(["low", "medium", "high", "critical"])
|
|
82
|
+
.describe("Priority level");
|
|
83
|
+
export const Severity = z
|
|
84
|
+
.enum(["low", "medium", "high", "critical"])
|
|
85
|
+
.describe("Severity level");
|
|
86
|
+
// ── Reusable object shapes ──────────────────────────────────
|
|
87
|
+
export const PaginationParams = z.object({
|
|
88
|
+
limit: Limit.optional(),
|
|
89
|
+
offset: Offset.optional(),
|
|
90
|
+
});
|
|
91
|
+
export const SearchFilters = z
|
|
92
|
+
.object({
|
|
93
|
+
file_type: z
|
|
94
|
+
.string()
|
|
95
|
+
.optional()
|
|
96
|
+
.describe("Filter by file extension (e.g. 'ts', 'py')"),
|
|
97
|
+
directory: z
|
|
98
|
+
.string()
|
|
99
|
+
.optional()
|
|
100
|
+
.describe("Filter by directory prefix"),
|
|
101
|
+
})
|
|
102
|
+
.optional()
|
|
103
|
+
.describe("Search filters");
|
|
104
|
+
export const Tags = z
|
|
105
|
+
.array(z.string())
|
|
106
|
+
.optional()
|
|
107
|
+
.describe("Tags for categorization");
|
|
108
|
+
export const Confidence = z
|
|
109
|
+
.number()
|
|
110
|
+
.min(0)
|
|
111
|
+
.max(1)
|
|
112
|
+
.optional()
|
|
113
|
+
.describe("Confidence score (0-1)");
|
|
114
|
+
// ── Composite input shapes ──────────────────────────────────
|
|
115
|
+
/** Base shape for search tools: query + optional limit + optional filters */
|
|
116
|
+
export const SearchInput = z.object({
|
|
117
|
+
query: QueryStr,
|
|
118
|
+
limit: Limit.optional(),
|
|
119
|
+
filters: SearchFilters,
|
|
120
|
+
});
|
|
121
|
+
/** Base shape for memory record tools */
|
|
122
|
+
export const MemoryRecordInput = z.object({
|
|
123
|
+
content: Content.describe("Content to remember"),
|
|
124
|
+
type: MemoryType,
|
|
125
|
+
tags: Tags,
|
|
126
|
+
importance: Importance.optional(),
|
|
127
|
+
context: z.string().optional().describe("Additional context"),
|
|
128
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Middleware — standalone middleware functions for MCP tool handlers.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from ToolRegistry.handle() so that McpServer.registerTool()
|
|
5
|
+
* (Phase 3) can reuse the same pipeline:
|
|
6
|
+
* auto-session → enrichment.before → handler → enrichment.after → trackUsage
|
|
7
|
+
*
|
|
8
|
+
* During Phase 2 migration, ToolRegistry continues to use its own copy.
|
|
9
|
+
* Phase 3 replaces ToolRegistry with wrapHandler() + McpServer.registerTool().
|
|
10
|
+
*/
|
|
11
|
+
import type { ToolContext, ToolHandler } from "./types.js";
|
|
12
|
+
import type { ContextEnricher } from "./context-enrichment.js";
|
|
13
|
+
/** Per-tool timeout overrides (ms) */
|
|
14
|
+
export declare const TOOL_TIMEOUTS: Record<string, number>;
|
|
15
|
+
/** Tools excluded from usage tracking (meta/admin, avoid recursion) */
|
|
16
|
+
export declare const TRACKING_EXCLUDE: Set<string>;
|
|
17
|
+
/** Session management tools — skip auto-session to avoid recursion */
|
|
18
|
+
export declare const SESSION_TOOLS: Set<string>;
|
|
19
|
+
/** Summarize tool args into a short string for analytics */
|
|
20
|
+
export declare function summarizeInput(name: string, args: Record<string, unknown>): string;
|
|
21
|
+
/** Count results from a tool response string */
|
|
22
|
+
export declare function countResults(result: string): number;
|
|
23
|
+
/** Auto-start a session via the RAG API if none is active */
|
|
24
|
+
export declare function ensureSession(ctx: ToolContext): Promise<void>;
|
|
25
|
+
/** Fire-and-forget usage tracking */
|
|
26
|
+
export declare function trackUsage(name: string, args: Record<string, unknown>, startTime: number, success: boolean, result: string, errorMessage: string | undefined, ctx: ToolContext): void;
|
|
27
|
+
/** Format an error caught during tool execution */
|
|
28
|
+
export declare function formatToolError(error: unknown, ctx: ToolContext): string;
|
|
29
|
+
export interface MiddlewareDeps {
|
|
30
|
+
enricher?: ContextEnricher;
|
|
31
|
+
ctx: ToolContext;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Wrap a raw ToolHandler with the full middleware pipeline:
|
|
35
|
+
* auto-session → enrichment.before → handler → enrichment.after → trackUsage
|
|
36
|
+
*
|
|
37
|
+
* Returns a ToolHandler with the same signature, so it works both
|
|
38
|
+
* with the legacy ToolRegistry and the Phase 3 McpServer adapter.
|
|
39
|
+
*/
|
|
40
|
+
export declare function wrapHandler(name: string, handler: ToolHandler, deps: MiddlewareDeps): ToolHandler;
|