Skip to main content
Glama
kiwamizamurai

Kibela MCP Server

kibela_get_note_content

Retrieves content and comments of a specific note by ID. Optionally includes image data URLs.

Instructions

Get content and comments of a specific note

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesNote ID
include_image_dataNoWhether to include image data URLs in the response

Implementation Reference

  • Tool definition (schema) for kibela_get_note_content: defines name 'kibela_get_note_content', description 'Get content and comments of a specific note', and input schema requiring 'id' (string) with optional 'include_image_data' (boolean).
    const GET_NOTE_CONTENT_TOOL: Tool = {
      name: "kibela_get_note_content",
      description: "Get content and comments of a specific note",
      inputSchema: {
        type: "object",
        properties: {
          id: { type: "string", description: "Note ID" },
          include_image_data: {
            type: "boolean",
            description: "Whether to include image data URLs in the response",
            default: false,
          },
        },
        required: ["id"],
      },
    };
  • Handler implementation for kibela_get_note_content: extracts 'id' and 'include_image_data' args, builds a GraphQL query (GetNote) that fetches note fields (id, title, content, contentHtml, etc.), author, groups, folders, comments, and optionally attachments with dataUrl. Sends request via GraphQL client and returns the note data as JSON.
    case "kibela_get_note_content": {
      const id = args.id as string;
      const includeImageData = (args.include_image_data as boolean) || false;
    
      const attachmentsFragment = includeImageData
        ? `attachments(first: 3) {
              nodes {
                id
                name
                dataUrl
                mimeType
              }
            }`
        : "";
    
      const operation = `
        query GetNote($id: ID!) {
          note(id: $id) {
            id
            title
            content
            contentHtml
            contentUpdatedAt
            publishedAt
            url
            path
            isLikedByCurrentUser
            ${attachmentsFragment}
            author {
              id
              account
              realName
            }
            groups {
              id
              name
            }
            folders(first: 3) {
              nodes {
                id
                name
                fullName
                path
              }
            }
            comments(first: 3) {
              nodes {
                id
                content
                contentHtml
                author {
                  account
                  realName
                }
                createdAt
              }
            }
          }
        }
      `;
    
      const response = await client.request<NoteContentResponse>(operation, { id });
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(response.note, null, 2),
          },
        ],
      };
    }
  • src/kibela.ts:206-221 (registration)
    Registration of the tool in ListToolsRequestSchema handler: GET_NOTE_CONTENT_TOOL is included in the array of tools returned to the client.
    server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        SEARCH_NOTES_TOOL,
        GET_MY_NOTES_TOOL,
        GET_NOTE_CONTENT_TOOL,
        GET_GROUPS_TOOL,
        GET_GROUP_FOLDERS_TOOL,
        GET_GROUP_NOTES_TOOL,
        GET_FOLDER_NOTES_TOOL,
        GET_USERS_TOOL,
        LIKE_NOTE_TOOL,
        UNLIKE_NOTE_TOOL,
        GET_RECENTLY_VIEWED_NOTES_TOOL,
        GET_NOTE_FROM_PATH_TOOL,
      ],
    }));
  • src/kibela.ts:223-770 (registration)
    Registration in CallToolRequestSchema handler: the switch-case dispatches 'kibela_get_note_content' to its handler block (lines 342-412).
    server.setRequestHandler(CallToolRequestSchema, async (request) => {
      try {
        const { name, arguments: args = {} } = request.params;
    
        switch (name) {
          case "kibela_search_notes": {
            const { query, coediting, isArchived, sortBy, userIds, folderIds } = args as {
              query: string;
              coediting?: boolean;
              isArchived?: boolean;
              sortBy?: string;
              userIds?: string[];
              folderIds?: string[];
            };
    
            const operation = `
              query SearchNotes(
                $query: String!,
                $coediting: Boolean,
                $isArchived: Boolean,
                $sortBy: SearchSortKind,
                $userIds: [ID!],
                $folderIds: [ID!]
              ) {
                search(
                  query: $query,
                  first: 15,
                  coediting: $coediting,
                  isArchived: $isArchived,
                  sortBy: $sortBy,
                  userIds: $userIds,
                  folderIds: $folderIds
                ) {
                  edges {
                    node {
                      document {
                        ... on Note {
                          id
                          title
                          url
                          contentUpdatedAt
                          author {
                            id
                            account
                            realName
                          }
                          groups {
                            id
                            name
                          }
                        }
                      }
                    }
                  }
                }
              }
            `;
    
            const response = await client.request<SearchResponse>(operation, {
              query,
              coediting,
              isArchived,
              sortBy,
              userIds,
              folderIds,
            });
    
            const notes = response.search.edges
              .filter((edge) => edge.node.document !== null)
              .map((edge) => edge.node.document);
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(notes, null, 2),
                },
              ],
            };
          }
    
          case "kibela_get_my_notes": {
            const limit = (args.limit as number) || 15;
            const operation = `
              query GetMyNotes($limit: Int!) {
                currentUser {
                  latestNotes(first: $limit) {
                    totalCount
                    edges {
                      node {
                        id
                        title
                        url
                        contentUpdatedAt
                        author {
                          id
                          account
                          realName
                        }
                      }
                    }
                  }
                }
              }
            `;
    
            const response = await client.request<NotesResponse>(operation, { limit });
            const notes = response.currentUser.latestNotes.edges.map((edge) => edge.node);
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(notes, null, 2),
                },
              ],
            };
          }
    
          case "kibela_get_note_content": {
            const id = args.id as string;
            const includeImageData = (args.include_image_data as boolean) || false;
    
            const attachmentsFragment = includeImageData
              ? `attachments(first: 3) {
                    nodes {
                      id
                      name
                      dataUrl
                      mimeType
                    }
                  }`
              : "";
    
            const operation = `
              query GetNote($id: ID!) {
                note(id: $id) {
                  id
                  title
                  content
                  contentHtml
                  contentUpdatedAt
                  publishedAt
                  url
                  path
                  isLikedByCurrentUser
                  ${attachmentsFragment}
                  author {
                    id
                    account
                    realName
                  }
                  groups {
                    id
                    name
                  }
                  folders(first: 3) {
                    nodes {
                      id
                      name
                      fullName
                      path
                    }
                  }
                  comments(first: 3) {
                    nodes {
                      id
                      content
                      contentHtml
                      author {
                        account
                        realName
                      }
                      createdAt
                    }
                  }
                }
              }
            `;
    
            const response = await client.request<NoteContentResponse>(operation, { id });
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response.note, null, 2),
                },
              ],
            };
          }
    
          case "kibela_get_groups": {
            const operation = `
              query GetGroups {
                groups(first: 10, ability: READABLE) {
                  nodes {
                    id
                    name
                    description
                    isPrivate
                    canBeManaged
                    canBeJoinedBySelf
                    isJoined
                  }
                }
              }
            `;
    
            const response = await client.request<GroupResponse>(operation);
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response.groups.nodes, null, 2),
                },
              ],
            };
          }
    
          case "kibela_get_group_folders": {
            const { groupId, parentFolderId } = args as {
              groupId: string;
              parentFolderId?: string;
            };
    
            const operation = `
              query GetGroupFolders($groupId: ID!, $parentFolderId: ID) {
                group(id: $groupId) {
                  folders(first: 30, active: true, parentFolderId: $parentFolderId) {
                    nodes {
                      id
                      name
                      fullName
                      path
                      canBeManaged
                      parent {
                        id
                        name
                      }
                      notes(first: 10, active: true, orderBy: { field: CONTENT_UPDATED_AT, direction: DESC }) {
                        nodes {
                          id
                          title
                          contentUpdatedAt
                          publishedAt
                          author {
                            account
                            realName
                          }
                        }
                      }
                    }
                  }
                }
              }
            `;
    
            const response = await client.request<GroupFoldersResponse>(operation, {
              groupId,
              parentFolderId,
            });
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response.group.folders.nodes, null, 2),
                },
              ],
            };
          }
    
          case "kibela_get_group_notes": {
            const { groupId } = args as { groupId: string };
    
            const operation = `
              query GetGroupNotes($groupId: ID!) {
                group(id: $groupId) {
                  notes(first: 10, active: true, onlyNotAttachedFolder: true, orderBy: { field: CONTENT_UPDATED_AT, direction: DESC }) {
                    nodes {
                      id
                      title
                      contentUpdatedAt
                      publishedAt
                      author {
                        account
                        realName
                      }
                    }
                  }
                }
              }
            `;
    
            const response = await client.request<GroupNotesResponse>(operation, { groupId });
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response.group.notes.nodes, null, 2),
                },
              ],
            };
          }
    
          case "kibela_get_folder_notes": {
            const { folderId, limit = 100 } = args as { folderId: string; limit?: number };
    
            const operation = `
              query GetFolderNotes($folderId: ID!, $limit: Int!) {
                folder(id: $folderId) {
                  notes(first: $limit, active: true, orderBy: { field: CONTENT_UPDATED_AT, direction: DESC }) {
                    nodes {
                      id
                      title
                      contentUpdatedAt
                      publishedAt
                      author {
                        account
                        realName
                      }
                    }
                  }
                }
              }
            `;
    
            const response = await client.request<FolderNotesResponse>(operation, { folderId, limit });
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response.folder.notes.nodes, null, 2),
                },
              ],
            };
          }
    
          case "kibela_get_users": {
            const operation = `
              query GetUsers {
                users(first: 100) {
                  nodes {
                    id
                    account
                    realName
                  }
                }
              }
            `;
    
            const response = await client.request<UsersResponse>(operation);
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response.users.nodes, null, 2),
                },
              ],
            };
          }
    
          case "kibela_like_note": {
            const noteId = args.noteId as string;
            const operation = `
              mutation LikeNote($input: LikeInput!) {
                like(input: $input) {
                  clientMutationId
                  likers(first: 3) {
                    nodes {
                      id
                      account
                      realName
                    }
                  }
                }
              }
            `;
    
            const response = await client.request<LikeResponse>(operation, {
              input: { noteId },
            });
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response.like, null, 2),
                },
              ],
            };
          }
    
          case "kibela_unlike_note": {
            const noteId = args.noteId as string;
            const operation = `
              mutation UnlikeNote($input: UnlikeInput!) {
                unlike(input: $input) {
                  clientMutationId
                  likers(first: 10) {
                    nodes {
                      id
                      account
                      realName
                    }
                  }
                }
              }
            `;
    
            const response = await client.request<UnlikeResponse>(operation, {
              input: { noteId },
            });
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response.unlike, null, 2),
                },
              ],
            };
          }
    
          case "kibela_get_recently_viewed_notes": {
            const limit = (args.limit as number) || 15;
            const operation = `
              query GetRecentlyViewedNotes($limit: Int!) {
                noteBrowsingHistories(first: $limit) {
                  nodes {
                    note {
                      id
                      title
                      url
                      contentUpdatedAt
                      author {
                        id
                        account
                        realName
                      }
                    }
                  }
                }
              }
            `;
    
            const response = await client.request<RecentlyViewedNotesResponse>(operation, { limit });
            const notes = response.noteBrowsingHistories.nodes.map((node) => node.note);
    
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(notes, null, 2),
                },
              ],
            };
          }
    
          case "kibela_get_note_from_path": {
            const rawPath = args.path as string;
            const includeImageData = (args.include_image_data as boolean) || false;
            // Extract path from URL if full URL is provided
            const path = rawPath.includes("kibe.la/notes/") ? `/notes/${rawPath.split("/notes/")[1]}` : rawPath;
    
            const attachmentsFragment = includeImageData
              ? `attachments(first: 3) {
                    nodes {
                      id
                      name
                      dataUrl
                      mimeType
                    }
                  }`
              : "";
    
            const operation = `            query GetNoteFromPath($path: String!) {
                noteFromPath(path: $path) {
                  id
                  title
                  content
                  contentHtml
                  contentUpdatedAt
                  publishedAt
                  url
                  path
                  isLikedByCurrentUser
                  ${attachmentsFragment}
                  author {
                    id
                    account
                    realName
                  }
                  groups {
                    id
                    name
                  }
                  folders(first: 3) {
                    nodes {
                      id
                      name
                      fullName
                      path
                    }
                  }
                  comments(first: 3) {
                    nodes {
                      id
                      content
                      contentHtml
                      author {
                        account
                        realName
                      }
                      createdAt
                    }
                  }
                }
              }
            `;
    
            const response = await client.request<NoteFromPathResponse>(operation, { path });
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(response.noteFromPath, null, 2),
                },
              ],
            };
          }
    
          default:
            throw new Error(`Unknown tool: ${name}`);
        }
      } catch (error) {
        console.error("Error:", error);
        return {
          content: [
            {
              type: "text",
              text: `Error: ${error instanceof Error ? error.message : String(error)}`,
            },
          ],
          isError: true,
        };
      }
    });
  • Type definition NoteContentResponse used by the handler: specifies that the GraphQL response returns a 'note' combining KibelaNote fields with a 'comments' node containing NoteComment objects.
    export interface NoteContentResponse {
      note: KibelaNote & {
        comments: {
          nodes: NoteComment[];
        };
      };
    }
Behavior2/5

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

No annotations provided; description does not disclose behavioral traits beyond the obvious read operation. Missing details on authentication, rate limits, error handling, or return format expectations for a tool with no output schema.

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?

Single sentence, 6 words, no fluff. Every word is necessary and front-loads the core purpose.

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 no output schema, the description should indicate return format or structure (e.g., note object, comments array). It does not, leaving the agent uninformed about what to expect.

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 coverage is 100% with descriptions for both 'id' (Note ID) and 'include_image_data' (boolean with default). Description adds no additional meaning beyond the schema, meeting baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves content and comments of a specific note, using verb 'Get' and resource 'content and comments'. However, it does not distinguish from the sibling tool 'kibela_get_note_from_path', which also retrieves a note by path, missing an opportunity for differentiation.

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

Usage Guidelines2/5

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

No guidance on when to use this tool versus alternatives (e.g., kibela_get_note_from_path, kibela_search_notes). No conditions described for appropriate use or when not to use.

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

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/kiwamizamurai/mcp-kibela-server'

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