Skip to content

feat(mcp): add server instructions to initialize response#389

Merged
Dumbris merged 3 commits into
smart-mcp-proxy:mainfrom
badigit:feature/server-instructions
Jun 13, 2026
Merged

feat(mcp): add server instructions to initialize response#389
Dumbris merged 3 commits into
smart-mcp-proxy:mainfrom
badigit:feature/server-instructions

Conversation

@badigit

@badigit badigit commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add configurable instructions field to top-level Config that is returned in the MCP initialize response via WithInstructions
  • When not set, a built-in default explains the retrieve_toolscall_tool_* workflow and warns against using search_servers for existing tool discovery
  • This helps AI agents understand how to correctly use the proxy without requiring per-client system prompt configuration

Problem

When an MCP client connects to mcpproxy-go, the initialize response contains no instructions field. Agents receive no guidance on how to use the proxy, leading to confusion between retrieve_tools (search existing upstream tools) and search_servers (discover NEW servers from external registries). We observed agents going to external registries to "find" Bitrix24 tools that were already connected as upstreams.

Changes

  • internal/config/config.go: Add Instructions string field to Config
  • internal/server/mcp.go: Add defaultInstructions const, resolveInstructions() helper, pass to mcpserver.WithInstructions()
  • internal/server/mcp_instructions_test.go: Tests for default/custom instructions

Test plan

  • go build ./... passes
  • go test ./internal/server/... -run Instructions -v — all pass
  • Manual: connect MCP client, verify initialize response contains instructions field

@badigit

badigit commented Apr 14, 2026

Copy link
Copy Markdown
Contributor Author

Premature — closing to test in fork first, will reopen when ready.

@badigit badigit closed this Apr 14, 2026
@denis-ros

Copy link
Copy Markdown

Hi @badigit — any updates on this? I noticed it's been sitting closed for a few weeks since the "test in fork first" note.

Bumping it because we just hit the exact problem this fixes: a Claude Code session connected to an mcpproxy deployment had no way to discover which upstreams were available, because the initialize response carries no instructions. The agent kept reaching for unrelated tools until a human nudged it.

The branch still merges cleanly against main and the diff is tight (+49 / -0). Happy to help get it across the line — review, rebase, or anything else useful. Would you like to reopen, or would you prefer someone else carry it forward with attribution?

Thanks!

@badigit badigit reopened this Jun 13, 2026
@badigit

badigit commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

Reopened and refreshed 👋 Thanks for the nudge, @Dumbris — confirmed the gap is still open (no top-level initialize instructions on main; the routing-mode work only added per-call usage_instructions inside the retrieve_tools response, which is complementary).

Pushed one follow-up commit so the default text is routing-mode-aware (Spec 031), instead of assuming retrieve_tools only:

  • retrieve_toolscall_tool_read/write/destructive via the call_with field
  • code_execution for single-step multi-tool orchestration
  • direct mode tools listed as server__tool, called by name

Original search_servers/upstream_servers guidance is kept; the key-terms test now also asserts code_execution and server__tool. Branch still targets main cleanly (diff stays tight). Happy to adjust wording or split the default into per-mode instructions if you'd prefer that.

badigit and others added 3 commits June 13, 2026 20:09
Add configurable Instructions field to Config that is returned in the
MCP initialize response via WithInstructions. When not set, a built-in
default explains the retrieve_tools → call_tool workflow and warns
against using search_servers for existing tool discovery.

This helps AI agents understand how to correctly use the proxy without
requiring per-client system prompt configuration.
Refresh defaultInstructions so the connect-time guidance covers all three
Spec 031 routing modes, not just retrieve_tools:
- retrieve_tools -> call_tool_read/write/destructive via the call_with field
- code_execution for single-step multi-tool orchestration
- direct mode tools listed as server__tool, called by name

Keeps the original search_servers / upstream_servers guidance. Extends the
key-terms test to assert code_execution and server__tool are covered.
…ument config

config.Config.Instructions is surfaced in the OpenAPI spec via
GetConfigResponse, so the generated oas/swagger.yaml and oas/docs.go must be
regenerated (make swagger) and committed — enforced by the "Verify OpenAPI
Artifacts" CI gate. Also documents the field in docs/configuration.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Dumbris Dumbris force-pushed the feature/server-instructions branch from a34214d to 2318444 Compare June 13, 2026 17:11
@Dumbris

Dumbris commented Jun 13, 2026

Copy link
Copy Markdown
Member

Thank you for this contribution, @badigit! 🙏

This is exactly the kind of quality-of-life improvement that helps every agent connecting to mcpproxy — surfacing instructions in the MCP initialize response is a clean, well-targeted fix for the real "agents go hunting in external registries for already-connected tools" problem you described. The routing-mode-aware default and the focused unit tests are a nice touch.

I've pushed two small maintainer follow-ups on top of your commits so we could land it:

  • Regenerated the OpenAPI artifacts (make swaggeroas/swagger.yaml + oas/docs.go), since config.Config is exposed via GetConfigResponse — that's what the Verify OpenAPI Artifacts gate was failing on. Good thing to remember for future config-field PRs: run make swagger and commit the result.
  • Documented the new instructions field in docs/configuration.md.

Your original commits are preserved with full authorship. I also rebuilt the branch onto current main (your fork's history had diverged from upstream, so it couldn't merge cleanly otherwise).

Merging now. We'd love to see more from you — there's a good first-issue list if you're looking for the next one. 🚀

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Dumbris Dumbris left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Small, well-scoped change: adds a configurable instructions field surfaced in the MCP initialize response with a routing-mode-aware default. Verified locally: go build ./... clean, instructions unit tests pass, OpenAPI artifacts regenerated (Verify OpenAPI Artifacts green), and config field documented. Thanks again @badigit!

@Dumbris Dumbris merged commit 25a1e10 into smart-mcp-proxy:main Jun 13, 2026
37 checks passed
Dumbris added a commit that referenced this pull request Jun 13, 2026
Adds a 'MCP server instructions' accordion to Settings → Advanced with an
editable textarea bound to the top-level `instructions` config key via the
key-driven SettingsSection pattern (getPath/buildPartial).

- New `textarea` control type in the settings field catalogue + SettingField.
- Built-in default shown as the placeholder, fetched live from
  /api/v1/status `default_instructions` (never hardcoded in the frontend);
  degrades gracefully when an older core doesn't expose it.
- Empty-means-default: clearing the box (incl. whitespace-only) persists "",
  which the backend maps back to the built-in default.
- vitest unit tests for the textarea control + field catalogue; docs row note.

Related #389
Related MCP-2175
Dumbris added a commit that referenced this pull request Jun 13, 2026
Adds a 'MCP server instructions' accordion to Settings → Advanced with an
editable textarea bound to the top-level `instructions` config key via the
key-driven SettingsSection pattern (getPath/buildPartial).

- New `textarea` control type in the settings field catalogue + SettingField.
- Built-in default shown as the placeholder, fetched live from
  /api/v1/status `default_instructions` (never hardcoded in the frontend);
  degrades gracefully when an older core doesn't expose it.
- Empty-means-default: clearing the box (incl. whitespace-only) persists "",
  which the backend maps back to the built-in default.
- vitest unit tests for the textarea control + field catalogue; docs row note.

Related #389
Related MCP-2175
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.

4 participants