Skip to content
Agent Orchestration
Skill

/mcporter

Convert any CLI tool or Python function into an MCP server using fastmcp. Zero-config tool injection into Claude Code.

BOOST
From plugin
hermes-ccc
13446 skills
Install
$ npx -y skills add alexai-mcp/hermes-ccc --skill mcporter --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/mcporter

Context preview

The summary Claude sees to decide when to auto-load this skill.

Convert any CLI tool or Python function into an MCP server using fastmcp. Zero-config tool injection into Claude Code.

SKILL.md

mcporter.SKILL.md
name: mcporter
description: Convert any CLI tool or Python function into an MCP server using fastmcp. Zero-config tool injection into Claude Code.
version: 1.0.0
author: hermes-CCC (ported from Hermes Agent by NousResearch)
license: MIT
metadata:
  hermes:
    tags: [MCP, Tools, Development, fastmcp, Integration, Server]
    related_skills: [native-mcp]

MCPorter — CLI to MCP Converter

Turn any Python function or CLI tool into an MCP server that Claude Code can call natively.

Setup

pip install fastmcp

---

Minimal Server

# my_server.py
from fastmcp import FastMCP

mcp = FastMCP("my-tool")

@mcp.tool()
def hello(name: str) -> str:
    """Say hello to someone."""
    return f"Hello, {name}!"

if __name__ == "__main__":
    mcp.run()  # stdio transport (for Claude Code)

Register in `.mcp.json`:

{
  "mcpServers": {
    "my-tool": {
      "command": "python",
      "args": ["my_server.py"]
    }
  }
}

Restart Claude Code → `hello` tool appears natively.

---

Type Annotations Matter

Claude reads your type hints to understand the tool:

@mcp.tool()
def search_files(
    query: str,
    directory: str = ".",
    max_results: int = 10,
    case_sensitive: bool = False,
) -> list[str]:
    """Search for files matching query in directory."""
    import subprocess
    flag = "" if case_sensitive else "-i"
    result = subprocess.run(
        ["grep", "-rl", flag, query, directory],
        capture_output=True, text=True
    )
    return result.stdout.strip().split("\n")[:max_results]

---

Wrap a CLI Tool

import subprocess
from fastmcp import FastMCP

mcp = FastMCP("git-helper")

@mcp.tool()
def git_log(n: int = 10, format: str = "oneline") -> str:
    """Show git commit history."""
    result = subprocess.run(
        ["git", "log", f"-{n}", f"--format={format}"],
        capture_output=True, text=True
    )
    return result.stdout

@mcp.tool()
def git_diff(staged: bool = False) -> str:
    """Show git diff."""
    args = ["git", "diff"]
    if staged:
        args.append("--staged")
    result = subprocess.run(args, capture_output=True, text=True)
    return result.stdout

if __name__ == "__main__":
    mcp.run()

---

Async Tools

import asyncio
import httpx
from fastmcp import FastMCP

mcp = FastMCP("web-fetcher")

@mcp.tool()
async def fetch_url(url: str, timeout: int = 10) -> str:
    """Fetch content from a URL."""
    async with httpx.AsyncClient() as client:
        response = await client.get(url, timeout=timeout)
        return response.text[:5000]  # first 5k chars

if __name__ == "__main__":
    mcp.run()

---

Resources (Read-Only Data)

@mcp.resource("config://settings")
def get_settings() -> str:
    """Return current settings."""
    import json, pathlib
    settings = pathlib.Path("settings.json").read_text()
    return settings

@mcp.resource("file://{path}")
def read_file(path: str) -> str:
    """Read a file by path."""
    return pathlib.Path(path).read_text()

---

Prompts

@mcp.prompt()
def code_review_prompt(code: str, language: str = "python") -> str:
    """Generate a code review prompt."""
    return f"Review this {language} code for bugs and improvements:\n\n```{language}\n{code}\n```"

---

HTTP Transport (for non-CC clients)

if __name__ == "__main__":
    mcp.run(transport="http", host="0.0.0.0", port=8080)

Then register as:

{"mcpServers": {"my-tool": {"url": "http://localhost:8080/sse"}}}

---

Error Handling

@mcp.tool()
def risky_operation(value: str) -> str:
    """Do something that might fail."""
    if not value:
        raise ValueError("value cannot be empty")  # MCP returns error to Claude
    return process(value)

---

Test Interactively

fastmcp dev my_server.py
# Opens interactive MCP inspector in browser

---

With Environment Variables

{
  "mcpServers": {
    "my-api": {
      "command": "python",
      "args": ["api_server.py"],
      "env": {
        "API_KEY": "your-secret-key",
        "BASE_URL": "https://api.example.com"
      }
    }
  }
}
Read more
Ships withhermes-ccc

Hermes Agent, faithfully ported to Claude Code Channel (CCC). hermes-CCC brings the power of Hermes Agent by NousResearch into Claude Code's native skill system — no separate process, no OAuth, no lock-in. Everything runs inside Claude Code.

Get the whole plugin

Other skills on hermes-ccc.