sdk: Expose githubMcpToolConfig across languages - #2112
Conversation
Adds the `githubMcpToolConfig` session option to `session.create` and `session.resume` in all six SDKs, forwarding the built-in GitHub MCP server settings the runtime already accepts: `enableAllTools`, `additionalToolsets`, `additionalTools`, `enableInsidersMode`, and the new `disableFormDeferral`. `disableFormDeferral` lets autonomous SDK workflows opt out of MCP App form deferral, so form-backed GitHub write tools execute directly instead of returning an awaiting-form stub. It requires MCP Apps to be enabled for the session. The option is omitted from the wire payload entirely when unset, so existing consumers see no change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Exposes the runtime’s githubMcpToolConfig option on session create/resume across multiple SDKs so callers can configure the built-in GitHub MCP server (notably disableFormDeferral) without dropping to raw payloads.
Changes:
- Added a GitHub MCP tool config type in each SDK and threaded it through
session.create/session.resume. - Ensured the option is omitted from wire payloads when unset (with tests in each language).
- Added language-specific helpers/builders/serialization to map SDK shapes to the runtime wire format.
Show a summary per file
| File | Description |
|---|---|
| rust/src/wire.rs | Adds github_mcp_tool_config to create/resume wire structs with omit-when-None behavior. |
| rust/src/types.rs | Introduces GitHubMcpToolConfig + builders; wires it through session configs and adds serde tests. |
| python/test_client.py | Adds pytest coverage verifying create/resume forwarding of githubMcpToolConfig. |
| python/copilot/session.py | Adds GitHubMcpToolConfig TypedDict for the public Python API. |
| python/copilot/client.py | Adds github_mcp_tool_config kwargs + wire conversion helper and forwards in payload. |
| python/copilot/init.py | Re-exports GitHubMcpToolConfig from the package root. |
| nodejs/test/client.test.ts | Adds tests for forwarding and omitting githubMcpToolConfig. |
| nodejs/src/types.ts | Adds GitHubMcpToolConfig interface and exposes it on SessionConfigBase. |
| nodejs/src/index.ts | Exports GitHubMcpToolConfig from package root. |
| nodejs/src/client.ts | Forwards githubMcpToolConfig in create/resume requests. |
| java/src/test/java/com/github/copilot/SessionRequestBuilderTest.java | Adds create/resume + omission serialization coverage for githubMcpToolConfig. |
| java/src/main/java/com/github/copilot/rpc/SessionConfig.java | Adds GitHubMcpToolConfig to session config + accessors + clone propagation. |
| java/src/main/java/com/github/copilot/rpc/ResumeSessionRequest.java | Adds githubMcpToolConfig JSON field to resume request. |
| java/src/main/java/com/github/copilot/rpc/ResumeSessionConfig.java | Adds GitHubMcpToolConfig to resume config + accessors + clone propagation. |
| java/src/main/java/com/github/copilot/rpc/GitHubMcpToolConfig.java | New bean defining the GitHub MCP tool config wire shape. |
| java/src/main/java/com/github/copilot/rpc/CreateSessionRequest.java | Adds githubMcpToolConfig JSON field to create request. |
| java/src/main/java/com/github/copilot/SessionRequestBuilder.java | Threads config into create/resume request builders. |
| go/types.go | Adds GitHubMCPToolConfig and threads it into session config + request wire structs. |
| go/client_test.go | Adds JSON serialization tests for create/resume/omitted behavior. |
| go/client.go | Passes config through to create/resume request payloads. |
| dotnet/test/Unit/SerializationTests.cs | Adds serialization coverage for create/resume + omit-when-unset. |
| dotnet/src/Types.cs | Adds GitHubMcpToolConfig and deep-copies it in SessionConfigBase copy ctor. |
| dotnet/src/Client.cs | Threads config into internal create/resume request records. |
Review details
- Files reviewed: 23/23 changed files
- Comments generated: 6
- Review effort level: Low
- node: omit githubMcpToolConfig for null as well as undefined - python: document github_mcp_tool_config on create_session/resume_session - go: assert json.Unmarshal succeeds in the omitted-when-unset subtest - java: call the non-deprecated buildCreateRequest(config, sessionId) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Review details
Comments suppressed due to low confidence (4)
java/src/main/java/com/github/copilot/SessionRequestBuilder.java:179
- Both builders unconditionally call
setGitHubMcpToolConfig(...), including when the config value isnull. This relies on global Jackson settings (or class-level@JsonInclude) to keep the field omitted; if serialization settings change, this could start emitting\"githubMcpToolConfig\": nulland violate the API contract of omitting when unset. Prefer only calling the setter when non-null (or calling an explicitclear.../leaving it untouched) to make omission behavior robust.
request.setGitHubMcpToolConfig(config.getGitHubMcpToolConfig());
java/src/main/java/com/github/copilot/SessionRequestBuilder.java:304
- Both builders unconditionally call
setGitHubMcpToolConfig(...), including when the config value isnull. This relies on global Jackson settings (or class-level@JsonInclude) to keep the field omitted; if serialization settings change, this could start emitting\"githubMcpToolConfig\": nulland violate the API contract of omitting when unset. Prefer only calling the setter when non-null (or calling an explicitclear.../leaving it untouched) to make omission behavior robust.
request.setGitHubMcpToolConfig(config.getGitHubMcpToolConfig());
python/copilot/client.py:351
- The helper includes a field whenever the key exists, even if the value is
None, which would serialize asnullon the wire. Since the intent is to omit unset fields while still preserving explicitFalse, consider checkingvalue is not Nonebefore setting each output key (this still forwardsFalsecorrectly). This avoids sendingnullvalues that may be rejected or interpreted differently by the runtime.
def _github_mcp_tool_config_to_wire(config: Mapping[str, Any]) -> dict[str, Any]:
"""Convert a ``GitHubMcpToolConfig`` mapping to wire format."""
wire: dict[str, Any] = {}
if "enable_all_tools" in config:
wire["enableAllTools"] = config["enable_all_tools"]
if "additional_toolsets" in config:
wire["additionalToolsets"] = config["additional_toolsets"]
if "additional_tools" in config:
wire["additionalTools"] = config["additional_tools"]
if "enable_insiders_mode" in config:
wire["enableInsidersMode"] = config["enable_insiders_mode"]
if "disable_form_deferral" in config:
wire["disableFormDeferral"] = config["disable_form_deferral"]
return wire
python/test_client.py:533
- Python adds forwarding coverage for
github_mcp_tool_config, but there’s no test asserting the key is omitted when unset/None (which is part of the PR’s stated contract and is covered in the other SDKs). Add a pytest case that callscreate_session()/resume_session()withoutgithub_mcp_tool_configand asserts\"githubMcpToolConfig\"is absent from the captured params.
@pytest.mark.asyncio
async def test_create_and_resume_session_forward_github_mcp_tool_config(self):
client = CopilotClient(connection=RuntimeConnection.for_stdio(path=CLI_PATH))
await client.start()
try:
captured = {}
async def mock_request(method, params, **kwargs):
captured[method] = params
if method in ("session.create", "session.resume"):
result = {"sessionId": params.get("sessionId") or "session-1"}
callback = kwargs.get("on_response_inline")
if callback is not None:
callback(result)
return result
return {}
client._client.request = mock_request
config = {
"enable_all_tools": True,
"additional_toolsets": ["repos"],
"additional_tools": ["get_issue"],
"enable_insiders_mode": True,
"disable_form_deferral": True,
}
session = await client.create_session(github_mcp_tool_config=config)
await client.resume_session(session.session_id, github_mcp_tool_config=config)
- Files reviewed: 23/23 changed files
- Comments generated: 0 new
- Review effort level: Low
There was a problem hiding this comment.
Review details
Comments suppressed due to low confidence (4)
python/test_client.py:545
- The new coverage validates forwarding on create/resume, but it doesn’t cover the “omitted-when-unset” behavior for Python (which the PR description claims for every language). Add a test that calls
create_session()/resume_session()withoutgithub_mcp_tool_configand assertsgithubMcpToolConfigis absent from the outgoing params.
@pytest.mark.asyncio
async def test_create_and_resume_session_forward_github_mcp_tool_config(self):
client = CopilotClient(connection=RuntimeConnection.for_stdio(path=CLI_PATH))
await client.start()
try:
captured = {}
async def mock_request(method, params, **kwargs):
captured[method] = params
if method in ("session.create", "session.resume"):
result = {"sessionId": params.get("sessionId") or "session-1"}
callback = kwargs.get("on_response_inline")
if callback is not None:
callback(result)
return result
return {}
client._client.request = mock_request
config = {
"enable_all_tools": True,
"additional_toolsets": ["repos"],
"additional_tools": ["get_issue"],
"enable_insiders_mode": True,
"disable_form_deferral": True,
}
session = await client.create_session(github_mcp_tool_config=config)
await client.resume_session(session.session_id, github_mcp_tool_config=config)
expected = {
"enableAllTools": True,
"additionalToolsets": ["repos"],
"additionalTools": ["get_issue"],
"enableInsidersMode": True,
"disableFormDeferral": True,
}
assert captured["session.create"]["githubMcpToolConfig"] == expected
assert captured["session.resume"]["githubMcpToolConfig"] == expected
finally:
await client.force_stop()
rust/src/types.rs:5941
- The omission assertion only covers the create wire path. To match the “omitted-when-unset” behavior on both create and resume, add the equivalent assertion for
ResumeSessionConfigwhengithub_mcp_tool_configis not set (i.e., ensuregithubMcpToolConfigis absent in the resume wire JSON too).
let (unset_wire, _) = SessionConfig::default()
.into_wire(Some(SessionId::from("github-mcp-unset")))
.expect("default config has no duplicate handlers");
assert!(
serde_json::to_value(&unset_wire)
.unwrap()
.get("githubMcpToolConfig")
.is_none()
);
go/client_test.go:2425
- The “unset is omitted” test only checks
createSessionRequest. Add the same omission check forresumeSessionRequest(with justSessionIDset) to ensuregithubMcpToolConfigalso omits correctly on the resume payload.
t.Run("unset is omitted", func(t *testing.T) {
data, err := json.Marshal(createSessionRequest{})
if err != nil {
t.Fatalf("Failed to marshal: %v", err)
}
var payload map[string]any
if err := json.Unmarshal(data, &payload); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
if _, ok := payload["githubMcpToolConfig"]; ok {
t.Fatal("Expected githubMcpToolConfig to be omitted")
}
})
java/src/test/java/com/github/copilot/SessionRequestBuilderTest.java:980
- This test checks omission when unset for create only. Add an assertion that
buildResumeRequest("session-2", new ResumeSessionConfig())also serializes without"githubMcpToolConfig"to fully cover the resume omission path.
@Test
void githubMcpToolConfigIsMappedAndSerializedForCreateAndResume() throws Exception {
var config = new GitHubMcpToolConfig().setEnableAllTools(true).setAdditionalToolsets(List.of("repos"))
.setAdditionalTools(List.of("get_issue")).setEnableInsidersMode(true).setDisableFormDeferral(true);
var createRequest = SessionRequestBuilder.buildCreateRequest(new SessionConfig().setGitHubMcpToolConfig(config),
"session-1");
var resumeRequest = SessionRequestBuilder.buildResumeRequest("session-1",
new ResumeSessionConfig().setGitHubMcpToolConfig(config));
assertSame(config, createRequest.getGitHubMcpToolConfig());
assertSame(config, resumeRequest.getGitHubMcpToolConfig());
var mapper = JsonRpcClient.getObjectMapper();
assertTrue(mapper.writeValueAsString(createRequest).contains("\"githubMcpToolConfig\""));
assertTrue(mapper.writeValueAsString(resumeRequest).contains("\"githubMcpToolConfig\""));
assertFalse(
mapper.writeValueAsString(SessionRequestBuilder.buildCreateRequest(new SessionConfig(), "session-2"))
.contains("\"githubMcpToolConfig\""));
}
- Files reviewed: 23/23 changed files
- Comments generated: 0 new
- Review effort level: Low
MackinnonBuck
left a comment
There was a problem hiding this comment.
Looks great overall - if we could add some E2E tests for this, that would be awesome.
Exercise the writable built-in GitHub MCP endpoint from Node and Go so regressions that drop githubMcpToolConfig fail end to end. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
10c79b1 to
cdb0b9f
Compare
Replace snapshot-specific replay behavior with a reusable captured-request endpoint and assert the writable GitHub MCP route and headers from Node and Go E2E tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Review details
Suppressed comments (4)
dotnet/src/Types.cs:3040
- The copy constructor assigns collection expressions (
[.. other...]) intoIList<string>?properties, which will typically produce arrays. Arrays implementIList<T>but are fixed-size, so callers modifyingAdditionalToolsets/AdditionalToolsafter cloning can hitNotSupportedException. Prefer copying into a mutableList<string>(or align the property types toIReadOnlyList<string>if immutability is intended).
GitHubMcpToolConfig = other.GitHubMcpToolConfig is null
? null
: new GitHubMcpToolConfig
{
EnableAllTools = other.GitHubMcpToolConfig.EnableAllTools,
AdditionalToolsets = other.GitHubMcpToolConfig.AdditionalToolsets is not null
? [.. other.GitHubMcpToolConfig.AdditionalToolsets]
: null,
AdditionalTools = other.GitHubMcpToolConfig.AdditionalTools is not null
? [.. other.GitHubMcpToolConfig.AdditionalTools]
: null,
EnableInsidersMode = other.GitHubMcpToolConfig.EnableInsidersMode,
DisableFormDeferral = other.GitHubMcpToolConfig.DisableFormDeferral,
};
java/src/main/java/com/github/copilot/SessionRequestBuilder.java:179
- The builder unconditionally calls
setGitHubMcpToolConfig(...)even when the config isnull. This makes omission behavior dependent on ObjectMapper null-handling. To guarantee the field is omitted when unset (and match the stated wire behavior), only call the setter whenconfig.getGitHubMcpToolConfig()is non-null (apply the same pattern inbuildResumeRequest).
if (config.isEnableMcpApps()) {
request.setRequestMcpApps(true);
}
request.setGitHubMcpToolConfig(config.getGitHubMcpToolConfig());
rust/src/types.rs:846
#[serde(default)]is redundant onOption<T>fields because Serde already treats missingOptionfields asNone. Removing thedefaultattribute reduces annotation noise while preserving the same serialization/deserialization behavior (theskip_serializing_ifis sufficient here).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub enable_all_tools: Option<bool>,
/// Additional GitHub MCP toolsets to enable.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub additional_toolsets: Option<Vec<String>>,
/// Additional GitHub MCP tools to enable.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub additional_tools: Option<Vec<String>>,
/// Whether GitHub MCP insiders mode is enabled.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub enable_insiders_mode: Option<bool>,
rust/src/types.rs:851
#[serde(default)]is redundant onOption<T>fields because Serde already treats missingOptionfields asNone. Removing thedefaultattribute reduces annotation noise while preserving the same serialization/deserialization behavior (theskip_serializing_ifis sufficient here).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub disable_form_deferral: Option<bool>,
- Files reviewed: 27/27 changed files
- Comments generated: 0 new
- Review effort level: Lite
There was a problem hiding this comment.
Review details
Suppressed comments (4)
java/src/main/java/com/github/copilot/SessionRequestBuilder.java:179
- The builder unconditionally calls
setGitHubMcpToolConfig(...), even when the value isnull. This makes omission of the field depend on ObjectMapper null-handling configuration and is less robust than explicitly setting the field only when non-null. Consider guarding these assignments (create + resume) with aconfig.getGitHubMcpToolConfig() != nullcheck so the request object stays "unset" when not provided.
if (config.isEnableMcpApps()) {
request.setRequestMcpApps(true);
}
request.setGitHubMcpToolConfig(config.getGitHubMcpToolConfig());
java/src/main/java/com/github/copilot/SessionRequestBuilder.java:304
- The builder unconditionally calls
setGitHubMcpToolConfig(...), even when the value isnull. This makes omission of the field depend on ObjectMapper null-handling configuration and is less robust than explicitly setting the field only when non-null. Consider guarding these assignments (create + resume) with aconfig.getGitHubMcpToolConfig() != nullcheck so the request object stays "unset" when not provided.
if (config.isEnableMcpApps()) {
request.setRequestMcpApps(true);
}
request.setGitHubMcpToolConfig(config.getGitHubMcpToolConfig());
go/internal/e2e/testharness/proxy.go:213
GetRequests()decodes the response body without checkingresp.StatusCode. If the proxy returns a non-200 (or an HTML/error payload), decoding will fail with a low-signal error. Consider checking forresp.StatusCode == http.StatusOKand returning a clearer error (ideally including the status and a short response body excerpt).
// GetRequests retrieves all captured outbound HTTP requests from the proxy.
func (p *CapiProxy) GetRequests() ([]CapturedRequest, error) {
p.mu.Lock()
url := p.proxyURL
p.mu.Unlock()
if url == "" {
return nil, fmt.Errorf("proxy not started")
}
resp, err := http.Get(url + "/requests")
if err != nil {
return nil, fmt.Errorf("failed to get requests: %w", err)
}
defer resp.Body.Close()
var requests []CapturedRequest
if err := json.NewDecoder(resp.Body).Decode(&requests); err != nil {
return nil, fmt.Errorf("failed to decode requests: %w", err)
}
return requests, nil
}
nodejs/test/e2e/harness/CapiProxy.ts:128
getRequests()assumes the response is always JSON and does not verifyresponse.ok. When the proxy is stopped or returns an error, this will throw a less actionable JSON parsing error. Consider checkingresponse.ok(and possibly content-type) and throwing a clearer error that includesresponse.status(and optionally response text).
async getRequests(): Promise<CapturedRequest[]> {
const response = await fetch(`${this.proxyUrl}/requests`, { method: "GET" });
return await response.json();
}
- Files reviewed: 30/30 changed files
- Comments generated: 0 new
- Review effort level: Lite
MRayermannMSFT
left a comment
There was a problem hiding this comment.
E2E tests were added as requested by @MackinnonBuck . 👍
* sdk: Expose githubMcpToolConfig across languages Adds the `githubMcpToolConfig` session option to `session.create` and `session.resume` in all six SDKs, forwarding the built-in GitHub MCP server settings the runtime already accepts: `enableAllTools`, `additionalToolsets`, `additionalTools`, `enableInsidersMode`, and the new `disableFormDeferral`. `disableFormDeferral` lets autonomous SDK workflows opt out of MCP App form deferral, so form-backed GitHub write tools execute directly instead of returning an awaiting-form stub. It requires MCP Apps to be enabled for the session. The option is omitted from the wire payload entirely when unset, so existing consumers see no change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * python: apply ruff formatting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * java: apply spotless formatting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review feedback - node: omit githubMcpToolConfig for null as well as undefined - python: document github_mcp_tool_config on create_session/resume_session - go: assert json.Unmarshal succeeds in the omitted-when-unset subtest - java: call the non-deprecated buildCreateRequest(config, sessionId) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: add GitHub MCP tool config E2E coverage Exercise the writable built-in GitHub MCP endpoint from Node and Go so regressions that drop githubMcpToolConfig fail end to end. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: capture GitHub MCP requests generically Replace snapshot-specific replay behavior with a reusable captured-request endpoint and assert the writable GitHub MCP route and headers from Node and Go E2E tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sdk: Expose githubMcpToolConfig across languages Adds the `githubMcpToolConfig` session option to `session.create` and `session.resume` in all six SDKs, forwarding the built-in GitHub MCP server settings the runtime already accepts: `enableAllTools`, `additionalToolsets`, `additionalTools`, `enableInsidersMode`, and the new `disableFormDeferral`. `disableFormDeferral` lets autonomous SDK workflows opt out of MCP App form deferral, so form-backed GitHub write tools execute directly instead of returning an awaiting-form stub. It requires MCP Apps to be enabled for the session. The option is omitted from the wire payload entirely when unset, so existing consumers see no change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * python: apply ruff formatting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * java: apply spotless formatting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review feedback - node: omit githubMcpToolConfig for null as well as undefined - python: document github_mcp_tool_config on create_session/resume_session - go: assert json.Unmarshal succeeds in the omitted-when-unset subtest - java: call the non-deprecated buildCreateRequest(config, sessionId) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: add GitHub MCP tool config E2E coverage Exercise the writable built-in GitHub MCP endpoint from Node and Go so regressions that drop githubMcpToolConfig fail end to end. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: capture GitHub MCP requests generically Replace snapshot-specific replay behavior with a reusable captured-request endpoint and assert the writable GitHub MCP route and headers from Node and Go E2E tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Updated [GitHub.Copilot.SDK](https://github.com/github/copilot-sdk) from
1.0.2 to 1.0.13.
<details>
<summary>Release notes</summary>
_Sourced from [GitHub.Copilot.SDK's
releases](https://github.com/github/copilot-sdk/releases)._
## 1.0.13
### Feature: cancellation for host-owned external tools
Host-owned external tool callbacks are now cancelled when their runtime
request completes or their SDK session terminates. The cancellation
primitive is idiomatic per SDK: .NET passes a request token to
`AIFunction`, Node.js exposes `ToolInvocation.signal`, Go cancels
`ToolInvocation.TraceContext`, Java cancels the returned
`CompletableFuture`, Python cancels the handler task, and Rust drops the
handler future. Go handlers that retain `TraceContext` for background
work must derive a separate lifetime because the invocation context is
cancelled when the request ends.
### Feature: declare application identity with client info
Client options now accept optional client info (application name and
version, integration name and version) across all six SDKs, exposed
idiomatically per language (`clientInfo` in Node.js, `client_info` in
Python and Rust, `ClientInfo` in Go and .NET, `setClientInfo` in Java).
When set, the SDK forwards it on the `server.connect` handshake so the
telemetry the runtime emits on the connection is attributed to the
application and its Copilot integration instead of the runtime's own
build. All fields are optional, and leaving client info unset keeps the
runtime's default attribution. See [Client
info](./docs/features/client-info.md).
### Feature: Node Agent Factories pagination and run notifications
The experimental Node.js Agent Factories convenience API now supports
paginated run history. Existing `session.factory.listRuns()` calls still
return the runs array, while calls with `afterSeq`, `beforeSeq`, or
`limit` return the full page with cursor and truncation metadata.
Factory `run` and `resume` options now accept `notifyOnComplete` and
`logPhaseNames`. The SDK forwards these options to the Copilot CLI for
new and resumed runs.
### Feature: selectable `ask_user` session behavior
Session create and cold resume now accept a language-specific
`askUserVariant` option with `legacy` and `elicitation` values. SDK
sessions retain the legacy question-and-answer tool by default. Select
`elicitation` and provide an elicitation handler to expose the
structured form-based `ask_user` tool.
### Feature: rotating session-scoped GitHub credentials
All six SDKs can now acquire short-lived GitHub credentials through a
session-scoped callback. The SDK registers the callback before session
create or resume, maps `initial` and `refresh` requests to the owning
session, and removes registrations on rollback, replacement, session
close, and client close. Static per-session `gitHubToken` credentials
remain supported and are mutually exclusive with the callback.
Token responses use the shared tagged token/cancelled shape and require
`expiresIn`, expressed as the positive number of seconds remaining when
the callback completes. See
[github/copilot-agent-runtime#16381](https://github.com/github/copilot-agent-runtime/pull/16381)
for the runtime credential-authority implementation.
Initial acquisition occurs during create or resume; cancellation,
callback errors, and invalid credentials reject that operation instead
of falling back to ambient authentication. Idle sessions refresh only
before their next credential-consuming operation.
### Feature: extensions can request sensitive environment variables
Copilot CLI extensions can now ask for named sensitive environment
variables when they join a session. `joinSession()` accepts a
`requestedEnvironmentVariables` option listing the variable names the
extension needs. The CLI shows a permission prompt naming the extension
and the exact variables requested. On approval, only those variables
reach that extension and their values are written into the extension
process's `process.env` before `joinSession()` resolves. On denial,
`joinSession()` rejects, the extension does not load, and its tools
never reach the model.
An approval is remembered against the exact set of names the user saw,
so an extension that later asks for one more variable prompts again.
Names that are unset, or that the CLI does not filter from extensions,
are not prompted for. This is the client half of the feature; it
requires a Copilot CLI that supports extension environment access, and
older CLIs ignore the request and grant nothing.
```ts
import { joinSession } from "@github/copilot-sdk/extension";
const session = await joinSession({
requestedEnvironmentVariables: ["GITHUB_TOKEN"],
});
const token = process.env.GITHUB_TOKEN;
```
### Feature: early session-event subscription (Rust)
The Rust SDK can now observe every event routed to a session, starting
with that session's very first routed event. `Client::prepare_session`
and `Client::prepare_resume_session` return an inert `PreparedSession`
that owns the session's event channel, so a subscription can be
installed *before* any protocol activity begins:
```rust
let prepared = client.prepare_session(
SessionConfig::default().with_event_buffer_capacity(2048),
)?;
let mut events = prepared.subscribe();
... (truncated)
## 1.0.13-preview.4
### Feature: rewind support across all SDKs
Sessions can now opt into file-change tracking and rewind conversation history and tracked file changes to any prior checkpoint. Enable file tracking when creating a session, then use `rewind` to roll back. ([#2321](https://github.com/github/copilot-sdk/pull/2321))
```ts
const session = await client.createSession({ enableFileChangeTracking:
true });
// ...later
const points = await session.rpc.rewind.list();
await session.rpc.rewind.rewind({ rewindTarget: points[0].id });
```
```cs
var session = await client.CreateSessionAsync(new SessionOptions {
EnableFileChangeTracking = true });
var points = await session.Rpc.Rewind.ListAsync();
await session.Rpc.Rewind.RewindAsync(new RewindRequest { RewindTarget =
points[0].Id });
```
```python
session = await client.create_session(enable_file_change_tracking=True)
points = await session.rpc.rewind.list()
await session.rpc.rewind.rewind(rewind_target=points[0].id)
```
### Feature: session-scoped GitHub token providers
Sessions now support expiry-aware GitHub token callbacks in addition to static tokens. The SDK handles refresh requests from the runtime, so extensions always receive fresh credentials. ([#2412](https://github.com/github/copilot-sdk/pull/2412))
```ts
const session = await client.createSession({
gitHubTokenProvider: async ({ host, reason }) => ({ token: await
fetchToken(host) })
});
```
```cs
var session = await client.CreateSessionAsync(new SessionOptions {
GitHubTokenProvider = async (req, ct) =>
new GitHubTokenResult { Token = await FetchTokenAsync(req.Host) }
});
```
```go
session, _ := client.CreateSession(ctx, copilot.SessionOptions{
GitHubTokenProvider: func(ctx context.Context, req
copilot.TokenProviderRequest) (copilot.TokenProviderResult, error) {
return copilot.TokenProviderResult{Token: fetchToken(req.Host)}, nil
},
})
```
### Feature: Java in-process native runtime on all platforms
... (truncated)
## 1.0.13-preview.3
### Feature: rewind support across all SDKs
Sessions can now opt into file-change tracking and conversation rewind. When `enableFileChangeTracking` is enabled, the session records which files were changed during a conversation turn. You can then list pending rewind points, preview changes, and rewind the conversation history together with any tracked file modifications. ([#2321](https://github.com/github/copilot-sdk/pull/2321))
```ts
const session = await client.createSession({ enableFileChangeTracking:
true });
const points = await session.rpc.rewind.listPendingRewindPoints();
await session.rpc.rewind.rewind({ id: points[0].id });
```
```cs
var session = await client.CreateSessionAsync(new SessionOptions {
EnableFileChangeTracking = true });
var points = await session.Rpc.Rewind.ListPendingRewindPointsAsync();
await session.Rpc.Rewind.RewindAsync(new RewindRequest { Id =
points[0].Id });
```
```python
session = await client.create_session(enable_file_change_tracking=True)
points = await session.rpc.rewind.list_pending_rewind_points()
await session.rpc.rewind.rewind(id=points[0].id)
```
### Feature: session-scoped GitHub token providers
Sessions now support a dynamic, expiry-aware GitHub token callback as an alternative to a static `gitHubToken`. The SDK maps each host request (with host, session, and reason context) to your callback, handling concurrent-session isolation automatically. ([#2412](https://github.com/github/copilot-sdk/pull/2412))
```ts
const session = await client.createSession({
gitHubTokenProvider: async ({ host }) => ({ token: await getToken(host),
expiresIn: 3600 }),
});
```
```cs
var session = await client.CreateSessionAsync(new SessionOptions
{
GitHubTokenProvider = async (req, ct) =>
new GitHubToken { Token = await GetTokenAsync(req.Host, ct), ExpiresIn =
TimeSpan.FromHours(1) }
});
```
```go
session, err := client.CreateSession(ctx, copilot.SessionOptions{
GitHubTokenProvider: func(ctx context.Context, req
copilot.GitHubTokenRequest) (copilot.GitHubToken, error) {
return copilot.GitHubToken{Token: getToken(req.Host), ExpiresIn: 3600},
nil
},
})
```
### Feature: built-in plugin directory support
... (truncated)
## 1.0.13-preview.2
### Feature: rewind support across all SDKs
Sessions can now opt in to file-change tracking so that rewinding restores both conversation history and the files that were modified. Enable it with the new `enableFileChangeTracking` session option. ([#2321](https://github.com/github/copilot-sdk/pull/2321))
```ts
const session = await client.startSession({ enableFileChangeTracking:
true });
```
```cs
var session = await client.StartSessionAsync(new SessionOptions {
EnableFileChangeTracking = true });
```
```python
session = await client.start_session(enable_file_change_tracking=True)
```
```go
session, _ := client.StartSession(ctx,
&copilot.SessionOptions{EnableFileChangeTracking: true})
```
```java
Session session = client.startSession(new
SessionOptions().setEnableFileChangeTracking(true)).get();
```
```rust
let session = client.start_session(SessionOptions {
enable_file_change_tracking: Some(true), ..Default::default() }).await?;
```
### Feature: session-scoped GitHub token providers
Applications can now supply a dynamic GitHub token callback instead of a static `gitHubToken` string. The runtime calls the callback before each token use, so short-lived tokens stay fresh across long-running sessions. ([#2412](https://github.com/github/copilot-sdk/pull/2412))
```ts
const session = await client.startSession({
gitHubTokenProvider: async ({ host, reason }) => ({ token: await
fetchToken(host) })
});
```
```cs
var session = await client.StartSessionAsync(new SessionOptions
{
GitHubTokenProvider = async (request, ct) => new GitHubTokenResult(await
FetchTokenAsync(request.Host))
});
```
```python
async def token_provider(request):
return GitHubTokenResult(token=await fetch_token(request.host))
session = await
client.start_session(github_token_provider=token_provider)
... (truncated)
## 1.0.13-preview.1
### Feature: `ClientMode::Empty` now disables built-in skills by default
`ClientMode::Empty` now applies deny-by-default isolation to
runtime-bundled skills in addition to other built-in capabilities.
`includedBuiltinSkills` defaults to `[]` in Empty mode; pass an explicit
allowlist to re-enable specific skills. This behavior is consistent
across all six SDKs.
([#2410](https://github.com/github/copilot-sdk/pull/2410))
```ts
// Node — empty mode: built-in skills excluded by default
const session = await client.createSession({ mode: ClientMode.Empty });
// opt back in:
const session = await client.createSession({ mode: ClientMode.Empty, includedBuiltinSkills: ["edit"] });
```
```cs
// C#
var session = await client.CreateSessionAsync(new SessionOptions { Mode = ClientMode.Empty });
// opt back in:
var session = await client.CreateSessionAsync(new SessionOptions { Mode = ClientMode.Empty, IncludedBuiltinSkills = ["edit"] });
```
```python
# Python
session = await client.create_session(mode=ClientMode.EMPTY)
# opt back in:
session = await client.create_session(mode=ClientMode.EMPTY, included_builtin_skills=["edit"])
```
```go
// Go
session, err := client.CreateSession(ctx, copilot.SessionOptions{Mode: copilot.ClientModeEmpty})
// opt back in:
session, err := client.CreateSession(ctx, copilot.SessionOptions{Mode: copilot.ClientModeEmpty, IncludedBuiltinSkills: []string{"edit"}})
```
> Generated by [Release Changelog
Generator](https://github.com/github/copilot-sdk/actions/runs/33008374598)
· sonnet46 28.6 AIC · ⌖ 4.12 AIC · ⊞ 8.1K
<!-- gh-aw-agentic-workflow: Release Changelog Generator, engine:
copilot, version: 1.0.73, model: claude-sonnet-4.6, id: 33008374598,
workflow_id: release-changelog, run:
https://github.com/github/copilot-sdk/actions/runs/33008374598 -->
## 1.0.13-preview.0
### Feature: rewind support across all SDKs
Sessions can now opt into file-change tracking and rewind conversation
history along with tracked file changes. Enable the new
`enableFileChangeTracking` session option to allow calling rewind later.
([#2321](https://github.com/github/copilot-sdk/pull/2321))
```ts
const session = await client.createSession({ enableFileChangeTracking: true });
// later:
await session.rpc.conversation.rewind({ ...rewindPoint });
```
```cs
var session = await client.CreateSessionAsync(new SessionOptions { EnableFileChangeTracking = true });
```
```python
session = await client.create_session(enable_file_change_tracking=True)
```
```go
session, err := client.CreateSession(ctx, copilot.SessionOptions{EnableFileChangeTracking: true})
```
### Feature: Java in-process runtime (experimental)
The Java SDK now ships platform-native classifier JARs that load the
Copilot runtime directly in-process via JNA — no separate CLI child
process required. Currently available for linux-x64, Windows x64, and
Apple Silicon macOS.
([#2301](https://github.com/github/copilot-sdk/pull/2301),
[#2393](https://github.com/github/copilot-sdk/pull/2393),
[#2402](https://github.com/github/copilot-sdk/pull/2402))
```java
CopilotClientOptions options = new CopilotClientOptions()
.setConnection(RuntimeConnection.forInProcess());
CopilotClient client = new CopilotClient(options);
client.start().get();
```
### Feature: permission decision context forwarding
Permission handlers can now attach `decisionContext` so the runtime can
attribute whether a decision came from a person, host policy, or an
automated recommendation. This is additive for Node, Python, Go, .NET,
and Java. Rust clients that construct or match
`PermissionResult::Decision` directly must migrate to the new struct
variant. ([#2294](https://github.com/github/copilot-sdk/pull/2294))
- TypeScript: `createAttributedPermissionResult(result, context)`
- Python: `copilot.create_attributed_permission_result(result, context)`
- Go: `copilot.NewAttributedPermissionResult(result, context)`
- C#: set `DecisionContext` on the permission decision
- Java:
`PermissionRequestResult.approveOnce().setDecisionContext(context)`
- Rust: `PermissionResult::approve_once().with_context(context)`
### Feature: built-in plugin directory support
Applications can now register a set of host-bundled plugin directories
that are trusted unconditionally and loaded before any user session
begins. ([#2330](https://github.com/github/copilot-sdk/pull/2330))
### Feature: extensions can request sensitive environment variables
(Node)
... (truncated)
## 1.0.12-preview.0
### Feature: rewind support across all SDKs
Sessions now support rewinding conversation history and tracked file
changes. Enable file-change tracking when creating a session, then
rewind to a previous checkpoint to discard later turns and restore file
state. ([#2321](https://github.com/github/copilot-sdk/pull/2321))
```ts
const session = await client.createSession({ enableFileChangeTracking: true });
const rewindPoints = await session.rpc.rewind.listRewindPoints();
await session.rpc.rewind.rewind({ rewindPointId: rewindPoints[0].rewindPointId });
```
```python
session = await client.create_session(enable_file_change_tracking=True)
rewind_points = await session.rpc.rewind.list_rewind_points()
await session.rpc.rewind.rewind(rewind_point_id=rewind_points[0].rewind_point_id)
```
```go
session, _ := client.CreateSession(ctx, &copilot.SessionOptions{EnableFileChangeTracking: true})
points, _ := session.RPC.Rewind.ListRewindPoints(ctx)
_ = session.RPC.Rewind.Rewind(ctx, &copilot.RewindRequest{RewindPointId: points[0].RewindPointId})
```
```cs
var session = await client.CreateSessionAsync(new SessionOptions { EnableFileChangeTracking = true });
var points = await session.Rpc.Rewind.ListRewindPointsAsync();
await session.Rpc.Rewind.RewindAsync(new RewindRequest { RewindPointId = points[0].RewindPointId });
```
```java
SessionOptions options = new SessionOptions().setEnableFileChangeTracking(true);
var session = client.createSession(options).get();
var points = session.getRpc().getRewind().listRewindPoints().get();
session.getRpc().getRewind().rewind(new RewindRequest().setRewindPointId(points.get(0).getRewindPointId())).get();
```
```rust
let session = client.create_session(SessionOptions { enable_file_change_tracking: Some(true), ..Default::default() }).await?;
let points = session.rpc.rewind.list_rewind_points().await?;
session.rpc.rewind.rewind(RewindRequest { rewind_point_id: points[0].rewind_point_id.clone() }).await?;
```
### Feature: Java in-process Copilot CLI (linux-x64)
The Java SDK now supports an **in-process connection mode** on linux-x64
that loads the Copilot runtime as a native library via JNA — no separate
CLI child process required. Add the `copilot-sdk-java-runtime`
classifier JAR for your platform alongside the core SDK JAR.
([#2301](https://github.com/github/copilot-sdk/pull/2301))
```java
CopilotClientOptions options = new CopilotClientOptions()
.setConnection(RuntimeConnection.forInProcess());
CopilotClient client = new CopilotClient(options);
client.start().get();
... (truncated)
## 1.0.11
## What's Changed
* docs: correct the Python Customize Mode section IDs and action list by @examon in https://github.com/github/copilot-sdk/pull/2264
* Add `history.clearContext` and `Tool.isTerminal` across all SDKs by @examon in https://github.com/github/copilot-sdk/pull/2129
* fix(java): preserve MCP permission extension data by @rinceyuan in https://github.com/github/copilot-sdk/pull/2276
* Update @github/copilot to 1.0.79-5 by @github-actions[bot] in https://github.com/github/copilot-sdk/pull/2282
* Update @github/copilot to 1.0.79-6 by @github-actions[bot] in https://github.com/github/copilot-sdk/pull/2287
* SDK, Runtime: Recover JSON-RPC frames containing unpaired UTF-16 surrogates by @Chuxel in https://github.com/github/copilot-sdk/pull/2283
* Add managed permission settings to session startup by @joshspicer in https://github.com/github/copilot-sdk/pull/2139
* Skip untyped internal properties in C# codegen by @stephentoub in https://github.com/github/copilot-sdk/pull/2298
* Update @github/copilot to 1.0.79-9 by @github-actions[bot] in https://github.com/github/copilot-sdk/pull/2299
* Update @github/copilot to 1.0.79 by @github-actions[bot] in https://github.com/github/copilot-sdk/pull/2306
* Consolidate SDK GitHub releases by @stephentoub in https://github.com/github/copilot-sdk/pull/2305
* [SDK/Factories] Make The Agent Factories Surface Match The Wire Contract by @MRayermannMSFT in https://github.com/github/copilot-sdk/pull/2309
* Add rewind support across all SDKs by @stephentoub in https://github.com/github/copilot-sdk/pull/2321
* [java] Add linux-x64 implementation of in process Copilot CLI by @edburns in https://github.com/github/copilot-sdk/pull/2301
* [Java] Fix java publish to maven by @edburns in https://github.com/github/copilot-sdk/pull/2324
* test(java): skip linux runtime tests on other platforms by @edburns in https://github.com/github/copilot-sdk/pull/2325
* Fix codegen for internal runtime schemas by @stephentoub in https://github.com/github/copilot-sdk/pull/2331
* [SDK/Factories] Add argsSchema To The Factory Authoring Surface by @MRayermannMSFT in https://github.com/github/copilot-sdk/pull/2315
* Add built-in plugin directory support by @lutzroeder in https://github.com/github/copilot-sdk/pull/2330
* sdk: Forward decisionContext on permission replies across languages by @aymenfurter in https://github.com/github/copilot-sdk/pull/2294
## New Contributors
* @Chuxel made their first contribution in https://github.com/github/copilot-sdk/pull/2283
* @lutzroeder made their first contribution in https://github.com/github/copilot-sdk/pull/2330
* @aymenfurter made their first contribution in https://github.com/github/copilot-sdk/pull/2294
**Full Changelog**: https://github.com/github/copilot-sdk/compare/v1.0.9...v1.0.11
## 1.0.11-preview.2
### Feature: rewind support across all SDKs
The Copilot runtime supports rewinding conversation history and tracked file changes. SDKs can now opt into file-change tracking via a new `enableFileChangeTracking` session option, and then use rewind to restore the session to an earlier checkpoint. ([#2321](https://github.com/github/copilot-sdk/pull/2321))
```ts
// TypeScript
const session = await client.startSession({ enableFileChangeTracking:
true });
const rewindPoints = await session.rpc.session.listRewindPoints();
await session.rpc.session.rewind({ rewindPointId: rewindPoints[0].id });
```
```cs
// C#
var session = await client.StartSessionAsync(new SessionOptions {
EnableFileChangeTracking = true });
var points = await session.Rpc.Session.ListRewindPointsAsync();
await session.Rpc.Session.RewindAsync(new RewindParams { RewindPointId =
points[0].Id });
```
```python
# Python
session = await client.start_session(enable_file_change_tracking=True)
points = await session.rpc.session.list_rewind_points()
await session.rpc.session.rewind(rewind_point_id=points[0].id)
```
```go
// Go
session, _ := client.StartSession(ctx,
&sdk.SessionOptions{EnableFileChangeTracking: true})
points, _ := session.RPC.Session.ListRewindPoints(ctx)
session.RPC.Session.Rewind(ctx, &sdk.RewindParams{RewindPointId:
points[0].Id})
```
```java
// Java
SessionOptions options = new
SessionOptions().setEnableFileChangeTracking(true);
CopilotSession session = client.startSession(options).get();
List<RewindPoint> points =
session.getRpc().getSession().listRewindPoints().get();
session.getRpc().getSession().rewind(new
RewindParams().setRewindPointId(points.get(0).getId())).get();
```
```rust
// Rust
let session = client.start_session(SessionOptions {
enable_file_change_tracking: Some(true), ..Default::default() }).await?;
let points = session.rpc().session().list_rewind_points().await?;
session.rpc().session().rewind(&RewindParams { rewind_point_id:
points[0].id.clone() }).await?;
```
### Feature: Java in-process runtime for Linux x64
The Java SDK now supports loading the Copilot runtime as a native library (via JNA) directly in-process on Linux x64, eliminating the need for a separate CLI child process. This mirrors the in-process mode already available in .NET and Rust. The feature is marked `@CopilotExperimental`. ([#2301](https://github.com/github/copilot-sdk/pull/2301))
... (truncated)
## 1.0.10-preview.0
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track releases of the reference implementation. For each release of the reference implementation, there may follow a corresponding release of this implementation with the same number as the reference implementation. Release identifiers of the reference implementation are in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding maven version for the release will be `Maj.Min.Micro-java.N`, where `Maj`, `Min` and `Micro` are the corresponding numbers for the reference implementation release, and `N` is a monotonically increasing sequence number starting with 0 for each release. See the corresponding architectural decision record for more information in the `docs/adr` directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) · [Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.10-preview.0</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.10-preview.0")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.10-preview.0'
```
### Feature: managed permission settings at session startup
Applications can now supply host-managed permission settings at session startup via `SessionConfig.setManagedSettings()`. The runtime validates and composes this policy with self-fetched and device policy. Re-supply on resume as it is not persisted. ([#2139](https://github.com/github/copilot-sdk/pull/2139))
```java
SessionConfig config = new SessionConfig()
.setManagedSettings(new ManagedSettings()
.setPermissions(new ManagedSettingsPermissions()
.setFilesystem(PermissionLevel.READ_WRITE)));
```
### Feature: `userPromptTransformed` hook
A new `onUserPromptTransformed` hook on `SessionHooks` lets applications observe (and optionally modify) the prompt text after the runtime transforms it. ([#2254](https://github.com/github/copilot-sdk/pull/2254))
```java
session.getHooks().setOnUserPromptTransformed((input, ctx) -> {
System.out.println("Transformed prompt: " + input.getPrompt());
return CompletableFuture.completedFuture(null);
});
```
... (truncated)
## 1.0.9
## What's Changed
* dotnet: update README attachment examples to current API (fixes #2196) by @HindzStark in https://github.com/github/copilot-sdk/pull/2208
* Support reasoningEffort: max by @Dharshika-11 in https://github.com/github/copilot-sdk/pull/2228
* Stop sendAndWait from emitting an unhandled rejection by @thejesh23 in https://github.com/github/copilot-sdk/pull/2206
* docs: clarify working directory defaults across SDKs by @xianjianlf2 in https://github.com/github/copilot-sdk/pull/2201
* Speed up Rust E2E tests with shared clients by @SteveSandersonMS in https://github.com/github/copilot-sdk/pull/2250
* build(deps-dev): bump ip-address from 10.2.0 to 10.4.0 in /test/harness by @dependabot[bot] in https://github.com/github/copilot-sdk/pull/2245
* build(deps-dev): bump the npm_and_yarn group across 1 directory with 2 updates by @dependabot[bot] in https://github.com/github/copilot-sdk/pull/2244
* build(deps-dev): bump postcss from 8.5.15 to 8.5.25 in /nodejs by @dependabot[bot] in https://github.com/github/copilot-sdk/pull/2243
* build(deps-dev): bump fast-uri from 3.1.4 to 3.1.5 in /test/harness by @dependabot[bot] in https://github.com/github/copilot-sdk/pull/2242
* docs: move SDK development guidance to local READMEs by @SteveSandersonMS in https://github.com/github/copilot-sdk/pull/2253
* build(deps-dev): bump postcss from 8.5.15 to 8.5.25 in /test/harness by @dependabot[bot] in https://github.com/github/copilot-sdk/pull/2252
* docs: replace removed `session.idle.backgroundTasks` field with the current `aborted` field by @examon in https://github.com/github/copilot-sdk/pull/2232
* Parallelize Python and Windows .NET CI tests by @SteveSandersonMS in https://github.com/github/copilot-sdk/pull/2251
* Fix active Node and Rust replay E2E flakes by @roji in https://github.com/github/copilot-sdk/pull/2186
* Add userPromptTransformed hook to all SDKs by @SteveSandersonMS in https://github.com/github/copilot-sdk/pull/2254
* fix: Java README version stuck at 1.0.5-01; release sed regex can't match numeric qualifiers by @rinceyuan in https://github.com/github/copilot-sdk/pull/2226
* docs: update Go and Rust API reference links by @scottaddie in https://github.com/github/copilot-sdk/pull/2266
* docs: add citations guide by @patniko in https://github.com/github/copilot-sdk/pull/2267
* sdk: Expose disabled MCP servers across languages by @connor4312 in https://github.com/github/copilot-sdk/pull/2260
## New Contributors
* @HindzStark made their first contribution in https://github.com/github/copilot-sdk/pull/2208
* @Dharshika-11 made their first contribution in https://github.com/github/copilot-sdk/pull/2228
* @thejesh23 made their first contribution in https://github.com/github/copilot-sdk/pull/2206
* @xianjianlf2 made their first contribution in https://github.com/github/copilot-sdk/pull/2201
**Full Changelog**: https://github.com/github/copilot-sdk/compare/rust/v1.0.9-preview.3...rust/v1.0.9
## 1.0.9-preview.3
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track releases of the reference implementation. For each release of the reference implementation, there may follow a corresponding release of this implementation with the same number as the reference implementation. Release identifiers of the reference implementation are in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding maven version for the release will be `Maj.Min.Micro-java.N`, where `Maj`, `Min` and `Micro` are the corresponding numbers for the reference implementation release, and `N` is a monotonically increasing sequence number starting with 0 for each release. See the corresponding architectural decision record for more information in the `docs/adr` directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) · [Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.9-preview.3</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.9-preview.3")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.9-preview.3'
```
### Feature: managed approval requirement on permission requests
Permission handlers can now inspect `request.getManagedApprovalRequired()` to determine when a human decision is required. `PermissionHandler.APPROVE_ALL` now completes exceptionally when managed settings are enabled, preventing auto-approval of requests that require explicit human review. ([#2080](https://github.com/github/copilot-sdk/pull/2080))
```java
PermissionHandler handler = (request, invocation) -> {
if (Boolean.TRUE.equals(request.getManagedApprovalRequired())) {
return requestHumanApproval(request);
}
return CompletableFuture.completedFuture(
new
PermissionRequestResult().setKind(PermissionRequestResultKind.APPROVED));
};
```
### Feature: GitHub MCP tool configuration
`SessionConfig` and `ResumeSessionConfig` now expose a `GitHubMcpToolConfig` option to configure the built-in GitHub MCP server, including selectively enabling tools and disabling form deferral. ([#2112](https://github.com/github/copilot-sdk/pull/2112))
```java
var config = new SessionConfig()
.setGitHubMcpToolConfig(new GitHubMcpToolConfig()
.setDisableFormDeferral(true));
... (truncated)
## 1.0.9-preview.2
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.9-preview.2</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.9-preview.2")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.9-preview.2'
```
## Changes
- improvement: re-enable `ModeHandlers` exit_plan_mode E2E test
assertions ([#2032](https://github.com/github/copilot-sdk/pull/2032))
- improvement: update E2E test fixtures to use `gpt-5.4` for reasoning
effort tests ([#2181](https://github.com/github/copilot-sdk/pull/2181))
### New contributors
- `@arimu1` made their first contribution in
[#2032](https://github.com/github/copilot-sdk/pull/2032)
> Generated by [Release Changelog
Generator](https://github.com/github/copilot-sdk/actions/runs/30652758765)
· sonnet46 36.1 AIC · ⌖ 6.98 AIC · ⊞ 8.6K
<!-- gh-aw-agentic-workflow: Release Changelog Generator, engine:
copilot, version: 1.0.73, model: claude-sonnet-4.6, id: 30652758765,
workflow_id: release-changelog, run:
https://github.com/github/copilot-sdk/actions/runs/30652758765 -->
## 1.0.9-preview.1
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.9-preview.1</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.9-preview.1")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.9-preview.1'
```
### Other changes
- improvement: document MCP tool filter naming convention
(`<server-key>-<tool-name>`) for `setAvailableTools`,
`setExcludedTools`, and agent config in README
([#2101](https://github.com/github/copilot-sdk/pull/2101))
- improvement: fix `EnableConfigDiscovery` Javadoc to accurately
describe agent discovery behavior — it gates `.github/agents/`
discovery, independent of `SkipCustomInstructions`
([#2019](https://github.com/github/copilot-sdk/pull/2019))
### New contributors
- `@syedkazmi14` made their first contribution in
[#2101](https://github.com/github/copilot-sdk/pull/2101)
- `@smz202000` made their first contribution in
[#2019](https://github.com/github/copilot-sdk/pull/2019)
> Generated by [Release Changelog
Generator](https://github.com/github/copilot-sdk/actions/runs/30575555193)
· sonnet46 47 AIC · ⌖ 5.17 AIC · ⊞ 8.6K
<!-- gh-aw-agentic-workflow: Release Changelog Generator, engine:
copilot, version: 1.0.73, model: claude-sonnet-4.6, id: 30575555193,
workflow_id: release-changelog, run:
https://github.com/github/copilot-sdk/actions/runs/30575555193 -->
## 1.0.9-preview.0
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.9-preview.0</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.9-preview.0")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.9-preview.0'
```
---
### Feature: `AgentStop` lifecycle hook
The `agentStop` hook lets your application intercept the natural end of
an agent turn and optionally request the agent to continue. Return `{
decision: "block", reason: "..." }` to queue a follow-up prompt; return
nothing to let the agent stop normally.
([#2054](https://github.com/github/copilot-sdk/pull/2054))
```java
SessionHooks hooks = new SessionHooks()
.setOnAgentStop((input, invocation) -> {
if (!input.isStopHookActive() && needsValidation()) {
return CompletableFuture.completedFuture(
new AgentStopHookOutput()
.setDecision("block")
.setReason("Run final validation and fix any failures.")
);
}
return CompletableFuture.completedFuture(null);
});
```
### Feature: custom JSON schema for `@CopilotToolParam`
... (truncated)
## 1.0.8
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.8</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.8")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.8'
```
### Feature: per-agent reasoning effort
`CustomAgentConfig` now accepts an optional `reasoningEffort` field that
controls the reasoning intensity for a specific sub-agent. Omitting it
inherits the session-level effort; omitting it at both levels leaves the
choice to the backend.
([#1981](https://github.com/github/copilot-sdk/pull/1981))
```java
CustomAgentConfig agent = new CustomAgentConfig()
.setName("coder")
.setReasoningEffort("high");
```
### Other changes
- improvement: **[Java]** strongly type the internal `expAssignments`
session-config field with `CopilotExpAssignmentResponse` to match the
runtime wire contract
([#2033](https://github.com/github/copilot-sdk/pull/2033))
> [!WARNING]
> <details>
> <summary>Firewall blocked 1 domain</summary>
>
> The following domain was blocked by the firewall during workflow
execution:
>
> - `awmgmcpg`
>> To allow these domains, add them to the `network.allowed` list in
your workflow frontmatter:
... (truncated)
## 1.0.8-preview.0
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.8-preview.0</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.8-preview.0")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.8-preview.0'
```
---
### Feature: per-agent reasoning effort
You can now set a `reasoningEffort` override on individual custom agents
within a session. When omitted, no per-agent override is sent and the
backend chooses its default.
([#1981](https://github.com/github/copilot-sdk/pull/1981))
```java
CustomAgentConfig agent = new CustomAgentConfig()
.setName("my-agent")
.setModel("claude-sonnet-4-5")
.setReasoningEffort("high");
```
### Other changes
- improvement: strongly type internal `expAssignments` session config
field with `CopilotExpAssignmentResponse`
([#2033](https://github.com/github/copilot-sdk/pull/2033))
> [!WARNING]
> <details>
> <summary>Firewall blocked 1 domain</summary>
>
> The following domain was blocked by the firewall during workflow
execution:
... (truncated)
## 1.0.7
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.7</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.7")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.7'
```
### Feature: opaque metadata passthrough for tool definitions
Hosts can now attach namespaced, opaque metadata to tool definitions and
have it forwarded verbatim over the `session.create`/`resumeSession`
wire call. Use `ToolDefinition.createWithMetadata(...)` or the fluent
`.metadata(Map)` builder, or express shallow flag maps via
`@CopilotTool.MetadataEntry` annotations.
([#1864](https://github.com/github/copilot-sdk/pull/1864))
```java
ToolDefinition tool = ToolDefinition.create("search", "Search files", schema, handler)
.metadata(Map.of("com.example:featureFlags", Map.of("streamResults", true)));
```
### Feature: tool search configuration support
`SessionConfig` and `ResumeSessionConfig` now accept a
`ToolSearchConfig` that enables server-side tool search and controls the
deferral threshold. Tool results can also carry back `toolReferences`
indicating which tools were consulted during search.
([#1933](https://github.com/github/copilot-sdk/pull/1933))
```java
SessionConfig config = new SessionConfig()
.setToolSearch(new ToolSearchConfig().setEnabled(true).setDeferThreshold(5));
```
### Other changes
- feature: **[Java]** forward `enableManagedSettings` on
`SessionConfig`/`ResumeSessionConfig` to opt into enterprise
managed-settings enforcement at session bootstrap
([#1925](https://github.com/github/copilot-sdk/pull/1925))
- feature: **[Java]** expose `agentId()`, `parentAgentId()`, and
`interactionType()` on `CopilotRequestContext` in request-handler
callbacks ([#1949](https://github.com/github/copilot-sdk/pull/1949))
... (truncated)
## 1.0.7-preview.3
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.7-preview.3</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.7-preview.3")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.7-preview.3'
```
---
### Feature: tool search configuration
Sessions can now configure tool search behavior via `ToolSearchConfig`
on `SessionConfig`. Tool search keeps the model's active tool set small
by deferring MCP and external tools until needed.
([#1933](https://github.com/github/copilot-sdk/pull/1933))
```java
var config = new SessionConfig()
.setToolSearch(new ToolSearchConfig()
.setEnabled(true)
.setDeferThreshold(20));
var session = client.createSession(config).get();
```
### Other changes
- improvement: **[Java]** updated Javadoc examples to reference current
model IDs ([#1978](https://github.com/github/copilot-sdk/pull/1978))
### New contributors
- `@rinceyuan` made their first contribution in
[#1978](https://github.com/github/copilot-sdk/pull/1978)
... (truncated)
## 1.0.7-preview.2
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.7-preview.2</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.7-preview.2")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.7-preview.2'
```
## Changes since java/v1.0.7-preview.1
- improvement: **[Java]** document native runtime bundling strategy
(ADR-007): chose per-platform classifier JARs (DJL-style) with JNA
bindings over Panama FFM, including decision rationale and monolithic
uber-jar support via `maven-assembly-plugin`
([#1966](https://github.com/github/copilot-sdk/pull/1966))
> Generated by [Release Changelog
Generator](https://github.com/github/copilot-sdk/actions/runs/29133933220)
· sonnet46 738.2K
<!-- gh-aw-agentic-workflow: Release Changelog Generator, engine:
copilot, version: 1.0.55, model: claude-sonnet-4.6, id: 29133933220,
workflow_id: release-changelog, run:
https://github.com/github/copilot-sdk/actions/runs/29133933220 -->
## 1.0.7-preview.1
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.7-preview.1</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.7-preview.1")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.7-preview.1'
```
---
### Feature: request handler context now exposes agent metadata
`CopilotRequestContext` now includes `agentId`, `parentAgentId`, and
`interactionType` fields, giving request handlers visibility into which
agent is making an LLM inference call and whether it is a subagent.
([#1949](https://github.com/github/copilot-sdk/pull/1949))
```java
client.setRequestHandler((context, chain) -> {
System.out.println("Agent: " + context.getAgentId());
System.out.println("Parent: " + context.getParentAgentId());
System.out.println("Interaction: " + context.getInteractionType());
return chain.apply(context);
});
```
> Generated by [Release Changelog
Generator](https://github.com/github/copilot-sdk/actions/runs/29070709628)
· sonnet46 747.2K
<!-- gh-aw-agentic-workflow: Release Changelog Generator, engine:
copilot, version: 1.0.55, model: claude-sonnet-4.6, id: 29070709628,
workflow_id: release-changelog, run:
https://github.com/github/copilot-sdk/actions/runs/29070709628 -->
## 1.0.7-preview.0
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.7-preview.0</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.7-preview.0")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.7-preview.0'
```
### Feature: opt in to enterprise managed-settings enforcement
`SessionConfig` and `ResumeSessionConfig` now support an
`enableManagedSettings` flag. When set to `true`, the runtime enforces
organizational bypass-permissions policies at session creation using the
session's GitHub token.
([#1925](https://github.com/github/copilot-sdk/pull/1925))
```java
var session = client.createSession(
new SessionConfig().setEnableManagedSettings(true)
).get();
```
> Generated by [Release Changelog
Generator](https://github.com/github/copilot-sdk/actions/runs/29030107286)
· sonnet46 2.3M
<!-- gh-aw-agentic-workflow: Release Changelog Generator, engine:
copilot, version: 1.0.55, model: claude-sonnet-4.6, id: 29030107286,
workflow_id: release-changelog, run:
https://github.com/github/copilot-sdk/actions/runs/29030107286 -->
## 1.0.6
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.6</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.6")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.6'
```
---
### Feature: inline lambda tool definitions
Developers can now define tools directly at the call site using
`ToolDefinition.from(...)` with typed lambda handlers and
`Param.of(...)` parameter metadata — no separate annotated class
required. Async variants (`fromAsync`) and `ToolInvocation` context
injection (`fromWithToolInvocation`) are also available.
([#1895](https://github.com/github/copilot-sdk/pull/1895))
```java
ToolDefinition greet = ToolDefinition.from(
"greet", "Greets a user by name",
Param.of(String.class, "name", "The user's name"),
name -> "Hello, " + name + "!");
```
### Other changes
- bugfix: **[Java]** preserve explicit null map values in JSON-RPC
params so user setting clears reach the CLI
([#1906](https://github.com/github/copilot-sdk/pull/1906))
- feature: **[Java]** add experimental `onGitHubTelemetry` callback on
`CopilotClientOptions` for receiving forwarded GitHub telemetry events
([#1835](https://github.com/github/copilot-sdk/pull/1835))
> Generated by [Release Changelog
Generator](https://github.com/github/copilot-sdk/actions/runs/28957271778)
· sonnet46 2.5M
<!-- gh-aw-agentic-workflow: Release Changelog Generator, engine:
copilot, version: 1.0.55, model: claude-sonnet-4.6, id: 28957271778,
workflow_id: release-changelog, run:
https://github.com/github/copilot-sdk/actions/runs/28957271778 -->
## 1.0.6-preview.1
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.6-preview.1</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.6-preview.1")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.6-preview.1'
```
### Feature: experimental GitHub telemetry forwarding
The Java SDK now supports forwarding per-session GitHub telemetry events
to your application. Set `onGitHubTelemetry` on `CopilotClientOptions`
to receive `gitHubTelemetry.event` notifications from the runtime; the
client automatically opts every session it creates or resumes into
telemetry forwarding when the handler is present.
([#1835](https://github.com/github/copilot-sdk/pull/1835))
```java
CopilotClientOptions options = new CopilotClientOptions()
.setOnGitHubTelemetry(notification -> {
// process per-session GitHub telemetry event
return CompletableFuture.completedFuture(null);
});
```
> **Note:** This is an experimental feature (`@CopilotExperimental`)
and may change or be removed without notice.
> Generated by [Release Changelog
Generator](https://github.com/github/copilot-sdk/actions/runs/28603913829)
· sonnet46 977.2K
<!-- gh-aw-agentic-workflow: Release Changelog Generator, engine:
copilot, version: 1.0.55, model: claude-sonnet-4.6, id: 28603913829,
workflow_id: release-changelog, run:
https://github.com/github/copilot-sdk/actions/runs/28603913829 -->
## 1.0.6-preview.0
## What's Changed
* Update @github/copilot to 1.0.66 by @github-actions[bot] in
https://github.com/github/copilot-sdk/pull/1859
* Update @github/copilot to 1.0.67 by @github-actions[bot] in
https://github.com/github/copilot-sdk/pull/1860
* Expose new session options across SDKs by @stephentoub in
https://github.com/github/copilot-sdk/pull/1865
* Fix MCP OAuth resume order in Node.js SDK by @MackinnonBuck in
https://github.com/github/copilot-sdk/pull/1861
* docs: update billing information for GitHub Copilot SDK usage by
@coleflennikenmsft in https://github.com/github/copilot-sdk/pull/1854
* docs: add session limits guidance by @szabta89 in
https://github.com/github/copilot-sdk/pull/1856
* Stream Anthropic /messages responses in E2E fake handlers by
@stephentoub in https://github.com/github/copilot-sdk/pull/1868
* [changelog] Add changelog for java/v1.0.5-01 by @github-actions[bot]
in https://github.com/github/copilot-sdk/pull/1871
* [changelog] Add changelog for v1.0.5 by @github-actions[bot] in
https://github.com/github/copilot-sdk/pull/1869
* Add experimental GitHub telemetry redirection across all SDKs by
@MackinnonBuck in https://github.com/github/copilot-sdk/pull/1835
## New Contributors
* @coleflennikenmsft made their first contribution in
https://github.com/github/copilot-sdk/pull/1854
* @szabta89 made their first contribution in
https://github.com/github/copilot-sdk/pull/1856
**Full Changelog**:
https://github.com/github/copilot-sdk/compare/rust/v1.0.5-preview.1...rust/v1.0.6-preview.0
## 1.0.5
# Installation
⚠️ **Artifact versioning plan:** Releases of this implementation track
releases of the reference implementation. For each release of the
reference implementation, there may follow a corresponding release of
this implementation with the same number as the reference
implementation. Release identifiers of the reference implementation are
in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding
maven version for the release will be `Maj.Min.Micro-java.N`, where
`Maj`, `Min` and `Micro` are the corresponding numbers for the reference
implementation release, and `N` is a monotonically increasing sequence
number starting with 0 for each release. See the corresponding
architectural decision record for more information in the `docs/adr`
directory of the source code.
📦 [View on Maven Central]((central.sonatype.com/redacted)
📖 [Documentation]((github.github.io/redacted) ·
[Javadoc]((github.github.io/redacted)
## Maven
```xml
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>1.0.5</version>
</dependency>
```
## Gradle (Kotlin DSL)
```kotlin
implementation("com.github:copilot-sdk-java:1.0.5")
```
## Gradle (Groovy DSL)
```groovy
implementation 'com.github:copilot-sdk-java:1.0.5'
```
---
### Feature: annotation-based tool API (`@CopilotTool`)
The Java SDK now includes a high-level, annotation-driven tool API.
Annotate methods with `@CopilotTool` and parameters with
`@CopilotToolParam` to define tools — a JSR-269 annotation processor
generates metadata at compile time with no runtime reflection. Use
`ToolDefinition.fromObject()` to register tools with minimal
boilerplate. ([#1792](https://github.com/github/copilot-sdk/pull/1792))
```java
public class WeatherTools {
`@CopilotTool`("Get the current weather for a given city")
public String getWeather(
`@CopilotToolParam`(value = "The city to get weather for", required = true) String city,
`@CopilotToolParam`(value = "Temperature unit: celsius or fahrenheit", defaultValue = "celsius") String unit) {
// implementation
}
}
List<ToolDefinition> tools = ToolDefinition.fromObject(new WeatherTools());
SessionConfig config = new SessionConfig().setTools(tools);
```
### Feature: `ToolInvocation` injection in `@CopilotTool` methods
... (truncated)
## 1.0.5-preview.1
## What's Changed
* Fix flaky C# permission E2E assertions by @roji in
https://github.com/github/copilot-sdk/pull/1827
* Update @github/copilot to 1.0.66-2 by @github-actions[bot] in
https://github.com/github/copilot-sdk/pull/1828
* [Java] Support hidden `ToolInvocation` injection in `@CopilotTool`
methods by @edburns with @Copilot in
https://github.com/github/copilot-sdk/pull/1832
* Rename `Param` annotation to `CopilotToolParam` in Java SDK by
@edburns with @Copilot in
https://github.com/github/copilot-sdk/pull/1838
* Add SDK MCP OAuth host token handlers by @roji in
https://github.com/github/copilot-sdk/pull/1669
## New Contributors
* @roji made their first contribution in
https://github.com/github/copilot-sdk/pull/1827
**Full Changelog**:
https://github.com/github/copilot-sdk/compare/rust/v1.0.5-preview.0...rust/v1.0.5-preview.1
## 1.0.5-preview.0
## What's Changed
* Add sessionId to BYOK provider-token callback; rename to
bearerTokenProvider by @SteveSandersonMS in
https://github.com/github/copilot-sdk/pull/1796
* Fix block-remove-before-merge workflow failing on merge_group events
by @edburns with @Copilot in
https://github.com/github/copilot-sdk/pull/1798
* Sunbrye/fix azure managed identity tabs by @sunbrye in
https://github.com/github/copilot-sdk/pull/1801
* Make abort E2E snapshots tolerate timing variants by @stephentoub in
https://github.com/github/copilot-sdk/pull/1808
* Java: Implement `@CopilotTool` ergonomics by @edburns in
https://github.com/github/copilot-sdk/pull/1792
* [changelog] Add changelog for java/v1.0.4 by @gith…
Why
The runtime accepts a
githubMcpToolConfigoption onsession.create/session.resumeto configure the built-in GitHub MCP server, but no SDK exposed it, so SDK consumers could not reach it.The motivating case is the new
disableFormDeferralcontrol. MCP Apps are useful, but having issue and pull request tools open an interactive form instead of completing the requested operation is disruptive for autonomous SDK workflows, where the caller expects the tool to just run.disableFormDeferrallets those consumers keep MCP Apps result views while form-backed write tools execute directly.Companion changes:
mcp_apps_disable_form_deferralfeature flaggithubMcpToolConfig.disableFormDeferraland forwards the flags viaX-MCP-FeaturesWhat
Adds
githubMcpToolConfigto session create and resume across all six SDKs, carrying the settings the runtime already accepts:enableAllToolsbooladditionalToolsetsstring[]additionalToolsstring[]enableInsidersModebooldisableFormDeferralboolPer language:
GitHubMcpToolConfiginterface onSessionConfigBase, exported from the package rootGitHubMcpToolConfigTypedDictplus agithub_mcp_tool_configkeyword argument, converted by a_github_mcp_tool_config_to_wirehelper matching the existing_memory_to_wire/_tool_search_to_wireconventionGitHubMCPToolConfigstruct onSessionConfig/ResumeSessionConfigGitHubMcpToolConfigwith builder methods, wired throughSessionCreateWire/SessionResumeWireGitHubMcpToolConfigbean threaded throughSessionRequestBuilderGitHubMcpToolConfigclass onSessionConfigBase, including the copy constructordisableFormDeferralrequires MCP Apps to be enabled for the session; on its own it is inert. The whole option is omitted from the wire payload when unset, so existing consumers see no behavior change.Testing
Every language gets create/resume/omitted-when-unset coverage.
Run locally:
go build,go vet, andTestSessionRequests_GitHubMCPToolConfigpasscargo clippy --libcleantypecheck,format:check,lint(0 errors), and both new tests passNot run locally (no toolchain on this machine; relying on CI):
_github_mcp_tool_config_to_wirehelper was verified in isolation for the full, empty, and explicit-falsecases, butpytestneeds Python 3.11+ /uv