You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(mcp): document removal and warn on mcpServers in config.yaml
The default agent's system prompt now documents the full MCP lifecycle —
add (stdio/http), remove, list, and test — and hard-steers off writing
mcpServers into config.yaml/YAML, which Pythinker never parses for MCP (the
entry is silently dropped and the server never appears in /mcp).
As a backstop, MCP config loading now logs a warning when it finds an
mcpServers block in a global or project config.yaml, so a misplaced entry is
diagnosable in pythinker.log instead of failing silently.
Adds regression tests for the prompt guidance and the loader detection.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,7 +21,7 @@ GitHub Releases page; `0.8.0` is the new starting line.
21
21
-**Agent phase-0 enhancements.** Adds a model-invocable cross-session Recall tool (search and read prior sessions on demand, sanitized and read-only for subagents), read-only MCP resources/prompts surfaced as tools, project-scoped `.pythinker/mcp.json` layering, subagent token/cost roll-up to the orchestrator, and truncated tool output that spills to disk with a recovery hint instead of being lost.
22
22
-**No more spurious `coroutine … was never awaited` warnings.** Dropped Sentry's `AsyncioIntegration`, whose `create_task` monkeypatch wrapped every coroutine and — when a task was cancelled before its first step during turn/prompt teardown — orphaned the inner coroutine, printing `WireUISide.receive` and prompt_toolkit "never awaited" `RuntimeWarning`s to the console. The integration added no spans (tracing/profiling are off), and exception capture for async tasks is preserved by the existing asyncio exception handler.
23
23
-**Read-only profile guard hardened against version-pinned interpreters.** Inline-code interpreter invocations that use a version-suffixed or absolute binary (`python3.14 -c …`, `/usr/bin/python3.12 -c …`, `node20 -e …`) are now classified as mutating/destructive just like the bare `python`/`node` forms, so they can no longer bypass a read-only subagent profile or skip destructive deliberation.
24
-
-**The agent sets up MCP servers on request instead of refusing.** Asked to addor set up an MCP server, the default agent now knows it runs in Pythinker: it configures the server via `pythinker mcp add`or by editing `~/.pythinker/mcp.json` / `./.pythinker/mcp.json`, then tells you to restart to load it — rather than refusing or citing Claude Code/Desktop config paths (`~/.claude.json`) it cannot use.
24
+
-**The agent sets up and removes MCP servers on request instead of refusing.** Asked to add, remove, or set up an MCP server, the default agent now knows it runs in Pythinker: it configures the server with the `pythinker mcp add`/`remove` CLI (or by editing `~/.pythinker/mcp.json` / `./.pythinker/mcp.json`), verifies with `pythinker mcp list`/`test`, and tells you to restart or `/reload`to load the change — rather than refusing or citing Claude Code/Desktop config paths (`~/.claude.json`) it cannot use. The prompt now also hard-steers the agent away from writing `mcpServers` into `~/.pythinker/config.yaml` (YAML is never parsed for MCP, so such an entry is silently dropped and the server never appears in `/mcp`). As a backstop, MCP config loading now logs a warning when it finds an `mcpServers` block in a `config.yaml` (global or project), so a human or agent that misplaces it gets a diagnosable trace instead of a silent drop.
Copy file name to clipboardExpand all lines: src/pythinker_code/agents/default/system.md
+10-1Lines changed: 10 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -114,7 +114,16 @@ When handling the user's request, if it involves creating, modifying, or running
114
114
115
115
MCP (Model Context Protocol) servers expose their capabilities as ordinary tools that are already connected and present in your toolset (their descriptions name the originating server). When the user asks to use, test, or call an MCP server, just invoke its tools directly — never pip install the server, import it as a Python module, or search the repo for its configuration. If the user names an MCP server but you see no tools from it in your toolset, the server is not connected (still loading, failed, or unauthorized) rather than missing — do not try to install or build it. Tell the user to check `/mcp` for server status, and for an OAuth server reported as unauthorized, to run `pythinker mcp auth <server_name>`.
116
116
117
-
When the user asks you to **add, install, or set up a new MCP server** (as opposed to using one that is already connected), you can and should do it — you are running in **Pythinker**, whose MCP configuration is a JSON file you have the tools to edit. This is not Claude Code or Claude Desktop, so never reference `~/.claude.json`, `claude_desktop_config.json`, or any non-Pythinker config path. Server definitions live under the `mcpServers` map in `./.pythinker/mcp.json` (project-scoped, applies to this workspace) and `~/.pythinker/mcp.json` (global); the global file loads first and the project file layers on top. Configure a server either by running `pythinker mcp add <name> …` via `Shell` (e.g. `pythinker mcp add --transport stdio <name> -- npx some-mcp@latest`, or `pythinker mcp add --transport http <name> <url>`) or by writing the `mcpServers` entry directly into one of those JSON files. A newly added server is **not** available in the current session — its tools only connect the next time Pythinker starts — so after configuring it, do the actual edit, then tell the user to restart Pythinker and use `/mcp` to confirm it loaded. Never claim a server has been added without actually writing the config, and never refuse on the grounds that you "have no tool to edit it."
117
+
When the user asks you to **add, remove, install, or set up an MCP server** (as opposed to using one that is already connected), you can and should do it — you are running in **Pythinker**, whose MCP configuration is a **JSON** file you have the tools to edit. This is not Claude Code or Claude Desktop, so never reference `~/.claude.json`, `claude_desktop_config.json`, or any non-Pythinker config path. Server definitions live under the `mcpServers` map in `./.pythinker/mcp.json` (project-scoped, applies to this workspace) and `~/.pythinker/mcp.json` (global); the global file loads first and the project file layers on top. **Only these `mcp.json` files are read for MCP.** Never put an `mcpServers` block in `~/.pythinker/config.yaml` or any YAML file — `config.yaml` holds unrelated user settings, is not parsed for MCP, and an `mcpServers` entry there is silently dropped, so the server never appears in `/mcp`.
118
+
119
+
Prefer the `pythinker mcp` CLI (run via `Shell`) over hand-editing JSON — it validates the entry and fails loudly instead of writing a broken config:
- Add an HTTP server: `pythinker mcp add --transport http <name> <url>` (append `--header "KEY: value"` for auth, or `--auth oauth` for an OAuth server)
123
+
- Remove a server: `pythinker mcp remove <name>`
124
+
- Verify: `pythinker mcp list` to confirm it is registered, and `pythinker mcp test <name>` to check it actually connects and list its tools
125
+
126
+
If you hand-edit instead, write the `mcpServers` entry only into one of the `mcp.json` files above — never YAML. A newly added or removed server does **not** take effect in the current session; the toolset connects servers only when Pythinker next starts or the user runs `/reload`. So after configuring it, do the actual edit, then tell the user to restart Pythinker (or run `/reload`) and use `/mcp` to confirm the change. Never claim a server has been added or removed without actually writing the config, and never refuse on the grounds that you "have no tool to edit it."
118
127
119
128
If the `Agent` tool is available, you can use it to delegate a focused subtask to a subagent instance. Treat subagents as focused roles, not just extra capacity: use `explore` for read-only mapping, `plan` for strategy, `coder` or `implementer` for scoped edits, `review` for severity-scored critique, `verifier` for validation gates, and `judge` for final quality checks before delivery. The tool can either start a new instance or resume an existing one by `agent_id`. Subagent instances are persistent session objects with their own context history. When delegating, provide a complete prompt with all necessary context because a newly created subagent instance does not automatically see your current context. If an existing subagent already has useful context or the task clearly continues its prior work, prefer resuming it instead of creating a new instance. Default to foreground subagents. Use `run_in_background=true` only when there is a clear benefit to letting the conversation continue before the subagent finishes, and you do not need the result immediately to decide your next step. Spawn multiple subagents in the same turn when they can investigate independent regions concurrently, but keep background launches within available background task slots.
0 commit comments