related_concepts
Discover semantically related concepts using ConceptNet’s embeddings. Input a term to explore ranked results with similarity scores, relationship context, and language filtering, enabling effective brainstorming and concept expansion.
Instructions
Find concepts semantically related to a given concept using ConceptNet's embeddings.
This tool uses ConceptNet's semantic similarity algorithms to discover
concepts that are related to the input term. Results are ranked by
similarity score and include comprehensive analysis.
Features:
- Semantic similarity discovery using advanced algorithms
- Ranked results with detailed similarity analysis
- Default English language filtering (can be disabled or changed)
- Statistical analysis and categorization
- Format control: minimal (~96% smaller) vs verbose (full metadata)
Format Options:
- verbose=false (default): Returns minimal format optimized for LLM consumption
- verbose=true: Returns comprehensive format with full ConceptNet metadata
- Backward compatibility maintained with existing tools
Similarity Analysis:
- Similarity scores from 0.0 (unrelated) to 1.0 (very similar)
- Descriptive categories (very strong, strong, moderate, weak, very weak)
- Relationship context and likely connections
- Language distribution and statistical summaries
Use this when you need to:
- Discover semantically similar concepts
- Expand concept exploration and brainstorming
- Find related terms and ideas
- Understand semantic neighborhoods
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filter_language | No | en | |
| language | No | en | |
| limit | No | ||
| term | Yes | ||
| verbose | No |
Implementation Reference
- Main handler function implementing the core logic for the related_concepts tool: validates parameters, queries ConceptNet /related endpoint, processes responses in minimal or verbose formats, handles errors.async def related_concepts( term: str, ctx: Context, language: str = "en", filter_language: Optional[str] = None, limit: int = 100, verbose: bool = False ) -> Dict[str, Any]: """ Find concepts semantically related to the given concept. This tool uses ConceptNet's semantic similarity algorithms to find concepts that are related to the input term. Results are ranked by similarity score and can be filtered by language. By default, returns a minimal format optimized for LLM consumption. Args: term: The concept term to find related concepts for (e.g., "dog", "happiness") language: Language code for the input term (default: "en" for English) filter_language: Language to filter results to (default: None, which defaults to "en" for English) limit: Maximum number of related concepts to return (default: 100, max: 100) verbose: If True, returns detailed format with full metadata (default: False) Returns: Related concepts with similarity scores (minimal format) or comprehensive analysis with statistical metadata (verbose format). Examples: - related_concepts("dog") -> Minimal format with similarity scores - related_concepts("dog", verbose=True) -> Full detailed format with analysis - related_concepts("perro", "es") -> Spanish concepts related to "perro" - related_concepts("cat", limit=10) -> Top 10 concepts related to "cat" """ start_time = datetime.now(timezone.utc) try: # Default filter_language to "en" if not provided if filter_language is None: filter_language = "en" # Log the incoming request await ctx.info(f"Finding related concepts for: '{term}' (language: {language})") # 1. Parameter validation await _validate_parameters(term, language, filter_language, limit, ctx) # 2. Normalize the input term normalized_term = normalize_concept_text(term, language) if normalized_term != term: await ctx.debug(f"Normalized term: '{term}' -> '{normalized_term}'") # 3. Query ConceptNet API for related concepts await ctx.info(f"Querying ConceptNet /related endpoint for '{normalized_term}'...") async with ConceptNetClient() as client: try: response = await client.get_related( term=normalized_term, language=language, filter_language=filter_language, limit=limit ) except ConceptNotFoundError: return _create_not_found_response(term, language, normalized_term) except ConceptNetAPIError as e: return _create_api_error_response(term, language, str(e)) # 4. Return appropriate format based on verbose parameter if verbose: # Return detailed format with full metadata (existing behavior) enhanced_response = await _create_enhanced_response( response, term, normalized_term, language, filter_language, limit, start_time, ctx ) total_found = enhanced_response.get("summary", {}).get("total_found", 0) await ctx.info(f"Successfully found {total_found} related concepts for '{term}' (verbose format)") return enhanced_response else: # Return minimal format optimized for LLMs # Create a mock processed response for the minimal formatter mock_response = {"related_concepts": []} # Process raw related concepts data related_concepts_raw = response.get("related", []) for i, concept_data in enumerate(related_concepts_raw): concept_id = concept_data.get("@id", "") weight = concept_data.get("weight", 0.0) # Extract term from URI term_text = "" if concept_id: parts = concept_id.split('/') if len(parts) >= 4 and parts[1] == 'c': raw_term = parts[3].replace('_', ' ') # Apply POS tag filtering to remove "/Wn/..." patterns term_text = _clean_concept_term(raw_term) if term_text: mock_response["related_concepts"].append({ "concept": { "term": term_text, "normalized_display": term_text }, "similarity": { "score": weight } }) minimal_response = ResponseProcessor().create_minimal_related_response( mock_response, term ) total_found = minimal_response.get("summary", {}).get("total_found", 0) await ctx.info(f"Successfully found {total_found} related concepts for '{term}' (minimal format)") return minimal_response except MCPValidationError as e: # Handle validation errors specifically return { "error": "validation_error", "message": f"Validation error for field '{e.field}': {e.value} (expected: {e.expected})", "field": e.field, "value": e.value, "expected": e.expected, "term": term, "language": language, "query_time": start_time.isoformat() + "Z" } except ConceptNotFoundError: return _create_not_found_response(term, language, term) except ConceptNetAPIError as e: return _create_api_error_response(term, language, str(e)) except Exception as e: logger.error(f"Unexpected error in related_concepts: {e}") return { "error": "unexpected_error", "message": f"An unexpected error occurred: {str(e)}", "term": term, "language": language, "query_time": start_time.isoformat() + "Z" }
- src/conceptnet_mcp/server.py:277-344 (registration)MCP tool registration decorator and wrapper function that registers 'related_concepts' tool and delegates to the core handler.@mcp.tool( name="related_concepts", description=""" Find concepts semantically related to a given concept using ConceptNet's embeddings. This tool uses ConceptNet's semantic similarity algorithms to discover concepts that are related to the input term. Results are ranked by similarity score and include comprehensive analysis. Features: - Semantic similarity discovery using advanced algorithms - Ranked results with detailed similarity analysis - Default English language filtering (can be disabled or changed) - Statistical analysis and categorization - Format control: minimal (~96% smaller) vs verbose (full metadata) Format Options: - verbose=false (default): Returns minimal format optimized for LLM consumption - verbose=true: Returns comprehensive format with full ConceptNet metadata - Backward compatibility maintained with existing tools Similarity Analysis: - Similarity scores from 0.0 (unrelated) to 1.0 (very similar) - Descriptive categories (very strong, strong, moderate, weak, very weak) - Relationship context and likely connections - Language distribution and statistical summaries Use this when you need to: - Discover semantically similar concepts - Expand concept exploration and brainstorming - Find related terms and ideas - Understand semantic neighborhoods """, tags={"conceptnet", "semantic", "similarity", "related", "discovery"} ) async def related_concepts_tool( term: str, ctx: Context, language: str = "en", filter_language: Optional[str] = "en", limit: int = 100, verbose: bool = False ) -> Dict[str, Any]: """ MCP tool wrapper for finding related concepts functionality. Args: term: The concept term to find related concepts for (e.g., "dog", "happiness") language: Language code for the input term (default: "en" for English) filter_language: Language to filter results to (default: "en" for English, use None for no filtering) limit: Maximum number of related concepts to return (default: 100, max: 100) verbose: If True, returns detailed format with full metadata (default: False) Returns: Related concepts with similarity scores (minimal format) or comprehensive analysis with statistical metadata (verbose format) """ try: return await related_concepts( term=term, ctx=ctx, language=language, filter_language=filter_language, limit=limit, verbose=verbose ) except Exception as e: return await handle_server_error(e, "related_concepts")
- Pydantic schema/model for RelatedConceptsQuery defining input validation for term, language, filter_language, limit parameters.class RelatedConceptsQuery(BaseModel): """ Query model for finding related concepts. This model defines parameters for finding concepts related to a given concept through various relation types. """ term: str = Field( description="The concept term to find relations for" ) language: str = Field( default="en", description="Language of the input term" ) filter_language: Optional[str] = Field( default=None, description="Filter results to specific language" ) limit: int = Field( default=100, description="Maximum number of related concepts to return", ge=1, le=100 ) @field_validator('language', 'filter_language') @classmethod def validate_language_codes(cls, v: Optional[str]) -> Optional[str]: """Validate language codes are reasonable.""" if v is not None and (len(v) < 2 or len(v) > 3 or not v.isalpha()): raise ValueError("Language code must be 2-3 alphabetic characters") return v.lower() if v else v def to_concept_uri(self) -> str: """Convert term and language to ConceptNet URI format.""" normalized_term = self.term.replace(' ', '_').lower() return f"/c/{self.language}/{normalized_term}" def __str__(self) -> str: """Return a human-readable string representation.""" return f"RelatedConcepts('{self.term}' in {self.language}, limit={self.limit})"