Skip to content

Add support for Operation Collections #118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jun 11, 2025
Merged

Conversation

Jephuff
Copy link
Contributor

@Jephuff Jephuff commented Jun 4, 2025

Adds operation collection as an OperationSource. It's currently setup so that it will poll for changes every 30s and will only fetch the fully data for operations that change.

A few TODOs which I can either do in this PR or as fast follows

  • The first request should be the full operation collection data to avoid running the poll request and then fetching the data
  • Explorer supports jsonc, should we consider supporting that here as well?

@svc-apollo-docs
Copy link
Collaborator

svc-apollo-docs commented Jun 4, 2025

✅ Docs preview has no changes

The preview was not built because there were no changes.

Build ID: f4d9ccb27f26f05820cd16db

@Jephuff Jephuff force-pushed the jeffrey/poll-operation-collections branch from f422991 to f818ae0 Compare June 4, 2025 18:41
@Jephuff Jephuff marked this pull request as ready for review June 5, 2025 17:59
@Jephuff Jephuff requested a review from a team as a code owner June 5, 2025 17:59
@Jephuff Jephuff force-pushed the jeffrey/poll-operation-collections branch from 3972dbe to 9bad1a3 Compare June 5, 2025 18:24
}

impl CollectionSource {
pub fn into_stream(self) -> Pin<Box<dyn Stream<Item = CollectionEvent> + Send>> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This return type looks Greek to me 😂

operation.id.clone(),
CollectionData {
last_updated_at: updated_at,
raw_operation: None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we setting this to None? Shouldn't we set it to the updated operation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have the operation data yet at this point because we've only run the poll query.

But thinking about it, writing to this cache would only really help if we have overlapping requests and we probably should avoid that. So maybe we could make raw operations required and write to the cache once we get the full body back 🤔

Copy link
Contributor

@pubmodmatt pubmodmatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have more commets, but I'm suggesting some things that have a wide impact so getting these out first

Copy link
Contributor

@DaleSeo DaleSeo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @Jephuff for showering your PR with newbie comments! I was just using it as my Rust crash course. 🙈 Learned heaps, though, so thanks for putting up with my noise!

Now that I’ve wrapped my head around the code, I'll spend some time tomorrow testing it with a graph on Studio.

@DaleSeo DaleSeo self-requested a review June 5, 2025 20:11
@Jephuff
Copy link
Contributor Author

Jephuff commented Jun 5, 2025

Sorry @Jephuff for showering your PR with newbie comments! I was just using it as my Rust crash course. 🙈 Learned heaps, though, so thanks for putting up with my noise!

Now that I’ve wrapped my head around the code, I'll spend some time tomorrow testing it with a graph on Studio.

Love the comments! keep the noise coming, we will learn together :D hahaha

@DaleSeo
Copy link
Contributor

DaleSeo commented Jun 6, 2025

@Jephuff I had no luck getting this work locally 😞 The server crashes with Error in response: Not Authorized when I use ---collection option though APOLLO_KEY is set. Am I missing anything?

$ APOLLO_GRAPH_REF=🔑 APOLLO_KEY=🔑 cargo run -p apollo-mcp-server -- -i -u --http-address 127.0.0.1 --http-port 5000 --collection 4efe3d61-a3cf-4906-bd6d-6cdf6c18239b -l debug 
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.16s
     Running `target/debug/apollo-mcp-server -i -u --http-address 127.0.0.1 --http-port 5000 -l debug --collection 4efe3d61-a3cf-4906-bd6d-6cdf6c18239b`
2025-06-06T16:24:08.383024Z  INFO Apollo MCP Server v0.3.0 // (c) Apollo Graph, Inc. // Licensed as ELv2 (https://go.apollo.dev/elv2)
2025-06-06T16:24:08.386057Z DEBUG starting new connection: https://uplink.api.apollographql.com/    
2025-06-06T16:24:08.386799Z DEBUG starting new connection: https://graphql.api.apollographql.com/    
2025-06-06T16:24:08.485455Z DEBUG connecting to 34.30.93.119:443
2025-06-06T16:24:08.485628Z DEBUG connecting to 34.117.186.194:443
2025-06-06T16:24:08.534777Z DEBUG connected to 34.117.186.194:443
2025-06-06T16:24:08.558533Z DEBUG connected to 34.30.93.119:443
2025-06-06T16:24:08.809370Z DEBUG uplink response Response { url: "https://uplink.api.apollographql.com/", status: 200, headers: {"content-type": "application/json;charset=utf-8", "x-cloud-trace-context": "27bd18f8775451310924e30b1eb5b6c4", "date": "Fri, 06 Jun 2025 16:24:08 GMT", "server": "Google Frontend", "content-length": "4338", "via": "1.1 google", "alt-svc": "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"} }
2025-06-06T16:24:08.814416Z DEBUG pooling idle connection for ("https", uplink.api.apollographql.com)
2025-06-06T16:24:08.833726Z DEBUG Received schema: ✂️(The schema is too long to paste here)✂️

2025-06-06T16:24:08.868704Z DEBUG pooling idle connection for ("https", graphql.api.apollographql.com)
Error: Failed to create operation: Error loading collection: Error in response: Not Authorized

Caused by:
    Error loading collection: Error in response: Not Authorized

@Jephuff
Copy link
Contributor Author

Jephuff commented Jun 6, 2025

@DaleSeo How did you get the APOLLO_KEY? Is it a graph key?

@DaleSeo
Copy link
Contributor

DaleSeo commented Jun 6, 2025

@Jephuff Yes, it's a graph key from a graph on my free account. The log indicates that it fetched the schema without any issues using the key.

Shot 2025-06-06 at 19 08 46

@Jephuff
Copy link
Contributor Author

Jephuff commented Jun 6, 2025

It looks like you grabbed a personal collection id instead of a shared one. Personal ones would require a user token, but the shared ones would be able to be fetched by the graph token! :)

@DaleSeo
Copy link
Contributor

DaleSeo commented Jun 9, 2025

It looks like you grabbed a personal collection id instead of a shared one. Personal ones would require a user token, but the shared ones would be able to be fetched by the graph token! :)

