Skip to main content
Glama
feuerdev
by feuerdev

pin_note

Change the pinned status of a note to keep important notes accessible at the top of your list.

Instructions

Pin or unpin a note.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
note_idYes
pinnedNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The pin_note tool handler function: retrieves the note, validates it is modifiable, sets pinned status, syncs, and returns serialized note.
    @mcp.tool()
    def pin_note(note_id: str, pinned: bool = True) -> str:
        """Pin or unpin a note."""
        keep, note = _get_note_or_raise(note_id)
        _ensure_modifiable(note)
    
        note.pinned = pinned
        keep.sync()
        return json.dumps(serialize_note(note))
  • Registration via @mcp.tool() decorator on the pin_note function, making it an MCP tool named 'pin_note'.
    @mcp.tool()
  • Schema/parameters: note_id (str, required) and pinned (bool, default True) define the input contract.
    def pin_note(note_id: str, pinned: bool = True) -> str:
  • The serialize_note helper function used by pin_note to convert the note object into a JSON-serializable dict (including the 'pinned' field).
    def serialize_note(note):
        """
        Serialize a Google Keep note into a dictionary.
        
        Args:
            note: A Google Keep note object
            
        Returns:
            dict: A dictionary containing the note's id, title, text, pinned status, color and labels
        """
        payload = {
            'id': note.id,
            'title': note.title,
            'text': note.text,
            'type': note.type.value,
            'pinned': note.pinned,
            'archived': note.archived,
            'trashed': note.trashed,
            'color': note.color.value if note.color else None,
            'labels': [serialize_label(label) for label in note.labels.all()],
            'collaborators': list(note.collaborators.all()),
        }
    
        if hasattr(note, 'items'):
            payload['items'] = [serialize_list_item(item) for item in note.items]
    
        payload['media'] = [
            {
                'blob_id': blob.id,
                'type': blob.blob.type.value if blob.blob and blob.blob.type else None,
            }
            for blob in note.blobs
        ]
    
        return payload
  • The _get_note_or_raise helper used to fetch the note by ID or raise an error.
    def _get_note_or_raise(note_id: str):
        keep = get_client()
        note = keep.get(note_id)
        if not note:
            raise ValueError(f"Note with ID {note_id} not found")
        return keep, note

Schema Changelog

Changes observed during successful MCP inspections.

  1. Addedv0.3.1

TDQS

C2.9/5.0
Behavior2/5

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

With no annotations, the description carries the full burden for behavioral disclosure, but it only restates the core action. It does not mention idempotency, effect on note ordering/visibility, behavior on archived or trashed notes, invalid note_id handling, or what response is returned. No contradiction with annotations because none are 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?

The description is six words and fully front-loaded. There is no filler, and for a simple two-parameter toggle the size is appropriate; all other gaps are issues of content rather than structure.

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?

Given the low complexity and presence of an output schema, the description does not need to explain return values. It is minimally viable: an agent can infer the basic call from the name, schema, and short description. However, missing behavioral details and usage routing keep it from being fully complete.

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

Parameters2/5

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

Schema description coverage is 0% and the description adds no explicit parameter meaning beyond the phrase 'Pin or unpin'. It does not clarify that pinned=false means unpin or explain note_id format/constraints. The schema's titles and default for pinned provide some self-evident meaning, keeping this above 1, but the description does not compensate for the missing documentation.

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 states a specific action ('Pin or unpin') and resource ('a note'), making the tool's purpose immediately clear. It is not a tautology and the operation is distinct enough from siblings like archive_note and trash_note that an agent can identify it, though it does not explicitly contrast with update_note.

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 when-to-use guidance, preconditions, or alternatives are provided. The description gives no indication of when pinning is appropriate or how this differs from update_note or other note operations. Usage context must be inferred entirely from the tool name.

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