@crowley/rag-mcp 1.0.5 → 1.0.6

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 (49) 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 +46 -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/review.d.ts +2 -2
  41. package/dist/tools/review.js +142 -189
  42. package/dist/tools/search.d.ts +2 -2
  43. package/dist/tools/search.js +230 -305
  44. package/dist/tools/session.d.ts +2 -2
  45. package/dist/tools/session.js +288 -345
  46. package/dist/tools/suggestions.d.ts +2 -2
  47. package/dist/tools/suggestions.js +425 -512
  48. package/dist/types.d.ts +19 -2
  49. 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";
@@ -51,54 +50,54 @@ const ctx = {
51
50
  collectionPrefix: COLLECTION_PREFIX,
52
51
  enrichmentEnabled: true,
53
52
  };
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
53
+ // Context enrichment middleware
75
54
  const enricher = new ContextEnricher({
76
55
  maxAutoRecall: 3,
77
56
  minRelevance: 0.6,
78
57
  timeoutMs: 2000,
79
58
  });
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
- });
59
+ // Collect all tool specs from modules
60
+ const allSpecs = [
61
+ ...createSearchTools(PROJECT_NAME),
62
+ ...createAskTools(PROJECT_NAME),
63
+ ...createIndexingTools(PROJECT_NAME),
64
+ ...createMemoryTools(PROJECT_NAME),
65
+ ...createArchitectureTools(PROJECT_NAME),
66
+ ...createDatabaseTools(PROJECT_NAME),
67
+ ...createConfluenceTools(PROJECT_NAME),
68
+ ...createPmTools(PROJECT_NAME),
69
+ ...createReviewTools(PROJECT_NAME),
70
+ ...createAnalyticsTools(PROJECT_NAME),
71
+ ...createClusteringTools(PROJECT_NAME),
72
+ ...createSessionTools(PROJECT_NAME, ctx),
73
+ ...createFeedbackTools(PROJECT_NAME),
74
+ ...createSuggestionTools(PROJECT_NAME),
75
+ ...createCacheTools(PROJECT_NAME),
76
+ ...createGuidelinesTools(PROJECT_NAME),
77
+ ...createAdvancedTools(PROJECT_NAME),
78
+ ...createAgentTools(PROJECT_NAME),
79
+ ];
80
+ // MCP Server (modern McpServer API with native Zod validation)
81
+ const server = new McpServer({ name: `${PROJECT_NAME}-rag`, version: "1.0.5" }, { capabilities: { tools: {} } });
82
+ // Register all tools with McpServer using wrapHandler middleware
83
+ for (const spec of allSpecs) {
84
+ const wrapped = wrapHandler(spec.name, spec.handler, { enricher, ctx });
85
+ server.registerTool(spec.name, {
86
+ description: spec.description,
87
+ inputSchema: spec.schema,
88
+ ...(spec.outputSchema ? { outputSchema: spec.outputSchema } : {}),
89
+ annotations: spec.annotations,
90
+ }, async (args) => {
91
+ const result = await wrapped(args, ctx);
92
+ if (typeof result === "string") {
93
+ return { content: [{ type: "text", text: result }] };
94
+ }
95
+ return {
96
+ content: [{ type: "text", text: result.text }],
97
+ structuredContent: result.structured,
98
+ };
99
+ });
100
+ }
102
101
  // Graceful shutdown: close active session on exit
103
102
  async function cleanup() {
104
103
  if (ctx.activeSessionId) {
@@ -122,6 +121,6 @@ async function main() {
122
121
  const transport = new StdioServerTransport();
123
122
  await server.connect(transport);
124
123
  console.error(`${PROJECT_NAME} RAG MCP server running (collection prefix: ${COLLECTION_PREFIX})`);
125
- console.error(`Registered ${registry.getTools().length} tools from 18 modules`);
124
+ console.error(`Registered ${allSpecs.length} tools from 18 modules`);
126
125
  }
127
126
  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" | "tech_debt" | "architecture" | "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" | "tech_debt" | "architecture" | "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;