Skip to content

fix(mcp): pass the credential store to web_fetch and the classifier - #144

Merged
mudler merged 1 commit into
masterfrom
fix/webfetch-credential-store
Oct 13, 2026
Merged

mudler merged 1 commit into
masterfrom
fix/webfetch-credential-store

Conversation

@mudler-agent

Copy link
Copy Markdown
Collaborator

What

web_fetch and the prompt-injection classifier built their LLM with llmprovider.New, which passes no credential store. Providers whose API key was stored by nib login (regolo, openai, anthropic, …) were resolved with an empty key, so every web_fetch extraction call sent no Authorization header and got 401 Unauthorized: An authentication key is required.

The sub-agent reasoning path was unaffected: newAgentLLM builds its LLM with NewWithTemperatureAndStore, passing s.credStore.

Why

Two LLM-construction paths in nib resolve credentials differently:

Path Store? Affected providers
Sub-agent reasoning (newAgentLLM) yes (s.credStore) all
web_fetch extraction (StartWebMCPServer) no /login-managed only
Prompt-injection classifier (ClassifierForConfig) no /login-managed only

Providers configured with an inline api_key in the YAML never hit this, because the resolver finds the key in config. Only providers authenticated via nib login (key in the credential store, not in config or env) were affected.

How

Build the store from cfg.BaseDir at the same path as NewSession:

filepath.Join(plugin.BaseDirIn(cfg.BaseDir), "credentials.json")

and pass it to llmprovider.NewWithStore in StartWebMCPServer and ClassifierForConfig. The store is a path (reads the file on each call), not shared state, so an independent instance is safe.

Verify

  • go build ./...
  • go test ./provenance/ ./mcp/ ./auth/ ./llmprovider/
  • go test ./chat/ -timeout 120s
  • New test TestWebFetchLLMUsesCredentialStore proves that a key stored only in the credential store is resolved with the store and is empty without it.
  • New test TestWebFetchCredentialStorePath proves the store path matches NewSession's.

web_fetch and the prompt-injection classifier built their LLM with
llmprovider.New, which passes no credential store. Providers whose
API key was stored by `nib login` (regolo, openai, anthropic, …)
were resolved with an empty key, so every web_fetch extraction call
sent no Authorization header and got 401.

The sub-agent reasoning path was unaffected: newAgentLLM builds its
LLM with NewWithTemperatureAndStore, passing s.credStore.

Build the store from cfg.BaseDir at the same path as NewSession
(filepath.Join(plugin.BaseDirIn(cfg.BaseDir), "credentials.json"))
and pass it to llmprovider.NewWithStore in StartWebMCPServer and
ClassifierForConfig. The store is a path, not shared state, so an
independent instance is safe.
@mudler
mudler merged commit 9864b73 into master Oct 13, 2026
2 checks passed
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.

2 participants