-
Notifications
You must be signed in to change notification settings - Fork 15
Add Prompts support to the MCP Server #825
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
Conversation
|
||
var prompt = prompts.get(promptName); | ||
|
||
if (prompt == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we respond with PromptMessage too ? Like we do in the file PromptProcessor.java?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need model list here.
You should be able to pull this off the schema as long as these traits are retained at runtime. This controlled by runtimeTraits
property, example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for sharing that example it makes sense that we can use the schema
. I will try that approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we make this a default runtime trait?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a valid point. Making it a default will save confusion at least for customers.
mcp/mcp-server/src/main/java/software/amazon/smithy/java/mcp/server/PromptLoader.java
Outdated
Show resolved
Hide resolved
mcp/mcp-server/src/main/java/software/amazon/smithy/java/mcp/server/McpServerBuilder.java
Outdated
Show resolved
Hide resolved
mcp/mcp-server/src/main/java/software/amazon/smithy/java/mcp/server/PromptProcessor.java
Show resolved
Hide resolved
* @return List of PromptArgument objects representing the structure members | ||
*/ | ||
public static List<PromptArgument> convertArgumentShapeToPromptArgument(Model model, ShapeId argumentShapeId) { | ||
StructureShape argument = model.expectShape(argumentShapeId, StructureShape.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to get this behavior using the Service
class? I looked at the TypeRegistry
and Schema
but could not find a pattern on how to use it. Maybe that's me being unfamiliar with access patterns of Smithy java.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You will not have access to the StructureShape, but in this method all you are doing is accessing members and traits. Both can be done from the Schema class, using Schema#getMembers
and Schema#getTrait
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep I can try that out. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to extract arguments using only the Schema and TypeRegistry from the Service interface, I hit some blockers:
Schema is too limited
It only knows about the main service shape and its direct pieces. It doesn't include operations or resources (where our @prompts traits actually live) a valid use-case. So we can't even find the prompts, let alone process them
TypeRegistry doesn't help. It only stores error types, nothing else. I tried to look up argument shapes, but they're not there
The main blocker is ShapeId references. Prompts have an arguments field that points to a structure (like SearchArguments). To process this, we need to find that structure in the model and read its fields Schema and TypeRegistry just don't have this information
What We're Doing Instead
We're parsing prompts in ProxyService
because it has access to the full Smithy model. The prompts will behave as an operation with a synthetic trait on it. We will filter those in the McpServer from tools, and also serve them as prompts when needed. On a prompts/get
call, we will just apply the arguments passed in by the client to the operation and return the template string. This is suggested by @rhernandez35 so that it is easier to pass the information by only passing the Service, and the ProxyService already has model information so we will be able to parse the information as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It only knows about the main service shape and its direct pieces. It doesn't include operations or resources (where our @prompts traits actually live) a valid use-case. So we can't even find the prompts, let alone process them
This isn't accurate. We generate Schema for both operations as well as resources.
The main blocker is ShapeId references. Prompts have an arguments field that points to a structure (like SearchArguments). To process this, we need to find that structure in the model and read its fields Schema and TypeRegistry just don't have this information
Should be fixed by #827
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't accurate. We generate Schema for both operations as well as resources.
Hmm, interesting from my debugging,maybe again this is my understanding and missing context. I was only able to the see the information related to the service. In my case, what would the PromptLoader method look like in terms of arguments it takes instead of the model we have currently?
Should be fixed by #827
Nice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're parsing prompts in ProxyService because it has access to the full Smithy model. The prompts will behave as an operation with a synthetic trait on it. We will filter those in the McpServer from tools, and also serve them as prompts when needed. On a prompts/get call, we will just apply the arguments passed in by the client to the operation and return the template string. This is suggested by @rhernandez35 so that it is easier to pass the information by only passing the Service, and the ProxyService already has model information so we will be able to parse the information as well.
Do you think this will be a good approach? I discussed with Richard and it seemed only fair for now.
In future, we should plan to move artifact generation for the tools and prompts such that the Smithy build system provides that data. The MCP Server can just become consumer using maybe a new McpService class that can take in Mcp specific things.
mcp/mcp-server/src/main/java/software/amazon/smithy/java/mcp/server/PromptLoader.java
Show resolved
Hide resolved
0e49455
to
3e97b6b
Compare
} | ||
|
||
/** | ||
* Applies template arguments to a template string with maximum efficiency. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"with maximum efficiency" doesn't need to be documented
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack. Removed in local. Will send a new commit for various nit fixes.
.build()) | ||
.serverInfo(ServerInfo.builder() | ||
.name(name) | ||
.version("1.0.0") | ||
.build()) | ||
.build()); | ||
case "prompts/list" -> writeResponse(req.getId(), | ||
ListPromptsResult.builder().prompts(prompts.values().stream().toList()).build()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to prevent the prompt templates from being serialized in this response. We only want the name, title, description, and arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I can update the response shape.
3e97b6b
to
d82e620
Compare
49d5fc8
to
aae765c
Compare
return getServerJavaClassSymbol(serviceShape); | ||
} | ||
|
||
private Symbol getServerJavaClassSymbol() { | ||
private Symbol getServerJavaClassSymbol(ServiceShape serviceShape) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't required. I think you messed something in the rebase.
@@ -22,6 +23,7 @@ public final class McpServerBuilder { | |||
OutputStream os; | |||
List<Service> serviceList = new ArrayList<>(); | |||
List<McpServerProxy> proxyList = new ArrayList<>(); | |||
List<Model> modelList = new ArrayList<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh yes. 🤦🏽♂️
...egen/src/main/java/software/amazon/smithy/java/codegen/server/ServiceJavaSymbolProvider.java
Outdated
Show resolved
Hide resolved
...egen/src/main/java/software/amazon/smithy/java/codegen/server/ServiceJavaSymbolProvider.java
Outdated
Show resolved
Hide resolved
mcp/mcp-server/src/main/java/software/amazon/smithy/java/mcp/server/McpServerBuilder.java
Outdated
Show resolved
Hide resolved
mcp/mcp-server/src/main/java/software/amazon/smithy/java/mcp/server/McpServerBuilder.java
Outdated
Show resolved
Hide resolved
mcp/mcp-server/src/test/java/software/amazon/smithy/java/mcp/server/PromptProcessorTest.java
Show resolved
Hide resolved
212067c
to
f42538d
Compare
NOTE: The main goal with the PR is to get feedback and discuss around ways to ingest the model / prompts appropriately.
This adds prompt support to the MCP server, letting LLMs get helpful context directly from Smithy models.
What's New
Core Features:
• Define prompts in Smithy using @prompts trait as defined in #829
• MCP server automatically exposes them via
prompts/list
andprompts/get
• Template support with
{{placeholder}}
syntax for dynamic content.Key Components:
•
PromptLoader
- discovers prompts from Smithy models•
PromptProcessor
- handles template substitution and validationTesting
This is what
/prompts
in Q CLI which correctly demonstrates the data from the prompts trait. Will add more calling examples later.User experience for
prompts/get
or@prompts
invocation in Q CLI.