Improve AI agent usability across all MCP tools - #14
Open
lucasjahn wants to merge 7 commits into
Open
Conversation
List tools (orders, products, customers, collections) now accept an optional 'fields' parameter to select which fields the GraphQL query returns, reducing context pollution when only IDs or specific data is needed. Max page size raised from 10-100 to 250 (Shopify API limit). Affected tools: get-orders, get-products, get-customers, get-collections, get-customer-orders
Make descriptions more assertive so AI agents actually use the fields parameter instead of fetching all data. Descriptions now tell agents to always specify fields, and to ask the user which fields are needed when unsure rather than defaulting to all fields.
… and bulk tags Driven by iterative feedback from an AI consumer agent testing all 45 tools, this addresses the main friction points when an LLM operates the MCP toolset without human guidance. Field selection & countOnly: - Add `fields` param to all GET tools (products, orders, customers, collections, metafields, variants) so agents fetch only the data they need - Add `countOnly` param to list tools (get-products, get-orders, get-customers, get-customer-orders) to size result sets before paginating - Increase max page size from 50 to 250 on list endpoints Bulk tag management: - Add manage-tags-bulk tool for batch add/remove on up to 100 resources Description clarity & consistency: - Add format examples to all ID params (GID vs numeric, with examples) - Add cross-tool navigation hints (e.g. create-fulfillment references get-fulfillment-orders for obtaining required IDs) - Add metafield upsert semantics to all update tools - Add customer notification safety warnings requiring user confirmation - Change inventory-set-quantities reason from free text to validated enum Collection improvements: - Add field selection to get-collection-by-id README: - Update tool count from 31 to 45 - Document new sections: Collections, Configuration, Enhanced Order, Inventory & Pricing, shared field selection and countOnly capabilities
Owner
|
hi @lucasjahn thanks for the PR, I found there's merge conflicts after #13 got merged, can you sync with origin main again? thanks |
|
Hi, just curious. Do we have some bandwidth issues to get this merged? If yes, are you guys open for help here? Would love to contribute and get this merged before I use this in my project. |
Resolves conflicts from upstream's "Add Shopify GraphQL codegen
validation" change, which added #graphql magic comments so codegen
validates queries against the live Shopify schema.
Conflict: the field-selection tools build queries dynamically via
${fieldSelection} interpolation, which is incompatible with static
codegen extraction (interpolations are stripped, yielding empty
selection sets). graphql-tag-pluck only picks up gql-tagged /
#graphql documents, so the dynamic queries use plain template
strings and are simply skipped by validation (their result type was
already `any`, so no type coverage is lost).
Resolution for the 10 conflicted GET tools: keep the dynamic
plain-string queries (field selection, countOnly, and getMetafields'
keys/namespace branches). Every fully-static query elsewhere keeps
its gql/#graphql tag and stays schema-validated.
Verified: `npm run build` and `npm run validate:graphql` both pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deepening refactor (architecture review candidates A + B). The field
selection feature was three shallow pieces kept in sync by hand across
10 GET tools: a FIELD_MAP of fragments, an AVAILABLE_*_FIELDS enum, a
~450-char copy-pasted "always specify fields" describe string, and a
per-tool formatter that re-discovered which fields are connections.
defineProjection() in src/lib/projection.ts is now the single source of
truth per tool. From one field→fragment map it derives:
- selection(fields): the GraphQL selection set (id always included),
joined with newlines — removes the hidden 16-space indent coupling in
the old buildFieldSelection (GraphQL is whitespace-insensitive).
- fieldsParam({noun, extra}): the zod `fields` param with the shared
agent guidance baked in — the describe text now lives in exactly one
place instead of being copy-pasted (with drift) across 10 files.
- normalize(node): flattens any top-level connection-shaped value
({edges:[...]}) to an array of nodes. Shape-based, so field aliases
(e.g. addressesV2 under key "addresses") are handled correctly.
countOnlyParam() likewise centralizes the countOnly guidance.
Pure refactor — output shapes unchanged. Per-tool renames (priceRangeV2
→priceRange, addressesV2→addresses), computed fields (imageUrl, variant
image), and formatOrderSummary delegation are preserved; default
(no-fields) paths are untouched. getMetafields keeps its own keys/
namespace model. buildFieldSelection removed.
Net: tools shrink by ~200 lines; selection/normalize are now pure and
unit-testable without the GraphQL client global.
Verified: npm run build and npm run validate:graphql both pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`fallow` flagged the count-only block as duplicated across the four list tools (get-products, get-orders, get-customers, get-customer-orders) — each inlined a near-identical *Count query, request, and unwrap that differed only by the count field name and the query filter. Add fetchCount(client, countField, query?) to projection.ts (alongside countOnlyParam, its schema counterpart) and call it from all four tools. Pure refactor — behavior unchanged. Verified: npm run build and npm run validate:graphql both pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The shared `fields` guidance hardcoded the example ["id", "title"], but orders use `name` and customers have no `title` field — an agent copying the example into get-orders/get-customers would hit a zod enum rejection. Derive the example field from the projection's own fields (first non-id key), so the example is always a valid selection for that tool. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Author
|
@GeLi2001 you can have another look over it. It diverged a bit from main so I had to make some conflict resolving. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When an AI agent/LLM consumed this MCP toolset autonomously, it hits several friction points that cause unnecessary round-trips, context bloat, and outright errors:
Solution
Iterative improvements driven by a consumer AI agent auditing all 45 tools.
All changes are backwards compatible. No new dependencies.