In-process tools for Spring AI
The second starter hands the same operation files to a ChatClient, without a
Model Context Protocol (MCP) server:
<dependency>
<groupId>io.gatool</groupId>
<artifactId>gatool-in-process-spring-boot-starter</artifactId>
<version>0.1.0</version>
</dependency>
@Bean
ChatClient assistant(ChatClient.Builder builder, GAToolCallbacks tools) {
return builder.defaultTools(tools.toolCallbackProvider()).build();
}
ChatClient.Builder comes from a Spring AI chat model starter, such as
spring-ai-starter-model-anthropic. The application adds that starter beside
this one.
Files under gatool/in-process/, the in-process folder, reach the ChatClient.
Files under gatool/mcp/, the MCP folder, reach the MCP server. One
application can therefore serve both with different lists.
An in-process tool runs inside the application. Three things stay out of its
path: the scopes an operation file lists, the rate limiter, and Spring AI's
ToolContext. The tool takes its arguments from the model's text alone. The
caller is the application itself. Under token-exchange and under
gatool.api.credentials.unsafe.forward-client-tokens, the forwarded token, the
caller is the user on the thread that calls the tool. Both strategies read the
token from that thread's security context. Under a per-caller credential,
GATool refuses a call where the thread's security context may belong to another
caller. The caller and the request
thread describes that refusal.
The arguments travel to the API as the model wrote them. An argument the input schema does not name is forwarded as sent. An argument the model left out stays out. A misspelt name therefore gets the API's own answer for the unnamed argument: its default, or the API's own error. The MCP path refuses such a call before the API sees it. A later minor release may validate arguments before the call, as the MCP path does.
A scope list on an in-process file states what the application has to enforce
itself. The application enforces it with method security on the resolver, or in
the code that builds the ChatClient. The startup listing, the list of tools
GATool prints at INFO when the application starts, says so beside the tool.
Spring AI's own spring.ai.tool observation covers each call. A refusal
reaches the model as a plain sentence of text. One example is a credential the
configured strategy could not supply. An answer arrives as the same GraphQL
envelope the MCP path returns.