search-all
Search note.com for users, hashtags, and articles using keywords, with options to filter by context, sort results, and limit output.
Instructions
note全体検索(ユーザー、ハッシュタグ、記事など)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | 検索キーワード | |
| context | No | 検索コンテキスト(user,hashtag,noteなどをカンマ区切りで指定) | user,hashtag,note |
| mode | No | 検索モード(typeaheadなど) | typeahead |
| size | No | 取得する件数(最大5件) | |
| sort | No | ソート順(new: 新着順, popular: 人気順, hot: 急上昇) | hot |
Implementation Reference
- src/tools/search-tools.ts:192-259 (handler)The asynchronous handler function that implements the core logic of the 'search-all' tool. It calls the note.com search API (/v3/searches), parses users, hashtags, and notes from the response, formats them into a structured result, and handles errors.async ({ query, context, mode, size, sort }) => { try { const data = await noteApiRequest( `/v3/searches?context=${encodeURIComponent(context)}&mode=${encodeURIComponent(mode)}&q=${encodeURIComponent(query)}&size=${size}&sort=${sort}`, "GET", null, false ); const result = { query, context, mode, size, results: {} as any }; if (data.data) { // ユーザー検索結果 if (data.data.users && Array.isArray(data.data.users)) { result.results.users = data.data.users.map((user: any) => ({ id: user.id || "", nickname: user.nickname || "", urlname: user.urlname || "", bio: user.profile?.bio || user.bio || "", profileImageUrl: user.profileImageUrl || "", url: `https://note.com/${user.urlname || ''}` })); } // ハッシュタグ検索結果 if (data.data.hashtags && Array.isArray(data.data.hashtags)) { result.results.hashtags = data.data.hashtags.map((tag: any) => ({ name: tag.name || "", displayName: tag.displayName || tag.name || "", url: `https://note.com/hashtag/${tag.name || ''}` })); } // 記事検索結果 if (data.data.notes) { let notesArray: any[] = []; if (Array.isArray(data.data.notes)) { notesArray = data.data.notes; } else if (typeof data.data.notes === 'object' && data.data.notes !== null) { const notesObj = data.data.notes as { contents?: any[] }; if (notesObj.contents && Array.isArray(notesObj.contents)) { notesArray = notesObj.contents; } } result.results.notes = notesArray.map((note: any) => ({ id: note.id || "", title: note.name || note.title || "", excerpt: note.body ? (note.body.length > 100 ? note.body.substring(0, 100) + '...' : note.body) : '', user: note.user?.nickname || 'unknown', publishedAt: note.publishAt || note.publish_at || '', url: `https://note.com/${note.user?.urlname || 'unknown'}/n/${note.key || ''}` })); } } return createSuccessResponse(result); } catch (error) { return handleApiError(error, "全体検索"); } }
- src/tools/search-tools.ts:185-191 (schema)Zod input schema defining parameters for the search-all tool: query (string), context (string, default 'user,hashtag,note'), mode (string, default 'typeahead'), size (number, default 10), sort (enum, default 'hot').{ query: z.string().describe("検索キーワード"), context: z.string().default("user,hashtag,note").describe("検索コンテキスト(user,hashtag,noteなどをカンマ区切りで指定)"), mode: z.string().default("typeahead").describe("検索モード(typeaheadなど)"), size: z.number().default(10).describe("取得する件数(最大5件)"), sort: z.enum(["new", "popular", "hot"]).default("hot").describe("ソート順(new: 新着順, popular: 人気順, hot: 急上昇)"), },
- src/tools/search-tools.ts:182-260 (registration)The server.tool() call that registers the 'search-all' tool with the MCP server, specifying name, description, input schema, and handler function.server.tool( "search-all", "note全体検索(ユーザー、ハッシュタグ、記事など)", { query: z.string().describe("検索キーワード"), context: z.string().default("user,hashtag,note").describe("検索コンテキスト(user,hashtag,noteなどをカンマ区切りで指定)"), mode: z.string().default("typeahead").describe("検索モード(typeaheadなど)"), size: z.number().default(10).describe("取得する件数(最大5件)"), sort: z.enum(["new", "popular", "hot"]).default("hot").describe("ソート順(new: 新着順, popular: 人気順, hot: 急上昇)"), }, async ({ query, context, mode, size, sort }) => { try { const data = await noteApiRequest( `/v3/searches?context=${encodeURIComponent(context)}&mode=${encodeURIComponent(mode)}&q=${encodeURIComponent(query)}&size=${size}&sort=${sort}`, "GET", null, false ); const result = { query, context, mode, size, results: {} as any }; if (data.data) { // ユーザー検索結果 if (data.data.users && Array.isArray(data.data.users)) { result.results.users = data.data.users.map((user: any) => ({ id: user.id || "", nickname: user.nickname || "", urlname: user.urlname || "", bio: user.profile?.bio || user.bio || "", profileImageUrl: user.profileImageUrl || "", url: `https://note.com/${user.urlname || ''}` })); } // ハッシュタグ検索結果 if (data.data.hashtags && Array.isArray(data.data.hashtags)) { result.results.hashtags = data.data.hashtags.map((tag: any) => ({ name: tag.name || "", displayName: tag.displayName || tag.name || "", url: `https://note.com/hashtag/${tag.name || ''}` })); } // 記事検索結果 if (data.data.notes) { let notesArray: any[] = []; if (Array.isArray(data.data.notes)) { notesArray = data.data.notes; } else if (typeof data.data.notes === 'object' && data.data.notes !== null) { const notesObj = data.data.notes as { contents?: any[] }; if (notesObj.contents && Array.isArray(notesObj.contents)) { notesArray = notesObj.contents; } } result.results.notes = notesArray.map((note: any) => ({ id: note.id || "", title: note.name || note.title || "", excerpt: note.body ? (note.body.length > 100 ? note.body.substring(0, 100) + '...' : note.body) : '', user: note.user?.nickname || 'unknown', publishedAt: note.publishAt || note.publish_at || '', url: `https://note.com/${note.user?.urlname || 'unknown'}/n/${note.key || ''}` })); } } return createSuccessResponse(result); } catch (error) { return handleApiError(error, "全体検索"); } } );