Skip to main content
Glama

DevPilot

DevPilot is an MCP-based local development agent. An LLM reasons over the user's request and available tools, calls MCP tools (git / docker / filesystem), observes the results, and loops until it can produce a final answer.


Quick start

  1. Copy .env.example to .env and set OPENAI_API_KEY (OpenRouter / Groq / OpenAI-compatible).

  2. From the repo root:

PYTHONPATH=client poetry run python client/client.py
  1. Type a prompt. Type quit to exit.

Hiring-manager demo (broken backend container):

PYTHONPATH=client poetry run python demo/run_demo.py

See demo/README.md for the talking script and a no-Docker backup.

Optional env vars:

Variable

Default

Purpose

OPENAI_API_KEY

(required)

API key

OPENAI_BASE_URL

https://openrouter.ai/api/v1

Compatible API base URL

OPENAI_MODEL

openai/gpt-4o-mini

Model name


Related MCP server: My Coding Buddy MCP Server

Architecture

                   User
                     │
                     ▼
          Conversation Manager
                     │
                     ▼
              Tool Registry (MCP)
                     │
        list_tools() + inputSchema
                     │
                     ▼
                 LLM (Planner)
                     │
     ┌───────────────┴────────────────┐
     │                                │
     ▼                                ▼
 Tool Call(s)                  Final Answer
     │                                │
     ▼                                ▼
  Executor                         Exit
     │
     ▼
 Tool Result(s)
     │
     ▼
Conversation Manager
     │
     └───────────────► Back to LLM

File map

Stage

File

Role

Entry

client/client.py

Starts MCP server over stdio, REPL, prints answers

Loop

client/agent/main.py

Orchestrates plan → execute → update history (max 8 turns)

History

client/agent/conversation.py

Stores user / assistant / tool messages

Schemas

client/agent/registry.py

Formats MCP tool schemas for the LLM

Planner

client/agent/llm.py

LLM returns tool_call / final_answer / clarification / error

Execute

client/agent/executor.py

Calls session.call_tool(...) over MCP

Format

client/agent/context.py

Pretty-prints tool results into conversation

Models

client/agent/models.py

AgentStatus, ToolCall, ToolResult, etc.

MCP app

server/app.py

FastMCP("DevPilot")

Tools

server/server.py

@mcp.tool registrations

Impl

