Skip to content

kurtisvg/skillful-mcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

37 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

skillful-mcp

Go CI Go Report Card License: MIT

Too many MCP tools slowing your agent down? Might be a Skill Issue πŸ˜‰

skillful-mcp eliminates tool bloat by turning your MCP servers into Agent Skills in an MCP-native way.

  • πŸ” Progressive Disclosure β€” start with 4 tools, discover more as needed
  • ⚑ Code Mode β€” trigger and combine multiple tool calls with Python
  • πŸ”’ Secure sandbox β€” code executes in a sandbox, not your shell
  • πŸ”Œ Any MCP client β€” works with Gemini CLI, Claude Code, Codex, and more

Table of contents

❓ Why?

Connecting an agent to too many tools (or MCP servers) creates tool bloat. An agent with access to 5 servers might have 80+ tools loaded into its context window before the user says a word. Accuracy drops, latency increases, and adding capabilities makes the agent worse.

skillful-mcp fixes this through progressive disclosure. The agent sees just 4 tools and discovers specific schemas on-demand, collapsing thousands of tokens down to a lightweight index.

πŸ’‘ How it works

Agent  <--MCP-->  skillful-mcp  <--MCP-->  Database Server
                                <--MCP-->  Filesystem Server
                                <--MCP-->  API Server

skillful-mcp reads a standard mcp.json config, connects to each downstream server, and exposes four tools:

Tool Description
list_skills Returns the names of all configured downstream servers
use_skill Lists the tools and resources available in a specific skill
read_resource Reads a resource from a specific skill
execute_code Runs Python code in a secure Monty sandbox

The typical agent workflow:

  1. Call list_skills to see what's available
  2. Call use_skill to inspect a skill's tools and their input schemas
  3. Use execute_code to orchestrate tool calls in a single round-trip

Example Code Mode Usage

After discovering tools via use_skill, the agent can call them directly by name inside execute_code β€” chaining outputs from one tool into another:

# Query users, then send each one a welcome email
users = query(sql="SELECT name, email FROM users WHERE welcomed = false")
for user in users:
    send_email(to=user["email"], subject="Welcome!", body="Hi " + user["name"])
"Sent " + str(len(users)) + " welcome emails"

All downstream tools are available as functions with positional and keyword arguments. If two skills define a tool with the same name, the function is prefixed with the skill name (e.g. database_search, docs_search). Tool names returned by use_skill always match the function names in execute_code.

πŸš€ Getting started

Install

Download a binary
VERSION="0.0.1"
OS="linux"       # or: darwin, windows
ARCH="amd64"     # or: arm64

curl -L "https://github.com/kurtisvg/skillful-mcp/releases/download/v${VERSION}/skillful-mcp_${VERSION}_${OS}_${ARCH}" -o skillful-mcp
chmod +x skillful-mcp

Or download from the releases page.

Docker
docker run --rm \
  -v /path/to/mcp.json:/mcp.json \
  ghcr.io/kurtisvg/skillful-mcp:latest \
  --config /mcp.json --transport http --port 8080
Go install (requires Go 1.25+)
go install github.com/kurtisvg/skillful-mcp@latest
Build from source
git clone https://github.com/kurtisvg/skillful-mcp.git
cd skillful-mcp
go build -o skillful-mcp .

Create a config

Create an mcp.json file with your downstream servers:

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "@toolbox-sdk/server", "--prebuilt=postgres"],
      "description": "Postgres database tools β€” query, inspect schemas, and manage tables. Use when the user needs to read or write data, explore table structures, or run SQL.",
      "env": {
        "POSTGRES_HOST": "${POSTGRES_HOST}",
        "POSTGRES_USER": "${POSTGRES_USER}",
        "POSTGRES_PASSWORD": "${POSTGRES_PASSWORD}",
        "POSTGRES_DATABASE": "${POSTGRES_DATABASE}"
      }
    },
    "github-issues": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/x/issues",
      "headers": {
        "Authorization": "Bearer ${GITHUB_TOKEN}"
      },
      "description": "GitHub issue management β€” create, search, update, and comment on issues. Use when the user mentions bugs, feature requests, or issue triage."
    }
  }
}

Run

skillful-mcp --config mcp.json

Or over HTTP:

skillful-mcp --config mcp.json --transport http --port 8080

Connect to your agent

Gemini CLI (~/.gemini/settings.json)
{
  "mcpServers": {
    "skillful": {
      "command": "/path/to/skillful-mcp",
      "args": ["--config", "/path/to/mcp.json"]
    }
  }
}
Claude Code (.claude/settings.json)
{
  "mcpServers": {
    "skillful": {
      "command": "/path/to/skillful-mcp",
      "args": ["--config", "/path/to/mcp.json"]
    }
  }
}
Codex CLI (~/.codex/config.toml)
[mcp_servers.skillful]
command = "/path/to/skillful-mcp"
args = ["--config", "/path/to/mcp.json"]

Any MCP-compatible client works β€” just point it at the skillful-mcp binary.

Advanced example: GitHub MCP Server

The GitHub MCP server exposes 19+ toolsets β€” a perfect candidate for skill decomposition. Instead of one massive server, split it into focused skills by feature group. The agent sees 4 skills instead of 40+ tools, and calls use_skill only when it needs a specific capability.

{
  "mcpServers": {
    "github-issues": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/x/issues",
      "headers": {
        "Authorization": "Bearer ${GITHUB_TOKEN}"
      },
      "description": "GitHub issue management β€” create, search, update, and comment on issues. Use when the user mentions bugs, feature requests, or issue triage."
    },
    "github-labels": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/x/labels",
      "headers": {
        "Authorization": "Bearer ${GITHUB_TOKEN}"
      },
      "description": "GitHub label management β€” create, assign, and remove labels. Use when organizing or categorizing issues and pull requests."
    },
    "github-prs": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/x/pull_requests",
      "headers": {
        "Authorization": "Bearer ${GITHUB_TOKEN}"
      },
      "description": "GitHub pull request workflows β€” review, merge, and manage PRs. Use when the user asks about code review, PR status, or merging changes."
    },
    "github-actions": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/x/actions",
      "headers": {
        "Authorization": "Bearer ${GITHUB_TOKEN}"
      },
      "description": "GitHub Actions CI/CD β€” trigger, monitor, and debug workflows. Use when the user asks about build status, failed checks, or re-running pipelines."
    }
  }
}

πŸ“ Configuration

Each entry in mcpServers is a downstream server that becomes a skill. The key is the skill name. The value depends on the transport type.

All string values support ${VAR} environment variable expansion. Missing variables cause a startup error.

Common options

All server types support these optional fields:

Field Description
description Override the server's instructions shown by list_skills
allowedTools Only expose these tool names (default: all)
allowedResources Only expose these resource URIs (default: all)

Excluded tools are invisible everywhere β€” they won't appear in use_skill, can't be called via execute_code, and won't cause name-conflict prefixing.

STDIO server

Spawns the server as a child process. Only env vars explicitly listed in env are passed to the child β€” the parent environment is not inherited.

Field Required Description
command yes Executable to run
args no Arguments array
env no Environment variables for the child process
{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "@toolbox-sdk/server", "--prebuilt=postgres"],
      "description": "Postgres database tools β€” query, inspect schemas, and manage tables. Use when the user needs to read or write data, explore table structures, or run SQL.",
      "env": {
        "POSTGRES_HOST": "${POSTGRES_HOST}",
        "POSTGRES_USER": "${POSTGRES_USER}",
        "POSTGRES_PASSWORD": "${POSTGRES_PASSWORD}",
        "POSTGRES_DATABASE": "${POSTGRES_DATABASE}"
      }
    }
  }
}

HTTP server

Connects via Streamable HTTP.

Field Required Description
type yes Must be "http"
url yes Server endpoint URL
headers no HTTP headers (e.g. auth tokens)
{
  "mcpServers": {
    "remote-api": {
      "type": "http",
      "url": "https://api.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${API_KEY}"
      }
    }
  }
}

SSE server

Connects via Server-Sent Events.

Field Required Description
type yes Must be "sse"
url yes SSE endpoint URL
headers no HTTP headers

Flags

Flag Default Description
--config ./mcp.json Path to the config file
--transport stdio Upstream transport: stdio or http
--host localhost HTTP listen host
--port 8080 HTTP listen port
--version Print version and exit

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors