search_entra_news
Search Microsoft Entra announcements and community tools from the Entra.news archive using natural language queries. Retrieve sourced excerpts with issue details and URLs.
Instructions
Search the full Entra.news archive using natural language or keywords. Returns sourced excerpts from past issues with issue number, date, and URL. Supports hybrid semantic + keyword search (semantic requires OPENAI_API_KEY). Covers all Entra.news issues from mid-2023 to present.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Natural language question or keywords to search for | |
| limit | No | Maximum number of results to return (default: 10, max: 50) | |
| mode | No | Search mode: hybrid (default), semantic-only, or keyword-only | hybrid |
Implementation Reference
- src/tools/search.ts:56-97 (handler)The handler function 'handleSearchEntraNews' that performs the search using keyword and semantic search logic.
export async function handleSearchEntraNews(args: SearchArgs): Promise<string> { const { query, limit, mode } = args; const apiKey = process.env.OPENAI_API_KEY; let semanticResults: SearchResult[] = []; let keywordResults: SearchResult[] = []; if (mode !== 'keyword' && apiKey) { try { const embedding = await getEmbedding(query, apiKey); semanticResults = semanticSearch(embedding, limit); } catch (err) { process.stderr.write(`[entra-news-mcp] Semantic search failed, falling back to keyword: ${err}\n`); } } if (mode !== 'semantic') { keywordResults = keywordSearch(query, limit); } if (semanticResults.length === 0 && keywordResults.length === 0) { return `No results found for "${query}". Try different keywords or a broader query.`; } let results: SearchResult[]; if (mode === 'semantic') { results = semanticResults.slice(0, limit); } else if (mode === 'keyword') { results = keywordResults.slice(0, limit); } else { results = deduplicateAndMerge(semanticResults, keywordResults, limit); } const modeNote = mode === 'hybrid' && !apiKey ? '\n> *(Keyword-only mode — set OPENAI_API_KEY for semantic search)*\n' : ''; const header = `## Search results for: "${query}"\n${modeNote}\nFound ${results.length} result(s):\n\n---\n\n`; const body = results.map((r, i) => formatResult(r, i + 1)).join('\n\n---\n\n'); return header + body; } - src/tools/search.ts:5-12 (schema)The zod schema definition used to validate inputs for 'search_entra_news'.
export const searchSchema = z.object({ query: z.string().min(1).describe('Natural language question or keywords to search for'), limit: z.number().int().min(1).max(50).default(10).describe('Maximum number of results to return'), mode: z .enum(['hybrid', 'semantic', 'keyword']) .default('hybrid') .describe('Search mode: hybrid (default), semantic-only, or keyword-only'), }); - src/server.ts:147-152 (registration)The tool handler registration block in the main MCP server implementation.
switch (name) { case 'search_entra_news': { const parsed = searchSchema.parse(args ?? {}); text = await handleSearchEntraNews(parsed); break; }