Skip to content

Conversation

@yanand0909
Copy link
Contributor

@yanand0909 yanand0909 commented Dec 1, 2025

Linked issue: #334

Purpose of change

  • This PR adds StreamableHttp transport based support for MCP Servers which includes MCPTools and MCPPrompts.
  • This PR also updates Prompt structure to be in line with python Prompt, LocalPrompt and MCPPrompt Structure.
  • MCP SDK is compiled in Java 17 so to support it we need to update the project java version to 17 as well.

Tests

Added Unit tests for it

API

Yes, Prompt

Documentation

  • doc-needed
  • doc-not-needed

@github-actions github-actions bot added priority/major Default priority of the PR or issue. fixVersion/0.2.0 The feature or bug should be implemented/fixed in the 0.2.0 version. doc-label-missing The Bot applies this label either because none or multiple labels were provided. labels Dec 1, 2025
@github-actions
Copy link

github-actions bot commented Dec 1, 2025

@yanand0909 Please add the following content to your PR description and select a checkbox:

- [ ] `doc-needed` 
- [ ] `doc-not-needed` <!-- Your PR changes do not impact docs -->

@github-actions github-actions bot added doc-needed Your PR changes impact docs. and removed doc-label-missing The Bot applies this label either because none or multiple labels were provided. labels Dec 1, 2025
@yanand0909 yanand0909 force-pushed the add_java_mcp_recource branch from 61dbe19 to 81930d6 Compare December 1, 2025 10:44
@wenjin272 wenjin272 self-requested a review December 10, 2025 08:04
@wenjin272
Copy link
Collaborator

Hi, @yanand0909, thanks for your contribution, I will find time to review this week.

@wenjin272
Copy link
Collaborator

wenjin272 commented Dec 11, 2025

Hi, @yanand0909, in #380, we support run ut & it & e2e on java 17. After it merged, I think we can verify the test cases about MCP in CI. For java 11, you can skip the related tests by add annotation @DisabledOnJre(JRE.JAVA_11).

But this can't resolve the compile problem in java 11, due to the MCP dependency require java version higher than 17. As we discussed in the last community sync, since the python-side features do not depend on a higher JDK version and many companies in China are still using JDK 11, we hope to support at least JDK 11, JDK 17, and JDK 21 simultaneously.

A preliminary idea is that we could use a Maven profile to control include the MCP SDK and compile MCP api only in java 17, like

