Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changesets/maint_nc_rust_toolchain_pin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### ci: Pin stable rust version ([Issue #287](https://github.com/apollographql/apollo-mcp-server/issues/287))

Pins the stable version of Rust to the current latest version to ensure backwards compatibility with future versions.
27 changes: 27 additions & 0 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
@@ -1,22 +1,49 @@
{
// Allow for intellisense in editors
$schema: "https://docs.renovatebot.com/renovate-schema.json",

// List of rules to apply
extends: [
// Recommended best practices from renovate itself
// See: https://docs.renovatebot.com/upgrade-best-practices/#whats-in-the-configbest-practices-preset
"config:best-practices",

// Apply our own internal best practices
// See: https://github.com/apollographql/apollo-mcp-server/commits/main/.github/renovate.json5
"github>apollographql/renovate-config-apollo-open-source:default.json5",

// Update to the latest rust stable version as it releases.
// See: https://github.com/Turbo87/renovate-config/blob/master/rust/updateToolchain.json
"github>Turbo87/renovate-config//rust/updateToolchain",
],

// Globally disable all automatic update PRs from renovate
packageRules: [
{
enabled: false,
matchPackageNames: ["*"],
},
],

// Automating Nix upgrades is currently in beta and opt-in only.
// https://docs.renovatebot.com/modules/manager/nix/
nix: {
enabled: true,
},

// Globally enable vulnerability alerts
//
// Note: This needs extra configuration at the repository level, which is described in the link
// below.
//
// See: https://docs.renovatebot.com/configuration-options/#vulnerabilityalerts
vulnerabilityAlerts: {
enabled: true,
},

// Disable automatically updating lock files to latest versions once a week.
//
// See: https://docs.renovatebot.com/configuration-options/#lockfilemaintenance
lockFileMaintenance: {
enabled: false,
},
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ members = [

[workspace.package]
authors = ["Apollo <[email protected]>"]
edition = "2024"
license-file = "LICENSE"
repository = "https://github.com/apollographql/apollo-mcp-server"
rust-version = "1.89.0"
version = "0.7.5"

[workspace.dependencies]
Expand Down
10 changes: 6 additions & 4 deletions crates/apollo-mcp-registry/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
[package]
name = "apollo-mcp-registry"
version.workspace = true
edition = "2024"
authors.workspace = true
license-file = "../LICENSE"
repository = "https://github.com/apollographql/apollo-mcp-server"
edition.workspace = true
license-file.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

description = "Registry providing schema and operations to the MCP Server"

[dependencies]
Expand Down
11 changes: 5 additions & 6 deletions crates/apollo-mcp-registry/src/uplink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,11 @@ where
.send()
.await
.inspect_err(|e| {
if let Some(hyper_err) = e.source() {
if let Some(os_err) = hyper_err.source() {
if os_err.to_string().contains("tcp connect error: Cannot assign requested address (os error 99)") {
tracing::warn!("If your MCP server is executing within a kubernetes pod, this failure may be caused by istio-proxy injection. See https://github.com/apollographql/router/issues/3533 for more details about how to solve this");
}
}
if let Some(hyper_err) = e.source() &&
let Some(os_err) = hyper_err.source() &&
os_err.to_string().contains("tcp connect error: Cannot assign requested address (os error 99)")
{
tracing::warn!("If your MCP server is executing within a kubernetes pod, this failure may be caused by istio-proxy injection. See https://github.com/apollographql/router/issues/3533 for more details about how to solve this");
}
})?;
tracing::debug!("uplink response {:?}", res);
Expand Down
6 changes: 0 additions & 6 deletions crates/apollo-mcp-registry/src/uplink/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,6 @@ impl SchemaSource {
}
}

#[derive(thiserror::Error, Debug)]
enum FetcherError {
#[error("failed to build http client")]
InitializationError(#[from] reqwest::Error),
}

// Encapsulates fetching the schema from the first viable url.
// It will try each url in order until it finds one that works.
#[allow(clippy::unwrap_used)] // TODO - existing unwrap from router code
Expand Down
9 changes: 6 additions & 3 deletions crates/apollo-mcp-server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
[package]
name = "apollo-mcp-server"
version.workspace = true
authors.workspace = true
edition = "2024"
license-file = "../LICENSE"
edition.workspace = true
license-file.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

default-run = "apollo-mcp-server"

[dependencies]
Expand Down
28 changes: 13 additions & 15 deletions crates/apollo-mcp-server/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,12 +490,11 @@ pub fn variable_description_overrides(
let comment = last_offset
.map(|start_offset| &source_text[start_offset..source_span.offset()]);

if let Some(description) = comment.filter(|d| !d.is_empty() && d.contains('#')) {
if let Some(description) =
if let Some(description) = comment.filter(|d| !d.is_empty() && d.contains('#'))
&& let Some(description) =
extract_and_format_comments(Some(description.to_string()))
{
argument_overrides_map.insert(v.name.to_string(), description);
}
{
argument_overrides_map.insert(v.name.to_string(), description);
}

last_offset = Some(source_span.end_offset());
Expand Down Expand Up @@ -731,16 +730,15 @@ impl Operation {
}

fn ensure_properties_exists(json_object: &mut Value) {
if let Some(obj_type) = json_object.get("type") {
if obj_type == "object" {
if let Some(obj_map) = json_object.as_object_mut() {
let props = obj_map
.entry("properties")
.or_insert_with(|| Value::Object(serde_json::Map::new()));
if !props.is_object() {
*props = Value::Object(serde_json::Map::new());
}
}
if let Some(obj_type) = json_object.get("type")
&& obj_type == "object"
&& let Some(obj_map) = json_object.as_object_mut()
{
let props = obj_map
.entry("properties")
.or_insert_with(|| Value::Object(serde_json::Map::new()));
if !props.is_object() {
*props = Value::Object(serde_json::Map::new());
}
}
}
Expand Down
19 changes: 9 additions & 10 deletions crates/apollo-mcp-server/src/schema_tree_shake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,16 +532,15 @@ fn retain_argument_descriptions(
) {
let operation_argument_name = operation_arguments.get(arg.name.as_str());

if let Some(op_arg_name) = operation_argument_name {
if let Some(description) = arg.description.as_deref() {
if !description.trim().is_empty() {
let descriptions = tree_shaker
.arguments_descriptions
.entry(op_arg_name.to_string())
.or_default();
descriptions.push(description.trim().to_string())
}
}
if let Some(op_arg_name) = operation_argument_name
&& let Some(description) = arg.description.as_deref()
&& !description.trim().is_empty()
{
let descriptions = tree_shaker
.arguments_descriptions
.entry(op_arg_name.to_string())
.or_default();
descriptions.push(description.trim().to_string())
}
}

Expand Down
8 changes: 5 additions & 3 deletions crates/apollo-schema-index/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
[package]
name = "apollo-schema-index"
edition = "2024"
authors.workspace = true
edition.workspace = true
license-file.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true
license-file = "../LICENSE"
repository = "https://github.com/apollographql/apollo-mcp-server"

description = "GraphQL schema indexing"

[dependencies]
Expand Down
106 changes: 52 additions & 54 deletions crates/apollo-schema-index/src/traverse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,67 +53,65 @@ impl SchemaExt for Schema {
);

let cloned = current_path.clone();
if let Some(extended_type) = self.types.get(named_type) {
if !extended_type.is_built_in() {
if traverse_children {
match extended_type {
ExtendedType::Object(obj) => {
stack.extend(obj.fields.values().map(|field| {
let field_type = field.ty.inner_named_type();
let field_args = field
.arguments
.iter()
.map(|arg| arg.ty.inner_named_type().clone())
.collect::<Vec<_>>();
(
field_type,
current_path.clone().add_child(
Some(field.name.clone()),
field_args,
field_type.clone(),
),
)
}));
}
ExtendedType::Interface(interface) => {
stack.extend(interface.fields.values().map(|field| {
let field_type = field.ty.inner_named_type();
let field_args = field
.arguments
.iter()
.map(|arg| arg.ty.inner_named_type().clone())
.collect::<Vec<_>>();
if let Some(extended_type) = self.types.get(named_type)
&& !extended_type.is_built_in()
{
if traverse_children {
match extended_type {
ExtendedType::Object(obj) => {
stack.extend(obj.fields.values().map(|field| {
let field_type = field.ty.inner_named_type();
let field_args = field
.arguments
.iter()
.map(|arg| arg.ty.inner_named_type().clone())
.collect::<Vec<_>>();
(
field_type,
current_path.clone().add_child(
Some(field.name.clone()),
field_args,
field_type.clone(),
),
)
}));
}
ExtendedType::Interface(interface) => {
stack.extend(interface.fields.values().map(|field| {
let field_type = field.ty.inner_named_type();
let field_args = field
.arguments
.iter()
.map(|arg| arg.ty.inner_named_type().clone())
.collect::<Vec<_>>();
(
field_type,
current_path.clone().add_child(
Some(field.name.clone()),
field_args,
field_type.clone(),
),
)
}));
}
ExtendedType::Union(union) => {
stack.extend(union.members.iter().map(|member| &member.name).map(
|next_type| {
(
field_type,
next_type,
current_path.clone().add_child(
Some(field.name.clone()),
field_args,
field_type.clone(),
None,
vec![],
next_type.clone(),
),
)
}));
}
ExtendedType::Union(union) => {
stack.extend(
union.members.iter().map(|member| &member.name).map(
|next_type| {
(
next_type,
current_path.clone().add_child(
None,
vec![],
next_type.clone(),
),
)
},
),
);
}
_ => {}
},
));
}
_ => {}
}
return Some((extended_type, cloned));
}
return Some((extended_type, cloned));
}
}
None
Expand Down
24 changes: 12 additions & 12 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[toolchain]
channel = "stable"
channel = "1.89.0"
profile = "default"
components = ["rust-analyzer", "rust-src"]