Skip to content

Toolcraft: expose standard MCP tool annotations and titles from defineCommand #526

Description

@kamilio

Problem

Toolcraft commands cannot declare standard MCP tool metadata. CommandConfig has no title or annotations, and the MCP adapter registers commands through the legacy server.tool(...) overload. As a result, every generated MCP tool omits readOnlyHint, destructiveHint, idempotentHint, and openWorldHint.

MCP applies pessimistic defaults when these fields are absent: non-read-only, potentially destructive, non-idempotent, and open-world. A consumer with many read tools therefore presents all of them as destructive. OpenAI Apps review also expects complete annotations.

The bundled tiny MCP server already supports these fields through registerTool(definition, handler).

Proposed API

Keep this optional and local to the existing command API:

defineCommand({
  name: "get",
  title: "Get calendar event",
  annotations: {
    readOnlyHint: true,
    destructiveHint: false,
    idempotentHint: true,
    openWorldHint: false
  },
  params,
  handler
})

Non-MCP and existing commands should require no changes. Re-export a Toolcraft-owned structural ToolAnnotations type so callers do not need to import a transport package.

Implementation

  • Add optional title and annotations to CommandConfig and materialized Command metadata.
  • Clone and preserve them across group materialization/composition.
  • Include them in enumerated MCP tool definitions.
  • Register non-stream tools through server.registerTool({ name, title, description, inputSchema, outputSchema, annotations }, handler).
  • Preserve existing input/output validation and structured-content behavior.
  • Add tools/list tests for all four boolean hints and title, plus a compatibility test proving commands without metadata remain unchanged.

Acceptance criteria

  • tools/list contains declared title and annotations unchanged.
  • All four standard hints are supported.
  • Output schemas continue to be advertised and validated.
  • CLI/SDK behavior and commands that omit this optional metadata are unchanged.
  • Public API stays on defineCommand; no separate package or server-specific configuration is required.

Found while auditing the hosted Skylight Calendar MCP server, where all 116 tools currently inherit the unsafe defaults.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions