DEV Community

gentic news
gentic news

Posted on • Originally published at gentic.news

The One Decorator That Makes Your Script Agentic: @mcp.tool() vs. Subprocess

Wrap your Claude Code helper scripts in @mcp.tool() to expose typed, discoverable interfaces agents can reason about—the schema, not the AI call, is what makes it agentic.

What Changed — The One Decorator That Makes Your Script Agentic

How to Use Anthropic MCP Tools with Your AutoGen Agents (and any model)

You have a 20-line Python script that generates Conventional Commit messages. It shells out to claude -p, prints a result, and works perfectly when you run python git_commit.py by hand. Then you wrap the same logic in an MCP tool with @mcp.tool(), and suddenly it's "agentic." But why?

The author of this Dev.to post diffed the two approaches and found the AI call is identical—same subprocess, same prompt, same OAuth session. The difference is one line: @mcp.tool(). That decorator converts your function's Python signature (def generate_commit_message(diff: str) -> str) into a JSON Schema object with a name, description from the docstring, and typed parameters—published over the MCP protocol before any tool is ever called.

An agent deciding what to do next reads that schema, not your function body. It knows "this tool takes a string called diff and returns a string." That's the entire interface contract. Your plain script has none of that—it's a black box only a human who already knows to run python git_commit.py can use.

What It Means For You — Why Schema Beats Subprocess

Exposing Your Agent as an MCP Server with Microsoft Agent ...

This distinction bites when you try to let an agent use both interchangeably. The author tried wiring an agent to shell out to git_commit.py directly via a generic bash-execution tool. It failed because the script's failure mode is a print() and a nonzero exit code—fine for a human, useless for an agent parsing stdout/exit-code pairs generically. Is that "expected condition, try something else" or "real error, stop"? The agent has to guess.

The MCP tool avoids this because the interface is typed. A -> str return means the agent always gets a message back. Error signaling goes through the protocol's own mechanism, not smuggled through print statements designed for human eyes.

Try It Now — Convert Your Scripts to MCP Tools

  1. Install the MCP SDK: pip install mcp
  2. Create a server file (server.py):
from mcp.server import Server, Tool

server = Server("my-tools")

@server.tool()
def generate_commit_message(diff: str) -> str:
    """Generate a Conventional Commits message from a git diff string."""
    # Your existing logic here—same subprocess call as before
    import subprocess
    SYSTEM = "You are a commit message generator..."
    raw = subprocess.check_output(
        ["claude", "-p", SYSTEM + "\n\n" + diff],
        text=True,
    ).strip()
    return raw
Enter fullscreen mode Exit fullscreen mode
  1. Wire it into Claude Code: Add to your claude.json or project config:
{
  "mcpServers": {
    "my-tools": {
      "command": "python",
      "args": ["server.py"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now Claude Code can discover and call your tool by its schema. The same AI call, but now agentic—because the boundary of what it does is described in a form something other than a human can read.


Source: dev.to


Originally published on gentic.news

Top comments (0)