Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
![Iterable MCP Server Setup](images/iterable-mcp-setup.png)


With the new Iterable MCP server, you can now connect Iterable to your favorite AI tools like Cursor, Claude Desktop, and Claude Code!
With the new Iterable MCP server, you can now connect Iterable to your favorite AI tools like Cursor, Claude Desktop, Claude Code, and Gemini CLI!

## What is MCP?

Expand Down Expand Up @@ -58,7 +58,7 @@ Throughout this guide, commands are shown as `iterable-mcp` for brevity. If not
```bash
git clone https://github.com/iterable/mcp-server.git
cd mcp-server
pnpm install-dev:cursor # or install-dev:claude-desktop or install-dev:claude-code
pnpm install-dev:cursor # or install-dev:claude-desktop, install-dev:claude-code, or install-dev:gemini-cli
```

### Claude Code
Expand Down Expand Up @@ -94,11 +94,14 @@ claude mcp add-from-claude-desktop

For more information, see the [Claude Code MCP documentation](https://docs.claude.com/en/docs/claude-code/mcp).

### Manual configuration (Cursor & Claude Desktop)
### Manual configuration (Cursor, Claude Desktop & Gemini CLI)

The above commands will automatically configure your AI tool to use the MCP server by editing the appropriate configuration file, but you can also manually edit the appropriate configuration file:
- **Claude Desktop:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Cursor:** `~/.cursor/mcp.json`
- **Gemini CLI:** `~/.gemini/settings.json`

All three use the same configuration format:

**Recommended: Using key manager:**
```bash
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
"install-dev:claude-code:debug": "pnpm install-dev && node dist/index.js setup --claude-code --debug --local",
"install-dev:cursor": "pnpm install-dev && node dist/index.js setup --cursor --local",
"install-dev:cursor:debug": "pnpm install-dev && node dist/index.js setup --cursor --debug --local",
"install-dev:gemini-cli": "pnpm install-dev && node dist/index.js setup --gemini-cli --local",
"install-dev:gemini-cli:debug": "pnpm install-dev && node dist/index.js setup --gemini-cli --debug --local",
"lint:fix": "eslint \"src/**/*.ts\" \"tests/**/*.ts\" --fix --quiet",
"prepublishOnly": "pnpm build",
"prestart": "pnpm build",
Expand Down
40 changes: 23 additions & 17 deletions src/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,6 @@ const { dirname, join } = path;
const LOCAL_BINARY_NAME = "iterable-mcp";
const NPX_PACKAGE_NAME = "@iterable/mcp";

// Tool display names
const TOOL_NAMES = {
cursor: "Cursor",
"claude-desktop": "Claude Desktop",
"claude-code": "Claude Code",
manual: "Manual Setup",
} as const;

// Get package version
const packageJson = JSON.parse(
readFileSync(
Expand All @@ -35,6 +27,17 @@ const packageJson = JSON.parse(
)
) as { version: string };

// Tool display names
type ToolName = keyof typeof TOOL_NAMES;
const TOOL_NAMES = {
cursor: "Cursor",
"claude-desktop": "Claude Desktop",
"claude-code": "Claude Code",
"gemini-cli": "Gemini CLI",
manual: "Manual Setup",
} as const;

type FileBasedToolName = keyof typeof TOOL_CONFIGS;
const TOOL_CONFIGS = {
"claude-desktop": (() => {
switch (process.platform) {
Expand All @@ -61,7 +64,8 @@ const TOOL_CONFIGS = {
}
})(),
cursor: path.join(os.homedir(), ".cursor", "mcp.json"),
} as const;
"gemini-cli": path.join(os.homedir(), ".gemini", "settings.json"),
} as const satisfies Record<string, string>;

const execFileAsync = promisify(execFile);

Expand Down Expand Up @@ -221,10 +225,11 @@ export const setupMcpServer = async (): Promise<void> => {
const showHelp = args.includes("--help") || args.includes("-h");
const advanced = args.includes("--advanced");
const autoUpdate = args.includes("--auto-update");
let tools = [
let tools: ToolName[] = [
...(args.includes("--claude-desktop") ? ["claude-desktop" as const] : []),
...(args.includes("--cursor") ? ["cursor" as const] : []),
...(args.includes("--claude-code") ? ["claude-code" as const] : []),
...(args.includes("--gemini-cli") ? ["gemini-cli" as const] : []),
...(args.includes("--manual") ? ["manual" as const] : []),
];

Expand Down Expand Up @@ -254,6 +259,7 @@ export const setupMcpServer = async (): Promise<void> => {
[`${commandName} setup --claude-desktop`, "Configure for Claude Desktop"],
[`${commandName} setup --cursor`, "Configure for Cursor"],
[`${commandName} setup --claude-code`, "Configure for Claude Code"],
[`${commandName} setup --gemini-cli`, "Configure for Gemini CLI"],
[`${commandName} setup --manual`, "Show manual config instructions"],
[
`${commandName} setup --cursor --claude-desktop`,
Expand Down Expand Up @@ -359,9 +365,7 @@ export const setupMcpServer = async (): Promise<void> => {
showIterableLogo(packageJson.version);

const { selectedTools } = await inquirer.prompt<{
selectedTools: Array<
"cursor" | "claude-desktop" | "claude-code" | "manual"
>;
selectedTools: ToolName[];
}>([
{
type: "checkbox",
Expand All @@ -371,6 +375,7 @@ export const setupMcpServer = async (): Promise<void> => {
{ name: "Cursor", value: "cursor" },
{ name: "Claude Desktop", value: "claude-desktop" },
{ name: "Claude Code (CLI)", value: "claude-code" },
{ name: "Gemini CLI", value: "gemini-cli" },
{ name: "Other / Manual Setup", value: "manual" },
],
validate: (arr: any) =>
Expand Down Expand Up @@ -898,17 +903,16 @@ export const setupMcpServer = async (): Promise<void> => {
}

const fileBasedTools = tools.filter(
(tool) => tool === "claude-desktop" || tool === "cursor"
) as Array<"claude-desktop" | "cursor">;
(tool): tool is FileBasedToolName => tool in TOOL_CONFIGS
);
const needsClaudeCode = tools.includes("claude-code");
const needsManual = tools.includes("manual");

if (fileBasedTools.length > 0) {
const { updateToolConfig } = await import("./utils/tool-config.js");
for (const tool of fileBasedTools) {
const configPath = TOOL_CONFIGS[tool];
const toolName =
tool === "claude-desktop" ? "Claude Desktop" : "Cursor";
const toolName = TOOL_NAMES[tool];
spinner.start(`Configuring ${toolName}...`);
try {
await updateToolConfig(configPath, iterableMcpConfig);
Expand Down Expand Up @@ -1004,6 +1008,8 @@ export const setupMcpServer = async (): Promise<void> => {
if (fileBasedTools.includes("cursor")) configuredTools.push("Cursor");
if (fileBasedTools.includes("claude-desktop"))
configuredTools.push("Claude Desktop");
if (fileBasedTools.includes("gemini-cli"))
configuredTools.push("Gemini CLI");
if (needsClaudeCode) configuredTools.push("Claude Code");
if (needsManual) configuredTools.push("your AI tool");

Expand Down