Tool Studio¶
Tool Studio is the low-code authoring environment for JavaScript-based tools. It is the part of the product that turns the Playground from a read-only testing interface into an executable tool runtime.
A tool you author in Tool Studio is a small JavaScript action plus a structured spec — name, description, parameters, optional static variables, and a sandbox capability profile. Tool Studio compiles that into an MCP-callable tool, runs it once locally against your declared test values to earn a Local Pass, and only then publishes it to the built-in MCP server.
The authoring screen has two working halves that fold into a single page:
- Tool spec form at the top — name, description, parameters.
- Tool Action below it — JavaScript code editor, test run controls, and the collapsible Sandbox & Capabilities pane that controls how the tool's runtime differs from the default.
Top of Tool Studio: tool name / category / tags, free-form tool description, and structured parameters (Parameter #1 with required flag, name, type, description, and a test value the local sandbox actually executes against).
What Tool Studio Does¶
Tool Studio lets you:
- create tools directly in the browser
- define structured input parameters
- define static variables
- test tool execution immediately
- publish tools to the built-in MCP server without restart or redeploy
Local Pass — Test Before Publish¶
Spring AI Playground treats the local test-run as a gate, not a polish step. This is the rule surfaced on the Home screen as No pass, no run.
- every tool has at least one sample input (the static variables you define) used for its test-run
- the tool must pass its test locally before Tool Studio publishes it
- when the test passes, the tool earns a Local Pass and is added live to the built-in MCP server the same moment — no restart, no redeploy
- a tool that has not passed is not added to the built-in MCP server and is not callable from Agentic Chat
In practice this means the act of publishing is the act of testing. You never produce a tool whose first execution happens in front of an agent.
Every one of the 86 bundled Default Tools crossed this same gate before being shipped — they live as ready-to-fork reference for the workflow above.
Built-in MCP Server¶
Tool Studio is tightly integrated with the built-in MCP server.
- endpoint:
http://localhost:8282/mcp - protocol: Streamable HTTP
- default server name:
spring-ai-playground-tool-mcp
When you publish a tool from Tool Studio, it becomes available through that MCP endpoint immediately.
Tool Action — JavaScript code editor¶
The lower half of the authoring page is the Tool Action area: the JavaScript code that actually runs when the tool is invoked, plus the controls and panels that surround it.
Tool Action area top-to-bottom: Sandbox & Capabilities stays collapsed by default with a Locked L0 badge so authoring focuses on the JS action itself; Static Variables sit just above the code, available to the action as globals and masked from logs if env-backed; the JS Code Editor ships with a sample that lists the cross-bridged globals (fetch, URL, URLSearchParams, atob/btoa, crypto, the safety.* helpers) so the author has a working reference without leaving the page; Test Run / Clear / Format drive execution; Debug Console captures console.log output with env-var masking; the bottom action bar — Save Draft / Local Pass badge / Test & Publish — closes the loop. The only way to expose a tool through MCP is to make its sandboxed test run pass.
JavaScript Runtime¶
Tool actions run as JavaScript through GraalVM Polyglot inside the JVM, on a virtual-thread-per-task executor so a runaway tool can be hard-killed on timeout without leaking platform threads.
Runtime characteristics:
- ECMAScript 2024 with extras enabled —
temporal,iterator-helpers,new-set-methods,regexp-unicode-sets,intl-402,text-encoding(configured via GraalVMjs.*options on a sharedEngine) - controlled Java interop through a deny-first class allowlist (configured under Sandbox & Capabilities below)
- safe built-in helpers for HTTP, filesystem, and parsing — so tools rarely need raw
Java.type(...) - statement-budget and wall-clock timeout enforced outside the JS context:
max-statements: 500000(GraalVMResourceLimits) andtimeout-seconds: 30(Future.get+Future.cancel(true)). Neither is bypassable from JS.
Source of truth: JsToolExecutor, JsRuntimeGlobals.
Cross-platform by design¶
The JS-on-JVM design is what lets every tool in this app — both the bundled defaults and anything you author here — work the same on macOS, Windows, and Linux without per-OS packaging or native toolchains. This is the main split from typical MCP server tools, which ship one native binary per platform and need a build environment on the user's machine.
Concretely:
- One artifact runs on all three OSes — the same JAR is repackaged into the Docker image and the Electron-packaged desktop launcher, all from one
pom.xml. See Getting Started for the platform-specific launchers. - All 86 default tools are pure JavaScript executed through GraalVM Polyglot. No native dependencies, no per-OS build step, no install-time compile.
- Every cross-bridged helper resolves to a Java standard library or well-known JVM library, so platform quirks are handled at the JVM layer:
safety.fsrides onjava.nio.file.Path/Files—/vs\and case folding are normalised before any I/O.fetchuses the JDKHttpClient— same TLS stack, same redirect handling, same connection pool everywhere.safety.parser.html/xml/yaml/csvgo through jsoup /javax.xml.parsers(XXE-hardened) / SnakeYAML / Apache Commons CSV.crypto.subtlegoes through JCE — algorithms and key formats are JVM-controlled, not OS-controlled.
- Authoring a new tool needs nothing installed locally beyond the running app. No
cargo build, nonpm install, no platform-specific shell scripts. Tool Studio's editor + Local Pass is the entire build pipeline.
A pure-runtime caveat: a tool whose JS hard-codes platform-specific paths or external services (/etc/..., C:\Program Files\..., OS-only binaries) is still platform-coupled at the user-data level. The runtime is OS-agnostic; whether a specific tool you author is portable depends on what it does.
Built-in JavaScript Helpers¶
Tools call a small set of capability-scoped helpers instead of raw Java. These are the same helpers the bundled default tools use, so authoring a new tool typically does not require any Java.type(...) interop at all.
| Helper | What it does |
|---|---|
fetch(url, init?) |
HTTPS/HTTP request with the SSRF four-layer guard. 5 redirect cap, 10 MB body cap, 30 s request timeout, 5 s connect timeout. Restricted hop-by-hop headers (Host, Connection, Content-Length, Expect, Upgrade) are stripped before sending. 303 redirects downgrade POST → GET. init accepts method, headers, body plus maxLength / startIndex for response pagination. Returns {status, ok, statusText, url, contentType, truncated, nextStartIndex, headers: {get(name)}, text(), json(), arrayBuffer()}. Only installed when the effective egress level is not blocked. |
URL, URLSearchParams |
WHATWG URL parsing / building. |
atob, btoa |
Base64 encode / decode of strings. |
crypto.subtle |
digest (SHA-256 / SHA-384 / SHA-512 only), importKey + sign / verify for HMAC, and getRandomValues — backed by JCE. |
crypto.randomUUID() |
UUID v4. |
safety.fs |
readText, writeText (auto-creates parent directories), list, stat, exists, grep, lineCount, slice, cut, sort, find (depth-limited walk, follows symlinks). Every path is resolved against the base path and rejected if normalize() escapes the root. Per-tool override fsBasePath swaps the root for that tool. |
safety.parser.html |
jsoup-backed cleaner. Returns a org.jsoup.nodes.Document host object — methods are callable from JS, but the class itself is not in the allow-list, so user code cannot construct new jsoup instances via Java.type(...). |
safety.parser.xml |
XXE-hardened DOM parser: disallow-doctype-decl=true, external general + parameter entities disabled, XIncludeAware=false, expandEntityReferences=false. Returns a plain {tag, attrs, text, children} proxy tree — no host nodes leak. |
safety.parser.yaml |
SnakeYAML Yaml().load(). Caveat: this is the regular constructor (not SafeConstructor), so YAML tags such as !!class.name will trigger class instantiation during load. Treat YAML input as trusted-source-only; do not parse user-supplied YAML with this helper. |
safety.parser.csv |
Apache Commons CSV — optional header and delimiter opts. |
console.log |
Captured into the Tool Studio debug pane and into the chat's tool-call trace. Environment-backed static variables are masked by substring replacement when their full resolved value appears in output. Only anchored full-string $ENV_VAR references are auto-collected as secrets — substring-inlined env vars are not. Log entries are capped at 1000 per execution. console.error is not installed in the current build. |
Every helper above is exercised by one or more of the 86 Default Tools — open one in Tool Studio to see the helper in working code, then use Copy to New Tool to fork it.
Sandbox & Capabilities¶
Sandbox & Capabilities is the collapsible pane inside Tool Action that controls how a tool's effective runtime policy differs from the global default. Every tool starts at the baseline — no network, no filesystem, deny-first class allowlist — and earns an L0 badge. Opening this pane lets you widen specific dimensions per tool, and the Risk Level badge updates live as you do so.
Sandbox & Capabilities expanded: Deny Classes chips list packages user JS can never touch (removing chips lowers safety — removing reflection denies → L4, removing System / Runtime / Process → L5); Allow Classes chips list packages user JS can use (adding new chips can raise risk to L3+); Network mode radio chooses blocked / allowlist / strict (default, with SSRF four-layer guard) / open; Filesystem mode chooses off (hidden) / read (L3) / read+write (L4) / readwrite; Base path sets the per-tool safety.fs root, default ${TOOL_STUDIO_FS_BASE:${user.home}}.
The Sandbox & Capabilities pane reads and writes a SandboxOverrides block on the tool's spec. None of the bundled defaults touch the class lists — they only set network mode and host list — but the full surface is available. The five subsections below document the baseline, the override shape, and the per-control semantics in detail.
Default sandbox baseline (application.yaml)¶
The Sandbox & Capabilities pane modifies a global baseline defined in application.yaml. The defaults are deliberately restrictive: no I/O of any kind, only pure-compute Java packages reachable through Java.type(...), and an explicit deny-list that beats any allow match.
spring:
ai:
playground:
tool-studio:
timeout-seconds: 30
fs:
base-path: ${TOOL_STUDIO_FS_BASE:${user.home}}
js-sandbox:
allow-network-io: false
allow-file-io: false # single boolean — flips read and write together
allow-native-access: false
allow-create-thread: false
max-statements: 500000
deny-classes: # evaluated before allow-classes — deny ALWAYS wins
- java.lang.System
- java.lang.Runtime
- java.lang.ProcessBuilder
- java.lang.Process
- java.lang.Class
- java.lang.invoke.*
- java.lang.reflect.*
- java.lang.Thread
- java.lang.ThreadGroup
- java.lang.ClassLoader
- java.util.ServiceLoader
- java.util.spi.*
allow-classes: # pure-compute only
- java.lang.*
- java.math.*
- java.time.*
- java.util.*
- java.text.*
Pattern semantics for deny-classes / allow-classes: an entry is either the exact class name (java.lang.Class) or a package prefix ending in .* (java.lang.reflect.* matches java.lang.reflect.Method but not bare java.lang.reflect). Deny is evaluated first; if a class matches both lists, the deny wins.
A tool that legitimately needs raw Java network/filesystem access or relaxed network egress opts in per tool via Sandbox Capabilities — the per-tool override surface documented in the next subsection. If you need an even stricter deployment than this baseline, GraalVM sandbox policies can be layered on top in a custom source build; see the GraalVM Security Guide.
SandboxOverrides JSON shape¶
SandboxOverrides is the per-tool block that the Sandbox & Capabilities pane edits and the resolver applies. None of the bundled defaults touch the class lists — they only set network mode and host list — but the full shape is:
{
"addAllowClasses": ["java.net.URL"],
"removeAllowClasses": [],
"addDenyClasses": [],
"removeDenyClasses": [],
"networkMode": "strict | allowlist | open | blocked",
"hostsAllow": ["api.example.com", "*.example.com"],
"fileRead": true,
"fileWrite": null,
"fsBasePath": null
}
- Putting the same class in both
addAllowClassesandaddDenyClassesthrows — the resolver enforces a single source of truth. networkModereplaces the baseline egress level;hostsAllowonly applies whennetworkModeisallowlist.fileRead/fileWriteare nullable — leave them asnullto inherit the baseline (which is the singleallow-file-ioflag); set them per-tool to split read and write.fsBasePathswaps thesafety.fsroot for that one tool. Use sparingly — it bypasses the per-app base path.
Egress modes (network)¶
The Tool Studio override form exposes four user-facing modes. A fifth (permissive, alias for open) and a sixth (custom, deny-list-based) exist inside SafeHttpFetch.enforce; custom is currently only filled in from yaml profiles, not from the per-tool form.
| Mode | What it does | SSRF guard |
|---|---|---|
blocked |
fetch is not installed at all — calling it from JS throws ReferenceError. |
n/a |
strict (default) |
Public hosts only. Both the literal host and every DNS-resolved address must not be private/reserved. | ✅ runs |
allowlist |
Host must match an entry in hostsAllow (exact match or *.suffix). |
not run |
open (= permissive) |
No host check. Use only when the tool genuinely needs open egress. | not run |
custom (internal) |
Allowed unless the host matches hostsDeny. Reachable from yaml profiles only. |
not run |
All modes enforce the rest of the contract: scheme is http or https, body cap 10 MB, redirect cap 5, request timeout 30 s, connect timeout 5 s, restricted hop-by-hop headers stripped, 303 POST→GET downgrade.
Filesystem mode¶
The Filesystem radio chooses how safety.fs behaves for the tool. The baseline is off (no read, no write); per-tool overrides widen the surface.
| Mode | fileRead |
fileWrite |
Risk impact |
|---|---|---|---|
off (default) |
false | false | Hidden — safety.fs calls reject with policy error. |
read |
true | false | L3 — tool can readText / list / stat / find within the base path. |
read+write |
true | true | L4 — tool can also writeText, which auto-creates parent directories. |
readwrite |
true | true | L4 (same posture as read+write; alternate label). |
All file access is rooted at the configured Base path (default ${TOOL_STUDIO_FS_BASE:${user.home}}, set per-app under tool-studio.fs.base-path). SafeFs.resolveAndValidate calls normalize() and rejects any path whose result does not startsWith(base), so ../../etc/passwd and absolute paths outside the root both fail. safety.fs.find walks with FileVisitOption.FOLLOW_LINKS — symbolic links are traversed, so consider that when sharing the base path with untrusted directory trees.
SSRF four-layer guard¶
Active only when egress is strict. From SafeHttpFetch.enforce and enforceSsrfFourLayer, in order:
- Scheme check — only
httpandhttpsaccepted. Anything else rejected asunsupported-scheme. - Egress switch — based on the resolved mode. Only
strictcontinues to the next layers. - Literal IP vs DNS branch — if the host parses as a literal IPv4/IPv6 address, check that address directly. Otherwise resolve via DNS (
InetAddress.getAllByName) and check every returned address. DNS failure or empty resolution both block — fail-closed. - Private/reserved address check — rejects:
- loopback (
127.0.0.0/8,::1) - link-local (
169.254.0.0/16,fe80::/10) - site-local (RFC 1918:
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16) - any-local (
0.0.0.0,::) - multicast (
224.0.0.0/4,ff00::/8) - IPv6 ULA (
fc00::/7) - CGNAT (
100.64.0.0/10) — explicitly handled because Java'sisSiteLocalAddress()does not cover this range
Risk Level Reference¶
Computed by SandboxPostureCalculator.compute from the tool's effective policy. The badge is the max of all signals below. Only L0/L3/L4/L5 are produced by the current calculator (L1 and L2 exist as labels in the UI but no rule yields them today).
| Signal | Threshold | Level |
|---|---|---|
| Default posture (no overrides) | — | L0 |
networkMode = allowlist with concrete hosts |
non-* allow-list |
L3 |
networkMode = allowlist containing * |
wildcard everything | L4 |
networkMode = open |
any host | L4 |
fileRead = true (write false) |
file read only | L3 |
fileWrite = true |
write capability | L4 |
| Removed deny entry — non-critical | 1–2 entries dropped | L3 |
| Removed deny entry — non-critical | 3+ entries dropped | L4 |
| Removed deny entry — critical | any of System / Runtime / Process / ProcessBuilder |
L5 |
| Added allow entry — file-read | java.io.File*, java.nio.file.Files/Path/Paths |
L4 |
| Added allow entry — reflection | java.lang.reflect.*, java.lang.invoke.*, java.lang.Class |
L4 |
| Added allow entry — network | java.net.http, Socket, URL, URLConnection, HttpURLConnection, javax.net.ssl, org.jsoup |
L4 |
| Added allow entry — file-write | java.io.FileWriter, FileOutputStream, RandomAccessFile, FileChannel |
L5 |
| Added allow entry — critical | System / Runtime / Process / ProcessBuilder |
L5 |
| Any other class added | non-critical allow | L3 |
Practical interpretation:
- L0 = baseline defaults. Every starter tool runs here.
- L3 = narrowed network access or file-read; reviewable.
- L4 = broad network, file-write, or substantial deny-list relaxation — review carefully before exposing through MCP.
- L5 = critical class re-enabled — process spawn, reflection escape, or raw file write. Treat as effectively unsandboxed and reserve for trusted authors only.
Safety — defense in depth¶
The terminology matters: this is safety in the GraalVM sandbox sense — keeping a small JavaScript action from doing things its author did not intend — not security in the sense of authenticating outside callers. The two are layered but separate, and the code makes the same distinction (safety.fs, safety.parser.* for the sandbox surface; Spring Security on top for the endpoint).
The three layers:
- Java-level sandbox (always on) — what every tool runs inside, no matter who authored it. Deny-first class allowlist, network/file I/O blocked at the JVM (helpers are the only paths), statement-budget + wall-clock timeout, secret masking on
console.logoutput. Not bypassable from JS. Configured by Default sandbox baseline above. - Per-tool overrides (visible risk) — the Sandbox & Capabilities pane widens the sandbox in declared, badge-visible ways. Each widening surfaces as a Risk Level (L0–L5) before publish, so the gate is review rather than runtime. Layer 1 still holds: the deny-list and SSRF guard cannot be turned off here, only the allow-side and network mode can be widened.
- MCP endpoint security (Spring Security) — adversarial-threat layer in front of the MCP transport. Disabled by default for the local single-user case; enabled via Spring AI MCP Security for deployed scenarios.
The first two are about safety of execution. The third is about who can talk to the MCP server. Both matter; they fail to different threats.
For the system-level reference — three-layer diagram, policy resolution flow, per-execution enforcement points, threat-to-layer mapping, and known limitations — see AI Agent Tool Safety Architecture.
Connect to the Built-in MCP Server¶
Once Spring AI Playground is running, the built-in MCP server can be consumed directly by MCP-compatible clients.
Claude Code¶
Recent Claude Code versions support Streamable HTTP directly.
claude mcp add spring-ai-playground http://localhost:8282/mcp
Restart Claude Code if needed so the new server is picked up.
Cursor¶
Configure a Streamable HTTP server in Cursor with:
- Name:
Spring AI Playground - URL:
http://localhost:8282/mcp
In practice, that means:
- open Cursor Settings
- navigate to Features > MCP
- add a new MCP server
- choose Streamable HTTP
- enter the name and URL above
Claude Desktop¶
If your Claude Desktop plan supports native remote connectors, you can add http://localhost:8282/mcp directly from the Settings UI.
For broader compatibility, one practical approach is to use mcp-remote:
{
"mcpServers": {
"spring-ai-playground": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:8282/mcp"]
}
}
}
Restart Claude Desktop after saving the config.
This proxy-style setup is especially useful when direct remote configuration is unavailable or inconvenient, because it wraps the remote Streamable HTTP MCP server behind a local process contract that desktop clients already understand well.
Dynamic Tool Exposure¶
Tool Studio and the built-in MCP server are intentionally designed for a no-restart workflow:
- create or update a tool
- test it
- publish it
- inspect it through MCP immediately
When a tool is created or updated in Tool Studio, it is dynamically discovered and exposed by the default built-in MCP server. You can then inspect its schema and validate execution behavior from the MCP Server screen without restarting or redeploying the application.
Key Tool Studio Capabilities¶
- Tool MCP Server Setting drawer (toolbox icon in the Tool Studio header): the single surface controlling what the built-in MCP server exposes. Three sections — Tools exposed chip summary (current preset + the tools it resolves to); Custom tools (you created) with an Auto-add new custom tools toggle plus a Manually exposed tools MultiSelect for per-tool overrides on what you authored; Default tools (built-in) with the Preset radio (
Starter 5,Dev Essentials,Korea Toolkit (free),File Toolkit,Everything,Custom) and an Advanced curation block (include by tag / category / name, exclude by tag / name) layered on top. - Draft state + MCP exposure gate: a tool that has not earned a Local Pass stays in the Drafts section, is not exposed through the built-in MCP server, and is not callable from Agentic Chat. Only published (Local-Passed) tools cross the gate.
- Category-grouped sidebar: tools group under a fixed taxonomy (Text, Data, Date/Time, Math, Encoding, Crypto, Security, Files, Web, Productivity, Messaging, AI APIs, Custom) with chip-based filters.
- Sandbox Capabilities view: per-tool overrides for
addAllowClasses/removeAllowClasses/addDenyClasses/removeDenyClasses,hostsAllow,fileRead/fileWrite,fsBasePath, andnetworkMode— with a live risk-level badge (L0–L5). See Sandbox & Capabilities. - Tool Specification View: inspect the generated JSON schema, metadata, parameter contract, and the resulting
McpToolDefinitionenvelope (manifest hash, code hash, audit timestamps). - Copy to New Tool: clone an existing tool as a template instead of starting from scratch.
- Structured Parameters: define required inputs, descriptions, and test values for model-side tool calling.
- Static Variables: inject configuration values and environment-backed secrets — masked in logs.
- Test Run and Debug Console: validate console output, status, elapsed time, and result before publishing.
In the UI these capabilities show up as the practical authoring workflow:
- curate which subset of the bundled catalog is exposed through MCP
- inspect the generated tool specification before publishing
- override sandbox capabilities only where a specific tool needs them, with the risk level visible
- copy a working tool into a new template instead of starting from a blank definition
- test with representative values and review the debug output before updating the runtime
You can keep many tools in your workspace, expose only a controlled subset, validate the exact contract the model will see, and update the runtime without a restart cycle.
Low-code Tool Development Workflow¶
- Open Tool Studio.
- Define the tool name and description.
- Add structured parameters with test values.
- Add static variables if needed.
- Write the JavaScript action.
- Run Test Run and inspect the debug output.
- Publish with Test & Publish (or Test & Update if the tool was already published before).
Pre-built Example Tools¶
Full inventory lives in Default Tools
Per-tool reference — name, one-line description, params, env-var deps — is on the five pages under Default Tools. This section sticks to the preset and curation shape used inside Tool Studio — how the bundle is sliced for MCP exposure.
-
7 · starter tools — fetch a web page, look up weather, search Google, call OpenAI, post to Slack.
-
26 · pure-compute — text, datetime, math, security, encoding, crypto, CSV. No I/O.
-
10 ·
safety.fspipeline — read, list, grep, slice, sort, find, write — under the FS base path. -
22 · public APIs — GitHub, Wikipedia, weather, finance, geo, search.
-
21 · Korean-domain services — Upbit, Bithumb, Naver, Kakao, KMA, KOFIC, KRX, MOLIT, MFDS.
The app ships with a bundled catalog of 86 default tools across five JSON source bundles. They are ready to call from chat the moment a model provider is connected, and they also serve as editable references when you start writing your own.
The MCP server does not expose all of them by default. A preset decides the starting subset, and include / exclude rules layer per-tool tweaks on top. Each preset stands on its own — Dev Essentials, Korea Toolkit, and File Toolkit do not automatically inherit Starter 5 (only getCurrentTime and evalExpression carry through deliberately).
| Preset | Tools exposed | Notes |
|---|---|---|
Starter 5 (default) |
getCurrentTime, getWeather, searchWikipedia, extractPageContent, evalExpression |
No setup, no API keys — works on a fresh install |
Dev Essentials |
getCurrentTime, evalExpression, uuid, hash, base64, jwtDecode, regexExtract |
Everyday local utilities |
Korea Toolkit (free) |
getCurrentTime, evalExpression, getUpbitTicker, getBithumbTicker, searchKpopOnItunes, searchKBeautyProducts |
Free Korean services |
File Toolkit |
getCurrentTime, evalExpression, readTextFile, listDir, grepFile, findFiles, sliceFile, sortFile, cutFileFields |
Filesystem pipeline — set TOOL_STUDIO_FS_BASE (or rely on the ${user.home} default) |
Everything |
All 86 default tools | Heavy MCP catalog |
Custom |
None initially | Active when you only want the include/exclude rules to decide what gets exposed |
Per-tool include / exclude rules layer on top: name-add → tag-add → category-add → name-remove → tag-remove → category-remove. The Tool MCP Server Setting drawer exposes include-by-tag / -category / -name and exclude-by-tag / -name; exclude.categories is data-supported but currently only reachable via CLI / yaml override.
Some default tools depend on environment-backed secrets — OPENAI_API_KEY, GOOGLE_API_KEY + GOOGLE_PSE_ID, SLACK_WEBHOOK_URL, the data.go.kr keychain, and the Korean provider keys — and stay inert until those are set. The consolidated list lives in Default Tools → Environment variables; per-page details are on each reference page. The File Toolkit preset additionally honours TOOL_STUDIO_FS_BASE (defaulting to ${user.home}) for safety.fs. The desktop launcher's environment-variable workflow exists exactly to make this configuration ergonomic.
Where preset choices live¶
The same preset + rules shape can be edited from two surfaces, both writing to the same file <home>/spring-ai-playground/tool/save/default-tools-preference.json:
- Default MCP Tools card inside the desktop launcher's config editor — for picking the preset on first launch and adjusting it on any later configuration session. See Getting Started → Default MCP Tools Curation.
- Tool MCP Server Setting drawer inside Tool Studio — for adjusting at any time after the app is running, no restart required.
Tool MCP Server Setting drawer, top to bottom: Tools exposed chip summary (Starter 5 · 5 of 86 tools with the resolved tool list); Custom tools (you created) — Auto-add new custom tools to the MCP server toggle (on by default, so every Local-Passed tool you author goes live) plus the Manually exposed tools MultiSelect for per-tool overrides; Default tools (built-in) — the Preset radio (Starter 5 selected here alongside Dev Essentials, Korea Toolkit (free), File Toolkit, Everything, Custom) and the collapsible Advanced curation — applied on top of the preset block exposing Include by tag / category / name and Exclude by tag / name. Confirm writes the change to default-tools-preference.json and updates the live MCP server without a restart.
CLI / yaml override¶
You can pin the preset at boot time without touching the preference file:
./mvnw spring-boot:run -Dspring-boot.run.arguments="\
--spring.ai.playground.default-tools.preset=dev-essentials \
--spring.ai.playground.default-tools.include.tags=korea"
CLI / yaml properties take precedence at boot but are not persisted back to the preference file; clearing them on the next launch reverts to whatever the file says.
Migration note¶
If a defaultToolOverrides.json file from an earlier milestone exists, the M6 build renames it to defaultToolOverrides.json.deprecated on startup once. The new file is default-tools-preference.json in the same tool/save/ directory.
Using Tools in Agentic Chat¶
Tool Studio tools can be used in Agentic Chat through MCP integration. With a tool-capable model and the built-in MCP connection enabled, the model can call those built-in tools during agentic workflows.
Agentic Chat can also call tools exposed by external MCP servers that you explicitly connect and trust.
→ Next: MCP Server — inspect and validate tools exposed by the built-in MCP server or external connections.