You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Allow registration of custom JSON-RPC methods #954
Although the Golang SDK provides a solid interface, it currently does not allow to extend handlers for custom JSON-RPC methods.
Describe the solution you'd like
The mcp package can expose following interfaces
Add methods to both the Client and Server to register receiving and sending custom methods. For example:
AddReceivingCustomMethod[P paramsPtr[T], R Result, T any](method string, handler typedServerMethodHandler[P, R])
AddSendingCustomMethod[P paramsPtr[T], R Result, T any](method string, handler typedClientMethodHandler[P, R])
Export other internal components that are necessary to implement these custom handlers, such as Params.isParams, Result.isResult, typedServerMethodHandler, typedClientMethodHandler, paramsPtr, etc.
Describe alternatives you've considered
N/A
Additional context
For reference, we have already implemented AddReceivingCustomMethod for the server in a vendored version of the library. You can view the implementation details here:
@jba please let me know if you have any other way to do this. I'm open to implement in another way. But this seems good use case and test bed for method registration in my view.
@guglielmo-san@jba Hi, I want to ask if this issue can be pushed forward. I believe following seps are showing the needs of custom json rpc methods pretty well.
Also SDK parity could be another discussion point in my opinion.
It seems SDKs are not aligned, but they are providing interface for custom method or low level json rpc handler in their ways:
@jba please let me know if you have any other way to do this. I'm open to implement in another way. But this seems good use case and test bed for method registration in my view.
Let's find a concrete, compelling use case before we open up method registration. This doesn't seem to be it.
I'd need to see another use case other than this for your proposal.
There's probably a way to make them experimental with a build tag, but I haven't thought it through.
You need to learn about build tags, try them for this problem, and come back here with either "I tried but I don't think they'll work, let me explain why" or "I tried and I succeeded, here's the updated PR."
I really want to clarify that I'm not currently the author of opened pr and I'm not arguing for or against build tags. i'm just tracking this issue because I want to make progression on downstream project. and that was why I tagged the author of the PR here. I understand maintainers may have different views, and may reject this feature request. That's also sensible and I respect that.
Also to answer your points:
On writing the extensions code directly into go-sdk - it's still in experimental, it may not even be approved. Still evolving. I want to avoid prototyping in go-sdk repository. If it's graduating, I agree with you.
On the build tags - fortunately, I'm already familiar with it. I think it can be done either 1) writing interceptor codes directly into go-sdk with build tags or 2) providing custom method registration with build tags. but for (1), as I mentioned above, I want to avoid to do it during prototyping. For (2), I want to leave the decisions to reviewers and pr authors.
Let's find a concrete, compelling use case before we open up method registration. This doesn't seem to be it.
I'd need to see another use case other than this for your proposal.
Just to add to @jeongukjae's comments, there are already concrete examples of custom JSON-RPC methods in use, specifically in the official extensions (Apps and Tasks).
The Tasks extension introduces tasks/get, tasks/list, tasks/result, tasks/update, tasks/cancel, and notifications/tasks/status, all methods outside the core spec that need to be dispatched by the SDK.
MCP Apps similarly introduces ui/initialize, ui/notifications/initialized, and ui/notifications/size-changed for iframe-host communication.
The extension mechanism (SEP-1724) is designed so that new capabilities can be negotiated and custom JSON-RPC methods can be used to extend the protocol. Compared to the other language SDKs mentioned above, the lack of custom method support makes it difficult to implement extensions on Go servers.
SDKs may optionally implement any number of extensions and where appropriate (and necessary) should provide facilities for enabling and configuring extensions. Extensions must be disabled by default and require opt-in. SDK documentation should list supported extensions.
This seems to say that the SDKs should implement official exceptions.
Please open issues on this repo (if not open already) and submit PRs for them.
I think you're misreading that (but it might be me). The specs are in separate repos, but that doc says:
Implement: Build at least one reference implementation in an official SDK — this is required before the SEP can be reviewed.
I interpret that as meaning that you have to add it to an official SDK. In the case of Go, you can submit a PR with a build tag, or you can fork the repo.
Let me be clear about my objection to custom methods.
Go has only two visibility levels:
Only within the package or module.
Everyone.
If everyone can use custom methods, then that endorses anyone to effectively implement an alternative protocol. We could expect hundreds of slightly different MCP servers and clients, fragmenting the ecosystem.
While it's still possible to do this by forking the repo, at least you know that when you fork, you're going outside the usual development process. If we have exported symbols for extending the protocol, people will think it's fine to do it.
If everyone can use custom methods, then that endorses anyone to effectively implement an alternative protocol. We could expect hundreds of slightly different MCP servers and clients, fragmenting the ecosystem.
Preventing the fragmentation isn't really go-sdk's responsibility. The SEP process, extension mechanisms, and capability negotiation are what's designed against "hundreds of slightly different MCP servers".
This seems like a reasonable, narrowly scoped feature that primarily brings the Go SDK into alignment with the capabilities already exposed by other official SDKs. Without that, developers are effectively pushed toward maintaining forks or using a different SDK entirely.
developers are effectively pushed toward maintaining forks or using a different SDK entirely
I think the key word here is "developers." Are we talking about "developers of the SDK" or "developers using the SDK"? Maybe I'm confused, but I think it's the first one.
Developers of the SDK should develop the SDK itself. They should not build things on top of it. That is for everyone else. To develop the SDK, you submit a PR. If the PR implements an experimental feature, gate it with a build tag.
Developers using the SDK should not need custom methods. They are following—indeed, they are constrained to follow—the MCP spec. The right way to get a "custom method" into the SDK is to write a SEP.
Why would you need to maintain a fork? Maybe one possibility is this: you work for an organization that really wants tasks, for example, and you want them now. You don't want to wait for the maintainers to review your changes, and you can't use custom methods to implement them, so you must fork.
That seems like the right model to me. If you need something in an API before the package maintainers can do it, you send a PR to them (because you're a good open-source citizen) and then run on a fork that includes your PR until it's accepted. That is true of all open-source software, isn't it?
The SEP process, extension mechanisms, and capability negotiation are what's designed against "hundreds of slightly different MCP servers".
But aren't you trying to subvert those processes? I mean, maybe not you—you're implementing an official exension, let's say—but the next person. They can now implement their favorite feature without any of those pesky administrative details.
Again, I may be missing something. If there were in fact an "extension" feature that implied that anyone could extend the SDK with custom methods, we would implement it. But AFAICT, "extensions" are protocol extensions that are nevertheless implemented within the SDK. You seem to disagree with this: above you wrote
The extension mechanism (SEP-1724) is designed so that new capabilities can be negotiated and custom JSON-RPC methods can be used to extend the protocol. Compared to the other language SDKs mentioned above, the lack of custom method support makes it difficult to implement extensions on Go servers.
@jba I think we're still talking past each other a bit, so let me try to separate the concerns.
Where we agree
When you say that extensions are protocol extensions implemented within the SDK, I agree — that is a reasonable path for official extensions. Once an extension has graduated through the SEP process and a given SDK maintainer wants to support it directly, implementing it in that SDK via PR makes complete sense.
What this issue is actually about
The extensions motivating this issue are experimental — they're in the incubation phase, before SEP acceptance. SEP-2133 explicitly creates a separate governance path for this:
Experimental extension repos live under the modelcontextprotocol org with the experimental-ext- prefix
They are associated with a WG or IG, with their own maintainers responsible for day-to-day governance
They must be separate packages that clearly indicate their experimental status
These are not rogue projects, but they are also not SDK-owned code. Experimental extension maintainers are not necessarily Go SDK maintainers, and the whole point of the experimental path is to let WGs and IGs iterate separately — without being bottlenecked on SDK-maintainer review for code that is still evolving and may never be approved.
What I'm asking for
I am not asking the Go SDK maintainers to accept, implement, bless, or maintain any particular extension.
I am asking for the SDK to be usable as a library by code that needs to extend MCP in the way SEP-2133 anticipates. The spec itself contemplates this:
"This SEP does not prescribe how SDKs should structure or package extensions. Maintainers may provide extension points, plugin systems, or any other mechanism they see fit."
Concretely, a clean separation would look like:
The Go SDK owns the core API, routing, validation, and safety invariants
Experimental extension maintainers own their experimental packages
Consumers explicitly opt into those packages
Nothing experimental is enabled by default or shipped as part of the core SDK
The SDK exposes only a narrow, controlled API for custom method registration
Why the alternatives don't work
Build tags — Putting experimental extension code into the main SDK, even behind build tags, is actually what I want to avoid. It couples experimental work to the SDK release surface, creates dependency and govulncheck noise for downstream users who aren't using the extension, and makes Go SDK maintainers the de facto gatekeepers for experimental extension iteration. Every change goes through the SDK repo, even when the extension has separate maintainers and a separate cadence.
Forking — We actually tried this. The experience is difficult in practice — the fork needs constant rebasing as the underlying SDK evolves, and when you're trying to prove out an experimental extension with real use cases, that rebasing overhead becomes a serious drag on iteration. The whole value of building on top of an SDK is that you get transport, auth, protocol handling, etc. for free. A fork doesn't give you that cleanly — it gives you a snapshot that immediately starts diverging.
Forking also breaks down entirely when you need to stack multiple experimental extensions. Each experimental extension is developed independently in its own experimental-ext-* repo by its own maintainers — if you want to combine two or three of them, there's no clean way to layer independent forks. You end up maintaining a single mega-fork that cherry-picks from multiple extension repos, which is fragile and defeats the purpose of independent experimentation. With a custom method registration API, each extension is just a separate dependency that registers its methods independently, and they compose naturally on top of a single, unmodified SDK.
The model that works well in other official SDKs is much simpler: for example, in the TypeScript SDK, an extension is a separate dependency that imports the SDK and registers its additional methods. The underlying SDK version stays independent and updatable. That's exactly the separation SEP-2133 envisions — and it's what a narrow extension point like AddMethod would enable here.
This is already proven elsewhere
Nearly every official SDK already provides custom method registration. We have working server and client implementations proving out the experimental extension in several of these:
If everyone can use custom methods, then that endorses anyone to effectively implement an alternative protocol.
I understand this concern. But the MCP project already handles fragmentation at the protocol level — vendor-prefixed identifiers, capability negotiation during initialize, and graceful degradation requirements. Those are the mechanisms designed for this, and the other official SDKs have all adopted custom method registration without the ecosystem fragmenting as a result.
The middle ground
I don't think the right dichotomy is "implemented in the SDK" versus "unsupported alternative protocol." There is a middle ground: the SDK exposes a controlled extension point, while extension packages remain separate, clearly marked, opt-in, and governed by their own maintainers.
That would let the Go SDK preserve its safety boundaries without taking ownership of experimental extension code — and it would let the experimental extension process function as SEP-2133 designed it.
OK, this is the first time I looked at SEP 2133. Concurrently, Kurtis Van Gent pointed me there too. Up until now I've been looking at SEP 1724, which I guess is the issue that turned into 2133.
2133 says:
This SEP does not prescribe how SDKs should structure or package extensions. Maintainers may provide extension points, plugin systems, or any other mechanism they see fit.
Next step is a PR. Do we have a volunteer? Also, I'm not the primary maintainer, I've only been dealing with this issue. So they need to be involved. I don't think there will be any disagreement, they just have to sign off on the review, since they will be maintaining it.
@guglielmo-san it seems like the pr implements what interceptor wg needs. thanks!
btw, for the completeness, I think it's worth to consider sending custom method from server, and receiving one from client. (the opposite direction that pr implemented)
Activity
jba commentedon May 28, 2026
Can you explain the connection? I looked over the SEP and I don't see why it requires custom methods.
jeongukjae commentedon May 28, 2026
@jba Hi, the SEP introduces following JSON RPC methods
interceptors/list: to discover interceptors in the serverinterceptors/invoke: to invoke specific interceptorjba commentedon May 28, 2026
Why can't we just add those to our code directly, as we have done for all the other MCP methods?
See serverMethodInfos in mcp/server.go.
jeongukjae commentedon May 29, 2026
That's good point, but the proposed SEP is still experimental.
Making them standard requires more process on the SEP and alignment.
+ I think this feature is not only applied to interceptors. This would be helpful for other possible extensions.
jba commentedon May 29, 2026
Let's find a concrete, compelling use case before we open up method registration. This doesn't seem to be it.
There's probably a way to make them experimental with a build tag, but I haven't thought it through.
jeongukjae commentedon Jun 8, 2026
@jba please let me know if you have any other way to do this. I'm open to implement in another way. But this seems good use case and test bed for method registration in my view.
jeongukjae commentedon Jun 16, 2026
@guglielmo-san @jba Hi, I want to ask if this issue can be pushed forward. I believe following seps are showing the needs of custom json rpc methods pretty well.
Also SDK parity could be another discussion point in my opinion.
It seems SDKs are not aligned, but they are providing interface for custom method or low level json rpc handler in their ways:
jba commentedon Jun 22, 2026
You're not addressing my concerns.
I'd need to see another use case other than this for your proposal.
You need to learn about build tags, try them for this problem, and come back here with either "I tried but I don't think they'll work, let me explain why" or "I tried and I succeeded, here's the updated PR."
jeongukjae commentedon Jun 23, 2026
Hi!
I really want to clarify that I'm not currently the author of opened pr and I'm not arguing for or against build tags. i'm just tracking this issue because I want to make progression on downstream project. and that was why I tagged the author of the PR here. I understand maintainers may have different views, and may reject this feature request. That's also sensible and I respect that.
Also to answer your points:
On writing the extensions code directly into go-sdk - it's still in experimental, it may not even be approved. Still evolving. I want to avoid prototyping in go-sdk repository. If it's graduating, I agree with you.
On the build tags - fortunately, I'm already familiar with it. I think it can be done either 1) writing interceptor codes directly into go-sdk with build tags or 2) providing custom method registration with build tags. but for (1), as I mentioned above, I want to avoid to do it during prototyping. For (2), I want to leave the decisions to reviewers and pr authors.
Also I want to ask you about the policies of go-sdk. I believe prototypings should happen in isolated repository following this doc, but does go-sdk encourage to contribute those directly to go-sdk?
imfing commentedon Jun 23, 2026
Just to add to @jeongukjae's comments, there are already concrete examples of custom JSON-RPC methods in use, specifically in the official extensions (Apps and Tasks).
The Tasks extension introduces
tasks/get,tasks/list,tasks/result,tasks/update,tasks/cancel, andnotifications/tasks/status, all methods outside the core spec that need to be dispatched by the SDK.MCP Apps similarly introduces
ui/initialize,ui/notifications/initialized, andui/notifications/size-changedfor iframe-host communication.The extension mechanism (SEP-1724) is designed so that new capabilities can be negotiated and custom JSON-RPC methods can be used to extend the protocol. Compared to the other language SDKs mentioned above, the lack of custom method support makes it difficult to implement extensions on Go servers.
jba commentedon Jun 23, 2026
I read SEP-1724, in particular the following:
This seems to say that the SDKs should implement official exceptions.
Please open issues on this repo (if not open already) and submit PRs for them.
jba commentedon Jun 23, 2026
I think you're misreading that (but it might be me). The specs are in separate repos, but that doc says:
I interpret that as meaning that you have to add it to an official SDK. In the case of Go, you can submit a PR with a build tag, or you can fork the repo.
jba commentedon Jun 23, 2026
Let me be clear about my objection to custom methods.
Go has only two visibility levels:
If everyone can use custom methods, then that endorses anyone to effectively implement an alternative protocol. We could expect hundreds of slightly different MCP servers and clients, fragmenting the ecosystem.
While it's still possible to do this by forking the repo, at least you know that when you fork, you're going outside the usual development process. If we have exported symbols for extending the protocol, people will think it's fine to do it.
jba commentedon Jun 23, 2026
By the way, #755 starts to implement tasks.
imfing commentedon Jun 24, 2026
Preventing the fragmentation isn't really go-sdk's responsibility. The SEP process, extension mechanisms, and capability negotiation are what's designed against "hundreds of slightly different MCP servers".
This seems like a reasonable, narrowly scoped feature that primarily brings the Go SDK into alignment with the capabilities already exposed by other official SDKs. Without that, developers are effectively pushed toward maintaining forks or using a different SDK entirely.
BTW, this PR wasn't updated over the past 3 months, it's effectively abandoned
jba commentedon Jun 24, 2026
I think the key word here is "developers." Are we talking about "developers of the SDK" or "developers using the SDK"? Maybe I'm confused, but I think it's the first one.
Developers of the SDK should develop the SDK itself. They should not build things on top of it. That is for everyone else. To develop the SDK, you submit a PR. If the PR implements an experimental feature, gate it with a build tag.
Developers using the SDK should not need custom methods. They are following—indeed, they are constrained to follow—the MCP spec. The right way to get a "custom method" into the SDK is to write a SEP.
Why would you need to maintain a fork? Maybe one possibility is this: you work for an organization that really wants tasks, for example, and you want them now. You don't want to wait for the maintainers to review your changes, and you can't use custom methods to implement them, so you must fork.
That seems like the right model to me. If you need something in an API before the package maintainers can do it, you send a PR to them (because you're a good open-source citizen) and then run on a fork that includes your PR until it's accepted. That is true of all open-source software, isn't it?
But aren't you trying to subvert those processes? I mean, maybe not you—you're implementing an official exension, let's say—but the next person. They can now implement their favorite feature without any of those pesky administrative details.
Again, I may be missing something. If there were in fact an "extension" feature that implied that anyone could extend the SDK with custom methods, we would implement it. But AFAICT, "extensions" are protocol extensions that are nevertheless implemented within the SDK. You seem to disagree with this: above you wrote
but in response I wrote:
Maybe we should focus on this narrow point, since it seems to be at the root of our disagreement.
sambhav commentedon Jun 24, 2026
@jba I think we're still talking past each other a bit, so let me try to separate the concerns.
Where we agree
When you say that extensions are protocol extensions implemented within the SDK, I agree — that is a reasonable path for official extensions. Once an extension has graduated through the SEP process and a given SDK maintainer wants to support it directly, implementing it in that SDK via PR makes complete sense.
What this issue is actually about
The extensions motivating this issue are experimental — they're in the incubation phase, before SEP acceptance. SEP-2133 explicitly creates a separate governance path for this:
modelcontextprotocolorg with theexperimental-ext-prefixThese are not rogue projects, but they are also not SDK-owned code. Experimental extension maintainers are not necessarily Go SDK maintainers, and the whole point of the experimental path is to let WGs and IGs iterate separately — without being bottlenecked on SDK-maintainer review for code that is still evolving and may never be approved.
What I'm asking for
I am not asking the Go SDK maintainers to accept, implement, bless, or maintain any particular extension.
I am asking for the SDK to be usable as a library by code that needs to extend MCP in the way SEP-2133 anticipates. The spec itself contemplates this:
Concretely, a clean separation would look like:
Why the alternatives don't work
Build tags — Putting experimental extension code into the main SDK, even behind build tags, is actually what I want to avoid. It couples experimental work to the SDK release surface, creates dependency and
govulnchecknoise for downstream users who aren't using the extension, and makes Go SDK maintainers the de facto gatekeepers for experimental extension iteration. Every change goes through the SDK repo, even when the extension has separate maintainers and a separate cadence.Forking — We actually tried this. The experience is difficult in practice — the fork needs constant rebasing as the underlying SDK evolves, and when you're trying to prove out an experimental extension with real use cases, that rebasing overhead becomes a serious drag on iteration. The whole value of building on top of an SDK is that you get transport, auth, protocol handling, etc. for free. A fork doesn't give you that cleanly — it gives you a snapshot that immediately starts diverging.
Forking also breaks down entirely when you need to stack multiple experimental extensions. Each experimental extension is developed independently in its own
experimental-ext-*repo by its own maintainers — if you want to combine two or three of them, there's no clean way to layer independent forks. You end up maintaining a single mega-fork that cherry-picks from multiple extension repos, which is fragile and defeats the purpose of independent experimentation. With a custom method registration API, each extension is just a separate dependency that registers its methods independently, and they compose naturally on top of a single, unmodified SDK.The model that works well in other official SDKs is much simpler: for example, in the TypeScript SDK, an extension is a separate dependency that imports the SDK and registers its additional methods. The underlying SDK version stays independent and updatable. That's exactly the separation SEP-2133 envisions — and it's what a narrow extension point like
AddMethodwould enable here.This is already proven elsewhere
Nearly every official SDK already provides custom method registration. We have working server and client implementations proving out the experimental extension in several of these:
setRequestHandler()/setNotificationHandler()add_request_handler()/add_notification_handler()CustomRequestsetRequestHandler(Method.Custom(...))withMethodHandler()via protocol conformanceOn fragmentation
I understand this concern. But the MCP project already handles fragmentation at the protocol level — vendor-prefixed identifiers, capability negotiation during
initialize, and graceful degradation requirements. Those are the mechanisms designed for this, and the other official SDKs have all adopted custom method registration without the ecosystem fragmenting as a result.The middle ground
I don't think the right dichotomy is "implemented in the SDK" versus "unsupported alternative protocol." There is a middle ground: the SDK exposes a controlled extension point, while extension packages remain separate, clearly marked, opt-in, and governed by their own maintainers.
That would let the Go SDK preserve its safety boundaries without taking ownership of experimental extension code — and it would let the experimental extension process function as SEP-2133 designed it.
jba commentedon Jun 24, 2026
OK, this is the first time I looked at SEP 2133. Concurrently, Kurtis Van Gent pointed me there too. Up until now I've been looking at SEP 1724, which I guess is the issue that turned into 2133.
2133 says:
So that sanctions custom methods.
I approve of this change. (That was easy!)
jba commentedon Jun 24, 2026
Next step is a PR. Do we have a volunteer? Also, I'm not the primary maintainer, I've only been dealing with this issue. So they need to be involved. I don't think there will be any disagreement, they just have to sign off on the review, since they will be maintaining it.
sambhav commentedon Jun 24, 2026
I believe we already have a PR from @guglielmo-san who I believe is a maintainer?
#956
He was waiting on your comments before that PR progressed further.
#956 (comment)
guglielmo-san commentedon Jun 25, 2026
@sambhav @jeongukjae @imfing can you confirm if the current implementation of the PR #956 meets your needs?
jeongukjae commentedon Jun 25, 2026
@guglielmo-san it seems like the pr implements what interceptor wg needs. thanks!
btw, for the completeness, I think it's worth to consider sending custom method from server, and receiving one from client. (the opposite direction that pr implemented)
mcp: Allow registration of custom JSON-RPC methods (modelcontextproto…