Skip to main content
Glama
moria97
by moria97

search-book

Search for books on Douban using ISBN numbers or keyword queries to find titles, authors, and publication details.

Instructions

search books from douban, either by ISBN or by query

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
qNoquery string, e.g. "python"
isbnNoISBN number, e.g. "9787501524044"

Implementation Reference

  • src/index.ts:25-55 (registration)
    Registration of the 'search-book' tool with MCP server, including description, input schema, and inline handler function.
    server.tool(
      TOOL.SEARCH_BOOK,
      'search books from douban, either by ISBN or by query',
      {
        q: z.string().optional().describe('query string, e.g. "python"'),
        isbn: z.string().optional().describe('ISBN number, e.g. "9787501524044"')
      },
      async (args) => {
        if (!args.isbn && !args.q) {
          throw new McpError(ErrorCode.InvalidParams, "Either q or isbn must be provided")
        }
        const books = await searchBooks(args)
        const text = json2md({
          table: {
            headers: ['publish_date', 'title', 'author', 'rating' ,'id', 'isbn'],
            rows: books.map(_ => ({
              id: _.id || '',
              title: _.title || '',
              author: (_.author || []).join('、'),
              publish_date: _.pubdate,
              isbn: _.isbn13 || '',
              rating: `${_.rating?.average || 0} (${_.rating?.numRaters || 0}人)`
            }))
          }
        })
    
        return {
          content: [{ type: 'text', text }]
        }
      }
    );
  • Helper function searchBooks that dispatches to keyword or ISBN search on Douban API.
    export async function searchBooks(params: {
      q?: string
      isbn?: string
    }) {
      if (params.q) {
        return searchByKeyword(params.q)
      }
      if (params.isbn) {
        return searchByISBN(params.isbn)
      }
      return []
    }
  • Implementation of keyword-based book search using Douban v2 API.
    async function searchByKeyword (q: string) {
      const url = new URL('https://api.douban.com/v2/book/search')
      url.searchParams.set('q', q)
      url.searchParams.set('apikey', apiKey)
      const res: {
        count: number
        start: number
        total: number
        books: Douban.Book[]
      } = await (await fetch(url.toString(), {
        headers: FAKE_HEADERS
      })).json()
    
      return res?.books ? res.books.map(parseDoubanBook) : []
    }
  • TOOL enum defining the 'search-book' name as SEARCH_BOOK constant, used for registration.
    export enum TOOL {
      SEARCH_BOOK = 'search-book',
      LIST_BOOK_REVIEWS = 'list-book-reviews',
      SEARCH_MOVIE = 'search-movie',
      LIST_MOVIE_REVIEWS = 'list-movie-reviews',
      BROWSE = 'browse',
      LIST_GROUP_TOPICS = 'list-group-topics',
      GET_GROUP_TOPIC_DETAIL = 'get-group-topic-detail'
    }
  • TypeScript interface for Douban Book, used in search results.
    interface Book {
      rating: {
        max: number
        numRaters: number
        average: string
        min: number
      }
      subtitle: string
      author: string[]
      pubdate: string
      tags: {
        count: number
        name: string
        title: string
      }[]
      origin_title: string
      image: string
      binding: string
      translator: any[]
      catalog: string
      pages: string
      images: {
        small: string
        large: string
        medium: string
      }
      alt: string
      id: string
      publisher: string
      isbn10: string
      isbn13: string
      title: string
      url: string
      alt_title: string
      author_intro: string
      summary: string
      series: {
        id: string
        title: string
      }
      price: string
      ebook_url: string
    }

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv1.0.0
    • addedInput schema / $schema
      Added value: +"http://json-schema.org/draft-07/schema#"
    • addedInput schema / additionalProperties
      Added value: +false
  2. First observed

TDQS

A3.8/5.0
Behavior2/5

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

With no annotations, the description bears full responsibility for disclosing behavior. It only states the search action and criteria, omitting key details such as return format, authentication needs, rate limits, or that at least one parameter should be provided.

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?

A single, front-loaded sentence conveys the essential purpose and usage modes without any redundant wording. It is an exemplary model of conciseness.

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

Completeness2/5

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

Given the absence of an output schema and annotations, the description is too thin to fully prepare an agent. It does not describe what the search returns (e.g., list, details), pagination, or other behavioral nuances, making it incomplete for confident invocation.

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

Parameters4/5

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

The schema already describes each parameter with 100% coverage, so the baseline is 3. The description adds value by specifying 'either by ISBN or by query,' implying mutual exclusivity and that at least one is expected, which goes beyond the schema definition.

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 action (search) on a specific resource (books from douban) and highlights two search modes (ISBN or query). This distinguishes it from sibling search tools like search-movie, which target a different resource.

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 makes it evident this tool is for searching books, differentiating it from movie and TV tools. However, it does not explicitly mention alternatives or when not to use this tool, though the context is clear.

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