Skip to content

feat(mcp): expose synthetic authenticate tool for needs_auth MCPs#27725

Open
msvechla wants to merge 1 commit into
anomalyco:devfrom
msvechla:feat/mcp-needs-auth-synthetic-tool
Open

feat(mcp): expose synthetic authenticate tool for needs_auth MCPs#27725
msvechla wants to merge 1 commit into
anomalyco:devfrom
msvechla:feat/mcp-needs-auth-synthetic-tool

Conversation

@msvechla
Copy link
Copy Markdown
Contributor

@msvechla msvechla commented May 15, 2026

Issue for this PR

Closes #27724

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

For every configured MCP whose status is needs_auth, MCP.tools() now exposes a synthetic <name>__authenticate tool to the agent. The tool's execute calls MCP.authenticate(name) (opens the browser, awaits the callback, rebuilds the transport on success).

This closes the gap where the agent had no way to discover or recover unauthenticated MCPs from inside a conversation. After the synthetic tool returns connected, the real MCP tools are live in the same session — MCP.authenticate ends in createAndStore() which registers the new transport into s.clients immediately, so no restart is required.

The synthetic tool returns the canonical MCP { content: [...] } result shape so downstream consumers reading result.content don't crash.

Filtering

A synthetic is registered only when ALL of:

  • mcp.type === "remote"
  • mcp.oauth !== false
  • s.status[name].status === "needs_auth"

Connected, failed, disabled, and OAuth-disabled MCPs are unaffected.

How did you verify your code works?

  • bun run typecheck clean (passes pre-push hook).
  • bun test test/mcp/lifecycle.test.ts — 21/21 pass.
  • Cleared tokens for a Keycloak-backed MCP, asked the agent to use it. Agent invoked <name>__authenticate, browser opened, OAuth completed, the agent then immediately called the MCP's real tools in the same session.
  • Confirmed the original symptom (agent sees no tools matching the MCP name) reproduces on dev before applying the patch.

Screenshots / recordings

CleanShot 2026-05-15 at 13 13 33

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

For every configured MCP whose status is needs_auth, MCP.tools() now
exposes a synthetic <name>__authenticate tool to the agent. The tool's
execute calls MCP.authenticate(name) (opens the browser, awaits the
callback, rebuilds the transport on success).

This closes the gap where the agent had no way to discover or recover
unauthenticated MCPs from inside a conversation. After the synthetic
tool returns connected, the real MCP tools are live in the same session
because MCP.authenticate ends in createAndStore() which registers the
new transport into s.clients immediately.

The synthetic tool returns the canonical MCP { content: [...] } result
shape so downstream consumers reading result.content don't crash.

A synthetic is registered only when ALL of:
- mcp.type === "remote"
- mcp.oauth !== false
- s.status[name].status === "needs_auth"

Connected, failed, disabled, and OAuth-disabled MCPs are unaffected.

Closes anomalyco#27724
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agents have no awareness of MCPs that need auth

1 participant