Repository navigation
mcp no longer works in OSGi #562
Description
Bug description
In version 0.12, there was a single "mcp" jar which happens to be a valid OSGi bundle having a valid OSGi manifest. Its dependencies all happen to be OSGi bundles as well. So, mcp and all its dependencies have been loading in OSGi without issue.
In version 0.13, the "mcp" jar has been replaced with "mcp-core" and "mcp-json-jackson2". Although "mcp-core" is still an OSGi bundle, "mcp-json-jackson2" is not.
Environment
I have been using an Apache Felix Servlet Bridge setup but the OSGi container shouldn't matter.
Steps to reproduce
Building an McpServer from an OSGi container results in the following:
java.lang.IllegalStateException: No default JsonSchemaValidatorSupplier implementation found
at io.modelcontextprotocol.json.schema.JsonSchemaInternal.lambda$createDefaultValidator$2(JsonSchemaInternal.java:66)
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
at io.modelcontextprotocol.json.schema.JsonSchemaInternal.createDefaultValidator(JsonSchemaInternal.java:61)
at io.modelcontextprotocol.json.schema.JsonSchemaInternal.getDefaultValidator(JsonSchemaInternal.java:30)
at io.modelcontextprotocol.json.schema.JsonSchemaValidator.getDefault(JsonSchemaValidator.java:61)
at io.modelcontextprotocol.server.McpServer$StreamableSyncSpecification.build(McpServer.java:848)
Expected behavior
The "mcp-json-jackson2" jar should have an OSGi manifest. The mcp bundles should have proper "Require-Capability" and "Provide-Capability" headers to support the OSGi Service Loader mechanism, like what's implemented by Apache SPI Fly: https://aries.apache.org/documentation/modules/spi-fly.html#specconf
Minimal Complete Reproducible example
The original Servlet Bridge example is here:
https://github.com/apache/felix-dev/tree/8c10c79ff48b6a8938e9fc8088964a2facb42da1/http/samples/bridge
You would need to add your own OSGi bundle with a bundle Activator that starts an MCP server and registers its transport using the OSGi HTTP service. Some detail: https://github.com/apache/felix-dev/blob/master/http/README.md#using-the-httpservice
Workaround
The workaround is to wrap the "mcp-json-jackson2" jar inside of a custom OSGi bundle and to explicitly call "Builder.jsonMapper" and "jsonSchemaValidator" methods on everything to avoid the broken service lookup.
Activity
rombert commentedon Nov 21, 2025
I also think that making the 'original' artifacts compatible with OSGi environments is the way to go. Moving to another project creates responsibility and reproducibility issues that will hinder adoption.
It looks to me like the current OSGi consumers are willing to use the MCP SDK as-is, have found workarounds to minor issues and are willing to contribute fixes.
I am certain that we can find a solution that is acceptable to the maintainers and get the minor issues solved. I sincerely hope that we will not lose OSGi support for the main artifacts.
benken-parasoft commentedon Nov 21, 2025
I believe the jars should be correctly defined as bundles, each owning their own package with proper import/export declarations in their MANIFEST.MF.
I'm have to wrap "mcp-json-jackson2" inside my own bundle as a workaround. Wrapping jars inside other jars definitely shouldn't be the solution.
I recommend the Apache maven-bundle-plugin.
I can't agree this is a good direction. I've seen this type of thing happen before, where you have someone else maintaining their own "repackaged" version of some other project, published under some other groupId. It's really a workaround and requires someone else doing their own maintenance, keeping up with releases of the main project, etc. Eventually such projects become obsolete when the main project finally catches up.
scottslewis commentedon Nov 21, 2025
I have contributed a pr #682 as a fix for issue #612.
The fix in #682 has a positive side effect of allowing/keeping mcp-core, mcp-jackson2, and other mcp-sdk jars separate (no need for a single jar/bundle for OSGi).
Additionally, #682 has this commit, which fixes the original problem as reported in this bug...i.e. the setting of a default json mapper/validator via osgi declarative services (osgi environments) and the use of ServiceLoader (all other java environments).
Happily then, #682 also provides a fix for this specific issue...which was due to the use of ServiceLoader for inter-jar service dependency (default singleton service for json gen/parsing/validating). It is, however, a general approach for supporting osgi environments using the OSGi service registry, and all non-osgi java environments using ServiceLoader. The same approach can be used elsewhere in mcp-sdk if needed.
This requires no environment-specific code, only META-INF and OSGI-INF metadata. I'm happy to explain further how this works in OSGI and non-OSGi environments if desired.
scottslewis commentedon Nov 25, 2025
I've enhanced this pr, done some simplifying refactoring and tested the meta-data additions in osgi.
With these changes, mcp-core does not need mcp-json jar nor mcp-jackson2 jar at compile time (as per #612), and at runtime it only needs mcp-jackson2 jar (or some other/non-Jackson impl of mcp json mapper and mcp json validator services).
In non-osgi runtimes, the ServiceLoader creates the default instances of the mapper and validator services via the mapper and validator suppliers as before.
In osgi runtimes, json default instances are created and used via OSGi declarative services (via manifest and xml metadata in OSGI-INF directory) using the same java classes.
scottslewis commentedon Dec 5, 2025
Summary: As described above, pr #682 issue #612 provides a permanent fix for this issue by:
Migrating the < 10 classes currently in the mcp-json project/jar back into mcp-core. As described in Mcp-core has compile-time dependency on mcp-json #612 mcp-core currently has a compile-time dependency on mcp-json classes.
Modifying the default json mapper and schema validation providers to allow OSGi declarative services to be used (available only in osgi environments) to set the providers upon startup...rather than use the ServiceLoader...which is still the default outside of osgi environments.
Add standard declarative services metadata to the mcp-core manifest and the mcp-jackson2 manifest creation on build. This consists of a small addition of a declarative services xml files, and references to those files in the manifest.mf as per the osgi specification.
The result is a mcp-core.jar and mcp-jackson2 jar that when used in non-osgi environments: uses the ServiceLoader to set the mapper provider and schema validation provider to set the default (jackson2, if that's the jar present at runtime, or other).
and when used in osgi environments: uses declarative services to set the mapper provider and schema validation provider defaults via osgi services.
I've tested the osgi environment behavior by using it in a recent update to this project, which is osgi based.
sdeleuze commentedon Jan 12, 2026
@scottslewis I am planning to contribute a new
mcp-json-jackson3module via a PR, I would welcome your feedback from an OSGI perpective.Currently
mcp-json-jackson2is using theio.modelcontextprotocol.json.jacksonandio.modelcontextprotocol.json.schema.jacksonpackages.I am wondering if we should either:
mcp-json-jackson2andmcp-json-jackson3io.modelcontextprotocol.json.jackson2/io.modelcontextprotocol.json.schema.jackson2formcp-json-jackson2andio.modelcontextprotocol.json.jackson3/io.modelcontextprotocol.json.schema.jackson3formcp-json-jackson3.1 has the advantage of not breaking the current API.
mcp-json-jackson2andmcp-json-jackson3are not really designed to be used at the same time, but should we go as far as using the same package for those mutually-exclusive implementations? 2 clearly separate both at package level but is a breaking change (maybe ok since we still use 0.x versions).cc @graemerocher @sdelamo
scottslewis commentedon Jan 12, 2026
This is a difficult choice IMHO. My inclination is to do what you describe and a new, jackson3 project that can live/run alongside jackson2 and have different package names. Reason: You can be pretty sure that there will be some consumers of the sdk that even as jackson3 gets more common/used that they will require continuing to use Jackson2...even while they use new versions of the sdk (e.g. to keep up with enhancements/bug fixes). The last thing most consumers will want (especially large ones) is a forced upgrade of any library.
This is not a serious problem at all in OSGI environments, as the classloader-per-bundle aspect of the environment allows more than one class with the same package/class name. For example, there are separate providers for multiple major versions of httpclient in Eclipse/ECF (the project I've led for long time). These can all run in the same runtime at the same time and do so happily.
But for non OSGi environments, you can potentially have classloader/class name collision problems. This can make it impossible....or at least very difficult for consumers to use more than one major/incompatible versions of Jackson (or any other lib) at the same time...therefore requiring cutovers. Any such cutover can be very painful (or impossible) for sdk consumers...and so is to be avoided if possible.
filiphr commentedon Jan 12, 2026
Since I already did a PR for Jackson 3 in #742. I wanted to clarify what @sdeleuze proposed in #562 (comment).
I do understand where you are coming from @sdeleuze and I would have liked to solve it using the same package name as well. However, I have another idea.
What if we do the following, create a new
mcp-json-jacksonmodule which would have an optional dependency on Jackson 2 and Jackson 3, that's possible since they have different artifacts anyways. That way we can stay with the packageio.modelcontextprotocol.json.jackson. Then there can be 2 wrapper modulesmcp-json-jackson2andmcp-json-jackson3which would only pull in the right dependencies.The only problem though would be the schema validation. From what I can see the
com.networknt:json-schema-validatordoes not have different artifacts for the different Jackson versions. There is version 2.0.0 for Jackson 2 and version 3.0.0 for Jackson 3.scottslewis commentedon Jan 12, 2026
If at all possible, I would think you would want to just have one api (i.e. mcp-json...which might go back into mcp-core...i.e. #682). Adding a another api (i.e. across Jackson major versions but not non-jackson providers of json serialization/deserialization) will require more maintenance and build/deployment subtleties over the long term.
Plus it will cause additional fits for OSGi environments as described here with use of ServiceLoader.
sdeleuze commentedon Jan 13, 2026
I am also not convinced that this
mcp-json-jacksonproposal will help.For production I don't think we want to support both, but for tests, I can see how we could want that. Also conceptually, it would be a bit of a shame to use the same package while service loader provides a clean way to use a different one.
In the end, I think my vote is for using different packages (solution 2 from #562 (comment), let's continue this discussion in #742 where I have added a new comment) and merging
mcp-jsontomcp-core(#682).scottslewis commentedon Jan 29, 2026
For info of people watching this issue:
pr #762 includes OSGi metadata (Manifest.mf and SCR xml files) that fully addresses this issue. I'm happy to give a technical description of how this is done, but it's mostly covered by previous discussion on this issue so I won't repeat it unless summarization is necessary.
This includes support for using either Jackson2 xor Jackson3 for mcp serialization. All that's needed to use one or the other is to include the appropirate jar/bundle (mcp-json-jackson2 or mcp-json-jackson3) into your osgi environment alongside mcp-core.
I'm testing this now in my local osgi environment, so there may be some small changes to the pr in case the osgi meta-data is not right for whatever reason...or there is something about Jackson3 that doesn't work correctly in osgi environments, but I just don't know yet.
scottslewis commentedon Feb 8, 2026
I've now tested the fixes in pr #762 in OSGi environment (OSGi 8, Java 17 with Service Component Runtime from OSGi 8 spec). This repo has an example/test app that I've been using for testing.
These tests work with either the jackson2 jackson3 modules. See mcpserver.bndrun and mcpserver.jackson3.bndrun files in mcpserver project (or mcpclient) for details of the runtime configuration for jackson2 vs. jackson3.
scottslewis commentedon Feb 17, 2026
@Kerlann : With pr #779 being now merged, this issue is now fixed. It can be closed.
The default mapper and the default schema validator will be null...as in the original description stack trace...if there is no jackson2 or jackson3 (or some other provider) available at runtime.
In OSGi environments the service component runtime (SCR) is required.
chemicL commentedon Feb 20, 2026
With the above by @scottslewis and the recent changes I am closing the issue. If that's not correct, please reopen or create a new issue to better describe the current status. Thanks!
garpinc commentedon Mar 5, 2026
This is still an issue in version 1.0.0
chemicL commentedon Mar 5, 2026
I addressed the above concern in #856 (comment)