Skip to main content
Glama
TeeDDub

Aladin Book Search MCP Server

by TeeDDub

도서 베스트셀러

get_bestsellers

Retrieve Aladin Bookstore bestseller lists by category or specific week. Customize results with max results, start number, and year/month/week parameters.

Instructions

알라딘 도서 베스트셀러 목록을 조회합니다. 카테고리별로 검색할 수 있으며, 특정 주간의 베스트셀러를 조회할 수 있습니다. 특정 주간을 조회할 때는 연도, 월, 주를 모두 입력해주세요.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
categoryIdNo카테고리 ID (CID) - 특정 카테고리로 검색을 제한할 때 사용
maxResultsNo최대 결과 개수
monthNo조회할 월 (1-12) - 생략하면 현재 주간
startNo검색 시작 번호
weekNo조회할 주 (1-5) - 생략하면 현재 주간
yearNo조회할 연도 (예: 2025) - 생략하면 현재 주간

Implementation Reference

  • The handler function that implements the core logic for the 'get_bestsellers' tool. It constructs parameters for Aladin's ItemList API with QueryType 'Bestseller', optionally includes categoryId, year, month, week filters, fetches data via callAladinApi, maps results to standardized BookSearchResult format, and returns formatted text output.
    async ({ maxResults, start, categoryId, year, month, week }) => {
      try {
        const params: any = {
          QueryType: 'Bestseller',
          MaxResults: maxResults,
          start: start,
          SearchTarget: 'Book',
          Cover: 'Big'
        };
    
        if (categoryId) {
          params.CategoryId = categoryId;
        }
    
        if (year) {
          params.Year = year;
        }
        
        if (month) {
          params.Month = month;
        }
        
        if (week) {
          params.Week = week;
        }
    
        const result = await callAladinApi('ItemList.aspx', params);
        
        const books: BookSearchResult[] = result.item?.map((item: any) => ({
          title: item.title || '',
          author: item.author || '',
          publisher: item.publisher || '',
          pubDate: item.pubDate || '',
          isbn: item.isbn || '',
          isbn13: item.isbn13 || '',
          cover: item.cover || '',
          categoryName: item.categoryName || '',
          description: item.description || '',
          priceStandard: item.priceStandard || 0,
          priceSales: item.priceSales || 0,
          link: item.link || '',
          pages: item.subInfo?.itemPage || undefined,
          pricePerPage: (item.priceStandard > 0 && item.subInfo?.itemPage > 0) 
            ? parseFloat((item.priceStandard / item.subInfo.itemPage).toFixed(2)) 
            : undefined
        })) || [];
    
        const categoryText = categoryId ? ` (카테고리: ${categoryId})` : '';
        const timeText = (year && month && week) ? ` (${year}년 ${month}월 ${week}주)` : '';
        
        return {
          content: [{
            type: 'text',
            text: `📈 베스트셀러 목록${categoryText}${timeText}\n\n검색된 도서 수: ${books.length}권\n\n${JSON.stringify(books, null, 2)}`
          }]
        };
      } catch (error) {
        logger.error(`베스트셀러 조회 중 오류 발생: ${error}`);
        return {
          content: [{
            type: 'text',
            text: `베스트셀러 조회 중 오류가 발생했습니다: ${error instanceof Error ? error.message : String(error)}`
          }],
          isError: true
        };
      }
    }
  • The input schema definition for the 'get_bestsellers' tool using Zod validators for parameters including maxResults, start, optional categoryId, year, month, and week.
    {
      title: '도서 베스트셀러',
      description: '알라딘 도서 베스트셀러 목록을 조회합니다. 카테고리별로 검색할 수 있으며, 특정 주간의 베스트셀러를 조회할 수 있습니다. 특정 주간을 조회할 때는 연도, 월, 주를 모두 입력해주세요.',
      inputSchema: {
        maxResults: z.number().min(1).max(100).default(10).describe('최대 결과 개수'),
        start: z.number().min(1).default(1).describe('검색 시작 번호'),
        categoryId: z.string().optional().describe('카테고리 ID (CID) - 특정 카테고리로 검색을 제한할 때 사용'),
        year: z.number().min(2000).max(2030).optional().describe('조회할 연도 (예: 2025) - 생략하면 현재 주간'),
        month: z.number().min(1).max(12).optional().describe('조회할 월 (1-12) - 생략하면 현재 주간'),
        week: z.number().min(1).max(5).optional().describe('조회할 주 (1-5) - 생략하면 현재 주간')
      }
    },
  • src/index.ts:316-397 (registration)
    The registration of the 'get_bestsellers' tool using McpServer.registerTool, including the tool name, schema, and handler function.
    server.registerTool(
      'get_bestsellers',
      {
        title: '도서 베스트셀러',
        description: '알라딘 도서 베스트셀러 목록을 조회합니다. 카테고리별로 검색할 수 있으며, 특정 주간의 베스트셀러를 조회할 수 있습니다. 특정 주간을 조회할 때는 연도, 월, 주를 모두 입력해주세요.',
        inputSchema: {
          maxResults: z.number().min(1).max(100).default(10).describe('최대 결과 개수'),
          start: z.number().min(1).default(1).describe('검색 시작 번호'),
          categoryId: z.string().optional().describe('카테고리 ID (CID) - 특정 카테고리로 검색을 제한할 때 사용'),
          year: z.number().min(2000).max(2030).optional().describe('조회할 연도 (예: 2025) - 생략하면 현재 주간'),
          month: z.number().min(1).max(12).optional().describe('조회할 월 (1-12) - 생략하면 현재 주간'),
          week: z.number().min(1).max(5).optional().describe('조회할 주 (1-5) - 생략하면 현재 주간')
        }
      },
      async ({ maxResults, start, categoryId, year, month, week }) => {
        try {
          const params: any = {
            QueryType: 'Bestseller',
            MaxResults: maxResults,
            start: start,
            SearchTarget: 'Book',
            Cover: 'Big'
          };
    
          if (categoryId) {
            params.CategoryId = categoryId;
          }
    
          if (year) {
            params.Year = year;
          }
          
          if (month) {
            params.Month = month;
          }
          
          if (week) {
            params.Week = week;
          }
    
          const result = await callAladinApi('ItemList.aspx', params);
          
          const books: BookSearchResult[] = result.item?.map((item: any) => ({
            title: item.title || '',
            author: item.author || '',
            publisher: item.publisher || '',
            pubDate: item.pubDate || '',
            isbn: item.isbn || '',
            isbn13: item.isbn13 || '',
            cover: item.cover || '',
            categoryName: item.categoryName || '',
            description: item.description || '',
            priceStandard: item.priceStandard || 0,
            priceSales: item.priceSales || 0,
            link: item.link || '',
            pages: item.subInfo?.itemPage || undefined,
            pricePerPage: (item.priceStandard > 0 && item.subInfo?.itemPage > 0) 
              ? parseFloat((item.priceStandard / item.subInfo.itemPage).toFixed(2)) 
              : undefined
          })) || [];
    
          const categoryText = categoryId ? ` (카테고리: ${categoryId})` : '';
          const timeText = (year && month && week) ? ` (${year}년 ${month}월 ${week}주)` : '';
          
          return {
            content: [{
              type: 'text',
              text: `📈 베스트셀러 목록${categoryText}${timeText}\n\n검색된 도서 수: ${books.length}권\n\n${JSON.stringify(books, null, 2)}`
            }]
          };
        } catch (error) {
          logger.error(`베스트셀러 조회 중 오류 발생: ${error}`);
          return {
            content: [{
              type: 'text',
              text: `베스트셀러 조회 중 오류가 발생했습니다: ${error instanceof Error ? error.message : String(error)}`
            }],
            isError: true
          };
        }
      }
    );
  • Shared helper function used by get_bestsellers to make HTTP requests to the Aladin API.
    async function callAladinApi(endpoint: string, params: Record<string, any>): Promise<any> {
      if (!ALADIN_TTB_KEY || ALADIN_TTB_KEY.length === 0) {
        throw new Error('알라딘 API 키가 설정되지 않았습니다. ALADIN_TTB_KEY 환경변수를 올바르게 설정해주세요.');
      }
    
      const baseParams = {
        ttbkey: ALADIN_TTB_KEY,
        output: 'js',
        version: '20131101'
      };
    
      const finalParams = { ...baseParams, ...params };
      const url = `${ALADIN_BASE_URL}/${endpoint}`;
    
      try {
        const response = await axios.get(url, { params: finalParams });
        return response.data;
      } catch (error) {
        logger.error(`알라딘 API 호출 오류: ${error}`);
        throw error;
      }
    }
Behavior3/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It describes the core functionality well but lacks details about rate limits, authentication requirements, pagination behavior beyond start parameter, error conditions, or what the response format looks like. The description is adequate for basic understanding but misses important operational details.

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

Conciseness5/5

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

The description is perfectly sized at three sentences, front-loaded with the core purpose, followed by filtering capabilities, and ending with specific guidance for time parameters. Every sentence earns its place with no wasted words or redundant information.

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

Completeness3/5

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

For a read-only query tool with 6 parameters and no output schema, the description provides adequate context about what the tool does and basic usage. However, without annotations and with no output schema, it should ideally describe what the return data looks like (list structure, fields included) and any important behavioral constraints. The description is complete enough for basic understanding but has gaps for full operational use.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents all 6 parameters thoroughly. The description adds some context about the time parameters ('특정 주간을 조회할 때는 연도, 월, 주를 모두 입력해주세요'), but doesn't provide significant additional semantic meaning beyond what's already in the parameter descriptions. This meets the baseline expectation when schema coverage is complete.

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?

The description clearly states the tool's purpose with specific verbs ('조회합니다' - retrieve/query) and resources ('알라딘 도서 베스트셀러 목록' - Aladdin book bestseller list). It distinguishes from siblings by focusing specifically on bestsellers rather than new books, editor choices, or general searches.

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

Usage Guidelines4/5

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

The description provides clear context about when to use this tool - for retrieving bestseller lists with optional category filtering and time period specification. However, it doesn't explicitly state when NOT to use it or mention specific alternatives among the sibling tools (like get_new_books or search_books for different purposes).

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

Install Server

Other Tools

Related Tools

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/TeeDDub/mcp-aladin-books-server'

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