Skip to main content
Glama
README.md
# AgentForge MCP

A local MCP (Model Context Protocol) server that inspects and analyzes Agentic AI
projects on your machine. It requires no external APIs, no API keys, no
database, and no paid services — everything runs locally, offline, using
Python's own file system and code-parsing capabilities.

## Table of contents

- [Why this was built](#why-this-was-built)
- [Who it's for](#who-its-for)
- [What it does](#what-it-does)
- [How it works](#how-it-works-in-simple-terms)
- [Tools, Resources, and Prompts provided](#tools-resources-and-prompts-provided)
- [Example output](#example-output)
- [Project structure](#project-structure)
- [Requirements](#requirements)
- [Running and testing it](#running-and-testing-it)
- [Connecting to Claude Desktop](#connecting-to-claude-desktop)
- [Design notes and limitations](#design-notes-and-limitations)

## Why this was built

Understanding an unfamiliar agentic AI codebase — which agents it defines,
what tools those agents can call, whether basics like a README, a
dependency file, or tests exist — usually means opening files one by one.
AgentForge automates that first pass of inspection.

It also exists as a small, complete, working reference implementation of an
MCP server: one that actually uses all three MCP primitives (Tools,
Resources, and Prompts) together, rather than only one of them.

## Who it's for

- Developers who want a quick structural overview of an agentic AI project
  before reading through its code.
- Anyone learning MCP by working with a real, runnable example rather than
  isolated snippets.

## What it does

AgentForge reads and analyzes the structure of a Python project. It never
imports or executes any code belonging to the project it's inspecting — all
analysis is done by reading file contents and parsing source code as text
(via Python's built-in `ast` module for `.py` files). Given a folder path,
it can:

- Report the project's file structure: total files, Python file count, key
  files present (`README.md`, `requirements.txt`, `pyproject.toml`, etc.),
  and which known agent framework (if any) it appears to use, based on
  simple text matching against import statements and dependency files.
- Detect functions and classes that look like agent "tools" — functions
  decorated with something tool-like (e.g. `@tool`), named `*_tool` /
  `tool_*`, or classes with "Tool" in the name.
- Detect classes that look like agent definitions — classes named `*Agent*`
  or inheriting from a base class with "Agent" in its name.
- Combine all of the above into one architecture report, plus a short list
  of best-practice warnings (e.g. no README found, no tests found, no tools
  detected).

A small sample project is bundled at `example_agent_project/` so every tool,
resource, and prompt can be tested immediately by passing the path
`"example"`, without needing a real project on hand first.

## How it works, in simple terms

AgentForge is a normal Python program built on the `fastmcp` library. It
exposes three kinds of capabilities over the MCP protocol:

- **Tools** — functions that take an input (a project path) and compute a
  fresh result on every call. An AI client can invoke these on its own,
  based on what the user asks in conversation.
- **Resources** — fixed content addressed by a URI (e.g.
  `agentforge://architecture`), with no input parameters. Clients typically
  require the user to attach these explicitly rather than fetching them
  automatically.
- **Prompts** — reusable instruction templates with named arguments (e.g.
  `path`, `issue_description`). A user selects a prompt and fills in its
  arguments; the template text becomes the starting instructions for the
  AI, directing it to call specific tools in a specific order.

An MCP client (such as Claude Desktop) starts `server.py` as a subprocess
and communicates with it over standard input/output (the "stdio"
transport) using JSON-RPC messages. When a tool is called, the client sends
a message naming the tool and its arguments; the server runs the matching
Python function and returns the result as plain text.

Internally, `server.py` only handles this MCP wiring. The actual logic
lives in the `agentforge/` package, split by responsibility:

- `agentforge/utils.py` — resolves the path argument (including the
  `"example"` shortcut) and walks the directory tree, skipping folders like
  `.git`, `__pycache__`, and `venv`.
- `agentforge/scanner.py` — implements the logic behind `scan_project`.
- `agentforge/tool_lister.py` — implements the logic behind
  `list_agent_tools`, using `ast.parse()` and `ast.walk()`.
- `agentforge/analyzer.py` — implements the logic behind `analyze_agent`,
  combining the two above with its own agent-class detection and warning
  checks.

Because this logic doesn't depend on MCP at all, it's tested directly with
pytest in `tests/`, with no MCP client or protocol involved.

## Tools, Resources, and Prompts provided

### Tools

| Tool | Signature | What it does |
|---|---|---|
| `scan_project` | `scan_project(path: str) -> str` | Returns a Markdown report of file counts, key files found, and detected frameworks |
| `list_agent_tools` | `list_agent_tools(path: str) -> str` | Returns a Markdown list of functions/classes that look like agent tools, with file and line number |
| `analyze_agent` | `analyze_agent(path: str) -> str` | Returns a combined Markdown report: agents found, tools found, and best-practice warnings |

All three accept the literal string `"example"` in place of a real path,
which resolves to the bundled `example_agent_project/` folder. Invalid
paths return a readable error message rather than raising an exception to
the client.

### Resources

| URI | Returns |
|---|---|
| `agentforge://project` | A `scan_project`-style report of the bundled example project (fixed, no input) |
| `agentforge://tools` | A static Markdown reference describing AgentForge's own three tools |
| `agentforge://architecture` | A static Markdown guide covering a recommended agent-project folder layout and five design principles |

### Prompts

| Prompt | Arguments | Purpose |
|---|---|---|
| `review_agent` | `path` (default `"example"`) | Instructs the AI to call `scan_project`, `list_agent_tools`, and `analyze_agent`, then read `agentforge://architecture`, before writing a structured review with a ranked top-3 improvements list |
| `debug_agent` | `path` (default `"example"`), `issue_description` (default provided) | Instructs the AI to call `analyze_agent`, `list_agent_tools`, and `scan_project` in that order to investigate a described problem, then produce ranked hypotheses |
| `design_agent` | `requirements` (default provided) | Instructs the AI to read `agentforge://architecture` first, then propose a folder structure, agent list, tool list, and framework recommendation for a new project |

## Example output

Running `scan_project("example")` against the bundled sample project
returns:

Project Scan: .../example_agent_project
Total files: 11
Python files: 9
Other files: 2
Frameworks detected
None detected (plain Python, or a framework not in our signature list)
Key files found
README.md
requirements.txt
File tree (11 entries shown)
README.md
agents/init.py
agents/base.py
agents/researcher_agent.py
agents/writer_agent.py
main.py
requirements.txt
tools/init.py
tools/base.py
tools/calculator_tool.py
tools/search_tool.py




Running `analyze_agent("example")` additionally reports 3 agent classes
found (`Agent`, `ResearcherAgent`, `WriterAgent`), 2 tools found
(`web_search`, `calculate_tool`), and two warnings: no known framework
detected, and no test files detected — both true, since the example
project is intentionally minimal.

## Project structure

agentforge-mcp/
├── server.py # MCP server: registers all tools, resources, prompts
├── requirements.txt # fastmcp, pytest
├── pytest.ini # lets tests import agentforge/ from the project root
├── .gitignore
├── agentforge/ # Core logic — no MCP-specific code
│ ├── init.py
│ ├── utils.py # path resolution, safe directory walking
│ ├── scanner.py # logic behind scan_project
│ ├── tool_lister.py # logic behind list_agent_tools
│ └── analyzer.py # logic behind analyze_agent
├── example_agent_project/ # Bundled sample project used for testing
│ ├── README.md
│ ├── requirements.txt
│ ├── main.py
│ ├── agents/
│ │ ├── base.py # fake Agent base class
│ │ ├── researcher_agent.py # ResearcherAgent
│ │ └── writer_agent.py # WriterAgent
│ └── tools/
│ ├── base.py # fake @tool decorator
│ ├── search_tool.py # web_search (fake, no network call)
│ └── calculator_tool.py # calculate_tool (real, safe ast-based eval)
├── tests/ # pytest tests for agentforge/ core logic
│ ├── test_scanner.py
│ ├── test_tool_lister.py
│ └── test_analyzer.py
└── config/
└── claude_desktop_config.example.json


## Requirements

- Python 3.10 or newer
- `fastmcp>=2.3.0`
- `pytest>=7.4.0` (only needed to run the test suite)

Both dependencies are listed in `requirements.txt`.

## Running and testing it

```bash
python3 -m venv venv
source venv/bin/activate          # Windows: venv\Scripts\activate
pip install -r requirements.txt
```

Run the automated test suite (tests the core logic in `agentforge/`
directly, no MCP client needed):

```bash
pytest -v
```

Run the server directly, as a sanity check. It will sit idle, since it's
waiting for MCP protocol messages on stdin — this is expected. Press
Ctrl+C to stop it:

```bash
python server.py
```

## Connecting to Claude Desktop

Claude Desktop supports local MCP servers over the stdio transport. Add an
entry to its configuration file:

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "agentforge": {
      "command": "/ABSOLUTE/PATH/TO/agentforge-mcp/venv/bin/python",
      "args": ["/ABSOLUTE/PATH/TO/agentforge-mcp/server.py"]
    }
  }
}
```

Replace the paths with the real absolute path to this project on your
machine. On Windows, use `venv\Scripts\python.exe` and double backslashes
in the JSON. Fully quit and reopen Claude Desktop for the change to take
effect. A ready-to-edit copy of this config is included at
`config/claude_desktop_config.example.json`.

Once connected, Tools can be invoked by describing what you want in a
normal chat message. Resources and Prompts require using Claude Desktop's
attachment/template UI (the `+` button next to the message box), since MCP
clients require explicit user selection for those two primitive types
rather than triggering them automatically.

## Design notes and limitations

- Framework and tool detection are based on simple text/AST pattern
  matching, not a real import resolver — they can miss unusual patterns or,
  less commonly, produce false positives (e.g. a framework name mentioned
  only in a comment or docstring).
- No project code is ever executed; all analysis is static (file reading
  and `ast` parsing only), which makes it safe to point at any project.
- The bundled `example_agent_project/` is intentionally minimal (no tests,
  no framework) so that `analyze_agent`'s warnings can be demonstrated
  meaningfully on it.