From f0d69121d4f28ccc5a3570a05ad6d72f88594441 Mon Sep 17 00:00:00 2001 From: Evan Silverman Date: Fri, 12 Sep 2025 14:15:51 -0400 Subject: [PATCH 1/9] add minify support for directives and specify deprecated --- .../src/introspection/minify.rs | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/apollo-mcp-server/src/introspection/minify.rs b/crates/apollo-mcp-server/src/introspection/minify.rs index 81af9534..c029e1b9 100644 --- a/crates/apollo-mcp-server/src/introspection/minify.rs +++ b/crates/apollo-mcp-server/src/introspection/minify.rs @@ -1,6 +1,6 @@ use apollo_compiler::schema::{ExtendedType, Type}; use regex::Regex; -use std::sync::OnceLock; +use std::{collections::HashMap, sync::OnceLock}; pub trait MinifyExt { /// Serialize in minified form @@ -72,6 +72,34 @@ fn minify_input_object(input_object_type: &apollo_compiler::schema::InputObjectT format!("I:{type_name}:{fields}") } +// We should only minify directives that assist the LLM in understanding the schema. This included @deprecated +fn minify_directives(directives: &apollo_compiler::ast::DirectiveList) -> String { + let mut result = String::new(); + + static DIRECTIVES_TO_MINIFY: OnceLock> = OnceLock::new(); + let directives_to_minify = + DIRECTIVES_TO_MINIFY.get_or_init(|| HashMap::from([("deprecated", "D")])); + + for directive in directives.iter() { + if let Some(minified_name) = directives_to_minify.get(directive.name.as_str()) { + if !directive.arguments.is_empty() { + // Since we're only handling @deprecated right now we can just add the reason and minify it + let reason = directive + .arguments + .iter() + .find(|a| a.name == "reason") + .and_then(|a| a.value.as_str()) + .unwrap_or("No longer supported") + .to_string(); + result.push_str(&format!("@{}(\"{}\")", minified_name, reason)); + } else { + result.push_str(&format!("@{}", minified_name)); + } + } + } + result +} + fn minify_fields( fields: &apollo_compiler::collections::IndexMap< apollo_compiler::Name, @@ -99,6 +127,8 @@ fn minify_fields( // Add field type result.push(':'); result.push_str(&type_name(&field.ty)); + result.push_str(&minify_directives(&field.directives)); + result.push(','); } @@ -128,6 +158,7 @@ fn minify_input_fields( result.push_str(field_name.as_str()); result.push(':'); result.push_str(&type_name(&field.ty)); + result.push_str(&minify_directives(&field.directives)); result.push(','); } @@ -147,13 +178,19 @@ fn minify_arguments( .map(|arg| { if let Some(desc) = arg.description.as_ref() { format!( - "\"{}\"{}:{}", + "\"{}\"{}:{}{}", normalize_description(desc), arg.name.as_str(), - type_name(&arg.ty) + type_name(&arg.ty), + minify_directives(&arg.directives) ) } else { - format!("{}:{}", arg.name.as_str(), type_name(&arg.ty)) + format!( + "{}:{}{}", + arg.name.as_str(), + type_name(&arg.ty), + minify_directives(&arg.directives) + ) } }) .collect::>() From 880ff4405bee4ef36ef9d873d757d7fad2b82475 Mon Sep 17 00:00:00 2001 From: Evan Silverman Date: Fri, 12 Sep 2025 14:16:17 -0400 Subject: [PATCH 2/9] update tool descriptions to support Deprecated directive understanding in the LLM --- crates/apollo-mcp-server/src/introspection/tools/introspect.rs | 2 +- crates/apollo-mcp-server/src/introspection/tools/search.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/apollo-mcp-server/src/introspection/tools/introspect.rs b/crates/apollo-mcp-server/src/introspection/tools/introspect.rs index 436c89e3..e45b7136 100644 --- a/crates/apollo-mcp-server/src/introspection/tools/introspect.rs +++ b/crates/apollo-mcp-server/src/introspection/tools/introspect.rs @@ -122,7 +122,7 @@ fn tool_description( minify: bool, ) -> String { if minify { - "Get GraphQL type information - T=type,I=input,E=enum,U=union,F=interface;s=String,i=Int,f=Float,b=Boolean,d=ID;!=required,[]=list,<>=implements;".to_string() + "Get GraphQL type information - T=type,I=input,E=enum,U=union,F=interface;s=String,i=Int,f=Float,b=Boolean,d=ID;@D=deprecated;!=required,[]=list,<>=implements;".to_string() } else { format!( "Get detailed information about types from the GraphQL schema.{}{}", diff --git a/crates/apollo-mcp-server/src/introspection/tools/search.rs b/crates/apollo-mcp-server/src/introspection/tools/search.rs index 3e146b63..e327f3f7 100644 --- a/crates/apollo-mcp-server/src/introspection/tools/search.rs +++ b/crates/apollo-mcp-server/src/introspection/tools/search.rs @@ -77,7 +77,7 @@ impl Search { format!( "Search a GraphQL schema{}", if minify { - " - T=type,I=input,E=enum,U=union,F=interface;s=String,i=Int,f=Float,b=Boolean,d=ID;!=required,[]=list,<>=implements" + " - T=type,I=input,E=enum,U=union,F=interface;s=String,i=Int,f=Float,b=Boolean,d=ID;@D=deprecated;!=required,[]=list,<>=implements" } else { "" } From 0f4072e3936886bdf11e783e0cd926d1873f5e08 Mon Sep 17 00:00:00 2001 From: Evan Silverman Date: Wed, 17 Sep 2025 10:25:20 -0400 Subject: [PATCH 3/9] normalize reason text --- crates/apollo-mcp-server/src/introspection/minify.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/apollo-mcp-server/src/introspection/minify.rs b/crates/apollo-mcp-server/src/introspection/minify.rs index c029e1b9..b7bf7ff8 100644 --- a/crates/apollo-mcp-server/src/introspection/minify.rs +++ b/crates/apollo-mcp-server/src/introspection/minify.rs @@ -83,7 +83,8 @@ fn minify_directives(directives: &apollo_compiler::ast::DirectiveList) -> String for directive in directives.iter() { if let Some(minified_name) = directives_to_minify.get(directive.name.as_str()) { if !directive.arguments.is_empty() { - // Since we're only handling @deprecated right now we can just add the reason and minify it + // Since we're only handling @deprecated right now we can just add the reason and minify it. + // We should handle this more generically in the future. let reason = directive .arguments .iter() @@ -91,7 +92,11 @@ fn minify_directives(directives: &apollo_compiler::ast::DirectiveList) -> String .and_then(|a| a.value.as_str()) .unwrap_or("No longer supported") .to_string(); - result.push_str(&format!("@{}(\"{}\")", minified_name, reason)); + result.push_str(&format!( + "@{}(\"{}\")", + minified_name, + normalize_description(&reason) + )); } else { result.push_str(&format!("@{}", minified_name)); } From 1775b7b7344414b20af706bd40d1de36110920be Mon Sep 17 00:00:00 2001 From: Evan Silverman Date: Wed, 17 Sep 2025 10:32:47 -0400 Subject: [PATCH 4/9] add snapshot tests for minification --- .../src/introspection/minify.rs | 24 +++++++ ...pection__minify__tests__minify_schema.snap | 64 +++++++++++++++++++ .../tools/testdata/schema.graphql | 1 + 3 files changed, 89 insertions(+) create mode 100644 crates/apollo-mcp-server/src/introspection/snapshots/apollo_mcp_server__introspection__minify__tests__minify_schema.snap diff --git a/crates/apollo-mcp-server/src/introspection/minify.rs b/crates/apollo-mcp-server/src/introspection/minify.rs index b7bf7ff8..d4026983 100644 --- a/crates/apollo-mcp-server/src/introspection/minify.rs +++ b/crates/apollo-mcp-server/src/introspection/minify.rs @@ -253,3 +253,27 @@ fn normalize_description(desc: &str) -> String { let re = WHITESPACE_PATTERN.get_or_init(|| Regex::new(r"\s+").expect("regex pattern compiles")); re.replace_all(desc, "").to_string() } + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_SCHEMA: &str = include_str!("tools/testdata/schema.graphql"); + + #[test] + fn test_minify_schema() { + let schema = apollo_compiler::schema::Schema::parse(TEST_SCHEMA, "schema.graphql") + .expect("Failed to parse schema") + .validate() + .expect("Failed to validate schema"); + + let minified = schema + .types + .iter() + .map(|(_, type_)| format!("{}: {}", type_.name().as_str(), type_.minify())) + .collect::>() + .join("\n"); + + insta::assert_snapshot!(minified); + } +} diff --git a/crates/apollo-mcp-server/src/introspection/snapshots/apollo_mcp_server__introspection__minify__tests__minify_schema.snap b/crates/apollo-mcp-server/src/introspection/snapshots/apollo_mcp_server__introspection__minify__tests__minify_schema.snap new file mode 100644 index 00000000..f9c1f6e3 --- /dev/null +++ b/crates/apollo-mcp-server/src/introspection/snapshots/apollo_mcp_server__introspection__minify__tests__minify_schema.snap @@ -0,0 +1,64 @@ +--- +source: crates/apollo-mcp-server/src/introspection/minify.rs +expression: minified +--- +__Schema: T:"AGraphQLSchemadefinesthecapabilitiesofaGraphQLserver.Itexposesallavailabletypesanddirectivesontheserver,aswellastheentrypointsforquery,mutation,andsubscriptionoperations."__Schema:description:s,"Alistofalltypessupportedbythisserver."types:[__Type],"Thetypethatqueryoperationswillberootedat."queryType:__Type!,"Ifthisserversupportsmutation,thetypethatmutationoperationswillberootedat."mutationType:__Type,"Ifthisserversupportsubscription,thetypethatsubscriptionoperationswillberootedat."subscriptionType:__Type,"Alistofalldirectivessupportedbythisserver."directives:[__Directive] +__Type: T:"ThefundamentalunitofanyGraphQLSchemaisthetype.TherearemanykindsoftypesinGraphQLasrepresentedbythe`__TypeKind`enum.Dependingonthekindofatype,certainfieldsdescribeinformationaboutthattype.Scalartypesprovidenoinformationbeyondaname,descriptionandoptional`specifiedByURL`,whileEnumtypesprovidetheirvalues.ObjectandInterfacetypesprovidethefieldstheydescribe.Abstracttypes,UnionandInterface,providetheObjecttypespossibleatruntime.ListandNonNulltypescomposeothertypes."__Type:kind:__TypeKind!,name:s,description:s,fields(includeDeprecated:b):[__Field],interfaces:[__Type],possibleTypes:[__Type],enumValues(includeDeprecated:b):[__EnumValue],inputFields(includeDeprecated:b):[__InputValue],ofType:__Type,specifiedByURL:s +__TypeKind: E:"Anenumdescribingwhatkindoftypeagiven`__Type`is."__TypeKind:SCALAR,OBJECT,INTERFACE,UNION,ENUM,INPUT_OBJECT,LIST,NON_NULL +__Field: T:"ObjectandInterfacetypesaredescribedbyalistofFields,eachofwhichhasaname,potentiallyalistofarguments,andareturntype."__Field:name:s!,description:s,args(includeDeprecated:b):[__InputValue],type:__Type!,isDeprecated:b!,deprecationReason:s +__InputValue: T:"ArgumentsprovidedtoFieldsorDirectivesandtheinputfieldsofanInputObjectarerepresentedasInputValueswhichdescribetheirtypeandoptionallyadefaultvalue."__InputValue:name:s!,description:s,type:__Type!,"AGraphQL-formattedstringrepresentingthedefaultvalueforthisinputvalue."defaultValue:s,isDeprecated:b!,deprecationReason:s +__EnumValue: T:"OnepossiblevalueforagivenEnum.Enumvaluesareuniquevalues,notaplaceholderforastringornumericvalue.HoweveranEnumvalueisreturnedinaJSONresponseasastring."__EnumValue:name:s!,description:s,isDeprecated:b!,deprecationReason:s +__Directive: T:"ADirectiveprovidesawaytodescribealternateruntimeexecutionandtypevalidationbehaviorinaGraphQLdocument.Insomecases,youneedtoprovideoptionstoalterGraphQL'sexecutionbehaviorinwaysfieldargumentswillnotsuffice,suchasconditionallyincludingorskippingafield.Directivesprovidethisbydescribingadditionalinformationtotheexecutor."__Directive:name:s!,description:s,locations:[__DirectiveLocation],args(includeDeprecated:b):[__InputValue],isRepeatable:b! +__DirectiveLocation: E:"ADirectivecanbeadjacenttomanypartsoftheGraphQLlanguage,a__DirectiveLocationdescribesonesuchpossibleadjacencies."__DirectiveLocation:QUERY,MUTATION,SUBSCRIPTION,FIELD,FRAGMENT_DEFINITION,FRAGMENT_SPREAD,INLINE_FRAGMENT,VARIABLE_DEFINITION,SCHEMA,SCALAR,OBJECT,FIELD_DEFINITION,ARGUMENT_DEFINITION,INTERFACE,UNION,ENUM,ENUM_VALUE,INPUT_OBJECT,INPUT_FIELD_DEFINITION +Int: i +Float: f +String: s +Boolean: b +ID: d +DateTime: DateTime +JSON: JSON +Upload: Upload +UserRole: E:UserRole:ADMIN,MODERATOR,USER,GUEST +ContentStatus: E:ContentStatus:DRAFT,PUBLISHED,ARCHIVED,DELETED +NotificationPriority: E:NotificationPriority:LOW,MEDIUM,HIGH,URGENT +MediaType: E:MediaType:IMAGE,VIDEO,AUDIO,DOCUMENT +Node: F:Node:id:d!,createdAt:DateTime!,updatedAt:DateTime! +Content: F:Content:id:d!,title:s!,status:ContentStatus!,author:User!,metadata:JSON +User: T:User:id:d!,createdAt:DateTime!,updatedAt:DateTime!,username:s!,email:s!,role:UserRole!,profile:UserProfile,posts:[Post],comments:[Comment],notifications:[Notification],preferences:UserPreferences! +UserProfile: T:UserProfile:firstName:s,lastName:s,bio:s,avatar:Media,socialLinks:[SocialLink],location:Location +Location: T:Location:country:s!,city:s,coordinates:Coordinates +Coordinates: T:Coordinates:latitude:f!,longitude:f! +SocialLink: T:SocialLink:platform:s!,url:s!,verified:b! +Post: T:Post:id:d!,createdAt:DateTime!,updatedAt:DateTime!,title:s!,content:s!,status:ContentStatus!,author:User!,metadata:JSON,comments:[Comment],media:[Media],tags:[Tag],analytics:PostAnalytics! +Comment: T:Comment:id:d!,createdAt:DateTime!,updatedAt:DateTime!,content:s!,author:User!,post:Post!,parentComment:Comment,replies:[Comment],reactions:[Reaction] +Media: T:Media:id:d!,type:MediaType!,url:s!,thumbnail:s,metadata:MediaMetadata!,uploader:User! +MediaMetadata: T:MediaMetadata:size:i!,format:s!,dimensions:Dimensions,duration:i +Dimensions: T:Dimensions:width:i!,height:i! +Tag: T:Tag:id:d!,name:s!,slug:s!,description:s,posts:[Post] +Reaction: T:Reaction:id:d!,type:s!,user:User!,comment:Comment!,createdAt:DateTime! +Notification: T:Notification:id:d!,type:s!,priority:NotificationPriority!,message:s!,recipient:User!,read:b!,createdAt:DateTime!,metadata:JSON +PostAnalytics: T:PostAnalytics:views:i!,likes:i!,shares:i!,comments:i!,engagement:f!,demographics:Demographics! +Demographics: T:Demographics:ageGroups:[AgeGroup],locations:[LocationStats],devices:[DeviceStats] +AgeGroup: T:AgeGroup:range:s!,percentage:f! +LocationStats: T:LocationStats:country:s!,count:i! +DeviceStats: T:DeviceStats:type:s!,count:i! +UserPreferences: T:UserPreferences:theme:s!,language:s!,notifications:NotificationPreferences!,privacy:PrivacySettings! +NotificationPreferences: T:NotificationPreferences:email:b!,push:b!,sms:b!,frequency:s! +PrivacySettings: T:PrivacySettings:profileVisibility:s!,showEmail:b!,showLocation:b! +CreateUserInput: I:CreateUserInput:username:s!,email:s!,password:s!,role:UserRole,profile:CreateUserProfileInput +CreateUserProfileInput: I:CreateUserProfileInput:firstName:s,lastName:s,bio:s,location:CreateLocationInput +CreateLocationInput: I:CreateLocationInput:country:s!,city:s,coordinates:CreateCoordinatesInput +CreateCoordinatesInput: I:CreateCoordinatesInput:latitude:f!,longitude:f! +CreatePostInput: I:CreatePostInput:title:s!,content:s!,status:ContentStatus,tags:[s],media:[Upload] +UpdatePostInput: I:UpdatePostInput:title:s,content:s,status:ContentStatus,tags:[s] +CreateCommentInput: I:CreateCommentInput:content:s!,postId:d!,parentCommentId:d +NotificationFilter: I:NotificationFilter:priority:NotificationPriority,read:b,type:s,startDate:DateTime,endDate:DateTime +Query: T:Query:node(id:d!):Node,user(id:d!):User,post(id:d!):Post,postsOld(filter:[d]):[Post]@D("Usepostsinstead"),posts(filter:PostFilter):[Post],comments(postId:d!):[Comment],notifications(filter:NotificationFilter):[Notification],search(query:s!):SearchResult! +Mutation: T:Mutation:createUser(input:CreateUserInput!):User!,createPost(input:CreatePostInput!):Post!,updatePost(id:d!,input:UpdatePostInput!):Post!,createComment(input:CreateCommentInput!):Comment!,deletePost(id:d!):b!,uploadMedia(file:Upload!):Media!,updateUserPreferences(id:d!,preferences:UserPreferencesInput!):UserPreferences! +Subscription: T:Subscription:postUpdated(id:d!):Post!,newComment(postId:d!):Comment!,notificationReceived(userId:d!):Notification! +SearchResult: U:SearchResult:User,Post,Comment,Tag +PostFilter: I:PostFilter:status:ContentStatus,authorId:d,tags:[s],dateRange:DateRangeInput +DateRangeInput: I:DateRangeInput:start:DateTime!,end:DateTime! +UserPreferencesInput: I:UserPreferencesInput:theme:s,language:s,notifications:NotificationPreferencesInput,privacy:PrivacySettingsInput +NotificationPreferencesInput: I:NotificationPreferencesInput:email:b,push:b,sms:b,frequency:s +PrivacySettingsInput: I:PrivacySettingsInput:profileVisibility:s,showEmail:b,showLocation:b diff --git a/crates/apollo-mcp-server/src/introspection/tools/testdata/schema.graphql b/crates/apollo-mcp-server/src/introspection/tools/testdata/schema.graphql index 5407ba1b..a70e2660 100644 --- a/crates/apollo-mcp-server/src/introspection/tools/testdata/schema.graphql +++ b/crates/apollo-mcp-server/src/introspection/tools/testdata/schema.graphql @@ -268,6 +268,7 @@ type Query { node(id: ID!): Node user(id: ID!): User post(id: ID!): Post + postsOld(filter: [ID!]) : [Post!]! @deprecated(reason: "Use posts instead") posts(filter: PostFilter): [Post!]! comments(postId: ID!): [Comment!]! notifications(filter: NotificationFilter): [Notification!]! From cf1cb3db9bfa1eaee013175d3886536a7e5497cf Mon Sep 17 00:00:00 2001 From: Evan Silverman Date: Wed, 17 Sep 2025 10:45:30 -0400 Subject: [PATCH 5/9] add changeset --- .changesets/fix_evan_minify_include_builtin_directives.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changesets/fix_evan_minify_include_builtin_directives.md diff --git a/.changesets/fix_evan_minify_include_builtin_directives.md b/.changesets/fix_evan_minify_include_builtin_directives.md new file mode 100644 index 00000000..d5e08bda --- /dev/null +++ b/.changesets/fix_evan_minify_include_builtin_directives.md @@ -0,0 +1,3 @@ +### Minify: Add support for deprecated directive - @esilverm PR #367 + +Includes any existing `@deprecated` directives in the schema in the minified output of builtin tools. Now operations generated via these tools should take into account deprecated fields when being generated. \ No newline at end of file From 22e96071e902932f5434efa4b8eebd8a77f86b08 Mon Sep 17 00:00:00 2001 From: Evan Silverman Date: Wed, 17 Sep 2025 10:56:15 -0400 Subject: [PATCH 6/9] update existing snapshots --- ...erver__introspection__tools__search__tests__search_tool.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/apollo-mcp-server/src/introspection/tools/snapshots/apollo_mcp_server__introspection__tools__search__tests__search_tool.snap b/crates/apollo-mcp-server/src/introspection/tools/snapshots/apollo_mcp_server__introspection__tools__search__tests__search_tool.snap index e62de8e1..997c8996 100644 --- a/crates/apollo-mcp-server/src/introspection/tools/snapshots/apollo_mcp_server__introspection__tools__search__tests__search_tool.snap +++ b/crates/apollo-mcp-server/src/introspection/tools/snapshots/apollo_mcp_server__introspection__tools__search__tests__search_tool.snap @@ -28,7 +28,7 @@ type Post implements Node & Content { type Query { user(id: ID!): User - post(id: ID!): Post + postsOld(filter: [ID!]): [Post!]! @deprecated(reason: "Use posts instead") posts(filter: PostFilter): [Post!]! } From f2ddeaded733f9cdf07349ec18c87e990b21acd6 Mon Sep 17 00:00:00 2001 From: Evan Silverman Date: Thu, 18 Sep 2025 12:02:44 -0400 Subject: [PATCH 7/9] move reason handling to if let so it is clear that we only handle the arguments if we have that present --- .../apollo-mcp-server/src/introspection/minify.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/crates/apollo-mcp-server/src/introspection/minify.rs b/crates/apollo-mcp-server/src/introspection/minify.rs index d4026983..6cc47a8a 100644 --- a/crates/apollo-mcp-server/src/introspection/minify.rs +++ b/crates/apollo-mcp-server/src/introspection/minify.rs @@ -82,20 +82,19 @@ fn minify_directives(directives: &apollo_compiler::ast::DirectiveList) -> String for directive in directives.iter() { if let Some(minified_name) = directives_to_minify.get(directive.name.as_str()) { - if !directive.arguments.is_empty() { - // Since we're only handling @deprecated right now we can just add the reason and minify it. - // We should handle this more generically in the future. - let reason = directive + // Since we're only handling @deprecated right now we can just add the reason and minify it. + // We should handle this more generically in the future. + if !directive.arguments.is_empty() + && let Some(reason) = directive .arguments .iter() .find(|a| a.name == "reason") .and_then(|a| a.value.as_str()) - .unwrap_or("No longer supported") - .to_string(); + { result.push_str(&format!( "@{}(\"{}\")", minified_name, - normalize_description(&reason) + normalize_description(reason) )); } else { result.push_str(&format!("@{}", minified_name)); From c45a51ceb42f5fc81e91fe5069568220addd4d15 Mon Sep 17 00:00:00 2001 From: Evan Silverman Date: Thu, 18 Sep 2025 12:02:53 -0400 Subject: [PATCH 8/9] update tests to show support for deprecation with no provided reason --- ...mcp_server__introspection__minify__tests__minify_schema.snap | 2 +- .../src/introspection/tools/testdata/schema.graphql | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/apollo-mcp-server/src/introspection/snapshots/apollo_mcp_server__introspection__minify__tests__minify_schema.snap b/crates/apollo-mcp-server/src/introspection/snapshots/apollo_mcp_server__introspection__minify__tests__minify_schema.snap index f9c1f6e3..439853a6 100644 --- a/crates/apollo-mcp-server/src/introspection/snapshots/apollo_mcp_server__introspection__minify__tests__minify_schema.snap +++ b/crates/apollo-mcp-server/src/introspection/snapshots/apollo_mcp_server__introspection__minify__tests__minify_schema.snap @@ -42,7 +42,7 @@ Demographics: T:Demographics:ageGroups:[AgeGroup],locations:[LocationStats],devi AgeGroup: T:AgeGroup:range:s!,percentage:f! LocationStats: T:LocationStats:country:s!,count:i! DeviceStats: T:DeviceStats:type:s!,count:i! -UserPreferences: T:UserPreferences:theme:s!,language:s!,notifications:NotificationPreferences!,privacy:PrivacySettings! +UserPreferences: T:UserPreferences:theme:s!,oldTheme:s@D,language:s!,notifications:NotificationPreferences!,privacy:PrivacySettings! NotificationPreferences: T:NotificationPreferences:email:b!,push:b!,sms:b!,frequency:s! PrivacySettings: T:PrivacySettings:profileVisibility:s!,showEmail:b!,showLocation:b! CreateUserInput: I:CreateUserInput:username:s!,email:s!,password:s!,role:UserRole,profile:CreateUserProfileInput diff --git a/crates/apollo-mcp-server/src/introspection/tools/testdata/schema.graphql b/crates/apollo-mcp-server/src/introspection/tools/testdata/schema.graphql index a70e2660..5c4bbc0d 100644 --- a/crates/apollo-mcp-server/src/introspection/tools/testdata/schema.graphql +++ b/crates/apollo-mcp-server/src/introspection/tools/testdata/schema.graphql @@ -191,6 +191,7 @@ type DeviceStats { type UserPreferences { theme: String! + oldTheme: String @deprecated language: String! notifications: NotificationPreferences! privacy: PrivacySettings! From 8d8338272923e9874e3bde37a85c67038912b250 Mon Sep 17 00:00:00 2001 From: Evan Silverman Date: Thu, 18 Sep 2025 12:04:14 -0400 Subject: [PATCH 9/9] update docs --- docs/source/define-tools.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/define-tools.mdx b/docs/source/define-tools.mdx index 2fd6c6cc..1272cc44 100644 --- a/docs/source/define-tools.mdx +++ b/docs/source/define-tools.mdx @@ -156,6 +156,7 @@ Both the `introspect` and `search` tools support minification of their results t - **Type prefixes**: `T=type`, `I=input`, `E=enum`, `U=union`, `F=interface` - **Scalar abbreviations**: `s=String`, `i=Int`, `f=Float`, `b=Boolean`, `d=ID` +- **Directive abbreviations**: `@D=deprecated` - **Type modifiers**: `!=required`, `[]=list`, `<>=implements` Example comparison: