diff --git a/AGENTS.md b/AGENTS.md index 4d8e145e..f667f608 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,207 +1,22 @@ -# MCPHost Development Context +# MCPHost Agent Guidelines ## Build/Test Commands -- **Build**: `go build -o output/mcphost` or use `./contribute/build.sh` -- **Test**: `go test ./...` (run all tests) -- **Test single package**: `go test ./cmd` (test script functionality) -- **Lint**: `go vet ./...` (built-in Go linter) +- **Build**: `go build -o output/mcphost` +- **Test all**: `go test -race ./...` +- **Test single**: `go test -race ./cmd -run TestScriptExecution` +- **Lint**: `go vet ./...` - **Format**: `go fmt ./...` -- **Dependencies**: `go mod tidy` -## UI and Output Modes -MCPHost supports multiple output modes for different use cases: +## Code Style +- **Imports**: stdlib → third-party → local (blank lines between) +- **Naming**: camelCase (unexported), PascalCase (exported) +- **Errors**: Always check, wrap with `fmt.Errorf("context: %w", err)` +- **Logging**: Use `github.com/charmbracelet/log` structured logging +- **Types**: Prefer `any` over `interface{}` +- **JSON**: snake_case tags with `omitempty` where appropriate +- **Context**: First parameter for blocking operations -### Standard Mode (Default) -- Full-featured terminal UI with rich styling and formatting -- Interactive message display with proper spacing and visual hierarchy -- Suitable for regular interactive usage - -### Compact Mode (`--compact`) -- **Location**: `internal/ui/compact_renderer.go`, `internal/ui/cli.go` -- **Purpose**: Simplified output format without fancy styling for better readability in automation contexts -- **Features**: - - Single-line message format where possible - - Minimal visual styling and spacing - - Consistent symbol-based prefixes (🧑, 🤖, 🔧, etc.) - - Optimized for scripting and log parsing -- **Usage**: Add `--compact` flag to any mcphost command -- **Note**: Has no effect when combined with `--quiet` (mutually exclusive) - -### Quiet Mode (`--quiet`) -- Suppresses all UI elements except the AI response -- Only works with `--prompt` (non-interactive mode) -- Ideal for shell scripting and piping output to other commands -- **Note**: When `--quiet` is used, `--compact` has no effect since no UI elements are shown - -## Code Style Guidelines -- **Package structure**: `pkg/` for reusable packages, `cmd/` for CLI commands -- **Imports**: Standard library first, then third-party, then local packages with blank lines between groups -- **Naming**: Use camelCase for unexported, PascalCase for exported; descriptive names (e.g., `CreateMessage`, `mcpClients`) -- **Interfaces**: Keep small and focused (e.g., `llm.Provider`, `llm.Message`) -- **Error handling**: Always check errors, wrap with context using `fmt.Errorf("context: %v", err)` -- **Logging**: Use `github.com/charmbracelet/log` with structured logging: `log.Info("message", "key", value)` -- **Types**: Prefer `any` over `interface{}` (modernize hint from linter) -- **JSON tags**: Use snake_case for JSON fields, include omitempty where appropriate -- **Context**: Always pass `context.Context` as first parameter for operations that may block - -## Architecture Notes -- Multi-provider LLM support (Anthropic, OpenAI, Ollama, Google) -- MCP (Model Context Protocol) client-server architecture for tool integration -- Provider pattern for LLM abstraction with common `llm.Provider` interface -- History management with message pruning based on configurable window size -- Tool calling support across all providers with unified `llm.Tool` interface - -## MCP Configuration Schema -MCPHost supports a simplified configuration schema with three server types: - -### New Simplified Format -- **Local servers** (`"type": "local"`): Run commands locally via stdio transport - - `command`: Array of command and arguments (e.g., `["npx", "server", "args"]`) - - `environment`: Key-value map of environment variables -- **Remote servers** (`"type": "remote"`): Connect via StreamableHTTP transport - - `url`: Server endpoint URL - - Automatically uses StreamableHTTP for optimal performance -- **Builtin servers** (`"type": "builtin"`): Run in-process for optimal performance - - `name`: Internal name of the builtin server (e.g., `"fs"`) - - `options`: Configuration options specific to the builtin server - -### Legacy Format Support -- Maintains full backward compatibility with existing configurations -- Automatic detection and conversion of legacy formats -- Custom `UnmarshalJSON` method handles format migration seamlessly -- **Bug Fix**: Improved stdio transport reliability for legacy configurations with external processes (Docker, NPX, etc.) - -### Transport Mapping -- `"local"` type → `stdio` transport (launches local processes) -- `"remote"` type → `streamable` transport (StreamableHTTP protocol) -- `"builtin"` type → `inprocess` transport (in-process execution) -- Legacy `transport` field still supported for backward compatibility - -### Configuration Files -- Primary: `~/.mcphost.yml` or `~/.mcphost.json` -- Legacy: `~/.mcp.yml` or `~/.mcp.json` -- Custom location via `--config` flag - -## Available Builtin Servers -MCPHost includes several builtin MCP servers for common functionality: - -### Filesystem Server (`fs`) -- **Location**: `internal/builtin/registry.go` (registration), uses external `mcp-filesystem-server` -- **Purpose**: Secure filesystem access with configurable allowed directories -- **Options**: `allowed_directories` array (defaults to current working directory) - -### Bash Server (`bash`) -- **Location**: `internal/builtin/bash.go` -- **Purpose**: Execute bash commands with security restrictions and timeout controls -- **Features**: Banned commands list, configurable timeouts, output size limits -- **Security**: Blocks network commands (curl, wget, etc.), 30KB output limit, 2-10 minute timeouts - -### Todo Server (`todo`) -- **Location**: `internal/builtin/todo.go` -- **Purpose**: Manage ephemeral todo lists for task tracking during sessions -- **Features**: In-memory storage, thread-safe operations, JSON-based API -- **Tools**: `todowrite` (create/update todos), `todoread` (read current todos) - -### Fetch Server (`fetch`) -- **Location**: `internal/builtin/fetch.go` -- **Purpose**: Fetch web content and convert to text, markdown, or HTML formats -- **Features**: HTTP/HTTPS support, HTML parsing, markdown conversion, size limits -- **Security**: 5MB response limit, configurable timeouts, localhost-aware HTTPS upgrade - -## Environment Variable Substitution System -MCPHost includes a comprehensive environment variable substitution system for secure configuration management. - -### Implementation Details -- **Location**: `internal/config/substitution.go` (core logic), `internal/config/substitution_test.go` (unit tests) -- **Purpose**: Replace `${env://VAR}` and `${env://VAR:-default}` patterns with environment variable values -- **Integration**: Works in both config files and script frontmatter/prompts - -### Substitution Components -- **EnvSubstituter**: Handles environment variable substitution -- **ArgsSubstituter**: Handles script argument substitution (refactored from existing code) -- **Shared Parsing Logic**: `parseVariableWithDefault()` function used by both substituters - -### Processing Order -1. **Config Loading**: `cmd/root.go` → `loadConfigWithEnvSubstitution()` → env substitution → YAML/JSON parsing -2. **Script Mode**: `cmd/script.go` → `parseScriptContent()` → env substitution → YAML parsing → args substitution - -### Security Features -- **No Shell Execution**: Direct environment variable lookup using `os.Getenv()` -- **Error Handling**: Clear error messages for missing required variables -- **Validation**: Regex-based pattern matching with comprehensive validation - -## Script System -MCPHost includes a powerful script system for automation and reusable workflows. - -### Script Features -- **Location**: `cmd/script.go` (main implementation), `cmd/script_test.go` (comprehensive tests) -- **Purpose**: Execute YAML-based automation scripts with dual variable substitution -- **Format**: YAML frontmatter + prompt content in single executable files - -### Variable Substitution System -- **Environment Variables**: `${env://VAR}` and `${env://VAR:-default}` - Processed first -- **Script Arguments**: `${variable}` and `${variable:-default}` - Processed after environment variables -- **Features**: - - Bash-style default syntax for familiarity - - Empty defaults supported: `${var:-}` and `${env://VAR:-}` - - Complex defaults: paths, URLs, commands with spaces - - Full backward compatibility with existing scripts -- **Implementation**: Dual-phase substitution with shared parsing logic - -### Script Examples -- **Location**: `examples/scripts/` directory -- **Demo Script**: `default-values-demo.sh` - Showcases script argument default values -- **Env Substitution Script**: `env-substitution-script.sh` - Demonstrates environment variable usage -- **Usage Examples**: Multiple scenarios from simple defaults to complex environment/args combinations - -### Testing -- **Unit Tests**: 25+ test cases in `internal/config/substitution_test.go` covering all substitution scenarios -- **Integration Tests**: `internal/config/integration_test.go` and `cmd/script_integration_test.go` -- **Edge Cases**: Empty defaults, complex values, mixed required/optional variables, processing order -- **Backward Compatibility**: Ensures existing scripts and configs continue working unchanged - -## Authentication System -MCPHost includes optional OAuth authentication for Anthropic Claude as an alternative to API keys. - -### Authentication Commands -- **Location**: `cmd/auth.go` (main implementation) -- **Purpose**: Manage Anthropic OAuth credentials (alternative to API keys) -- **Commands**: `login anthropic`, `logout anthropic`, `status` - -### OAuth Implementation -- **Location**: `internal/auth/oauth.go` (OAuth client), `internal/auth/credentials.go` (credential management) -- **Features**: PKCE security, automatic token refresh, encrypted storage, browser-based flow -- **Priority**: OAuth credentials > API keys (environment variables/flags) - -## Recent Features - -### Environment Variable Substitution (New) -- **Feature**: Added support for `${env://VAR}` and `${env://VAR:-default}` syntax in config files and scripts -- **Implementation**: - - `internal/config/substitution.go`: Core substitution logic with shared parsing - - `cmd/root.go`: Config loading integration with `loadConfigWithEnvSubstitution()` - - `cmd/script.go`: Script parsing integration with dual-phase substitution -- **Security**: Environment variables processed safely without shell execution -- **Compatibility**: Full backward compatibility with existing configurations and scripts -- **Testing**: Comprehensive test suite with 25+ unit tests and integration tests - -### Processing Flow -1. **Config Files**: Raw content → Env substitution → YAML/JSON parsing → Viper config -2. **Scripts**: Raw content → Env substitution → YAML parsing → Args substitution → Final config - -## Recent Bug Fixes - -### Legacy MCP Server Configuration Fix -- **Issue**: Legacy stdio transport configurations (using `command` + `args` format) were failing with timeout errors -- **Root Cause**: MCP client creation was not properly handling legacy argument parsing when `Command` array was incomplete -- **Fix**: Added fallback logic in `internal/tools/mcp.go` to use legacy `Args` field when `Command` array only contains the command -- **Impact**: Fixes Docker-based MCP servers, NPX-based servers, and other external process configurations -- **Files Modified**: - - `internal/tools/mcp.go`: Added legacy args fallback logic - - `internal/config/config.go`: Enhanced headers support for remote servers -- **Testing**: Verified with both Docker (`ghcr.io/mark3labs/phalcon-mcp:latest`) and NPX (`@modelcontextprotocol/server-filesystem`) servers - -### MCP Client Initialization Improvements -- **Timeout**: Increased initialization timeout from 10s to 30s for slower external processes -- **Capabilities**: Added explicit `ClientCapabilities{}` to initialization request for better compatibility -- **Headers**: Enhanced SSE transport to support custom headers for authentication \ No newline at end of file +## Architecture +- Multi-provider LLM support via `llm.Provider` interface +- MCP client-server for tool integration +- Builtin servers: bash, fetch, todo, fs \ No newline at end of file diff --git a/README.md b/README.md index 97e2f342..be1a83d9 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,42 @@ # MCPHost 🤖 -A CLI host application that enables Large Language Models (LLMs) to interact with external tools through the Model Context Protocol (MCP). Currently supports both Claude 3.5 Sonnet and Ollama models. +A CLI host application that enables Large Language Models (LLMs) to interact with external tools through the Model Context Protocol (MCP). Currently supports Claude, OpenAI, Google Gemini, and Ollama models. Discuss the Project on [Discord](https://discord.gg/RqSS2NQVsY) +## Table of Contents + +- [Overview](#overview-) +- [Features](#features-) +- [Requirements](#requirements-) +- [Environment Setup](#environment-setup-) +- [Installation](#installation-) +- [Configuration](#configuration-) + - [MCP Servers](#mcp-servers) + - [Environment Variable Substitution](#environment-variable-substitution) + - [Simplified Configuration Schema](#simplified-configuration-schema) + - [Tool Filtering](#tool-filtering) + - [Legacy Configuration Support](#legacy-configuration-support) + - [Transport Types](#transport-types) + - [System Prompt](#system-prompt) +- [Usage](#usage-) + - [Interactive Mode](#interactive-mode-default) + - [Script Mode](#script-mode) + - [Hooks System](#hooks-system) + - [Non-Interactive Mode](#non-interactive-mode) + - [Model Generation Parameters](#model-generation-parameters) + - [Available Models](#available-models) + - [Examples](#examples) + - [Flags](#flags) + - [Authentication Subcommands](#authentication-subcommands) + - [Configuration File Support](#configuration-file-support) + - [Interactive Commands](#interactive-commands) +- [Automation & Scripting](#automation--scripting-) +- [MCP Server Compatibility](#mcp-server-compatibility-) +- [Contributing](#contributing-) +- [License](#license-) +- [Acknowledgments](#acknowledgments-) + ## Overview 🌟 MCPHost acts as a host in the MCP client-server architecture, where: @@ -17,23 +50,28 @@ This architecture allows language models to: - Execute commands and retrieve information safely 🔒 Currently supports: -- Claude 3.5 Sonnet (claude-3-5-sonnet-20240620) +- Anthropic Claude models (Claude 3.5 Sonnet, Claude 3.5 Haiku, etc.) +- OpenAI models (GPT-4, GPT-4 Turbo, GPT-3.5, etc.) +- Google Gemini models (Gemini 2.0 Flash, Gemini 1.5 Pro, etc.) - Any Ollama-compatible model with function calling support -- Google Gemini models -- Any OpenAI-compatible local or online model with function calling support +- Any OpenAI-compatible API endpoint ## Features ✨ -- Interactive conversations with support models +- Interactive conversations with multiple AI models - **Non-interactive mode** for scripting and automation - **Script mode** for executable YAML-based automation scripts - Support for multiple concurrent MCP servers - **Tool filtering** with `allowedTools` and `excludedTools` per server - Dynamic tool discovery and integration -- Tool calling capabilities for both model types +- Tool calling capabilities across all supported models - Configurable MCP server locations and arguments - Consistent command interface across model types - Configurable message history window for context management +- **OAuth authentication** support for Anthropic (alternative to API keys) +- **Hooks system** for custom integrations and security policies +- **Environment variable substitution** in configs and scripts +- **Builtin servers** for common functionality (filesystem, bash, todo, http) ## Requirements 📋 @@ -64,7 +102,7 @@ ollama pull mistral ollama serve ``` -You can also configure the Ollama client using standard environment variables, such as `OLLAMA HOST` for the Ollama base URL. +You can also configure the Ollama client using standard environment variables, such as `OLLAMA_HOST` for the Ollama base URL. 3. Google API Key (for Gemini): ```bash @@ -392,11 +430,6 @@ You can specify a custom system prompt using the `--system-prompt` flag. You can - Explain your reasoning ``` -Usage: -```bash -mcphost --system-prompt ./my-system-prompt.json -``` - ## Usage 🚀 @@ -664,10 +697,11 @@ These parameters work with all supported providers (OpenAI, Anthropic, Google, O ### Available Models Models can be specified using the `--model` (`-m`) flag: -- Anthropic Claude (default): `anthropic:claude-3-5-sonnet-latest` -- OpenAI or OpenAI-compatible: `openai:gpt-4` -- Ollama models: `ollama:modelname` -- Google: `google:gemini-2.0-flash` +- **Anthropic Claude** (default): `anthropic:claude-sonnet-4-20250514`, `anthropic:claude-3-5-sonnet-latest`, `anthropic:claude-3-5-haiku-latest` +- **OpenAI**: `openai:gpt-4`, `openai:gpt-4-turbo`, `openai:gpt-3.5-turbo` +- **Google Gemini**: `google:gemini-2.0-flash`, `google:gemini-1.5-pro` +- **Ollama models**: `ollama:llama3.2`, `ollama:qwen2.5:3b`, `ollama:mistral` +- **OpenAI-compatible**: Any model via custom endpoint with `--provider-url` ### Examples