Skip to main content
Glama

twining_what_changed

Track changes in decisions and entries since a specific timestamp to catch up on updates in the Twining MCP Server's coordination system.

Instructions

Report what changed since a given point in time. Returns new decisions, new entries, overridden decisions, and reconsidered decisions. Use this to catch up on changes since you last checked.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sinceYesISO 8601 timestamp (e.g., 2024-01-15T10:00:00Z)
scopeNoOptional scope filter

Implementation Reference

  • The actual implementation of the twining_what_changed logic inside the ContextAssembler class.
    async whatChanged(
      since: string,
      scope?: string,
    ): Promise<WhatChangedResult> {
      // Get new entries since timestamp
      const readOpts: { since: string; scope?: string } = { since };
      if (scope) readOpts.scope = scope;
      const { entries } = await this.blackboardStore.read(readOpts);
    
      const newEntries = entries.map((e) => ({
        id: e.id,
        entry_type: e.entry_type,
        summary: e.summary,
      }));
    
      // Get decisions since timestamp
      const index = await this.decisionStore.getIndex();
      let filteredIndex = index.filter((e) => e.timestamp >= since);
      if (scope) {
        filteredIndex = filteredIndex.filter(
          (e) =>
            e.scope.startsWith(scope) || scope.startsWith(e.scope),
        );
      }
    
      const newDecisions = filteredIndex
        .filter((e) => e.status === "active" || e.status === "provisional")
        .map((e) => ({ id: e.id, summary: e.summary }));
    
      // Find overridden decisions since timestamp
      const overriddenDecisions: WhatChangedResult["overridden_decisions"] = [];
      const allOverridden = index.filter((e) => e.status === "overridden");
      for (const entry of allOverridden) {
        const decision = await this.decisionStore.get(entry.id);
        if (decision && decision.timestamp >= since) {
          if (!scope || decision.scope.startsWith(scope) || scope.startsWith(decision.scope)) {
            overriddenDecisions.push({
              id: decision.id,
              summary: decision.summary,
              reason: decision.override_reason ?? "No reason provided",
            });
          }
        }
      }
    
      // Find reconsidered (provisional) decisions since timestamp
      const reconsideredDecisions = filteredIndex
        .filter((e) => e.status === "provisional")
        .map((e) => ({ id: e.id, summary: e.summary }));
    
      return {
        new_decisions: newDecisions,
        new_entries: newEntries,
        overridden_decisions: overriddenDecisions,
        reconsidered_decisions: reconsideredDecisions,
      };
    }
  • The tool registration and request handler for twining_what_changed in context-tools.ts.
    server.registerTool(
      "twining_what_changed",
      {
        description:
          "Report what changed since a given point in time. Returns new decisions, new entries, overridden decisions, and reconsidered decisions. Use this to catch up on changes since you last checked.",
        inputSchema: {
          since: z
            .string()
            .refine((val) => !isNaN(Date.parse(val)), {
              message: "Must be a valid ISO 8601 timestamp",
            })
            .describe("ISO 8601 timestamp (e.g., 2024-01-15T10:00:00Z)"),
          scope: z.string().optional().describe("Optional scope filter"),
        },
      },
      async (args) => {
        try {
          const result = await contextAssembler.whatChanged(
            args.since,
            args.scope,
          );
          return toolResult(result);
        } catch (e) {
          if (e instanceof TwiningError) {
            return toolError(e.message, e.code);
          }
          return toolError(
            e instanceof Error ? e.message : "Unknown error",
            "INTERNAL_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 tool's function and output categories but doesn't mention important behavioral aspects like whether this is a read-only operation, potential rate limits, authentication requirements, or how results are structured/paginated. The description adds basic context but lacks depth for a tool with no annotation coverage.

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 concise and well-structured: two sentences that efficiently convey purpose and usage. Every word earns its place with zero redundancy. The first sentence explains what the tool does and what it returns, while the second provides clear usage guidance.

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 tool with 2 parameters, 100% schema coverage, but no annotations and no output schema, the description provides adequate but minimal context. It explains the tool's purpose and basic usage but doesn't compensate for the lack of output schema or behavioral annotations. The description is complete enough for basic understanding but leaves important questions unanswered about return format and operational characteristics.

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 both parameters completely. The description doesn't add any parameter-specific information beyond what's in the schema. It mentions 'since a given point in time' which aligns with the 'since' parameter but provides no additional semantic context. Baseline 3 is appropriate when schema does the heavy lifting.

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's purpose: 'Report what changed since a given point in time' with specific output categories (new decisions, new entries, overridden decisions, reconsidered decisions). It distinguishes itself from siblings by focusing on change detection rather than operations like 'decide', 'override', or 'reconsider'. However, it doesn't explicitly differentiate from 'twining_recent' which might have overlapping functionality.

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 for when to use this tool: 'Use this to catch up on changes since you last checked.' This gives practical guidance about its primary use case. However, it doesn't specify when NOT to use it or mention alternatives among the many sibling tools, particularly 'twining_recent' which might serve a similar purpose.

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/daveangulo/twining-mcp'

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