Skip to content

Commit 206adf4

Browse files
committed
feat(mcp): add direct knowledge dump via ask all=true
When all=true, the ask tool now returns all nodes directly from SQLite grouped by type, bypassing semantic search and LLM calls entirely. Single request, instant response. Updates the context skill to use it.
1 parent 0930416 commit 206adf4

3 files changed

Lines changed: 68 additions & 10 deletions

File tree

cmd/mcp_server.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func runMCPServer(ctx context.Context) error {
164164
// Register ask tool - retrieves stored codebase knowledge for AI context
165165
tool := &mcpsdk.Tool{
166166
Name: "ask",
167-
Description: "Search project knowledge: decisions, patterns, constraints, and code symbols. Returns an AI-synthesized answer and relevant context by default. Use {\"query\":\"search term\"} for semantic search.",
167+
Description: "Search project knowledge: decisions, patterns, constraints, and code symbols. Returns an AI-synthesized answer and relevant context by default. Use {\"query\":\"search term\"} for semantic search. Use {\"all\":true} for a complete knowledge dump (no LLM calls, instant).",
168168
}
169169

170170
mcpsdk.AddTool(server, tool, func(ctx context.Context, session *mcpsdk.ServerSession, params *mcpsdk.CallToolParamsFor[mcppresenter.ProjectContextParams]) (*mcpsdk.CallToolResultFor[any], error) {
@@ -320,6 +320,16 @@ REQUIRED FIELDS BY ACTION:
320320
// This ensures MCP and CLI use identical search logic with zero drift.
321321
// Uses the app.AskApp for all business logic - single source of truth.
322322
func handleNodeContext(ctx context.Context, repo *memory.Repository, params mcppresenter.ProjectContextParams) (*mcpsdk.CallToolResultFor[any], error) {
323+
// Fast path: all=true dumps every node from SQLite with no LLM calls.
324+
// This is the MCP equivalent of `taskwing knowledge`.
325+
if params.All {
326+
nodes, err := repo.ListNodes("")
327+
if err != nil {
328+
return mcpErrorResponse(fmt.Errorf("list nodes: %w", err))
329+
}
330+
return mcpMarkdownResponse(mcppresenter.FormatKnowledgeDump(nodes))
331+
}
332+
323333
// Create app context with query role - respects llm.models.query config (same as CLI)
324334
appCtx := app.NewContextForRole(repo, llm.RoleQuery)
325335
askApp := app.NewAskApp(appCtx)
@@ -337,9 +347,8 @@ func handleNodeContext(ctx context.Context, repo *memory.Repository, params mcpp
337347
}
338348

339349
// Resolve workspace filtering
340-
// params.All=true or empty workspace = search all workspaces
341350
var workspace string
342-
if !params.All && params.Workspace != "" {
351+
if params.Workspace != "" {
343352
if err := app.ValidateWorkspace(params.Workspace); err != nil {
344353
return mcpValidationErrorResponse("workspace", err.Error())
345354
}

internal/mcp/presenter.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,64 @@ import (
1212
"github.com/josephgoksu/TaskWing/internal/app"
1313
"github.com/josephgoksu/TaskWing/internal/codeintel"
1414
"github.com/josephgoksu/TaskWing/internal/knowledge"
15+
"github.com/josephgoksu/TaskWing/internal/memory"
1516
"github.com/josephgoksu/TaskWing/internal/task"
1617
"golang.org/x/text/cases"
1718
"golang.org/x/text/language"
1819
)
1920

21+
// FormatKnowledgeDump formats all knowledge nodes as Markdown, grouped by type.
22+
// This is the MCP equivalent of `taskwing knowledge` -- a direct SQLite dump
23+
// with no LLM calls, semantic search, or embedding lookups.
24+
func FormatKnowledgeDump(nodes []memory.Node) string {
25+
if len(nodes) == 0 {
26+
return "No knowledge nodes found. Run `taskwing bootstrap` to populate."
27+
}
28+
29+
var sb strings.Builder
30+
sb.WriteString(fmt.Sprintf("## Knowledge (%d nodes)\n\n", len(nodes)))
31+
32+
typeOrder := []string{"constraint", "decision", "feature", "pattern", "plan", "note", "metadata", "documentation"}
33+
grouped := make(map[string][]memory.Node)
34+
for i := range nodes {
35+
t := nodes[i].Type
36+
if t == "" {
37+
t = "unknown"
38+
}
39+
grouped[t] = append(grouped[t], nodes[i])
40+
}
41+
42+
for _, t := range typeOrder {
43+
group := grouped[t]
44+
if len(group) == 0 {
45+
continue
46+
}
47+
sb.WriteString(fmt.Sprintf("### %s (%d)\n", cases.Title(language.English).String(t), len(group)))
48+
for _, n := range group {
49+
title := n.Summary
50+
if title == "" {
51+
title = truncate(n.Content, 120)
52+
}
53+
sb.WriteString(fmt.Sprintf("- **%s**", title))
54+
if n.Workspace != "" && n.Workspace != "root" {
55+
sb.WriteString(fmt.Sprintf(" [%s]", n.Workspace))
56+
}
57+
// Include content preview when it adds info beyond the summary
58+
if n.Content != "" && n.Content != n.Summary {
59+
content := cleanContent(n.Content, title)
60+
if content != "" {
61+
preview := truncate(content, 200)
62+
sb.WriteString(fmt.Sprintf("\n %s", preview))
63+
}
64+
}
65+
sb.WriteString("\n")
66+
}
67+
sb.WriteString("\n")
68+
}
69+
70+
return strings.TrimSpace(sb.String())
71+
}
72+
2073
// FormatAsk converts an AskResult into token-efficient Markdown.
2174
// Structure: Answer (if present) -> Knowledge (grouped by type) -> Symbols
2275
// Includes debt warnings for patterns/decisions marked as technical debt.

skills/taskwing-context/SKILL.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,12 @@ Inject the complete project knowledge base into this conversation so you have fu
3232

3333
## Steps
3434

35-
1. Call MCP tool `ask` with a broad query to retrieve all knowledge:
35+
1. Call MCP tool `ask` with `all=true` to dump all knowledge directly from SQLite (no LLM calls, instant):
3636
```json
37-
{"query": "project decisions patterns constraints features", "all": true}
37+
{"all": true}
3838
```
3939

40-
2. Present the returned knowledge organized by type:
41-
- **Constraints** first (mandatory rules)
42-
- **Decisions** (technology and architecture choices)
43-
- **Patterns** (recurring practices)
44-
- **Features** (product capabilities)
40+
2. Present the returned knowledge verbatim. The response is already organized by type (constraints, decisions, patterns, features).
4541

4642
3. After presenting, confirm: "Project context loaded. I now have full visibility into your architecture. What would you like to work on?"
4743

0 commit comments

Comments
 (0)