Thanks @Jephuff for clarification. I never thought using a personal collection versus a shared collection could make a difference.

I tried using a user key instead, but it fails to fetch the schema from Uplink. 🙃
It seems like I can't use a personal collection unless we introduce a new environment variable. 😞

2025-06-09T13:02:20.456238Z ERROR uplink error, the request will not be retried: code=AUTHENTICATION_FAILED message=Only graph tokens can be used with uplink. User tokens are not supported at this time.
Error: No valid schema was supplied

@DaleSeo
Copy link
Contributor

DaleSeo commented Jun 9, 2025

I got it working using a shared collection and a graph key! 🎉

Shot 2025-06-09 at 09 21 37

@pubmodmatt
Copy link
Contributor

Also this definitely needs a changeset entry and doc updates.

@apollographql apollographql deleted a comment from apollo-librarian bot Jun 10, 2025
@apollographql apollographql deleted a comment from apollo-librarian bot Jun 10, 2025
@Jephuff Jephuff requested a review from a team as a code owner June 10, 2025 20:32
@apollo-librarian
Copy link

apollo-librarian bot commented Jun 10, 2025

✅ Docs preview ready

The preview is ready to be viewed. View the preview

File Changes

0 new, 3 changed, 0 removed
* (developer-tools)/apollo-mcp-server/(latest)/command-reference.mdx
* (developer-tools)/apollo-mcp-server/(latest)/guides/index.mdx
* graphos/routing/(latest)/security/jwt.mdx

Build ID: 64a588ec763284706af03b49

URL: https://www.apollographql.com/docs/deploy-preview/64a588ec763284706af03b49

@Jephuff Jephuff requested a review from pubmodmatt June 10, 2025 20:40
Copy link

@apollo-librarian apollo-librarian bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Style Review Summary

⚠️ This review and suggested changes are AI-generated. Please use common sense when accepting these suggestions, as they may not always be accurate or appropriate for your specific context.

Summary of changes:

The term 'ID' (without code font) is now used when referring generically to an identifier.

The pull request has 1 style issue. Please review the changes and make the necessary adjustments.

If you encounter any issues with this AI review, please reach out to Developer Experience Marketing for assistance.

@@ -109,6 +109,7 @@ apollo-mcp-server [OPTIONS] --directory <DIRECTORY>
| `-x, --explorer` | Expose a tool that returns the URL to open a GraphQL operation in Apollo Explorer (requires `APOLLO_KEY` and `APOLLO_GRAPH_REF`). |
| `-o, --operations [<OPERATIONS>...]` | Operation files to expose as MCP tools. [Learn more](/apollo-mcp-server/guides/#from-operation-files). |
| `--manifest <MANIFEST>` | The path to the persisted query manifest containing operations. |
| `--collection <COLLECTION_ID>` | The id of an operation collection to use as the source for operations |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Warning

Use 'ID' (no code font) when referring generically to something's identifier.

Suggested change
| `--collection <COLLECTION_ID>` | The id of an operation collection to use as the source for operations |
| <code>--collection <COLLECTION_ID></code> | The ID of an operation collection to use as the source for operations |

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore this for now 😄 working to resolve this issue with the prompt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance we can turn these off if they aren't quite ready? It's quite a lot and contradicting itself 😂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually agree with the ID capitalization.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah the ID I definitely agree with :)