<profiles>
    <profile>
        <id>java17</id>
        <activation>
            <jdk>[17,)</jdk>
        </activation>
        <dependencies>
            <dependency>
                <groupId>io.modelcontextprotocol.sdk</groupId>
                <artifactId>mcp</artifactId>
                <version>0.16.0</version>
            </dependency>
        </dependencies>
    </profile>

    <profile>
        <id>java11</id>
        <activation>
            <jdk>[11,)</jdk>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <excludes>
                            <exclude>org/apache/flink/agents/api/mcp/*.java</exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

I haven't confirmed whether this approach works, but you can use it as a reference. However, I believe it won't affect the MCP implementation itself, so I'll start the review as soon as I free up some time.

@yanand0909
Copy link
Contributor Author

Hi, @yanand0909, in #380, we support run ut & it & e2e on java 17. After it merged, I think we can verify the test cases about MCP in CI. For java 11, you can skip the related tests by add annotation @DisabledOnJre(JRE.JAVA_11).

But this can't resolve the compile problem in java 11, due to the MCP dependency require java version higher than 17. As we discussed in the last community sync, since the python-side features do not depend on a higher JDK version and many companies in China are still using JDK 11, we hope to support at least JDK 11, JDK 17, and JDK 21 simultaneously.

A preliminary idea is that we could use a Maven profile to control include the MCP SDK and compile MCP api only in java 17, like

<profiles>
    <profile>
        <id>java17</id>
        <activation>
            <jdk>[17,)</jdk>
        </activation>
        <dependencies>
            <dependency>
                <groupId>io.modelcontextprotocol.sdk</groupId>
                <artifactId>mcp</artifactId>
                <version>0.16.0</version>
            </dependency>
        </dependencies>
    </profile>

    <profile>
        <id>java11</id>
        <activation>
            <jdk>[11,)</jdk>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <excludes>
                            <exclude>org/apache/flink/agents/api/mcp/*.java</exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

I haven't confirmed whether this approach works, but you can use it as a reference. However, I believe it won't affect the MCP implementation itself, so I'll start the review as soon as I free up some time.

Think for updating the CI pipeline @wenjin272, and the above approach to support all 3 version looks intuitive if it works

@yanand0909 yanand0909 force-pushed the add_java_mcp_recource branch 9 times, most recently from 1955a5c to 5b7451c Compare December 12, 2025 21:44
@yanand0909
Copy link
Contributor Author

I have updated the code to support both Java 17 and Java 11 profiles, we can also add Java 21 profiles later when needed. @wenjin272 @xintongsong can you take a look

Copy link
Collaborator

@wenjin272 wenjin272 left a comment

Choose a reason for hiding this comment

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

Thanks for your work, @yanand0909. Overall looks good to me, just some minor comments.

Copy link
Contributor

@Sxnan Sxnan left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! I just left some comments regarding the multi-JDK version support

@Sxnan
Copy link
Contributor

Sxnan commented Dec 17, 2025

We also need to determine how to support multiple JDKs for flink-agents-dist. The Python library may need to choose the jar according to the JDK version. We can do this in a separate PR to avoid complicating this PR anymore.

@wenjin272 WDYT

@yanand0909 yanand0909 force-pushed the add_java_mcp_recource branch from 8b4c00e to 32064c8 Compare December 17, 2025 21:24
@yanand0909 yanand0909 force-pushed the add_java_mcp_recource branch from 32064c8 to dc96dbc Compare December 18, 2025 05:39
@wenjin272
Copy link
Collaborator

Thanks for addressing my comments, LGTM.

Copy link
Contributor

@Sxnan Sxnan left a comment

Choose a reason for hiding this comment

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

Thanks for the update! LGTM. @xintongsong Can you take a look at this PR?

Copy link
Contributor

@xintongsong xintongsong left a comment

Choose a reason for hiding this comment

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

@yanand0909,
Thanks for working on this feature. The overall implementation looks good to me. I have a few more comments, mostly related to hiding internal implementation from users and organizing ci pipelines. Should not require significant code changes. PTAL.

*
* <p>Reference: <a href="https://modelcontextprotocol.io/sdk/java/mcp-client">MCP Java Client</a>
*/
public class MCPServer extends SerializableResource {
Copy link
Contributor

Choose a reason for hiding this comment

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

Currently, the entire implementation of MCPServer and related tools/prompts are in the api module, which is not ideal. We should keep the api module as lightweight as possible, including only a minimum set of interfaces that users need to depend on when writing their agent codes. I think we can move the entire api/mcp directory into the the integration module. The only think users need to see in the api module is the annotation.

Copy link
Contributor

Choose a reason for hiding this comment

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

@wenjin272, we should also fix this for the python api.

* );
* }</pre>
*/
public class LocalPrompt extends Prompt {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd suggest to make this a private class in Prompt.java. Users should not be aware of the different implementations of Prompt. The should always use Prompt.fromText/Messages() to create a prompt, rather than new LocalPrompt().

Copy link
Contributor

Choose a reason for hiding this comment

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

And we should also use Prompt.fromText/Messages() in the doc sample codes, examples and tests.

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 can move localPrompt to be a subclass of prompt but I cannot make it private as PythonPrompt extends it

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. Can we move LocalPrompt to the plan module, and use reflection to create it in Prompt.fromText/Messages? My point is to hide it from the user-facing APIs if possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we move LocalPrompt to Plan module that will create circular dependency as we would still need LocalPrompt on the classpath at runtime for the reflection call, we can either move this to integration module but that does not seems appropriate looking at the design or we can keep it in API module under some internal package and discourage users to use it directly.

WDYT @xintongsong ?

Copy link
Contributor

Choose a reason for hiding this comment

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

If we move LocalPrompt to Plan module that will create circular dependency as we would still need LocalPrompt on the classpath at runtime for the reflection call

That should be fine. We are using the same approach for AgentsExecutionEnvironment and it works fine. User programs only need to depend on the api module, with provided scope. They don't need to explicitly depend on the plan / runtime modules. Users must first install flink-agents to their flink clusters in order to execute the programs, which is specified in our installation documentations. So we can just assume the plan / runtime modules exist in the classpath in runtime.

# Add Python venv to PATH so Java tests can find MCP dependencies
export PATH="${{ github.workspace }}/python/.venv/bin:$PATH"
export PYTHONPATH="${{ github.workspace }}/python/.venv/lib/python3.11/site-packages:$PYTHONPATH"
tools/ut.sh -j
Copy link
Contributor

Choose a reason for hiding this comment

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

IIUC, we need this to start an external mcp server, so that we can access from the test cases? If that is the case, I'd suggest to move the test cases that depends on external mcp server to the it-java pipeline. In theory, any test case that interacts with an external system should be considered as integration test or e2e test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is for AgentPlanDeclareMCPServerTest to test whether MCP Tools and Prompts from MCP Server is properly discoverable, we need a running MCP server for this test. Do you think we should move this test to integration test?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I think we can move that test to integration test.

@yanand0909 yanand0909 force-pushed the add_java_mcp_recource branch 2 times, most recently from 79295d1 to 173856c Compare December 22, 2025 23:16
@yanand0909 yanand0909 force-pushed the add_java_mcp_recource branch from 173856c to 4e1897b Compare December 22, 2025 23:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc-needed Your PR changes impact docs. fixVersion/0.2.0 The feature or bug should be implemented/fixed in the 0.2.0 version. priority/major Default priority of the PR or issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants