@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.
Files changed (51) hide show
  1. package/dist/annotations.d.ts +16 -0
  2. package/dist/annotations.js +158 -0
  3. package/dist/context-enrichment.js +7 -0
  4. package/dist/formatters.d.ts +2 -0
  5. package/dist/formatters.js +12 -0
  6. package/dist/index.js +99 -47
  7. package/dist/schemas.d.ts +97 -0
  8. package/dist/schemas.js +128 -0
  9. package/dist/tool-middleware.d.ts +40 -0
  10. package/dist/tool-middleware.js +216 -0
  11. package/dist/tool-registry.js +2 -1
  12. package/dist/tools/advanced.d.ts +2 -2
  13. package/dist/tools/advanced.js +200 -275
  14. package/dist/tools/agents.d.ts +2 -2
  15. package/dist/tools/agents.js +59 -78
  16. package/dist/tools/analytics.d.ts +2 -2
  17. package/dist/tools/analytics.js +170 -210
  18. package/dist/tools/architecture.d.ts +2 -2
  19. package/dist/tools/architecture.js +506 -669
  20. package/dist/tools/ask.d.ts +2 -2
  21. package/dist/tools/ask.js +164 -219
  22. package/dist/tools/cache.d.ts +2 -2
  23. package/dist/tools/cache.js +63 -82
  24. package/dist/tools/clustering.d.ts +2 -2
  25. package/dist/tools/clustering.js +154 -215
  26. package/dist/tools/confluence.d.ts +2 -2
  27. package/dist/tools/confluence.js +80 -116
  28. package/dist/tools/database.d.ts +2 -2
  29. package/dist/tools/database.js +303 -380
  30. package/dist/tools/feedback.d.ts +2 -2
  31. package/dist/tools/feedback.js +143 -184
  32. package/dist/tools/guidelines.d.ts +2 -2
  33. package/dist/tools/guidelines.js +123 -135
  34. package/dist/tools/indexing.d.ts +2 -2
  35. package/dist/tools/indexing.js +100 -108
  36. package/dist/tools/memory.d.ts +2 -2
  37. package/dist/tools/memory.js +299 -485
  38. package/dist/tools/pm.d.ts +2 -2
  39. package/dist/tools/pm.js +367 -615
  40. package/dist/tools/quality.d.ts +8 -0
  41. package/dist/tools/quality.js +60 -0
  42. package/dist/tools/review.d.ts +2 -2
  43. package/dist/tools/review.js +142 -189
  44. package/dist/tools/search.d.ts +2 -2
  45. package/dist/tools/search.js +230 -305
  46. package/dist/tools/session.d.ts +2 -2
  47. package/dist/tools/session.js +288 -345
  48. package/dist/tools/suggestions.d.ts +2 -2
  49. package/dist/tools/suggestions.js +517 -512
  50. package/dist/types.d.ts +19 -2
  51. 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
  }
@@ -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;
@@ -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 { Server } from "@modelcontextprotocol/sdk/server/index.js";
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
- // Build tool registry from modules
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
- registry.setEnricher(enricher);
81
- // MCP Server
82
- const server = new Server({
83
- name: `${PROJECT_NAME}-rag`,
84
- version: "1.0.0",
85
- }, {
86
- capabilities: {
87
- tools: {},
88
- },
89
- });
90
- // List tools handler
91
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
92
- tools: registry.getTools(),
93
- }));
94
- // Call tool handler
95
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
96
- const { name, arguments: args } = request.params;
97
- const result = await registry.handle(name, args || {}, ctx);
98
- return {
99
- content: [{ type: "text", text: result }],
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 ${registry.getTools().length} tools from 18 modules`);
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
+ }>;
@@ -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;