smart-agent-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smart_agent_mcp-0.1.0/.gitignore +50 -0
- smart_agent_mcp-0.1.0/LICENSE +21 -0
- smart_agent_mcp-0.1.0/PKG-INFO +260 -0
- smart_agent_mcp-0.1.0/README.md +228 -0
- smart_agent_mcp-0.1.0/pyproject.toml +87 -0
- smart_agent_mcp-0.1.0/smart_agent/__init__.py +24 -0
- smart_agent_mcp-0.1.0/smart_agent/analyzer.py +220 -0
- smart_agent_mcp-0.1.0/smart_agent/cli.py +73 -0
- smart_agent_mcp-0.1.0/smart_agent/config.py +63 -0
- smart_agent_mcp-0.1.0/smart_agent/doctor.py +129 -0
- smart_agent_mcp-0.1.0/smart_agent/lint.py +244 -0
- smart_agent_mcp-0.1.0/smart_agent/reflector.py +129 -0
- smart_agent_mcp-0.1.0/smart_agent/reporter.py +99 -0
- smart_agent_mcp-0.1.0/smart_agent/server.py +568 -0
- smart_agent_mcp-0.1.0/smart_agent/store.py +241 -0
- smart_agent_mcp-0.1.0/smoke_stdio.py +149 -0
- smart_agent_mcp-0.1.0/tests/__init__.py +0 -0
- smart_agent_mcp-0.1.0/tests/conftest.py +38 -0
- smart_agent_mcp-0.1.0/tests/test_analyzer.py +76 -0
- smart_agent_mcp-0.1.0/tests/test_cli.py +54 -0
- smart_agent_mcp-0.1.0/tests/test_doctor.py +64 -0
- smart_agent_mcp-0.1.0/tests/test_lint.py +124 -0
- smart_agent_mcp-0.1.0/tests/test_reflector.py +90 -0
- smart_agent_mcp-0.1.0/tests/test_server.py +97 -0
- smart_agent_mcp-0.1.0/tests/test_server_new.py +54 -0
- smart_agent_mcp-0.1.0/tests/test_store.py +81 -0
- smart_agent_mcp-0.1.0/uv.lock +1860 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# --- Python ------------------------------------------------------------
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
*.egg
|
|
11
|
+
*.egg-info/
|
|
12
|
+
|
|
13
|
+
# --- Test / lint caches ------------------------------------------------
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.coverage
|
|
18
|
+
.coverage.*
|
|
19
|
+
htmlcov/
|
|
20
|
+
.tox/
|
|
21
|
+
.nox/
|
|
22
|
+
|
|
23
|
+
# --- Virtual environments ---------------------------------------------
|
|
24
|
+
.venv/
|
|
25
|
+
venv/
|
|
26
|
+
env/
|
|
27
|
+
ENV/
|
|
28
|
+
|
|
29
|
+
# --- IDE / OS ---------------------------------------------------------
|
|
30
|
+
.vscode/
|
|
31
|
+
.idea/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
.DS_Store
|
|
35
|
+
Thumbs.db
|
|
36
|
+
|
|
37
|
+
# --- uv ----------------------------------------------------------------
|
|
38
|
+
# `uv.lock` is intentionally tracked: smart-agent is an installed
|
|
39
|
+
# tool, not a library; pinning ensures the same versions run across
|
|
40
|
+
# environments. Drop it from the repo if you'd rather not.
|
|
41
|
+
|
|
42
|
+
# --- Smart-agent runtime ----------------------------------------------
|
|
43
|
+
# The SQLite store lives at:
|
|
44
|
+
# %LOCALAPPDATA%/smart-agent/store.db (Windows)
|
|
45
|
+
# $XDG_DATA_HOME/smart-agent/store.db (POSIX)
|
|
46
|
+
# and is per-user, not per-project — already outside the working tree.
|
|
47
|
+
|
|
48
|
+
# `AGENTS.md` is the project-curated convention file. The default
|
|
49
|
+
# `Config.load()` writes to `<project_root>/AGENTS.md`. Track it if
|
|
50
|
+
# you want shared conventions; ignore it for personal-only state.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 cbunt
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: smart-agent-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A stateful coding-analysis MCP specialist — persistent lesson store, deterministic checks, evolving AGENTS.md.
|
|
5
|
+
Project-URL: Homepage, https://github.com/cbuntingde/smart-agent
|
|
6
|
+
Project-URL: Repository, https://github.com/cbuntingde/smart-agent.git
|
|
7
|
+
Project-URL: Issues, https://github.com/cbuntingde/smart-agent/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/cbuntingde/smart-agent/releases
|
|
9
|
+
Author: cbunt
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: agent,code-analysis,lint,mcp,memory,model-context-protocol,reflection,self-improving,static-analysis
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Requires-Dist: fastmcp<4.0,>=3.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# smart-agent
|
|
34
|
+
|
|
35
|
+
> ## ⚠️ Prototype / unvalidated idea — not production-tested
|
|
36
|
+
>
|
|
37
|
+
> This project exists to explore whether a "smart, self-evolving coding agent"
|
|
38
|
+
> is buildable with today's MCP + LLM tooling. It was assembled as a single
|
|
39
|
+
> focused session from a research scan, not from a backlog of real-world use.
|
|
40
|
+
>
|
|
41
|
+
> **What's been tested:** unit tests pass (44), a local stdio handshake with
|
|
42
|
+
> FastMCP works, and the doctor CLI runs. **What's *not* been tested:**
|
|
43
|
+
> extended use inside Kimi Code (or any other orchestrator), production data
|
|
44
|
+
> volumes, permission boundaries, scale of the lesson store, multi-session
|
|
45
|
+
> behaviour, conflicts with the rest of the user's MCP servers.
|
|
46
|
+
>
|
|
47
|
+
> Treat this as a **design probe**, not a finished product. The architecture
|
|
48
|
+
> and code are deliberately simple so they can be read, modified, and either
|
|
49
|
+
> proven-out or thrown away. Don't ship it to anyone else until you've actually
|
|
50
|
+
> used it yourself for a while.
|
|
51
|
+
|
|
52
|
+
A **stateful coding-analysis MCP specialist** for the Kimi Code (and Claude Code / Cursor / any MCP-aware orchestrator) agent loop. It holds a persistent lesson store, runs deterministic static checks the LLM shouldn't be trusted with, and helps a project *evolve* a curated rules file (`AGENTS.md`) over time.
|
|
53
|
+
|
|
54
|
+
## What's possible today — and what isn't
|
|
55
|
+
|
|
56
|
+
| Goal | Status |
|
|
57
|
+
|---|---|
|
|
58
|
+
| Persistent memory across sessions | ✅ SQLite + FTS5 lesson store |
|
|
59
|
+
| Deterministic static analysis | ✅ `analyze_path` (long fns, bare `except:`, TODO/FIXME, long lines, oversized files) |
|
|
60
|
+
| Living conventions file | ✅ `AGENTS.md` that the orchestrator appends to |
|
|
61
|
+
| Recall-at-start / record-at-end loop | ✅ via `recall_lessons` + `record_lesson` |
|
|
62
|
+
| Code self-modification of the agent itself | ❌ not shipping in any production tool |
|
|
63
|
+
| Online weight learning | ❌ not production-stable |
|
|
64
|
+
| True evolutionary self-improvement | ❌ research-only |
|
|
65
|
+
|
|
66
|
+
This agent doesn't try to do the impossible — it does the things that *actually* compose to "smarter over time":
|
|
67
|
+
|
|
68
|
+
1. **Lessons persist** across sessions (SQLite + FTS5 — semantic retrieval without an embedding model).
|
|
69
|
+
2. **The orchestrator applies them** via `recall_lessons` at task start.
|
|
70
|
+
3. **The orchestrator records new ones** via `record_lesson` after each task.
|
|
71
|
+
4. **The conventions file grows** as `set_convention` is called.
|
|
72
|
+
|
|
73
|
+
The orchestrator's LLM is the "reasoning" component. This agent is the **stateful, deterministic scaffolding around it**.
|
|
74
|
+
|
|
75
|
+
## Architecture
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
┌─────────────────────────────┐
|
|
79
|
+
│ Main AI agent (Kimi Code) │ ← does reasoning, talks to user
|
|
80
|
+
│ LLM / tool-calling loop │
|
|
81
|
+
└─────────────┬───────────────┘
|
|
82
|
+
│ MCP / stdio
|
|
83
|
+
▼
|
|
84
|
+
┌─────────────────────────────┐
|
|
85
|
+
│ smart-agent (this server) │
|
|
86
|
+
│ │
|
|
87
|
+
│ Tools: │
|
|
88
|
+
│ analyze_path ▶ findings │
|
|
89
|
+
│ record_lesson ▶ insert │
|
|
90
|
+
│ recall_lessons▶ search │
|
|
91
|
+
│ recent_lessons▶ tail │
|
|
92
|
+
│ mark_lesson_used ▶ bump │ ───┐
|
|
93
|
+
│ get_conventions │ │
|
|
94
|
+
│ set_convention │ │ SQLite + FTS5
|
|
95
|
+
│ propose_fix │ ───┤ lessons table
|
|
96
|
+
│ store_stats │ │ (WAL mode)
|
|
97
|
+
│ │ │
|
|
98
|
+
│ Resources: │ ▼
|
|
99
|
+
│ memory://recent ◀──── │ ┌────────────────────┐
|
|
100
|
+
│ memory://stats ◀──── │ │ store.db (FTS5) │
|
|
101
|
+
│ conventions://current │ └────────────────────┘
|
|
102
|
+
└─────────────────────────────┘ │
|
|
103
|
+
│ │
|
|
104
|
+
▼ ▼
|
|
105
|
+
┌─────────────┐ ┌─────────────┐
|
|
106
|
+
│ AGENTS.md │ │ SQLite DB │
|
|
107
|
+
│ (curated │ │ ~/.local/ │
|
|
108
|
+
│ rules) │ │ share/... │
|
|
109
|
+
└─────────────┘ └─────────────┘
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The agent itself has **no LLM call**. Every "intelligence" is the orchestrator's, mediated through deterministic tools.
|
|
113
|
+
|
|
114
|
+
## Caveats before you read further
|
|
115
|
+
|
|
116
|
+
This was assembled quickly and the goal was *to learn what such an agent
|
|
117
|
+
looks like*, not to ship a stable product. Specific things I have **not**
|
|
118
|
+
verified:
|
|
119
|
+
|
|
120
|
+
- **Behaviour as a real `mcp.json` server** in your daily Kimi Code sessions.
|
|
121
|
+
Only the `smoke_stdio.py` handshake has run, in isolation.
|
|
122
|
+
- **Tool-runtime edge cases** beyond what the unit tests cover: very large
|
|
123
|
+
codebases for `analyze_path`, pathological FTS5 inputs, store with >1k
|
|
124
|
+
lessons.
|
|
125
|
+
- **Multi-user / shared-`AGENTS.md` semantics.** Today every entry is just
|
|
126
|
+
appended; there is no merge logic or ownership tracking.
|
|
127
|
+
- **Prompt injection.** Convention text from this file is *not* fed back
|
|
128
|
+
into any LLM prompt by this server directly, but the orchestrator may
|
|
129
|
+
include it in its own context. Treat `AGENTS.md` like you treat any
|
|
130
|
+
other user-supplied file that ends up in an LLM prompt.
|
|
131
|
+
- **Concurrency.** The SQLite store is single-process; if you ever wire it
|
|
132
|
+
up so multiple sessions hit the same DB file, expect WAL contention.
|
|
133
|
+
- **The "evolution" claim.** The agent *accumulates* knowledge and
|
|
134
|
+
*suggests* conventions — whether that becomes a meaningfully better
|
|
135
|
+
coding agent over weeks of use is an open question. Use it long enough
|
|
136
|
+
to find out, or don't.
|
|
137
|
+
|
|
138
|
+
If you find a bug, file it as an issue or fix it inline and learn from
|
|
139
|
+
the patch — the code is short on purpose.
|
|
140
|
+
|
|
141
|
+
## Tools
|
|
142
|
+
|
|
143
|
+
| Tool | Purpose |
|
|
144
|
+
|---|---|
|
|
145
|
+
| `analyze_path(path, focus, max_files)` | Run built-in static checks; returns Markdown report + raw findings. |
|
|
146
|
+
| `lint_check(path, runs, timeout_seconds)` | Run `ruff` and/or `pytest` as subprocesses; returns findings in the same shape, with `source="ruff"`/`"pytest"`. Tools not on PATH are skipped. |
|
|
147
|
+
| `record_lesson(category, summary, evidence, tags)` | Persist an atomic lesson. Categories: `bug`, `style`, `perf`, `convention`, `debt`, `risky`, `win`. |
|
|
148
|
+
| `recall_lessons(query, k)` | Retrieve top-k lessons by FTS5 match. Empty query → recent. |
|
|
149
|
+
| `recent_lessons(limit)` | Chronological tail. |
|
|
150
|
+
| `by_category(category, limit)` | All lessons for a category. |
|
|
151
|
+
| `mark_lesson_used(lesson_id)` | Bump `times_used` when the orchestrator actually applied a lesson. |
|
|
152
|
+
| `get_conventions()` | Read the project's `AGENTS.md`. |
|
|
153
|
+
| `set_convention(text)` | Append a bullet to `AGENTS.md`. |
|
|
154
|
+
| `propose_fix(issue_summary, k)` | Stitch a fix sketch from past lessons. |
|
|
155
|
+
| `reflect(lookback_n, min_count, dry_run)` | Return a Markdown draft of new conventions from recent lessons. **Always non-destructive** — orchestrator decides which lines to apply via `set_convention`. |
|
|
156
|
+
| `store_stats()` | Total + per-category counts. |
|
|
157
|
+
| `doctor_tool()` | Same report as `smart-agent doctor` CLI, returned as a string. |
|
|
158
|
+
|
|
159
|
+
### Resources
|
|
160
|
+
|
|
161
|
+
| URI | Content |
|
|
162
|
+
|---|---|
|
|
163
|
+
| `memory://recent` | Last 20 lessons (Markdown). |
|
|
164
|
+
| `memory://stats` | Total + per-category counts. |
|
|
165
|
+
| `conventions://current` | Full `AGENTS.md` content. |
|
|
166
|
+
|
|
167
|
+
### Prompt
|
|
168
|
+
|
|
169
|
+
- `code_review(diff, focus)` — structured prompt that asks the orchestrator to start by recalling lessons and conventions before reviewing.
|
|
170
|
+
|
|
171
|
+
## Convention: recall-at-start / record-at-end
|
|
172
|
+
|
|
173
|
+
Smart agents get smarter only if the orchestrator follows this discipline:
|
|
174
|
+
|
|
175
|
+
```text
|
|
176
|
+
BEFORE tackling a task:
|
|
177
|
+
1. Call recall_lessons(query=task_topic, k=5)
|
|
178
|
+
2. Read conventions://current
|
|
179
|
+
3. Apply each relevant rule before flagging it as a new finding
|
|
180
|
+
|
|
181
|
+
AFTER each non-trivial task (or whenever you learn something reusable):
|
|
182
|
+
1. Call record_lesson(category, summary, evidence, tags)
|
|
183
|
+
- Keep summary atomic (~80 chars)
|
|
184
|
+
- Category must be one of: bug, style, perf, convention, debt, risky, win
|
|
185
|
+
- Tags comma-separated, no spaces within tags
|
|
186
|
+
2. If the lesson is project-wide, also call set_convention(...)
|
|
187
|
+
- Use plain English, 1-3 sentences
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The MCP server's `instructions` field repeats this so any MCP-aware orchestrator gets the reminder at session start.
|
|
191
|
+
|
|
192
|
+
## Storage
|
|
193
|
+
|
|
194
|
+
| Path | Purpose |
|
|
195
|
+
|---|---|
|
|
196
|
+
| `~/.local/share/smart-agent/store.db` (POSIX) | SQLite DB |
|
|
197
|
+
| `%LOCALAPPDATA%/smart-agent/store.db` (Win) | SQLite DB |
|
|
198
|
+
| `<project>/AGENTS.md` | Curated conventions file (track in git!) |
|
|
199
|
+
|
|
200
|
+
Override the data dir with `SMART_AGENT_HOME=/path/to/dir`.
|
|
201
|
+
|
|
202
|
+
## Run the server
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
uv sync
|
|
206
|
+
uv run smart-agent # stdio transport (== `smart-agent serve`)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Run diagnostics
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
uv run smart-agent doctor
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Validates paths, DB integrity, linter availability, and store contents. Exit code 0 = OK; 1 = a hard error (DB unreadable, store corrupt). WARN lines (linters missing, conventions file absent) don't fail the doctor.
|
|
216
|
+
|
|
217
|
+
## Wire it into Kimi Code CLI
|
|
218
|
+
|
|
219
|
+
`~/.kimi-code/mcp.json`:
|
|
220
|
+
|
|
221
|
+
```json
|
|
222
|
+
{
|
|
223
|
+
"mcpServers": {
|
|
224
|
+
"smart-agent": {
|
|
225
|
+
"command": "uv",
|
|
226
|
+
"args": ["--directory", "C:/az-mcpservers/smart-agent", "run", "smart-agent"]
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Tests
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
uv run pytest
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
44 tests across `tests/test_{store,analyzer,server,server_new,lint,reflector,doctor,cli}.py`.
|
|
239
|
+
|
|
240
|
+
There's also a real-subprocess stdio handshake verifier:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
uv run python smoke_stdio.py
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
The test suite uses the FastMCP in-memory `Client` (`from fastmcp import Client`) so the full MCP protocol path is exercised without spawning subprocesses.
|
|
247
|
+
|
|
248
|
+
## Roadmap
|
|
249
|
+
|
|
250
|
+
Things to add when this first version needs more muscle:
|
|
251
|
+
|
|
252
|
+
1. **Semantic recall.** Replace FTS5 with `sqlite-vec` for embedding-based search when >10k lessons pile up.
|
|
253
|
+
2. **Reflection worker.** Add a `reflect(lookback_n=50)` tool that returns a summary of recent lessons grouped by category — the orchestrator reads it and proposes a new `AGENTS.md` draft. Already half-built (`propose_fix` does the pattern-match half).
|
|
254
|
+
3. **Per-check tooling.** Compose with Ruff/mypy/pytest via subprocess and feed results into the same `Finding` shape.
|
|
255
|
+
4. **DSPy offline optimization.** Once you have a labelled "what worked / didn't" set, run GEPA/MIPROv2 against this agent's prompts as a batch job.
|
|
256
|
+
5. **Project isolation.** Multi-tenant the SQLite by `project_root` so a monorepo can keep per-package lessons.
|
|
257
|
+
|
|
258
|
+
## License
|
|
259
|
+
|
|
260
|
+
MIT.
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# smart-agent
|
|
2
|
+
|
|
3
|
+
> ## ⚠️ Prototype / unvalidated idea — not production-tested
|
|
4
|
+
>
|
|
5
|
+
> This project exists to explore whether a "smart, self-evolving coding agent"
|
|
6
|
+
> is buildable with today's MCP + LLM tooling. It was assembled as a single
|
|
7
|
+
> focused session from a research scan, not from a backlog of real-world use.
|
|
8
|
+
>
|
|
9
|
+
> **What's been tested:** unit tests pass (44), a local stdio handshake with
|
|
10
|
+
> FastMCP works, and the doctor CLI runs. **What's *not* been tested:**
|
|
11
|
+
> extended use inside Kimi Code (or any other orchestrator), production data
|
|
12
|
+
> volumes, permission boundaries, scale of the lesson store, multi-session
|
|
13
|
+
> behaviour, conflicts with the rest of the user's MCP servers.
|
|
14
|
+
>
|
|
15
|
+
> Treat this as a **design probe**, not a finished product. The architecture
|
|
16
|
+
> and code are deliberately simple so they can be read, modified, and either
|
|
17
|
+
> proven-out or thrown away. Don't ship it to anyone else until you've actually
|
|
18
|
+
> used it yourself for a while.
|
|
19
|
+
|
|
20
|
+
A **stateful coding-analysis MCP specialist** for the Kimi Code (and Claude Code / Cursor / any MCP-aware orchestrator) agent loop. It holds a persistent lesson store, runs deterministic static checks the LLM shouldn't be trusted with, and helps a project *evolve* a curated rules file (`AGENTS.md`) over time.
|
|
21
|
+
|
|
22
|
+
## What's possible today — and what isn't
|
|
23
|
+
|
|
24
|
+
| Goal | Status |
|
|
25
|
+
|---|---|
|
|
26
|
+
| Persistent memory across sessions | ✅ SQLite + FTS5 lesson store |
|
|
27
|
+
| Deterministic static analysis | ✅ `analyze_path` (long fns, bare `except:`, TODO/FIXME, long lines, oversized files) |
|
|
28
|
+
| Living conventions file | ✅ `AGENTS.md` that the orchestrator appends to |
|
|
29
|
+
| Recall-at-start / record-at-end loop | ✅ via `recall_lessons` + `record_lesson` |
|
|
30
|
+
| Code self-modification of the agent itself | ❌ not shipping in any production tool |
|
|
31
|
+
| Online weight learning | ❌ not production-stable |
|
|
32
|
+
| True evolutionary self-improvement | ❌ research-only |
|
|
33
|
+
|
|
34
|
+
This agent doesn't try to do the impossible — it does the things that *actually* compose to "smarter over time":
|
|
35
|
+
|
|
36
|
+
1. **Lessons persist** across sessions (SQLite + FTS5 — semantic retrieval without an embedding model).
|
|
37
|
+
2. **The orchestrator applies them** via `recall_lessons` at task start.
|
|
38
|
+
3. **The orchestrator records new ones** via `record_lesson` after each task.
|
|
39
|
+
4. **The conventions file grows** as `set_convention` is called.
|
|
40
|
+
|
|
41
|
+
The orchestrator's LLM is the "reasoning" component. This agent is the **stateful, deterministic scaffolding around it**.
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
┌─────────────────────────────┐
|
|
47
|
+
│ Main AI agent (Kimi Code) │ ← does reasoning, talks to user
|
|
48
|
+
│ LLM / tool-calling loop │
|
|
49
|
+
└─────────────┬───────────────┘
|
|
50
|
+
│ MCP / stdio
|
|
51
|
+
▼
|
|
52
|
+
┌─────────────────────────────┐
|
|
53
|
+
│ smart-agent (this server) │
|
|
54
|
+
│ │
|
|
55
|
+
│ Tools: │
|
|
56
|
+
│ analyze_path ▶ findings │
|
|
57
|
+
│ record_lesson ▶ insert │
|
|
58
|
+
│ recall_lessons▶ search │
|
|
59
|
+
│ recent_lessons▶ tail │
|
|
60
|
+
│ mark_lesson_used ▶ bump │ ───┐
|
|
61
|
+
│ get_conventions │ │
|
|
62
|
+
│ set_convention │ │ SQLite + FTS5
|
|
63
|
+
│ propose_fix │ ───┤ lessons table
|
|
64
|
+
│ store_stats │ │ (WAL mode)
|
|
65
|
+
│ │ │
|
|
66
|
+
│ Resources: │ ▼
|
|
67
|
+
│ memory://recent ◀──── │ ┌────────────────────┐
|
|
68
|
+
│ memory://stats ◀──── │ │ store.db (FTS5) │
|
|
69
|
+
│ conventions://current │ └────────────────────┘
|
|
70
|
+
└─────────────────────────────┘ │
|
|
71
|
+
│ │
|
|
72
|
+
▼ ▼
|
|
73
|
+
┌─────────────┐ ┌─────────────┐
|
|
74
|
+
│ AGENTS.md │ │ SQLite DB │
|
|
75
|
+
│ (curated │ │ ~/.local/ │
|
|
76
|
+
│ rules) │ │ share/... │
|
|
77
|
+
└─────────────┘ └─────────────┘
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The agent itself has **no LLM call**. Every "intelligence" is the orchestrator's, mediated through deterministic tools.
|
|
81
|
+
|
|
82
|
+
## Caveats before you read further
|
|
83
|
+
|
|
84
|
+
This was assembled quickly and the goal was *to learn what such an agent
|
|
85
|
+
looks like*, not to ship a stable product. Specific things I have **not**
|
|
86
|
+
verified:
|
|
87
|
+
|
|
88
|
+
- **Behaviour as a real `mcp.json` server** in your daily Kimi Code sessions.
|
|
89
|
+
Only the `smoke_stdio.py` handshake has run, in isolation.
|
|
90
|
+
- **Tool-runtime edge cases** beyond what the unit tests cover: very large
|
|
91
|
+
codebases for `analyze_path`, pathological FTS5 inputs, store with >1k
|
|
92
|
+
lessons.
|
|
93
|
+
- **Multi-user / shared-`AGENTS.md` semantics.** Today every entry is just
|
|
94
|
+
appended; there is no merge logic or ownership tracking.
|
|
95
|
+
- **Prompt injection.** Convention text from this file is *not* fed back
|
|
96
|
+
into any LLM prompt by this server directly, but the orchestrator may
|
|
97
|
+
include it in its own context. Treat `AGENTS.md` like you treat any
|
|
98
|
+
other user-supplied file that ends up in an LLM prompt.
|
|
99
|
+
- **Concurrency.** The SQLite store is single-process; if you ever wire it
|
|
100
|
+
up so multiple sessions hit the same DB file, expect WAL contention.
|
|
101
|
+
- **The "evolution" claim.** The agent *accumulates* knowledge and
|
|
102
|
+
*suggests* conventions — whether that becomes a meaningfully better
|
|
103
|
+
coding agent over weeks of use is an open question. Use it long enough
|
|
104
|
+
to find out, or don't.
|
|
105
|
+
|
|
106
|
+
If you find a bug, file it as an issue or fix it inline and learn from
|
|
107
|
+
the patch — the code is short on purpose.
|
|
108
|
+
|
|
109
|
+
## Tools
|
|
110
|
+
|
|
111
|
+
| Tool | Purpose |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `analyze_path(path, focus, max_files)` | Run built-in static checks; returns Markdown report + raw findings. |
|
|
114
|
+
| `lint_check(path, runs, timeout_seconds)` | Run `ruff` and/or `pytest` as subprocesses; returns findings in the same shape, with `source="ruff"`/`"pytest"`. Tools not on PATH are skipped. |
|
|
115
|
+
| `record_lesson(category, summary, evidence, tags)` | Persist an atomic lesson. Categories: `bug`, `style`, `perf`, `convention`, `debt`, `risky`, `win`. |
|
|
116
|
+
| `recall_lessons(query, k)` | Retrieve top-k lessons by FTS5 match. Empty query → recent. |
|
|
117
|
+
| `recent_lessons(limit)` | Chronological tail. |
|
|
118
|
+
| `by_category(category, limit)` | All lessons for a category. |
|
|
119
|
+
| `mark_lesson_used(lesson_id)` | Bump `times_used` when the orchestrator actually applied a lesson. |
|
|
120
|
+
| `get_conventions()` | Read the project's `AGENTS.md`. |
|
|
121
|
+
| `set_convention(text)` | Append a bullet to `AGENTS.md`. |
|
|
122
|
+
| `propose_fix(issue_summary, k)` | Stitch a fix sketch from past lessons. |
|
|
123
|
+
| `reflect(lookback_n, min_count, dry_run)` | Return a Markdown draft of new conventions from recent lessons. **Always non-destructive** — orchestrator decides which lines to apply via `set_convention`. |
|
|
124
|
+
| `store_stats()` | Total + per-category counts. |
|
|
125
|
+
| `doctor_tool()` | Same report as `smart-agent doctor` CLI, returned as a string. |
|
|
126
|
+
|
|
127
|
+
### Resources
|
|
128
|
+
|
|
129
|
+
| URI | Content |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `memory://recent` | Last 20 lessons (Markdown). |
|
|
132
|
+
| `memory://stats` | Total + per-category counts. |
|
|
133
|
+
| `conventions://current` | Full `AGENTS.md` content. |
|
|
134
|
+
|
|
135
|
+
### Prompt
|
|
136
|
+
|
|
137
|
+
- `code_review(diff, focus)` — structured prompt that asks the orchestrator to start by recalling lessons and conventions before reviewing.
|
|
138
|
+
|
|
139
|
+
## Convention: recall-at-start / record-at-end
|
|
140
|
+
|
|
141
|
+
Smart agents get smarter only if the orchestrator follows this discipline:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
BEFORE tackling a task:
|
|
145
|
+
1. Call recall_lessons(query=task_topic, k=5)
|
|
146
|
+
2. Read conventions://current
|
|
147
|
+
3. Apply each relevant rule before flagging it as a new finding
|
|
148
|
+
|
|
149
|
+
AFTER each non-trivial task (or whenever you learn something reusable):
|
|
150
|
+
1. Call record_lesson(category, summary, evidence, tags)
|
|
151
|
+
- Keep summary atomic (~80 chars)
|
|
152
|
+
- Category must be one of: bug, style, perf, convention, debt, risky, win
|
|
153
|
+
- Tags comma-separated, no spaces within tags
|
|
154
|
+
2. If the lesson is project-wide, also call set_convention(...)
|
|
155
|
+
- Use plain English, 1-3 sentences
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The MCP server's `instructions` field repeats this so any MCP-aware orchestrator gets the reminder at session start.
|
|
159
|
+
|
|
160
|
+
## Storage
|
|
161
|
+
|
|
162
|
+
| Path | Purpose |
|
|
163
|
+
|---|---|
|
|
164
|
+
| `~/.local/share/smart-agent/store.db` (POSIX) | SQLite DB |
|
|
165
|
+
| `%LOCALAPPDATA%/smart-agent/store.db` (Win) | SQLite DB |
|
|
166
|
+
| `<project>/AGENTS.md` | Curated conventions file (track in git!) |
|
|
167
|
+
|
|
168
|
+
Override the data dir with `SMART_AGENT_HOME=/path/to/dir`.
|
|
169
|
+
|
|
170
|
+
## Run the server
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
uv sync
|
|
174
|
+
uv run smart-agent # stdio transport (== `smart-agent serve`)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Run diagnostics
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
uv run smart-agent doctor
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Validates paths, DB integrity, linter availability, and store contents. Exit code 0 = OK; 1 = a hard error (DB unreadable, store corrupt). WARN lines (linters missing, conventions file absent) don't fail the doctor.
|
|
184
|
+
|
|
185
|
+
## Wire it into Kimi Code CLI
|
|
186
|
+
|
|
187
|
+
`~/.kimi-code/mcp.json`:
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
{
|
|
191
|
+
"mcpServers": {
|
|
192
|
+
"smart-agent": {
|
|
193
|
+
"command": "uv",
|
|
194
|
+
"args": ["--directory", "C:/az-mcpservers/smart-agent", "run", "smart-agent"]
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Tests
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
uv run pytest
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
44 tests across `tests/test_{store,analyzer,server,server_new,lint,reflector,doctor,cli}.py`.
|
|
207
|
+
|
|
208
|
+
There's also a real-subprocess stdio handshake verifier:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
uv run python smoke_stdio.py
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The test suite uses the FastMCP in-memory `Client` (`from fastmcp import Client`) so the full MCP protocol path is exercised without spawning subprocesses.
|
|
215
|
+
|
|
216
|
+
## Roadmap
|
|
217
|
+
|
|
218
|
+
Things to add when this first version needs more muscle:
|
|
219
|
+
|
|
220
|
+
1. **Semantic recall.** Replace FTS5 with `sqlite-vec` for embedding-based search when >10k lessons pile up.
|
|
221
|
+
2. **Reflection worker.** Add a `reflect(lookback_n=50)` tool that returns a summary of recent lessons grouped by category — the orchestrator reads it and proposes a new `AGENTS.md` draft. Already half-built (`propose_fix` does the pattern-match half).
|
|
222
|
+
3. **Per-check tooling.** Compose with Ruff/mypy/pytest via subprocess and feed results into the same `Finding` shape.
|
|
223
|
+
4. **DSPy offline optimization.** Once you have a labelled "what worked / didn't" set, run GEPA/MIPROv2 against this agent's prompts as a batch job.
|
|
224
|
+
5. **Project isolation.** Multi-tenant the SQLite by `project_root` so a monorepo can keep per-package lessons.
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
MIT.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "smart-agent-mcp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A stateful coding-analysis MCP specialist — persistent lesson store, deterministic checks, evolving AGENTS.md."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "cbunt" },
|
|
10
|
+
]
|
|
11
|
+
keywords = [
|
|
12
|
+
"mcp",
|
|
13
|
+
"agent",
|
|
14
|
+
"code-analysis",
|
|
15
|
+
"self-improving",
|
|
16
|
+
"memory",
|
|
17
|
+
"model-context-protocol",
|
|
18
|
+
"static-analysis",
|
|
19
|
+
"lint",
|
|
20
|
+
"reflection",
|
|
21
|
+
]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 3 - Alpha",
|
|
24
|
+
"Intended Audience :: Developers",
|
|
25
|
+
"License :: OSI Approved :: MIT License",
|
|
26
|
+
"Operating System :: OS Independent",
|
|
27
|
+
"Programming Language :: Python :: 3",
|
|
28
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
29
|
+
"Programming Language :: Python :: 3.10",
|
|
30
|
+
"Programming Language :: Python :: 3.11",
|
|
31
|
+
"Programming Language :: Python :: 3.12",
|
|
32
|
+
"Programming Language :: Python :: 3.13",
|
|
33
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
34
|
+
"Typing :: Typed",
|
|
35
|
+
]
|
|
36
|
+
dependencies = [
|
|
37
|
+
# Standalone FastMCP (Prefect) — actively maintained, v3.x.
|
|
38
|
+
# NOT the legacy `mcp.server.fastmcp` 1.0 surface in the official SDK.
|
|
39
|
+
"fastmcp>=3.0,<4.0",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://github.com/cbuntingde/smart-agent"
|
|
44
|
+
Repository = "https://github.com/cbuntingde/smart-agent.git"
|
|
45
|
+
Issues = "https://github.com/cbuntingde/smart-agent/issues"
|
|
46
|
+
Changelog = "https://github.com/cbuntingde/smart-agent/releases"
|
|
47
|
+
|
|
48
|
+
[project.scripts]
|
|
49
|
+
# Entry point. `smart-agent [serve]` runs the MCP server; `smart-agent doctor`
|
|
50
|
+
# runs diagnostics. Default subcommand is `serve`.
|
|
51
|
+
smart-agent = "smart_agent.cli:main"
|
|
52
|
+
|
|
53
|
+
[project.optional-dependencies]
|
|
54
|
+
dev = [
|
|
55
|
+
"pytest>=8.0",
|
|
56
|
+
"pytest-asyncio>=0.23",
|
|
57
|
+
"ruff>=0.5",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
# PEP 735 — uv uses this for `uv sync --group dev` etc. Equivalent to the
|
|
61
|
+
# `dev` extra above but recognised by uv tooling.
|
|
62
|
+
[dependency-groups]
|
|
63
|
+
dev = [
|
|
64
|
+
"pytest>=8.0",
|
|
65
|
+
"pytest-asyncio>=0.23",
|
|
66
|
+
"ruff>=0.5",
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
[build-system]
|
|
70
|
+
requires = ["hatchling"]
|
|
71
|
+
build-backend = "hatchling.build"
|
|
72
|
+
|
|
73
|
+
# Hatchling auto-includes LICENSE / README / NOTICE from the project root
|
|
74
|
+
# into the wheel's dist-info. No explicit force-include needed.
|
|
75
|
+
[tool.hatch.build.targets.wheel]
|
|
76
|
+
packages = ["smart_agent"]
|
|
77
|
+
|
|
78
|
+
[tool.pytest.ini_options]
|
|
79
|
+
asyncio_mode = "auto"
|
|
80
|
+
testpaths = ["tests"]
|
|
81
|
+
|
|
82
|
+
[tool.ruff]
|
|
83
|
+
line-length = 100
|
|
84
|
+
target-version = "py310"
|
|
85
|
+
|
|
86
|
+
[tool.ruff.lint]
|
|
87
|
+
select = ["E", "F", "I", "B", "UP", "W"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""smart-agent — a stateful coding-analysis MCP specialist.
|
|
2
|
+
|
|
3
|
+
Design (see README.md for full evolution model):
|
|
4
|
+
|
|
5
|
+
- Tools: record_lesson, recall_lessons, analyze_path, recent_lessons,
|
|
6
|
+
get_conventions, set_convention, propose_fix.
|
|
7
|
+
- Resources: memory://recent (live updates), conventions://current.
|
|
8
|
+
- Storage: SQLite + FTS5 lesson store at ~/.local/share/smart-agent/store.db.
|
|
9
|
+
- Conventions: AGENTS.md as a human-readable, agent-curated rule file.
|
|
10
|
+
|
|
11
|
+
The smart agent does NOT call any LLM itself — every "intelligence" call
|
|
12
|
+
comes from the orchestrator (Kimi Code / Claude Code / etc). The agent's
|
|
13
|
+
job is to (a) hold persistent state across sessions, (b) run deterministic
|
|
14
|
+
static checks the LLM can't be trusted with, (c) make past lessons
|
|
15
|
+
trivially retrievable so the orchestrator can apply them.
|
|
16
|
+
|
|
17
|
+
That's what enables "evolution" today: persistent lessons + an orchestrator
|
|
18
|
+
that follows the recall-at-start / record-at-end convention.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from smart_agent.config import Config
|
|
22
|
+
|
|
23
|
+
__all__ = ["Config"]
|
|
24
|
+
__version__ = "0.1.0"
|