Skip to main content
Glama

analyze-notes

Analyze note.com articles to compare content performance, identify trends, and conduct competitive research using customizable search parameters.

Instructions

記事の詳細分析を行う(競合分析やコンテンツ成果の比較等)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes検索キーワード
sizeNo取得する件数(分析に十分なデータ量を確保するため、初期値は多め)
startNo検索結果の開始位置
sortNoソート順(new: 新着順, popular: 人気順, hot: 急上昇)popular
includeUserDetailsNo著者情報を詳細に含めるかどうか
analyzeContentNoコンテンツの特徴(画像数、アイキャッチの有無など)を分析するか
categoryNo特定のカテゴリに絞り込む(オプション)
dateRangeNo日付範囲で絞り込む(例: 7d=7日以内、2m=2ヶ月以内)
priceRangeNo価格帯(all: 全て, free: 無料のみ, paid: 有料のみ)all

Implementation Reference

  • The core handler function for the 'analyze-notes' tool. It constructs API parameters, calls the note.com search API (with authentication), extracts and formats notes, computes analytics using the analyzeNotes helper, and returns structured results or errors.
    async ({ query, size, start, sort, includeUserDetails, analyzeContent, category, dateRange, priceRange }) => { try { const params = new URLSearchParams({ q: query, size: size.toString(), start: start.toString(), sort: sort }); if (category) params.append("category", category); if (dateRange) params.append("date_range", dateRange); if (priceRange !== "all") params.append("price", priceRange); // 認証が必要なエンドポイントのため、requireAuth を true に設定 const data = await noteApiRequest( `/v3/searches?context=note&${params.toString()}`, "GET", null, true ); if (env.DEBUG) { console.error(`API Response structure for analyze-notes: ${JSON.stringify(data, null, 2)}`); } if (!data || !data.data) { return createErrorResponse(`APIレスポンスが空です: ${JSON.stringify(data)}`); } if (data.status === "error" || data.error) { return createErrorResponse(`APIエラー: ${JSON.stringify(data)}`); } const notesArray = safeExtractData(data, commonExtractors.notes); const totalCount = safeExtractTotal(data, notesArray.length); const formattedNotes = notesArray.map(note => formatNote(note, undefined, includeUserDetails, analyzeContent) ); const analytics = analyzeNotes(formattedNotes, query, sort); return createSuccessResponse({ analytics, notes: formattedNotes }); } catch (error) { return handleApiError(error, "記事分析"); } }
  • Zod schema defining the input parameters for the 'analyze-notes' tool, including query, pagination, sorting, filtering options, and analysis flags.
    { query: z.string().describe("検索キーワード"), size: z.number().default(20).describe("取得する件数(分析に十分なデータ量を確保するため、初期値は多め)"), start: z.number().default(0).describe("検索結果の開始位置"), sort: z.enum(["new", "popular", "hot"]).default("popular").describe("ソート順(new: 新着順, popular: 人気順, hot: 急上昇)"), includeUserDetails: z.boolean().default(true).describe("著者情報を詳細に含めるかどうか"), analyzeContent: z.boolean().default(true).describe("コンテンツの特徴(画像数、アイキャッチの有無など)を分析するか"), category: z.string().optional().describe("特定のカテゴリに絞り込む(オプション)"), dateRange: z.string().optional().describe("日付範囲で絞り込む(例: 7d=7日以内、2m=2ヶ月以内)"), priceRange: z.enum(["all", "free", "paid"]).default("all").describe("価格帯(all: 全て, free: 無料のみ, paid: 有料のみ)"), },
  • Local registration of the 'analyze-notes' tool using McpServer.tool(), including name, description, schema, and handler. This function is called from src/tools/index.ts via registerSearchTools(server).
    server.tool( "analyze-notes", "記事の詳細分析を行う(競合分析やコンテンツ成果の比較等)", { query: z.string().describe("検索キーワード"), size: z.number().default(20).describe("取得する件数(分析に十分なデータ量を確保するため、初期値は多め)"), start: z.number().default(0).describe("検索結果の開始位置"), sort: z.enum(["new", "popular", "hot"]).default("popular").describe("ソート順(new: 新着順, popular: 人気順, hot: 急上昇)"), includeUserDetails: z.boolean().default(true).describe("著者情報を詳細に含めるかどうか"), analyzeContent: z.boolean().default(true).describe("コンテンツの特徴(画像数、アイキャッチの有無など)を分析するか"), category: z.string().optional().describe("特定のカテゴリに絞り込む(オプション)"), dateRange: z.string().optional().describe("日付範囲で絞り込む(例: 7d=7日以内、2m=2ヶ月以内)"), priceRange: z.enum(["all", "free", "paid"]).default("all").describe("価格帯(all: 全て, free: 無料のみ, paid: 有料のみ)"), }, async ({ query, size, start, sort, includeUserDetails, analyzeContent, category, dateRange, priceRange }) => { try { const params = new URLSearchParams({ q: query, size: size.toString(), start: start.toString(), sort: sort }); if (category) params.append("category", category); if (dateRange) params.append("date_range", dateRange); if (priceRange !== "all") params.append("price", priceRange); // 認証が必要なエンドポイントのため、requireAuth を true に設定 const data = await noteApiRequest( `/v3/searches?context=note&${params.toString()}`, "GET", null, true ); if (env.DEBUG) { console.error(`API Response structure for analyze-notes: ${JSON.stringify(data, null, 2)}`); } if (!data || !data.data) { return createErrorResponse(`APIレスポンスが空です: ${JSON.stringify(data)}`); } if (data.status === "error" || data.error) { return createErrorResponse(`APIエラー: ${JSON.stringify(data)}`); } const notesArray = safeExtractData(data, commonExtractors.notes); const totalCount = safeExtractTotal(data, notesArray.length); const formattedNotes = notesArray.map(note => formatNote(note, undefined, includeUserDetails, analyzeContent) ); const analytics = analyzeNotes(formattedNotes, query, sort); return createSuccessResponse({ analytics, notes: formattedNotes }); } catch (error) { return handleApiError(error, "記事分析"); } } );
  • Supporting utility function that performs statistical analysis on formatted notes, calculating engagement metrics, content features, pricing stats, and author insights. Called within the tool handler.
    export function analyzeNotes(formattedNotes: FormattedNote[], query: string, sort: string) { return { totalFound: formattedNotes.length, analyzed: formattedNotes.length, query, sort, // エンゲージメント分析 engagementAnalysis: { averageLikes: formattedNotes.reduce((sum, note) => sum + note.likesCount, 0) / formattedNotes.length || 0, averageComments: formattedNotes.reduce((sum, note) => sum + (note.commentsCount || 0), 0) / formattedNotes.length || 0, maxLikes: Math.max(...formattedNotes.map(note => note.likesCount)), maxComments: Math.max(...formattedNotes.map(note => note.commentsCount || 0)) }, // コンテンツタイプ分析 contentTypeAnalysis: { withEyecatch: formattedNotes.filter(note => note.contentAnalysis?.hasEyecatch).length, withVideo: formattedNotes.filter(note => note.contentAnalysis?.hasVideo).length, withAudio: formattedNotes.filter(note => note.contentAnalysis?.hasAudio).length, averageImageCount: formattedNotes.reduce((sum, note) => sum + (note.contentAnalysis?.imageCount || 0), 0) / formattedNotes.length || 0 }, // 価格分析 priceAnalysis: { free: formattedNotes.filter(note => !note.isPaid).length, paid: formattedNotes.filter(note => note.isPaid).length, averagePrice: formattedNotes.filter(note => note.isPaid).reduce((sum, note) => sum + (note.price || 0), 0) / formattedNotes.filter(note => note.isPaid).length || 0, maxPrice: Math.max(...formattedNotes.map(note => note.price || 0)), minPrice: Math.min(...formattedNotes.filter(note => note.isPaid).map(note => note.price || 0)) || 0 }, // 著者分析 authorAnalysis: { uniqueAuthors: [...new Set(formattedNotes.map(note => note.author?.id))].length, averageFollowers: formattedNotes.reduce((sum, note) => sum + (note.author?.details?.followerCount || 0), 0) / formattedNotes.length || 0, maxFollowers: Math.max(...formattedNotes.map(note => note.author?.details?.followerCount || 0)), officialAccounts: formattedNotes.filter(note => note.author?.details?.isOfficial).length, withTwitterConnection: formattedNotes.filter(note => note.author?.details?.twitterConnected).length, withCustomEngagement: formattedNotes.filter(note => note.author?.details?.hasLikeAppeal || note.author?.details?.hasFollowAppeal).length } }; }
  • Top-level registration entry point that calls registerSearchTools(server), which in turn registers the 'analyze-notes' tool among others. Invoked from the main server file.
    export function registerAllTools(server: McpServer): void { // 各カテゴリのツールを登録 registerSearchTools(server); registerNoteTools(server); registerUserTools(server); registerMembershipTools(server); registerMagazineTools(server); registerImageTools(server); registerObsidianTools(server); registerPublishTools(server);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shimayuz/note-com-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server