Copy link

@apollo-librarian apollo-librarian bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Style Review (Review 1 of 1)

⚠️ This review and suggested changes are AI-generated. Please use common sense when accepting these suggestions, as they may not always be accurate or appropriate for your specific context.

Summary of changes:

Documentation changes include: updating references to 'ID' for generic identifiers, 'id' for GraphQL field names, and 'ID' for the GraphQL scalar type; and clarifying command option descriptions to explicitly state their function, aligning similar options (e.g., --collection) with consistent functional descriptions rather than cross-referencing.

The pull request has 2 style issues. Please review the changes and make the necessary adjustments.

If you encounter any issues with this AI review, please reach out to Developer Experience Marketing for assistance.

Copy link

@apollo-librarian apollo-librarian bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Style Review (Review 1 of 1)

⚠️ This review and suggested changes are AI-generated. Please use common sense when accepting these suggestions, as they may not always be accurate or appropriate for your specific context.

Summary of changes:

Documentation updates include standardizing 'ID' to uppercase for generic identifiers and clarifying command relationships, such as aliasing between '--mcp-collection' and '--collection'.

The pull request has 1 style issue. Please review the changes and make the necessary adjustments.

If you encounter any issues with this AI review, please reach out to Developer Experience Marketing for assistance.

@@ -0,0 +1,3 @@
### Add `--collection <COLLECTION_ID>` as another option for operation source

Use operation collections as the source of operations for your MCP server. The server will watch for changes and automatically update when you change your operation collection.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Use operation collections as the source of operations for your MCP server. The server will watch for changes and automatically update when you change your operation collection.
Use shared operation collections as the source of operations for your MCP server. The server will watch for changes and automatically update when you change your operation collection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to word this, you 100% can use a sandbox or personal collection as long as your APOLLO_KEY has access to it. If you do, it is incompatible with uplink but you can still pass in a schema.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a larger doc section, beyond just the options in the command reference, that explains this. This will be an immediate area of confusion. But that can be in a follow-on doc PR.

@@ -109,6 +109,7 @@ apollo-mcp-server [OPTIONS] --directory <DIRECTORY>
| `-x, --explorer` | Expose a tool that returns the URL to open a GraphQL operation in Apollo Explorer (requires `APOLLO_KEY` and `APOLLO_GRAPH_REF`). |
| `-o, --operations [<OPERATIONS>...]` | Operation files to expose as MCP tools. [Learn more](/apollo-mcp-server/guides/#from-operation-files). |
| `--manifest <MANIFEST>` | The path to the persisted query manifest containing operations. |
| `--collection <COLLECTION_ID>` | The id of an operation collection to use as the source for operations |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually agree with the ID capitalization.

Co-authored-by: apollo-librarian[bot] <212934294+apollo-librarian[bot]@users.noreply.github.com>
@Jephuff Jephuff requested a review from pubmodmatt June 11, 2025 17:59
Copy link
Contributor

@pubmodmatt pubmodmatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved, but identified a few things to follow up.

@@ -0,0 +1,3 @@
### Add `--collection <COLLECTION_ID>` as another option for operation source

Use operation collections as the source of operations for your MCP server. The server will watch for changes and automatically update when you change your operation collection.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a larger doc section, beyond just the options in the command reference, that explains this. This will be an immediate area of confusion. But that can be in a follow-on doc PR.

Comment on lines 4 to 8
... on OperationCollection {
operations {
lastUpdatedAt
id
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can work this out after this PR, but I think it's probably both. It may depend on how we integrate this with GraphOS generally - if it's a special MCP collection, maybe that collection simply can't be updated past the limit, for example.

}
}

async fn poll_operation_collection(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was discussed separately - it sounds like we have some ideas here, but I'd like to see some follow up after this merges.

@Jephuff Jephuff merged commit 5198357 into main Jun 11, 2025
7 checks passed
@DaleSeo DaleSeo mentioned this pull request Jun 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants