Conversation
A Toolbox `tools.yaml` is a list of callable things: it has verbs and no nouns. The word `hotels` never appears in the quickstart config as a thing, only inside SQL, five times, as a table somebody happened to query. So the import cannot map verb to verb -- it reconstructs the nouns from the SQL inside the verbs. `kcmd toolbox import <file|dir>` parses every statement and reads out: a table named anywhere -> an entity, bound to that table a column attributed to one -> a field, expression = the column a join equality in a SELECT -> a relationship, oriented by the FK an INSERT/UPDATE/DELETE tool -> an action with a `sql` executor the tool's parameters -> action parameters, rebound to @name, carrying description/required/default the DML target/verb/columns -> the action's `affects` the source coordinates -> the entity `source`, and the model's `deployment_target` one level up a SELECT tool -> nothing That last one is the point: a lookup over an entity is generated from the model, not stored in it. The AlloyDB quickstart's four tools import to two actions and three lookups nobody wrote. `affects` is derived rather than trusted -- the Toolbox annotations say only "destructive", while the statement says which table, which verb and which columns, and excludes the `id` it matched the row on. Parameter metadata rides on what GoogleCloudPlatform#442 added. Toolbox's `required` is nil-defaults-to-TRUE, the opposite of how an absent flag usually reads, so it is written out explicitly rather than passed on as an ambiguity; a defaulted parameter states its default and not its necessity, since push rejects `required: true` beside a `default`. Both published quickstart configs are the fixtures, unedited, so the tests say what a real configuration yields. Both the flat form and the legacy nested form parse to byte-identical output. What a configuration cannot say is pinned as warnings rather than left to be discovered: no primary key (join columns are named as candidates and nothing is written), no value restrictions on a parameter (they belong in a constraint guarding the action, which the warning says), no toolsets, no templated statements (interpolated before the statement is prepared, so the blast radius cannot be declared), and nothing for a tool that wraps an API instead of SQL. A non-Google source binds to no store, which the import states at import time. osi_schema.test.ts skips the new fixture directory: those are converter input in a foreign format, the way the OWL inputs are Turtle.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
kcmd toolbox import <file|dir>: reads an MCP Toolbox for Databasesconfiguration and reconstructs the semantic model its tools imply.
Why it is not a one-to-one mapping
A Toolbox
tools.yamlis a list of callable things. It has verbs and nonouns — in the published quickstart the word
hotelsnever appears as a thing,only inside SQL, five times, as a table somebody happened to query. A semantic
model is a list of things that are true, with the callable surface derived
from them.
So the import cannot map verb to verb. It parses every statement and
reconstructs the nouns out of the SQL inside the verbs:
expression= the columnSELECTINSERT/UPDATE/DELETEtoolsqlexecutorparameters@name, carrying description / required / defaultaffectssource, and the model'sdeployment_targetone level upSELECTtoolThe last row is the point: a lookup over an entity is generated from the model,
not stored in it. The AlloyDB quickstart's four tools import to two actions and
three lookups nobody wrote, and
kcmd agent toolslists all five.Notes on the mapping
affectsis derived, not trusted. The Toolbox annotations say onlydestructive; the statement says which table, which verb and which columns,and
idis excluded because the statement reads it to find the row rather thanchanging it.
Positional placeholders are rebound by index, not by order of appearance —
the quickstart's
SET checkin_date = CAST($2 ...), checkout_date = CAST($3 ...) WHERE id = $1against parametershotel_id, checkin_date, checkout_datewouldotherwise bind the row's identity to a date.
Join direction is decided from evidence in the text: a column naming the other
table is the foreign-key side. Where nothing in the text decides it, the written
order is kept and a warning says so.
Parameter metadata rides on what #442 added, and the description is the string
that mattered — it is what the agent reads to decide what to put in the
argument, and it now reaches the derived tool listing verbatim. Toolbox's
requiredis nil-defaults-to-true, the opposite of how an absent flagusually reads, so it is written out explicitly rather than passed on as an
ambiguity; a defaulted parameter states its default and not its necessity,
since push rejects
required: truebeside adefault.deployment_targetis written from the source coordinates, which is whatseparates a model that loads from a model that runs — kcmd asks for one before
it offers an agent any tool. A configuration naming two databases gets none and
a warning naming both.
What a configuration cannot say
Reported as warnings rather than guessed at, because each is a real difference
between the formats and not an unfinished corner:
and no key is written, since a wrong key is worse than an absent one
allowedValuesis a rule about theargument, and a rule belongs in a constraint guarding the action, which the
warning says; likewise a parameter filled from a verified claim imports as an
ordinary one, which is a real loosening and is called out
templateParametersare interpolated before thestatement is prepared, so the blast radius cannot be declared ahead of the
call; those tools are skipped
entity out of
A non-Google source (plain
postgres,mysql) produces a model that loads,validates and publishes to Knowledge Catalog but binds to no store. The import
says so at import time rather than leaving it to the first call.
Tests
Both published Toolbox quickstart configurations are the fixtures, unedited,
so the tests say what a real configuration yields rather than what a
purpose-written one does. 30 tests cover the converter and assert the output
loads via
loadModelsand passesvalidatePushRequirements; 1003 pass acrossthe semantic suite.
osi_schema.test.tsskips the new fixture directory — those are converter inputin a foreign format, the way the OWL inputs are Turtle.