@fractary/codex-mcp 0.1.0 → 0.3.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/README.md CHANGED
@@ -37,7 +37,7 @@ Add to your `.claude/settings.json`:
37
37
  "mcpServers": {
38
38
  "fractary-codex": {
39
39
  "command": "npx",
40
- "args": ["-y", "@fractary/codex-mcp-server", "--config", ".fractary/codex.yaml"]
40
+ "args": ["-y", "@fractary/codex-mcp-server", "--config", ".fractary/codex/config.yaml"]
41
41
  }
42
42
  }
43
43
  }
@@ -46,7 +46,7 @@ Add to your `.claude/settings.json`:
46
46
  ### Stdio Mode (Default)
47
47
 
48
48
  ```bash
49
- fractary-codex-mcp --config .fractary/codex.yaml
49
+ fractary-codex-mcp --config .fractary/codex/config.yaml
50
50
  ```
51
51
 
52
52
  The server communicates via stdin/stdout using the MCP protocol.
@@ -61,11 +61,11 @@ The server exposes an SSE (Server-Sent Events) endpoint for HTTP clients.
61
61
 
62
62
  ## Configuration
63
63
 
64
- Create a `.fractary/codex.yaml` configuration file:
64
+ Create a `.fractary/codex/config.yaml` configuration file:
65
65
 
66
66
  ```yaml
67
67
  cache:
68
- dir: .codex-cache
68
+ dir: .fractary/codex/cache
69
69
  maxMemorySize: 104857600 # 100 MB
70
70
  defaultTtl: 3600 # 1 hour
71
71
 
@@ -79,14 +79,14 @@ storage:
79
79
 
80
80
  ### Environment Variables
81
81
 
82
- - `FRACTARY_CONFIG`: Path to configuration file (default: `.fractary/codex.yaml`)
82
+ - `FRACTARY_CONFIG`: Path to configuration file (default: `.fractary/codex/config.yaml`)
83
83
  - `GITHUB_TOKEN`: GitHub personal access token for GitHub storage provider
84
84
 
85
85
  ## Available Tools
86
86
 
87
87
  The MCP server exposes the following tools:
88
88
 
89
- ### codex_fetch
89
+ ### codex_document_fetch
90
90
 
91
91
  Fetch a document from the Codex knowledge base by URI.
92
92
 
@@ -112,7 +112,7 @@ Search for documents in the knowledge base.
112
112
  }
113
113
  ```
114
114
 
115
- ### codex_list
115
+ ### codex_cache_list
116
116
 
117
117
  List cached documents.
118
118
 
@@ -124,9 +124,9 @@ List cached documents.
124
124
  }
125
125
  ```
126
126
 
127
- ### codex_invalidate
127
+ ### codex_cache_clear
128
128
 
129
- Invalidate cached documents by pattern.
129
+ Clear cached documents by pattern.
130
130
 
131
131
  ```json
132
132
  {
@@ -241,7 +241,7 @@ If you were using the MCP server from `@fractary/codex` (versions ≤0.1.x), upd
241
241
  "mcpServers": {
242
242
  "fractary-codex": {
243
243
  "command": "npx",
244
- "args": ["@fractary/codex", "mcp", "--config", ".fractary/codex.yaml"]
244
+ "args": ["@fractary/codex", "mcp", "--config", ".fractary/codex/config.yaml"]
245
245
  }
246
246
  }
247
247
  }
@@ -253,7 +253,7 @@ If you were using the MCP server from `@fractary/codex` (versions ≤0.1.x), upd
253
253
  "mcpServers": {
254
254
  "fractary-codex": {
255
255
  "command": "npx",
256
- "args": ["-y", "@fractary/codex-mcp-server", "--config", ".fractary/codex.yaml"]
256
+ "args": ["-y", "@fractary/codex-mcp-server", "--config", ".fractary/codex/config.yaml"]
257
257
  }
258
258
  }
259
259
  }
package/dist/cli.js CHANGED
@@ -13,7 +13,7 @@ import { resolveReference as resolveReference2 } from "@fractary/codex";
13
13
  import { resolveReference } from "@fractary/codex";
