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
71 changes: 68 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ The CLI can be customized in several ways using command-line args or by creating
* [Usage](#usage)
* [Command Topics](#command-topics)
* [MCP Server for AI Assistants](#mcp-server-for-ai-assistants)
* [This installs both 'dvc' CLI and 'dvc-mcp' server](#this-installs-both-dvc-cli-and-dvc-mcp-server)
* [Access via: npx dvc-mcp](#access-via-npx-dvc-mcp)
* [Repo Configuration](#repo-configuration)
<!-- tocstop -->
# Setup
Expand Down Expand Up @@ -149,7 +151,27 @@ USAGE

The DevCycle CLI includes an MCP (Model Context Protocol) server that enables AI coding assistants like Cursor and Claude to manage feature flags directly. This allows you to create, update, and manage feature flags without leaving your coding environment.

## Quick Setup
## Installation

### Option 1: Global Installation (Recommended)
```bash
npm install -g @devcycle/cli
# This installs both 'dvc' CLI and 'dvc-mcp' server
```
Comment on lines +156 to +160
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we have a brew package that we also maintain?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure, I'll add a ticket for looking at that later.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


### Option 2: Project-Specific Installation
```bash
npm install --save-dev @devcycle/cli
# Access via: npx dvc-mcp
```

### Verify Installation
```bash
dvc-mcp --version # Should display the DevCycle CLI version
dvc --version # Verify CLI is also installed
```

## Configuration

### For Cursor
Add to `.cursor/mcp_settings.json`:
Expand All @@ -165,6 +187,10 @@ Add to `.cursor/mcp_settings.json`:

### For Claude Desktop
Add to your Claude configuration file:

**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
"mcpServers": {
Expand All @@ -175,9 +201,48 @@ Add to your Claude configuration file:
}
```

The MCP server uses the same authentication as the CLI. Simply run `dvc login sso` first, then your AI assistant can manage feature flags on your behalf.
### For Project-Specific Installation
If you installed locally, update the command path:
```json
{
"mcpServers": {
"devcycle": {
"command": "npx",
"args": ["dvc-mcp"]
}
}
}
```

## Authentication

The MCP server uses the same authentication as the CLI:

1. **Authenticate with DevCycle:**
```bash
dvc login sso
```

2. **Select your project:**
```bash
dvc projects select
```

3. **Verify setup:**
```bash
dvc status
```

Your AI assistant can now manage feature flags on your behalf.

## Troubleshooting

- **Command not found:** Ensure the CLI is installed globally or use `npx dvc-mcp`
- **Authentication errors:** Run `dvc login sso` to re-authenticate
- **No project selected:** Run `dvc projects select` to choose a project
- **Permission issues:** On Unix systems, you may need to restart your terminal after global installation

For detailed documentation, see [docs/mcp.md](docs/mcp.md).
For detailed documentation and advanced usage, see [docs/mcp.md](docs/mcp.md).

# Repo Configuration
The following commands can only be run from the root of a configured repository
Expand Down
6 changes: 6 additions & 0 deletions bin/mcp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env node

const path = require('path')

// Run the MCP server directly
require(path.resolve(__dirname, '..', 'dist', 'mcp', 'index.js'))
3 changes: 3 additions & 0 deletions bin/mcp.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@echo off

node "%~dp0\mcp" %*
2 changes: 1 addition & 1 deletion oclif.manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "5.21.0",
"version": "5.21.1",
"commands": {
"authCommand": {
"id": "authCommand",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"author": "support@devcycle.com",
"bin": {
"dvc": "./bin/run",
"dvc-mcp": "./dist/mcp/index.js"
"dvc-mcp": "./bin/mcp"
},
"homepage": "https://github.com/DevCycleHQ/cli",
"license": "MIT",
Expand Down
6 changes: 3 additions & 3 deletions src/api/zodClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,12 +314,12 @@ const UpdateAudienceDto = z
})
.partial()
const VariableValidationEntity = z.object({
schemaType: z.object({}).partial(),
enumValues: z.object({}).partial().optional(),
schemaType: z.string(),
enumValues: z.array(z.string()).optional(),
regexPattern: z.string().optional(),
jsonSchema: z.string().optional(),
description: z.string(),
exampleValue: z.object({}).partial(),
exampleValue: z.any(),
})
const CreateVariableDto = z.object({
name: z.string().max(100).optional(),
Expand Down
91 changes: 89 additions & 2 deletions src/mcp/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,53 @@
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { DevCycleMCPServer } from './server'
import { readFileSync } from 'fs'
import { join } from 'path'

// Get version for MCP server
function getVersion(): string {
try {
const packagePath = join(__dirname, '..', '..', 'package.json')
const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'))
return packageJson.version
} catch (error) {
return 'unknown version'
}
}

// Handle command line arguments
const args = process.argv.slice(2)
if (args.includes('--version') || args.includes('-v')) {
console.log(getVersion())
process.exit(0)
}

if (args.includes('--help') || args.includes('-h')) {
console.log('DevCycle MCP Server')
console.log('')
console.log(
'A Model Context Protocol server for DevCycle feature flag management.',
)
console.log(
'Designed to be used with AI coding assistants like Cursor and Claude.',
)
console.log('')
console.log('Usage:')
console.log(' dvc-mcp Start the MCP server')
console.log(' dvc-mcp --version Show version information')
console.log(' dvc-mcp --help Show this help message')
console.log('')
console.log(
'For setup instructions, see: https://github.com/DevCycleHQ/cli#mcp-server-for-ai-assistants',
)
process.exit(0)
}

async function main() {
const server = new Server(
{
name: 'devcycle',
version: '0.0.1',
version: getVersion(),
},
{
capabilities: {
Expand All @@ -27,6 +68,52 @@ async function main() {
}

main().catch((error) => {
console.error('Failed to start DevCycle MCP server:', error)
console.error('❌ Failed to start DevCycle MCP server')
console.error('')

if (error instanceof Error) {
// Check for common error patterns and provide helpful guidance
if (
error.message.includes('authentication') ||
error.message.includes('DEVCYCLE_CLIENT_ID')
) {
console.error('πŸ” Authentication Error:')
console.error(` ${error.message}`)
console.error('')
console.error('πŸ’‘ To fix this:')
console.error(' 1. Run: dvc login sso')
console.error(' 2. Or set environment variables:')
console.error(' export DEVCYCLE_CLIENT_ID="your-client-id"')
console.error(
' export DEVCYCLE_CLIENT_SECRET="your-client-secret"',
)
} else if (
error.message.includes('project') ||
error.message.includes('DEVCYCLE_PROJECT_KEY')
) {
console.error('πŸ“ Project Configuration Error:')
console.error(` ${error.message}`)
console.error('')
console.error('πŸ’‘ To fix this:')
console.error(' 1. Run: dvc projects select')
console.error(' 2. Or set environment variable:')
console.error(
' export DEVCYCLE_PROJECT_KEY="your-project-key"',
)
} else {
console.error('⚠️ Unexpected Error:')
console.error(` ${error.message}`)
console.error('')
console.error('πŸ’‘ For help:')
console.error(' - Run: dvc status')
console.error(' - Check: https://docs.devcycle.com')
console.error(' - Contact: support@devcycle.com')
}
} else {
console.error('⚠️ Unknown error occurred')
console.error(` ${error}`)
}

console.error('')
process.exit(1)
})
Loading