Skip to content

Commit 42fcc35

Browse files
committed
Add me claude install for MCP-only Claude Code setup
Adds an MCP-only install path for Claude Code, matching the existing `me opencode/codex/gemini install` pattern. The full Claude Code plugin flow (hooks + slash commands + MCP via plugin marketplace) is unchanged. Also exposes `-s, --scope` on `me claude install` (local|user|project, default user) and `me gemini install` (user|project, default user) by plumbing scope through the shared MCP install pipeline.
1 parent 46e377b commit 42fcc35

9 files changed

Lines changed: 331 additions & 40 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ me memory search "how does authentication work"
4040
me opencode install
4141
me codex install
4242
me gemini install
43+
me claude install # MCP-only
4344

44-
# Claude Code uses the Memory Engine plugin
45+
# Or, for the full Claude Code plugin (hooks + slash commands + MCP):
4546
claude plugin marketplace add timescale/memory-engine
4647
claude plugin install memory-engine@memory-engine
4748
```

docs/agents.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ mcp:
1414
opencode: me opencode install
1515
codex_cli: me codex install
1616
gemini_cli: me gemini install
17-
claude_code: claude plugin marketplace add timescale/memory-engine && claude plugin install memory-engine@memory-engine
18-
description: Memory engine ships as an MCP server. OpenCode, Codex CLI, and Gemini CLI use agent-specific install commands. Claude Code uses the Memory Engine plugin.
17+
claude_code: me claude install
18+
claude_code_plugin: claude plugin marketplace add timescale/memory-engine && claude plugin install memory-engine@memory-engine
19+
description: Memory engine ships as an MCP server. OpenCode, Codex CLI, Gemini CLI, and Claude Code all support MCP-only install via `me <agent> install`. Claude Code additionally supports a full plugin (hooks + slash commands + MCP) via Claude Code's plugin marketplace.
1920
compatible_clients:
2021
- Claude Code
2122
- Codex CLI

docs/cli/me-claude.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,40 @@ Claude Code integration commands.
44

55
## Commands
66

7+
- [me claude install](#me-claude-install) -- register `me` as an MCP server with Claude Code (MCP-only)
78
- [me claude hook](#me-claude-hook) -- invoked by the Claude Code plugin to capture events as memories
89
- [me claude import](#me-claude-import) -- import Claude Code sessions from `~/.claude/projects`
910

1011
---
1112

13+
## me claude install
14+
15+
Register `me` as an MCP server with Claude Code.
16+
17+
This is the **MCP-only** install path: it adds the `me` tools to Claude Code without installing the full Memory Engine plugin. If you want hooks (auto-capture of Claude Code events) and slash commands, install the plugin instead -- see [me claude hook](#me-claude-hook).
18+
19+
```
20+
me claude install [options]
21+
```
22+
23+
| Option | Description |
24+
|--------|-------------|
25+
| `--api-key <key>` | API key to embed in the MCP config. |
26+
| `--server <url>` | Server URL to embed in the MCP config. |
27+
| `-s, --scope <scope>` | Claude Code config scope: `local`, `user`, or `project`. Default: `user`. |
28+
29+
If no `--api-key` or `--server` is provided, values are resolved from `~/.config/me/credentials.yaml` (set by `me login` and `me engine use`).
30+
31+
The `--scope` flag mirrors `claude mcp add --scope`:
32+
33+
- `local` -- registration scoped to the current project on this machine only.
34+
- `user` -- registration available to all projects for your user (default).
35+
- `project` -- registration committed to the current project (e.g. checked into `.claude/`).
36+
37+
For manual MCP client configuration, see [MCP Integration](../mcp-integration.md).
38+
39+
---
40+
1241
## me claude hook
1342

1443
Invoked by the Claude Code plugin. Reads the event JSON from stdin, resolves config from `CLAUDE_PLUGIN_OPTION_*` env vars, and captures the event as a memory.
@@ -21,7 +50,7 @@ me claude hook --event <name>
2150
|--------|-------------|
2251
| `--event <name>` | Hook event name (required). |
2352

24-
This command is not run directly -- the Claude Code plugin calls it. The plugin is installed via Claude Code's native flow:
53+
This command is not run directly -- the Claude Code plugin calls it. The plugin (which includes hooks, slash commands, and MCP) is installed via Claude Code's native flow:
2554

2655
```bash
2756
claude plugin marketplace add timescale/memory-engine
@@ -30,6 +59,8 @@ claude plugin install memory-engine@memory-engine [--scope user|project|local]
3059
/plugin # select memory-engine, Configure, fill api_key/server/tree_prefix
3160
```
3261

62+
If you only want the MCP tools (no hooks, no slash commands), use [me claude install](#me-claude-install) instead.
63+
3364
Best-effort: logs failures to stderr but always exits 0 so that a hook failure never blocks a Claude Code session.
3465

3566
---

docs/cli/me-gemini.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ me gemini install [options]
2020
|--------|-------------|
2121
| `--api-key <key>` | API key to embed in the MCP config. |
2222
| `--server <url>` | Server URL to embed in the MCP config. |
23+
| `-s, --scope <scope>` | Gemini CLI config scope: `user` or `project`. Default: `user`. |
2324

2425
If no `--api-key` or `--server` is provided, values are resolved from `~/.config/me/credentials.yaml` (set by `me login` and `me engine use`).
2526

packages/cli/commands/claude.ts

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
/**
22
* me claude — Claude Code integration commands.
33
*
4-
* Just one subcommand: `me claude hook --event <name>`. The plugin itself
5-
* is installed via Claude Code's native flow:
4+
* Two integration paths:
65
*
7-
* claude plugin marketplace add timescale/memory-engine
8-
* claude plugin install memory-engine@memory-engine [--scope user|project|local]
9-
* # then, in a Claude Code session:
10-
* /plugin # select memory-engine, Configure, fill api_key/server/tree_prefix
6+
* 1. Full plugin (hooks + slash commands + MCP) via Claude Code's native
7+
* plugin marketplace:
118
*
12-
* Claude Code delivers the configured values to our hook as
13-
* CLAUDE_PLUGIN_OPTION_* env vars.
9+
* claude plugin marketplace add timescale/memory-engine
10+
* claude plugin install memory-engine@memory-engine [--scope user|project|local]
11+
* # then, in a Claude Code session:
12+
* /plugin # select memory-engine, Configure, fill api_key/server/tree_prefix
13+
*
14+
* Claude Code delivers the configured values to our hook (`me claude
15+
* hook --event <name>`) via CLAUDE_PLUGIN_OPTION_* env vars.
16+
*
17+
* 2. MCP-only via `me claude install`. Registers `me` as an MCP server
18+
* with Claude Code (no hooks, no slash commands — just the tools).
1419
*/
15-
import { Command } from "commander";
20+
import { Command, InvalidArgumentError } from "commander";
1621
import {
1722
captureHookEvent,
1823
HOOK_EVENT_NAMES,
@@ -21,8 +26,57 @@ import {
2126
resolveHookConfigFromEnv,
2227
} from "../claude/capture.ts";
2328
import { claudeImporter } from "../importers/claude.ts";
29+
import {
30+
type AgentInstallOptions,
31+
runAgentMcpInstall,
32+
} from "../mcp/agent-install.ts";
2433
import { buildAgentImportSubcommand } from "./import.ts";
2534

35+
const CLAUDE_SCOPES = ["local", "user", "project"] as const;
36+
type ClaudeScope = (typeof CLAUDE_SCOPES)[number];
37+
38+
function parseClaudeScope(value: string): ClaudeScope {
39+
if (!CLAUDE_SCOPES.includes(value as ClaudeScope)) {
40+
throw new InvalidArgumentError(
41+
`must be one of: ${CLAUDE_SCOPES.join(", ")}`,
42+
);
43+
}
44+
return value as ClaudeScope;
45+
}
46+
47+
/**
48+
* me claude install — register me as an MCP server with Claude Code.
49+
*
50+
* MCP-only: leaves the full Claude Code plugin install flow alone. Use this
51+
* if you want the `me` MCP tools available in Claude Code but don't want the
52+
* plugin's hooks or slash commands.
53+
*/
54+
function createClaudeInstallCommand(): Command {
55+
return new Command("install")
56+
.description("register me as an MCP server with Claude Code")
57+
.option("--api-key <key>", "API key to embed in MCP config")
58+
.option("--server <url>", "server URL to embed in MCP config")
59+
.option(
60+
"-s, --scope <scope>",
61+
`Claude Code config scope (${CLAUDE_SCOPES.join(", ")})`,
62+
parseClaudeScope,
63+
"user",
64+
)
65+
.action(
66+
async (
67+
opts: AgentInstallOptions & { scope: ClaudeScope },
68+
cmd: Command,
69+
) => {
70+
const globalOpts = cmd.optsWithGlobals();
71+
await runAgentMcpInstall("claude", {
72+
apiKey: opts.apiKey,
73+
server: globalOpts.server ?? opts.server,
74+
scope: opts.scope,
75+
});
76+
},
77+
);
78+
}
79+
2680
/**
2781
* me claude hook — invoked by the Claude Code plugin to capture events as
2882
* memories.
@@ -101,6 +155,7 @@ function createClaudeHookCommand(): Command {
101155

102156
export function createClaudeCommand(): Command {
103157
const claude = new Command("claude").description("Claude Code integration");
158+
claude.addCommand(createClaudeInstallCommand());
104159
claude.addCommand(createClaudeHookCommand());
105160
claude.addCommand(
106161
buildAgentImportSubcommand(

packages/cli/commands/gemini.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,48 @@
33
*
44
* - me gemini install: register me as an MCP server with Gemini CLI
55
*/
6-
import { Command } from "commander";
6+
import { Command, InvalidArgumentError } from "commander";
77
import {
88
type AgentInstallOptions,
99
runAgentMcpInstall,
1010
} from "../mcp/agent-install.ts";
1111

12+
const GEMINI_SCOPES = ["user", "project"] as const;
13+
type GeminiScope = (typeof GEMINI_SCOPES)[number];
14+
15+
function parseGeminiScope(value: string): GeminiScope {
16+
if (!GEMINI_SCOPES.includes(value as GeminiScope)) {
17+
throw new InvalidArgumentError(
18+
`must be one of: ${GEMINI_SCOPES.join(", ")}`,
19+
);
20+
}
21+
return value as GeminiScope;
22+
}
23+
1224
function createGeminiInstallCommand(): Command {
1325
return new Command("install")
1426
.description("register me as an MCP server with Gemini CLI")
1527
.option("--api-key <key>", "API key to embed in MCP config")
1628
.option("--server <url>", "server URL to embed in MCP config")
17-
.action(async (opts: AgentInstallOptions, cmd: Command) => {
18-
const globalOpts = cmd.optsWithGlobals();
19-
await runAgentMcpInstall("gemini", {
20-
apiKey: opts.apiKey,
21-
server: globalOpts.server ?? opts.server,
22-
});
23-
});
29+
.option(
30+
"-s, --scope <scope>",
31+
`Gemini CLI config scope (${GEMINI_SCOPES.join(", ")})`,
32+
parseGeminiScope,
33+
"user",
34+
)
35+
.action(
36+
async (
37+
opts: AgentInstallOptions & { scope: GeminiScope },
38+
cmd: Command,
39+
) => {
40+
const globalOpts = cmd.optsWithGlobals();
41+
await runAgentMcpInstall("gemini", {
42+
apiKey: opts.apiKey,
43+
server: globalOpts.server ?? opts.server,
44+
scope: opts.scope,
45+
});
46+
},
47+
);
2448
}
2549

2650
export function createGeminiCommand(): Command {

packages/cli/mcp/agent-install.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import { buildMeCommand, installMcpServer, MCP_TOOLS } from "./install.ts";
1111
export interface AgentInstallOptions {
1212
apiKey?: string;
1313
server?: string;
14+
/**
15+
* Configuration scope for tools that support it (Claude Code, Gemini CLI).
16+
* Ignored by tools without a scope concept (Codex, OpenCode).
17+
*/
18+
scope?: string;
1419
}
1520

1621
/**
@@ -63,7 +68,7 @@ export async function runAgentMcpInstall(
6368

6469
const spin = clack.spinner();
6570
spin.start(`Registering with ${tool.name}...`);
66-
const result = await installMcpServer(tool, meCmd);
71+
const result = await installMcpServer(tool, meCmd, { scope: opts.scope });
6772

6873
if (result.success) {
6974
spin.stop(result.message);

0 commit comments

Comments
 (0)