Skip to main content
Glama
README.md
# mcp-agent-toolkit

An MCP (Model Context Protocol) server exposing two other projects in this
portfolio as tools any MCP client -- Claude Desktop, or any other
MCP-compatible app -- can call directly:

- **`query_finance_filings`** -- hybrid RAG search (BM25 + semantic +
  cross-encoder reranking) with cited answers over 10 companies' real SEC
  10-K filings, from [rag-finance-assistant](https://github.com/naomytcheums-dotcom/rag-finance-assistant).
- **`fix_code_bug`** -- plans, writes, and test-verifies a fix for a seeded
  bug in a small demo repo, from [code-fix-agent](https://github.com/naomytcheums-dotcom/code-fix-agent)'s bounded LangGraph loop.
- **`list_finance_companies`** -- lists the 10 available tickers.

MCP is the protocol OpenAI, Google DeepMind, and Microsoft have all
adopted for connecting LLM clients to external tools -- this project is
about proving I can package real, already-working agentic systems behind
it, not a toy "hello world" server.

## Why vendored, not a dependency on the sibling repos

`vendor/rag_finance/` and `vendor/code_fix_agent/` are copies of the
relevant source (and, for the finance side, the already-cleaned SEC filing
text) from the two sibling repos, not a `pip install` of them or a
`git submodule`. A recruiter who clones this repo should get a working
server without also having to clone and wire up two other repositories --
self-contained beats DRY for a single-purpose portfolio piece like this
one. The tradeoff, stated plainly: a bug fixed in the original
rag-finance-assistant or code-fix-agent repos won't automatically appear
here.

## Setup

```bash
python -m venv .venv
.venv\Scripts\activate   # source .venv/bin/activate on macOS/Linux
pip install -r requirements.txt

# One-time: build the local vector store for query_finance_filings.
# No API key needed -- embeddings are local sentence-transformers.
python scripts/build_finance_index.py
```

Create a `.env` file at the project root (gitignored) with your own key,
only needed for `query_finance_filings`'s generation step and for
`fix_code_bug`:

```
ANTHROPIC_API_KEY=sk-ant-...
```

### Connect it to Claude Desktop

Add this to Claude Desktop's `claude_desktop_config.json` (Settings ->
Developer -> Edit Config):

```json
{
  "mcpServers": {
    "ai-portfolio-toolkit": {
      "command": "C:\\path\\to\\mcp-agent-toolkit\\.venv\\Scripts\\python.exe",
      "args": ["C:\\path\\to\\mcp-agent-toolkit\\server.py"],
      "env": { "ANTHROPIC_API_KEY": "sk-ant-..." }
    }
  }
}
```

Restart Claude Desktop, then ask it something like *"What did Apple's 10-K
say about total net sales? Use the finance filings tool."* -- Claude will
call `query_finance_filings` itself and show the tool call in its UI.

### Run the server directly (for debugging, not how an MCP client uses it)

```bash
python server.py
```

Speaks MCP over stdio -- not meant to be interacted with directly in a
terminal; use an MCP client (Claude Desktop, or the `mcp` SDK's own dev
inspector: `mcp dev server.py`) to actually call the tools.

## Design choices, stated up front

- **Environment-variable API key, not per-call config.** The sibling
  Streamlit dashboards pass keys through per-request config because
  they're shared multi-tenant deployments -- one process, many visitors,
  each supplying their own key. An MCP server launched by Claude Desktop
  is the opposite shape: one process per user, started by their own
  client. An env var set in that user's own `claude_desktop_config.json`
  is the correct BYOK pattern here, not a shortcut.
- **`fix_code_bug` never opens a PR.** Unlike code-fix-agent's own
  dashboard, there's no natural place in a tool call for a visitor to
  supply their own GitHub token and target repo, and letting an LLM's
  tool-call decision push code somewhere is a meaningfully bigger blast
  radius than proposing a diff it can review first. Scoped to "propose and
  verify a fix" only -- see `mcp_tools/code_fix.py`.
- **`query_finance_filings` doesn't modify the vendored retrieval.py.**
  Company filtering happens by biasing the retrieval query with the
  company's full name and filtering the returned pool by ticker
  afterward, rather than adding a `where` filter to the vendored Chroma
  query -- keeps the vendored retrieval code byte-for-byte traceable back
  to its source project. See `mcp_tools/finance_qa.py`.
- **Every `fix_code_bug` call gets a disposable copy of the demo repo.**
  Same statefulness lesson as code-fix-agent's own dashboard: operating on
  the vendored original directly would mean the first call's "fix"
  permanently fixes the seeded bug for every call after it.

## Bugs found while building this, before any live run

1. **Package name collision.** The vendored `code_fix_agent/src/tools/`
   package (`repo_explorer.py`, `git_ops.py`, etc.) has the same name as
   the wrapper package this project's own tools live in. With both on
   `sys.path`, Python resolved `import tools` to whichever one came first
   and code-fix-agent's own internal imports
   (`from tools.repo_explorer import write_file`) broke with
   `ModuleNotFoundError`. Fixed by renaming this project's wrapper package
   to `mcp_tools/` rather than touching the vendored code.
2. **Vendored files assumed a `src/` nesting level that wasn't there.**
   `retrieval.py`, `generation.py`, and `indexing.py` compute
   `PROJECT_ROOT = Path(__file__).resolve().parent.parent`, correct in
   the original repo where they live at `src/<file>.py` one level under
   the project root -- but I'd initially copied them straight into
   `vendor/rag_finance/`, which put `PROJECT_ROOT` one directory too high
   and broke every relative data path (`data/processed/finance_docs.json`
   not found). Fixed by nesting them under `vendor/rag_finance/src/` to
   match the layout the code actually assumes, instead of editing the
   vendored files.

## Tests

```bash
pytest tests/ -v
```

6 tests: the server registers exactly the 3 expected tools with correct
input schemas, ticker validation/normalization, and `fix_code_bug`'s
API-key guard -- all protocol-level, none need an Anthropic API key.

`query_finance_filings`'s retrieval stage (BM25 + semantic + reranking) is
verified working end-to-end against the real indexed filings -- confirmed
it correctly isolates a single company's chunks from the shared 10-company
corpus. Its generation stage, and all of `fix_code_bug`, need a funded
Anthropic key to run past the point these tests reach -- not yet tested
live, same status as the sibling projects.

## Stack

Official `mcp` Python SDK (stdio transport) + the vendored RAG and
LangGraph agent pipelines from rag-finance-assistant and code-fix-agent.

## Status

Structurally verified: all 6 tests pass, tool registration/dispatch
confirmed through the real MCP server object (not mocked), retrieval
confirmed working against the real vector store. Generation
(`query_finance_filings`'s answer step) and the full `fix_code_bug` loop
are code-complete but blocked on the same zero-credit Anthropic API key as
the rest of this portfolio -- see Status in the sibling repos' READMEs.