package tools import ( "context" "strings" "github.com/modelcontextprotocol/go-sdk/mcp" "git.warky.dev/wdevs/amcs/internal/session" "git.warky.dev/wdevs/amcs/internal/store" thoughttypes "git.warky.dev/wdevs/amcs/internal/types" ) type ProjectsTool struct { store *store.DB sessions *session.ActiveProjects } type CreateProjectInput struct { Name string `json:"name" jsonschema:"the unique project name"` Description string `json:"description,omitempty" jsonschema:"optional project description"` } type CreateProjectOutput struct { Project thoughttypes.Project `json:"project"` } type ListProjectsInput struct{} type ListProjectsOutput struct { Projects []thoughttypes.ProjectSummary `json:"projects"` } type SetActiveProjectInput struct { Project string `json:"project" jsonschema:"project name or id"` } type SetActiveProjectOutput struct { Project thoughttypes.Project `json:"project"` } type GetActiveProjectInput struct{} type GetActiveProjectOutput struct { Project *thoughttypes.Project `json:"project,omitempty"` } func NewProjectsTool(db *store.DB, sessions *session.ActiveProjects) *ProjectsTool { return &ProjectsTool{store: db, sessions: sessions} } func (t *ProjectsTool) Create(ctx context.Context, _ *mcp.CallToolRequest, in CreateProjectInput) (*mcp.CallToolResult, CreateProjectOutput, error) { name := strings.TrimSpace(in.Name) if name == "" { return nil, CreateProjectOutput{}, errRequiredField("name") } project, err := t.store.CreateProject(ctx, name, strings.TrimSpace(in.Description)) if err != nil { return nil, CreateProjectOutput{}, err } return nil, CreateProjectOutput{Project: project}, nil } func (t *ProjectsTool) List(ctx context.Context, _ *mcp.CallToolRequest, _ ListProjectsInput) (*mcp.CallToolResult, ListProjectsOutput, error) { projects, err := t.store.ListProjects(ctx) if err != nil { return nil, ListProjectsOutput{}, err } return nil, ListProjectsOutput{Projects: projects}, nil } func (t *ProjectsTool) SetActive(ctx context.Context, req *mcp.CallToolRequest, in SetActiveProjectInput) (*mcp.CallToolResult, SetActiveProjectOutput, error) { sid, err := sessionID(req) if err != nil { return nil, SetActiveProjectOutput{}, err } project, err := resolveProject(ctx, t.store, t.sessions, req, in.Project, true) if err != nil { return nil, SetActiveProjectOutput{}, err } t.sessions.Set(sid, project.ID) _ = t.store.TouchProject(ctx, project.ID) return nil, SetActiveProjectOutput{Project: *project}, nil } func (t *ProjectsTool) GetActive(ctx context.Context, req *mcp.CallToolRequest, _ GetActiveProjectInput) (*mcp.CallToolResult, GetActiveProjectOutput, error) { project, err := resolveProject(ctx, t.store, t.sessions, req, "", false) if err != nil { return nil, GetActiveProjectOutput{}, err } return nil, GetActiveProjectOutput{Project: project}, nil }