Package io.meeds.mcp.server.util
Class McpToolUtils
java.lang.Object
io.meeds.mcp.server.util.McpToolUtils
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final StringName of theExoFeatureServicefeature carrying the MCP server's global on/off flag.static final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final Stringstatic final String -
Method Summary
Modifier and TypeMethodDescriptionstatic StringformatDate(Long time) static StringformatDate(Date date) static final ToolDefinitionMethodsfromJsonString(String value) static ToolDefinitionMethodsfromJsonStringBase64(String value) Same asfromJsonString(String)for the persisted form, whose input schemas are base64 encoded.static StringResolves the AI chat conversation in which the current Tool is executed.static StringResolves the user on behalf of whom the current Tool is executed: the kernelConversationStateidentity when set, else, for the internal client-credentials call only, theTOOL_CONTEXT_USER_NAME_PARAMrequest header, else the authenticated principal.static ObjectgetMethodToolFieldValue(org.springframework.ai.tool.method.MethodToolCallback toolCallback, String fieldName) Reads a private field of a Spring AIMethodToolCallback, which exposes no accessor for the tool object and method it wraps.static TimeZoneReads the acting user's time zone from their platform profile, so that a date a tool returns reads the same as the one the web UI shows them.static booleanisInternalClientAuthentication(org.springframework.security.core.Authentication authentication) Tells whether the authentication is the internal client-credentials call: a bearer token whose introspection attributes nameMCP_OAUTH2_CLIENT_CREDENTIALS_REGISTRATION_IDas the owning OAuth client (OAuth2TokenIntrospectionClaimNames.CLIENT_ID, set by the authorization server from the registered client the token was issued to).static booleanisInternalClientPrincipal(Map<String, Object> tokenAttributes) Same question asisInternalClientAuthentication(Authentication), asked one step earlier: at token introspection time there is noAuthenticationyet, only the introspected principal.static StringmarkdownToHtml(String markdown) Renders Markdown a tool produced into the HTML the platform's content fields expect, and leaves it untouched when it already carries HTML — a tool's output is not always Markdown, and rendering HTML twice mangles it.static List<SimpleToolDefinition> parseToolDefinitions(URL url) Parses oneai-tool-definitions.jsonresource.static StringtoCamelCase(String name) static Datestatic StringtoJsonStringBase64(ToolDefinitionMethods toolDefinitions) Serializes tool definitions to their persisted form, base64 encoding each input schema.static StringtoSnakeCase(String name)
-
Field Details
-
AI_AGENT_TOOL_EXECUTION_EVENT
- See Also:
-
MCP_OAUTH2_CLIENT_CREDENTIALS_REGISTRATION_ID
- See Also:
-
MCP_SERVER_FEATURE
Name of theExoFeatureServicefeature carrying the MCP server's global on/off flag. The per-user audience is not a feature plugin: it is resolved byMcpServerAudienceServicealone.- See Also:
-
EVENT_MCP_SERVER_AUDIENCE_UPDATED
- See Also:
-
TOOL_CONTEXT_USER_NAME_PARAM
- See Also:
-
TOOL_CONTEXT_ID_PARAM
- See Also:
-
TOOL_CONTEXT_CONVERSATION_ID_PARAM
- See Also:
-
TOOL_CONTEXT_ID
-
TOOL_READ_SCOPE
- See Also:
-
TOOL_WRITE_SCOPE
- See Also:
-
TOOL_WRITE_APPROVE_SCOPE
- See Also:
-
EVENT_TOOL_UPDATED
- See Also:
-
AI_AGENT_TOOL_APPROVED_PARAM
- See Also:
-
AI_AGENT_TOOL_USERNAME_PARAM
- See Also:
-
AI_AGENT_TOOL_CONVERSATION_ID_PARAM
- See Also:
-
AI_AGENT_TOOL_INPUT_PARAM
- See Also:
-
AI_AGENT_TOOL_OUTPUT_PARAM
- See Also:
-
AI_AGENT_TOOL_TYPE_PARAM
- See Also:
-
AI_AGENT_TOOL_DURATION_PARAM
- See Also:
-
AI_AGENT_TOOL_START_TIME_PARAM
- See Also:
-
AI_AGENT_TOOL_ID_PARAM
- See Also:
-
AI_AGENT_TOOL_NAME_PARAM
- See Also:
-
AI_AGENT_TOOL_EXEC_COMPLETED_PARAM
- See Also:
-
-
Method Details
-
parseToolDefinitions
Parses oneai-tool-definitions.jsonresource.- Parameters:
url- the resource to read- Returns:
- the tool definitions it declares, empty when it cannot be read
-
fromJsonString
- Parameters:
value- the tool definitions as a JSON string- Returns:
- the parsed definitions, or null when the string is blank
-
fromJsonStringBase64
Same asfromJsonString(String)for the persisted form, whose input schemas are base64 encoded.- Parameters:
value- the persisted tool definitions- Returns:
- the parsed definitions with decoded schemas, or null when blank
-
toJsonStringBase64
Serializes tool definitions to their persisted form, base64 encoding each input schema.- Parameters:
toolDefinitions- the definitions to serialize- Returns:
- the JSON string to persist
-
toSnakeCase
- Parameters:
name- a Java method name- Returns:
- its snake-case form, which is the MCP tool name
-
toCamelCase
- Parameters:
name- a snake-case name- Returns:
- its camel-case form
-
getMethodToolFieldValue
public static Object getMethodToolFieldValue(org.springframework.ai.tool.method.MethodToolCallback toolCallback, String fieldName) throws NoSuchFieldException, IllegalAccessException Reads a private field of a Spring AIMethodToolCallback, which exposes no accessor for the tool object and method it wraps.- Parameters:
toolCallback- the callback to introspectfieldName- the field to read- Returns:
- the field value
- Throws:
NoSuchFieldException- when the field does not existIllegalAccessException- when it cannot be read
-
getCurrentUserName
Resolves the user on behalf of whom the current Tool is executed: the kernelConversationStateidentity when set, else, for the internal client-credentials call only, theTOOL_CONTEXT_USER_NAME_PARAMrequest header, else the authenticated principal. The header is trusted under the gate ofgetInternalToolCallRequest()and nowhere else; the internal call is recognized by the OAuth client that owns the token (isInternalClientAuthentication(Authentication)), never by the token subject, so a user whose login happens to be the internal client id is just that user.- Returns:
- the user name, or null when no user can be resolved
-
getCurrentConversationId
Resolves the AI chat conversation in which the current Tool is executed. The id travels in theTOOL_CONTEXT_CONVERSATION_ID_PARAMrequest header set by the internal MCP client and is trusted under exactly the same gate as the user name (getInternalToolCallRequest()): any other caller, an external OAuth MCP client for instance, gets null whatever it sends, so it can never choose the conversation its Tool executions are recorded in.- Returns:
- the conversation id, or null when the call isn't the internal client's or carries no conversation
-
isInternalClientAuthentication
public static boolean isInternalClientAuthentication(org.springframework.security.core.Authentication authentication) Tells whether the authentication is the internal client-credentials call: a bearer token whose introspection attributes nameMCP_OAUTH2_CLIENT_CREDENTIALS_REGISTRATION_IDas the owning OAuth client (OAuth2TokenIntrospectionClaimNames.CLIENT_ID, set by the authorization server from the registered client the token was issued to). The token subject is deliberately not consulted: it is the client id for a client-credentials grant but the user login for a user grant, so a user whose login is the internal client id would otherwise enter the internal path with an ordinary user token.- Parameters:
authentication- the currentAuthentication, may be null- Returns:
- true when the token belongs to the internal client, else false
-
isInternalClientPrincipal
Same question asisInternalClientAuthentication(Authentication), asked one step earlier: at token introspection time there is noAuthenticationyet, only the introspected principal. Both enforcement points of the MCP access gate must recognize the internal client the same way or the exemption means two different things, so both go throughisInternalClientId(Object)and neither consults the token subject.- Parameters:
tokenAttributes- the introspected token attributes, may be null- Returns:
- true when the token belongs to the internal client, else false
-
markdownToHtml
Renders Markdown a tool produced into the HTML the platform's content fields expect, and leaves it untouched when it already carries HTML — a tool's output is not always Markdown, and rendering HTML twice mangles it.- Parameters:
markdown- the tool output, may be null or blank- Returns:
- the rendered HTML, or the input unchanged when it is blank, when it already looks like HTML, or when rendering failed
-
toDate
- Parameters:
date- an ISO-8601 date as a tool argument carries it, may be null or blank- Returns:
- the parsed date, or null when nothing was given
-
formatDate
- Parameters:
time- an epoch timestamp in milliseconds, may be null or non-positive- Returns:
- the ISO-8601 representation in the current user's time zone, or null when no usable timestamp was given
-
formatDate
- Parameters:
date- the date to render, may be null- Returns:
- the ISO-8601 representation in the current user's time zone, or null when no date was given
-
getUserTimeZone
Reads the acting user's time zone from their platform profile, so that a date a tool returns reads the same as the one the web UI shows them.- Returns:
- the user's time zone, or null when the profile carries none — the caller then falls back to the server's default
-