Skip to content
This repository was archived by the owner on Sep 3, 2026. It is now read-only.

Commit 19f1ede

Browse files
author
outlndrr
committed
feat(agent): add local skills and MCP tools
- move discovered skills to Lummy-owned paths and add /new slash UI - surface tool timeout/retry metadata and assistant fallback on tool failure - add stdio MCP discovery/runtime docs and tests
1 parent e39a536 commit 19f1ede

38 files changed

Lines changed: 5408 additions & 622 deletions

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ Notes:
192192
- UI talks to same-origin backend routes, so no CORS setup needed
193193
- backend still requires `LUMMY_OPENROUTER_API_KEY`
194194
- UI opens live session SSE stream at `/api/v1/sessions/:id/events`
195+
- typing `/` opens slash commands for `/new` and discovered `/skill:<name>` entries
195196
- UI includes debug pane for HTTP actions, SSE status, and streamed events
196197
- backend now logs request + run/provider/tool lifecycle to Erlang logger
197198

@@ -234,7 +235,9 @@ Notes:
234235
| `LUMMY_AGENT_ALLOWED_TOOL_CAPABILITIES` | `math,filesystem_read,network,external_api,memory` | Default capability allowlist; blocks `file_write` and `shell_command` by default |
235236
| `LUMMY_AGENT_MAX_TOOL_RISK` | `low` | Global tool risk ceiling |
236237
| `LUMMY_AGENT_EXTERNAL_PROVIDER_MAX_TOOL_RISK` | `low` | Extra risk ceiling applied when non-`basic-local` provider is in chain |
237-
| `LUMMY_SKILLS_PATH` | `./skills` | Directory of local JSON skill manifests |
238+
| `LUMMY_SKILLS_PATH` | `./skills` | Directory of local Agent Skills packages (`<name>/SKILL.md`) used by explicit `skill_ids` |
239+
| `LUMMY_AGENT_SKILL_DISCOVERY_PATH` | `./skills` | Directory scanned for discovered slash/model-visible skills; relative paths resolve under `LUMMY_AGENT_TOOL_FILE_ROOT` |
240+
| `LUMMY_MCP_SERVERS_PATH` | `./mcp_servers.json` | Local MCP server config file |
238241

239242
## Dev
240243

@@ -260,6 +263,8 @@ Or from `cmd.exe` / PowerShell in project root use bundled `rebar3.cmd` wrapper.
260263
- Domain core notes: `docs/domain-core.md`
261264
- Persistence notes: `docs/persistence.md`
262265
- Session runtime notes: `docs/session-runtime.md`
266+
- Skills v1: `docs/skills.md`
267+
- MCP v1: `docs/mcp.md`
263268
- Quickstart: `docs/quickstart.md`
264269
- HTTP API notes: `docs/http-api.md`
265270
- Event stream notes: `docs/event-stream.md`

TODO.md

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,35 @@
2828
- [x] add `skill_ids` on run start
2929
- [x] persist effective skill config on `AgentRun`
3030
- [x] merge prompt/provider/tool policy deterministically
31-
- [ ] add registry abstraction and richer manifest consumption (`memory_hints`, `tags`)
32-
- [ ] document stable merge rules + sample manifests
31+
- [x] add registry abstraction and richer manifest consumption (`memory_hints`, `tags`)
32+
- [x] document stable merge rules + sample manifests
33+
- [x] align local skill packaging with Agent Skills `SKILL.md` spec
3334

3435
### M4. MCP v1
35-
- [ ] add stdio MCP client lifecycle
36-
- [ ] discover MCP tools into local tool definitions
37-
- [ ] keep local capability/risk mapping authoritative
38-
- [ ] execute MCP tools through current tool-call lifecycle
39-
- [ ] add timeout/cancel/retry tests
36+
- [ ] add session-scoped stdio MCP client lifecycle
37+
- [x] discover MCP tools into local tool definitions
38+
- [x] keep local capability/risk mapping authoritative
39+
- [x] execute MCP tools through current tool-call/runtime path
40+
- [ ] translate MCP input schemas/result payloads more faithfully
41+
- [ ] add explicit cancel/retry coverage beyond timeout path
4042

4143
### M5. Safety groundwork after M1-M4
4244
- [ ] API auth groundwork
4345
- [ ] secret storage groundwork
4446
- [ ] audit log groundwork
4547
- [ ] quotas / budgets groundwork
4648

49+
## Improvements pass (from IMPROVEMENTS.md)
50+
- [x] add slash command `/new` in UI
51+
- [x] constrain slash menu height, add scroll, bump menu text size
52+
- [x] support multiline `description: >` skill frontmatter values
53+
- [x] stop discovered-skill lookup from reading Pi paths; use Lummy config/env path instead
54+
- [x] fix explicit skill use path so discovered skills load reliably
55+
- [x] add assistant fallback message when tool call fails
56+
- [x] verify tool retries/timeouts and cover with tests
57+
- [x] reduce duplicate snapshot refresh at end of agent run
58+
- [x] clean up touched code/docs/tests
59+
4760
## Notes
4861
- Removed planning docs after folding execution order into this file.
49-
- Current implementation pass completed M1 and M2, plus core M3 skill plumbing.
62+
- Current implementation pass completed M1, M2, M3, and partial M4.

docs/http-api.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Copy-paste examples live in `docs/quickstart.md`.
1515
- `POST /api/v1/providers/openai-compatible/verify`
1616

