diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index da59f99..2aca35a 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.4.0"
+ ".": "0.5.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 3a11178..b120b66 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 7
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-ed52466945f2f8dfd3814a29e948d7bf30af7b76a7a7689079c03b8baf64e26f.yml
-openapi_spec_hash: 5d57aaf2362b0d882372dbf76477ba23
-config_hash: 8ec9eaf59304f664cf79f73de1488671
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-39cd9547d16412cf0568f6ce2ad8d43805dffe65bde830beeff630b903ae3b38.yml
+openapi_spec_hash: 9cd7c9fefa686f9711392782d948470f
+config_hash: 3c21550e2c94cad4339d3093d794beb0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb9b53c..10cbeca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,21 @@
# Changelog
+## 0.5.0 (2026-01-07)
+
+Full Changelog: [v0.4.0...v0.5.0](https://github.com/browserbase/stagehand-java/compare/v0.4.0...v0.5.0)
+
+### Features
+
+* /end endpoint returns empty object ([058cf38](https://github.com/browserbase/stagehand-java/commit/058cf3853b589356fe0b88d5899c98e4c44c8f19))
+* Added optional param to force empty object ([a93f1bf](https://github.com/browserbase/stagehand-java/commit/a93f1bf0324f4fa0b1bd96122d29534ff03cd9b2))
+* **client:** add `HttpRequest#url()` method ([5a4d99f](https://github.com/browserbase/stagehand-java/commit/5a4d99fd20473dcd6045fb65d8230c3894734364))
+
+
+### Documentation
+
+* add full working example script to readme and stagehand-java-example ([#5](https://github.com/browserbase/stagehand-java/issues/5)) ([7135947](https://github.com/browserbase/stagehand-java/commit/713594728cd301df4587bdb0337a5047695704eb))
+* prominently feature MCP server setup in root SDK readmes ([0c7cb02](https://github.com/browserbase/stagehand-java/commit/0c7cb0241f65547071fcd15e7bce41f621cfbfcb))
+
## 0.4.0 (2026-01-05)
Full Changelog: [v0.3.0...v0.4.0](https://github.com/browserbase/stagehand-java/compare/v0.3.0...v0.4.0)
diff --git a/README.md b/README.md
index 35c6e6a..79c6b2b 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
-[](https://central.sonatype.com/artifact/com.browserbase.api/stagehand-java/0.4.0)
-[](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.4.0)
+[](https://central.sonatype.com/artifact/com.browserbase.api/stagehand-java/0.5.0)
+[](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.5.0)
@@ -11,9 +11,18 @@ The Stagehand Java SDK provides convenient access to the [Stagehand REST API](ht
It is generated with [Stainless](https://www.stainless.com/).
+## MCP Server
+
+Use the Stagehand MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.
+
+[](https://cursor.com/en-US/install-mcp?name=stagehand-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInN0YWdlaGFuZC1tY3AiXX0)
+[](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22stagehand-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22stagehand-mcp%22%5D%7D)
+
+> Note: You may need to set environment variables in your MCP client.
+
-The REST API documentation can be found on [docs.stagehand.dev](https://docs.stagehand.dev). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.4.0).
+The REST API documentation can be found on [docs.stagehand.dev](https://docs.stagehand.dev). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.5.0).
@@ -24,7 +33,7 @@ The REST API documentation can be found on [docs.stagehand.dev](https://docs.sta
### Gradle
```kotlin
-implementation("com.browserbase.api:stagehand-java:0.4.0")
+implementation("com.browserbase.api:stagehand-java:0.5.0")
```
### Maven
@@ -33,7 +42,7 @@ implementation("com.browserbase.api:stagehand-java:0.4.0")
com.browserbase.api
stagehand-java
- 0.4.0
+ 0.5.0
```
diff --git a/build.gradle.kts b/build.gradle.kts
index bd9f794..0db3fe0 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -9,7 +9,7 @@ repositories {
allprojects {
group = "com.browserbase.api"
- version = "0.4.0" // x-release-please-version
+ version = "0.5.0" // x-release-please-version
}
subprojects {
diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/http/HttpRequest.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/http/HttpRequest.kt
index f42f44a..280bd51 100644
--- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/http/HttpRequest.kt
+++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/http/HttpRequest.kt
@@ -2,6 +2,7 @@ package com.browserbase.api.core.http
import com.browserbase.api.core.checkRequired
import com.browserbase.api.core.toImmutable
+import java.net.URLEncoder
class HttpRequest
private constructor(
@@ -13,6 +14,35 @@ private constructor(
@get:JvmName("body") val body: HttpRequestBody?,
) {
+ fun url(): String = buildString {
+ append(baseUrl)
+
+ pathSegments.forEach { segment ->
+ if (!endsWith("/")) {
+ append("/")
+ }
+ append(URLEncoder.encode(segment, "UTF-8"))
+ }
+
+ if (queryParams.isEmpty()) {
+ return@buildString
+ }
+
+ append("?")
+ var isFirst = true
+ queryParams.keys().forEach { key ->
+ queryParams.values(key).forEach { value ->
+ if (!isFirst) {
+ append("&")
+ }
+ append(URLEncoder.encode(key, "UTF-8"))
+ append("=")
+ append(URLEncoder.encode(value, "UTF-8"))
+ isFirst = false
+ }
+ }
+ }
+
fun toBuilder(): Builder = Builder().from(this)
override fun toString(): String =
diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt
index 90a656f..e10e438 100644
--- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt
+++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt
@@ -3,16 +3,21 @@
package com.browserbase.api.models.sessions
import com.browserbase.api.core.Enum
+import com.browserbase.api.core.ExcludeMissing
import com.browserbase.api.core.JsonField
+import com.browserbase.api.core.JsonMissing
import com.browserbase.api.core.JsonValue
import com.browserbase.api.core.Params
import com.browserbase.api.core.http.Headers
import com.browserbase.api.core.http.QueryParams
-import com.browserbase.api.core.toImmutable
import com.browserbase.api.errors.StagehandInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
+import java.util.Collections
import java.util.Objects
import java.util.Optional
import kotlin.jvm.optionals.getOrNull
@@ -25,9 +30,9 @@ private constructor(
private val xSdkVersion: String?,
private val xSentAt: OffsetDateTime?,
private val xStreamResponse: XStreamResponse?,
+ private val body: Body,
private val additionalHeaders: Headers,
private val additionalQueryParams: QueryParams,
- private val additionalBodyProperties: Map,
) : Params {
/** Unique session identifier */
@@ -45,8 +50,9 @@ private constructor(
/** Whether to stream the response via SSE */
fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse)
- /** Additional body properties to send with the request. */
- fun _additionalBodyProperties(): Map = additionalBodyProperties
+ fun __forceBody(): JsonValue = body.__forceBody()
+
+ fun _additionalBodyProperties(): Map = body._additionalProperties()
/** Additional headers to send with the request. */
fun _additionalHeaders(): Headers = additionalHeaders
@@ -72,9 +78,9 @@ private constructor(
private var xSdkVersion: String? = null
private var xSentAt: OffsetDateTime? = null
private var xStreamResponse: XStreamResponse? = null
+ private var body: Body.Builder = Body.builder()
private var additionalHeaders: Headers.Builder = Headers.builder()
private var additionalQueryParams: QueryParams.Builder = QueryParams.builder()
- private var additionalBodyProperties: MutableMap = mutableMapOf()
@JvmSynthetic
internal fun from(sessionEndParams: SessionEndParams) = apply {
@@ -83,9 +89,9 @@ private constructor(
xSdkVersion = sessionEndParams.xSdkVersion
xSentAt = sessionEndParams.xSentAt
xStreamResponse = sessionEndParams.xStreamResponse
+ body = sessionEndParams.body.toBuilder()
additionalHeaders = sessionEndParams.additionalHeaders.toBuilder()
additionalQueryParams = sessionEndParams.additionalQueryParams.toBuilder()
- additionalBodyProperties = sessionEndParams.additionalBodyProperties.toMutableMap()
}
/** Unique session identifier */
@@ -121,6 +127,36 @@ private constructor(
fun xStreamResponse(xStreamResponse: Optional) =
xStreamResponse(xStreamResponse.getOrNull())
+ /**
+ * Sets the entire request body.
+ *
+ * This is generally only useful if you are already constructing the body separately.
+ * Otherwise, it's more convenient to use the top-level setters instead:
+ * - [_forceBody]
+ */
+ fun body(body: Body) = apply { this.body = body.toBuilder() }
+
+ fun _forceBody(_forceBody: JsonValue) = apply { body._forceBody(_forceBody) }
+
+ fun additionalBodyProperties(additionalBodyProperties: Map) = apply {
+ body.additionalProperties(additionalBodyProperties)
+ }
+
+ fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply {
+ body.putAdditionalProperty(key, value)
+ }
+
+ fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) =
+ apply {
+ body.putAllAdditionalProperties(additionalBodyProperties)
+ }
+
+ fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) }
+
+ fun removeAllAdditionalBodyProperties(keys: Set) = apply {
+ body.removeAllAdditionalProperties(keys)
+ }
+
fun additionalHeaders(additionalHeaders: Headers) = apply {
this.additionalHeaders.clear()
putAllAdditionalHeaders(additionalHeaders)
@@ -219,28 +255,6 @@ private constructor(
additionalQueryParams.removeAll(keys)
}
- fun additionalBodyProperties(additionalBodyProperties: Map) = apply {
- this.additionalBodyProperties.clear()
- putAllAdditionalBodyProperties(additionalBodyProperties)
- }
-
- fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply {
- additionalBodyProperties.put(key, value)
- }
-
- fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) =
- apply {
- this.additionalBodyProperties.putAll(additionalBodyProperties)
- }
-
- fun removeAdditionalBodyProperty(key: String) = apply {
- additionalBodyProperties.remove(key)
- }
-
- fun removeAllAdditionalBodyProperties(keys: Set) = apply {
- keys.forEach(::removeAdditionalBodyProperty)
- }
-
/**
* Returns an immutable instance of [SessionEndParams].
*
@@ -253,14 +267,13 @@ private constructor(
xSdkVersion,
xSentAt,
xStreamResponse,
+ body.build(),
additionalHeaders.build(),
additionalQueryParams.build(),
- additionalBodyProperties.toImmutable(),
)
}
- fun _body(): Optional