14
14
  var CODEX_TOOLS = [
15
15
  {
16
- name: "codex_fetch",
16
+ name: "codex_document_fetch",
17
17
  description: "Fetch a document from the Codex knowledge base by URI. Returns the document content.",
18
18
  inputSchema: {
19
19
  type: "object",
@@ -65,7 +65,7 @@ var CODEX_TOOLS = [
65
65
  }
66
66
  },
67
67
  {
68
- name: "codex_list",
68
+ name: "codex_cache_list",
69
69
  description: "List documents in the Codex cache.",
70
70
  inputSchema: {
71
71
  type: "object",
@@ -86,8 +86,8 @@ var CODEX_TOOLS = [
86
86
  }
87
87
  },
88
88
  {
89
- name: "codex_invalidate",
90
- description: "Invalidate cached documents matching a pattern.",
89
+ name: "codex_cache_clear",
90
+ description: "Clear cached documents matching a pattern.",
91
91
  inputSchema: {
92
92
  type: "object",
93
93
  properties: {
@@ -160,14 +160,14 @@ async function handleSearch(args, ctx) {
160
160
  }
161
161
  const stats = await ctx.cache.getStats();
162
162
  if (stats.entryCount === 0) {
163
- return textResult("No documents in cache. Use codex_fetch to load documents first.");
163
+ return textResult("No documents in cache. Use codex_document_fetch to load documents first.");
164
164
  }
165
165
  const message = `Search functionality requires a search index.
166
166
  Query: "${query}"
167
167
  Filters: org=${org || "any"}, project=${project || "any"}
168
168
  Limit: ${limit}
169
169
 
170
- To fetch documents, use codex_fetch with a specific URI like:
170
+ To fetch documents, use codex_document_fetch with a specific URI like:
171
171
  codex://org/project/docs/file.md`;
172
172
  return textResult(message);
173
173
  }
@@ -224,7 +224,7 @@ function validateRegexPattern(pattern) {
224
224
  return { valid: false, error: message };
225
225
  }
226
226
  }
227
- async function handleInvalidate(args, ctx) {
227
+ async function handleCacheClear(args, ctx) {
228
228
  const { pattern } = args;
229
229
  if (!pattern || typeof pattern !== "string") {
230
230
  return textResult("Pattern is required and must be a string", true);
@@ -236,22 +236,22 @@ async function handleInvalidate(args, ctx) {
236
236
  try {
237
237
  const regex = new RegExp(pattern);
238
238
  const count = await ctx.cache.invalidatePattern(regex);
239
- return textResult(`Invalidated ${count} cache entries matching pattern: ${pattern}`);
239
+ return textResult(`Cleared ${count} cache entries matching pattern: ${pattern}`);
240
240
  } catch (error) {
241
241
  const message = error instanceof Error ? error.message : String(error);
242
- return textResult(`Failed to invalidate cache: ${message}`, true);
242
+ return textResult(`Failed to clear cache: ${message}`, true);
243
243
  }
244
244
  }
245
245
  async function handleToolCall(name, args, ctx) {
246
246
  switch (name) {
247
- case "codex_fetch":
247
+ case "codex_document_fetch":
248
248
  return handleFetch(args, ctx);
249
249
  case "codex_search":
250
250
  return handleSearch(args, ctx);
251
- case "codex_list":
251
+ case "codex_cache_list":
252
252
  return handleList(args, ctx);
253
- case "codex_invalidate":
254
- return handleInvalidate(args, ctx);
253
+ case "codex_cache_clear":
254
+ return handleCacheClear(args, ctx);
255
255
  default:
256
256
  return textResult(`Unknown tool: ${name}`, true);
257
257
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/server.ts","../src/tools.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry point for @fractary/codex-mcp-server\n *\n * Provides MCP server with stdio transport.\n */\n\nimport { Command } from 'commander'\nimport { createCacheManager, createStorageManager } from '@fractary/codex'\nimport { readFileSync } from 'fs'\nimport * as yaml from 'js-yaml'\nimport { McpServer } from './server.js'\n\nconst program = new Command()\n\nprogram\n .name('fractary-codex-mcp')\n .description('MCP server for Fractary Codex knowledge management')\n .version('0.1.0')\n .option('--config <path>', 'Path to config file', '.fractary/codex.yaml')\n .action(async (options) => {\n // Load configuration\n let config: Record<string, unknown> = {}\n try {\n const configFile = readFileSync(options.config, 'utf-8')\n config = yaml.load(configFile) as Record<string, unknown>\n } catch (error) {\n // Config file is optional - continue with defaults\n if (options.config !== '.fractary/codex.yaml') {\n console.error(`Warning: Could not load config file: ${options.config}`)\n }\n }\n\n // Initialize storage and cache managers\n const storage = createStorageManager(config.storage as Record<string, unknown> | undefined)\n const cache = createCacheManager({\n cacheDir: (config.cache as Record<string, unknown>)?.cacheDir as string || '.fractary/cache',\n ...(config.cache as Record<string, unknown>),\n })\n\n // Create MCP server\n const server = new McpServer({\n name: 'fractary-codex',\n version: '0.1.0',\n cache,\n storage,\n })\n\n // Stdio mode\n process.stdin.setEncoding('utf-8')\n\n let buffer = ''\n process.stdin.on('data', async (chunk) => {\n buffer += chunk\n const lines = buffer.split('\\n')\n buffer = lines.pop() || ''\n\n for (const line of lines) {\n if (line.trim()) {\n try {\n const message = JSON.parse(line)\n const response = await handleMessage(server, message)\n process.stdout.write(JSON.stringify(response) + '\\n')\n } catch (error) {\n const errorResponse = {\n jsonrpc: '2.0',\n error: {\n code: -32700,\n message: 'Parse error',\n data: error instanceof Error ? error.message : 'Unknown error',\n },\n id: null,\n }\n process.stdout.write(JSON.stringify(errorResponse) + '\\n')\n }\n }\n }\n })\n\n process.stdin.on('end', () => {\n process.exit(0)\n })\n\n console.error('MCP server running in stdio mode')\n })\n\n/**\n * Handle a JSON-RPC message\n */\nasync function handleMessage(\n server: McpServer,\n message: Record<string, unknown>\n): Promise<Record<string, unknown>> {\n const method = message.method as string\n const params = (message.params as Record<string, unknown>) || {}\n const id = message.id\n\n try {\n let result: unknown\n\n switch (method) {\n case 'initialize':\n result = server.getServerInfo()\n break\n\n case 'tools/list':\n result = { tools: server.listTools() }\n break\n\n case 'tools/call': {\n const toolName = params.name as string\n const toolArgs = params.arguments as Record<string, unknown>\n result = await server.callTool(toolName, toolArgs)\n break\n }\n\n case 'resources/list':\n result = { resources: [] }\n break\n\n default:\n return {\n jsonrpc: '2.0',\n error: {\n code: -32601,\n message: `Method not found: ${method}`,\n },\n id,\n }\n }\n\n return {\n jsonrpc: '2.0',\n result,\n id,\n }\n } catch (error) {\n return {\n jsonrpc: '2.0',\n error: {\n code: -32603,\n message: 'Internal error',\n data: error instanceof Error ? error.message : 'Unknown error',\n },\n id,\n }\n }\n}\n\n// Run the program\nprogram.parse(process.argv)\n","/**\n * MCP Server implementation\n *\n * Implements a Model Context Protocol server for the Codex SDK.\n * This server can be used standalone or embedded in other applications.\n */\n\nimport type { CacheManager } from '@fractary/codex'\nimport type { StorageManager } from '@fractary/codex'\nimport { resolveReference } from '@fractary/codex'\nimport type {\n McpServerInfo,\n McpCapabilities,\n McpTool,\n McpResource,\n McpResourceTemplate,\n ResourceContent,\n ToolResult,\n} from './types.js'\nimport { CODEX_TOOLS, handleToolCall, type ToolHandlerContext } from './tools.js'\n\n/**\n * MCP Server configuration\n */\nexport interface McpServerConfig {\n /** Server name */\n name?: string\n /** Server version */\n version?: string\n /** Cache manager instance */\n cache: CacheManager\n /** Storage manager instance */\n storage: StorageManager\n}\n\n/**\n * MCP Server for Codex\n *\n * Provides a Model Context Protocol server implementation that exposes\n * Codex functionality as MCP tools and resources.\n */\nexport class McpServer {\n private config: Required<Omit<McpServerConfig, 'cache' | 'storage'>> & Pick<McpServerConfig, 'cache' | 'storage'>\n private toolContext: ToolHandlerContext\n\n constructor(config: McpServerConfig) {\n this.config = {\n name: config.name ?? 'codex',\n version: config.version ?? '1.0.0',\n cache: config.cache,\n storage: config.storage,\n }\n\n this.toolContext = {\n cache: config.cache,\n storage: config.storage,\n }\n }\n\n /**\n * Get server info\n */\n getServerInfo(): McpServerInfo {\n return {\n name: this.config.name,\n version: this.config.version,\n capabilities: this.getCapabilities(),\n }\n }\n\n /**\n * Get server capabilities\n */\n getCapabilities(): McpCapabilities {\n return {\n tools: {\n listChanged: false,\n },\n resources: {\n subscribe: false,\n listChanged: false,\n },\n }\n }\n\n /**\n * List available tools\n */\n listTools(): McpTool[] {\n return CODEX_TOOLS\n }\n\n /**\n * Call a tool\n */\n async callTool(name: string, args: Record<string, unknown>): Promise<ToolResult> {\n return handleToolCall(name, args, this.toolContext)\n }\n\n /**\n * List available resources\n */\n async listResources(): Promise<McpResource[]> {\n // List cached documents as resources\n const resources: McpResource[] = []\n\n // Get cache stats for info\n const stats = await this.config.cache.getStats()\n\n // Add a summary resource\n resources.push({\n uri: 'codex://cache/summary',\n name: 'Cache Summary',\n description: `${stats.entryCount} cached documents`,\n mimeType: 'text/plain',\n })\n\n return resources\n }\n\n /**\n * List resource templates\n */\n listResourceTemplates(): McpResourceTemplate[] {\n return [\n {\n uriTemplate: 'codex://{org}/{project}/{path}',\n name: 'Codex Document',\n description: 'Fetch a document from the Codex knowledge base',\n mimeType: 'text/markdown',\n },\n ]\n }\n\n /**\n * Read a resource\n */\n async readResource(uri: string): Promise<ResourceContent[]> {\n // Handle special URIs\n if (uri === 'codex://cache/summary') {\n const stats = await this.config.cache.getStats()\n return [\n {\n uri,\n mimeType: 'text/plain',\n text: `Cache Statistics:\n- Total entries: ${stats.entryCount}\n- Memory entries: ${stats.memoryEntries}\n- Fresh: ${stats.freshCount}\n- Stale: ${stats.staleCount}\n- Expired: ${stats.expiredCount}`,\n },\n ]\n }\n\n // Resolve and fetch the reference\n const ref = resolveReference(uri)\n if (!ref) {\n throw new Error(`Invalid codex URI: ${uri}`)\n }\n\n const result = await this.config.cache.get(ref)\n return [\n {\n uri,\n mimeType: result.contentType,\n text: result.content.toString('utf-8'),\n },\n ]\n }\n\n /**\n * Handle JSON-RPC request\n *\n * This method handles the low-level MCP protocol messages.\n */\n async handleRequest(method: string, params?: Record<string, unknown>): Promise<unknown> {\n switch (method) {\n case 'initialize':\n return {\n protocolVersion: '2024-11-05',\n serverInfo: this.getServerInfo(),\n capabilities: this.getCapabilities(),\n }\n\n case 'tools/list':\n return { tools: this.listTools() }\n\n case 'tools/call': {\n const { name, arguments: args } = params as { name: string; arguments: Record<string, unknown> }\n return await this.callTool(name, args)\n }\n\n case 'resources/list':\n return { resources: await this.listResources() }\n\n case 'resources/templates/list':\n return { resourceTemplates: this.listResourceTemplates() }\n\n case 'resources/read': {\n const { uri } = params as { uri: string }\n return { contents: await this.readResource(uri) }\n }\n\n case 'prompts/list':\n return { prompts: [] }\n\n default:\n throw new Error(`Unknown method: ${method}`)\n }\n }\n\n /**\n * Process a JSON-RPC message\n */\n async processMessage(message: string): Promise<string> {\n let id: unknown = null\n\n try {\n const request = JSON.parse(message)\n id = request.id\n const { method, params } = request\n\n const result = await this.handleRequest(method, params)\n\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n result,\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n error: {\n code: -32603,\n message: errorMessage,\n },\n })\n }\n }\n}\n\n/**\n * Create an MCP server\n */\nexport function createMcpServer(config: McpServerConfig): McpServer {\n return new McpServer(config)\n}\n","/**\n * MCP Tool definitions and handlers\n *\n * Implements the tools exposed by the Codex MCP server.\n */\n\nimport type { CacheManager } from '@fractary/codex'\nimport type { StorageManager } from '@fractary/codex'\nimport { resolveReference } from '@fractary/codex'\nimport type {\n McpTool,\n ToolResult,\n FetchToolArgs,\n SearchToolArgs,\n ListToolArgs,\n InvalidateToolArgs,\n} from './types.js'\n\n/**\n * Tool definitions for the MCP server\n */\nexport const CODEX_TOOLS: McpTool[] = [\n {\n name: 'codex_fetch',\n description: 'Fetch a document from the Codex knowledge base by URI. Returns the document content.',\n inputSchema: {\n type: 'object',\n properties: {\n uri: {\n type: 'string',\n description: 'Codex URI in format: codex://org/project/path/to/file.md',\n },\n branch: {\n type: 'string',\n description: 'Git branch to fetch from (default: main)',\n },\n noCache: {\n type: 'boolean',\n description: 'Bypass cache and fetch fresh content',\n },\n },\n required: ['uri'],\n },\n },\n {\n name: 'codex_search',\n description: 'Search for documents in the Codex knowledge base.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query string',\n },\n org: {\n type: 'string',\n description: 'Filter by organization',\n },\n project: {\n type: 'string',\n description: 'Filter by project',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results (default: 10)',\n },\n type: {\n type: 'string',\n description: 'Filter by artifact type (e.g., docs, specs, logs)',\n },\n },\n required: ['query'],\n },\n },\n {\n name: 'codex_list',\n description: 'List documents in the Codex cache.',\n inputSchema: {\n type: 'object',\n properties: {\n org: {\n type: 'string',\n description: 'Filter by organization',\n },\n project: {\n type: 'string',\n description: 'Filter by project',\n },\n includeExpired: {\n type: 'boolean',\n description: 'Include expired cache entries',\n },\n },\n },\n },\n {\n name: 'codex_invalidate',\n description: 'Invalidate cached documents matching a pattern.',\n inputSchema: {\n type: 'object',\n properties: {\n pattern: {\n type: 'string',\n description: 'URI pattern to invalidate (supports regex)',\n },\n },\n required: ['pattern'],\n },\n },\n]\n\n/**\n * Tool handler context\n */\nexport interface ToolHandlerContext {\n cache: CacheManager\n storage: StorageManager\n}\n\n/**\n * Create a text result\n */\nfunction textResult(text: string, isError = false): ToolResult {\n return {\n content: [{ type: 'text', text }],\n isError,\n }\n}\n\n/**\n * Create a resource result\n */\nfunction resourceResult(uri: string, content: string, mimeType?: string): ToolResult {\n return {\n content: [\n {\n type: 'resource',\n resource: {\n uri,\n mimeType,\n text: content,\n },\n },\n ],\n }\n}\n\n/**\n * Handle codex_fetch tool\n */\nexport async function handleFetch(args: FetchToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { uri, branch, noCache } = args\n\n // Validate input\n if (!uri || typeof uri !== 'string') {\n return textResult('URI is required and must be a string', true)\n }\n\n if (branch && typeof branch !== 'string') {\n return textResult('Branch must be a string', true)\n }\n\n // Resolve the reference\n const ref = resolveReference(uri)\n if (!ref) {\n return textResult(`Invalid codex URI: ${uri}`, true)\n }\n\n try {\n let result\n\n if (noCache) {\n // Bypass cache, fetch directly\n result = await ctx.storage.fetch(ref, { branch })\n // Still cache the result for next time\n await ctx.cache.set(uri, result)\n } else {\n // Use cache\n result = await ctx.cache.get(ref, { branch })\n }\n\n const content = result.content.toString('utf-8')\n return resourceResult(uri, content, result.contentType)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return textResult(`Failed to fetch ${uri}: ${message}`, true)\n }\n}\n\n/**\n * Handle codex_search tool\n *\n * Note: This is a basic implementation that searches cached entries.\n * A more sophisticated implementation might use a search index.\n */\nexport async function handleSearch(args: SearchToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { query, org, project, limit = 10 } = args\n\n // Validate input\n if (!query || typeof query !== 'string') {\n return textResult('Query is required and must be a string', true)\n }\n\n if (query.length > 500) {\n return textResult('Query too long (max 500 characters)', true)\n }\n\n if (typeof limit !== 'number' || limit < 1 || limit > 100) {\n return textResult('Limit must be a number between 1 and 100', true)\n }\n\n // Get all cached entries\n const stats = await ctx.cache.getStats()\n if (stats.entryCount === 0) {\n return textResult('No documents in cache. Use codex_fetch to load documents first.')\n }\n\n // This is a simplified search - in a real implementation,\n // we would use a proper search index\n // For now, we search through the cached URIs and content\n\n // Note: This is a placeholder. The actual search implementation\n // would depend on having access to the cache persistence layer's\n // list of URIs and their content.\n\n const message = `Search functionality requires a search index.\nQuery: \"${query}\"\nFilters: org=${org || 'any'}, project=${project || 'any'}\nLimit: ${limit}\n\nTo fetch documents, use codex_fetch with a specific URI like:\ncodex://org/project/docs/file.md`\n\n return textResult(message)\n}\n\n/**\n * Handle codex_list tool\n */\nexport async function handleList(args: ListToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { org, project, includeExpired } = args\n\n // Get cache stats and any available info\n const stats = await ctx.cache.getStats()\n\n let message = `Cache Statistics:\n- Total entries: ${stats.entryCount}\n- Memory entries: ${stats.memoryEntries}\n- Memory size: ${formatBytes(stats.memorySize)}\n- Total size: ${formatBytes(stats.totalSize)}\n- Fresh: ${stats.freshCount}\n- Stale: ${stats.staleCount}\n- Expired: ${stats.expiredCount}`\n\n if (org) {\n message += `\\n\\nFiltered by org: ${org}`\n }\n if (project) {\n message += `\\nFiltered by project: ${project}`\n }\n if (includeExpired) {\n message += `\\nIncluding expired entries`\n }\n\n return textResult(message)\n}\n\n/**\n * Validate and sanitize regex pattern to prevent ReDoS attacks\n */\nfunction validateRegexPattern(pattern: string): { valid: boolean; error?: string } {\n // Check pattern length (prevent extremely long patterns)\n if (pattern.length > 1000) {\n return { valid: false, error: 'Pattern too long (max 1000 characters)' }\n }\n\n // Check for common ReDoS patterns\n const redosPatterns = [\n /(\\.\\*){3,}/, // Multiple consecutive .*\n /(\\+\\+|\\*\\*|\\?\\?)/, // Nested quantifiers\n /(\\([^)]*){10,}/, // Too many groups\n /(\\[[^\\]]{100,})/, // Very long character classes\n ]\n\n for (const redos of redosPatterns) {\n if (redos.test(pattern)) {\n return { valid: false, error: 'Pattern contains potentially dangerous constructs' }\n }\n }\n\n // Try to compile the regex to check for syntax errors\n try {\n new RegExp(pattern)\n return { valid: true }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Invalid regex'\n return { valid: false, error: message }\n }\n}\n\n/**\n * Handle codex_invalidate tool\n */\nexport async function handleInvalidate(args: InvalidateToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { pattern } = args\n\n if (!pattern || typeof pattern !== 'string') {\n return textResult('Pattern is required and must be a string', true)\n }\n\n // Validate pattern to prevent ReDoS\n const validation = validateRegexPattern(pattern)\n if (!validation.valid) {\n return textResult(`Invalid pattern: ${validation.error}`, true)\n }\n\n try {\n const regex = new RegExp(pattern)\n const count = await ctx.cache.invalidatePattern(regex)\n\n return textResult(`Invalidated ${count} cache entries matching pattern: ${pattern}`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return textResult(`Failed to invalidate cache: ${message}`, true)\n }\n}\n\n/**\n * Route a tool call to its handler\n */\nexport async function handleToolCall(\n name: string,\n args: Record<string, unknown>,\n ctx: ToolHandlerContext\n): Promise<ToolResult> {\n switch (name) {\n case 'codex_fetch':\n return handleFetch(args as unknown as FetchToolArgs, ctx)\n case 'codex_search':\n return handleSearch(args as unknown as SearchToolArgs, ctx)\n case 'codex_list':\n return handleList(args as unknown as ListToolArgs, ctx)\n case 'codex_invalidate':\n return handleInvalidate(args as unknown as InvalidateToolArgs, ctx)\n default:\n return textResult(`Unknown tool: ${name}`, true)\n }\n}\n\n/**\n * Format bytes to human readable string\n */\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`\n}\n"],"mappings":"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","names":["resolveReference","resolveReference"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/server.ts","../src/tools.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry point for @fractary/codex-mcp-server\n *\n * Provides MCP server with stdio transport.\n */\n\nimport { Command } from 'commander'\nimport { createCacheManager, createStorageManager } from '@fractary/codex'\nimport { readFileSync } from 'fs'\nimport * as yaml from 'js-yaml'\nimport { McpServer } from './server.js'\n\nconst program = new Command()\n\nprogram\n .name('fractary-codex-mcp')\n .description('MCP server for Fractary Codex knowledge management')\n .version('0.1.0')\n .option('--config <path>', 'Path to config file', '.fractary/codex.yaml')\n .action(async (options) => {\n // Load configuration\n let config: Record<string, unknown> = {}\n try {\n const configFile = readFileSync(options.config, 'utf-8')\n config = yaml.load(configFile) as Record<string, unknown>\n } catch (error) {\n // Config file is optional - continue with defaults\n if (options.config !== '.fractary/codex.yaml') {\n console.error(`Warning: Could not load config file: ${options.config}`)\n }\n }\n\n // Initialize storage and cache managers\n const storage = createStorageManager(config.storage as Record<string, unknown> | undefined)\n const cache = createCacheManager({\n cacheDir: (config.cache as Record<string, unknown>)?.cacheDir as string || '.fractary/cache',\n ...(config.cache as Record<string, unknown>),\n })\n\n // Create MCP server\n const server = new McpServer({\n name: 'fractary-codex',\n version: '0.1.0',\n cache,\n storage,\n })\n\n // Stdio mode\n process.stdin.setEncoding('utf-8')\n\n let buffer = ''\n process.stdin.on('data', async (chunk) => {\n buffer += chunk\n const lines = buffer.split('\\n')\n buffer = lines.pop() || ''\n\n for (const line of lines) {\n if (line.trim()) {\n try {\n const message = JSON.parse(line)\n const response = await handleMessage(server, message)\n process.stdout.write(JSON.stringify(response) + '\\n')\n } catch (error) {\n const errorResponse = {\n jsonrpc: '2.0',\n error: {\n code: -32700,\n message: 'Parse error',\n data: error instanceof Error ? error.message : 'Unknown error',\n },\n id: null,\n }\n process.stdout.write(JSON.stringify(errorResponse) + '\\n')\n }\n }\n }\n })\n\n process.stdin.on('end', () => {\n process.exit(0)\n })\n\n console.error('MCP server running in stdio mode')\n })\n\n/**\n * Handle a JSON-RPC message\n */\nasync function handleMessage(\n server: McpServer,\n message: Record<string, unknown>\n): Promise<Record<string, unknown>> {\n const method = message.method as string\n const params = (message.params as Record<string, unknown>) || {}\n const id = message.id\n\n try {\n let result: unknown\n\n switch (method) {\n case 'initialize':\n result = server.getServerInfo()\n break\n\n case 'tools/list':\n result = { tools: server.listTools() }\n break\n\n case 'tools/call': {\n const toolName = params.name as string\n const toolArgs = params.arguments as Record<string, unknown>\n result = await server.callTool(toolName, toolArgs)\n break\n }\n\n case 'resources/list':\n result = { resources: [] }\n break\n\n default:\n return {\n jsonrpc: '2.0',\n error: {\n code: -32601,\n message: `Method not found: ${method}`,\n },\n id,\n }\n }\n\n return {\n jsonrpc: '2.0',\n result,\n id,\n }\n } catch (error) {\n return {\n jsonrpc: '2.0',\n error: {\n code: -32603,\n message: 'Internal error',\n data: error instanceof Error ? error.message : 'Unknown error',\n },\n id,\n }\n }\n}\n\n// Run the program\nprogram.parse(process.argv)\n","/**\n * MCP Server implementation\n *\n * Implements a Model Context Protocol server for the Codex SDK.\n * This server can be used standalone or embedded in other applications.\n */\n\nimport type { CacheManager } from '@fractary/codex'\nimport type { StorageManager } from '@fractary/codex'\nimport { resolveReference } from '@fractary/codex'\nimport type {\n McpServerInfo,\n McpCapabilities,\n McpTool,\n McpResource,\n McpResourceTemplate,\n ResourceContent,\n ToolResult,\n} from './types.js'\nimport { CODEX_TOOLS, handleToolCall, type ToolHandlerContext } from './tools.js'\n\n/**\n * MCP Server configuration\n */\nexport interface McpServerConfig {\n /** Server name */\n name?: string\n /** Server version */\n version?: string\n /** Cache manager instance */\n cache: CacheManager\n /** Storage manager instance */\n storage: StorageManager\n}\n\n/**\n * MCP Server for Codex\n *\n * Provides a Model Context Protocol server implementation that exposes\n * Codex functionality as MCP tools and resources.\n */\nexport class McpServer {\n private config: Required<Omit<McpServerConfig, 'cache' | 'storage'>> & Pick<McpServerConfig, 'cache' | 'storage'>\n private toolContext: ToolHandlerContext\n\n constructor(config: McpServerConfig) {\n this.config = {\n name: config.name ?? 'codex',\n version: config.version ?? '1.0.0',\n cache: config.cache,\n storage: config.storage,\n }\n\n this.toolContext = {\n cache: config.cache,\n storage: config.storage,\n }\n }\n\n /**\n * Get server info\n */\n getServerInfo(): McpServerInfo {\n return {\n name: this.config.name,\n version: this.config.version,\n capabilities: this.getCapabilities(),\n }\n }\n\n /**\n * Get server capabilities\n */\n getCapabilities(): McpCapabilities {\n return {\n tools: {\n listChanged: false,\n },\n resources: {\n subscribe: false,\n listChanged: false,\n },\n }\n }\n\n /**\n * List available tools\n */\n listTools(): McpTool[] {\n return CODEX_TOOLS\n }\n\n /**\n * Call a tool\n */\n async callTool(name: string, args: Record<string, unknown>): Promise<ToolResult> {\n return handleToolCall(name, args, this.toolContext)\n }\n\n /**\n * List available resources\n */\n async listResources(): Promise<McpResource[]> {\n // List cached documents as resources\n const resources: McpResource[] = []\n\n // Get cache stats for info\n const stats = await this.config.cache.getStats()\n\n // Add a summary resource\n resources.push({\n uri: 'codex://cache/summary',\n name: 'Cache Summary',\n description: `${stats.entryCount} cached documents`,\n mimeType: 'text/plain',\n })\n\n return resources\n }\n\n /**\n * List resource templates\n */\n listResourceTemplates(): McpResourceTemplate[] {\n return [\n {\n uriTemplate: 'codex://{org}/{project}/{path}',\n name: 'Codex Document',\n description: 'Fetch a document from the Codex knowledge base',\n mimeType: 'text/markdown',\n },\n ]\n }\n\n /**\n * Read a resource\n */\n async readResource(uri: string): Promise<ResourceContent[]> {\n // Handle special URIs\n if (uri === 'codex://cache/summary') {\n const stats = await this.config.cache.getStats()\n return [\n {\n uri,\n mimeType: 'text/plain',\n text: `Cache Statistics:\n- Total entries: ${stats.entryCount}\n- Memory entries: ${stats.memoryEntries}\n- Fresh: ${stats.freshCount}\n- Stale: ${stats.staleCount}\n- Expired: ${stats.expiredCount}`,\n },\n ]\n }\n\n // Resolve and fetch the reference\n const ref = resolveReference(uri)\n if (!ref) {\n throw new Error(`Invalid codex URI: ${uri}`)\n }\n\n const result = await this.config.cache.get(ref)\n return [\n {\n uri,\n mimeType: result.contentType,\n text: result.content.toString('utf-8'),\n },\n ]\n }\n\n /**\n * Handle JSON-RPC request\n *\n * This method handles the low-level MCP protocol messages.\n */\n async handleRequest(method: string, params?: Record<string, unknown>): Promise<unknown> {\n switch (method) {\n case 'initialize':\n return {\n protocolVersion: '2024-11-05',\n serverInfo: this.getServerInfo(),\n capabilities: this.getCapabilities(),\n }\n\n case 'tools/list':\n return { tools: this.listTools() }\n\n case 'tools/call': {\n const { name, arguments: args } = params as { name: string; arguments: Record<string, unknown> }\n return await this.callTool(name, args)\n }\n\n case 'resources/list':\n return { resources: await this.listResources() }\n\n case 'resources/templates/list':\n return { resourceTemplates: this.listResourceTemplates() }\n\n case 'resources/read': {\n const { uri } = params as { uri: string }\n return { contents: await this.readResource(uri) }\n }\n\n case 'prompts/list':\n return { prompts: [] }\n\n default:\n throw new Error(`Unknown method: ${method}`)\n }\n }\n\n /**\n * Process a JSON-RPC message\n */\n async processMessage(message: string): Promise<string> {\n let id: unknown = null\n\n try {\n const request = JSON.parse(message)\n id = request.id\n const { method, params } = request\n\n const result = await this.handleRequest(method, params)\n\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n result,\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n error: {\n code: -32603,\n message: errorMessage,\n },\n })\n }\n }\n}\n\n/**\n * Create an MCP server\n */\nexport function createMcpServer(config: McpServerConfig): McpServer {\n return new McpServer(config)\n}\n","/**\n * MCP Tool definitions and handlers\n *\n * Implements the tools exposed by the Codex MCP server.\n */\n\nimport type { CacheManager } from '@fractary/codex'\nimport type { StorageManager } from '@fractary/codex'\nimport { resolveReference } from '@fractary/codex'\nimport type {\n McpTool,\n ToolResult,\n FetchToolArgs,\n SearchToolArgs,\n ListToolArgs,\n CacheClearToolArgs,\n} from './types.js'\n\n/**\n * Tool definitions for the MCP server\n */\nexport const CODEX_TOOLS: McpTool[] = [\n {\n name: 'codex_document_fetch',\n description: 'Fetch a document from the Codex knowledge base by URI. Returns the document content.',\n inputSchema: {\n type: 'object',\n properties: {\n uri: {\n type: 'string',\n description: 'Codex URI in format: codex://org/project/path/to/file.md',\n },\n branch: {\n type: 'string',\n description: 'Git branch to fetch from (default: main)',\n },\n noCache: {\n type: 'boolean',\n description: 'Bypass cache and fetch fresh content',\n },\n },\n required: ['uri'],\n },\n },\n {\n name: 'codex_search',\n description: 'Search for documents in the Codex knowledge base.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query string',\n },\n org: {\n type: 'string',\n description: 'Filter by organization',\n },\n project: {\n type: 'string',\n description: 'Filter by project',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results (default: 10)',\n },\n type: {\n type: 'string',\n description: 'Filter by artifact type (e.g., docs, specs, logs)',\n },\n },\n required: ['query'],\n },\n },\n {\n name: 'codex_cache_list',\n description: 'List documents in the Codex cache.',\n inputSchema: {\n type: 'object',\n properties: {\n org: {\n type: 'string',\n description: 'Filter by organization',\n },\n project: {\n type: 'string',\n description: 'Filter by project',\n },\n includeExpired: {\n type: 'boolean',\n description: 'Include expired cache entries',\n },\n },\n },\n },\n {\n name: 'codex_cache_clear',\n description: 'Clear cached documents matching a pattern.',\n inputSchema: {\n type: 'object',\n properties: {\n pattern: {\n type: 'string',\n description: 'URI pattern to invalidate (supports regex)',\n },\n },\n required: ['pattern'],\n },\n },\n]\n\n/**\n * Tool handler context\n */\nexport interface ToolHandlerContext {\n cache: CacheManager\n storage: StorageManager\n}\n\n/**\n * Create a text result\n */\nfunction textResult(text: string, isError = false): ToolResult {\n return {\n content: [{ type: 'text', text }],\n isError,\n }\n}\n\n/**\n * Create a resource result\n */\nfunction resourceResult(uri: string, content: string, mimeType?: string): ToolResult {\n return {\n content: [\n {\n type: 'resource',\n resource: {\n uri,\n mimeType,\n text: content,\n },\n },\n ],\n }\n}\n\n/**\n * Handle codex_document_fetch tool\n */\nexport async function handleFetch(args: FetchToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { uri, branch, noCache } = args\n\n // Validate input\n if (!uri || typeof uri !== 'string') {\n return textResult('URI is required and must be a string', true)\n }\n\n if (branch && typeof branch !== 'string') {\n return textResult('Branch must be a string', true)\n }\n\n // Resolve the reference\n const ref = resolveReference(uri)\n if (!ref) {\n return textResult(`Invalid codex URI: ${uri}`, true)\n }\n\n try {\n let result\n\n if (noCache) {\n // Bypass cache, fetch directly\n result = await ctx.storage.fetch(ref, { branch })\n // Still cache the result for next time\n await ctx.cache.set(uri, result)\n } else {\n // Use cache\n result = await ctx.cache.get(ref, { branch })\n }\n\n const content = result.content.toString('utf-8')\n return resourceResult(uri, content, result.contentType)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return textResult(`Failed to fetch ${uri}: ${message}`, true)\n }\n}\n\n/**\n * Handle codex_search tool\n *\n * Note: This is a basic implementation that searches cached entries.\n * A more sophisticated implementation might use a search index.\n */\nexport async function handleSearch(args: SearchToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { query, org, project, limit = 10 } = args\n\n // Validate input\n if (!query || typeof query !== 'string') {\n return textResult('Query is required and must be a string', true)\n }\n\n if (query.length > 500) {\n return textResult('Query too long (max 500 characters)', true)\n }\n\n if (typeof limit !== 'number' || limit < 1 || limit > 100) {\n return textResult('Limit must be a number between 1 and 100', true)\n }\n\n // Get all cached entries\n const stats = await ctx.cache.getStats()\n if (stats.entryCount === 0) {\n return textResult('No documents in cache. Use codex_document_fetch to load documents first.')\n }\n\n // This is a simplified search - in a real implementation,\n // we would use a proper search index\n // For now, we search through the cached URIs and content\n\n // Note: This is a placeholder. The actual search implementation\n // would depend on having access to the cache persistence layer's\n // list of URIs and their content.\n\n const message = `Search functionality requires a search index.\nQuery: \"${query}\"\nFilters: org=${org || 'any'}, project=${project || 'any'}\nLimit: ${limit}\n\nTo fetch documents, use codex_document_fetch with a specific URI like:\ncodex://org/project/docs/file.md`\n\n return textResult(message)\n}\n\n/**\n * Handle codex_cache_list tool\n */\nexport async function handleList(args: ListToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { org, project, includeExpired } = args\n\n // Get cache stats and any available info\n const stats = await ctx.cache.getStats()\n\n let message = `Cache Statistics:\n- Total entries: ${stats.entryCount}\n- Memory entries: ${stats.memoryEntries}\n- Memory size: ${formatBytes(stats.memorySize)}\n- Total size: ${formatBytes(stats.totalSize)}\n- Fresh: ${stats.freshCount}\n- Stale: ${stats.staleCount}\n- Expired: ${stats.expiredCount}`\n\n if (org) {\n message += `\\n\\nFiltered by org: ${org}`\n }\n if (project) {\n message += `\\nFiltered by project: ${project}`\n }\n if (includeExpired) {\n message += `\\nIncluding expired entries`\n }\n\n return textResult(message)\n}\n\n/**\n * Validate and sanitize regex pattern to prevent ReDoS attacks\n */\nfunction validateRegexPattern(pattern: string): { valid: boolean; error?: string } {\n // Check pattern length (prevent extremely long patterns)\n if (pattern.length > 1000) {\n return { valid: false, error: 'Pattern too long (max 1000 characters)' }\n }\n\n // Check for common ReDoS patterns\n const redosPatterns = [\n /(\\.\\*){3,}/, // Multiple consecutive .*\n /(\\+\\+|\\*\\*|\\?\\?)/, // Nested quantifiers\n /(\\([^)]*){10,}/, // Too many groups\n /(\\[[^\\]]{100,})/, // Very long character classes\n ]\n\n for (const redos of redosPatterns) {\n if (redos.test(pattern)) {\n return { valid: false, error: 'Pattern contains potentially dangerous constructs' }\n }\n }\n\n // Try to compile the regex to check for syntax errors\n try {\n new RegExp(pattern)\n return { valid: true }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Invalid regex'\n return { valid: false, error: message }\n }\n}\n\n/**\n * Handle codex_cache_clear tool\n */\nexport async function handleCacheClear(args: CacheClearToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { pattern } = args\n\n if (!pattern || typeof pattern !== 'string') {\n return textResult('Pattern is required and must be a string', true)\n }\n\n // Validate pattern to prevent ReDoS\n const validation = validateRegexPattern(pattern)\n if (!validation.valid) {\n return textResult(`Invalid pattern: ${validation.error}`, true)\n }\n\n try {\n const regex = new RegExp(pattern)\n const count = await ctx.cache.invalidatePattern(regex)\n\n return textResult(`Cleared ${count} cache entries matching pattern: ${pattern}`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return textResult(`Failed to clear cache: ${message}`, true)\n }\n}\n\n/**\n * Route a tool call to its handler\n */\nexport async function handleToolCall(\n name: string,\n args: Record<string, unknown>,\n ctx: ToolHandlerContext\n): Promise<ToolResult> {\n switch (name) {\n case 'codex_document_fetch':\n return handleFetch(args as unknown as FetchToolArgs, ctx)\n case 'codex_search':\n return handleSearch(args as unknown as SearchToolArgs, ctx)\n case 'codex_cache_list':\n return handleList(args as unknown as ListToolArgs, ctx)\n case 'codex_cache_clear':\n return handleCacheClear(args as unknown as CacheClearToolArgs, ctx)\n default:\n return textResult(`Unknown tool: ${name}`, true)\n }\n}\n\n/**\n * Format bytes to human readable string\n */\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`\n}\n"],"mappings":"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","names":["resolveReference","resolveReference"]}
package/dist/index.d.ts CHANGED
@@ -38,7 +38,7 @@ interface ListToolArgs {
38
38
  project?: string;
39
39
  includeExpired?: boolean;
40
40
  }
41
- interface InvalidateToolArgs {
41
+ interface CacheClearToolArgs {
42
42
  pattern: string;
43
43
  }
44
44
  interface ToolResult {
@@ -115,7 +115,7 @@ interface ToolHandlerContext {
115
115
  declare function handleFetch(args: FetchToolArgs, ctx: ToolHandlerContext): Promise<ToolResult>;
116
116
  declare function handleSearch(args: SearchToolArgs, ctx: ToolHandlerContext): Promise<ToolResult>;
117
117
  declare function handleList(args: ListToolArgs, ctx: ToolHandlerContext): Promise<ToolResult>;
118
- declare function handleInvalidate(args: InvalidateToolArgs, ctx: ToolHandlerContext): Promise<ToolResult>;
118
+ declare function handleCacheClear(args: CacheClearToolArgs, ctx: ToolHandlerContext): Promise<ToolResult>;
119
119
  declare function handleToolCall(name: string, args: Record<string, unknown>, ctx: ToolHandlerContext): Promise<ToolResult>;
120
120
 
121
- export { CODEX_TOOLS, type FetchToolArgs, type InvalidateToolArgs, type ListToolArgs, type McpCapabilities, type McpResource, type McpResourceTemplate, McpServer, type McpServerConfig, type McpServerInfo, type McpTool, type ResourceContent, type SearchResult, type SearchToolArgs, type ToolHandlerContext, type ToolResult, createMcpServer, handleFetch, handleInvalidate, handleList, handleSearch, handleToolCall };
121
+ export { CODEX_TOOLS, type CacheClearToolArgs, type FetchToolArgs, type ListToolArgs, type McpCapabilities, type McpResource, type McpResourceTemplate, McpServer, type McpServerConfig, type McpServerInfo, type McpTool, type ResourceContent, type SearchResult, type SearchToolArgs, type ToolHandlerContext, type ToolResult, createMcpServer, handleCacheClear, handleFetch, handleList, handleSearch, handleToolCall };
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { resolveReference as resolveReference2 } from "@fractary/codex";
5
5
  import { resolveReference } from "@fractary/codex";
6
6
  var CODEX_TOOLS = [
7
7
  {
8
- name: "codex_fetch",
8
+ name: "codex_document_fetch",
9
9
  description: "Fetch a document from the Codex knowledge base by URI. Returns the document content.",
10
10
  inputSchema: {
11
11
  type: "object",
@@ -57,7 +57,7 @@ var CODEX_TOOLS = [
57
57
  }
58
58
  },
59
59
  {
60
- name: "codex_list",
60
+ name: "codex_cache_list",
61
61
  description: "List documents in the Codex cache.",
62
62
  inputSchema: {
63
63
  type: "object",
@@ -78,8 +78,8 @@ var CODEX_TOOLS = [
78
78
  }
79
79
  },
80
80
  {
81
- name: "codex_invalidate",
82
- description: "Invalidate cached documents matching a pattern.",
81
+ name: "codex_cache_clear",
82
+ description: "Clear cached documents matching a pattern.",
83
83
  inputSchema: {
84
84
  type: "object",
85
85
  properties: {
@@ -152,14 +152,14 @@ async function handleSearch(args, ctx) {
152
152
  }
153
153
  const stats = await ctx.cache.getStats();
154
154
  if (stats.entryCount === 0) {
155
- return textResult("No documents in cache. Use codex_fetch to load documents first.");
155
+ return textResult("No documents in cache. Use codex_document_fetch to load documents first.");
156
156
  }
157
157
  const message = `Search functionality requires a search index.
158
158
  Query: "${query}"
159
159
  Filters: org=${org || "any"}, project=${project || "any"}
160
160
  Limit: ${limit}
161
161
 
162
- To fetch documents, use codex_fetch with a specific URI like:
162
+ To fetch documents, use codex_document_fetch with a specific URI like:
163
163
  codex://org/project/docs/file.md`;
164
164
  return textResult(message);
165
165
  }
@@ -216,7 +216,7 @@ function validateRegexPattern(pattern) {
216
216
  return { valid: false, error: message };
217
217
  }
218
218
  }
219
- async function handleInvalidate(args, ctx) {
219
+ async function handleCacheClear(args, ctx) {
220
220
  const { pattern } = args;
221
221
  if (!pattern || typeof pattern !== "string") {
222
222
  return textResult("Pattern is required and must be a string", true);
@@ -228,22 +228,22 @@ async function handleInvalidate(args, ctx) {
228
228
  try {
229
229
  const regex = new RegExp(pattern);
230
230
  const count = await ctx.cache.invalidatePattern(regex);
231
- return textResult(`Invalidated ${count} cache entries matching pattern: ${pattern}`);
231
+ return textResult(`Cleared ${count} cache entries matching pattern: ${pattern}`);
232
232
  } catch (error) {
233
233
  const message = error instanceof Error ? error.message : String(error);
234
- return textResult(`Failed to invalidate cache: ${message}`, true);
234
+ return textResult(`Failed to clear cache: ${message}`, true);
235
235
  }
236
236
  }
237
237
  async function handleToolCall(name, args, ctx) {
238
238
  switch (name) {
239
- case "codex_fetch":
239
+ case "codex_document_fetch":
240
240
  return handleFetch(args, ctx);
241
241
  case "codex_search":
242
242
  return handleSearch(args, ctx);
243
- case "codex_list":
243
+ case "codex_cache_list":
244
244
  return handleList(args, ctx);
245
- case "codex_invalidate":
246
- return handleInvalidate(args, ctx);
245
+ case "codex_cache_clear":
246
+ return handleCacheClear(args, ctx);
247
247
  default:
248
248
  return textResult(`Unknown tool: ${name}`, true);
249
249
  }
@@ -435,8 +435,8 @@ export {
435
435
  CODEX_TOOLS,
436
436
  McpServer,
437
437
  createMcpServer,
438
+ handleCacheClear,
438
439
  handleFetch,
439
- handleInvalidate,
440
440
  handleList,
441
441
  handleSearch,
442
442
  handleToolCall
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/tools.ts"],"sourcesContent":["/**\n * MCP Server implementation\n *\n * Implements a Model Context Protocol server for the Codex SDK.\n * This server can be used standalone or embedded in other applications.\n */\n\nimport type { CacheManager } from '@fractary/codex'\nimport type { StorageManager } from '@fractary/codex'\nimport { resolveReference } from '@fractary/codex'\nimport type {\n McpServerInfo,\n McpCapabilities,\n McpTool,\n McpResource,\n McpResourceTemplate,\n ResourceContent,\n ToolResult,\n} from './types.js'\nimport { CODEX_TOOLS, handleToolCall, type ToolHandlerContext } from './tools.js'\n\n/**\n * MCP Server configuration\n */\nexport interface McpServerConfig {\n /** Server name */\n name?: string\n /** Server version */\n version?: string\n /** Cache manager instance */\n cache: CacheManager\n /** Storage manager instance */\n storage: StorageManager\n}\n\n/**\n * MCP Server for Codex\n *\n * Provides a Model Context Protocol server implementation that exposes\n * Codex functionality as MCP tools and resources.\n */\nexport class McpServer {\n private config: Required<Omit<McpServerConfig, 'cache' | 'storage'>> & Pick<McpServerConfig, 'cache' | 'storage'>\n private toolContext: ToolHandlerContext\n\n constructor(config: McpServerConfig) {\n this.config = {\n name: config.name ?? 'codex',\n version: config.version ?? '1.0.0',\n cache: config.cache,\n storage: config.storage,\n }\n\n this.toolContext = {\n cache: config.cache,\n storage: config.storage,\n }\n }\n\n /**\n * Get server info\n */\n getServerInfo(): McpServerInfo {\n return {\n name: this.config.name,\n version: this.config.version,\n capabilities: this.getCapabilities(),\n }\n }\n\n /**\n * Get server capabilities\n */\n getCapabilities(): McpCapabilities {\n return {\n tools: {\n listChanged: false,\n },\n resources: {\n subscribe: false,\n listChanged: false,\n },\n }\n }\n\n /**\n * List available tools\n */\n listTools(): McpTool[] {\n return CODEX_TOOLS\n }\n\n /**\n * Call a tool\n */\n async callTool(name: string, args: Record<string, unknown>): Promise<ToolResult> {\n return handleToolCall(name, args, this.toolContext)\n }\n\n /**\n * List available resources\n */\n async listResources(): Promise<McpResource[]> {\n // List cached documents as resources\n const resources: McpResource[] = []\n\n // Get cache stats for info\n const stats = await this.config.cache.getStats()\n\n // Add a summary resource\n resources.push({\n uri: 'codex://cache/summary',\n name: 'Cache Summary',\n description: `${stats.entryCount} cached documents`,\n mimeType: 'text/plain',\n })\n\n return resources\n }\n\n /**\n * List resource templates\n */\n listResourceTemplates(): McpResourceTemplate[] {\n return [\n {\n uriTemplate: 'codex://{org}/{project}/{path}',\n name: 'Codex Document',\n description: 'Fetch a document from the Codex knowledge base',\n mimeType: 'text/markdown',\n },\n ]\n }\n\n /**\n * Read a resource\n */\n async readResource(uri: string): Promise<ResourceContent[]> {\n // Handle special URIs\n if (uri === 'codex://cache/summary') {\n const stats = await this.config.cache.getStats()\n return [\n {\n uri,\n mimeType: 'text/plain',\n text: `Cache Statistics:\n- Total entries: ${stats.entryCount}\n- Memory entries: ${stats.memoryEntries}\n- Fresh: ${stats.freshCount}\n- Stale: ${stats.staleCount}\n- Expired: ${stats.expiredCount}`,\n },\n ]\n }\n\n // Resolve and fetch the reference\n const ref = resolveReference(uri)\n if (!ref) {\n throw new Error(`Invalid codex URI: ${uri}`)\n }\n\n const result = await this.config.cache.get(ref)\n return [\n {\n uri,\n mimeType: result.contentType,\n text: result.content.toString('utf-8'),\n },\n ]\n }\n\n /**\n * Handle JSON-RPC request\n *\n * This method handles the low-level MCP protocol messages.\n */\n async handleRequest(method: string, params?: Record<string, unknown>): Promise<unknown> {\n switch (method) {\n case 'initialize':\n return {\n protocolVersion: '2024-11-05',\n serverInfo: this.getServerInfo(),\n capabilities: this.getCapabilities(),\n }\n\n case 'tools/list':\n return { tools: this.listTools() }\n\n case 'tools/call': {\n const { name, arguments: args } = params as { name: string; arguments: Record<string, unknown> }\n return await this.callTool(name, args)\n }\n\n case 'resources/list':\n return { resources: await this.listResources() }\n\n case 'resources/templates/list':\n return { resourceTemplates: this.listResourceTemplates() }\n\n case 'resources/read': {\n const { uri } = params as { uri: string }\n return { contents: await this.readResource(uri) }\n }\n\n case 'prompts/list':\n return { prompts: [] }\n\n default:\n throw new Error(`Unknown method: ${method}`)\n }\n }\n\n /**\n * Process a JSON-RPC message\n */\n async processMessage(message: string): Promise<string> {\n let id: unknown = null\n\n try {\n const request = JSON.parse(message)\n id = request.id\n const { method, params } = request\n\n const result = await this.handleRequest(method, params)\n\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n result,\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n error: {\n code: -32603,\n message: errorMessage,\n },\n })\n }\n }\n}\n\n/**\n * Create an MCP server\n */\nexport function createMcpServer(config: McpServerConfig): McpServer {\n return new McpServer(config)\n}\n","/**\n * MCP Tool definitions and handlers\n *\n * Implements the tools exposed by the Codex MCP server.\n */\n\nimport type { CacheManager } from '@fractary/codex'\nimport type { StorageManager } from '@fractary/codex'\nimport { resolveReference } from '@fractary/codex'\nimport type {\n McpTool,\n ToolResult,\n FetchToolArgs,\n SearchToolArgs,\n ListToolArgs,\n InvalidateToolArgs,\n} from './types.js'\n\n/**\n * Tool definitions for the MCP server\n */\nexport const CODEX_TOOLS: McpTool[] = [\n {\n name: 'codex_fetch',\n description: 'Fetch a document from the Codex knowledge base by URI. Returns the document content.',\n inputSchema: {\n type: 'object',\n properties: {\n uri: {\n type: 'string',\n description: 'Codex URI in format: codex://org/project/path/to/file.md',\n },\n branch: {\n type: 'string',\n description: 'Git branch to fetch from (default: main)',\n },\n noCache: {\n type: 'boolean',\n description: 'Bypass cache and fetch fresh content',\n },\n },\n required: ['uri'],\n },\n },\n {\n name: 'codex_search',\n description: 'Search for documents in the Codex knowledge base.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query string',\n },\n org: {\n type: 'string',\n description: 'Filter by organization',\n },\n project: {\n type: 'string',\n description: 'Filter by project',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results (default: 10)',\n },\n type: {\n type: 'string',\n description: 'Filter by artifact type (e.g., docs, specs, logs)',\n },\n },\n required: ['query'],\n },\n },\n {\n name: 'codex_list',\n description: 'List documents in the Codex cache.',\n inputSchema: {\n type: 'object',\n properties: {\n org: {\n type: 'string',\n description: 'Filter by organization',\n },\n project: {\n type: 'string',\n description: 'Filter by project',\n },\n includeExpired: {\n type: 'boolean',\n description: 'Include expired cache entries',\n },\n },\n },\n },\n {\n name: 'codex_invalidate',\n description: 'Invalidate cached documents matching a pattern.',\n inputSchema: {\n type: 'object',\n properties: {\n pattern: {\n type: 'string',\n description: 'URI pattern to invalidate (supports regex)',\n },\n },\n required: ['pattern'],\n },\n },\n]\n\n/**\n * Tool handler context\n */\nexport interface ToolHandlerContext {\n cache: CacheManager\n storage: StorageManager\n}\n\n/**\n * Create a text result\n */\nfunction textResult(text: string, isError = false): ToolResult {\n return {\n content: [{ type: 'text', text }],\n isError,\n }\n}\n\n/**\n * Create a resource result\n */\nfunction resourceResult(uri: string, content: string, mimeType?: string): ToolResult {\n return {\n content: [\n {\n type: 'resource',\n resource: {\n uri,\n mimeType,\n text: content,\n },\n },\n ],\n }\n}\n\n/**\n * Handle codex_fetch tool\n */\nexport async function handleFetch(args: FetchToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { uri, branch, noCache } = args\n\n // Validate input\n if (!uri || typeof uri !== 'string') {\n return textResult('URI is required and must be a string', true)\n }\n\n if (branch && typeof branch !== 'string') {\n return textResult('Branch must be a string', true)\n }\n\n // Resolve the reference\n const ref = resolveReference(uri)\n if (!ref) {\n return textResult(`Invalid codex URI: ${uri}`, true)\n }\n\n try {\n let result\n\n if (noCache) {\n // Bypass cache, fetch directly\n result = await ctx.storage.fetch(ref, { branch })\n // Still cache the result for next time\n await ctx.cache.set(uri, result)\n } else {\n // Use cache\n result = await ctx.cache.get(ref, { branch })\n }\n\n const content = result.content.toString('utf-8')\n return resourceResult(uri, content, result.contentType)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return textResult(`Failed to fetch ${uri}: ${message}`, true)\n }\n}\n\n/**\n * Handle codex_search tool\n *\n * Note: This is a basic implementation that searches cached entries.\n * A more sophisticated implementation might use a search index.\n */\nexport async function handleSearch(args: SearchToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { query, org, project, limit = 10 } = args\n\n // Validate input\n if (!query || typeof query !== 'string') {\n return textResult('Query is required and must be a string', true)\n }\n\n if (query.length > 500) {\n return textResult('Query too long (max 500 characters)', true)\n }\n\n if (typeof limit !== 'number' || limit < 1 || limit > 100) {\n return textResult('Limit must be a number between 1 and 100', true)\n }\n\n // Get all cached entries\n const stats = await ctx.cache.getStats()\n if (stats.entryCount === 0) {\n return textResult('No documents in cache. Use codex_fetch to load documents first.')\n }\n\n // This is a simplified search - in a real implementation,\n // we would use a proper search index\n // For now, we search through the cached URIs and content\n\n // Note: This is a placeholder. The actual search implementation\n // would depend on having access to the cache persistence layer's\n // list of URIs and their content.\n\n const message = `Search functionality requires a search index.\nQuery: \"${query}\"\nFilters: org=${org || 'any'}, project=${project || 'any'}\nLimit: ${limit}\n\nTo fetch documents, use codex_fetch with a specific URI like:\ncodex://org/project/docs/file.md`\n\n return textResult(message)\n}\n\n/**\n * Handle codex_list tool\n */\nexport async function handleList(args: ListToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { org, project, includeExpired } = args\n\n // Get cache stats and any available info\n const stats = await ctx.cache.getStats()\n\n let message = `Cache Statistics:\n- Total entries: ${stats.entryCount}\n- Memory entries: ${stats.memoryEntries}\n- Memory size: ${formatBytes(stats.memorySize)}\n- Total size: ${formatBytes(stats.totalSize)}\n- Fresh: ${stats.freshCount}\n- Stale: ${stats.staleCount}\n- Expired: ${stats.expiredCount}`\n\n if (org) {\n message += `\\n\\nFiltered by org: ${org}`\n }\n if (project) {\n message += `\\nFiltered by project: ${project}`\n }\n if (includeExpired) {\n message += `\\nIncluding expired entries`\n }\n\n return textResult(message)\n}\n\n/**\n * Validate and sanitize regex pattern to prevent ReDoS attacks\n */\nfunction validateRegexPattern(pattern: string): { valid: boolean; error?: string } {\n // Check pattern length (prevent extremely long patterns)\n if (pattern.length > 1000) {\n return { valid: false, error: 'Pattern too long (max 1000 characters)' }\n }\n\n // Check for common ReDoS patterns\n const redosPatterns = [\n /(\\.\\*){3,}/, // Multiple consecutive .*\n /(\\+\\+|\\*\\*|\\?\\?)/, // Nested quantifiers\n /(\\([^)]*){10,}/, // Too many groups\n /(\\[[^\\]]{100,})/, // Very long character classes\n ]\n\n for (const redos of redosPatterns) {\n if (redos.test(pattern)) {\n return { valid: false, error: 'Pattern contains potentially dangerous constructs' }\n }\n }\n\n // Try to compile the regex to check for syntax errors\n try {\n new RegExp(pattern)\n return { valid: true }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Invalid regex'\n return { valid: false, error: message }\n }\n}\n\n/**\n * Handle codex_invalidate tool\n */\nexport async function handleInvalidate(args: InvalidateToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { pattern } = args\n\n if (!pattern || typeof pattern !== 'string') {\n return textResult('Pattern is required and must be a string', true)\n }\n\n // Validate pattern to prevent ReDoS\n const validation = validateRegexPattern(pattern)\n if (!validation.valid) {\n return textResult(`Invalid pattern: ${validation.error}`, true)\n }\n\n try {\n const regex = new RegExp(pattern)\n const count = await ctx.cache.invalidatePattern(regex)\n\n return textResult(`Invalidated ${count} cache entries matching pattern: ${pattern}`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return textResult(`Failed to invalidate cache: ${message}`, true)\n }\n}\n\n/**\n * Route a tool call to its handler\n */\nexport async function handleToolCall(\n name: string,\n args: Record<string, unknown>,\n ctx: ToolHandlerContext\n): Promise<ToolResult> {\n switch (name) {\n case 'codex_fetch':\n return handleFetch(args as unknown as FetchToolArgs, ctx)\n case 'codex_search':\n return handleSearch(args as unknown as SearchToolArgs, ctx)\n case 'codex_list':\n return handleList(args as unknown as ListToolArgs, ctx)\n case 'codex_invalidate':\n return handleInvalidate(args as unknown as InvalidateToolArgs, ctx)\n default:\n return textResult(`Unknown tool: ${name}`, true)\n }\n}\n\n/**\n * Format bytes to human readable string\n */\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`\n}\n"],"mappings":"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","names":["resolveReference","resolveReference"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/tools.ts"],"sourcesContent":["/**\n * MCP Server implementation\n *\n * Implements a Model Context Protocol server for the Codex SDK.\n * This server can be used standalone or embedded in other applications.\n */\n\nimport type { CacheManager } from '@fractary/codex'\nimport type { StorageManager } from '@fractary/codex'\nimport { resolveReference } from '@fractary/codex'\nimport type {\n McpServerInfo,\n McpCapabilities,\n McpTool,\n McpResource,\n McpResourceTemplate,\n ResourceContent,\n ToolResult,\n} from './types.js'\nimport { CODEX_TOOLS, handleToolCall, type ToolHandlerContext } from './tools.js'\n\n/**\n * MCP Server configuration\n */\nexport interface McpServerConfig {\n /** Server name */\n name?: string\n /** Server version */\n version?: string\n /** Cache manager instance */\n cache: CacheManager\n /** Storage manager instance */\n storage: StorageManager\n}\n\n/**\n * MCP Server for Codex\n *\n * Provides a Model Context Protocol server implementation that exposes\n * Codex functionality as MCP tools and resources.\n */\nexport class McpServer {\n private config: Required<Omit<McpServerConfig, 'cache' | 'storage'>> & Pick<McpServerConfig, 'cache' | 'storage'>\n private toolContext: ToolHandlerContext\n\n constructor(config: McpServerConfig) {\n this.config = {\n name: config.name ?? 'codex',\n version: config.version ?? '1.0.0',\n cache: config.cache,\n storage: config.storage,\n }\n\n this.toolContext = {\n cache: config.cache,\n storage: config.storage,\n }\n }\n\n /**\n * Get server info\n */\n getServerInfo(): McpServerInfo {\n return {\n name: this.config.name,\n version: this.config.version,\n capabilities: this.getCapabilities(),\n }\n }\n\n /**\n * Get server capabilities\n */\n getCapabilities(): McpCapabilities {\n return {\n tools: {\n listChanged: false,\n },\n resources: {\n subscribe: false,\n listChanged: false,\n },\n }\n }\n\n /**\n * List available tools\n */\n listTools(): McpTool[] {\n return CODEX_TOOLS\n }\n\n /**\n * Call a tool\n */\n async callTool(name: string, args: Record<string, unknown>): Promise<ToolResult> {\n return handleToolCall(name, args, this.toolContext)\n }\n\n /**\n * List available resources\n */\n async listResources(): Promise<McpResource[]> {\n // List cached documents as resources\n const resources: McpResource[] = []\n\n // Get cache stats for info\n const stats = await this.config.cache.getStats()\n\n // Add a summary resource\n resources.push({\n uri: 'codex://cache/summary',\n name: 'Cache Summary',\n description: `${stats.entryCount} cached documents`,\n mimeType: 'text/plain',\n })\n\n return resources\n }\n\n /**\n * List resource templates\n */\n listResourceTemplates(): McpResourceTemplate[] {\n return [\n {\n uriTemplate: 'codex://{org}/{project}/{path}',\n name: 'Codex Document',\n description: 'Fetch a document from the Codex knowledge base',\n mimeType: 'text/markdown',\n },\n ]\n }\n\n /**\n * Read a resource\n */\n async readResource(uri: string): Promise<ResourceContent[]> {\n // Handle special URIs\n if (uri === 'codex://cache/summary') {\n const stats = await this.config.cache.getStats()\n return [\n {\n uri,\n mimeType: 'text/plain',\n text: `Cache Statistics:\n- Total entries: ${stats.entryCount}\n- Memory entries: ${stats.memoryEntries}\n- Fresh: ${stats.freshCount}\n- Stale: ${stats.staleCount}\n- Expired: ${stats.expiredCount}`,\n },\n ]\n }\n\n // Resolve and fetch the reference\n const ref = resolveReference(uri)\n if (!ref) {\n throw new Error(`Invalid codex URI: ${uri}`)\n }\n\n const result = await this.config.cache.get(ref)\n return [\n {\n uri,\n mimeType: result.contentType,\n text: result.content.toString('utf-8'),\n },\n ]\n }\n\n /**\n * Handle JSON-RPC request\n *\n * This method handles the low-level MCP protocol messages.\n */\n async handleRequest(method: string, params?: Record<string, unknown>): Promise<unknown> {\n switch (method) {\n case 'initialize':\n return {\n protocolVersion: '2024-11-05',\n serverInfo: this.getServerInfo(),\n capabilities: this.getCapabilities(),\n }\n\n case 'tools/list':\n return { tools: this.listTools() }\n\n case 'tools/call': {\n const { name, arguments: args } = params as { name: string; arguments: Record<string, unknown> }\n return await this.callTool(name, args)\n }\n\n case 'resources/list':\n return { resources: await this.listResources() }\n\n case 'resources/templates/list':\n return { resourceTemplates: this.listResourceTemplates() }\n\n case 'resources/read': {\n const { uri } = params as { uri: string }\n return { contents: await this.readResource(uri) }\n }\n\n case 'prompts/list':\n return { prompts: [] }\n\n default:\n throw new Error(`Unknown method: ${method}`)\n }\n }\n\n /**\n * Process a JSON-RPC message\n */\n async processMessage(message: string): Promise<string> {\n let id: unknown = null\n\n try {\n const request = JSON.parse(message)\n id = request.id\n const { method, params } = request\n\n const result = await this.handleRequest(method, params)\n\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n result,\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n return JSON.stringify({\n jsonrpc: '2.0',\n id,\n error: {\n code: -32603,\n message: errorMessage,\n },\n })\n }\n }\n}\n\n/**\n * Create an MCP server\n */\nexport function createMcpServer(config: McpServerConfig): McpServer {\n return new McpServer(config)\n}\n","/**\n * MCP Tool definitions and handlers\n *\n * Implements the tools exposed by the Codex MCP server.\n */\n\nimport type { CacheManager } from '@fractary/codex'\nimport type { StorageManager } from '@fractary/codex'\nimport { resolveReference } from '@fractary/codex'\nimport type {\n McpTool,\n ToolResult,\n FetchToolArgs,\n SearchToolArgs,\n ListToolArgs,\n CacheClearToolArgs,\n} from './types.js'\n\n/**\n * Tool definitions for the MCP server\n */\nexport const CODEX_TOOLS: McpTool[] = [\n {\n name: 'codex_document_fetch',\n description: 'Fetch a document from the Codex knowledge base by URI. Returns the document content.',\n inputSchema: {\n type: 'object',\n properties: {\n uri: {\n type: 'string',\n description: 'Codex URI in format: codex://org/project/path/to/file.md',\n },\n branch: {\n type: 'string',\n description: 'Git branch to fetch from (default: main)',\n },\n noCache: {\n type: 'boolean',\n description: 'Bypass cache and fetch fresh content',\n },\n },\n required: ['uri'],\n },\n },\n {\n name: 'codex_search',\n description: 'Search for documents in the Codex knowledge base.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query string',\n },\n org: {\n type: 'string',\n description: 'Filter by organization',\n },\n project: {\n type: 'string',\n description: 'Filter by project',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results (default: 10)',\n },\n type: {\n type: 'string',\n description: 'Filter by artifact type (e.g., docs, specs, logs)',\n },\n },\n required: ['query'],\n },\n },\n {\n name: 'codex_cache_list',\n description: 'List documents in the Codex cache.',\n inputSchema: {\n type: 'object',\n properties: {\n org: {\n type: 'string',\n description: 'Filter by organization',\n },\n project: {\n type: 'string',\n description: 'Filter by project',\n },\n includeExpired: {\n type: 'boolean',\n description: 'Include expired cache entries',\n },\n },\n },\n },\n {\n name: 'codex_cache_clear',\n description: 'Clear cached documents matching a pattern.',\n inputSchema: {\n type: 'object',\n properties: {\n pattern: {\n type: 'string',\n description: 'URI pattern to invalidate (supports regex)',\n },\n },\n required: ['pattern'],\n },\n },\n]\n\n/**\n * Tool handler context\n */\nexport interface ToolHandlerContext {\n cache: CacheManager\n storage: StorageManager\n}\n\n/**\n * Create a text result\n */\nfunction textResult(text: string, isError = false): ToolResult {\n return {\n content: [{ type: 'text', text }],\n isError,\n }\n}\n\n/**\n * Create a resource result\n */\nfunction resourceResult(uri: string, content: string, mimeType?: string): ToolResult {\n return {\n content: [\n {\n type: 'resource',\n resource: {\n uri,\n mimeType,\n text: content,\n },\n },\n ],\n }\n}\n\n/**\n * Handle codex_document_fetch tool\n */\nexport async function handleFetch(args: FetchToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { uri, branch, noCache } = args\n\n // Validate input\n if (!uri || typeof uri !== 'string') {\n return textResult('URI is required and must be a string', true)\n }\n\n if (branch && typeof branch !== 'string') {\n return textResult('Branch must be a string', true)\n }\n\n // Resolve the reference\n const ref = resolveReference(uri)\n if (!ref) {\n return textResult(`Invalid codex URI: ${uri}`, true)\n }\n\n try {\n let result\n\n if (noCache) {\n // Bypass cache, fetch directly\n result = await ctx.storage.fetch(ref, { branch })\n // Still cache the result for next time\n await ctx.cache.set(uri, result)\n } else {\n // Use cache\n result = await ctx.cache.get(ref, { branch })\n }\n\n const content = result.content.toString('utf-8')\n return resourceResult(uri, content, result.contentType)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return textResult(`Failed to fetch ${uri}: ${message}`, true)\n }\n}\n\n/**\n * Handle codex_search tool\n *\n * Note: This is a basic implementation that searches cached entries.\n * A more sophisticated implementation might use a search index.\n */\nexport async function handleSearch(args: SearchToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { query, org, project, limit = 10 } = args\n\n // Validate input\n if (!query || typeof query !== 'string') {\n return textResult('Query is required and must be a string', true)\n }\n\n if (query.length > 500) {\n return textResult('Query too long (max 500 characters)', true)\n }\n\n if (typeof limit !== 'number' || limit < 1 || limit > 100) {\n return textResult('Limit must be a number between 1 and 100', true)\n }\n\n // Get all cached entries\n const stats = await ctx.cache.getStats()\n if (stats.entryCount === 0) {\n return textResult('No documents in cache. Use codex_document_fetch to load documents first.')\n }\n\n // This is a simplified search - in a real implementation,\n // we would use a proper search index\n // For now, we search through the cached URIs and content\n\n // Note: This is a placeholder. The actual search implementation\n // would depend on having access to the cache persistence layer's\n // list of URIs and their content.\n\n const message = `Search functionality requires a search index.\nQuery: \"${query}\"\nFilters: org=${org || 'any'}, project=${project || 'any'}\nLimit: ${limit}\n\nTo fetch documents, use codex_document_fetch with a specific URI like:\ncodex://org/project/docs/file.md`\n\n return textResult(message)\n}\n\n/**\n * Handle codex_cache_list tool\n */\nexport async function handleList(args: ListToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { org, project, includeExpired } = args\n\n // Get cache stats and any available info\n const stats = await ctx.cache.getStats()\n\n let message = `Cache Statistics:\n- Total entries: ${stats.entryCount}\n- Memory entries: ${stats.memoryEntries}\n- Memory size: ${formatBytes(stats.memorySize)}\n- Total size: ${formatBytes(stats.totalSize)}\n- Fresh: ${stats.freshCount}\n- Stale: ${stats.staleCount}\n- Expired: ${stats.expiredCount}`\n\n if (org) {\n message += `\\n\\nFiltered by org: ${org}`\n }\n if (project) {\n message += `\\nFiltered by project: ${project}`\n }\n if (includeExpired) {\n message += `\\nIncluding expired entries`\n }\n\n return textResult(message)\n}\n\n/**\n * Validate and sanitize regex pattern to prevent ReDoS attacks\n */\nfunction validateRegexPattern(pattern: string): { valid: boolean; error?: string } {\n // Check pattern length (prevent extremely long patterns)\n if (pattern.length > 1000) {\n return { valid: false, error: 'Pattern too long (max 1000 characters)' }\n }\n\n // Check for common ReDoS patterns\n const redosPatterns = [\n /(\\.\\*){3,}/, // Multiple consecutive .*\n /(\\+\\+|\\*\\*|\\?\\?)/, // Nested quantifiers\n /(\\([^)]*){10,}/, // Too many groups\n /(\\[[^\\]]{100,})/, // Very long character classes\n ]\n\n for (const redos of redosPatterns) {\n if (redos.test(pattern)) {\n return { valid: false, error: 'Pattern contains potentially dangerous constructs' }\n }\n }\n\n // Try to compile the regex to check for syntax errors\n try {\n new RegExp(pattern)\n return { valid: true }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Invalid regex'\n return { valid: false, error: message }\n }\n}\n\n/**\n * Handle codex_cache_clear tool\n */\nexport async function handleCacheClear(args: CacheClearToolArgs, ctx: ToolHandlerContext): Promise<ToolResult> {\n const { pattern } = args\n\n if (!pattern || typeof pattern !== 'string') {\n return textResult('Pattern is required and must be a string', true)\n }\n\n // Validate pattern to prevent ReDoS\n const validation = validateRegexPattern(pattern)\n if (!validation.valid) {\n return textResult(`Invalid pattern: ${validation.error}`, true)\n }\n\n try {\n const regex = new RegExp(pattern)\n const count = await ctx.cache.invalidatePattern(regex)\n\n return textResult(`Cleared ${count} cache entries matching pattern: ${pattern}`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return textResult(`Failed to clear cache: ${message}`, true)\n }\n}\n\n/**\n * Route a tool call to its handler\n */\nexport async function handleToolCall(\n name: string,\n args: Record<string, unknown>,\n ctx: ToolHandlerContext\n): Promise<ToolResult> {\n switch (name) {\n case 'codex_document_fetch':\n return handleFetch(args as unknown as FetchToolArgs, ctx)\n case 'codex_search':\n return handleSearch(args as unknown as SearchToolArgs, ctx)\n case 'codex_cache_list':\n return handleList(args as unknown as ListToolArgs, ctx)\n case 'codex_cache_clear':\n return handleCacheClear(args as unknown as CacheClearToolArgs, ctx)\n default:\n return textResult(`Unknown tool: ${name}`, true)\n }\n}\n\n/**\n * Format bytes to human readable string\n */\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`\n}\n"],"mappings":"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","names":["resolveReference","resolveReference"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fractary/codex-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "MCP server for Fractary Codex knowledge management",
5
5
  "keywords": [
6
6
  "codex",
@@ -50,7 +50,7 @@
50
50
  "prepublishOnly": "npm run build && npm run test"
51
51
  },
52
52
  "dependencies": {
53
- "@fractary/codex": "^0.2.0",
53
+ "@fractary/codex": "^0.3.0",
54
54
  "commander": "^11.1.0",
55
55
  "js-yaml": "^4.1.0"
56
56
  },