Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions arcade-java-example/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ dependencies {
// only needed for SpringAIExample
implementation("org.springframework.ai:spring-ai-starter-model-openai")
implementation("org.apache.httpcomponents.client5:httpclient5:5.6")

// Only needed for GmailExample
implementation("com.google.api-client:google-api-client:2.9.0")
implementation("com.google.oauth-client:google-oauth-client-jetty:1.39.0")
implementation("com.google.apis:google-api-services-gmail:v1-rev20260112-2.0.0")

}

// only needed for SpringAIExample
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@

public class AuthExample {

/**
*
* @param args
*/
public static void main(String[] args) {

// As the developer, you must identify the user you're authorizing
// and pass a unique identifier for them (e.g. an email or user ID) to Arcade:
String userId = System.getenv("ARCADE_USER_ID");
if (userId == null) {
throw new IllegalArgumentException("Missing environment variable USER_ID");
throw new IllegalArgumentException("Missing environment variable ARCADE_USER_ID");
}

ArcadeClient client = ArcadeOkHttpClient.builder().fromEnv().build();
Expand All @@ -29,8 +25,8 @@ public static void main(String[] args) {
authResponse
.status()
.filter(status -> status != AuthorizationResponse.Status.COMPLETED)
.ifPresent(status -> System.out.println(
"Click this link to authorize: " + authResponse.url().get()));
.flatMap(status -> authResponse.url())
.ifPresent(url -> System.out.println("Click this link to authorize: " + url));

// if the authorization is NOT complete, you can wait using the following method (for CLI applications):
client.auth().waitForCompletion(authResponse);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package dev.arcade.example;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.model.Message;
import dev.arcade.client.ArcadeClient;
import dev.arcade.client.okhttp.ArcadeOkHttpClient;
import dev.arcade.models.AuthorizationContext;
import dev.arcade.models.AuthorizationResponse;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GmailExample {

private static final Logger logger = LoggerFactory.getLogger(GmailExample.class);

public static void main(String[] args) throws Exception {

// As the developer, you must identify the user you're authorizing
// and pass a unique identifier for them (e.g. an email or user ID) to Arcade:
String userId = System.getenv("ARCADE_USER_ID");
if (userId == null) {
throw new IllegalArgumentException("Missing environment variable ARCADE_USER_ID");
}

ArcadeClient client = ArcadeOkHttpClient.fromEnv();

// get the auth service and call start
AuthorizationResponse authResponse = client.auth()
.start(userId, "google", "oauth2", List.of("https://www.googleapis.com/auth/gmail.readonly"));

// check the response status
authResponse
.status()
.filter(status -> status != AuthorizationResponse.Status.COMPLETED)
.flatMap(status -> authResponse.url())
.ifPresent(url -> logger.info("Click this link to authorize: {}", url));

// if the authorization is NOT complete, you can wait using the following method (for CLI applications):
AuthorizationResponse completedAuthResponse = client.auth().waitForCompletion(authResponse);

// Use the credential
String token = completedAuthResponse
.context()
.flatMap(AuthorizationContext::token)
.get();

JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
HttpTransport httpTransport = new NetHttpTransport();
GoogleCredential credential = new GoogleCredential().setAccessToken(token);

Gmail gmail = new Gmail.Builder(httpTransport, jsonFactory, credential)
.setApplicationName("Your Application Name")
.build();

// List email messages
List<Message> messages = gmail.users().messages().list("me").execute().getMessages();
logger.info("Messages: {}", messages);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@
import dev.arcade.client.okhttp.ArcadeOkHttpClient;
import dev.arcade.models.tools.ExecuteToolRequest;
import dev.arcade.models.tools.ExecuteToolResponse;
import dev.arcade.models.tools.ToolExecuteParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Example of calling a tool using the Arcade Java SDK.
* <p>
* Both the {@code ARCADE_USER_ID} and {@code ARCADE_API_KEY} environment variables must be set.
* See the <a href="https://docs.arcade.dev/en/get-started/setup/api-keys">Getting Your API Key</a> guide to create an API Key.
* Your username can be found in the lower left corner of your <a href="https://app.arcade.dev/home">Arcade console</a>.
*/
public class PlaySpotifyExample {

/**
* Executes the Spotify.ResumePlayback, both the <code>ARCADE_USER_ID</code> and <code>ARCADE_API_KEY</code> environment variables must be set.
* See the <a href="https://docs.arcade.dev/en/get-started/setup/api-keys">Getting Your API Key</a> guide to create an API Key.
* Your username can be found in the lower left corner of your <a href="https://app.arcade.dev/home">Arcade console</a>.
* @param args Not used.
*/
private static final Logger logger = LoggerFactory.getLogger(PlaySpotifyExample.class);

public static void main(String[] args) {

String userId = System.getenv("ARCADE_USER_ID"); // the Spotify tool requires a userId
Expand All @@ -27,17 +28,15 @@ public static void main(String[] args) {
// Configures using the `ARCADE_API_KEY` environment variable
ArcadeClient client = ArcadeOkHttpClient.fromEnv();

ToolExecuteParams params = ToolExecuteParams.builder()
.executeToolRequest(ExecuteToolRequest.builder()
ExecuteToolResponse response = client.tools()
.execute(ExecuteToolRequest.builder()
.toolName("Spotify.ResumePlayback@1.0.2")
.userId(userId)
.build())
.build();
ExecuteToolResponse executeToolResponse = client.tools().execute(params);
executeToolResponse
.output()
.build());

response.output()
.ifPresentOrElse(
output -> System.out.println("Tool output: " + output._value()),
() -> System.out.println("No output for this tool"));
output -> logger.info("Tool output: {}", output._value()),
() -> logger.info("No output for this tool"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package dev.arcade.example;

import dev.arcade.client.ArcadeClient;
import dev.arcade.client.okhttp.ArcadeOkHttpClient;
import dev.arcade.core.JsonValue;
import dev.arcade.models.AuthorizationResponse;
import dev.arcade.models.tools.AuthorizeToolRequest;
import dev.arcade.models.tools.ExecuteToolRequest;
import dev.arcade.models.tools.ExecuteToolResponse.Output;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QuickStartExample {

private static final Logger logger = LoggerFactory.getLogger(QuickStartExample.class);

public static void main(String[] args) {

// You can also set the `ARCADE_API_KEY` environment variable instead of passing it as a
// parameter by using ArcadeOkHttpClient.fromEnv().
ArcadeClient client =
ArcadeOkHttpClient.builder().apiKey("{arcade_api_key}").build();

// Arcade needs a unique identifier for your application user (this could be an email address, a UUID, etc).
// In this example, use the email you used to sign up for Arcade.dev:
String userId = "{arcade_user_id}";

Map<String, JsonValue> searchResult = authorizeAndRunTool(
client, "GoogleNews.SearchNewsStories", Map.of("keywords", "MCP URL mode elicitation"), userId);

// Extract the list of news results from the tool output
List<JsonValue> news = searchResult
.getOrDefault("news_results", JsonValue.from(List.of()))
.toListOrEmpty();

String output = "latest news about MCP URL mode elicitation:\n"
+ news.stream()
.map(item -> {
Map<String, JsonValue> newsItem = item.toMapOrEmpty();
return newsItem.get("source").asStringOrThrow() + " - "
+ newsItem.get("title").asStringOrThrow() + "\n"
+ newsItem.get("link").asStringOrThrow() + "\n\n";
})
.collect(Collectors.joining("\n"));

// Create a Google Doc with the news results
// If the user has not previously authorized the Google Docs tool, they will be prompted to authorize the tool
// call.
Map<String, JsonValue> createDocResult = authorizeAndRunTool(
client,
"GoogleDocs.CreateDocumentFromText",
Map.of("title", "News about MCP URL mode elicitation", "text_content", output),
userId);

String googleDocUrl = createDocResult.get("documentUrl").asStringOrThrow();

String emailBody =
"You can find the news about MCP URL mode elicitation in the following Google Doc: " + googleDocUrl;

Map<String, JsonValue> sendEmailResult = authorizeAndRunTool(
client,
"Gmail.SendEmail",
Map.of("recipient", userId, "subject", "News about MCP URL mode elicitation", "body", emailBody),
userId);

// Print the response from the tool call
logger.info(
"""
Success! Check your email at {}

You just chained 3 tools together:
1. Searched Google News for stories about MCP URL mode elicitation
2. Created a Google Doc with the results
3. Sent yourself an email with the document link

Email metadata: {}
""",
userId,
sendEmailResult);
}

/**
* Authorize (if needed) and execute a tool, returning the output as a Map.
*/
public static Map<String, JsonValue> authorizeAndRunTool(
ArcadeClient client, String toolName, Map<String, Object> input, String userId) {
// Start the authorization process
AuthorizationResponse authResponse = client.tools()
.authorize(AuthorizeToolRequest.builder()
.toolName(toolName)
.userId(userId)
.build());

// If the authorization is not completed, print the authorization URL and wait for the user to authorize the
// app.
// Tools that do not require authorization will have the status "completed" already.
authResponse
.status()
.filter(status -> status != AuthorizationResponse.Status.COMPLETED)
.flatMap(status -> authResponse.url())
.ifPresent(url -> logger.info(
"""
Click this link to authorize {}:
{}.
The process will continue once you have authorized the app.
""",
toolName,
url));
client.auth().waitForCompletion(authResponse);

// Execute the tool and extract the output as a Map
return client.tools()
.execute(ExecuteToolRequest.builder()
.toolName(toolName)
.input(input)
.userId(userId)
.includeErrorStacktrace(true)
.build())
.output()
.flatMap(Output::valueAsObject)
.orElse(Map.of());
}
}
Loading
Loading