@enfyra/mcp-server 0.0.81 → 0.0.83
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
|
@@ -12,7 +12,7 @@ From your project root:
|
|
|
12
12
|
npx @enfyra/mcp-server config
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
The config command can write project config for
|
|
15
|
+
The config command can write user-level Codex config plus project config for Claude Code and Cursor. It preserves other MCP servers and replaces only the `enfyra` entry.
|
|
16
16
|
|
|
17
17
|
Interactive setup asks for `ENFYRA_APP_URL` first, then asks for `ENFYRA_API_TOKEN`. The MCP API base is inferred as `<app>/api`, and the token page is inferred as `<app>/me`. For example, `https://demo.enfyra.io` becomes API base `https://demo.enfyra.io/api` and token page `https://demo.enfyra.io/me`.
|
|
18
18
|
|
|
@@ -37,7 +37,7 @@ yarn mcp:config
|
|
|
37
37
|
|
|
38
38
|
| Client | Command | Project config |
|
|
39
39
|
|--------|---------|----------------|
|
|
40
|
-
| Codex | `npx @enfyra/mcp-server config --codex` |
|
|
40
|
+
| Codex | `npx @enfyra/mcp-server config --codex` | `~/.codex/config.toml` |
|
|
41
41
|
| Claude Code | `npx @enfyra/mcp-server config --claude-code` | `.mcp.json` |
|
|
42
42
|
| Cursor | `npx @enfyra/mcp-server config --cursor` | `.cursor/mcp.json` |
|
|
43
43
|
| MCP Inspector / other hosts | Paste the shared STDIO config below | Host-specific `mcpServers` config |
|
|
@@ -49,7 +49,7 @@ yarn mcp:config
|
|
|
49
49
|
npx @enfyra/mcp-server config --codex
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
Generated
|
|
52
|
+
Generated user config:
|
|
53
53
|
|
|
54
54
|
```toml
|
|
55
55
|
[mcp_servers.enfyra]
|
|
@@ -61,9 +61,9 @@ ENFYRA_API_URL = "http://localhost:3000/api"
|
|
|
61
61
|
ENFYRA_API_TOKEN = "efy_pat_your-token"
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
The writer replaces only `[mcp_servers.enfyra]` and `[mcp_servers.enfyra.env]
|
|
64
|
+
The writer replaces only `[mcp_servers.enfyra]` and `[mcp_servers.enfyra.env]` in the user-level Codex config. Other Codex config and other MCP servers are preserved.
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
Restart Codex or start a new Codex session so user MCP config is loaded. The setup command does not create project `.codex/config.toml`, because project-scoped executable MCP config can trigger Codex workspace safety checks.
|
|
67
67
|
|
|
68
68
|
Official reference: [Codex config](https://developers.openai.com/codex/config-reference).
|
|
69
69
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enfyra/mcp-server",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.83",
|
|
4
4
|
"description": "MCP server for Enfyra - manage Enfyra instances from MCP-compatible coding tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
"enfyra-mcp-server": "src/index.mjs"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
|
-
"src"
|
|
14
|
-
".codex/skills"
|
|
13
|
+
"src"
|
|
15
14
|
],
|
|
16
15
|
"scripts": {
|
|
17
16
|
"start": "node src/index.mjs",
|
package/src/lib/config-local.mjs
CHANGED
|
@@ -23,7 +23,7 @@ const style = {
|
|
|
23
23
|
const clients = {
|
|
24
24
|
codex: {
|
|
25
25
|
label: 'Codex',
|
|
26
|
-
path: '
|
|
26
|
+
path: '~/.codex/config.toml',
|
|
27
27
|
color: style.green,
|
|
28
28
|
},
|
|
29
29
|
claude: {
|
|
@@ -61,7 +61,7 @@ ${style.bold('Usage')}
|
|
|
61
61
|
npx @enfyra/mcp-server config [options]
|
|
62
62
|
|
|
63
63
|
${style.bold('Supported clients')}
|
|
64
|
-
Codex
|
|
64
|
+
Codex ~/.codex/config.toml
|
|
65
65
|
Claude Code ./.mcp.json
|
|
66
66
|
Cursor ./.cursor/mcp.json
|
|
67
67
|
Other MCP hosts can use the shared stdio JSON from the README.
|
|
@@ -69,7 +69,7 @@ ${style.bold('Supported clients')}
|
|
|
69
69
|
${style.bold('Options')}
|
|
70
70
|
--app-url <url> Enfyra app/admin URL, for example https://demo.enfyra.io
|
|
71
71
|
--api-token, -t <secret> ENFYRA_API_TOKEN
|
|
72
|
-
--global Write
|
|
72
|
+
--global Write Claude Code/Cursor global config instead of project config; Codex is always user-level
|
|
73
73
|
--reconfig Always choose target again in interactive mode and replace the old enfyra config for that target
|
|
74
74
|
--yes Non-interactive: no prompts (CI / scripts); use CLI, env, existing file, then defaults
|
|
75
75
|
|
|
@@ -78,7 +78,7 @@ ${style.bold('Client selection')}
|
|
|
78
78
|
|
|
79
79
|
--claude-code, --claude, --claude-only Only ./.mcp.json (Claude Code project scope)
|
|
80
80
|
--cursor, --cursor-only Only ./.cursor/mcp.json (Cursor)
|
|
81
|
-
--codex, --codex-only Only
|
|
81
|
+
--codex, --codex-only Only ~/.codex/config.toml (Codex user scope)
|
|
82
82
|
Passing multiple target flags writes each selected target.
|
|
83
83
|
|
|
84
84
|
-h, --help Show this help
|
|
@@ -287,7 +287,7 @@ async function readCodexEnfyraEnv(absPath) {
|
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
function getCodexConfigPath(root, globalScope) {
|
|
290
|
-
return
|
|
290
|
+
return join(homedir(), '.codex', 'config.toml');
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
function getClaudeConfigPath(root, globalScope) {
|
|
@@ -361,7 +361,7 @@ async function promptTargetChoice() {
|
|
|
361
361
|
const rl = createInterface({ input, output });
|
|
362
362
|
const line = (await rl.question(
|
|
363
363
|
'Where should Enfyra MCP config be written?\n'
|
|
364
|
-
+ ' [1] Codex
|
|
364
|
+
+ ' [1] Codex ~/.codex/config.toml\n'
|
|
365
365
|
+ ' [2] Claude Code ./.mcp.json\n'
|
|
366
366
|
+ ' [3] Cursor ./.cursor/mcp.json\n'
|
|
367
367
|
+ ' [4] All [default]\n'
|
|
@@ -595,7 +595,14 @@ export async function runLocalConfig(argv) {
|
|
|
595
595
|
written.push({ client: 'cursor', path: p });
|
|
596
596
|
}
|
|
597
597
|
|
|
598
|
-
const
|
|
598
|
+
const hasProjectConfig = writeClaude || writeCursor;
|
|
599
|
+
const scopeLabel = opts.global
|
|
600
|
+
? 'global/user'
|
|
601
|
+
: writeCodex && hasProjectConfig
|
|
602
|
+
? 'project + Codex user'
|
|
603
|
+
: writeCodex
|
|
604
|
+
? 'Codex user'
|
|
605
|
+
: 'project';
|
|
599
606
|
console.log(`${statusIcon('success')} ${style.bold(style.green('Enfyra MCP config updated'))} ${style.dim(`(${scopeLabel})`)}\n`);
|
|
600
607
|
for (const entry of written) {
|
|
601
608
|
const meta = clients[entry.client];
|
|
@@ -606,7 +613,7 @@ export async function runLocalConfig(argv) {
|
|
|
606
613
|
const selectedClients = new Set(written.map(entry => entry.client));
|
|
607
614
|
console.log(`\n${style.bold(style.blue('Next steps'))}`);
|
|
608
615
|
if (selectedClients.has('codex')) {
|
|
609
|
-
console.log(' - Codex:
|
|
616
|
+
console.log(' - Codex: restart Codex or start a new Codex session so user MCP config is loaded.');
|
|
610
617
|
}
|
|
611
618
|
if (selectedClients.has('claude')) {
|
|
612
619
|
console.log(' - Claude Code: open this folder; approve project MCP if prompted.');
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# Enfyra MCP Performance And Debug Mode
|
|
2
|
-
|
|
3
|
-
Use this skill when designing, reviewing, or debugging Enfyra apps through MCP where performance, read/write shape, indexes, websocket latency, RLS filters, or query correctness matter.
|
|
4
|
-
|
|
5
|
-
## Rules
|
|
6
|
-
- Verify capability with live metadata before claiming performance behavior. Use `inspect_table`, `inspect_route`, `discover_query_capabilities`, and `discover_runtime_context` first.
|
|
7
|
-
- Prefer indexed relation filters over scalar mirror columns. Relation property names can be used in `indexes` and `uniques`; Enfyra resolves them to physical FK columns.
|
|
8
|
-
- For hot read paths, design indexes with the most selective/user-scoped field first. Examples: `["member","is_read","conversation"]` for unread lookup and `["conversation","member","is_read"]` for mark-read updates.
|
|
9
|
-
- Use existence checks for UI dots and badges unless the user explicitly needs exact counts. Avoid count queries on every conversation row.
|
|
10
|
-
- Use `meta=filterCount` or MCP `count_records` only when count is the product requirement.
|
|
11
|
-
- For RLS hooks, mutate `@QUERY.filter` and preserve existing user filters with `_and`. `@QUERY.filter` is already `{}` when omitted.
|
|
12
|
-
- For dynamic scripts, keep runtime values in their original type. Do not wrap ids or payload values in `String(...)`, `Number(...)`, or `Boolean(...)`.
|
|
13
|
-
- For websocket apps, connect browsers through the Enfyra app/Nuxt bridge, not the hidden backend. Event handlers should be script-owned and use `@SOCKET` explicitly.
|
|
14
|
-
- Authenticated websocket gateways load `user_definition` once and expose it as `@USER`; do not ask clients to send their own `senderId`.
|
|
15
|
-
- Enfyra automatically joins authenticated sockets to `user_<userId>` after the connection script succeeds. App scripts should use this for `emitToUser` and should not re-join that room manually.
|
|
16
|
-
|
|
17
|
-
## Debug Workflow
|
|
18
|
-
1. Inspect the table schema, relations, indexes, and route permissions before changing code.
|
|
19
|
-
2. Reproduce with the smallest real request or Socket.IO event. Prefer `test_rest_endpoint` or `run_admin_test` when available.
|
|
20
|
-
3. If the problem is performance, state the exact query shape and expected index. Add or update `indexes` on `table_definition` through `create_table` or `update_table`.
|
|
21
|
-
4. Reload metadata/cache after schema or script changes when the tool does not do it automatically.
|
|
22
|
-
5. Retest the exact route/event and compare behavior before/after. Do not invent benchmark numbers.
|
|
23
|
-
|
|
24
|
-
## Chat App Review Checklist
|
|
25
|
-
- Confirm REST and Socket.IO both go through the app origin. REST uses the app proxy prefix; Socket.IO uses `/ws/<namespace>` and `path: "/ws/socket.io"` when the app bridge exposes that path.
|
|
26
|
-
- Confirm browser code never stores or forwards custom JWT cookies when the Enfyra app/proxy already manages cookies.
|
|
27
|
-
- Confirm `chat:join` queries `chat_conversation` visible to `@USER`, then joins `conversation:<id>`. Do not join rooms from raw membership member ids.
|
|
28
|
-
- Confirm `chat:message` uses `@SOCKET.broadcastToRoom("conversation:" + conversationId, ...)` and persists with `@REPOS` inside the event script. Do not add a flow just to save chat messages.
|
|
29
|
-
- Confirm new DM UX creates no empty conversation. A draft opens first; the first message calls a creation event that creates the conversation and message together.
|
|
30
|
-
- Confirm route-level RLS is server-side: pre-hooks merge membership filters into `@QUERY.filter` with `_and`; the client must not fetch all conversations then filter locally.
|
|
31
|
-
- Confirm conversation titles are computed from visible memberships from the current user's perspective. DM title should be the other person, not the current user.
|
|
32
|
-
- Confirm message history uses cursor pagination, newest messages first from the API then reversed for display; loading older messages preserves scroll.
|
|
33
|
-
- Confirm disconnect state disables chat input and shows a visible retry banner immediately.
|
|
34
|
-
- Confirm typing state is room-scoped, user-aware, and remains active while the input has text, even if the user pauses typing.
|
|
35
|
-
|
|
36
|
-
## Chat Read/Unread Pattern
|
|
37
|
-
- Use a join table, e.g. `chat_message_read`, with:
|
|
38
|
-
- `message` relation to `chat_message`
|
|
39
|
-
- `conversation` relation to `chat_conversation`
|
|
40
|
-
- `member` relation to `user_definition`
|
|
41
|
-
- `is_read` boolean
|
|
42
|
-
- `read_at` date nullable
|
|
43
|
-
- Add unique `["message","member"]`.
|
|
44
|
-
- Add indexes `["member","is_read","conversation"]` and `["conversation","member","is_read"]`.
|
|
45
|
-
- On message create, create read rows for conversation members. Sender rows start as read; other member rows start unread.
|
|
46
|
-
- On conversation open/read, update unread rows for `@USER` in that conversation to read.
|
|
47
|
-
- UI unread dots should check whether an unread row exists; count only when requested.
|