server/git/*, server/doocker/*, server/filesystem/*

Real commands

Helpers

server/utils/{validator,Commands,response}.py

Validate paths, run subprocess, ok/fail dicts


Request flow (by file)

1. Boot — client/client.py

  • Loads .env

  • Spawns the MCP server: poetry run python -m server.server over stdio

  • Creates an MCP ClientSession, calls initialize(), then list_tools()

  • Starts a REPL and passes each prompt into agent_main

2. Agent loop — client/agent/main.py

Builds:

  • ConversationManager — history

  • ToolRegistry — tool schemas

  • LLMPlanner — next decision

  • Executor — MCP tool calls

Then:

  1. conversation.add_user(prompt)

  2. Loop up to MAX_TURNS = 8:

    • planner.plan(conversation, registry)

    • If tool_call → record calls → executor.execute → record results → continue

    • If final_answer / clarification / error → return

3. Conversation — client/agent/conversation.py

Stores messages as user, assistant, or tool.
to_prompt_text() is what the LLM sees every turn.

4. Tool registry — client/agent/registry.py

Turns MCP list_tools() into JSON schema text (name, description, properties, required).

5. LLM planner — client/agent/llm.py

Receives:

  • System prompt (DevPilot rules)

  • Available tool schemas

  • Conversation history

Returns a single JSON object parsed into AgentResponse.

6. Executor — client/agent/executor.py

For each ToolCall:

  • await session.call_tool(tool_name, tool_args)

  • Collects text content into ToolResult

The executor never decides — it only runs tools.

7. MCP server — server/server.py + implementations

@mcp.tool handlers delegate to modules under:

  • server/git/ — status, branch, log, diff, commit, push, pull, stash, …

  • server/doocker/ — ps, logs, inspect, exec, start, stop, restart, …

  • server/filesystem/ — read/write/list/search/find/delete/symbols

Helpers:

  • validator — ensure path is a git repo / file / directory

  • Commands.run_cmd / run_shell_cmd — subprocess wrappers

  • response.ok / fail — standard {success, result|message} dicts

8. Context — client/agent/context.py

Formats each ToolResult into readable text, then appends it to the conversation for the next LLM turn.


Example: git status + branch

User

What's the status of my repo at /Users/nitin/Desktop/local-git-mcp? Which branch am I on?

Turn 1 — LLM (client/agent/llm.py)

{
  "status": "tool_call",
  "tool_calls": [
    {
      "tool_name": "git_status",
      "tool_args": {
        "repo_path": "/Users/nitin/Desktop/local-git-mcp"
      }
    },
    {
      "tool_name": "git_current_branch",
      "tool_args": {
        "repo_path": "/Users/nitin/Desktop/local-git-mcp"
      }
    }
  ]
}

Executor → MCP → server

Tool

Path

Command

git_status

server/git/status.py

git -C <path> status

git_current_branch

server/git/current_branch.py

git -C <path> … (current branch)

Tool result shape

{"success": True, "result": "<command stdout>"}

Results are formatted by context.py and stored in the conversation.

Turn 2 — LLM

{
  "status": "final_answer",
  "answer": "You're on branch main. The working tree has unstaged changes in client/agent/llm.py."
}

client/client.py prints:

DevPilot> You're on branch main. The working tree has unstaged changes in client/agent/llm.py.

Example: docker debugging

User

Why is my backend container failing?
LLM → docker_ps()
       backend -> exited, db -> running

LLM → docker_logs(container="backend")
       panic: database connection refused

LLM → final_answer
       The backend exits because it cannot connect to the database.

LLM response types

Tool call

{
  "status": "tool_call",
  "tool_calls": [
    {
      "tool_name": "docker_logs",
      "tool_args": { "container": "backend" }
    }
  ]
}

Final answer

{
  "status": "final_answer",
  "answer": "The backend container exits because it cannot connect to the database."
}

Clarification

{
  "status": "clarification",
  "answer": "Which repository path should I inspect?"
}

Error

{
  "status": "error",
  "error": "Unable to execute the requested tool."
}

Agent loop (simplified)

conversation.add_user(prompt)

for _ in range(MAX_TURNS):
    response = planner.plan(conversation, registry)

    if response.status == TOOL_CALL:
        results = await executor.execute(response.tool_calls)
        conversation.add_tool_calls_and_results(...)
        continue

    return response  # final_answer | clarification | error

Design principles

  • LLM reasons; MCP tools execute — the executor never makes decisions.

  • Discoverable tools — schemas come from MCP list_tools(), not hard-coded client logic.

  • Conversation is stateful — multi-step flows (e.g. docker_psdocker_logs) work naturally.

  • Structured LLM I/O — forced JSON statuses; the agent must not invent tool output.

  • Deterministic tools — validators + subprocess; standard ok/fail responses.

  • Bounded loop — stops after MAX_TURNS (8) to avoid infinite tool calling.


Available tools (high level)

Git: status, current branch, branch list, log, diff, show, checkout, create branch, commit, push, pull, stash

Docker: ps, images, logs, inspect, exec, start, stop, restart

Filesystem: read/write file, list directory, search text, find files, file info, delete file, list/read symbols

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A comprehensive Model Context Protocol server implementation that enables AI assistants to interact with file systems, databases, GitHub repositories, web resources, and system tools while maintaining security and control.
    74 npm
    2
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    A personal AI coding assistant that connects to various development environments and helps automate tasks, provide codebase insights, and improve coding decisions by leveraging the Model Context Protocol.
    10
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Secure local development platform that exposes controlled developer capabilities (FS, Git, search, command execution) to AI assistants via MCP with deny-by-default security and audit logging.
    -