Skip to content

Moves mcp-json API back into mcp-core for simplified dependencies and support of osgi runtimes#762

Open
scottslewis wants to merge 5 commits intomodelcontextprotocol:mainfrom
scottslewis:issue_612_jackson3
Open

Moves mcp-json API back into mcp-core for simplified dependencies and support of osgi runtimes#762
scottslewis wants to merge 5 commits intomodelcontextprotocol:mainfrom
scottslewis:issue_612_jackson3

Conversation

@scottslewis
Copy link

mcp-core so that mcp-json API is no longer needed and mcp-core has fewer dependencies.

See issue #612 and previous pr #682

Motivation and Context

Simplifies dependency structure, and reenables ability to use OSGi runtimes #562

How Has This Been Tested?

Have tested in OSGi environments running OSGi application.

Breaking Changes

This eliminates the need to deploy mcp-json jar, meaning that users will only have to (minimally) deploy mcp-core and either mcp-json-jackson2 or mcp-json-jackson3

Types of changes

  • [X ] Bug fix (non-breaking change which fixes an issue)

Checklist

  • [X ] I have read the MCP Documentation
  • [X ] My code follows the repository's style guidelines
  • New and existing tests pass locally
  • [X ] I have added appropriate error handling
  • [X ] I have added or updated documentation as needed

Additional context

To deal with the testing dependencies issues as described here: #682 (comment)

it may be necessary to add further changes/refactoring/moving of the test code (in mcp-core specifically). I'm willing to do or contribute to this refactoring if needed, once consensus is achieved.

…n API back into

mcp-core so that mcp-json API is no longer needed and mcp-core has fewer
dependencies.
@scottslewis scottslewis changed the title Rebasing on main after #742 merged. Moves mcp-json API back into mcp-core for simplified dependency and support of osgi runtimes Moves mcp-json API back into mcp-core for simplified dependency and support of osgi runtimes Jan 29, 2026
scottslewis and others added 4 commits January 29, 2026 13:43
…Loader.java

Co-authored-by: Luca Chang <131398524+LucaButBoring@users.noreply.github.com>
and DefaultMcpJsonSchemaSupplier as they were originally committed
accidently.  Thanks to LucaButBoring for pointing out the error.
@filiphr
Copy link
Contributor

filiphr commented Jan 30, 2026

@scottslewis, I'm not familiar with OSGi that much, but I have some general questions about the PR.

  • Why not delete mcp-json in this PR as well?
  • What is the difference between the mechanism that was being used before in the McpJsonInternal vs the one in this PR with the McpJsonDefaults? Of course taking into consideration the fact the move into mcp-core

@scottslewis
Copy link
Author

scottslewis commented Jan 30, 2026

@scottslewis, I'm not familiar with OSGi that much, but I have some general questions about the PR.

  • Why not delete mcp-json in this PR as well?

I could have...but chose to leave it so that the pr was not as large. If doing it in one step is preferable then that can be done.

  • What is the difference between the mechanism that was being used before in the McpJsonInternal vs the one in this PR with the McpJsonDefaults? Of course taking into consideration the fact the move into mcp-core

The impl of McpJsonDefaults is key to working (for json defaults) in non osgi and osgi environments. In non osgi environments, the serviceloader is used to find and load jackson2 or jackson3 impl for defaults as done previously.

In osgi, the serviceloader does not work the same...because of classloader-per-bundle as per osgi issue #562. In osgi, mcpjsondefaults is created and configured on start by the osgi sevice registry using scr metadata in manifests.

For clarity here is the McpJsonDefaults scr metadata

@scottslewis scottslewis changed the title Moves mcp-json API back into mcp-core for simplified dependency and support of osgi runtimes Moves mcp-json API back into mcp-core for simplified dependencies and support of osgi runtimes Jan 30, 2026
@filiphr
Copy link
Contributor

filiphr commented Jan 30, 2026

Thanks for the explanation @scottslewis, always good to learn a bit more about it.

I could have...but chose to leave it so that the pr was not as large. If doing it in one step is preferable then that can be done.

I think the PR would actually be smaller then, since the classes that are removed, they'll show up as modified moved in git with no changes.

@scottslewis
Copy link
Author

Thanks for the explanation @scottslewis, always good to learn a bit more about it.

I could have...but chose to leave it so that the pr was not as large. If doing it in one step is preferable then that can be done.

I think the PR would actually be smaller then, since the classes that are removed, they'll show up as modified moved in git with no changes.

Ok, honestly I don't care that much. Let's get the code and build/test/dependency changes reviewed/complete/consensus, etc...without breaking the build and test/CI if possible...and I'll delete or someone else can...whatever the choice is fine by me.

Copy link
Contributor

@Kehrlann Kehrlann left a comment

Choose a reason for hiding this comment

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

  • I agree with @filiphr , remove mcp-json
  • Please run ./mvnw spring-javaformat:apply
  • We need test passing before we can merge this

mcpMapperServiceLoader.unsetSupplier(supplier);
}

public synchronized static McpJsonMapper getDefaultMcpJsonMapper() {
Copy link
Contributor

Choose a reason for hiding this comment

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

[issue] There are two separate synchronized methods, each using constructor side-effects. My understanding is that the synchronized is to avoid calling the constructor twice. If that's the case, in the current state, calling both methods at the same time triggers a race condition.

@@ -0,0 +1,50 @@
package io.modelcontextprotocol.json;
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing license header

import io.modelcontextprotocol.json.schema.JsonSchemaValidatorSupplier;
import io.modelcontextprotocol.util.McpServiceLoader;

public class McpJsonDefaults {
Copy link
Contributor

Choose a reason for hiding this comment

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

The patterns used here are uncommon in non-OSGi codebases. Please add a note in the javadoc mentioning OSGi compatibility.

@@ -0,0 +1,50 @@
package io.modelcontextprotocol.util;
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing license header.

import java.util.ServiceLoader;
import java.util.function.Supplier;

public class McpServiceLoader<S extends Supplier<R>, R> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as McpJsonDefaults, mention OSGi here.

// Use serviceloader
Optional<?> sl = serviceLoad(this.supplierType);
if (sl.isEmpty()) {
throw new ServiceConfigurationError("No %s available for creating McpJsonMapper".format(this.supplierType.getSimpleName()));
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you mean to use "...".formatted(...), or String.format("...", ...) ?

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.

4 participants