Skip to main content
Glama

Hybrid semantic + structural search

search_hybrid_context
Read-onlyIdempotent

Use for initial codebase discovery to find features by meaning through read-only semantic and structural search combining vector embeddings and graph analysis, returning files, signatures, and docs.

Instructions

Read-only semantic and structural code search combining vector embeddings with graph analysis. Use this for initial codebase discovery to find features by their meaning (e.g., 'user authentication'). Locates code based on natural language descriptions instead of exact keywords, returning relevant files, signatures, and documentation.

⚠️ PREREQUISITE: This tool requires an active knot-mcp server with vector database (Qdrant) and graph database (Neo4j) initialized.

Behavior & Return: Performs a read-only dual query against vector DB (for semantic similarity) and graph DB (for architectural relationships). Returns Markdown-formatted results with file paths, line numbers, code snippets, and cross-repository dependencies. No side effects.

Usage: Use as your FIRST step when exploring unfamiliar code or discovering architectural patterns. Do NOT use this to find all usages of a specific function—use the 'find_callers' tool for that instead.

Ranking contract: results are kind-aware — function/method/class/struct definitions outrank markdown docs, test files, config properties and build-dependency entities for natural-language queries; callers and helpers appear as context attached to a definition, never as substitutes. The shared entry point of the highest-ranked helpers outranks those helpers a loose paraphrase surfaces.

Relationship summary: each result's 'Called by' / 'Called via dispatch' counts come from the graph edges of that exact entity — the same edges 'find_callers' reports for its fully qualified name; same-named entities elsewhere never contribute. 'Calls' lists callees qualified with their owning type or module, capped at 8 plus '+N more'. Callers in test code count toward the totals but are shown as 'N in tests' unless 'include_tests' is true; a sample in the result's own file reads 'name (same file)'.

Detail: 'detail: "brief"' renders one line per result (kind, file:line, caller/callee counts) to scan many hits cheaply; expand the one you need with 'find_callers' / 'explore_file' or a default 'full' search.

Generic-verb guard: an entity merely named after a generic verb or noun (find/get/create/build/acquire/borrow/current/…) does not win on that name alone; the full name boost is paid only when the entity's container context (FQN) corroborates a second query token.

Recall contract: entity embeds carry identifier tokens and the tokenized call names of the entity's body, so a paraphrase of what a definition does (even one with no doc comment) still surfaces it. Entities whose identifier shares a word with the query enter the candidate pool by token match alone.

Result bound: 'max_results' is 1-100 (default 5) and is enforced — a larger request is clamped to 100 and the reply says so. There is no pagination: when the bound is not enough, narrow the scope with 'kinds' / 'path' / 'repo_name' or refine the query rather than raising the limit.

Parameter guidance: 'query' should be 2-5 words describing functionality. Increase 'max_results' to 10-20 for broad discovery, keep at 5 for focused search. Include 'repo_name' in your first query to avoid cross-repository pollution.

Supports Java, Kotlin, C#, and TypeScript codebases.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "query": "<query>"
    },
    "name": "search_hybrid_context"
  }
}

Input Schema

NameRequiredDescriptionDefault
pathNoOptional path filter. A repo-relative directory prefix ('src/api', matched on a path boundary so 'src/api-notes.md' never matches) or a glob ('src/**/*_test.rs'). Use 'list_files' first when you do not know the layout. Omit to search every file.
kindsNoOptional entity-kind filter. Accepts exact wire-format kinds (`'rust_function'`, `'markdown_section'`, `'kotlin_class'`, …) or aliases: `'definition'` (all functions/methods/types), `'callable'`/`'function'`/`'method'` (all callable kinds), `'class'`/`'type'`/`'struct'` (all type kinds). Comma-separate for multiple values. Omit to search all kinds.
queryYesSearch query describing what you're looking for (e.g., 'user authentication', 'API error handling')
detailNoOptional detail level: 'full' (default) renders file, FQN, signature, docs and relationship summaries; 'brief' renders one line per result (kind, file:line, caller/callee counts). Scan with 'brief', then expand the hit you need with find_callers / explore_file or a 'full' search.
repo_nameNoOptional but HIGHLY RECOMMENDED: repository scope. Accepts a single repository name (`'my-repo'`), a comma-separated list (`'repo-a,repo-b'`), or `'all'` (or `'*'`) to query every indexed repository. If you know the repository you are working on, include it in your FIRST query to avoid mixed results from other indexed projects. Omit to search across all repositories.
max_resultsNoMaximum number of results to return (default: 5, max: 100). Requests above 100 are clamped to 100 and the reply says so — there is no cursor or pagination; to look past the bound, narrow the search with 'kinds' / 'path' / 'repo_name' or refine the query.
include_testsNoOptional: set to true to list callers and usages from test code in the samples. By default they are only counted ('N in tests'); the counts always include them.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv1.13.0
    • addedInput schema / properties / detail
      Added value: +{
      +  "description": "Optional detail level: 'full' (default) renders file, FQN, signature, docs and relationship summaries; 'brief' renders one line per result (kind, file:line, caller/callee counts). Scan with 'brief', then expand the hit you need with find_callers / explore_file or a 'full' search.",
      +  "maxLength": 16,
      +  "minLength": 1,
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedInput schema / properties / include_tests
      Added value: +{
      +  "description": "Optional: set to true to list callers and usages from test code in the samples. By default they are only counted ('N in tests'); the counts always include them.",
      +  "type": [
      +    "boolean",
      +    "null"
      +  ]
      +}
  2. Changed4 schema fields changedv1.9.6
    • addedInput schema / properties / kinds
      Added value: +{
      +  "description": "Optional entity-kind filter. Accepts exact wire-format kinds (`'rust_function'`, `'markdown_section'`, `'kotlin_class'`, …) or aliases: `'definition'` (all functions/methods/types), `'callable'`/`'function'`/`'method'` (all callable kinds), `'class'`/`'type'`/`'struct'` (all type kinds). Comma-separate for multiple values. Omit to search all kinds.",
      +  "maxLength": 255,
      +  "minLength": 1,
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • changedInput schema / properties / max_results / description
      Previous value: -"Maximum number of results to return (default: 5)"New value: +"Maximum number of results to return (default: 5, max: 100). Requests above 100 are clamped to 100 and the reply says so — there is no cursor or pagination; to look past the bound, narrow the search with 'kinds' / 'path' / 'repo_name' or refine the query."
    • changedInput schema / properties / max_results / maximum
      Previous value: -20New value: +100
    • addedInput schema / properties / path
      Added value: +{
      +  "description": "Optional path filter. A repo-relative directory prefix ('src/api', matched on a path boundary so 'src/api-notes.md' never matches) or a glob ('src/**/*_test.rs'). Use 'list_files' first when you do not know the layout. Omit to search every file.",
      +  "maxLength": 500,
      +  "minLength": 1,
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
  3. Changed2 schema fields changedv1.9.4
    • changedInput schema / properties / max_results / type
      Previous value: -"integer"New value: +[
      +  "integer",
      +  "null"
      +]
    • changedInput schema / properties / repo_name / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
  4. Changed1 schema field changedv1.8.1
    • changedInput schema / properties / repo_name / description
      Previous value: -"Optional but HIGHLY RECOMMENDED: repository name to filter results to a specific codebase (e.g., 'my-java-repo'). If you know the repository you are working on, include this in your FIRST query to avoid mixed results from other indexed projects. Omit only to search across all repositories."New value: +"Optional but HIGHLY RECOMMENDED: repository scope. Accepts a single repository name (`'my-repo'`), a comma-separated list (`'repo-a,repo-b'`), or `'all'` (or `'*'`) to query every indexed repository. If you know the repository you are working on, include it in your FIRST query to avoid mixed results from other indexed projects. Omit to search across all repositories."
  5. Addedv1.4.0
  6. Removedv1.3.8
  7. Added
  8. Removedv1.3.2
  9. Addedv1.2.8
  10. Removedv1.2.7
  11. Addedv0.8.4
  12. Removedv1.0.0
  13. First observedv0.1.0

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, so the safety profile is structured data and repeating 'No side effects' earns little. The description does add real value beyond annotations: the hard prerequisite of an active knot-mcp server with Qdrant and Neo4j, the enforced max_results clamp with an explicit 'no pagination' contract, and the ranking/recall behavior that explains why results are ordered as they are. Those are genuine disclosures, though the ranking contract and generic-verb guard drift into internal implementation detail an agent cannot act on.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded correctly: purpose, then prerequisite, then behavior/return, then usage, then the long contract sections. But the body runs well past 400 words, and the 'Ranking contract', 'Generic-verb guard', and 'Recall contract' paragraphs are dense internals that no agent action depends on. Every sentence does not earn its place, even though the ordering is sound.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter discovery tool with no output schema, the description covers the missing pieces: what the Markdown result contains (file paths, line numbers, snippets, cross-repository dependencies), the 'Called by' / 'Calls' semantics, the 'N in tests' convention, and the no-pagination bound. Nothing an agent needs to call it or interpret its output is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description earns a step above by adding guidance the schema lacks, notably that 'query' should be 2-5 words describing functionality, that max_results should be raised to 10-20 for broad discovery but held at 5 for focused search, and that repo_name belongs in the first query to avoid cross-repository pollution. It does not re-describe path, kinds, or include_tests beyond what the schema already says, so it is additive rather than redundant.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('semantic and structural code search combining vector embeddings with graph analysis') and immediately names the sibling it is not ('Do NOT use this to find all usages of a specific function—use find_callers'). An agent can distinguish it from explore_file, list_files, and find_callers without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly prescribes 'Use as your FIRST step when exploring unfamiliar code', gives an exclusion routing to find_callers, and adds concrete tuning advice (2-5 word queries, max_results 10-20 for broad discovery, include repo_name on the first query, scan with 'brief' then expand). Both when-to-use and when-not-to-use are covered with named alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.