Skip to main content
Glama
ppetru

TiddlyWiki MCP Server

by ppetru

update_tiddler

Updates an existing tiddler in a TiddlyWiki wiki, showing a diff of changes and requesting approval before applying. Preserves metadata like created timestamp and supports custom fields.

Instructions

Update an existing tiddler. Shows a diff of changes and requests approval before applying. Preserves metadata like created timestamp. Supports arbitrary custom fields beyond the standard ones (e.g., caption, summary, author, or any TiddlyWiki field).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
titleYesTitle of the tiddler to update
textNoNew text content (optional)
tagsNoNew tags as space-separated string (optional)
typeNoContent type like "text/markdown" or "text/vnd.tiddlywiki" (optional)

Implementation Reference

  • The main handler function for the update_tiddler tool. Parses input via UpdateTiddlerInput schema, fetches current tiddler, applies updates (text, tags, type, custom fields), generates a diff, and saves the tiddler.
    export async function handleUpdateTiddler(args: unknown): Promise<ToolResult> {
      const input = UpdateTiddlerInput.parse(args);
    
      // Get current tiddler
      const current = await getTiddler(input.title);
      if (!current) {
        return {
          content: [
            {
              type: 'text',
              text: JSON.stringify({ error: `Tiddler not found: ${input.title}` }, null, 2),
            },
          ],
          isError: true,
        };
      }
    
      // Build updated tiddler - include all custom fields from input
      const { title: _title, text, tags, type, ...customFields } = input;
      const updates: Partial<Tiddler> = { ...customFields };
      if (text !== undefined) updates.text = text;
      if (tags !== undefined) updates.tags = tags;
      if (type !== undefined) updates.type = type;
    
      const updated = updateTiddlerObject(current, updates, getAuthUser());
    
      // Generate diff
      const diff = generateTiddlerDiff(current, updated);
    
      // Apply the change
      await putTiddler(updated);
    
      return {
        content: [
          {
            type: 'text',
            text: `## Updated: "${input.title}"\n\n${diff}`,
          },
        ],
      };
    }
  • Zod schema for the update_tiddler input. Defines title (required), text, tags, type as optional fields, with passthrough() to allow arbitrary custom fields.
    export const UpdateTiddlerInput = z
      .object({
        title: z.string().describe('Title of the tiddler to update'),
        text: z.string().optional().describe('New text content'),
        tags: z.string().optional().describe('New tags (space-separated)'),
        type: z.string().optional().describe('Content type (e.g., text/markdown)'),
      })
      .passthrough(); // Allow additional custom fields
    
    export type UpdateTiddlerInputType = z.infer<typeof UpdateTiddlerInput>;
  • src/index.ts:154-248 (registration)
    Registration of the update_tiddler tool: name/description/inputSchema in the server definition (line 154) and routing in the switch statement (line 247-248).
            name: 'update_tiddler',
            description:
              'Update an existing tiddler. Shows a diff of changes and requests approval before applying. Preserves metadata like created timestamp. Supports arbitrary custom fields beyond the standard ones (e.g., caption, summary, author, or any TiddlyWiki field).',
            inputSchema: {
              type: 'object',
              properties: {
                title: {
                  type: 'string',
                  description: 'Title of the tiddler to update',
                },
                text: {
                  type: 'string',
                  description: 'New text content (optional)',
                },
                tags: {
                  type: 'string',
                  description: 'New tags as space-separated string (optional)',
                },
                type: {
                  type: 'string',
                  description:
                    'Content type like "text/markdown" or "text/vnd.tiddlywiki" (optional)',
                },
              },
              additionalProperties: {
                type: 'string',
                description: 'Any additional TiddlyWiki field (e.g., caption, summary, author)',
              },
              required: ['title'],
            },
          },
          {
            name: 'create_tiddler',
            description:
              'Create a new tiddler. Shows a preview and requests approval before creating. Supports arbitrary custom fields beyond the standard ones (e.g., caption, summary, author, or any TiddlyWiki field).',
            inputSchema: {
              type: 'object',
              properties: {
                title: {
                  type: 'string',
                  description: 'Title of the new tiddler',
                },
                text: {
                  type: 'string',
                  description: 'Text content',
                },
                tags: {
                  type: 'string',
                  description:
                    'Tags as space-separated string (optional, e.g., "Journal" or "Journal OYS")',
                  default: '',
                },
                type: {
                  type: 'string',
                  description: 'Content type (default: text/markdown)',
                  default: 'text/markdown',
                },
              },
              additionalProperties: {
                type: 'string',
                description: 'Any additional TiddlyWiki field (e.g., caption, summary, author)',
              },
              required: ['title', 'text'],
            },
          },
          {
            name: 'delete_tiddler',
            description:
              'Delete a tiddler. Shows current content and requests approval before deleting.',
            inputSchema: {
              type: 'object',
              properties: {
                title: {
                  type: 'string',
                  description: 'Title of the tiddler to delete',
                },
              },
              required: ['title'],
            },
          },
        ],
      };
    });
    
    // Tool implementation handler
    server.setRequestHandler(CallToolRequestSchema, async (request) => {
      const { name, arguments: args } = request.params;
    
      try {
        switch (name) {
          case 'search_tiddlers':
            return await handleSearchTiddlers(args, getToolDependencies());
    
          case 'update_tiddler':
            return await handleUpdateTiddler(args);
  • Helper function that merges updates onto the current tiddler while preserving created/creator/title fields, setting modified/modifier timestamp, and stripping server-managed fields.
    export function updateTiddlerObject(
      current: Tiddler,
      updates: Partial<Tiddler>,
      modifier: string
    ): Tiddler {
      return {
        ...current,
        ...updates,
        // Always preserve these fields from the current tiddler
        title: current.title,
        created: current.created,
        creator: current.creator,
        // Set modification metadata
        modified: generateTimestamp(),
        modifier,
        // Remove server-managed fields
        revision: undefined,
        bag: undefined,
      };
    }
  • Helper function that generates a human-readable diff between the old and new tiddler, including text diff (using createTwoFilesPatch) and metadata changes (tags, type).
    function generateTiddlerDiff(oldTiddler: Tiddler, newTiddler: Tiddler): string {
      const lines: string[] = [];
    
      // Text diff
      const oldText = oldTiddler.text || '';
      const newText = newTiddler.text || '';
    
      if (oldText !== newText) {
        const patch = createTwoFilesPatch(
          oldTiddler.title,
          newTiddler.title,
          oldText,
          newText,
          'Before',
          'After',
          { context: 1 } // Reduce context to 1 line for more compact diffs
        );
    
        // Add a concise summary
        const oldLines = oldText.split('\n').length;
        const newLines = newText.split('\n').length;
        const delta = newLines - oldLines;
        const summary =
          delta > 0
            ? `+${delta} line${delta === 1 ? '' : 's'}`
            : delta < 0
              ? `${delta} line${delta === -1 ? '' : 's'}`
              : 'modified';
    
        lines.push(`**Content:** ${summary}`);
        lines.push('```diff');
        lines.push(patch);
        lines.push('```');
      }
    
      // Metadata changes
      const metadataChanges: string[] = [];
    
      if (oldTiddler.tags !== newTiddler.tags) {
        metadataChanges.push(`  tags: "${oldTiddler.tags || ''}" → "${newTiddler.tags || ''}"`);
      }
    
      if (oldTiddler.type !== newTiddler.type) {
        metadataChanges.push(`  type: "${oldTiddler.type}" → "${newTiddler.type}"`);
      }
    
      if (metadataChanges.length > 0) {
        lines.push('');
        lines.push('**Metadata:**');
        lines.push(...metadataChanges);
      }
    
      return lines.join('\n');
    }
Behavior4/5

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

Given no annotations, the description carries full burden. It discloses that the tool shows a diff, requests approval before applying, and preserves metadata like created timestamp. This is fairly transparent, though it lacks details on auth needs, rate limits, or what happens on failure. Still above average.

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?

Three sentences, each earning its place: first states purpose, second adds key behavioral traits, third clarifies field support. Front-loaded and efficient.

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?

The tool has 4 parameters and no output schema. The description covers the update behavior and arbitrary fields but does not explain return values, error handling (e.g., tiddler not found), or the full scope of what 'preserves metadata' entails. Adequate but not complete.

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%, so the baseline is 3. The description mentions support for arbitrary custom fields, which reinforces the schema's additionalProperties but does not add new meaning beyond what the schema already provides (e.g., 'caption, summary, author'). No additional parameter context is provided.

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 'Update an existing tiddler' and distinguishes it from sibling tools (create, delete, search) by name and description. It also adds specific behavior like showing a diff and requesting approval, which clarifies the tool's role.

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 implies the tool is for updating existing tiddlers, and the sibling tool names provide context, but it does not explicitly state when to use this over alternatives or when not to use it. However, the behavioral note about diff/approval suggests an interactive use case.

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/ppetru/tiddlywiki-mcp'

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