Skip to content

Commit 8d83407

Browse files
refactor: extract MCP workspace service and typed prompt I/O
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
1 parent ea3280e commit 8d83407

7 files changed

Lines changed: 815 additions & 308 deletions

File tree

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// @index Typed decode/encode helpers for analysis MCP handlers (find_dead_code, find_suspect_fallback_edges, find_large_functions).
2+
package mcp
3+
4+
import (
5+
"github.com/mark3labs/mcp-go/mcp"
6+
7+
"github.com/tae2089/code-context-graph/internal/paging"
8+
)
9+
10+
// findDeadCodeInput captures decoded request arguments for find_dead_code.
11+
// @intent give findDeadCode a typed view of its request so the handler stays a thin adapter over deadcode.Service.
12+
type findDeadCodeInput struct {
13+
Page paging.Request
14+
Kinds []string
15+
PathPrefix string
16+
Namespace string
17+
}
18+
19+
// findSuspectFallbackInput captures decoded request arguments for find_suspect_fallback_edges.
20+
// @intent give findSuspectFallbackEdges a typed view of its request so the handler stays a thin adapter over the fallback analyzer.
21+
type findSuspectFallbackInput struct {
22+
Page paging.Request
23+
Namespace string
24+
}
25+
26+
// findLargeFuncsInput captures decoded request arguments for find_large_functions.
27+
// @intent give findLargeFunctions a typed view of its request so the handler stays a thin adapter over largefunc.Service.
28+
type findLargeFuncsInput struct {
29+
MinLines int
30+
Page paging.Request
31+
PathPrefix string
32+
Namespace string
33+
}
34+
35+
// decodeFindDeadCodeRequest extracts and validates find_dead_code arguments.
36+
// @intent isolate request parsing and pagination validation for find_dead_code.
37+
// @ensures returned page request is normalized and limit/offset are non-negative.
38+
func decodeFindDeadCodeRequest(request mcp.CallToolRequest) (findDeadCodeInput, error) {
39+
limit := request.GetInt("limit", 50)
40+
offset := request.GetInt("offset", 0)
41+
pageReq, err := normalizeListPaging(limit, offset)
42+
if err != nil {
43+
return findDeadCodeInput{}, err
44+
}
45+
return findDeadCodeInput{
46+
Page: pageReq,
47+
Kinds: request.GetStringSlice("kinds", nil),
48+
PathPrefix: request.GetString("path", ""),
49+
Namespace: requestNamespace(request),
50+
}, nil
51+
}
52+
53+
// decodeFindSuspectFallbackRequest extracts and validates find_suspect_fallback_edges arguments.
54+
// @intent isolate request parsing and pagination validation for find_suspect_fallback_edges.
55+
func decodeFindSuspectFallbackRequest(request mcp.CallToolRequest) (findSuspectFallbackInput, error) {
56+
limit := request.GetInt("limit", 50)
57+
offset := request.GetInt("offset", 0)
58+
pageReq, err := normalizeListPaging(limit, offset)
59+
if err != nil {
60+
return findSuspectFallbackInput{}, err
61+
}
62+
return findSuspectFallbackInput{
63+
Page: pageReq,
64+
Namespace: requestNamespace(request),
65+
}, nil
66+
}
67+
68+
// decodeFindLargeFuncsRequest extracts and validates find_large_functions arguments.
69+
// @intent isolate request parsing and pagination validation for find_large_functions.
70+
func decodeFindLargeFuncsRequest(request mcp.CallToolRequest) (findLargeFuncsInput, error) {
71+
limit := request.GetInt("limit", 50)
72+
offset := request.GetInt("offset", 0)
73+
pageReq, err := normalizeListPaging(limit, offset)
74+
if err != nil {
75+
return findLargeFuncsInput{}, err
76+
}
77+
return findLargeFuncsInput{
78+
MinLines: request.GetInt("min_lines", 50),
79+
Page: pageReq,
80+
PathPrefix: request.GetString("path", ""),
81+
Namespace: requestNamespace(request),
82+
}, nil
83+
}
84+
85+
// normalizeListPaging validates limit/offset and returns a normalized paging.Request.
86+
// @intent share the limit-positive, offset-non-negative, normalize triple used by every analysis list handler.
87+
func normalizeListPaging(limit, offset int) (paging.Request, error) {
88+
if err := validatePositiveLimit(limit); err != nil {
89+
return paging.Request{}, err
90+
}
91+
if err := validateOffset(offset); err != nil {
92+
return paging.Request{}, err
93+
}
94+
pageReq, err := paging.Normalize(paging.Request{Limit: limit, Offset: offset})
95+
if err != nil {
96+
return paging.Request{}, newToolResultErr(err.Error())
97+
}
98+
return pageReq, nil
99+
}
100+
101+
// encodePagedListResponse serializes a paged list response with the legacy alias key plus shared items/count/pagination fields.
102+
// @intent keep the {<legacyKey>, items, count, pagination} envelope identical across analysis list handlers.
103+
// @param legacyKey is the historical response field name retained for backward compatibility.
104+
func encodePagedListResponse(legacyKey string, items []map[string]any, pagination paging.Page) (string, error) {
105+
resp := map[string]any{
106+
legacyKey: items,
107+
"items": items,
108+
"count": len(items),
109+
"pagination": pagination,
110+
}
111+
return marshalJSON(resp)
112+
}

0 commit comments

Comments
 (0)