Skip to content

chore: cache prompt and refresh config for obot mcp#238

Merged
cjellick merged 2 commits intonanobot-ai:mainfrom
cjellick:mcp-cli-changes
Mar 16, 2026
Merged

chore: cache prompt and refresh config for obot mcp#238
cjellick merged 2 commits intonanobot-ai:mainfrom
cjellick:mcp-cli-changes

Conversation

@cjellick
Copy link
Contributor

@cjellick cjellick commented Mar 16, 2026

This reworks the mcp-cli integration in nanobot. The big functional differences:

  1. There is a single mcp-cli/config.json file for the agent stored at ROOT/.nanobot/mcp-cli/config.json
  2. When a user starts a session, we get all their connected servers and append them to the system prompt. the intent here is to make it so that the agent knows right off the bat about the mcp servers the user has existing connections to. this is a point in time snapshot so that we dont keep changing the system prompt (thus ruining prompt caching).
  3. Eliminates the mcp-cli skill and moves a shorter version to the system prompt. the goal here is to eliminate the getSkill tool call for something that we view as very fundamental to our agent. Because the version that is now in the system prompt is much shorter, we may need to add bits of the skill back in over time, but i'll let real world testing reveal that.

To accomplish the above, this integrates with a new tool on the obot-mcp server called obot_list_connected_mcp_servers, specifically for getting the users's connected MCP servers. That PR is here: obot-platform/obot-mcp-server#4

The logic caches the tools retrieved from obot_list_connected_mcp_servers for 15 minutes. Though the agent can force a refresh of the config through a dedicated new tool call for that.

Signed-off-by: Craig Jellick craig@obot.ai

Inject the Obot MCP integration with two related behaviors:

- prepare the agent-scoped mcp-cli config from connected Obot MCP servers
- append a snapshot of configured MCP servers to the system prompt

The prompt snapshot is cached in session state so it is only generated once
per session, while the local mcp-cli config is refreshed independently when
its cache is stale.

Signed-off-by: Craig Jellick <craig@obot.ai>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR reworks Nanobot’s Obot MCP integration to keep the system prompt stable for caching while still exposing a snapshot of a user’s connected MCP servers, and adds a dedicated tool to refresh the local mcp-cli config on demand.

Changes:

  • Introduces a new nanobot.obot-mcp-cli MCP server with a refreshMCPServerConfig tool and wires it into the system config hook.
  • Fetches and caches a snapshot of connected MCP servers (15 min TTL) and appends a sanitized snapshot to the system prompt.
  • Removes the mcp-cli skill file and updates tests/docs accordingly; adds bash env handling to set MCP_CONFIG_PATH automatically for mcp-cli invocations.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pkg/servers/system/skills_test.go Updates skill expectations after removing the mcp-cli skill.
pkg/servers/system/skills/mcp-cli.md Removes the mcp-cli skill content (now moved into system prompt docs).
pkg/servers/system/server.go Routes bash env setup through new Obot MCP env helper.
pkg/servers/system/obot_mcp_bash_env.go Adds logic to inject MCP_API_KEY and set MCP_CONFIG_PATH for mcp-cli commands.
pkg/servers/system/mcp_servers_test.go Removes tests for dynamic MCP server management from system package.
pkg/servers/system/config_test.go Updates expectations and validates presence of refresh tool based on env configuration.
pkg/servers/system/config.go Delegates Obot MCP wiring to obotmcp.ConfigureIntegration and avoids nanobot.summary.
pkg/servers/system/bash_env_test.go Adds tests for the new bash env behavior.
pkg/servers/obotmcp/server.go Adds new MCP server exposing refreshMCPServerConfig.
pkg/servers/obotmcp/config.go Implements prompt snapshot injection + tool/server wiring.
pkg/servers/obotmcp/fetch.go Adds cached fetch of connected MCP servers via obot_list_connected_mcp_servers.
pkg/servers/obotmcp/mcpcli_config.go Writes the generated mcp-cli config under .nanobot/mcp-cli/config.json.
pkg/servers/obotmcp/dynamic.go Moves dynamic MCP server add/remove logic into obotmcp package.
pkg/servers/obotmcp/server_test.go Adds tests for snapshot sanitization/caching and dynamic server behavior.
pkg/servers/obotmcp/mcpcli_config_test.go Adds tests verifying config generation and refresh error behavior.
pkg/runtime/runtime.go Registers the new nanobot.obot-mcp-cli server.
pkg/config/agents/nanobot.md Adds shortened mcp-cli rules + refresh guidance to the agent prompt.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@cjellick cjellick requested review from g-linville and njhale March 16, 2026 00:12
Copy link
Contributor

@njhale njhale left a comment

Choose a reason for hiding this comment

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

The code looks good to me functionally


- `mcp-cli` is installed and its config is managed automatically. Do not create or edit the config yourself.
- Use these subcommands: `mcp-cli`, `mcp-cli info <server>`, `mcp-cli info <server> <tool>`, `mcp-cli grep "<pattern>"`, `mcp-cli call <server> <tool> '<json>'`.
- Before calling an MCP server tool with `mcp-cli call`, you MUST first:
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm curious as to whether most models will:
A) do this at most once
B) do this every time they attempt to call an MCP server with mcp-cli

Copy link
Contributor Author

Choose a reason for hiding this comment

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

claude does it at most once. doesnt do it on follow up calls ... and this bit is carried forward from the skill. we actually had to add it after initial testing showed the llm would try to get it right by trial and error.


func TestRemoveMCPServer_NonExistentIsNotError(t *testing.T) {
s := NewServer("")
ctx := context.Background()
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: t.Context()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ack. FYI, just so I don't have to soend unnecessary cycles on this, I don't intend to address any nits.

Comment on lines +14 to +15
const configuredMCPServersPromptSessionKey = "configuredMCPServersPrompt"
const configuredMCPServersPromptFieldMaxRunes = 200
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: this and a bunch of other places can use block declarations

Suggested change
const configuredMCPServersPromptSessionKey = "configuredMCPServersPrompt"
const configuredMCPServersPromptFieldMaxRunes = 200
const (
configuredMCPServersPromptSessionKey = "configuredMCPServersPrompt"
configuredMCPServersPromptFieldMaxRunes = 200
)

@cjellick cjellick merged commit 7c0f69f into nanobot-ai:main Mar 16, 2026
4 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.

4 participants