list_projects
List all registered projects with id, name, path, and has_hands flag to obtain project_id for scoped tools.
Instructions
List every registered project with id, name, absolute path, and a derived has_hands flag (true when the path exists on disk AND contains a ctxnest.json). Read-only; no side effects, auth, or rate limits. Use to find the project_id to pass to scoped tools (search, list_files, commit_backup, refresh_index, etc.). To register a new project use register_project; to inspect its Hands tools use list_hands.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- apps/mcp/src/index.ts:689-703 (handler)MCP tool handler for 'list_projects'. Calls listProjects() from core, augments each project with a 'has_hands' flag (true if path exists and contains ctxnest.json), and returns the JSON result.
server.tool( "list_projects", "List every registered project with id, name, absolute path, and a derived `has_hands` flag (true when the path exists on disk AND contains a `ctxnest.json`). Read-only; no side effects, auth, or rate limits. Use to find the project_id to pass to scoped tools (`search`, `list_files`, `commit_backup`, `refresh_index`, etc.). To register a new project use `register_project`; to inspect its Hands tools use `list_hands`.", {}, async () => { const result = listProjects(); const augmented = result.map((p: any) => ({ ...p, has_hands: !!(p.path && existsSync(p.path) && existsSync(`${p.path}/ctxnest.json`)), })); return { content: [{ type: "text", text: JSON.stringify(augmented, null, 2) }], }; } ); - apps/mcp/src/index.ts:692-692 (schema)The list_projects tool takes no parameters (empty schema object {}).
{}, - apps/mcp/src/index.ts:689-703 (registration)Tool registered via server.tool('list_projects', ...) on the McpServer instance.
server.tool( "list_projects", "List every registered project with id, name, absolute path, and a derived `has_hands` flag (true when the path exists on disk AND contains a `ctxnest.json`). Read-only; no side effects, auth, or rate limits. Use to find the project_id to pass to scoped tools (`search`, `list_files`, `commit_backup`, `refresh_index`, etc.). To register a new project use `register_project`; to inspect its Hands tools use `list_hands`.", {}, async () => { const result = listProjects(); const augmented = result.map((p: any) => ({ ...p, has_hands: !!(p.path && existsSync(p.path) && existsSync(`${p.path}/ctxnest.json`)), })); return { content: [{ type: "text", text: JSON.stringify(augmented, null, 2) }], }; } ); - Core implementation: queries the projects table from SQLite, ordered by name, and returns all ProjectRecord rows.
export function listProjects(): ProjectRecord[] { const db = getDatabase(); const stmt = db.prepare("SELECT * FROM projects ORDER BY name"); return stmt.all() as ProjectRecord[]; } - packages/core/src/index.ts:7-10 (helper)Re-exports listProjects from metadata module so it's available as a public API of ctxnest-core.
addTags, removeTags, setFavorite, search, registerProject, unregisterProject, discoverFiles, listTags, listProjects, findRelated, getTagsForFiles, type RelatedFileRecord, } from "./metadata/index.js";