1717
### Session and run API
18+
- `GET /api/v1/skills`
19+
- `GET /api/v1/sessions`
1820
- `POST /api/v1/sessions`
1921
- `GET /api/v1/sessions/:id`
2022
- `POST /api/v1/sessions/:id/messages`
@@ -42,7 +44,13 @@ Copy-paste examples live in `docs/quickstart.md`.
4244
- message append routes through `session_manager` -> `session_actor`
4345
- run start routes through `session_manager` -> `session_actor`
4446
- higher-level basic agent runs route through `basic_agent` orchestration
45-
- start-run request supports per-run execution policy and skill selection (`skill_ids` map to Agent Skills `name` / directory names under `LUMMY_SKILLS_PATH`):
47+
- `GET /api/v1/skills` returns discovered skills from `LUMMY_AGENT_SKILL_DISCOVERY_PATH` resolved relative to `tools.file_root` when needed
48+
- message append accepts `metadata` string fields; explicit callers can invoke discovered skills by setting:
49+
- `lummy_agent.skill: <name>` or `skill: <name>`
50+
- `lummy_agent.skills: comma,separated,names` or `skills: comma,separated,names`
51+
- `/ui` exposes discovered skills through a generic slash menu: typing `/` routes to `/new` and `/skill:<name>` entries with descriptions
52+
- explicit user skill invocations are expanded into the user prompt even when hidden from model-visible auto invocation
53+
- start-run request supports per-run execution policy and Agent Skills selection (`skill_ids` map to Agent Skills `name` / directory names under `LUMMY_SKILLS_PATH` / `skills.path` compatibility root):
4654
- `provider_fallback_ids`
4755
- `skill_ids`
4856
- `allowed_tools`
@@ -56,13 +64,15 @@ Copy-paste examples live in `docs/quickstart.md`.
5664
- `apply-result` persists tool output, appends tool message, and resumes run back to `calling_model`
5765
- `respond` appends assistant message and completes run from the model-response boundary
5866
- run JSON includes `provider_fallback_ids`, `tool_policy`, `skill_ids`, `skill_prompt_append`, `skill_memory_hints`, `skill_tags`, `plan_tasks`, and `scratchpad`
59-
- tool call list route reads persisted tool calls for a run
67+
- chat messages preserve metadata, allowing UI to surface user skill commands and agent-used skill reads in the transcript
68+
- tool call list route reads persisted tool calls for a run and includes runtime `timeout_ms`, `max_retries`, and `max_attempts`
6069
- SSE routes honor `Last-Event-ID` for persisted replay before live streaming
6170
- without `Last-Event-ID`, SSE routes stay live-only
6271
- event-log routes return persisted envelopes as JSON for debugging
6372
- event-log routes accept optional `after=<sequence>` query filtering
6473
- session memory route returns stored memory entries plus scored recall matches
6574
- session memory route accepts optional `query=<text>` and `limit=<n>`
75+
- basic agent tool failures fall back to an assistant message in the snapshot instead of returning a bare route error when the run can be completed with an explanation
6676
- responses are JSON only for now
6777

6878
## Runtime wiring
@@ -74,8 +84,7 @@ Copy-paste examples live in `docs/quickstart.md`.
7484
## Current limitations
7585
- no websocket API yet
7686
- no auth on API routes yet
77-
- no session list endpoint yet
78-
- no pagination controls on event-log routes yet
87+
- no pagination controls on session list or event-log routes yet
7988
- no attachment / artifact upload surface yet
8089
- simple Lustre UI exists at `GET /ui`, consumes session SSE directly, and shows a debug pane for live events
8190

docs/mcp.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# MCP v1
2+
3+
MCP support currently enters lummy as tool source.
4+
5+
## Config
6+
7+
- `LUMMY_MCP_SERVERS_PATH` defaults to `./mcp_servers.json`
8+
- if config file is missing, no MCP servers are loaded
9+
10+
## Server config format
11+
12+
```json
13+
{
14+
"servers": [
15+
{
16+
"server_id": "fake",
17+
"command": "uvx mcp-server-example",
18+
"working_directory": ".",
19+
"tool_mappings": [
20+
{
21+
"tool_name": "search",
22+
"capabilities": ["external_api"],
23+
"risk": "low",
24+
"timeout_ms": 5000
25+
}
26+
]
27+
}
28+
]
29+
}
30+
```
31+
32+
## Local policy rules
33+
34+
Local config is source of truth.
35+
36+
- only tools present in `tool_mappings` are exposed
37+
- unmapped discovered tools are ignored
38+
- local `capabilities` decide capability policy checks
39+
- local `risk` decides risk policy checks
40+
- local `timeout_ms` drives invocation timeout
41+
- tool names are namespaced as `mcp:<server_id>:<tool_name>`
42+
43+
## Runtime behavior
44+
45+
- tool discovery calls MCP `tools/list` over stdio
46+
- tool invocation calls MCP `tools/call` over stdio
47+
- discovered MCP tools are merged with built-in tools for run execution
48+
- run policy is extended with mapped MCP tool names, then normal capability/risk checks still apply
49+
- timeout handling reuses existing tool worker timeout path
50+
51+
## Current limits
52+
53+
- stdio only
54+
- one-off stdio handshake per discovery/call today; no long-lived client actor yet
55+
- generic object schema exposed to provider today; MCP input schema is not yet translated through
56+
- content extraction currently keeps text content only from `tools/call` result
57+
- no prompts/resources/sampling support yet

0 commit comments

Comments
 (0)