Skip to content

Commit 7fb97e8

Browse files
committed
docs: rewrite README for the local-first architecture; update Dockerfile
- engineering highlights, architecture diagram, agent loop walkthrough, configuration table, roadmap, demo GIF slot - Dockerfile: Ollama via host.docker.internal, drop Anthropic env git log --oneline; git status -s
1 parent 910547a commit 7fb97e8

2 files changed

Lines changed: 147 additions & 115 deletions

File tree

‎Dockerfile‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,23 @@ COPY . .
1212
# Create reports directory
1313
RUN mkdir -p /app/reports
1414

15-
# Environment — override these at runtime
16-
ENV ANTHROPIC_API_KEY=""
15+
# Environment — override these at runtime.
16+
# The LLM runs on the host's Ollama; from inside Docker use host.docker.internal.
17+
ENV OLLAMA_HOST="http://host.docker.internal:11434"
18+
ENV THINKMCP_MODEL="qwen3:8b"
1719
ENV TAVILY_API_KEY=""
1820
ENV GITHUB_TOKEN=""
1921
ENV THINKMCP_REPORTS_DIR="/app/reports"
22+
ENV THINKMCP_MEMORY_DB="/app/thinkmcp_memory.db"
2023

21-
# Default: expose Streamlit UI on 8501
24+
# Streamlit UI on 8501
2225
EXPOSE 8501
2326

2427
# MCP HTTP server on 8000 (used when running as a remote MCP server)
2528
EXPOSE 8000
2629

2730
# Default command: Streamlit UI
28-
# Override with: docker run ... python server/mcp_server.py --http --port 8000
31+
# Override with: docker run ... python -m transport.http_transport --port 8000
2932
CMD ["streamlit", "run", "app.py", \
3033
"--server.port=8501", \
3134
"--server.address=0.0.0.0", \

‎README.md‎

Lines changed: 140 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,131 @@
1-
# ThinkMCP
1+
<div align="center">
22

3-
A thinking-augmented MCP (Model Context Protocol) server that gives Claude deep research and reasoning tools. When connected, Claude can search the web, read URLs, find academic papers, search GitHub, plan multi-step tasks, record thoughts, manage in-session memory, and write reports — all while exposing its reasoning trace.
3+
# 🧠 ThinkMCP
44

5-
## What It Is
5+
**A local-first research agent that shows its work — built end-to-end on the Model Context Protocol.**
66

7-
ThinkMCP wraps 13 tools across four categories into a single MCP server:
7+
Qwen 3 thinks, plans, searches, self-critiques, and writes reports — entirely on your machine.
8+
No cloud LLM. No API bill. Every thought and tool call streamed live to the screen.
89

9-
| Category | Tools |
10-
|-----------|-------|
11-
| Research | `web_search`, `fetch_url`, `search_papers`, `search_code` |
12-
| Reasoning | `think`, `critique`, `plan` |
13-
| Memory | `remember`, `recall`, `list_memory` |
14-
| Actions | `write_report`, `create_summary`, `compare` |
10+
[![CI](https://github.com/Gh-Novel/ThinkMCP-Agentic-Tools/actions/workflows/ci.yml/badge.svg)](https://github.com/Gh-Novel/ThinkMCP-Agentic-Tools/actions/workflows/ci.yml)
11+
[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
12+
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
13+
[![MCP](https://img.shields.io/badge/protocol-MCP-7c3aed.svg)](https://modelcontextprotocol.io)
14+
[![Ollama](https://img.shields.io/badge/runs%20on-Ollama%20%C2%B7%20Qwen%203-orange.svg)](https://ollama.com)
1515

16-
It ships with two interfaces:
17-
- **Streamlit UI** (`app.py`) — interactive research assistant with visible thinking trace, tool call log, and markdown export
18-
- **MCP server** (`server/mcp_server.py`) — connects directly to Claude Desktop, Cursor, VS Code, or any MCP-compatible host
16+
</div>
1917

20-
## Requirements
18+
<!-- ──────────────────────────────────────────────────────────────
19+
DEMO GIF GOES HERE — record the Streamlit UI running a query
20+
and save it as docs/demo.gif, then uncomment:
2121
22-
- Python 3.12+
23-
- `ANTHROPIC_API_KEY` — [console.anthropic.com](https://console.anthropic.com)
24-
- `TAVILY_API_KEY` — [tavily.com](https://tavily.com) (web search)
25-
- `GITHUB_TOKEN` — optional, raises GitHub API rate limits for code search
22+
<p align="center">
23+
<img src="docs/demo.gif" alt="ThinkMCP — live thinking trace while researching" width="850">
24+
</p>
25+
─────────────────────────────────────────────────────────────── -->
2626

27-
## Install
27+
---
2828

29-
```bash
30-
git clone https://github.com/yourname/thinkmcp
31-
cd thinkmcp
32-
python -m venv .venv && source .venv/bin/activate
33-
pip install -r requirements.txt
34-
```
29+
## What it does
3530

36-
Set your keys:
31+
Ask a research question. The agent **plans** an approach, **searches** the web, ArXiv, and GitHub, **remembers** what it finds, **critiques** its own draft, and delivers a sourced answer — while the UI renders every reasoning step and tool invocation the moment it happens. Export any session as Markdown or JSON.
3732

38-
```bash
39-
export ANTHROPIC_API_KEY="sk-ant-..."
40-
export TAVILY_API_KEY="tvly-..."
41-
export GITHUB_TOKEN="ghp_..." # optional
42-
```
33+
The same 13-tool MCP server also plugs straight into **Claude Desktop, Cursor, or VS Code**.
4334

44-
## Run the Streamlit UI
35+
## Engineering highlights
4536

46-
```bash
47-
streamlit run app.py
37+
These are deliberate design decisions, not defaults:
38+
39+
- 🔌 **The agent is a real MCP client — not a wrapper.** It spawns the server as a subprocess, discovers tools over the protocol (`tools/list`), and invokes them with `tools/call` ([agent/mcp_client.py](agent/mcp_client.py)). Zero hardcoded tool schemas; add a tool to the server and the agent picks it up automatically. This is the exact integration path Claude Desktop uses.
40+
- 🏠 **Local-first inference.** The reasoning loop runs on Qwen 3 via Ollama ([agent/thinking_agent.py](agent/thinking_agent.py)), capturing the model's native thinking stream — with automatic fallback to parsing inline `<think>` tags for instruct-only variants. Works fully offline except optional web search.
41+
- 📡 **True live streaming.** The agent emits events (`thinking`, `tool_call`, `tool_result`) through a callback; the Streamlit UI drains them from a thread-safe queue and renders mid-run — no waiting for completion ([app.py](app.py)).
42+
- 💾 **Durable memory.** `remember`/`recall` are SQLite-backed ([server/tools/memory.py](server/tools/memory.py)), so findings survive restarts and are shared between the UI agent and any connected MCP host.
43+
- 🚦 **Two transports, one server.** stdio for desktop hosts, Streamable HTTP for remote/multi-client deployments — selected at launch, not forked code.
44+
- ✅ **Tested and linted in CI.** 31 pytest cases covering tools, agent helpers, and server registration, plus ruff — on Python 3.10 and 3.12 for every push.
45+
46+
## The 13 tools
47+
48+
| Category | Tools | Notes |
49+
|-----------|-------|-------|
50+
| Research | `web_search` · `fetch_url` · `search_papers` · `search_code` | Tavily, raw HTTP, ArXiv, GitHub |
51+
| Reasoning | `think` · `critique` · `plan` | deterministic, instant, reproducible |
52+
| Memory | `remember` · `recall` · `list_memory` | persisted in SQLite |
53+
| Actions | `write_report` · `create_summary` · `compare` | markdown deliverables |
54+
55+
## Architecture
56+
57+
```mermaid
58+
flowchart LR
59+
subgraph UI["Streamlit UI (app.py)"]
60+
Q[Query] --> A
61+
A -. "live events:<br/>thinking · tool_call · tool_result" .-> Q
62+
end
63+
subgraph Agent["Thinking Agent (agent/)"]
64+
A[Ollama · Qwen 3<br/>native thinking + tool calls]
65+
end
66+
subgraph Server["ThinkMCP Server (server/)"]
67+
T1[Research tools]
68+
T2[Reasoning tools]
69+
T3[Memory · SQLite]
70+
T4[Action tools]
71+
end
72+
A -- "MCP over stdio<br/>tools/list · tools/call" --> Server
73+
C[Claude Desktop / Cursor / VS Code] -- "MCP (stdio or HTTP)" --> Server
4874
```
4975

50-
Opens at `http://localhost:8501`. Enter a query, watch thinking steps and tool calls stream in real time, then export the session as markdown or JSON.
76+
## How the agent loop works
5177

52-
## Add to Claude Desktop
78+
1. Connect to the ThinkMCP server as an MCP client and discover all tools over the protocol.
79+
2. Send the query to Qwen 3 with the discovered tool schemas and thinking enabled.
80+
3. Capture the thinking stream → emit it to the UI as it arrives.
81+
4. Execute each requested tool **through MCP**, feed results back to the model.
82+
5. Repeat until the model answers (or the iteration cap trips), self-critiquing along the way.
5383

54-
1. Find your config file:
55-
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
56-
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
84+
## Quickstart
5785

58-
2. Add the server block (replace the paths and keys):
86+
**1. Install [Ollama](https://ollama.com) and a Qwen 3 model** (any tool-capable variant):
5987

60-
```json
61-
{
62-
"mcpServers": {
63-
"thinkmcp": {
64-
"command": "python",
65-
"args": ["/absolute/path/to/thinkmcp/server/mcp_server.py"],
66-
"env": {
67-
"ANTHROPIC_API_KEY": "sk-ant-...",
68-
"TAVILY_API_KEY": "tvly-...",
69-
"GITHUB_TOKEN": "ghp_...",
70-
"THINKMCP_REPORTS_DIR": "/absolute/path/to/thinkmcp/reports"
71-
}
72-
}
73-
}
74-
}
88+
```bash
89+
ollama pull qwen3:8b
7590
```
7691

77-
3. Restart Claude Desktop. You'll see ThinkMCP listed under connected servers.
92+
**2. Install ThinkMCP:**
7893

79-
## Add to Cursor
94+
```bash
95+
git clone https://github.com/Gh-Novel/ThinkMCP-Agentic-Tools
96+
cd ThinkMCP-Agentic-Tools
97+
python -m venv .venv && source .venv/bin/activate
98+
pip install -e ".[dev]"
99+
```
80100

81-
1. Open **Cursor Settings** → **MCP** → **Add MCP Server**
82-
2. Paste this config:
101+
**3. (Optional) keys for web/code search** — everything else needs none:
83102

84-
```json
85-
{
86-
"mcpServers": {
87-
"thinkmcp": {
88-
"command": "python",
89-
"args": ["/absolute/path/to/thinkmcp/server/mcp_server.py"],
90-
"env": {
91-
"ANTHROPIC_API_KEY": "sk-ant-...",
92-
"TAVILY_API_KEY": "tvly-...",
93-
"GITHUB_TOKEN": "ghp_...",
94-
"THINKMCP_REPORTS_DIR": "/absolute/path/to/thinkmcp/reports"
95-
}
96-
}
97-
}
98-
}
103+
```bash
104+
export TAVILY_API_KEY="tvly-..." # web search — tavily.com
105+
export GITHUB_TOKEN="ghp_..." # optional, raises GitHub rate limits
106+
```
107+
108+
**4. Run:**
109+
110+
```bash
111+
streamlit run app.py
99112
```
100113

101-
3. Save and reload the window.
114+
Opens at `http://localhost:8501` — pick your model in the sidebar (installed models are auto-detected) and run a query.
115+
116+
> Defaults are env-overridable: `THINKMCP_MODEL=qwen3:14b`, `OLLAMA_HOST=http://...`
102117
103-
## Add to VS Code (Copilot / MCP extension)
118+
## Use the server from Claude Desktop / Cursor / VS Code
104119

105-
With the [MCP extension](https://marketplace.visualstudio.com/items?itemName=anthropics.claude-vscode) or a compatible client, add to your `.vscode/mcp.json`:
120+
**Claude Desktop** — `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
106121

107122
```json
108123
{
109-
"servers": {
124+
"mcpServers": {
110125
"thinkmcp": {
111-
"type": "stdio",
112126
"command": "python",
113127
"args": ["/absolute/path/to/thinkmcp/server/mcp_server.py"],
114128
"env": {
115-
"ANTHROPIC_API_KEY": "sk-ant-...",
116129
"TAVILY_API_KEY": "tvly-...",
117130
"GITHUB_TOKEN": "ghp_...",
118131
"THINKMCP_REPORTS_DIR": "/absolute/path/to/thinkmcp/reports"
@@ -122,45 +135,54 @@ With the [MCP extension](https://marketplace.visualstudio.com/items?itemName=ant
122135
}
123136
```
124137

125-
## Run as Remote HTTP Server
138+
**Cursor** — Settings → MCP → Add MCP Server, paste the same block.
139+
**VS Code** — add the same server (with `"type": "stdio"`) to `.vscode/mcp.json`.
140+
141+
Restart the host and ThinkMCP appears under connected servers.
126142

127-
For cloud deployments or multi-client setups, run the Streamable HTTP transport:
143+
## Remote HTTP server & Docker
128144

129145
```bash
146+
# Streamable HTTP transport — MCP endpoint at http://host:8000/mcp
130147
python -m transport.http_transport --host 0.0.0.0 --port 8000
131148
```
132149

133-
The MCP endpoint is at `http://your-host:8000/mcp`.
134-
135-
Then configure your client with type `http` and URL `http://your-host:8000/mcp`.
136-
137-
## Docker
138-
139150
```bash
140151
docker build -t thinkmcp .
141-
```
142-
143-
Run the Streamlit UI:
144152

145-
```bash
153+
# Streamlit UI (talks to Ollama on the host machine)
146154
docker run -p 8501:8501 \
147-
-e ANTHROPIC_API_KEY="sk-ant-..." \
155+
-e OLLAMA_HOST="http://host.docker.internal:11434" \
148156
-e TAVILY_API_KEY="tvly-..." \
149-
-e GITHUB_TOKEN="ghp_..." \
150157
thinkmcp
158+
159+
# Or run the MCP HTTP server instead
160+
docker run -p 8000:8000 thinkmcp \
161+
python -m transport.http_transport --port 8000
151162
```
152163

153-
Run the MCP HTTP server instead:
164+
## Tests & quality
154165

155166
```bash
156-
docker run -p 8000:8000 \
157-
-e ANTHROPIC_API_KEY="sk-ant-..." \
158-
-e TAVILY_API_KEY="tvly-..." \
159-
thinkmcp \
160-
python -m transport.http_transport --port 8000
167+
pytest # 31 tests: tools, agent helpers, MCP server registration
168+
ruff check . # lint
161169
```
162170

163-
## Project Layout
171+
Both run in [GitHub Actions](.github/workflows/ci.yml) on Python 3.10 and 3.12 for every push and PR.
172+
173+
## Configuration
174+
175+
| Env var | Default | Purpose |
176+
|---|---|---|
177+
| `OLLAMA_HOST` | `http://localhost:11434` | Ollama server URL |
178+
| `THINKMCP_MODEL` | `qwen3:8b` | Default agent model |
179+
| `THINKMCP_NUM_CTX` | `16384` | Context window for the agent loop |
180+
| `THINKMCP_MEMORY_DB` | `./thinkmcp_memory.db` | SQLite memory location |
181+
| `THINKMCP_REPORTS_DIR` | `./reports` | Where `write_report` saves files |
182+
| `TAVILY_API_KEY` | — | Enables `web_search` |
183+
| `GITHUB_TOKEN` | — | Higher rate limits for `search_code` |
184+
185+
## Project layout
164186

165187
```
166188
thinkmcp/
@@ -169,25 +191,32 @@ thinkmcp/
169191
│ └── tools/
170192
│ ├── research.py # web_search, fetch_url, search_papers, search_code
171193
│ ├── reasoning.py # think, critique, plan
172-
│ ├── memory.py # remember, recall, list_memory
194+
│ ├── memory.py # remember, recall, list_memory (SQLite-backed)
173195
│ └── actions.py # write_report, create_summary, compare
174196
├── agent/
175-
│ ├── thinking_agent.py # agentic loop with adaptive thinking
176-
│ ├── tool_executor.py # in-process tool dispatch
177-
│ └── trace_parser.py # extracts thinking/tool blocks from responses
197+
│ ├── mcp_client.py # real MCP stdio client (tools/list + tools/call)
198+
│ └── thinking_agent.py # Ollama (Qwen 3) agentic loop with thinking
178199
├── transport/
179200
│ ├── stdio_transport.py # stdio launcher (Claude Desktop)
180201
│ └── http_transport.py # Streamable HTTP launcher (remote)
181-
├── app.py # Streamlit UI
182-
├── requirements.txt
183-
├── mcp_config.json # template config for MCP clients
202+
├── tests/ # pytest suite
203+
├── app.py # Streamlit UI with live-streaming trace
204+
├── pyproject.toml
184205
└── Dockerfile
185206
```
186207

187-
## Reports
208+
## Design notes
209+
210+
- `critique` and `plan` are **deterministic heuristics by choice** — instant, free, and reproducible. The LLM does the reasoning; these tools provide structure and a self-check ritual without burning tokens or adding nondeterminism.
211+
- Thinking capture degrades gracefully: native thinking stream when the model supports it, inline `<think>`-tag parsing when it doesn't.
212+
213+
## Roadmap
188214

189-
`write_report` saves markdown files to `THINKMCP_REPORTS_DIR` (default: `./reports/`). Files are timestamped: `report_my_topic_20240507_143022.md`.
215+
- [ ] Benchmark: answer quality with vs. without the reasoning tools on a fixed question set
216+
- [ ] LLM-judged critique mode (local, via Ollama) as an opt-in alternative to heuristics
217+
- [ ] Semantic memory recall (embeddings over the SQLite store)
218+
- [ ] One-command hosted demo
190219

191220
## License
192221

193-
MIT
222+
[MIT](LICENSE)

0 commit comments

Comments
 (0)