Skip to content

Commit 32faa4c

Browse files
authored
Merge branch 'main' into feat/28-7-mcp-spec
2 parents 3267770 + bb0ca87 commit 32faa4c

8 files changed

Lines changed: 459 additions & 152 deletions

File tree

CONTRIBUTING.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ propose an enhancement. Bug reports should have a reproducer in the form of a co
3535
sample or a repository attached that the maintainers or contributors can work with to
3636
address the problem.
3737

38+
## AI agents
39+
40+
**We accept contributions created with the help of AI coding agents, but they must be carefully reviewed by a human who remains accountable for the quality of the contribution.**
41+
These can be issues or pull requests. For issues, please ensure you describe your particular use-case, and not general considerations found by an AI agent.
42+
Contributions submitted by GitHub accounts controlled by autonomous AI bots are forbidden.
43+
3844
## Making Changes
3945

4046
1. Create a new branch:

mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,10 @@ public SyncSpec elicitationCompleteConsumers(
494494
* calling any client operation. This allows to extract thread-locals and hand
495495
* them over to the underlying transport.
496496
* <p>
497-
* There is no direct equivalent in {@link AsyncSpec}. To achieve the same result,
498-
* append {@code contextWrite(McpTransportContext.KEY, context)} to any
499-
* {@link McpAsyncClient} call.
497+
* The supplier is invoked at subscription time, on the calling thread, and the
498+
* resulting context is visible to the transport for every leg of the operation,
499+
* including connections opened on other threads, such as the SSE stream started
500+
* during initialization.
500501
* @param contextProvider A supplier to create a context
501502
* @return This builder for method chaining
502503
*/
@@ -580,6 +581,21 @@ public McpSyncClient build() {
580581
* <li>Change notification handlers for tools, resources, and prompts
581582
* <li>Custom message sampling logic
582583
* </ul>
584+
*
585+
* <p>
586+
* Unlike {@link SyncSpec}, this specification has no
587+
* {@code transportContextProvider}. This is deliberate: in a reactive pipeline the
588+
* caller owns the Reactor context, and whatever the transport needs, such as an
589+
* {@link McpTransportContext}, can be written into it directly. Write it once where
590+
* the reactive chain starts, rather than at every call site, and every
591+
* {@link McpAsyncClient} call downstream inherits it, including the connections
592+
* opened during initialization: <pre>{@code
593+
* chain.filter(exchange)
594+
* .contextWrite(ctx -> ctx.put(McpTransportContext.KEY, context));
595+
* }</pre> To bridge thread-locals into the chain, use Reactor's context propagation
596+
* support.
597+
*
598+
* @see SyncSpec#transportContextProvider(Supplier)
583599
*/
584600
class AsyncSpec {
585601

mcp-core/src/main/java/io/modelcontextprotocol/client/transport/customizer/McpAsyncHttpClientRequestCustomizer.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,26 @@
77
import java.net.URI;
88
import java.net.http.HttpRequest;
99

10+
import io.modelcontextprotocol.client.McpClient.SyncSpec;
11+
import io.modelcontextprotocol.common.McpTransportContext;
1012
import org.reactivestreams.Publisher;
1113
import reactor.core.publisher.Mono;
1214
import reactor.core.scheduler.Schedulers;
1315
import reactor.util.annotation.Nullable;
1416

15-
import io.modelcontextprotocol.common.McpTransportContext;
16-
1717
/**
1818
* Customize {@link HttpRequest.Builder} before executing the request, in either SSE or
1919
* Streamable HTTP transport.
2020
* <p>
2121
* When used in a non-blocking context, implementations MUST be non-blocking.
22+
* <p>
23+
* The {@link McpTransportContext} handed to {@code customize} is read from the Reactor
24+
* context, under {@link McpTransportContext#KEY}, and is
25+
* {@link McpTransportContext#EMPTY} when the caller wrote nothing there. Write it once
26+
* where the reactive chain starts, with
27+
* {@code contextWrite(ctx -> ctx.put(McpTransportContext.KEY, context))}, rather than at
28+
* every call site. With a synchronous client, configure
29+
* {@link SyncSpec#transportContextProvider} instead.
2230
*
2331
* @author Daniel Garnier-Moiroux
2432
*/

mcp-core/src/main/java/io/modelcontextprotocol/common/McpTransportContext.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,28 @@
1111
* Context associated with the transport layer. It allows to add transport-level metadata
1212
* for use further down the line. Specifically, it can be beneficial to extract HTTP
1313
* request metadata for use in MCP feature implementations.
14+
* <p>
15+
* The context travels in the Reactor context, under {@link #KEY}. On the server side, the
16+
* transports populate it from the incoming request. On the client side, writing it is the
17+
* caller's responsibility:
18+
* <ul>
19+
* <li>with a synchronous client, configure
20+
* {@code McpClient.SyncSpec#transportContextProvider(Supplier)}, which is invoked on the
21+
* calling thread before every operation;
22+
* <li>with an asynchronous client, write it into the Reactor context once, where the
23+
* reactive chain starts, using
24+
* {@code contextWrite(ctx -> ctx.put(McpTransportContext.KEY, context))}. Every client
25+
* call downstream inherits it, so there is no need to repeat it at each call site.
26+
* </ul>
1427
*
1528
* @author Dariusz Jędrzejczyk
1629
*/
1730
public interface McpTransportContext {
1831

1932
/**
20-
* Key for use in Reactor Context to transport the context to user land.
33+
* Key for use in Reactor Context to transport the context to user land. Write the
34+
* context under this key to make it visible to the transport, for example
35+
* {@code contextWrite(ctx -> ctx.put(McpTransportContext.KEY, context))}.
2136
*/
2237
String KEY = "MCP_TRANSPORT_CONTEXT";
2338

0 commit comments

Comments
 (0)