Skip to content
Open
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
21 changes: 21 additions & 0 deletions docs/mcp-tool-behavior-hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# MCP tool behavior hints

The tool catalog publishes all four MCP behavior hints for every registered tool. They describe the full range of accepted arguments, including collection and table behavior. They do not change execution, authorize requests, or deduplicate retries.

## Behavior behind the hints

Provider listing reads configured provider descriptions. It does not invoke embedding or reranking models. Schema validation and database or credential-service access remain within the managed service boundary. Open world identifies tools that can send input to an embedding or reranking provider.

Find and findOne can vectorize a sort clause, and findAndRerank can invoke both embedding and reranking. These tools do not change stored data, but repeated calls can repeat provider work and charges. Their idempotency hint stays false. Sortable single-document deletes can also vectorize a query.

Insert tools cover tables as well as collections. Table inserts can overwrite existing row values, so both tools carry the destructive hint. Missing collection IDs are generated per invocation. Inserts and updates can also vectorize document contents. None of these tools advertises safe replay.

Filtered deleteMany calls stop at the configured deletion limit. A repeated call can remove another batch. Single-document deletes can select a different matching document on a second call. Updates can increment values, replace data, or generate an upsert. A new RPC ID does not prevent any of those effects.

Named schema creates and drops have no additional schema effect when repeated with the same arguments and no intervening changes. Their idempotency hint does not promise the same response. Depending on command options, a second call can report that an object already exists or is missing. Alterations keep a conservative false idempotency hint across their supported operation forms and may remove columns or rename fields.

## Verification

McpToolAnnotationsTest reads the catalog over HTTP and checks all 35 tool definitions. The test covers every hint and fails if a new tool has no reviewed metadata. It does not execute mutations or contact a model provider.

