feat(mcp): name per-server concerns and default posture in mcp list - #241
Merged
Zongwei9888 merged 1 commit intoSep 27, 2026
Merged
Conversation
`mcp list` showed configuration/auth/runtime state and left the operator to cross-reference `--json` for anything that should give them pause. CONCERNS states only what is explicitly configured or actually broken: `disabled`, `missing-env`, `sends-credential`. The two permissive readings that hold for every server which never made the choice -- an absent `enabledTools` resolves to every tool (core/config.py substitutes `["*"]`), and `auto`/`approve` add no MCP approval gate (core/harness/permissions.py) -- are stated once in a footer line instead of repeated on every row. Measured on a six-server config, the per-row form lit up 4 of 5 enabled rows with the same two defaults, which is how an operator learns to ignore the column. Only key names are read, never credential values. The NAME column is now width-aware, so a long server name cannot skew the table. Rows whose configuration did not parse stay out of the footer: the posture fields on those rows are defaults filled in by the invalid-row builder in mcp_service.py, not choices anyone made, so counting them would report a posture that was never configured. Rendered in cli/mcp_cli.py only: every reading is a pure function of fields that already exist on the wire, so McpServerInfo keeps its 33 fields and the desktop fixtures are untouched. Tests assert the rendered stdout -- the table cells and the footer counts -- so re-adding a default-triggered label to every row fails loudly, and so does counting an unparsed row.
Zongwei9888
added a commit
that referenced
this pull request
Sep 27, 2026
…e in mcp list mcp list gains a CONCERNS column (disabled, missing-env, sends-credential) and a one-line count of enabled servers that expose every tool or add no MCP approval gate, derived only from fields McpServerInfo already exposes. Repair: document the column in the headless guide. Contributed by raymondginger2018-sudo.
Collaborator
|
Merged into One small addition on our side: a paragraph in |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the operator-facing risk summary asked for in #220, in the shape that PR's closing note specified:
What this does
mcp listshowed configuration/auth/runtime state and left the operator to cross-reference--jsonfor anything that should give them pause. It gains aCONCERNScolumn plus one footer line, derived only from fieldsMcpServerInfoalready exposes -- no protocol change, no new module, no new config, no new dependency.A row lists only what is explicitly configured or actually broken:
disabledmissing-envsends-credentialThe other two readings hold for every server that never made the choice -- an absent
enabledToolsresolves to every tool (core/config.pysubstitutes["*"]), andauto/approveadd no MCP approval gate (core/harness/permissions.py) -- so they are stated once in a footer line instead of repeated on every row:Measured on a six-server config, the per-row form lit up 4 of 5 enabled rows with the same two defaults, which is how an operator learns to ignore the column.
Only key names are read, never credential values. The
NAMEcolumn is now width-aware, so a long server name cannot skew the table. Rows whose configuration did not parse stay out of the footer: the posture fields on those rows are defaults filled in by the invalid-row builder inmcp_service.py, not choices anyone made.Tests
tests/test_mcp_cli.pyasserts the rendered stdout -- the table cells and the footer counts -- so re-adding a default-triggered label to every row fails loudly, and so does counting an unparsed row.Scope
cli/mcp_cli.py+73/-2 andtests/test_mcp_cli.py+72/-0. Every reading is a pure function of fields that already exist on the wire, soMcpServerInfokeeps its 33 fields and the desktop fixtures are untouched. Rebased on currentmain(behind_by: 0, no conflicts).