Improve tool descriptions for cross-model compatibility
Add concrete parameter examples, negative routing guidance, and format conventions to tool descriptions. Helps Gemini with literal tool selection and GPT with over-calling prevention.
This commit is contained in:
14
src/index.ts
14
src/index.ts
@@ -20,7 +20,7 @@ const server = new McpServer({
|
|||||||
|
|
||||||
server.tool(
|
server.tool(
|
||||||
"search_context",
|
"search_context",
|
||||||
"Semantic search across all homelab documentation. Returns the most relevant sections for a natural language query. Optionally filter by document type (device, infrastructure, network, automation, tool) or hostname.",
|
"Semantic search across all homelab documentation and projects. Returns the most relevant sections for a natural language query. Optionally filter by document type (device, infrastructure, network, automation, tool, project) or hostname. For projects, results include project name, slug, and status — use the returned slug with get_project for full details.",
|
||||||
searchContextSchema.shape,
|
searchContextSchema.shape,
|
||||||
async (input) => ({
|
async (input) => ({
|
||||||
content: [{ type: "text", text: await searchContext(searchContextSchema.parse(input)) }],
|
content: [{ type: "text", text: await searchContext(searchContextSchema.parse(input)) }],
|
||||||
@@ -47,7 +47,7 @@ server.tool(
|
|||||||
|
|
||||||
server.tool(
|
server.tool(
|
||||||
"search_issues",
|
"search_issues",
|
||||||
"Search for operational notes, troubleshooting info, known issues, and incident reports across all homelab documentation.",
|
"Search for operational problems, troubleshooting notes, known issues, and incident history across all homelab documentation. Searches the same collection as search_context but filters results to operational/issue-related content. Use search_context instead for general documentation lookup or project searches.",
|
||||||
searchIssuesSchema.shape,
|
searchIssuesSchema.shape,
|
||||||
async (input) => ({
|
async (input) => ({
|
||||||
content: [{ type: "text", text: await searchIssues(searchIssuesSchema.parse(input)) }],
|
content: [{ type: "text", text: await searchIssues(searchIssuesSchema.parse(input)) }],
|
||||||
@@ -56,7 +56,7 @@ server.tool(
|
|||||||
|
|
||||||
server.tool(
|
server.tool(
|
||||||
"upsert_context",
|
"upsert_context",
|
||||||
"Create or overwrite a homelab documentation chunk. Uses a deterministic ID based on source, section, and host so repeated upserts are idempotent.",
|
'Create or overwrite a homelab documentation chunk. Uses a deterministic ID based on source, section, and host so repeated upserts are idempotent. Example: {host: "proxmox", section: "GPU Passthrough", source: "devices/proxmox.md", type: "device", text: "...", tags: ["gpu", "nvidia"]}. source uses path-like format, host is the hostname, section is a human-readable heading.',
|
||||||
upsertContextSchema.shape,
|
upsertContextSchema.shape,
|
||||||
async (input) => ({
|
async (input) => ({
|
||||||
content: [{ type: "text", text: await upsertContext(upsertContextSchema.parse(input)) }],
|
content: [{ type: "text", text: await upsertContext(upsertContextSchema.parse(input)) }],
|
||||||
@@ -65,7 +65,7 @@ server.tool(
|
|||||||
|
|
||||||
server.tool(
|
server.tool(
|
||||||
"update_context",
|
"update_context",
|
||||||
"Update metadata fields on existing homelab documentation chunk(s). Filter by host, source, section, or project. Optionally provide new text to trigger re-embedding.",
|
'Update metadata fields on existing homelab documentation chunk(s). Filter fields (host, source, section, project) select which chunks to update. new_* fields set the new values. At least one filter required. Example: {host: "proxmox", section: "GPU Passthrough", new_tags: ["gpu", "nvidia", "rtx8000"]}. Optionally provide text to trigger re-embedding.',
|
||||||
updateContextSchema._def.schema.shape,
|
updateContextSchema._def.schema.shape,
|
||||||
async (input) => ({
|
async (input) => ({
|
||||||
content: [{ type: "text", text: await updateContext(updateContextSchema.parse(input)) }],
|
content: [{ type: "text", text: await updateContext(updateContextSchema.parse(input)) }],
|
||||||
@@ -83,7 +83,7 @@ server.tool(
|
|||||||
|
|
||||||
server.tool(
|
server.tool(
|
||||||
"list_projects",
|
"list_projects",
|
||||||
"List all tracked projects. Filter by status (default: 'active', or 'all' for everything). Returns JSON array of project summaries.",
|
"List all tracked projects at a glance. Filter by status (default: 'active', or 'all' for everything). Returns JSON array of project summaries with slug, name, status, summary, tags, and updated. Use search_context with type: 'project' for semantic/topic search across projects instead.",
|
||||||
listProjectsSchema.shape,
|
listProjectsSchema.shape,
|
||||||
async (input) => ({
|
async (input) => ({
|
||||||
content: [{ type: "text", text: await listProjects(listProjectsSchema.parse(input)) }],
|
content: [{ type: "text", text: await listProjects(listProjectsSchema.parse(input)) }],
|
||||||
@@ -101,7 +101,7 @@ server.tool(
|
|||||||
|
|
||||||
server.tool(
|
server.tool(
|
||||||
"upsert_project",
|
"upsert_project",
|
||||||
"Create or update a project. On create, 'name' is required; other fields default to empty. On update, only provided fields are changed. Relationships merge at sub-key level (hosts, software, git_repos, local_dirs).",
|
'Use for initial project creation or full rewrites. Do NOT use for incremental changes like adding a single blocker or history entry — use update_project instead. On create, slug and name are required; other fields default to empty. On update, only provided fields are changed. Relationships merge at sub-key level (hosts, software, git_repos, local_dirs). Example creation: {slug: "led-dimming", name: "LED Dimming Controller", status: "planning", summary: "PWM-based LED dimming system", tags: ["hardware", "esphome"]}.',
|
||||||
upsertProjectSchema.shape,
|
upsertProjectSchema.shape,
|
||||||
async (input) => ({
|
async (input) => ({
|
||||||
content: [{ type: "text", text: await upsertProject(upsertProjectSchema.parse(input)) }],
|
content: [{ type: "text", text: await upsertProject(upsertProjectSchema.parse(input)) }],
|
||||||
@@ -110,7 +110,7 @@ server.tool(
|
|||||||
|
|
||||||
server.tool(
|
server.tool(
|
||||||
"update_project",
|
"update_project",
|
||||||
"Apply granular mutations to an existing project. Supports scalar updates (status, summary, current_state) and array add/remove operations (blockers, tags, key_facts, history, decisions_pending, relationships).",
|
'Use for incremental mutations to existing projects. Supports adding/removing individual items without touching other fields. Do NOT use for initial creation — use upsert_project instead. Examples: add_blocker: "Waiting on PCB fab delivery", add_history: "2026-03-01: Deployed v1.0 to production", add_relationship: {category: "hosts", host: "proxmox", role: "compute node"}, add_relationship: {category: "git_repos", repo: "adamksmith/homelab-mcp", role: "source code"}, add_relationship: {category: "software", name: "ESPHome", role: "firmware framework", version: "2024.12"}, add_relationship: {category: "local_dirs", path: "/home/adam/projects/foo", role: "working directory"}, remove_relationship: {category: "hosts", host: "old-server"}.',
|
||||||
updateProjectSchema.shape,
|
updateProjectSchema.shape,
|
||||||
async (input) => ({
|
async (input) => ({
|
||||||
content: [{ type: "text", text: await updateProject(updateProjectSchema.parse(input)) }],
|
content: [{ type: "text", text: await updateProject(updateProjectSchema.parse(input)) }],
|
||||||
|
|||||||
Reference in New Issue
Block a user