The hint fields follow the [Quarkiverse annotation API](https://github.com/quarkiverse/quarkus-mcp-server/blob/2.0.3/core/runtime/src/main/java/io/quarkiverse/mcp/server/Tool.java) and the [MCP tool contract](https://modelcontextprotocol.io/specification/2026-07-28/server/tools).
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@ public class CollectionCommandTools {

@Inject McpResource mcpResource;

@Tool(description = "Command that alters the column definition in a table.")
@Tool(
description = "Command that alters the column definition in a table.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = false,
openWorldHint = false))
public Uni<ToolResponse> alterTable(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the table") String table,
Expand All @@ -37,7 +44,14 @@ public Uni<ToolResponse> alterTable(
return mcpResource.processCollectionCommand(keyspace, table, command);
}

@Tool(description = "Command that returns count of documents in a collection")
@Tool(
description = "Command that returns count of documents in a collection",
annotations =
@Tool.Annotations(
readOnlyHint = true,
destructiveHint = false,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> countDocuments(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection") String collection,
Expand All @@ -47,7 +61,14 @@ public Uni<ToolResponse> countDocuments(
return mcpResource.processCollectionCommand(keyspace, collection, command);
}

@Tool(description = "Creates a regular index for a column in a table.")
@Tool(
description = "Creates a regular index for a column in a table.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = false,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> createIndex(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the table") String table,
Expand All @@ -70,7 +91,13 @@ public Uni<ToolResponse> createIndex(

@Tool(
description =
"Creates an index on a text column that can be used for lexical filtering and sorting.")
"Creates an index on a text column that can be used for lexical filtering and sorting.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = false,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> createTextIndex(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the table") String table,
Expand All @@ -91,7 +118,14 @@ public Uni<ToolResponse> createTextIndex(
return mcpResource.processCollectionCommand(keyspace, table, command);
}

@Tool(description = "Creates an index on a vector column that can be used for vector sorting.")
@Tool(
description = "Creates an index on a vector column that can be used for vector sorting.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = false,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> createVectorIndex(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the table") String table,
Expand All @@ -114,7 +148,13 @@ public Uni<ToolResponse> createVectorIndex(

@Tool(
description =
"Command that finds documents based on the filter and deletes them from a collection")
"Command that finds documents based on the filter and deletes them from a collection",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = false,
openWorldHint = false))
public Uni<ToolResponse> deleteMany(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand All @@ -127,7 +167,14 @@ public Uni<ToolResponse> deleteMany(
return mcpResource.processCollectionCommand(keyspace, collection, command);
}

@Tool(description = "Command that finds a single document and deletes it from a collection")
@Tool(
description = "Command that finds a single document and deletes it from a collection",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> deleteOne(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand All @@ -139,7 +186,14 @@ public Uni<ToolResponse> deleteOne(
return mcpResource.processCollectionCommand(keyspace, collection, command);
}

@Tool(description = "Command that returns estimated count of documents in a collection")
@Tool(
description = "Command that returns estimated count of documents in a collection",
annotations =
@Tool.Annotations(
readOnlyHint = true,
destructiveHint = false,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> estimatedDocumentCount(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection") String collection) {
Expand All @@ -148,7 +202,14 @@ public Uni<ToolResponse> estimatedDocumentCount(
return mcpResource.processCollectionCommand(keyspace, collection, command);
}

@Tool(description = "Finds documents using vector and lexical sorting, then reranks the results.")
@Tool(
description = "Finds documents using vector and lexical sorting, then reranks the results.",
annotations =
@Tool.Annotations(
readOnlyHint = true,
destructiveHint = false,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> findAndRerank(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection") String collection,
Expand All @@ -170,7 +231,14 @@ public Uni<ToolResponse> findAndRerank(
return mcpResource.processCollectionCommand(keyspace, collection, command);
}

@Tool(description = "Command that finds JSON documents from a collection.")
@Tool(
description = "Command that finds JSON documents from a collection.",
annotations =
@Tool.Annotations(
readOnlyHint = true,
destructiveHint = false,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> find(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand All @@ -185,7 +253,13 @@ public Uni<ToolResponse> find(

@Tool(
description =
"Command that finds a single JSON document from a collection and deletes it. The deleted document is returned")
"Command that finds a single JSON document from a collection and deletes it. The deleted document is returned",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> findOneAndDelete(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand All @@ -199,7 +273,13 @@ public Uni<ToolResponse> findOneAndDelete(

@Tool(
description =
"Command that finds a single JSON document from a collection and replaces it with the replacement document.")
"Command that finds a single JSON document from a collection and replaces it with the replacement document.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> findOneAndReplace(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand All @@ -216,7 +296,13 @@ public Uni<ToolResponse> findOneAndReplace(

@Tool(
description =
"Command that finds a single JSON document from a collection and updates the values provided in the update clause.")
"Command that finds a single JSON document from a collection and updates the values provided in the update clause.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> findOneAndUpdate(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand All @@ -230,7 +316,14 @@ public Uni<ToolResponse> findOneAndUpdate(
return mcpResource.processCollectionCommand(keyspace, collection, command);
}

@Tool(description = "Command that finds a single JSON document from a collection.")
@Tool(
description = "Command that finds a single JSON document from a collection.",
annotations =
@Tool.Annotations(
readOnlyHint = true,
destructiveHint = false,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> findOne(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand All @@ -243,7 +336,14 @@ public Uni<ToolResponse> findOne(
return mcpResource.processCollectionCommand(keyspace, collection, command);
}

@Tool(description = "Command that lists all available indexes in a table.")
@Tool(
description = "Command that lists all available indexes in a table.",
annotations =
@Tool.Annotations(
readOnlyHint = true,
destructiveHint = false,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> listIndexes(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the table") String table,
Expand All @@ -254,7 +354,14 @@ public Uni<ToolResponse> listIndexes(
return mcpResource.processCollectionCommand(keyspace, table, command);
}

@Tool(description = "Command that inserts multiple JSON documents to a collection.")
@Tool(
description = "Command that inserts multiple JSON documents to a collection.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> insertMany(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand All @@ -266,7 +373,14 @@ public Uni<ToolResponse> insertMany(
return mcpResource.processCollectionCommand(keyspace, collection, command);
}

@Tool(description = "Command that inserts a single JSON document to a collection.")
@Tool(
description = "Command that inserts a single JSON document to a collection.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> insertOne(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand All @@ -278,7 +392,13 @@ public Uni<ToolResponse> insertOne(

@Tool(
description =
"Command that finds documents from a collection and updates it with the values provided in the update clause.")
"Command that finds documents from a collection and updates it with the values provided in the update clause.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> updateMany(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand All @@ -292,7 +412,13 @@ public Uni<ToolResponse> updateMany(

@Tool(
description =
"Command that finds a single JSON document from a table or collection and updates the values provided in the update clause.")
"Command that finds a single JSON document from a table or collection and updates the values provided in the update clause.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = false,
openWorldHint = true))
public Uni<ToolResponse> updateOne(
@ToolArg(description = "Name of the keyspace") String keyspace,
@ToolArg(description = "Name of the collection/table") String collection,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@ public class GeneralCommandTools {

@Inject McpResource mcpResource;

@Tool(description = "Command that creates a keyspace.")
@Tool(
description = "Command that creates a keyspace.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = false,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> createKeyspace(
@ToolArg(description = "Required name of the new Keyspace") String name,
@ToolArg(description = "Options for creating a new keyspace.", required = false)
Expand All @@ -30,22 +37,43 @@ public Uni<ToolResponse> createKeyspace(
return mcpResource.processCommand(() -> mcpResource.buildDatabaseContext(command), command);
}

@Tool(description = "Command that deletes a Keyspace.")
@Tool(
description = "Command that deletes a Keyspace.",
annotations =
@Tool.Annotations(
readOnlyHint = false,
destructiveHint = true,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> dropKeyspace(
@ToolArg(description = "Required name of the Keyspace to remove") @NotEmpty String name) {

var command = new DropKeyspaceCommand(name);
return mcpResource.processCommand(() -> mcpResource.buildDatabaseContext(command), command);
}

@Tool(description = "Command that lists all available keyspaces")
@Tool(
description = "Command that lists all available keyspaces",
annotations =
@Tool.Annotations(
readOnlyHint = true,
destructiveHint = false,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> findKeyspaces() {

var command = new FindKeyspacesCommand();
return mcpResource.processCommand(() -> mcpResource.buildDatabaseContext(command), command);
}

@Tool(description = "Lists the available Embedding Providers for this database.")
@Tool(
description = "Lists the available Embedding Providers for this database.",
annotations =
@Tool.Annotations(
readOnlyHint = true,
destructiveHint = false,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> findEmbeddingProviders(
@ToolArg(
description =
Expand All @@ -57,7 +85,14 @@ public Uni<ToolResponse> findEmbeddingProviders(
return mcpResource.processCommand(() -> mcpResource.buildDatabaseContext(command), command);
}

@Tool(description = "Lists the available Reranking Providers for this database.")
@Tool(
description = "Lists the available Reranking Providers for this database.",
annotations =
@Tool.Annotations(
readOnlyHint = true,
destructiveHint = false,
idempotentHint = true,
openWorldHint = false))
public Uni<ToolResponse> findRerankingProviders(
@ToolArg(
description =
Expand Down
Loading
Loading