Skip to content

feat: fill MCP surface area gaps (state fields, global create, ordering) #987

@shaoster

Description

@shaoster

Problem / Motivation

The MCP server (potterdoc_mcp/) exposes 9 tools covering piece CRUD, workflow reads, globals reads, and image operations. Several gaps exist that prevent an LLM agent from completing common workflows without falling back to the REST API directly:

  1. No update_current_state_fields tool — an agent can transition a piece to a new state (transition_piece) but cannot update editable fields on the current state without transitioning. The REST endpoint PATCH /api/pieces/<id>/state/ supports this, but it has no MCP equivalent.

  2. No create_global_entry tool — an agent can list global library entries (list_global_entries) but cannot create new ones. For example, an agent cataloging a new piece cannot create a new clay body or location record if it doesn't already exist. The REST endpoint POST /api/globals/<global_name>/ supports this.

  3. list_pieces is missing ordering and shared filters — the REST and GraphQL piece-list supports 6 sort orderings (last_modified_desc, last_modified_asc, name_asc, name_desc, created_desc, created_asc) and a shared boolean filter. The list_pieces MCP tool exposes neither, limiting an agent's ability to find recently modified pieces or pieces shared publicly.

  4. Tags are not documented as a global_name optionlist_global_entries accepts a global_name string but the tool docstring doesn't enumerate valid values. Tags are a global type (tag) that agents need to list in order to supply tag_ids to list_pieces or update_piece_metadata, but this is not discoverable from the tool description alone.

Proposed Solution

  • Add update_current_state_fields(piece_id, fields) tool — delegates to PATCH /api/pieces/<id>/state/. Accepts a fields dict of editable field name → value. Returns the updated state object. Tool docstring should note that only the current (non-sealed) state is editable.

  • Add create_global_entry(global_name, fields) tool — delegates to POST /api/globals/<global_name>/. Accepts the global type key and a fields dict. Returns the created (or existing) entry. For compose_from globals (e.g. glaze_combination), the fields dict contains the component IDs. Tool docstring should warn that this creates a private record for the authenticated user; public library entries are managed via Django admin only.

  • Add ordering and shared parameters to list_pieces — add an ordering string enum parameter and a shared boolean parameter, forwarded to the GraphQL pieces query.

  • Enumerate valid global_name values in list_global_entries docstring — list all global type keys from workflow.yml (clay_body, glaze_type, glaze_combination, glaze_method, location, firing_temperature, tag, section) with a note that the authoritative list comes from get_workflow_schema.

Acceptance Criteria

  • update_current_state_fields(piece_id, fields) tool added; calls PATCH /api/pieces/<id>/state/; docstring explains sealed-state constraint
  • create_global_entry(global_name, fields) tool added; calls POST /api/globals/<global_name>/; docstring explains private-only scope
  • list_pieces accepts ordering (string enum) and shared (bool) parameters, forwarded correctly to the backend
  • list_global_entries docstring enumerates all valid global_name values
  • All MCP integration tests pass: gz_test //potterdoc_mcp/...
  • All linters pass: gz_lint

Out of Scope

  • Image move between states (niche admin operation)
  • Past-state editing (impossible by design — history is append-only)
  • Admin/staff-only endpoints (import tool, manual crop import)
  • Account management (export, delete, invite) — not appropriate for agent access

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions