@fractary/codex-mcp 0.10.3 → 0.10.4

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
@@ -4,33 +4,23 @@ MCP (Model Context Protocol) server for Fractary Codex knowledge management.
4
4
 
5
5
  ## Overview
6
6
 
7
- This package provides a standalone MCP server that exposes Fractary Codex functionality as tools for AI agents and applications. It supports both stdio and HTTP/SSE transports for integration with Claude Code, LangChain, and other MCP-compatible clients.
7
+ This package provides a standalone MCP server that exposes Fractary Codex functionality as tools for AI agents. Supports both stdio and HTTP/SSE transports.
8
8
 
9
9
  ## Installation
10
10
 
11
- ### Global Installation
12
-
13
11
  ```bash
12
+ # Global
14
13
  npm install -g @fractary/codex-mcp-server
15
- ```
16
14
 
17
- ### Direct Usage (npx)
18
-
19
- ```bash
15
+ # Direct usage
20
16
  npx @fractary/codex-mcp-server
21
17
  ```
22
18
 
23
- ### As Dependency
24
-
25
- ```bash
26
- npm install @fractary/codex-mcp-server
27
- ```
28
-
29
- ## Usage
19
+ ## Quick Start
30
20
 
31
21
  ### Claude Code Integration
32
22
 
33
- Add to your `.claude/settings.json`:
23
+ Add to `.claude/settings.json`:
34
24
 
35
25
  ```json
36
26
  {
@@ -43,298 +33,78 @@ Add to your `.claude/settings.json`:
43
33
  }
44
34
  ```
45
35
 
46
- ### Stdio Mode (Default)
36
+ ### Stdio Mode
47
37
 
48
38
  ```bash
49
39
  fractary-codex-mcp --config .fractary/config.yaml
50
40
  ```
51
41
 
52
- The server communicates via stdin/stdout using the MCP protocol.
53
-
54
42
  ### HTTP Mode
55
43
 
56
44
  ```bash
57
45
  fractary-codex-mcp --port 3000 --host localhost
58
46
  ```
59
47
 
60
- The server exposes an SSE (Server-Sent Events) endpoint for HTTP clients.
48
+ ## Available Tools
49
+
50
+ | Tool | Description |
51
+ |------|-------------|
52
+ | `codex_document_fetch` | Fetch document by URI |
53
+ | `codex_search` | Search documents |
54
+ | `codex_cache_list` | List cached documents |
55
+ | `codex_cache_clear` | Clear cache by pattern |
56
+
57
+ ## Documentation
58
+
59
+ **Full documentation**: [docs/mcp-server/](../../docs/mcp-server/)
60
+
61
+ - [Configuration](../../docs/mcp-server/#configuration)
62
+ - [Archive Configuration](../../docs/mcp-server/#archive-configuration)
63
+ - [Tools Reference](../../docs/mcp-server/#available-tools)
64
+ - [Programmatic Usage](../../docs/mcp-server/#programmatic-usage)
65
+ - [Troubleshooting](../../docs/mcp-server/#troubleshooting)
61
66
 
62
67
  ## Configuration
63
68
 
64
- Create a `.fractary/config.yaml` configuration file:
69
+ Uses `.fractary/config.yaml`:
65
70
 
66
71
  ```yaml
67
- # Organization configuration
68
72
  organizationSlug: fractary
69
73
 
70
- # Cache configuration
71
74
  cache:
72
75
  dir: .fractary/codex/cache
73
- maxMemorySize: 104857600 # 100 MB
74
- defaultTtl: 3600 # 1 hour
76
+ defaultTtl: 3600
75
77
 
76
- # Storage providers
77
78
  storage:
78
79
  providers:
79
80
  - type: local
80
81
  basePath: ./knowledge
81
82
  - type: github
82
83
  token: ${GITHUB_TOKEN}
83
-
84
- # Archive configuration (optional)
85
- # Enables transparent access to archived documents in S3/R2/GCS
86
- archive:
87
- projects:
88
- fractary/auth-service:
89
- enabled: true
90
- handler: s3 # s3, r2, gcs, or local
91
- bucket: fractary-archives
92
- patterns: # Optional: limit to specific patterns
93
- - specs/**
94
- - docs/**
95
- fractary/api-gateway:
96
- enabled: true
97
- handler: r2
98
- bucket: api-archives
99
- ```
100
-
101
- ### Archive Configuration
102
-
103
- The archive feature enables transparent access to archived documents stored in cloud storage (S3, R2, GCS). When enabled, Codex automatically falls back to the archive when documents are not found locally or in GitHub.
104
-
105
- **Key Features:**
106
- - **Transparent URIs**: Same `codex://org/project/path` URI works for both active and archived documents
107
- - **Storage Priority**: Local → Archive → GitHub → HTTP (automatic fallback)
108
- - **Per-Project Config**: Different projects can use different storage backends and buckets
109
- - **Pattern Matching**: Optional patterns limit which files are archived
110
-
111
- **Configuration Fields:**
112
- - `enabled`: Boolean - Whether archive is active for this project
113
- - `handler`: String - Storage backend: `s3`, `r2`, `gcs`, or `local`
114
- - `bucket`: String (optional) - Cloud storage bucket name
115
- - `prefix`: String (optional) - Path prefix in bucket (default: `archive/`)
116
- - `patterns`: Array (optional) - Glob patterns to match (e.g., `specs/**`, `*.md`)
117
-
118
- **Archive Path Structure:**
119
- ```
120
- archive/{type}/{org}/{project}/{original-path}
121
-
122
- Examples:
123
- specs/WORK-123.md → archive/specs/fractary/auth-service/specs/WORK-123.md
124
- docs/api.md → archive/docs/fractary/auth-service/docs/api.md
125
- ```
126
-
127
- **Example Usage:**
128
- ```typescript
129
- // Reference archived spec (same URI as before archiving)
130
- const result = await fetch('codex://fractary/auth-service/specs/WORK-123.md')
131
- // Codex checks: local → S3 archive → GitHub → HTTP
132
- // Returns content from archive if not found locally
133
- ```
134
-
135
- **Requirements:**
136
- - [fractary CLI](https://github.com/fractary/cli) installed and configured
137
- - Cloud storage credentials (AWS credentials for S3, Cloudflare for R2, etc.)
138
- - Archive structure must mirror project structure
139
-
140
- ### Environment Variables
141
-
142
- - `FRACTARY_CONFIG`: Path to configuration file (default: `.fractary/config.yaml`)
143
- - `GITHUB_TOKEN`: GitHub personal access token for GitHub storage provider
144
- - `FRACTARY_CLI`: Path to fractary CLI executable (default: `fractary`)
145
- - `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`: AWS credentials for S3
146
- - `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_API_TOKEN`: Cloudflare credentials for R2
147
-
148
- ## Available Tools
149
-
150
- The MCP server exposes the following tools:
151
-
152
- ### codex_document_fetch
153
-
154
- Fetch a document from the Codex knowledge base by URI.
155
-
156
- ```json
157
- {
158
- "uri": "codex://org/project/path/to/file.md",
159
- "branch": "main",
160
- "noCache": false
161
- }
162
- ```
163
-
164
- ### codex_search
165
-
166
- Search for documents in the knowledge base.
167
-
168
- ```json
169
- {
170
- "query": "authentication",
171
- "org": "fractary",
172
- "project": "codex",
173
- "limit": 10,
174
- "type": "docs"
175
- }
176
- ```
177
-
178
- ### codex_cache_list
179
-
180
- List cached documents.
181
-
182
- ```json
183
- {
184
- "org": "fractary",
185
- "project": "codex",
186
- "includeExpired": false
187
- }
188
- ```
189
-
190
- ### codex_cache_clear
191
-
192
- Clear cached documents by pattern.
193
-
194
- ```json
195
- {
196
- "pattern": "docs/**"
197
- }
198
- ```
199
-
200
- ## Architecture
201
-
202
- The MCP server bridges the Codex SDK with the MCP protocol:
203
-
204
- ```
205
- ┌─────────────────────────────────────┐
206
- │ MCP Client (Claude Code, etc.) │
207
- └─────────────┬───────────────────────┘
208
- │ JSON-RPC (stdio/HTTP)
209
-
210
- ┌─────────────────────────────────────┐
211
- │ @fractary/codex-mcp-server │
212
- │ ┌───────────────────────────────┐ │
213
- │ │ MCP Protocol Handler │ │
214
- │ │ (StdioTransport / SSE) │ │
215
- │ └─────────────┬─────────────────┘ │
216
- │ │ │
217
- │ ┌─────────────▼─────────────────┐ │
218
- │ │ Tool Registration Bridge │ │
219
- │ │ (registerCodexTools) │ │
220
- │ └─────────────┬─────────────────┘ │
221
- └────────────────┼─────────────────────┘
222
-
223
-
224
- ┌─────────────────────────────────────┐
225
- │ @fractary/codex (SDK) │
226
- │ ┌─────────┐ ┌──────────────┐ │
227
- │ │ Cache │ │ Storage │ │
228
- │ │ Manager │ │ Manager │ │
229
- │ └─────────┘ └──────────────┘ │
230
- └─────────────────────────────────────┘
231
84
  ```
232
85
 
233
86
  ## Development
234
87
 
235
- ### Build
236
-
237
88
  ```bash
89
+ # Build
238
90
  npm run build
239
- ```
240
-
241
- ### Watch Mode
242
91
 
243
- ```bash
92
+ # Watch mode
244
93
  npm run dev
245
- ```
246
94
 
247
- ### Type Check
248
-
249
- ```bash
250
- npm run typecheck
251
- ```
252
-
253
- ### Testing
254
-
255
- ```bash
95
+ # Test
256
96
  npm test
257
- npm run test:watch
258
- npm run test:coverage
259
- ```
260
-
261
- ### Linting
262
-
263
- ```bash
264
- npm run lint
265
- npm run format
266
- ```
267
-
268
- ## Programmatic Usage
269
-
270
- You can also use the MCP server programmatically:
271
-
272
- ```typescript
273
- import { Server } from '@modelcontextprotocol/sdk/server/index.js'
274
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
275
- import { CacheManager, StorageManager } from '@fractary/codex'
276
- import { registerCodexTools } from '@fractary/codex-mcp-server'
277
-
278
- // Initialize SDK managers
279
- const storage = StorageManager.create({ /* config */ })
280
- const cache = CacheManager.create({ /* config */ })
281
- cache.setStorageManager(storage)
282
-
283
- // Create MCP server
284
- const server = new Server(
285
- { name: 'fractary-codex', version: '0.1.0' },
286
- { capabilities: { tools: {}, resources: {} } }
287
- )
288
97
 
289
- // Register Codex tools
290
- registerCodexTools(server, { cache, storage })
291
-
292
- // Connect transport
293
- const transport = new StdioServerTransport()
294
- await server.connect(transport)
295
- ```
296
-
297
- ## Migration from SDK-Embedded MCP
298
-
299
- If you were using the MCP server from `@fractary/codex` (versions ≤0.1.x), update your configuration:
300
-
301
- **Before:**
302
- ```json
303
- {
304
- "mcpServers": {
305
- "fractary-codex": {
306
- "command": "npx",
307
- "args": ["@fractary/codex", "mcp", "--config", ".fractary/config.yaml"]
308
- }
309
- }
310
- }
311
- ```
312
-
313
- **After:**
314
- ```json
315
- {
316
- "mcpServers": {
317
- "fractary-codex": {
318
- "command": "npx",
319
- "args": ["-y", "@fractary/codex-mcp-server", "--config", ".fractary/config.yaml"]
320
- }
321
- }
322
- }
98
+ # Type check
99
+ npm run typecheck
323
100
  ```
324
101
 
325
- The functionality remains identical; only the package name has changed.
326
-
327
102
  ## License
328
103
 
329
104
  MIT
330
105
 
331
- ## Related Packages
106
+ ## Related
332
107
 
333
108
  - [@fractary/codex](https://www.npmjs.com/package/@fractary/codex) - Core SDK
334
109
  - [@fractary/codex-cli](https://www.npmjs.com/package/@fractary/codex-cli) - CLI tool
335
-
336
- ## Links
337
-
338
- - [GitHub Repository](https://github.com/fractary/codex)
339
- - [Issue Tracker](https://github.com/fractary/codex/issues)
340
110
  - [MCP Specification](https://modelcontextprotocol.io)
package/dist/cli.cjs CHANGED
@@ -12702,12 +12702,24 @@ var DirectionalSyncConfigSchema = external_exports.object({
12702
12702
  /** Patterns to exclude (optional) */
12703
12703
  exclude: external_exports.array(external_exports.string()).optional()
12704
12704
  });
12705
+ var FromCodexSyncConfigSchema = DirectionalSyncConfigSchema.refine(
12706
+ (config) => {
12707
+ const includeValid = config.include.every(
12708
+ (pattern) => pattern.startsWith("codex://")
12709
+ );
12710
+ const excludeValid = !config.exclude || config.exclude.every((pattern) => pattern.startsWith("codex://"));
12711
+ return includeValid && excludeValid;
12712
+ },
12713
+ {
12714
+ message: 'from_codex patterns must use codex:// URI format (e.g., "codex://{org}/{codex_repo}/docs/**"). Plain paths like "docs/**" are not valid for from_codex.'
12715
+ }
12716
+ );
12705
12717
  var DirectionalSyncSchema = external_exports.object({
12706
12718
  // New format (v0.7.0+) - Recommended
12707
- // Patterns for files to push from this project to codex
12719
+ // Patterns for files to push from this project to codex (plain paths)
12708
12720
  to_codex: DirectionalSyncConfigSchema.optional(),
12709
- // Patterns for files to pull from codex to this project
12710
- from_codex: DirectionalSyncConfigSchema.optional(),
12721
+ // Patterns for files to pull from codex to this project (codex:// URIs required)
12722
+ from_codex: FromCodexSyncConfigSchema.optional(),
12711
12723
  // Global exclude patterns (applied to both directions)
12712
12724
  exclude: external_exports.array(external_exports.string()).optional(),
12713
12725
  // Legacy format (deprecated, backward compatible)
@@ -12735,25 +12747,9 @@ var AuthConfigSchema = external_exports.object({
12735
12747
  /** GitHub authentication configuration */
12736
12748
  github: GitHubAuthConfigSchema.optional()
12737
12749
  });
12738
- var SourceConfigSchema = external_exports.object({
12739
- /** Source type */
12740
- type: external_exports.enum(["github", "s3", "http", "local"]),
12741
- /** Environment variable containing the authentication token */
12742
- token_env: external_exports.string().optional(),
12743
- /** Direct token value (not recommended, use token_env instead) */
12744
- token: external_exports.string().optional(),
12745
- /** Branch to fetch from (for GitHub sources) */
12746
- branch: external_exports.string().optional(),
12747
- /** Base URL (for HTTP sources) */
12748
- base_url: external_exports.string().optional(),
12749
- /** Bucket name (for S3 sources) */
12750
- bucket: external_exports.string().optional(),
12751
- /** Prefix/path within bucket (for S3 sources) */
12752
- prefix: external_exports.string().optional()
12753
- });
12754
- var DependencyConfigSchema = external_exports.object({
12755
- /** Sources within this dependency */
12756
- sources: external_exports.record(SourceConfigSchema)
12750
+ var RemoteConfigSchema = external_exports.object({
12751
+ /** Authentication token - can be direct value or ${ENV_VAR} reference */
12752
+ token: external_exports.string().optional()
12757
12753
  });
12758
12754
  var CodexConfigSchema = external_exports.object({
12759
12755
  organizationSlug: external_exports.string(),
@@ -12771,8 +12767,9 @@ var CodexConfigSchema = external_exports.object({
12771
12767
  archive: ArchiveConfigSchema.optional(),
12772
12768
  // Authentication configuration
12773
12769
  auth: AuthConfigSchema.optional(),
12774
- // Dependencies configuration (external projects)
12775
- dependencies: external_exports.record(DependencyConfigSchema).optional()
12770
+ // Remote repositories configuration (external projects)
12771
+ // Keys are org/project identifiers, values configure authentication
12772
+ remotes: external_exports.record(RemoteConfigSchema).optional()
12776
12773
  }).strict();
12777
12774
  var FileSourceSchema = external_exports.object({
12778
12775
  type: external_exports.enum(["s3", "r2", "gcs", "local"]),
@@ -13780,30 +13777,31 @@ var StorageManager = class {
13780
13777
  }
13781
13778
  this.priority = config.priority || (config.filePlugin && config.s3Archive ? ["file-plugin", "local", "s3-archive", "github", "http"] : config.filePlugin ? ["file-plugin", "local", "github", "http"] : config.s3Archive ? ["local", "s3-archive", "github", "http"] : ["local", "github", "http"]);
13782
13779
  }
13780
+ /**
13781
+ * Resolve a token value, expanding ${VAR} references to environment variables
13782
+ */
13783
+ resolveTokenValue(token) {
13784
+ const envVarMatch = token.match(/^\$\{([^}]+)\}$/);
13785
+ if (envVarMatch && envVarMatch[1]) {
13786
+ const envVarName = envVarMatch[1];
13787
+ return process.env[envVarName];
13788
+ }
13789
+ return token;
13790
+ }
13783
13791
  /**
13784
13792
  * Resolve authentication token for a reference
13785
13793
  *
13786
- * Looks up dependency-specific authentication or falls back to default
13794
+ * Looks up remote-specific authentication or falls back to default
13787
13795
  */
13788
13796
  resolveToken(reference) {
13789
13797
  if (!this.codexConfig) {
13790
13798
  return void 0;
13791
13799
  }
13792
- const dependencyKey = `${reference.org}/${reference.project}`;
13793
- if (this.codexConfig.dependencies?.[dependencyKey]) {
13794
- const dependency = this.codexConfig.dependencies[dependencyKey];
13795
- for (const [, sourceConfig] of Object.entries(dependency.sources)) {
13796
- if (sourceConfig.type === "github") {
13797
- if (sourceConfig.token_env) {
13798
- const token = process.env[sourceConfig.token_env];
13799
- if (token) {
13800
- return token;
13801
- }
13802
- }
13803
- if (sourceConfig.token) {
13804
- return sourceConfig.token;
13805
- }
13806
- }
13800
+ const remoteKey = `${reference.org}/${reference.project}`;
13801
+ if (this.codexConfig.remotes?.[remoteKey]?.token) {
13802
+ const token = this.resolveTokenValue(this.codexConfig.remotes[remoteKey].token);
13803
+ if (token) {
13804
+ return token;
13807
13805
  }
13808
13806
  }
13809
13807
  const defaultTokenEnv = this.codexConfig.auth?.github?.default_token_env || "GITHUB_TOKEN";
@@ -13862,7 +13860,7 @@ var StorageManager = class {
13862
13860
  * Fetch content for a reference
13863
13861
  *
13864
13862
  * Tries providers in priority order until one succeeds.
13865
- * Automatically resolves authentication based on dependency configuration.
13863
+ * Automatically resolves authentication based on remote configuration.
13866
13864
  */
13867
13865
  async fetch(reference, options) {
13868
13866
  const resolvedOptions = this.resolveFetchOptions(reference, options);
@@ -13894,7 +13892,7 @@ var StorageManager = class {
13894
13892
  * Check if content exists for a reference
13895
13893
  *
13896
13894
  * Returns true if any provider reports the content exists.
13897
- * Automatically resolves authentication based on dependency configuration.
13895
+ * Automatically resolves authentication based on remote configuration.
13898
13896
  */
13899
13897
  async exists(reference, options) {
13900
13898
  const resolvedOptions = this.resolveFetchOptions(reference, options);