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
6 changes: 6 additions & 0 deletions .codemie/guides/architecture/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ codemie-code/
│ ├── agents/ Agent system (registry + plugins)
│ ├── providers/ LLM provider system
│ ├── frameworks/ Framework integrations
│ ├── mcp/ MCP proxy bridge & OAuth
│ ├── utils/ Shared utilities
│ ├── env/ Environment management
│ ├── workflows/ CI/CD templates
Expand Down Expand Up @@ -48,6 +49,11 @@ src/
├── frameworks/ Framework System
│ ├── core/ Framework interfaces
│ └── plugins/ Framework implementations (LangGraph)
├── mcp/ MCP Proxy System
│ ├── auth/ OAuth provider & callback server
│ ├── stdio-http-bridge.ts Stdio-to-HTTP bridge
│ ├── proxy-logger.ts File-based proxy logger
│ └── constants.ts MCP proxy constants
└── utils/ Utilities Layer
├── errors.ts Error classes
├── logger.ts Logging utilities
Expand Down
64 changes: 64 additions & 0 deletions .codemie/guides/integration/external-integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ External service integration patterns for CodeMie Code: LangGraph orchestration,
| Azure OpenAI | GPT via Azure | API Key + Endpoint | Azure credentials |
| LiteLLM | 100+ providers proxy | Varies | Provider-specific |
| OpenCode | Open-source AI assistant | SSO/API Key | Via CodeMie proxy |
| MCP Servers | Remote MCP tool servers | OAuth 2.0 (auto) | Via `codemie-mcp-proxy` |
| Enterprise SSO | Corporate auth | SAML/OAuth | SSO base URL |

