rename: fork mcphost to kit (github.com/mark3labs/kit)

Rename the entire project from mcphost to kit, including:
- Go module path and all import paths
- SDK type MCPHost -> Kit, file renames mcphost.go -> kit.go
- CLI command name, usage strings, UI labels (KIT in literature)
- Config paths (.mcphost -> .kit), env prefix (MCPHOST_ -> KIT_)
- Data/credential/hooks directory paths
- Remove legacy .mcp config fallbacks
- Session metadata field (mcphost_version -> kit_version)
- MCP client identity name
- Build output, goreleaser binary name
- All documentation, examples, scripts, and test files
This commit is contained in:
Ed Zynda
2026-02-26 16:59:59 +03:00
parent 7483bef1fa
commit 7fc94018a9
70 changed files with 351 additions and 350 deletions
+1 -2
View File
@@ -1,9 +1,8 @@
.aider*
.env
aidocs/
.mcp.json
*.log
mcphost
kit
.idea
test/
build/
+1 -1
View File
@@ -15,7 +15,7 @@ builds:
ignore:
- goos: windows
goarch: arm64
binary: mcphost
binary: kit
ldflags:
- -s -w -X main.version={{.Version}}
+3 -3
View File
@@ -17,10 +17,10 @@ Keep this managed block so 'openspec update' can refresh the instructions.
<!-- OPENSPEC:END -->
# MCPHost Agent Guidelines
# KIT Agent Guidelines
## Build/Test Commands
- **Build**: `go build -o output/mcphost`
- **Build**: `go build -o output/kit`
- **Test all**: `go test -race ./...`
- **Test single**: `go test -race ./cmd -run TestScriptExecution`
- **Lint**: `go vet ./...`
@@ -38,4 +38,4 @@ Keep this managed block so 'openspec update' can refresh the instructions.
## Architecture
- Multi-provider LLM support via `llm.Provider` interface
- MCP client-server for tool integration
- Builtin servers: bash, fetch, todo, fs
- Builtin servers: bash, fetch, todo, fs
+81 -83
View File
@@ -1,4 +1,4 @@
# MCPHost 🤖
# KIT 🤖
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.
@@ -40,8 +40,8 @@ Discuss the Project on [Discord](https://discord.gg/RqSS2NQVsY)
## Overview 🌟
MCPHost acts as a host in the MCP client-server architecture, where:
- **Hosts** (like MCPHost) are LLM applications that manage connections and interactions
KIT acts as a host in the MCP client-server architecture, where:
- **Hosts** (like KIT) are LLM applications that manage connections and interactions
- **Clients** maintain 1:1 connections with MCP servers
- **Servers** provide context, tools, and capabilities to the LLMs
@@ -117,19 +117,19 @@ export GOOGLE_API_KEY='your-api-key'
5. Self-Signed Certificates (TLS):
If your provider uses self-signed certificates (e.g., local Ollama with HTTPS), you can skip certificate verification:
```bash
mcphost --provider-url https://192.168.1.100:443 --tls-skip-verify
kit --provider-url https://192.168.1.100:443 --tls-skip-verify
```
⚠️ **WARNING**: Only use `--tls-skip-verify` for development or when connecting to trusted servers with self-signed certificates. This disables TLS certificate verification and is insecure for production use.
## Installation 📦
```bash
go install github.com/mark3labs/mcphost@latest
go install github.com/mark3labs/kit@latest
```
## SDK Usage 🛠️
MCPHost also provides a Go SDK for programmatic access without spawning OS processes. The SDK maintains identical behavior to the CLI, including configuration loading, environment variables, and defaults.
KIT also provides a Go SDK for programmatic access without spawning OS processes. The SDK maintains identical behavior to the CLI, including configuration loading, environment variables, and defaults.
### Quick Example
@@ -139,13 +139,13 @@ package main
import (
"context"
"fmt"
"github.com/mark3labs/mcphost/sdk"
"github.com/mark3labs/kit/sdk"
)
func main() {
ctx := context.Background()
// Create MCPHost instance with default configuration
// Create Kit instance with default configuration
host, err := sdk.New(ctx, nil)
if err != nil {
panic(err)
@@ -176,19 +176,18 @@ For detailed SDK documentation, examples, and API reference, see the [SDK README
## Configuration ⚙️
### MCP Servers
MCPHost will automatically create a configuration file in your home directory if it doesn't exist. It looks for config files in this order:
- `.mcphost.yml` or `.mcphost.json` (preferred)
- `.mcp.yml` or `.mcp.json` (backwards compatibility)
KIT will automatically create a configuration file in your home directory if it doesn't exist. It looks for config files in this order:
- `.kit.yml` or `.kit.json`
**Config file locations by OS:**
- **Linux/macOS**: `~/.mcphost.yml`, `~/.mcphost.json`, `~/.mcp.yml`, `~/.mcp.json`
- **Windows**: `%USERPROFILE%\.mcphost.yml`, `%USERPROFILE%\.mcphost.json`, `%USERPROFILE%\.mcp.yml`, `%USERPROFILE%\.mcp.json`
- **Linux/macOS**: `~/.kit.yml`, `~/.kit.json`
- **Windows**: `%USERPROFILE%\.kit.yml`, `%USERPROFILE%\.kit.json`
You can also specify a custom location using the `--config` flag.
### Environment Variable Substitution
MCPHost supports environment variable substitution in both config files and script frontmatter using the syntax:
KIT supports environment variable substitution in both config files and script frontmatter using the syntax:
- **`${env://VAR}`** - Required environment variable (fails if not set)
- **`${env://VAR:-default}`** - Optional environment variable with default value
@@ -218,13 +217,13 @@ export OPENAI_API_KEY="your_openai_key"
export DEBUG="true"
export MODEL="openai/gpt-4"
# Run mcphost
mcphost
# Run kit
kit
```
### Simplified Configuration Schema
MCPHost now supports a simplified configuration schema with three server types:
KIT now supports a simplified configuration schema with three server types:
#### Local Servers
For local MCP servers that run commands on your machine:
@@ -386,7 +385,7 @@ All MCP server types support tool filtering to restrict which tools are availabl
### Legacy Configuration Support
MCPHost maintains full backward compatibility with the previous configuration format. **Note**: A recent bug fix improved legacy stdio transport reliability for external MCP servers (Docker, NPX, etc.).
KIT maintains full backward compatibility with the previous configuration format. **Note**: A recent bug fix improved legacy stdio transport reliability for external MCP servers (Docker, NPX, etc.).
#### Legacy STDIO Format
```json
@@ -448,7 +447,7 @@ MCPHost maintains full backward compatibility with the previous configuration fo
### Transport Types
MCPHost supports four transport types:
KIT supports four transport types:
- **`stdio`**: Launches a local process and communicates via stdin/stdout (used by `"local"` servers)
- **`sse`**: Connects to a server using Server-Sent Events (legacy format)
- **`streamable`**: Connects to a server using Streamable HTTP protocol (used by `"remote"` servers)
@@ -465,12 +464,12 @@ You can specify a custom system prompt using the `--system-prompt` flag. You can
1. **Pass the prompt directly as text:**
```bash
mcphost --system-prompt "You are a helpful assistant that responds in a friendly tone."
kit --system-prompt "You are a helpful assistant that responds in a friendly tone."
```
2. **Pass a path to a text file containing the prompt:**
```bash
mcphost --system-prompt ./prompts/assistant.md
kit --system-prompt ./prompts/assistant.md
```
Example `assistant.md` file:
@@ -487,14 +486,14 @@ You can specify a custom system prompt using the `--system-prompt` flag. You can
## Usage 🚀
MCPHost is a CLI tool that allows you to interact with various AI models through a unified interface. It supports various tools through MCP servers and can run in both interactive and non-interactive modes.
KIT is a CLI tool that allows you to interact with various AI models through a unified interface. It supports various tools through MCP servers and can run in both interactive and non-interactive modes.
### Interactive Mode (Default)
Start an interactive conversation session:
```bash
mcphost
kit
```
### Script Mode
@@ -503,10 +502,10 @@ Run executable YAML-based automation scripts with variable substitution support:
```bash
# Using the script subcommand
mcphost script myscript.sh
kit script myscript.sh
# With variables
mcphost script myscript.sh --args:directory /tmp --args:name "John"
kit script myscript.sh --args:directory /tmp --args:name "John"
# Direct execution (if executable and has shebang)
./myscript.sh
@@ -517,7 +516,7 @@ mcphost script myscript.sh --args:directory /tmp --args:name "John"
Scripts combine YAML configuration with prompts in a single executable file. The configuration must be wrapped in frontmatter delimiters (`---`). You can either include the prompt in the YAML configuration or place it after the closing frontmatter delimiter:
```yaml
#!/usr/bin/env -S mcphost script
#!/usr/bin/env -S kit script
---
# This script uses the container-use MCP server from https://github.com/dagger/container-use
mcpServers:
@@ -533,7 +532,7 @@ prompt: |
Or alternatively, omit the `prompt:` field and place the prompt after the frontmatter:
```yaml
#!/usr/bin/env -S mcphost script
#!/usr/bin/env -S kit script
---
# This script uses the container-use MCP server from https://github.com/dagger/container-use
mcpServers:
@@ -556,12 +555,12 @@ Variables can be provided via command line arguments:
```bash
# Script with variables
mcphost script myscript.sh --args:directory /tmp --args:name "John"
kit script myscript.sh --args:directory /tmp --args:name "John"
```
##### Variable Syntax
MCPHost supports these variable syntaxes:
KIT supports these variable syntaxes:
1. **Required Environment Variables**: `${env://VAR}` - Must be set in environment
2. **Optional Environment Variables**: `${env://VAR:-default}` - Uses default if not set
@@ -570,7 +569,7 @@ MCPHost supports these variable syntaxes:
Example script with mixed environment variables and script arguments:
```yaml
#!/usr/bin/env -S mcphost script
#!/usr/bin/env -S kit script
---
mcpServers:
github:
@@ -600,16 +599,16 @@ export DEBUG="true"
export WORK_DIR="/home/user/projects"
# Uses env vars and defaults: name="World", repo_type="public", command="gh", count="10"
mcphost script myscript.sh
kit script myscript.sh
# Override specific script arguments
mcphost script myscript.sh --args:name "John" --args:username "alice"
kit script myscript.sh --args:name "John" --args:username "alice"
# Override multiple script arguments
mcphost script myscript.sh --args:name "John" --args:username "alice" --args:repo_type "private"
kit script myscript.sh --args:name "John" --args:username "alice" --args:repo_type "private"
# Mix of env vars, provided args, and default values
mcphost script myscript.sh --args:name "Alice" --args:command "gh api" --args:count "5"
kit script myscript.sh --args:name "Alice" --args:command "gh api" --args:count "5"
```
##### Default Value Features
@@ -627,7 +626,7 @@ mcphost script myscript.sh --args:name "Alice" --args:command "gh api" --args:co
#### Script Features
- **Executable**: Use shebang line for direct execution (`#!/usr/bin/env -S mcphost script`)
- **Executable**: Use shebang line for direct execution (`#!/usr/bin/env -S kit script`)
- **YAML Configuration**: Define MCP servers directly in the script
- **Embedded Prompts**: Include the prompt in the YAML
- **Variable Substitution**: Use `${variable}` and `${variable:-default}` syntax with `--args:variable value`
@@ -637,7 +636,7 @@ mcphost script myscript.sh --args:name "Alice" --args:command "gh api" --args:co
- **Tool Filtering**: Supports `allowedTools`/`excludedTools` per server
- **Clean Exit**: Automatically exits after completion
**Note**: The shebang line requires `env -S` to handle the multi-word command `mcphost script`. This is supported on most modern Unix-like systems.
**Note**: The shebang line requires `env -S` to handle the multi-word command `kit script`. This is supported on most modern Unix-like systems.
#### Script Examples
@@ -647,30 +646,30 @@ See `examples/scripts/` for sample scripts:
### Hooks System
MCPHost supports a powerful hooks system that allows you to execute custom commands at specific points during execution. This enables security policies, logging, custom integrations, and automated workflows.
KIT supports a powerful hooks system that allows you to execute custom commands at specific points during execution. This enables security policies, logging, custom integrations, and automated workflows.
#### Quick Start
1. Initialize a hooks configuration:
```bash
mcphost hooks init
kit hooks init
```
2. View active hooks:
```bash
mcphost hooks list
kit hooks list
```
3. Validate your configuration:
```bash
mcphost hooks validate
kit hooks validate
```
#### Configuration
Hooks are configured in YAML files with the following precedence (highest to lowest):
- `.mcphost/hooks.yml` (project-specific hooks)
- `$XDG_CONFIG_HOME/mcphost/hooks.yml` (user global hooks, defaults to `~/.config/mcphost/hooks.yml`)
- `.kit/hooks.yml` (project-specific hooks)
- `$XDG_CONFIG_HOME/kit/hooks.yml` (user global hooks, defaults to `~/.config/kit/hooks.yml`)
Example configuration:
```yaml
@@ -685,7 +684,7 @@ hooks:
UserPromptSubmit:
- hooks:
- type: command
command: "~/.mcphost/hooks/log-prompt.sh"
command: "~/.kit/hooks/log-prompt.sh"
```
#### Available Hook Events
@@ -695,7 +694,7 @@ hooks:
- **UserPromptSubmit**: When user submits a prompt
- **Stop**: When the agent finishes responding
- **SubagentStop**: When a subagent (Task tool) finishes
- **Notification**: When MCPHost sends notifications
- **Notification**: When KIT sends notifications
#### Security
@@ -703,7 +702,7 @@ hooks:
To temporarily disable all hooks, use the `--no-hooks` flag:
```bash
mcphost --no-hooks
kit --no-hooks
```
See the example hook scripts in `examples/hooks/`:
@@ -717,34 +716,34 @@ Run a single prompt and exit - perfect for scripting and automation:
```bash
# Basic non-interactive usage
mcphost -p "What is the weather like today?"
kit -p "What is the weather like today?"
# Quiet mode - only output the AI response (no UI elements)
mcphost -p "What is 2+2?" --quiet
kit -p "What is 2+2?" --quiet
# Use with different models
mcphost -m ollama/qwen2.5:3b -p "Explain quantum computing" --quiet
kit -m ollama/qwen2.5:3b -p "Explain quantum computing" --quiet
```
### Model Generation Parameters
MCPHost supports fine-tuning model behavior through various parameters:
KIT supports fine-tuning model behavior through various parameters:
```bash
# Control response length
mcphost -p "Explain AI" --max-tokens 1000
kit -p "Explain AI" --max-tokens 1000
# Adjust creativity (0.0 = focused, 1.0 = creative)
mcphost -p "Write a story" --temperature 0.9
kit -p "Write a story" --temperature 0.9
# Control diversity with nucleus sampling
mcphost -p "Generate ideas" --top-p 0.8
kit -p "Generate ideas" --top-p 0.8
# Limit token choices for more focused responses
mcphost -p "Answer precisely" --top-k 20
kit -p "Answer precisely" --top-k 20
# Set custom stop sequences
mcphost -p "Generate code" --stop-sequences "```","END"
kit -p "Generate code" --stop-sequences "```","END"
```
These parameters work with all supported providers (OpenAI, Anthropic, Google, Ollama) where supported by the underlying model.
@@ -762,13 +761,13 @@ Models can be specified using the `--model` (`-m`) flag:
#### Interactive Mode
```bash
# Use Ollama with Qwen model
mcphost -m ollama/qwen2.5:3b
kit -m ollama/qwen2.5:3b
# Use OpenAI's GPT-4
mcphost -m openai/gpt-4
kit -m openai/gpt-4
# Use OpenAI-compatible model with custom URL and API key
mcphost --model openai/<your-model-name> \
kit --model openai/<your-model-name> \
--provider-url <your-base-url> \
--provider-api-key <your-api-key>
```
@@ -776,27 +775,27 @@ mcphost --model openai/<your-model-name> \
#### Non-Interactive Mode
```bash
# Single prompt with full UI
mcphost -p "List files in the current directory"
kit -p "List files in the current directory"
# Compact mode for cleaner output without fancy styling
mcphost -p "List files in the current directory" --compact
kit -p "List files in the current directory" --compact
# Quiet mode for scripting (only AI response output, no UI elements)
mcphost -p "What is the capital of France?" --quiet
kit -p "What is the capital of France?" --quiet
# Use in shell scripts
RESULT=$(mcphost -p "Calculate 15 * 23" --quiet)
RESULT=$(kit -p "Calculate 15 * 23" --quiet)
echo "The answer is: $RESULT"
# Pipe to other commands
mcphost -p "Generate a random UUID" --quiet | tr '[:lower:]' '[:upper:]'
kit -p "Generate a random UUID" --quiet | tr '[:lower:]' '[:upper:]'
```
### Flags
- `--provider-url string`: Base URL for the provider API (applies to OpenAI, Anthropic, Ollama, and Google)
- `--provider-api-key string`: API key for the provider (applies to OpenAI, Anthropic, and Google)
- `--tls-skip-verify`: Skip TLS certificate verification (WARNING: insecure, use only for self-signed certificates)
- `--config string`: Config file location (default is $HOME/.mcphost.yml)
- `--config string`: Config file location (default is $HOME/.kit.yml)
- `--system-prompt string`: system-prompt file location
- `--debug`: Enable debug logging
- `--max-steps int`: Maximum number of agent steps (0 for unlimited, default: 0)
@@ -807,9 +806,9 @@ mcphost -p "Generate a random UUID" --quiet | tr '[:lower:]' '[:upper:]'
- `--stream`: Enable streaming responses (default: true, use `--stream=false` to disable)
### Authentication Subcommands
- `mcphost auth login anthropic`: Authenticate with Anthropic using OAuth (alternative to API keys)
- `mcphost auth logout anthropic`: Remove stored OAuth credentials
- `mcphost auth status`: Show authentication status
- `kit auth login anthropic`: Authenticate with Anthropic using OAuth (alternative to API keys)
- `kit auth logout anthropic`: Remove stored OAuth credentials
- `kit auth status`: Show authentication status
**Note**: OAuth credentials (when present) take precedence over API keys from environment variables and `--provider-api-key` flags.
@@ -822,11 +821,10 @@ mcphost -p "Generate a random UUID" --quiet | tr '[:lower:]' '[:upper:]'
### Configuration File Support
All command-line flags can be configured via the config file. MCPHost will look for configuration in this order:
1. `~/.mcphost.yml` or `~/.mcphost.json` (preferred)
2. `~/.mcp.yml` or `~/.mcp.json` (backwards compatibility)
All command-line flags can be configured via the config file. KIT will look for configuration in this order:
1. `~/.kit.yml` or `~/.kit.json`
Example config file (`~/.mcphost.yml`):
Example config file (`~/.kit.yml`):
```yaml
# MCP Servers - New Simplified Format
mcpServers:
@@ -882,16 +880,16 @@ While chatting, you can use:
### Authentication Commands
Optional OAuth authentication for Anthropic (alternative to API keys):
- `mcphost auth login anthropic`: Authenticate using OAuth
- `mcphost auth logout anthropic`: Remove stored OAuth credentials
- `mcphost auth status`: Show authentication status
- `kit auth login anthropic`: Authenticate using OAuth
- `kit auth logout anthropic`: Remove stored OAuth credentials
- `kit auth status`: Show authentication status
### Global Flags
- `--config`: Specify custom config file location
## Automation & Scripting 🤖
MCPHost's non-interactive mode makes it perfect for automation, scripting, and integration with other tools.
KIT's non-interactive mode makes it perfect for automation, scripting, and integration with other tools.
### Use Cases
@@ -899,11 +897,11 @@ MCPHost's non-interactive mode makes it perfect for automation, scripting, and i
```bash
#!/bin/bash
# Get weather and save to file
mcphost -p "What's the weather in New York?" --quiet > weather.txt
kit -p "What's the weather in New York?" --quiet > weather.txt
# Process files with AI
for file in *.txt; do
summary=$(mcphost -p "Summarize this file: $(cat $file)" --quiet)
summary=$(kit -p "Summarize this file: $(cat $file)" --quiet)
echo "$file: $summary" >> summaries.txt
done
```
@@ -912,27 +910,27 @@ done
```bash
# Code review automation
DIFF=$(git diff HEAD~1)
mcphost -p "Review this code diff and suggest improvements: $DIFF" --quiet
kit -p "Review this code diff and suggest improvements: $DIFF" --quiet
# Generate release notes
COMMITS=$(git log --oneline HEAD~10..HEAD)
mcphost -p "Generate release notes from these commits: $COMMITS" --quiet
kit -p "Generate release notes from these commits: $COMMITS" --quiet
```
#### Data Processing
```bash
# Process CSV data
mcphost -p "Analyze this CSV data and provide insights: $(cat data.csv)" --quiet
kit -p "Analyze this CSV data and provide insights: $(cat data.csv)" --quiet
# Generate reports
mcphost -p "Create a summary report from this JSON: $(cat metrics.json)" --quiet
kit -p "Create a summary report from this JSON: $(cat metrics.json)" --quiet
```
#### API Integration
```bash
# Use as a microservice
curl -X POST http://localhost:8080/process \
-d "$(mcphost -p 'Generate a UUID' --quiet)"
-d "$(kit -p 'Generate a UUID' --quiet)"
```
### Tips for Scripting
@@ -961,12 +959,12 @@ mcpServers:
DEBUG: "${env://DEBUG:-false}"
# Use in scripts
mcphost script my-script.sh --args:username alice
kit script my-script.sh --args:username alice
```
## MCP Server Compatibility 🔌
MCPHost can work with any MCP-compliant server. For examples and reference implementations, see the [MCP Servers Repository](https://github.com/modelcontextprotocol/servers).
KIT can work with any MCP-compliant server. For examples and reference implementations, see the [MCP Servers Repository](https://github.com/modelcontextprotocol/servers).
## Contributing 🤝
+9 -9
View File
@@ -6,7 +6,7 @@ import (
"os"
"strings"
"github.com/mark3labs/mcphost/internal/auth"
"github.com/mark3labs/kit/internal/auth"
"github.com/spf13/cobra"
)
@@ -26,9 +26,9 @@ Available providers:
- anthropic: Anthropic Claude API (OAuth)
Examples:
mcphost auth login anthropic
mcphost auth logout anthropic
mcphost auth status`,
kit auth login anthropic
kit auth logout anthropic
kit auth status`,
}
// authLoginCmd represents the login subcommand for authenticating with AI providers.
@@ -47,7 +47,7 @@ Available providers:
- anthropic: Anthropic Claude API (OAuth)
Example:
mcphost auth login anthropic`,
kit auth login anthropic`,
Args: cobra.ExactArgs(1),
RunE: runAuthLogin,
}
@@ -67,7 +67,7 @@ Available providers:
- anthropic: Anthropic Claude API
Example:
mcphost auth logout anthropic`,
kit auth logout anthropic`,
Args: cobra.ExactArgs(1),
RunE: runAuthLogout,
}
@@ -84,7 +84,7 @@ This command displays which providers have stored credentials and when they were
It does not display the actual API keys for security reasons.
Example:
mcphost auth status`,
kit auth status`,
RunE: runAuthStatus,
}
@@ -157,7 +157,7 @@ func runAuthStatus(cmd *cobra.Command, args []string) error {
}
fmt.Println("\nTo authenticate with a provider:")
fmt.Println(" mcphost auth login anthropic")
fmt.Println(" kit auth login anthropic")
return nil
}
@@ -231,7 +231,7 @@ func loginAnthropic() error {
fmt.Println("✅ Successfully authenticated with Anthropic!")
fmt.Printf("📁 Credentials stored in: %s\n", cm.GetCredentialsPath())
fmt.Println("\n🎉 Your OAuth credentials will now be used for Anthropic API calls.")
fmt.Println("💡 You can check your authentication status with: mcphost auth status")
fmt.Println("💡 You can check your authentication status with: kit auth status")
return nil
}
+17 -17
View File
@@ -5,18 +5,18 @@ import (
"os"
"text/tabwriter"
"github.com/mark3labs/mcphost/internal/hooks"
"github.com/mark3labs/kit/internal/hooks"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
)
// hooksCmd represents the hooks command for managing MCPHost hook configurations.
// hooksCmd represents the hooks command for managing KIT hook configurations.
// Hooks allow users to execute custom scripts or commands at various points
// during MCPHost execution, such as before/after tool use or when prompts are submitted.
// during KIT execution, such as before/after tool use or when prompts are submitted.
var hooksCmd = &cobra.Command{
Use: "hooks",
Short: "Manage MCPHost hooks",
Long: "Commands for managing and testing MCPHost hooks configuration",
Short: "Manage KIT hooks",
Long: "Commands for managing and testing KIT hooks configuration",
}
// hooksListCmd represents the list subcommand for displaying all configured hooks.
@@ -74,7 +74,7 @@ var hooksValidateCmd = &cobra.Command{
}
// hooksInitCmd represents the init subcommand for generating an example hooks configuration.
// It creates a .mcphost/hooks.yml file with sample hook configurations demonstrating
// It creates a .kit/hooks.yml file with sample hook configurations demonstrating
// various hook events and common use cases like logging commands and tool usage.
var hooksInitCmd = &cobra.Command{
Use: "init",
@@ -89,7 +89,7 @@ var hooksInitCmd = &cobra.Command{
Hooks: []hooks.HookEntry{
{
Type: "command",
Command: `mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/mcphost/logs" && jq -r '"[" + (now | strftime("%Y-%m-%d %H:%M:%S")) + "] $ " + .tool_input.command' >> "${XDG_CONFIG_HOME:-$HOME/.config}/mcphost/logs/bash-commands.log"`,
Command: `mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/kit/logs" && jq -r '"[" + (now | strftime("%Y-%m-%d %H:%M:%S")) + "] $ " + .tool_input.command' >> "${XDG_CONFIG_HOME:-$HOME/.config}/kit/logs/bash-commands.log"`,
Timeout: 5,
},
},
@@ -99,7 +99,7 @@ var hooksInitCmd = &cobra.Command{
Hooks: []hooks.HookEntry{
{
Type: "command",
Command: `jq -c '{time: now | strftime("%Y-%m-%d %H:%M:%S"), event: "pre", tool: .tool_name, input: .tool_input}' >> "${XDG_CONFIG_HOME:-$HOME/.config}/mcphost/logs/all-tools.jsonl"`,
Command: `jq -c '{time: now | strftime("%Y-%m-%d %H:%M:%S"), event: "pre", tool: .tool_name, input: .tool_input}' >> "${XDG_CONFIG_HOME:-$HOME/.config}/kit/logs/all-tools.jsonl"`,
Timeout: 5,
},
},
@@ -112,7 +112,7 @@ var hooksInitCmd = &cobra.Command{
Hooks: []hooks.HookEntry{
{
Type: "command",
Command: `jq -c '{time: now | strftime("%Y-%m-%d %H:%M:%S"), cmd: .tool_input.command, exit: .tool_response._meta.exit, stdout: (.tool_response._meta.stdout | rtrimstr("\n") | .[0:100]), stderr: (.tool_response._meta.stderr | rtrimstr("\n"))}' >> "${XDG_CONFIG_HOME:-$HOME/.config}/mcphost/logs/bash-audit.jsonl"`,
Command: `jq -c '{time: now | strftime("%Y-%m-%d %H:%M:%S"), cmd: .tool_input.command, exit: .tool_response._meta.exit, stdout: (.tool_response._meta.stdout | rtrimstr("\n") | .[0:100]), stderr: (.tool_response._meta.stderr | rtrimstr("\n"))}' >> "${XDG_CONFIG_HOME:-$HOME/.config}/kit/logs/bash-audit.jsonl"`,
Timeout: 5,
},
},
@@ -122,7 +122,7 @@ var hooksInitCmd = &cobra.Command{
Hooks: []hooks.HookEntry{
{
Type: "command",
Command: `jq -c '{time: now | strftime("%Y-%m-%d %H:%M:%S"), tool: .tool_name, response_preview: (.tool_response | tostring | .[0:200])}' >> "${XDG_CONFIG_HOME:-$HOME/.config}/mcphost/logs/mcp-tools.jsonl"`,
Command: `jq -c '{time: now | strftime("%Y-%m-%d %H:%M:%S"), tool: .tool_name, response_preview: (.tool_response | tostring | .[0:200])}' >> "${XDG_CONFIG_HOME:-$HOME/.config}/kit/logs/mcp-tools.jsonl"`,
Timeout: 5,
},
},
@@ -134,7 +134,7 @@ var hooksInitCmd = &cobra.Command{
Hooks: []hooks.HookEntry{
{
Type: "command",
Command: `mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/mcphost/logs" && jq -r '"[" + (now | strftime("%Y-%m-%d %H:%M:%S")) + "] " + .prompt' >> "${XDG_CONFIG_HOME:-$HOME/.config}/mcphost/logs/prompts.log"`,
Command: `mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/kit/logs" && jq -r '"[" + (now | strftime("%Y-%m-%d %H:%M:%S")) + "] " + .prompt' >> "${XDG_CONFIG_HOME:-$HOME/.config}/kit/logs/prompts.log"`,
},
},
},
@@ -145,7 +145,7 @@ var hooksInitCmd = &cobra.Command{
Hooks: []hooks.HookEntry{
{
Type: "command",
Command: `jq -r '"[" + (now | strftime("%Y-%m-%d %H:%M:%S")) + "] Session " + .session_id + " stopped"' >> "${XDG_CONFIG_HOME:-$HOME/.config}/mcphost/logs/sessions.log"`,
Command: `jq -r '"[" + (now | strftime("%Y-%m-%d %H:%M:%S")) + "] Session " + .session_id + " stopped"' >> "${XDG_CONFIG_HOME:-$HOME/.config}/kit/logs/sessions.log"`,
},
},
},
@@ -153,9 +153,9 @@ var hooksInitCmd = &cobra.Command{
},
}
// Create .mcphost directory if it doesn't exist
if err := os.MkdirAll(".mcphost", 0755); err != nil {
return fmt.Errorf("creating .mcphost directory: %w", err)
// Create .kit directory if it doesn't exist
if err := os.MkdirAll(".kit", 0755); err != nil {
return fmt.Errorf("creating .kit directory: %w", err)
}
// Write example configuration
@@ -164,11 +164,11 @@ var hooksInitCmd = &cobra.Command{
return fmt.Errorf("marshaling example: %w", err)
}
if err := os.WriteFile(".mcphost/hooks.yml", data, 0644); err != nil {
if err := os.WriteFile(".kit/hooks.yml", data, 0644); err != nil {
return fmt.Errorf("writing example: %w", err)
}
fmt.Println("Created .mcphost/hooks.yml with example configuration")
fmt.Println("Created .kit/hooks.yml with example configuration")
return nil
},
}
+10 -10
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"sort"
"github.com/mark3labs/mcphost/internal/models"
"github.com/mark3labs/kit/internal/models"
"github.com/spf13/cobra"
)
@@ -13,22 +13,22 @@ var modelsAllFlag bool
var modelsCmd = &cobra.Command{
Use: "models [provider]",
Short: "List available models from the model database",
Long: `List models known to mcphost from the models.dev database.
Long: `List models known to kit from the models.dev database.
By default, shows only providers that mcphost can use (native fantasy
By default, shows only providers that kit can use (native fantasy
providers plus openai-compatible auto-routed providers). Use --all
to show every provider in the database.
When a provider name is given, shows only that provider's models.
Note: models not listed here can still be used — the database is
advisory. Run 'mcphost update-models' to refresh.
advisory. Run 'kit update-models' to refresh.
Examples:
mcphost models
mcphost models --all
mcphost models anthropic
mcphost models deepseek`,
kit models
kit models --all
kit models anthropic
kit models deepseek`,
Args: cobra.MaximumNArgs(1),
RunE: runModels,
}
@@ -67,7 +67,7 @@ func printAllProviders(registry *models.ModelsRegistry, showAll bool) error {
}
if len(withModels) == 0 {
fmt.Println("No models in database. Run 'mcphost update-models' to fetch.")
fmt.Println("No models in database. Run 'kit update-models' to fetch.")
return nil
}
@@ -102,7 +102,7 @@ func printAllProviders(registry *models.ModelsRegistry, showAll bool) error {
func printProvider(registry *models.ModelsRegistry, provider string) error {
m, err := registry.GetModelsForProvider(provider)
if err != nil {
return fmt.Errorf("unknown provider %q. Run 'mcphost models' to see all providers", provider)
return fmt.Errorf("unknown provider %q. Run 'kit models' to see all providers", provider)
}
if len(m) == 0 {
+31 -31
View File
@@ -10,11 +10,11 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/fantasy"
"github.com/mark3labs/mcphost/internal/agent"
"github.com/mark3labs/mcphost/internal/app"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/mcphost/internal/session"
"github.com/mark3labs/mcphost/internal/ui"
"github.com/mark3labs/kit/internal/agent"
"github.com/mark3labs/kit/internal/app"
"github.com/mark3labs/kit/internal/config"
"github.com/mark3labs/kit/internal/session"
"github.com/mark3labs/kit/internal/ui"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/term"
@@ -80,13 +80,13 @@ func (a *agentUIAdapter) GetLoadedServerNames() []string {
}
// rootCmd represents the base command when called without any subcommands.
// This is the main entry point for the MCPHost CLI application, providing
// This is the main entry point for the KIT CLI application, providing
// an interface to interact with various AI models through a unified interface
// with support for MCP servers and tool integration.
var rootCmd = &cobra.Command{
Use: "mcphost",
Use: "kit",
Short: "Chat with AI models through a unified interface",
Long: `MCPHost is a CLI tool that allows you to interact with various AI models
Long: `KIT is a CLI tool that allows you to interact with various AI models
through a unified interface. It supports various tools through MCP servers
and provides streaming responses.
@@ -98,41 +98,41 @@ Available models can be specified using the --model flag:
Examples:
# Interactive mode
mcphost -m ollama/qwen2.5:3b
mcphost -m openai/gpt-4
mcphost -m google/gemini-2.0-flash
kit -m ollama/qwen2.5:3b
kit -m openai/gpt-4
kit -m google/gemini-2.0-flash
# Non-interactive mode
mcphost -p "What is the weather like today?"
mcphost -p "Calculate 15 * 23" --quiet
kit -p "What is the weather like today?"
kit -p "Calculate 15 * 23" --quiet
# Session management
mcphost --save-session ./my-session.json -p "Hello"
mcphost --load-session ./my-session.json -p "Continue our conversation"
mcphost --load-session ./session.json --save-session ./session.json -p "Next message"
mcphost --session ./session.json -p "Next message"
kit --save-session ./my-session.json -p "Hello"
kit --load-session ./my-session.json -p "Continue our conversation"
kit --load-session ./session.json --save-session ./session.json -p "Next message"
kit --session ./session.json -p "Next message"
# Script mode
mcphost script myscript.sh`,
kit script myscript.sh`,
RunE: func(cmd *cobra.Command, args []string) error {
return runMCPHost(context.Background())
return runKit(context.Background())
},
}
// GetRootCommand returns the root command with the version set.
// This function is the main entry point for the MCPHost CLI and should be
// This function is the main entry point for the KIT CLI and should be
// called from main.go with the appropriate version string.
func GetRootCommand(v string) *cobra.Command {
rootCmd.Version = v
return rootCmd
}
// InitConfig initializes the configuration for MCPHost by loading config files,
// InitConfig initializes the configuration for KIT by loading config files,
// environment variables, and hooks configuration. It follows this priority order:
// 1. Command-line specified config file (--config flag)
// 2. Current directory config file (.mcphost or .mcp)
// 3. Home directory config file (~/.mcphost or ~/.mcp)
// 4. Environment variables (MCPHOST_* prefix)
// 2. Current directory config file (.kit)
// 3. Home directory config file (~/.kit)
// 4. Environment variables (KIT_* prefix)
// This function is automatically called by cobra before command execution.
func InitConfig() {
if configFile != "" {
@@ -162,7 +162,7 @@ func InitConfig() {
// Try to find and load config file using viper's search mechanism
configLoaded := false
configNames := []string{".mcphost", ".mcp"} // Try .mcphost first, then legacy .mcp
configNames := []string{".kit"}
for _, name := range configNames {
viper.SetConfigName(name)
@@ -192,7 +192,7 @@ func InitConfig() {
}
// Set environment variable prefix
viper.SetEnvPrefix("MCPHOST")
viper.SetEnvPrefix("KIT")
viper.AutomaticEnv()
}
@@ -261,7 +261,7 @@ func init() {
}
rootCmd.PersistentFlags().
StringVar(&configFile, "config", "", "config file (default is $HOME/.mcp.json)")
StringVar(&configFile, "config", "", "config file (default is $HOME/.kit.yml)")
rootCmd.PersistentFlags().
StringVar(&systemPromptFile, "system-prompt", "", "system prompt text or path to text file")
@@ -332,7 +332,7 @@ func init() {
rootCmd.AddCommand(authCmd)
}
func runMCPHost(ctx context.Context) error {
func runKit(ctx context.Context) error {
return runNormalMode(ctx)
}
@@ -538,9 +538,9 @@ func runNormalMode(ctx context.Context) error {
// Set metadata
_ = sessionManager.SetMetadata(session.Metadata{
MCPHostVersion: "dev", // TODO: Get actual version
Provider: parsedProvider,
Model: modelName,
KitVersion: "dev", // TODO: Get actual version
Provider: parsedProvider,
Model: modelName,
})
}
+5 -5
View File
@@ -9,15 +9,15 @@ import (
"regexp"
"strings"
"github.com/mark3labs/mcphost/internal/app"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/mcphost/internal/ui"
"github.com/mark3labs/kit/internal/app"
"github.com/mark3labs/kit/internal/config"
"github.com/mark3labs/kit/internal/ui"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// scriptCmd represents the script command for executing MCPHost script files.
// scriptCmd represents the script command for executing KIT script files.
// Script files can contain YAML frontmatter configuration followed by a prompt,
// allowing for reproducible AI interactions with custom configurations and
// variable substitution support.
@@ -47,7 +47,7 @@ Variables in the script can be substituted using ${variable} syntax.
Variables can have default values using ${variable:-default} syntax.
Pass variables using --args:variable value syntax:
mcphost script myscript.sh --args:directory /tmp --args:name "John"
kit script myscript.sh --args:directory /tmp --args:name "John"
This will replace ${directory} with "/tmp" and ${name} with "John" in the script.
Variables with defaults (${var:-default}) are optional and use the default if not provided.`,
+2 -2
View File
@@ -7,7 +7,7 @@ import (
"strings"
"testing"
"github.com/mark3labs/mcphost/internal/models"
"github.com/mark3labs/kit/internal/models"
)
// TestDeepSeekChatScriptMode tests the regression where deepseek-chat model
@@ -18,7 +18,7 @@ func TestDeepSeekChatScriptMode(t *testing.T) {
tempDir := t.TempDir()
scriptPath := filepath.Join(tempDir, "deepseek-script.sh")
scriptContent := `#!/usr/bin/env -S mcphost script
scriptContent := `#!/usr/bin/env -S kit script
---
model: "openai/deepseek-chat"
provider-url: "https://api.deepseek.com/v1"
+5 -5
View File
@@ -12,7 +12,7 @@ func TestScriptWithEnvAndArgsSubstitution(t *testing.T) {
tempDir := t.TempDir()
scriptPath := filepath.Join(tempDir, "test-script.sh")
scriptContent := `#!/usr/bin/env -S mcphost script
scriptContent := `#!/usr/bin/env -S kit script
---
mcpServers:
github:
@@ -113,7 +113,7 @@ func TestScriptWithMissingRequiredEnvVar(t *testing.T) {
tempDir := t.TempDir()
scriptPath := filepath.Join(tempDir, "test-script.sh")
scriptContent := `#!/usr/bin/env -S mcphost script
scriptContent := `#!/usr/bin/env -S kit script
---
mcpServers:
github:
@@ -150,7 +150,7 @@ func TestScriptWithMissingRequiredArg(t *testing.T) {
tempDir := t.TempDir()
scriptPath := filepath.Join(tempDir, "test-script.sh")
scriptContent := `#!/usr/bin/env -S mcphost script
scriptContent := `#!/usr/bin/env -S kit script
---
mcpServers:
github:
@@ -185,7 +185,7 @@ func TestScriptProcessingOrder(t *testing.T) {
scriptPath := filepath.Join(tempDir, "test-script.sh")
// This script tests that env vars are processed first, then script args
scriptContent := `#!/usr/bin/env -S mcphost script
scriptContent := `#!/usr/bin/env -S kit script
---
mcpServers:
test:
@@ -241,7 +241,7 @@ func TestScriptBackwardCompatibility(t *testing.T) {
tempDir := t.TempDir()
scriptPath := filepath.Join(tempDir, "test-script.sh")
scriptContent := `#!/usr/bin/env -S mcphost script
scriptContent := `#!/usr/bin/env -S kit script
---
mcpServers:
filesystem:
+6 -6
View File
@@ -5,12 +5,12 @@ import (
"fmt"
"strings"
"github.com/mark3labs/mcphost/internal/agent"
"github.com/mark3labs/mcphost/internal/app"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/mcphost/internal/models"
"github.com/mark3labs/mcphost/internal/tools"
"github.com/mark3labs/mcphost/internal/ui"
"github.com/mark3labs/kit/internal/agent"
"github.com/mark3labs/kit/internal/app"
"github.com/mark3labs/kit/internal/config"
"github.com/mark3labs/kit/internal/models"
"github.com/mark3labs/kit/internal/tools"
"github.com/mark3labs/kit/internal/ui"
"github.com/spf13/viper"
)
+7 -7
View File
@@ -11,7 +11,7 @@ import (
"strings"
"time"
"github.com/mark3labs/mcphost/internal/models"
"github.com/mark3labs/kit/internal/models"
"github.com/spf13/cobra"
)
@@ -26,16 +26,16 @@ detection, and model suggestions.
When run without arguments, fetches from models.dev.
Sources:
(none) Fetch from models.dev (or MCPHOST_MODELS_URL override)
(none) Fetch from models.dev (or KIT_MODELS_URL override)
<url> Fetch from a custom URL
<file> Load from a local JSON file
embedded Reset to the built-in database shipped with this binary
Examples:
mcphost update-models
mcphost update-models https://models.dev/api.json
mcphost update-models /path/to/models.json
mcphost update-models embedded`,
kit update-models
kit update-models https://models.dev/api.json
kit update-models /path/to/models.json
kit update-models embedded`,
Args: cobra.MaximumNArgs(1),
RunE: runUpdateModels,
}
@@ -56,7 +56,7 @@ func runUpdateModels(_ *cobra.Command, args []string) error {
case source == "":
url := defaultModelsURL
if override := os.Getenv("MCPHOST_MODELS_URL"); override != "" {
if override := os.Getenv("KIT_MODELS_URL"); override != "" {
url = override
}
fmt.Fprintf(os.Stderr, "Fetching models from %s...\n", url)
+1 -1
View File
@@ -1,4 +1,4 @@
./output/mcphost --model openai:<your-model-name> \
./output/kit --model openai:<your-model-name> \
--openai-url <your-base-url> \
--openai-api-key <your-api-key> \
--config ./conf/demo.json --debug
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/bash
RUN_NAME="mcphost"
RUN_NAME="kit"
mkdir -p output
go build -o output/${RUN_NAME}
+3 -3
View File
@@ -3,12 +3,12 @@ Thanks for your contribution, you can follow these step to run this repo and deb
## Run demo
1. clone this repo to your work dir.
```bash
git clone https://github.com/mark3labs/mcphost.git
git clone https://github.com/mark3labs/kit.git
```
2. enter the `contribute` dir.
```bash
cd mcphost/contribute
cd kit/contribute
```
3. run `build.sh` to build your binary file.
@@ -22,7 +22,7 @@ Thanks for your contribution, you can follow these step to run this repo and deb
vi boost.sh
```
5. run `boost.sh` to run your mcphost, if you don't want run it in debug model, you can delete the `--debug` flag in `boost.sh`.
5. run `boost.sh` to run kit, if you don't want run it in debug model, you can delete the `--debug` flag in `boost.sh`.
```bash
./boost.sh
```
+18 -14
View File
@@ -2,6 +2,7 @@
"""
Monitors MCP tool usage and enforces policies.
"""
import json
import sys
import re
@@ -11,62 +12,65 @@ from datetime import datetime
# Define MCP tool policies
BLOCKED_MCP_TOOLS = [
"mcp__github__delete_.*", # Block all GitHub delete operations
"mcp__aws__.*_production", # Block production AWS operations
"mcp__aws__.*_production", # Block production AWS operations
]
RATE_LIMITS = {
"mcp__openai__.*": (10, 60), # 10 calls per 60 seconds
}
def check_rate_limit(tool_name, limits):
# This is a simplified example - real implementation would need persistent storage
# For now, just log the attempt
return True
def main():
try:
input_data = json.load(sys.stdin)
tool_name = input_data.get('tool_name', '')
tool_name = input_data.get("tool_name", "")
# Check if tool is blocked
for pattern in BLOCKED_MCP_TOOLS:
if re.match(pattern, tool_name):
output = {
"decision": "block",
"reason": f"Tool {tool_name} is blocked by security policy"
"reason": f"Tool {tool_name} is blocked by security policy",
}
print(json.dumps(output))
sys.exit(0)
# Check rate limits
for pattern, (limit, window) in RATE_LIMITS.items():
if re.match(pattern, tool_name):
if not check_rate_limit(tool_name, (limit, window)):
output = {
"decision": "block",
"reason": f"Rate limit exceeded: {limit} calls per {window}s"
"reason": f"Rate limit exceeded: {limit} calls per {window}s",
}
print(json.dumps(output))
sys.exit(0)
# Log MCP tool usage
log_entry = {
"timestamp": datetime.now().isoformat(),
"tool": tool_name,
"input": input_data.get('tool_input', {})
"input": input_data.get("tool_input", {}),
}
# Use XDG_CONFIG_HOME if set, otherwise default to ~/.config
config_home = os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config'))
log_dir = os.path.join(config_home, 'mcphost', 'logs')
config_home = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
log_dir = os.path.join(config_home, "kit", "logs")
os.makedirs(log_dir, exist_ok=True)
with open(os.path.join(log_dir, "mcp-usage.jsonl"), "a") as f:
f.write(json.dumps(log_entry) + "\n")
except Exception as e:
print(f"Hook error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
main()
+1 -1
View File
@@ -10,7 +10,7 @@ prompt=$(echo "$input" | jq -r '.prompt // empty')
if [ -n "$prompt" ]; then
# Use XDG_CONFIG_HOME if set, otherwise default to ~/.config
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}"
LOG_DIR="$CONFIG_DIR/mcphost/logs"
LOG_DIR="$CONFIG_DIR/kit/logs"
# Create log directory if it doesn't exist
mkdir -p "$LOG_DIR"
+10 -10
View File
@@ -1,6 +1,6 @@
# MCPHost Script Examples
# KIT Script Examples
This directory contains example scripts demonstrating various features of MCPHost's script mode.
This directory contains example scripts demonstrating various features of KIT's script mode.
## Scripts
@@ -16,13 +16,13 @@ Demonstrates the new default values feature for script variables.
**Usage:**
```bash
# Use all defaults
mcphost script default-values-demo.sh
kit script default-values-demo.sh
# Override specific variables
mcphost script default-values-demo.sh --args:user_name "John" --args:work_dir "/projects"
kit script default-values-demo.sh --args:user_name "John" --args:work_dir "/projects"
# Override multiple variables
mcphost script default-values-demo.sh \
kit script default-values-demo.sh \
--args:user_name "Alice" \
--args:editor "vim" \
--args:format "json"
@@ -39,20 +39,20 @@ Demonstrates TLS skip verify for connecting to providers with self-signed certif
**Usage:**
```bash
# Run with TLS skip verify enabled (configured in script)
mcphost script tls-test-script.sh
kit script tls-test-script.sh
# Override the provider URL
mcphost script tls-test-script.sh --provider-url https://192.168.1.100:443
kit script tls-test-script.sh --provider-url https://192.168.1.100:443
# Disable TLS skip verify via command line (overrides script config)
mcphost script tls-test-script.sh --tls-skip-verify=false
kit script tls-test-script.sh --tls-skip-verify=false
```
⚠️ **WARNING**: Only use `tls-skip-verify` for development or when connecting to trusted servers with self-signed certificates.
## Variable Syntax Reference
MCPHost scripts support two types of variables:
KIT scripts support two types of variables:
### Required Variables
```bash
@@ -80,4 +80,4 @@ ${variable:-default_value}
## Backward Compatibility
All existing scripts using `${variable}` syntax continue to work unchanged. The new default syntax is purely additive.
All existing scripts using `${variable}` syntax continue to work unchanged. The new default syntax is purely additive.
+3 -3
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env -S mcphost script
#!/usr/bin/env -S kit script
---
# Demo script showcasing default values in MCPHost scripts
# Demo script showcasing default values in KIT scripts
model: "anthropic/claude-sonnet-4-5-20250929"
mcpServers:
filesystem:
@@ -19,7 +19,7 @@ mcpServers:
Hello ${user_name:-Anonymous User}!
This script demonstrates the new default values feature in MCPHost scripts.
This script demonstrates the new default values feature in KIT scripts.
## Your Configuration:
- Working directory: ${work_dir:-/tmp}
+2 -2
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env -S mcphost script
#!/usr/bin/env -S kit script
---
# Example script demonstrating both environment variable and script argument substitution
# Environment variables are processed first, then script arguments
@@ -31,7 +31,7 @@ Working directory is ${env://WORK_DIR:-/tmp}.
# export WORK_DIR="/home/user/projects"
#
# 2. Run with script arguments:
# mcphost script env-substitution-script.sh --args:username alice --args:repo_type private --args:count 5
# kit script env-substitution-script.sh --args:username alice --args:repo_type private --args:count 5
#
# This will:
# - Use GITHUB_TOKEN from environment
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env -S mcphost script
#!/usr/bin/env -S kit script
---
# This script uses the container-use MCP server from https://github.com/dagger/container-use
mcpServers:
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env -S mcphost script
#!/usr/bin/env -S kit script
Hello! This is a simple script that uses the default MCP configuration.
What's 2 + 2?
What tools do you have?
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env -S mcphost script
#!/usr/bin/env -S kit script
---
# Example script demonstrating TLS skip verify for self-signed certificates
model: "ollama/llama3.2"
+1 -1
View File
@@ -1,4 +1,4 @@
module github.com/mark3labs/mcphost
module github.com/mark3labs/kit
go 1.26.0
+4 -4
View File
@@ -9,9 +9,9 @@ import (
"charm.land/fantasy"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/mcphost/internal/models"
"github.com/mark3labs/mcphost/internal/tools"
"github.com/mark3labs/kit/internal/config"
"github.com/mark3labs/kit/internal/models"
"github.com/mark3labs/kit/internal/tools"
)
// AgentConfig holds configuration options for creating a new Agent.
@@ -141,7 +141,7 @@ func (a *Agent) GenerateWithLoop(ctx context.Context, messages []fantasy.Message
// GenerateWithLoopAndStreaming processes messages using the fantasy agent with streaming and callbacks.
// Fantasy handles the tool call loop internally. We map fantasy's rich callback system
// to mcphost's existing callback interface for UI integration.
// to kit's existing callback interface for UI integration.
func (a *Agent) GenerateWithLoopAndStreaming(ctx context.Context, messages []fantasy.Message,
onToolCall ToolCallHandler, onToolExecution ToolExecutionHandler, onToolResult ToolResultHandler,
onResponse ResponseHandler, onToolCallContent ToolCallContentHandler,
+3 -3
View File
@@ -4,9 +4,9 @@ import (
"context"
"fmt"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/mcphost/internal/models"
"github.com/mark3labs/mcphost/internal/tools"
"github.com/mark3labs/kit/internal/config"
"github.com/mark3labs/kit/internal/models"
"github.com/mark3labs/kit/internal/tools"
)
// SpinnerFunc is a function type for showing spinners during agent creation.
+1 -1
View File
@@ -8,7 +8,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/fantasy"
"github.com/mark3labs/mcphost/internal/agent"
"github.com/mark3labs/kit/internal/agent"
)
// App is the application-layer orchestrator. It owns the agentic loop,
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"charm.land/fantasy"
"github.com/mark3labs/mcphost/internal/agent"
"github.com/mark3labs/kit/internal/agent"
)
// --------------------------------------------------------------------------
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"sync"
"charm.land/fantasy"
"github.com/mark3labs/mcphost/internal/session"
"github.com/mark3labs/kit/internal/session"
)
// MessageStore is a thread-safe store for the conversation history. It wraps a
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"testing"
"charm.land/fantasy"
"github.com/mark3labs/mcphost/internal/session"
"github.com/mark3labs/kit/internal/session"
)
// makeTextMsg builds a minimal fantasy.Message with a single TextPart.
+3 -3
View File
@@ -5,9 +5,9 @@ import (
"charm.land/fantasy"
"github.com/mark3labs/mcphost/internal/agent"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/mcphost/internal/session"
"github.com/mark3labs/kit/internal/agent"
"github.com/mark3labs/kit/internal/config"
"github.com/mark3labs/kit/internal/session"
)
// AgentRunner is the minimal interface the app layer requires from the agent
+5 -5
View File
@@ -57,7 +57,7 @@ type CredentialManager struct {
// NewCredentialManager creates a new credential manager instance. It determines
// the appropriate credentials path based on XDG_CONFIG_HOME or falls back to
// ~/.config/.mcphost/credentials.json. Returns an error if the home directory
// ~/.config/.kit/credentials.json. Returns an error if the home directory
// cannot be determined.
func NewCredentialManager() (*CredentialManager, error) {
credentialsPath, err := getCredentialsPath()
@@ -74,16 +74,16 @@ func NewCredentialManager() (*CredentialManager, error) {
func getCredentialsPath() (string, error) {
// Try XDG_CONFIG_HOME first
if xdgConfig := os.Getenv("XDG_CONFIG_HOME"); xdgConfig != "" {
return filepath.Join(xdgConfig, ".mcphost", "credentials.json"), nil
return filepath.Join(xdgConfig, ".kit", "credentials.json"), nil
}
// Fall back to ~/.config/.mcphost/credentials.json
// Fall back to ~/.config/.kit/credentials.json
homeDir, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("failed to get home directory: %w", err)
}
return filepath.Join(homeDir, ".config", ".mcphost", "credentials.json"), nil
return filepath.Join(homeDir, ".config", ".kit", "credentials.json"), nil
}
// LoadCredentials loads credentials from the JSON file. If the file doesn't exist,
@@ -272,5 +272,5 @@ func GetAnthropicAPIKey(flagValue string) (string, string, error) {
return envKey, "ANTHROPIC_API_KEY environment variable", nil
}
return "", "", fmt.Errorf("no Anthropic API key found. Use 'mcphost auth login anthropic', set ANTHROPIC_API_KEY environment variable, or use --provider-api-key flag")
return "", "", fmt.Errorf("no Anthropic API key found. Use 'kit auth login anthropic', set ANTHROPIC_API_KEY environment variable, or use --provider-api-key flag")
}
+3 -3
View File
@@ -8,7 +8,7 @@ import (
func TestCredentialManager(t *testing.T) {
// Create a temporary directory for testing
tempDir, err := os.MkdirTemp("", "mcphost-auth-test")
tempDir, err := os.MkdirTemp("", "kit-auth-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
@@ -125,7 +125,7 @@ func TestValidateAnthropicAPIKey(t *testing.T) {
func TestGetAnthropicAPIKey(t *testing.T) {
// Create a temporary directory for testing
tempDir, err := os.MkdirTemp("", "mcphost-auth-test")
tempDir, err := os.MkdirTemp("", "kit-auth-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
@@ -210,7 +210,7 @@ func TestGetAnthropicAPIKey(t *testing.T) {
func TestCredentialStorePersistence(t *testing.T) {
// Create a temporary directory for testing
tempDir, err := os.MkdirTemp("", "mcphost-auth-test")
tempDir, err := os.MkdirTemp("", "kit-auth-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
+1 -1
View File
@@ -179,7 +179,7 @@ Usage notes:
- It is very helpful if you write a clear, concise description of what this command does in 5-10 words.
- If the output exceeds 30000 characters, output will be truncated before being returned to you.
- VERY IMPORTANT: You MUST avoid using search commands like find and grep. Instead use Grep, Glob, or Task to search. You MUST avoid read tools like cat, head, tail, and ls, and use Read and LS to read files.
- If you _still_ need to run grep, STOP. ALWAYS USE ripgrep at rg (or /usr/bin/rg) first, which all mcphost users have pre-installed.
- If you _still_ need to run grep, STOP. ALWAYS USE ripgrep at rg (or /usr/bin/rg) first, which all kit users have pre-installed.
- When issuing multiple commands, use the ';' or '&&' operator to separate them. DO NOT use newlines (newlines are ok in quoted strings).
- Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of cd. You may use cd if the User explicitly requests it.
<good-example>
+7 -7
View File
@@ -264,16 +264,16 @@ func LoadSystemPrompt(input string) (string, error) {
}
// EnsureConfigExists checks if a config file exists and creates a default one if not.
// It searches for .mcphost.{yml,yaml,json} or legacy .mcp.{yml,yaml,json} files in
// the user's home directory. If none exist, creates a default .mcphost.yml with examples.
// It searches for .kit.{yml,yaml,json} files in the user's home directory.
// If none exist, creates a default .kit.yml with examples.
func EnsureConfigExists() error {
homeDir, err := os.UserHomeDir()
if err != nil {
return fmt.Errorf("error getting home directory: %v", err)
}
// Check for existing config files (new format first, then legacy)
configNames := []string{".mcphost", ".mcp"}
// Check for existing config files
configNames := []string{".kit"}
configTypes := []string{"yml", "yaml", "json"}
for _, configName := range configNames {
@@ -290,9 +290,9 @@ func EnsureConfigExists() error {
return createDefaultConfig(homeDir)
}
// createDefaultConfig creates a default .mcphost.yml file in the user's home directory
// createDefaultConfig creates a default .kit.yml file in the user's home directory
func createDefaultConfig(homeDir string) error {
configPath := filepath.Join(homeDir, ".mcphost.yml")
configPath := filepath.Join(homeDir, ".kit.yml")
// Create the file
file, err := os.Create(configPath)
@@ -302,7 +302,7 @@ func createDefaultConfig(homeDir string) error {
defer func() { _ = file.Close() }()
// Write a comprehensive YAML template with examples
content := `# MCPHost Configuration File
content := `# KIT Configuration File
# All command-line flags can be configured here
# This demonstrates the simplified local/remote/builtin server configuration
+7 -7
View File
@@ -207,7 +207,7 @@ func TestConfig_Validate(t *testing.T) {
func TestEnsureConfigExists(t *testing.T) {
// Create a temporary directory for testing
tempDir, err := os.MkdirTemp("", "mcphost_config_test")
tempDir, err := os.MkdirTemp("", "kit_config_test")
if err != nil {
t.Fatalf("Error creating temp dir: %v", err)
}
@@ -225,7 +225,7 @@ func TestEnsureConfigExists(t *testing.T) {
}
// Verify the config file was created
configPath := filepath.Join(tempDir, ".mcphost.yml")
configPath := filepath.Join(tempDir, ".kit.yml")
if _, err := os.Stat(configPath); os.IsNotExist(err) {
t.Fatalf("Config file was not created at %s", configPath)
}
@@ -240,7 +240,7 @@ func TestEnsureConfigExists(t *testing.T) {
// Verify it contains the expected sections
expectedSections := []string{
"# MCPHost Configuration File",
"# KIT Configuration File",
"mcpServers:",
"# Local MCP servers",
"# Builtin MCP servers",
@@ -437,11 +437,11 @@ func TestMCPServerConfig_RemoteFormatWithHeaders(t *testing.T) {
name: "Legacy remote server with headers",
jsonData: `{
"url": "https://legacy.example.com/mcp",
"headers": ["Content-Type: application/json", "User-Agent: MCPHost/1.0"]
"headers": ["Content-Type: application/json", "User-Agent: KIT/1.0"]
}`,
expectedType: "",
expectedURL: "https://legacy.example.com/mcp",
expectedHeaders: []string{"Content-Type: application/json", "User-Agent: MCPHost/1.0"},
expectedHeaders: []string{"Content-Type: application/json", "User-Agent: KIT/1.0"},
expectedTransport: "sse",
},
{
@@ -558,7 +558,7 @@ func TestMCPServerConfig_HeadersParsing(t *testing.T) {
func TestEnsureConfigExistsWhenFileExists(t *testing.T) {
// Create a temporary directory for testing
tempDir, err := os.MkdirTemp("", "mcphost_config_test")
tempDir, err := os.MkdirTemp("", "kit_config_test")
if err != nil {
t.Fatalf("Error creating temp dir: %v", err)
}
@@ -570,7 +570,7 @@ func TestEnsureConfigExistsWhenFileExists(t *testing.T) {
defer func() { _ = os.Setenv("HOME", oldHome) }()
// Create an existing config file
configPath := filepath.Join(tempDir, ".mcphost.yml")
configPath := filepath.Join(tempDir, ".kit.yml")
existingContent := "# Existing config\nmcpServers:\n test: {}\n"
err = os.WriteFile(configPath, []byte(existingContent), 0644)
if err != nil {
+6 -6
View File
@@ -3,7 +3,7 @@ package hooks
import (
"encoding/json"
"fmt"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/kit/internal/config"
"gopkg.in/yaml.v3"
"os"
"path/filepath"
@@ -35,7 +35,7 @@ type HookEntry struct {
// LoadHooksConfig loads and merges hook configurations from multiple sources.
// It searches for hooks.{json,yml} files in standard locations (XDG config directory,
// local .mcphost directory) and any custom paths provided. Configurations are merged
// local .kit directory) and any custom paths provided. Configurations are merged
// with later sources taking precedence. Environment variable substitution is applied
// to all loaded configurations.
func LoadHooksConfig(customPaths ...string) (*HookConfig, error) {
@@ -44,10 +44,10 @@ func LoadHooksConfig(customPaths ...string) (*HookConfig, error) {
// Define search paths in order of precedence (lowest to highest)
searchPaths := []string{
filepath.Join(configDir, "mcphost", "hooks.json"),
filepath.Join(configDir, "mcphost", "hooks.yml"),
".mcphost/hooks.json",
".mcphost/hooks.yml",
filepath.Join(configDir, "kit", "hooks.json"),
filepath.Join(configDir, "kit", "hooks.yml"),
".kit/hooks.json",
".kit/hooks.yml",
}
// Add custom paths with highest precedence
+1 -1
View File
@@ -1,6 +1,6 @@
package hooks
// HookEvent represents a point in MCPHost's lifecycle where hooks can be executed.
// HookEvent represents a point in KIT's lifecycle where hooks can be executed.
// Events can be tool-related (requiring matchers) or lifecycle-related.
type HookEvent string
+1 -1
View File
@@ -12,7 +12,7 @@ import (
"time"
)
// Executor handles hook execution for MCPHost lifecycle events. It manages
// Executor handles hook execution for KIT lifecycle events. It manages
// hook configuration, executes matching hooks in parallel, and processes
// their outputs to determine application behavior.
type Executor struct {
+1 -1
View File
@@ -55,7 +55,7 @@ type StopInput struct {
Meta json.RawMessage `json:"meta,omitempty"` // Additional metadata (e.g., token usage, model info)
}
// HookOutput represents the JSON output from a hook that controls MCPHost behavior.
// HookOutput represents the JSON output from a hook that controls KIT behavior.
// Hooks can decide whether to continue execution, provide reasons for stopping,
// suppress output, or block tool execution. The Decision field can be "approve",
// "block", or empty (default behavior).
+1 -1
View File
@@ -13,7 +13,7 @@ hooks:
UserPromptSubmit:
- hooks:
- type: command
command: "date >> /tmp/mcphost-prompts.log"
command: "date >> /tmp/kit-prompts.log"
PostToolUse:
- matcher: ".*"
hooks:
+6 -6
View File
@@ -17,18 +17,18 @@ type cacheEnvelope struct {
Providers map[string]modelsDBProvider `json:"providers"`
}
// dataDir returns the mcphost data directory following XDG Base Directory spec.
// dataDir returns the kit data directory following XDG Base Directory spec.
//
// Linux/macOS: $XDG_DATA_HOME/mcphost (default ~/.local/share/mcphost)
// Windows: %LOCALAPPDATA%/mcphost
// Linux/macOS: $XDG_DATA_HOME/kit (default ~/.local/share/kit)
// Windows: %LOCALAPPDATA%/kit
func dataDir() (string, error) {
if xdg := os.Getenv("XDG_DATA_HOME"); xdg != "" {
return filepath.Join(xdg, "mcphost"), nil
return filepath.Join(xdg, "kit"), nil
}
if runtime.GOOS == "windows" {
if local := os.Getenv("LOCALAPPDATA"); local != "" {
return filepath.Join(local, "mcphost"), nil
return filepath.Join(local, "kit"), nil
}
}
@@ -36,7 +36,7 @@ func dataDir() (string, error) {
if err != nil {
return "", fmt.Errorf("cannot determine home directory: %w", err)
}
return filepath.Join(home, ".local", "share", "mcphost"), nil
return filepath.Join(home, ".local", "share", "kit"), nil
}
// cachePath returns the full path to the cache file.
+3 -3
View File
@@ -23,8 +23,8 @@ import (
"charm.land/fantasy/providers/openrouter"
"charm.land/fantasy/providers/vercel"
"github.com/mark3labs/mcphost/internal/auth"
"github.com/mark3labs/mcphost/internal/ui/progress"
"github.com/mark3labs/kit/internal/auth"
"github.com/mark3labs/kit/internal/ui/progress"
)
const (
@@ -353,7 +353,7 @@ func createAnthropicProvider(ctx context.Context, config *ProviderConfig, modelN
return nil, err
}
if os.Getenv("DEBUG") != "" || os.Getenv("MCPHOST_DEBUG") != "" {
if os.Getenv("DEBUG") != "" || os.Getenv("KIT_DEBUG") != "" {
fmt.Fprintf(os.Stderr, "Using Anthropic API key from: %s\n", source)
}
+1 -1
View File
@@ -64,7 +64,7 @@ func NewModelsRegistry() *ModelsRegistry {
// buildFromModelsDB converts models.dev provider data into our internal format.
// It tries the on-disk cache first and falls back to the embedded database.
func buildFromModelsDB() map[string]ProviderInfo {
// Try cached data first (from `mcphost update-models`)
// Try cached data first (from `kit update-models`)
dbProviders, _ := LoadCachedProviders()
if len(dbProviders) == 0 {
// Fall back to compile-time embedded data
+2 -2
View File
@@ -32,8 +32,8 @@ type Session struct {
// Metadata contains session metadata that provides context about the
// environment and configuration used during the conversation.
type Metadata struct {
// MCPHostVersion is the version of MCPHost used for this session
MCPHostVersion string `json:"mcphost_version"`
// KitVersion is the version of KIT used for this session
KitVersion string `json:"kit_version"`
// Provider is the LLM provider used (e.g., "anthropic", "openai", "gemini")
Provider string `json:"provider"`
// Model is the specific model identifier used for the conversation
+4 -4
View File
@@ -9,11 +9,11 @@ import (
"time"
"charm.land/fantasy"
"github.com/mark3labs/kit/internal/builtin"
"github.com/mark3labs/kit/internal/config"
"github.com/mark3labs/mcp-go/client"
"github.com/mark3labs/mcp-go/client/transport"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcphost/internal/builtin"
"github.com/mark3labs/mcphost/internal/config"
)
// ConnectionPoolConfig defines configuration parameters for the MCP connection pool.
@@ -396,7 +396,7 @@ func (p *MCPConnectionPool) initializeClient(ctx context.Context, client client.
initRequest := mcp.InitializeRequest{}
initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
initRequest.Params.ClientInfo = mcp.Implementation{
Name: "mcphost",
Name: "kit",
Version: "1.0.0",
}
initRequest.Params.Capabilities = mcp.ClientCapabilities{}
@@ -513,7 +513,7 @@ func (p *MCPConnectionPool) GetConnectionStats() map[string]any {
}
// ServerName returns the server name associated with this MCP connection.
// This is the configured name from the MCPHost configuration, not necessarily
// This is the configured name from the KIT configuration, not necessarily
// the actual server implementation name.
func (c *MCPConnection) ServerName() string {
return c.serverName
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"charm.land/fantasy"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/kit/internal/config"
)
// MCPToolManager manages MCP (Model Context Protocol) tools and clients across multiple servers.
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"testing"
"time"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/kit/internal/config"
)
func TestMCPToolManager_LoadTools_WithTimeout(t *testing.T) {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"testing"
tea "charm.land/bubbletea/v2"
"github.com/mark3labs/mcphost/internal/app"
"github.com/mark3labs/kit/internal/app"
)
// ==========================================================================
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"golang.org/x/term"
)
// CLI manages the command-line interface for MCPHost, providing message rendering,
// CLI manages the command-line interface for KIT, providing message rendering,
// user input handling, and display management. It supports both standard and compact
// display modes, handles streaming responses, tracks token usage, and manages the
// overall conversation flow between the user and AI assistants.
+1 -1
View File
@@ -67,7 +67,7 @@ type Theme struct {
Highlight color.Color
}
// DefaultTheme creates and returns the default MCPHost theme based on the Catppuccin
// DefaultTheme creates and returns the default KIT theme based on the Catppuccin
// Mocha (dark) and Latte (light) color palettes. This theme provides a cohesive,
// pleasant visual experience with carefully selected colors for different UI elements.
func DefaultTheme() Theme {
+1 -1
View File
@@ -6,7 +6,7 @@ import (
tea "charm.land/bubbletea/v2"
"github.com/mark3labs/mcphost/internal/app"
"github.com/mark3labs/kit/internal/app"
)
// CLIEventHandler routes app-layer events to CLI display methods for
+2 -2
View File
@@ -4,8 +4,8 @@ import (
"fmt"
"strings"
"github.com/mark3labs/mcphost/internal/auth"
"github.com/mark3labs/mcphost/internal/models"
"github.com/mark3labs/kit/internal/auth"
"github.com/mark3labs/kit/internal/models"
)
// AgentInterface defines the minimal interface required from the agent package
+8 -8
View File
@@ -19,7 +19,7 @@ const (
AssistantMessage
ToolMessage
ToolCallMessage // New type for showing tool calls in progress
SystemMessage // New type for MCPHost system messages (help, tools, etc.)
SystemMessage // New type for KIT system messages (help, tools, etc.)
ErrorMessage // New type for error messages
)
@@ -171,9 +171,9 @@ func (r *MessageRenderer) RenderAssistantMessage(content string, timestamp time.
}
}
// RenderSystemMessage renders MCPHost system messages such as help text, command outputs,
// RenderSystemMessage renders KIT system messages such as help text, command outputs,
// and informational notifications. These messages are displayed with a distinctive system
// color border and "MCPHost System" label to differentiate them from user and AI content.
// color border and "KIT System" label to differentiate them from user and AI content.
func (r *MessageRenderer) RenderSystemMessage(content string, timestamp time.Time) UIMessage {
// Format timestamp
timeStr := timestamp.Local().Format("15:04")
@@ -192,7 +192,7 @@ func (r *MessageRenderer) RenderSystemMessage(content string, timestamp time.Tim
}
// Create info line
info := fmt.Sprintf(" MCPHost System (%s)", timeStr)
info := fmt.Sprintf(" KIT System (%s)", timeStr)
// Combine content and info
fullContent := strings.TrimSuffix(messageContent, "\n") + "\n" +
@@ -260,7 +260,7 @@ func (r *MessageRenderer) RenderDebugMessage(message string, timestamp time.Time
info := baseStyle.
Width(r.width - 5). // Account for margins and padding
Foreground(theme.Muted).
Render(fmt.Sprintf(" MCPHost (%s)", timeStr))
Render(fmt.Sprintf(" KIT (%s)", timeStr))
// Combine all parts
fullContent := lipgloss.JoinVertical(lipgloss.Left,
@@ -316,7 +316,7 @@ func (r *MessageRenderer) RenderDebugConfigMessage(config map[string]any, timest
info := baseStyle.
Width(r.width - 1).
Foreground(theme.Muted).
Render(fmt.Sprintf(" MCPHost (%s)", timeStr))
Render(fmt.Sprintf(" KIT (%s)", timeStr))
// Combine parts
parts := []string{header}
@@ -751,7 +751,7 @@ func (c *MessageContainer) renderEmptyState() string {
title := baseStyle.
Foreground(theme.System).
Bold(true).
Render("MCPHost")
Render("KIT")
// Subtitle with better typography
subtitle := baseStyle.
@@ -824,7 +824,7 @@ func (c *MessageContainer) renderCompactEmptyState() string {
welcome := lipgloss.NewStyle().
Foreground(theme.System).
Bold(true).
Render("MCPHost - AI Assistant with MCP Tools")
Render("KIT - AI Assistant with MCP Tools")
help := lipgloss.NewStyle().
Foreground(theme.Muted).
+1 -1
View File
@@ -7,7 +7,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
"github.com/mark3labs/mcphost/internal/app"
"github.com/mark3labs/kit/internal/app"
)
// appState represents the current state of the parent TUI model.
+1 -1
View File
@@ -6,7 +6,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/fantasy"
"github.com/mark3labs/mcphost/internal/app"
"github.com/mark3labs/kit/internal/app"
)
// --------------------------------------------------------------------------
+1 -1
View File
@@ -6,7 +6,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
"github.com/mark3labs/mcphost/internal/app"
"github.com/mark3labs/kit/internal/app"
)
// knightRiderFrames generates a KITT-style scanning animation where a bright
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"charm.land/lipgloss/v2"
"github.com/charmbracelet/glamour"
"github.com/charmbracelet/glamour/ansi"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/kit/internal/config"
"github.com/spf13/viper"
)
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"charm.land/lipgloss/v2"
"image/color"
"github.com/mark3labs/mcphost/internal/models"
"github.com/mark3labs/kit/internal/models"
)
// UsageStats encapsulates detailed token usage and cost breakdown for a single
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"strings"
"testing"
"github.com/mark3labs/mcphost/internal/models"
"github.com/mark3labs/kit/internal/models"
)
// stripAnsi removes ANSI escape codes from a string for test comparisons.
+1 -1
View File
@@ -3,7 +3,7 @@ package ui
import (
"testing"
"github.com/mark3labs/mcphost/internal/models"
"github.com/mark3labs/kit/internal/models"
)
func TestUsageTracker_OAuthCosts(t *testing.T) {
+2 -2
View File
@@ -6,7 +6,7 @@ import (
"os"
"github.com/charmbracelet/fang"
"github.com/mark3labs/mcphost/cmd"
"github.com/mark3labs/kit/cmd"
)
var version = "dev"
@@ -14,7 +14,7 @@ var version = "dev"
func main() {
for _, arg := range os.Args[1:] {
if arg == "--version" || arg == "-v" {
fmt.Printf("mcphost version %s\n", version)
fmt.Printf("kit version %s\n", version)
os.Exit(0)
}
}
+11 -11
View File
@@ -1,11 +1,11 @@
# MCPHost SDK
# KIT SDK
The MCPHost SDK allows you to use MCPHost programmatically from Go applications without spawning OS processes.
The KIT SDK allows you to use KIT programmatically from Go applications without spawning OS processes.
## Installation
```bash
go get github.com/mark3labs/mcphost
go get github.com/mark3labs/kit
```
## Basic Usage
@@ -18,13 +18,13 @@ import (
"fmt"
"log"
"github.com/mark3labs/mcphost/sdk"
"github.com/mark3labs/kit/sdk"
)
func main() {
ctx := context.Background()
// Create MCPHost instance with default configuration
// Create Kit instance with default configuration
host, err := sdk.New(ctx, nil)
if err != nil {
log.Fatal(err)
@@ -44,9 +44,9 @@ func main() {
## Configuration
The SDK behaves identically to the CLI:
- Loads configuration from `~/.mcphost.yml` by default
- Loads configuration from `~/.kit.yml` by default
- Creates default configuration if none exists
- Respects all environment variables (`MCPHOST_*`)
- Respects all environment variables (`KIT_*`)
- Uses the same defaults as the CLI
### Options
@@ -116,14 +116,14 @@ host.ClearSession()
### Types
- `MCPHost` - Main SDK type
- `Kit` - Main SDK type
- `Options` - Configuration options
- `Message` - Conversation message
- `ToolCall` - Tool invocation details
### Methods
- `New(ctx, opts)` - Create new MCPHost instance
- `New(ctx, opts)` - Create new Kit instance
- `Prompt(ctx, message)` - Send message and get response
- `PromptWithCallbacks(ctx, message, ...)` - Send message with progress callbacks
- `LoadSession(path)` - Load session from file
@@ -137,7 +137,7 @@ host.ClearSession()
All CLI environment variables work with the SDK:
- `MCPHOST_MODEL` - Override model
- `KIT_MODEL` - Override model
- `ANTHROPIC_API_KEY` - Anthropic API key
- `OPENAI_API_KEY` - OpenAI API key
- `GEMINI_API_KEY` - Google API key
@@ -145,4 +145,4 @@ All CLI environment variables work with the SDK:
## License
Same as MCPHost CLI
Same as KIT CLI
+2 -2
View File
@@ -5,13 +5,13 @@ import (
"fmt"
"log"
"github.com/mark3labs/mcphost/sdk"
"github.com/mark3labs/kit/sdk"
)
func main() {
ctx := context.Background()
// Example 1: Use all defaults (loads ~/.mcphost.yml)
// Example 1: Use all defaults (loads ~/.kit.yml)
fmt.Println("=== Example 1: Default configuration ===")
host, err := sdk.New(ctx, nil)
if err != nil {
+2 -2
View File
@@ -6,13 +6,13 @@ import (
"log"
"os"
"github.com/mark3labs/mcphost/sdk"
"github.com/mark3labs/kit/sdk"
)
func main() {
ctx := context.Background()
// Create MCPHost with environment variable for API key
// Create Kit with environment variable for API key
// Expects ANTHROPIC_API_KEY or appropriate provider key to be set
host, err := sdk.New(ctx, &sdk.Options{
Quiet: true, // Suppress debug output for scripting
+19 -19
View File
@@ -5,23 +5,23 @@ import (
"fmt"
"charm.land/fantasy"
"github.com/mark3labs/mcphost/cmd"
"github.com/mark3labs/mcphost/internal/agent"
"github.com/mark3labs/mcphost/internal/config"
"github.com/mark3labs/mcphost/internal/session"
"github.com/mark3labs/kit/cmd"
"github.com/mark3labs/kit/internal/agent"
"github.com/mark3labs/kit/internal/config"
"github.com/mark3labs/kit/internal/session"
"github.com/spf13/viper"
)
// MCPHost provides programmatic access to mcphost functionality, allowing
// Kit provides programmatic access to kit functionality, allowing
// integration of MCP tools and LLM interactions into Go applications. It manages
// agents, sessions, and model configurations.
type MCPHost struct {
type Kit struct {
agent *agent.Agent
sessionMgr *session.Manager
modelString string
}
// Options configures MCPHost creation with optional overrides for model,
// Options configures Kit creation with optional overrides for model,
// prompts, configuration, and behavior settings. All fields are optional
// and will use CLI defaults if not specified.
type Options struct {
@@ -33,10 +33,10 @@ type Options struct {
Quiet bool // Suppress debug output
}
// New creates an MCPHost instance using the same initialization as the CLI.
// New creates a Kit instance using the same initialization as the CLI.
// It loads configuration, initializes MCP servers, creates the LLM model, and
// sets up the agent for interaction. Returns an error if initialization fails.
func New(ctx context.Context, opts *Options) (*MCPHost, error) {
func New(ctx context.Context, opts *Options) (*Kit, error) {
if opts == nil {
opts = &Options{}
}
@@ -83,7 +83,7 @@ func New(ctx context.Context, opts *Options) (*MCPHost, error) {
// Create session manager
sessionMgr := session.NewManager("")
return &MCPHost{
return &Kit{
agent: a,
sessionMgr: sessionMgr,
modelString: viper.GetString("model"),
@@ -93,7 +93,7 @@ func New(ctx context.Context, opts *Options) (*MCPHost, error) {
// Prompt sends a message to the agent and returns the response. The agent may
// use tools as needed to generate the response. The conversation history is
// automatically maintained in the session. Returns an error if generation fails.
func (m *MCPHost) Prompt(ctx context.Context, message string) (string, error) {
func (m *Kit) Prompt(ctx context.Context, message string) (string, error) {
// Get messages from session
messages := m.sessionMgr.GetMessages()
@@ -124,7 +124,7 @@ func (m *MCPHost) Prompt(ctx context.Context, message string) (string, error) {
// PromptWithCallbacks sends a message with callbacks for monitoring tool execution
// and streaming responses. The callbacks allow real-time observation of tool calls,
// results, and response generation. Returns the final response or an error.
func (m *MCPHost) PromptWithCallbacks(
func (m *Kit) PromptWithCallbacks(
ctx context.Context,
message string,
onToolCall func(name, args string),
@@ -161,13 +161,13 @@ func (m *MCPHost) PromptWithCallbacks(
// GetSessionManager returns the current session manager for direct access
// to conversation history and session manipulation.
func (m *MCPHost) GetSessionManager() *session.Manager {
func (m *Kit) GetSessionManager() *session.Manager {
return m.sessionMgr
}
// LoadSession loads a previously saved session from a file, restoring the
// conversation history. Returns an error if the file cannot be loaded or parsed.
func (m *MCPHost) LoadSession(path string) error {
func (m *Kit) LoadSession(path string) error {
s, err := session.LoadFromFile(path)
if err != nil {
return err
@@ -178,25 +178,25 @@ func (m *MCPHost) LoadSession(path string) error {
// SaveSession saves the current session to a file for later restoration.
// Returns an error if the session cannot be written to the specified path.
func (m *MCPHost) SaveSession(path string) error {
func (m *Kit) SaveSession(path string) error {
return m.sessionMgr.GetSession().SaveToFile(path)
}
// ClearSession clears the current session history, starting a new conversation
// with an empty message history.
func (m *MCPHost) ClearSession() {
func (m *Kit) ClearSession() {
m.sessionMgr = session.NewManager("")
}
// GetModelString returns the current model string identifier (e.g.,
// "anthropic/claude-sonnet-4-5-20250929" or "openai/gpt-4") being used by the agent.
func (m *MCPHost) GetModelString() string {
func (m *Kit) GetModelString() string {
return m.modelString
}
// Close cleans up resources including MCP server connections and model resources.
// Should be called when the MCPHost instance is no longer needed. Returns an
// Should be called when the Kit instance is no longer needed. Returns an
// error if cleanup fails.
func (m *MCPHost) Close() error {
func (m *Kit) Close() error {
return m.agent.Close()
}
+4 -4
View File
@@ -5,7 +5,7 @@ import (
"os"
"testing"
"github.com/mark3labs/mcphost/sdk"
"github.com/mark3labs/kit/sdk"
)
func TestNew(t *testing.T) {
@@ -18,7 +18,7 @@ func TestNew(t *testing.T) {
// Test default initialization
host, err := sdk.New(ctx, nil)
if err != nil {
t.Fatalf("Failed to create MCPHost with defaults: %v", err)
t.Fatalf("Failed to create Kit with defaults: %v", err)
}
defer func() { _ = host.Close() }()
@@ -42,7 +42,7 @@ func TestNewWithOptions(t *testing.T) {
host, err := sdk.New(ctx, opts)
if err != nil {
t.Fatalf("Failed to create MCPHost with options: %v", err)
t.Fatalf("Failed to create Kit with options: %v", err)
}
defer func() { _ = host.Close() }()
@@ -60,7 +60,7 @@ func TestSessionManagement(t *testing.T) {
host, err := sdk.New(ctx, &sdk.Options{Quiet: true})
if err != nil {
t.Fatalf("Failed to create MCPHost: %v", err)
t.Fatalf("Failed to create Kit: %v", err)
}
defer func() { _ = host.Close() }()
+1 -1
View File
@@ -2,7 +2,7 @@ package sdk
import (
"charm.land/fantasy"
"github.com/mark3labs/mcphost/internal/session"
"github.com/mark3labs/kit/internal/session"
)
// Message is an alias for session.Message providing SDK users with access
+3 -3
View File
@@ -8,7 +8,7 @@ New capabilities: message queueing during streaming, double-tap ESC cancellation
## User Story
As an MCPHost user, I want the TUI to remain responsive during agent streaming so I can queue follow-up messages, cancel in-progress work, and see a persistent input area -- instead of waiting for each response to complete before typing.
As a KIT user, I want the TUI to remain responsive during agent streaming so I can queue follow-up messages, cancel in-progress work, and see a persistent input area -- instead of waiting for each response to complete before typing.
As a developer, I want the TUI architecture to follow Bubble Tea's idiomatic child-model pattern so components are composable, testable, and extensible without terminal ownership conflicts.
@@ -381,7 +381,7 @@ printResult(result)
assistant (claude-sonnet-4-20250514)
Let me check the build first.
⚙ bash: go build -o output/mcphost
⚙ bash: go build -o output/kit
◇◇◇◆◇◇◇ Executing...
─────────────────────────────────── 2 queued
@@ -395,7 +395,7 @@ printResult(result)
I need to run a command to check the build.
┌─ Tool Approval ──────────────────────┐
│ bash: go build -o output/mcphost
│ bash: go build -o output/kit
│ │
│ [Yes] No │
└──────────────────────────────────────┘