-
Notifications
You must be signed in to change notification settings - Fork 206
Description
Component(s)
router
Is your feature request related to a problem? Please describe.
Currently, MCP tool arguments only get descriptions if the underlying GraphQL type (e.g., SearchInput) has a description in the federated schema. There's no way to document individual operation variables at the operation level.
This is a problem because:
- LLM context - AI agents benefit from descriptive argument names and descriptions to understand how to use tools
- Operation-specific semantics - A
$idvariable might mean "employee ID" in one operation and "product ID" in another; the type-level description can't capture this - Self-documenting operations - Operations should be self-contained documentation units without requiring schema modifications
Related to #2308 and #2309 which added @mcpTool(name:) and operation-level descriptions.
Describe the solution you'd like
Add an @mcpToolArg directive that can be applied to variable definitions to specify argument descriptions:
"""
Retrieve an employee by their unique identifier.
"""
query GetEmployee(
$id: Int! @mcpToolArg(description: "The unique employee identifier")
$includeDetails: Boolean @mcpToolArg(description: "Include extended profile details")
) @mcpTool(name: "get_employee") {
employee(id: $id) {
id
name
details @include(if: $includeDetails) { email department }
}
}This would produce an MCP tool with:
{
"name": "get_employee",
"description": "Retrieve an employee by their unique identifier.",
"inputSchema": {
"type": "object",
"properties": {
"id": { "type": "integer", "description": "The unique employee identifier" },
"includeDetails": { "type": "boolean", "description": "Include extended profile details" }
},
"required": ["id"]
}
}Implementation approach (Cosmo-only, no upstream changes):
- Add
VariableDescriptions map[string]stringfield toOperationstruct inrouter/pkg/schemaloader/loader.go - Implement
extractMCPToolArgDescriptions()to parse@mcpToolArgdirectives from variable definitions - Implement
stripMCPToolArgDirectives()(similar to existingstripMCPDirective) - In
schema_builder.go, afterjsonschema.BuildJsonSchema()returns, merge descriptions into the JSON schema properties - Add tests
Notes:
requiredcontinues to be inferred from GraphQL nullability (!)- Directive location is
VARIABLE_DEFINITION(spec-compliant since GraphQL Sep 2025) - Directive must be stripped before validation to avoid "unknown directive" errors
Describe alternatives you've considered
Alternative 1: Upstream to graphql-go-tools
Extend BuildJsonSchema in graphql-go-tools/v2/pkg/engine/jsonschema to accept variable descriptions as an option:
type BuildOptions struct {
VariableDescriptions map[string]string
}
func BuildJsonSchema(opDoc, schemaDoc *ast.Document, opts ...BuildOptions) (*JSONSchema, error)Pros: Cleaner separation, reusable. Cons: Requires upstream PR and release cycle.
Alternative 2: Use Operation Description
This is generally the approach we'd currently use as a workaround. Basically, we add a docstring description to the operation and include a description of arguments and their purposes.
Pros: it works. Cons: Non-standard, so it shows up poorly in upstream MCP registries
Alternative 3: External metadata file
Separate YAML/JSON file mapping operation variables to descriptions. Cons: Disconnected from operations, harder to maintain.