---
Expand Down Expand Up @@ -654,6 +655,67 @@ export class ConfigLoader {

---

## MCP Server Integration

### Overview

The MCP (Model Context Protocol) proxy enables MCP clients to connect to remote MCP servers over HTTP, with automatic OAuth 2.0 authorization. It bridges stdio JSON-RPC to streamable HTTP transport.

**Key Components:**

| Component | File | Purpose |
|-----------|------|---------|
| Stdio-HTTP Bridge | `src/mcp/stdio-http-bridge.ts` | Bridges stdio JSON-RPC ↔ streamable HTTP |
| OAuth Provider | `src/mcp/auth/mcp-oauth-provider.ts` | Browser-based OAuth authorization code flow |
| Callback Server | `src/mcp/auth/callback-server.ts` | Ephemeral localhost server for OAuth callbacks |
| MCP Auth Plugin | `src/providers/plugins/sso/proxy/plugins/mcp-auth.plugin.ts` | SSO proxy plugin for URL rewriting and SSRF protection |

### Architecture Patterns

**Bridge Pattern (stdio ↔ HTTP):**
```typescript
// Source: src/mcp/stdio-http-bridge.ts
// StdioHttpBridge reads JSON-RPC messages from stdin, forwards them
// over streamable HTTP, and writes responses back to stdout.
const bridge = new StdioHttpBridge({ serverUrl: 'https://mcp-server.example.com/sse' });
await bridge.start();
```

**OAuth Client Pattern:**
```typescript
// Source: src/mcp/auth/mcp-oauth-provider.ts
// Implements OAuthClientProvider from @modelcontextprotocol/client
// Flow: 401 → metadata → dynamic registration → browser auth → callback → token
```

**Cookie Jar Pattern:**
```typescript
// Source: src/mcp/stdio-http-bridge.ts (CookieJar class)
// Per-origin cookie storage: captures Set-Cookie from responses,
// injects Cookie header on subsequent requests to the same origin.
```

### SSO Proxy Plugin

When running through the CodeMie SSO proxy, the MCP Auth Plugin (priority 3) provides:

- **URL rewriting**: `/mcp_auth?original=<url>` for initial connections, `/mcp_relay/<root_b64>/<relay_b64>/<path>` for relayed requests
- **Client name override**: Replaces `client_name` in Dynamic Client Registration with `MCP_CLIENT_NAME`
- **SSRF protection**: Rejects private/loopback origins (hostname + DNS resolution)
- **Per-flow origin scoping**: Tags discovered origins with their root MCP server to prevent cross-flow confusion

### Configuration

| Variable | Default | Description |
|----------|---------|-------------|
| `MCP_CLIENT_NAME` | `CodeMie CLI` | Client name for OAuth registration |
| `MCP_PROXY_DEBUG` | (unset) | Verbose proxy logging |
| `CODEMIE_PROXY_PORT` | (auto) | Fixed proxy port |

For full architecture details, see [Proxy Architecture — MCP Auth Plugin](../../docs/ARCHITECTURE-PROXY.md#65-mcp-auth-plugin).

---

## Troubleshooting

| Issue | Cause | Solution |
Expand All @@ -671,6 +733,8 @@ export class ConfigLoader {

## References

- **MCP Proxy**: `src/mcp/`
- **MCP Auth Plugin**: `src/providers/plugins/sso/proxy/plugins/mcp-auth.plugin.ts`
- **Provider Plugins**: `src/providers/plugins/`
- **Provider Core**: `src/providers/core/types.ts`
- **Agent System**: `src/agents/codemie-code/`
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ dist/
.env.local
.env.*.local

# MCP config (contains API keys)
.mcp.json*

# IDE
.vscode/
.idea/
Expand Down
3 changes: 2 additions & 1 deletion .gitleaks.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ description = "Exclude test files and build artifacts containing intentional fak
paths = [
'''src/utils/__tests__/sanitize\.test\.ts$''',
'''dist/''',
'''\.idea/'''
'''\.idea/''',
'''\.mcp\.json'''
]
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ CodeMie CLI is the all-in-one AI coding assistant for developers.
- 🔄 **Multi-Provider Support** - OpenAI, Azure OpenAI, AWS Bedrock, LiteLLM, Ollama, Enterprise SSO, and JWT Bearer Auth.
- 🚀 **Built-in Agent** - A powerful LangGraph-based assistant with file operations, command execution, and planning tools.
- 🖥️ **Cross-Platform** - Full support for Windows, Linux, and macOS with platform-specific optimizations.
- 🔗 **MCP Proxy** - Connect to remote MCP servers with automatic OAuth authorization.
- 🔐 **Enterprise Ready** - SSO and JWT authentication, audit logging, and role-based access.
- ⚡ **Productivity Boost** - Code review, refactoring, test generation, and bug fixing.
- 🎯 **Profile Management** - Manage work, personal, and team configurations separately.
Expand Down Expand Up @@ -57,6 +58,9 @@ codemie-code "Analyze this codebase"

# 6. Execute a single task and exit
codemie --task "Generate unit tests"

# 7. Connect to a remote MCP server (with automatic OAuth)
claude mcp add my-server -- codemie-mcp-proxy "https://mcp-server.example.com/sse"
```

**Prefer not to install globally?** Use npx with the full package name:
Expand Down Expand Up @@ -268,6 +272,7 @@ codemie profile # Manage provider profiles
codemie analytics # View usage analytics (sessions, tokens, costs, tools)
codemie workflow <cmd> # Manage CI/CD workflows
codemie doctor # Health check and diagnostics
codemie mcp-proxy <url> # Stdio-to-HTTP MCP proxy with OAuth
```

For a full command reference, see the [Commands Documentation](docs/COMMANDS.md).
Expand All @@ -285,6 +290,7 @@ Comprehensive guides are available in the `docs/` directory:
- **[Authentication](docs/AUTHENTICATION.md)** - SSO setup, token management, enterprise authentication
- **[Examples](docs/EXAMPLES.md)** - Common workflows, multi-provider examples, CI/CD integration
- **[Configuration Architecture](docs/ARCHITECTURE-CONFIGURATION.md)** - How configuration flows through the system from CLI to proxy plugins
- **[Proxy Architecture](docs/ARCHITECTURE-PROXY.md)** - Proxy plugin system, MCP authorization flow
- **[Claude Code Plugin](src/agents/plugins/claude/plugin/README.md)** - Built-in commands, hooks system, and plugin architecture

## Contributing
Expand Down
91 changes: 91 additions & 0 deletions bin/codemie-mcp-proxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/usr/bin/env node

/**
* MCP Proxy Entry Point
*
* Lightweight entry point for the stdio-to-HTTP MCP proxy.
* Skips migrations, update checks, and plugin loading to avoid
* any stdout output that would corrupt the JSON-RPC stdio channel.
*
* Usage:
* node bin/mcp-proxy.js <url>
* claude mcp add my-server -- node /path/to/bin/mcp-proxy.js "https://mcp-server/path"
*/

import { appendFileSync, mkdirSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';

// Boot-level file logger (before any imports that might touch stdout)
const logDir = join(homedir(), '.codemie', 'logs');
const logFile = join(logDir, 'mcp-proxy.log');
try { mkdirSync(logDir, { recursive: true }); } catch { /* ignore */ }

function bootLog(msg) {
const line = `[${new Date().toISOString()}] [boot] ${msg}\n`;
try { appendFileSync(logFile, line); } catch { /* ignore */ }
}

bootLog(`mcp-proxy started, argv: ${JSON.stringify(process.argv)}`);
bootLog(`env: CODEMIE_DEBUG=${process.env.CODEMIE_DEBUG}, MCP_PROXY_DEBUG=${process.env.MCP_PROXY_DEBUG}`);

const url = process.argv[2];

if (!url) {
console.error('Usage: mcp-proxy <url>');
console.error(' url: MCP server URL to connect to');
process.exit(1);
}

try {
new URL(url);
} catch {
bootLog(`Invalid URL: ${url}`);
console.error(`[mcp-proxy] Invalid MCP server URL: ${url}`);
process.exit(1);
}

bootLog(`URL validated: ${url}`);

let StdioHttpBridge;
try {
const mod = await import('../dist/mcp/stdio-http-bridge.js');
StdioHttpBridge = mod.StdioHttpBridge;
bootLog('Bridge module imported successfully');
} catch (error) {
bootLog(`Failed to import bridge: ${error.message}\n${error.stack}`);
console.error(`[mcp-proxy] Failed to load: ${error.message}`);
process.exit(1);
}

const bridge = new StdioHttpBridge({ serverUrl: url });

const shutdown = async () => {
bootLog('Shutdown signal received');
try {
await bridge.shutdown();
} catch (err) {
bootLog(`Shutdown error: ${err.message}`);
}
process.exit(0);
};

process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
process.on('uncaughtException', (err) => {
bootLog(`Uncaught exception: ${err.message}\n${err.stack}`);
process.exit(1);
});
process.on('unhandledRejection', (reason) => {
bootLog(`Unhandled rejection: ${reason}`);
});

try {
bootLog('Starting bridge...');
await bridge.start();
bootLog('Bridge started, listening on stdio');
} catch (error) {
bootLog(`Fatal error: ${error.message}\n${error.stack}`);
console.error(`[mcp-proxy] Fatal error: ${error.message}`);
process.exit(1);
}
84 changes: 83 additions & 1 deletion docs/ARCHITECTURE-PROXY.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
The CodeMie Proxy is a **plugin-based HTTP streaming proxy** that sits between AI coding agents and their target API endpoints. It enables:

- **SSO Authentication**: Automatic cookie injection for enterprise SSO
- **MCP Authorization**: OAuth proxy for remote MCP servers with SSRF protection
- **Header Management**: CodeMie-specific header injection for traceability
- **Observability**: Detailed logging and metrics collection
- **Metrics Sync**: Background sync of session metrics to CodeMie API
Expand Down Expand Up @@ -60,6 +61,7 @@ The CodeMie Proxy is a **plugin-based HTTP streaming proxy** that sits between A
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Plugin System (Priority-Based) │ │
│ │ │ │
│ │ [3] MCP Auth Plugin → MCP OAuth proxy & URL rewrite│ │
│ │ [10] SSO Auth Plugin → Inject cookies │ │
│ │ [20] Header Injection → Add X-CodeMie headers │ │
│ │ [50] Logging Plugin → Log requests/responses │ │
Expand Down Expand Up @@ -161,7 +163,8 @@ The CodeMie Proxy is a **plugin-based HTTP streaming proxy** that sits between A
- Retrieve plugin configurations

**Plugin Priority Levels**:
- **0-10**: Authentication and security (SSO Auth: 10)
- **0-3**: MCP protocol handling (MCP Auth: 3)
- **4-10**: Authentication and security (SSO Auth: 10)
- **11-50**: Header manipulation (Header Injection: 20)
- **51-100**: Observability (Logging: 50, Metrics Sync: 100)
- **101-500**: Business logic (rate limiting, caching)
Expand Down Expand Up @@ -609,6 +612,85 @@ Proxy Stop
- Check network connectivity to API
- Enable debug logging

### 6.5 MCP Auth Plugin

**Priority**: 3 (runs before all other plugins)
**File**: `src/providers/plugins/sso/proxy/plugins/mcp-auth.plugin.ts`

**Purpose**: Proxy MCP OAuth authorization flows through the CodeMie proxy so that all auth traffic is routed centrally and `client_name` can be overridden via the `MCP_CLIENT_NAME` environment variable.

#### 6.5.1 URL Scheme

The plugin intercepts two URL patterns:

| Route | Pattern | Purpose |
|-------|---------|---------|
| **Initial** | `/mcp_auth?original=<url>` | First MCP connection — starts an OAuth flow |
| **Relay** | `/mcp_relay/<root_b64>/<relay_b64>/<path>` | Subsequent requests routed through proxy |

- `root_b64`: Base64url-encoded root MCP server origin (for per-flow isolation)
- `relay_b64`: Base64url-encoded actual target origin (may differ when auth server is on a separate host)

#### 6.5.2 Request Handling

**`/mcp_auth` route:**
1. Extract `original` query parameter (the real MCP server URL)
2. Validate URL (SSRF check)
3. Forward request to the target MCP server
4. Buffer the JSON response and rewrite all discovered URLs to proxy relay URLs
5. Return the rewritten response to the MCP client

**`/mcp_relay` route:**
1. Decode `root_b64` and `relay_b64` to recover target origin
2. Validate root-relay association (per-flow origin scoping)
3. Reconstruct the full target URL from relay origin + path + query
4. Forward request to the real target
5. Buffer JSON auth metadata responses and rewrite URLs; stream all other responses

#### 6.5.3 Response URL Rewriting

The plugin buffers JSON responses (auth metadata, client registration, etc.) and rewrites all absolute HTTP(S) URLs found in JSON values to proxy relay URLs. This ensures the MCP client routes all subsequent requests through the proxy.

**Exceptions**: Token audience identifiers (e.g., `resource` field) are not rewritten — they are logical identifiers, not URLs to access.

**Browser endpoints** (e.g., `authorization_endpoint`) are left as-is so the user's browser navigates directly to the auth server.

#### 6.5.4 Security

**SSRF Protection:**
- Private/loopback IP addresses are rejected (both literal hostname check and DNS resolution)
- Only `http:` and `https:` schemes are allowed

**Per-Flow Origin Scoping:**
- Discovered origins (from auth metadata) are tagged with their root MCP server origin
- Relay requests validate that the relay origin is associated with the claimed root origin
- Prevents cross-flow origin confusion

**Buffering Policy:**
- Only auth metadata responses are buffered (for URL rewriting)
- Post-auth MCP traffic streams through without buffering

#### 6.5.5 Companion Components

The MCP Auth Plugin works in conjunction with the stdio-to-HTTP bridge:

| Component | File | Purpose |
|-----------|------|---------|
| Stdio-HTTP Bridge | `src/mcp/stdio-http-bridge.ts` | Bridges stdio JSON-RPC to streamable HTTP transport |
| OAuth Provider | `src/mcp/auth/mcp-oauth-provider.ts` | Implements `OAuthClientProvider` for browser-based OAuth flow |
| Callback Server | `src/mcp/auth/callback-server.ts` | Ephemeral localhost server for receiving OAuth callbacks |
| Proxy Logger | `src/mcp/proxy-logger.ts` | File-based logger for proxy operations |
| Constants | `src/mcp/constants.ts` | `MCP_CLIENT_NAME` default and accessor |

#### 6.5.6 Configuration

**Environment Variables:**
- `MCP_CLIENT_NAME`: Client name for OAuth Dynamic Client Registration (default: `CodeMie CLI`)
- `MCP_PROXY_DEBUG`: Enable verbose proxy logging
- `CODEMIE_PROXY_PORT`: Fixed proxy port (for stable MCP auth URLs across restarts)

**Log Location**: `~/.codemie/logs/mcp-proxy.log`

---

## 7. Quality Attributes
Expand Down
Loading
Loading