Progressive Disclosure CLI for Model Context Protocol Servers
A cross-platform command-line tool that enables AI assistants to interact with Model Context Protocol (MCP) servers through shell access, solving the fundamental problem of context pollution in LLM tool architectures.
Traditional MCP integrations load all tool definitions upfront, polluting the LLM's context with irrelevant information:
- Token Bloat: 100+ tools can consume 20-50K tokens
- Attention Degradation: Transformers can't truly ignore irrelevant context
- Reduced Quality: Model performance degrades with unnecessary information
MCP CLI implements lazy loading of tool schemas:
# Traditional approach: Load everything (35,000 tokens)
❌ Load all 125 tools from 6 servers upfront
# MCP CLI approach: Load only what's needed (350 tokens)
✅ mcp discover "read a file" # ~300 tokens (intelligent search)
✅ mcp tools schema filesystem read_file # ~200 tokens (just-in-time)
✅ mcp tools exec filesystem read_file --args '{"path": "README.md"}'
# OR: Step-by-step discovery
✅ mcp servers list --names-only # ~50 tokens
✅ mcp tools list filesystem --names-only # ~100 tokens
✅ mcp tools schema filesystem read_file # ~200 tokensResult: 99% reduction in context pollution, measurably better reasoning quality.
- Progressive Disclosure: Default to minimal output, escalate only when needed
- Cross-Platform: Works on Windows, macOS, and Linux
- AI Platform Agnostic: Works with Claude, ChatGPT, GitHub Copilot, or any custom agent
- Multiple Transports: Supports stdio, SSE, and HTTP MCP servers
- JSON Output: Consistent, parseable responses for AI assistants
- Context-Aware: Includes token estimates in all responses
- User-Friendly Errors: Suggestions for self-correction
Deno (recommended):
deno install -g -A -n mcp jsr:@cosmic/mcp-clinpm:
npx jsr:@cosmic/mcp-cliStandalone binary: Download from releases
# Initialize MCP configuration
mcp servers init # Create global config at ~/.mcp-cli/config.json
mcp servers init --local # Create local config at ./.mcp-cli.json
mcp servers init --path ./my-config.json # Create config at custom path
# Add a server
mcp servers add filesystem --type stdio \
--command npx \
--args "-y" "@modelcontextprotocol/server-filesystem" "/path/to/allowed/directory"
# List servers (minimal)
mcp servers list --names-only
# List tools (minimal - default)
mcp tools list filesystem --names-only
# Get specific tool schema (just-in-time)
mcp tools schema filesystem read_file
# Execute a tool
mcp tools exec filesystem read_file --args '{"path": "README.md"}'
# Intelligent discovery (recommended for AI agents)
mcp discover # List all servers with capabilities
mcp discover "read and write files" # Search + recommendations + suggested batch
# Search across all servers
mcp search "file operations"The CLI implements a three-tier disclosure pattern:
# Get server names (~50 tokens)
mcp servers list --names-only
# ["filesystem", "github", "slack"]
# Get tool names (~100-200 tokens)
mcp tools list github --names-only
# ["create_issue", "get_issue", "update_issue", ...]# Get tool descriptions (~500-1000 tokens)
mcp tools list github --brief
# [{"name": "create_issue", "description": "Create a new GitHub issue"}, ...]# Load complete schema when about to use (~200-500 tokens per tool)
mcp tools schema github create_issue
# {"name": "create_issue", "inputSchema": {...}}MCP CLI supports both global and project-specific configurations with automatic discovery:
Priority order (highest to lowest):
- --config flag:
mcp --config ./custom.json servers list - MCP_CONFIG env var:
MCP_CONFIG=./custom.json mcp servers list - Local config:
.mcp-cli.jsonin current directory - Parent search: Walks up directory tree to find
.mcp-cli.json - Global config:
~/.mcp-cli/config.json(or platform-specific location)
Default global config locations:
- Windows:
%USERPROFILE%\.mcp-cli\config.json - macOS/Linux:
~/.mcp-cli/config.json - Linux (XDG):
$XDG_CONFIG_HOME/mcp-cli/config.json
Create a new config file with default settings:
# Create global config
mcp servers init
# Create local project config
mcp servers init --local
# Create config at custom path
mcp servers init --path ./configs/mcp.json
# Overwrite existing config
mcp servers init --force{
"servers": {
"filesystem": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"],
"enabled": true
},
"github": {
"type": "sse",
"url": "http://localhost:3000/sse",
"apiKey": "${GITHUB_TOKEN}",
"enabled": true
}
},
"preferences": {
"defaultTimeout": 30000,
"cacheSchemas": true,
"cacheTTL": 300
}
}Environment variables are supported with ${VAR_NAME} syntax.
Global config for personal tools:
mcp servers init
mcp servers add my-tool --type stdio --command my-global-toolProject-specific config (committed to git):
cd my-project
mcp servers init --local
mcp servers add project-db --type stdio --command ./scripts/db-tool.sh
git add .mcp-cli.jsonTemporary config override:
MCP_CONFIG=./test-config.json mcp tools list test-servermcp servers init [--local] [--path <path>] [--force]- Initialize config filemcp servers list [--names-only] [--full]- List serversmcp servers add <name> --type <stdio|sse|http>- Add servermcp servers remove <name>- Remove servermcp servers test <name>- Test connectionmcp servers info <name>- Get detailed infomcp inspect <name>- Get capabilities summary
mcp tools list <server> [--names-only] [--brief] [--full]- List toolsmcp tools schema <server> <tool...>- Get tool schema(s)mcp tools exec <server> <tool> --args <json>- Execute toolmcp tools batch <server> --operations <json> [--transactional]- Execute multiple tools sequentiallymcp tools search <server> <query>- Search tools
mcp resources list <server> [--names-only]- List resourcesmcp resources read <server> <uri>- Read resourcemcp resources schema <server> <uri>- Get resource metadatamcp resources search <server> <pattern>- Search resources
mcp prompts list <server> [--names-only]- List promptsmcp prompts schema <server> <prompt>- Get prompt schemamcp prompts get <server> <prompt> [--args <json>]- Get prompt
mcp discover [query]- Unified discovery - List servers OR search with intelligent recommendationsmcp search <query> [--detailed]- Search across all serversmcp recommend <task-description>- Get tool recommendations
# Recommended: Use discover command for intelligent tool finding
discovery = bash_tool('mcp discover "read and write files"')
# Returns: servers, matches, suggested_batch
# Option 1: Execute suggested batch (if available)
if discovery.suggested_batch:
result = bash_tool(f'mcp tools batch {server} --operations \'{operations}\'')
# Option 2: Step-by-step discovery
servers = bash_tool('mcp servers list --names-only')
tools = bash_tool('mcp tools list filesystem --names-only')
schema = bash_tool('mcp tools schema filesystem read_file')
result = bash_tool('mcp tools exec filesystem read_file --args \'{"path": "file.txt"}\'')import subprocess
import json
result = subprocess.run(
['mcp', 'servers', 'list', '--names-only'],
capture_output=True,
text=True
)
servers = json.loads(result.stdout)const { exec } = require("child_process");
const { promisify } = require("util");
const execAsync = promisify(exec);
const { stdout } = await execAsync("mcp servers list --names-only");
const result = JSON.parse(stdout);All commands output JSON:
Success:
{
"success": true,
"data": { ... },
"metadata": {
"server": "filesystem",
"timestamp": "2025-11-08T12:00:00Z",
"executionTime": 145,
"tokensEstimate": 250,
"resultSize": "small"
}
}Error:
{
"success": false,
"error": {
"code": "TOOL_NOT_FOUND",
"message": "Tool 'invalid' not found on server 'filesystem'",
"suggestion": "Try: mcp tools list filesystem --names-only",
"similar": ["read_file", "write_file"]
}
}# Run from source
deno task dev servers list --names-only
# Run tests
deno task test
# Lint and format
deno task lint
deno task fmt
# Type check
deno task check
# Compile binaries
deno task compileThe CLI follows clean architecture principles:
src/
├── types/ # TypeScript type definitions
├── utils/ # Cross-platform utilities
├── config/ # Configuration management
├── client/ # MCP client implementations
├── commands/ # Command handlers
├── cli.ts # CLI entry point
└── mod.ts # Module exports
Key design decisions:
- Minimal by default: All list operations default to
--names-only - Explicit schema loading: Use
schemacommand when needed - JSON-only output: stdout is reserved for JSON, logs go to stderr
- Cross-platform first: Uses Deno's std library for path handling
- Connection pooling: Reuses connections across commands
Scenario: Multi-step development task across 6 tools from 3 servers
| Approach | Tokens Loaded | Tokens Used | Waste | Quality |
|---|---|---|---|---|
| Eager Loading | 18,000 | 1,650 | 83% | Degraded |
| MCP CLI | 1,650 | 1,650 | 0% | Optimal |
Savings: 91% reduction in tool-related context pollution
Contributions welcome! Please see CONTRIBUTING.md for guidelines.
MIT License - see LICENSE for details.
- Agent Integration Guide - Complete guide for AI agents to integrate with MCP CLI
- Workflows Guide - Multi-step workflow patterns and examples
- API Reference - Comprehensive command reference with examples
- Agent Examples - TypeScript, Python, and Bash agent implementations
- Workflow Examples - Practical multi-step workflow scripts
- Issues: GitHub Issues
- Discussions: GitHub Discussions