Skip to content

Feat/mcp tooling#48

Open
jlee-kitware wants to merge 4 commits into
feat/custom-data-filesfrom
feat/mcp-tooling
Open

Feat/mcp tooling#48
jlee-kitware wants to merge 4 commits into
feat/custom-data-filesfrom
feat/mcp-tooling

Conversation

@jlee-kitware

Copy link
Copy Markdown
Collaborator

Stacked on #47, which is stacked on #46. The diff here is only the four commits on top.

Tool calls from local models were silently discarded. Against Ollama, vtk-mcp appeared
to do nothing: the server was reachable, tools were sent, and the model was deciding to call
them, but nothing ran. Quantized local models often emit the call as plain JSON in the
message content instead of populating tool_calls, so the response comes back with
finish_reason: "stop" and the loop treated the JSON as the final answer. We now detect a
tool call that arrived as text (bare JSON, or a <tool_call> block) whose name matches a
known tool, execute it, and feed the result back like a native call. Anyone running against
a local backend is affected by this.

Logging. A "Log tool calls to the server console" setting (off by default). Each call
logs its name, arguments, and a short result as it happens. Previously there was no way to
tell whether the model was using tools at all. Persists in config.

Agentic retrieval toggle. Optionally skip the pre-injected RAG context, which runs to
roughly 4.5k tokens and is a large share of a 16k local context window. Note it does not by
itself make a confident quantized model call tools under tool_choice="auto". Off by
default.

Known gap. Tool use is still opportunistic: I used qwen2.5-coder-32b-ctx16 and asked about the streamtracer API, the model
answered from memory and hallucinated SetMaximumErrorTolerance (really SetMaximumError),
which a vtk_get_class_info call would have caught. The fix is deterministic
post-validation, calling the vtk-mcp validators on generated code ourselves. Follow-up.

Add a "Log tool calls to the server console" toggle in the vtk-mcp settings
(off by default, disabled without a server URL). When on, each tool call logs
its name, arguments, and a short result at INFO level, and the loop logs when
it hits the round cap without a final response. The flag threads from state
through generate to the tool-calling loop; when off, behavior is unchanged.
Quantized local models (e.g. qwen2.5-coder via Ollama) often return a tool call
as plain content instead of populating tool_calls, so finish_reason is "stop"
and the agentic loop never ran the tool: tools appeared dead even though the
model was trying to call them. Detect a tool call that arrived as text (a bare
JSON object with name/arguments, or a <tool_call> block) whose name matches a
known tool, execute it, and feed the result back like a native call. Answers,
which are explanation/code tagged, are never misread as calls.
log_tool_calls was session-only, so it reset to off every launch. Include it in
the exported config and restore it on startup, alongside mcp_url/top_k.
Add a setting to skip get_enriched_context so the model works from tools instead
of a large pre-injected RAG block (which also frees ~4.5k tokens of context).
Threaded from state through generate; persisted in config; off by default.

Note: on its own this does not make a confident quantized local model call
tools under tool_choice="auto"; deterministic post-validation is the reliable
path and is a separate change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant