Skip to content

feat(core): add structuredContent to resources_get and resources_list#1232

Merged
Cali0707 merged 1 commit into
containers:mainfrom
jordigilh:feat/resources-structured-content
Jun 29, 2026
Merged

feat(core): add structuredContent to resources_get and resources_list#1232
Cali0707 merged 1 commit into
containers:mainfrom
jordigilh:feat/resources-structured-content

Conversation

@jordigilh

Copy link
Copy Markdown
Contributor

What

resources_get and resources_list now return structuredContent alongside the existing text output, enabling programmatic MCP clients to consume K8s objects directly without parsing YAML or table strings.

This extracts the K8s resource tool retrofit from #920 as a standalone change, following Recipe 1 from docs/specs/structured-output.md.

Why

We maintain an MCP client (kubernaut) that consumes resources_get and resources_list programmatically to build unstructured.Unstructured objects for fleet metadata caching. Today we have to parse the text content (YAML or table strings) back into structured data, which is fragile and loses type fidelity. With structuredContent, our client can consume the K8s object directly as map[string]any.

The infrastructure is already on main (PR #960: PrintObjStructured, NewToolCallResultFull, ensureStructuredObject) and the structured-output spec documents Recipe 1 as the intended pattern for K8s resource tools — but notes "has no in-tree adopter yet." This PR is that first adopter for the core resource tools.

Changes

pkg/toolsets/core/resources.go (2 handlers, ~10 lines changed):

  • resourcesGet: output.MarshalYaml(ret) + NewToolCallResultoutput.Yaml.PrintObjStructured(ret) + NewToolCallResultFull
  • resourcesList: params.ListOutput.PrintObj(ret) + NewToolCallResultparams.ListOutput.PrintObjStructured(ret) + NewToolCallResultFull

pkg/mcp/resources_test.go (3 new subtests):

  • resources_get returns namespace / returns structured content — asserts StructuredContent is a map with kind, apiVersion, metadata.name
  • resources_list returns namespaces / returns structured content with items — asserts StructuredContent is {"items": [...]} per MCP spec wrapping
  • resources_list as table / returns structured content from table — asserts table output also produces StructuredContent

Backward compatibility

Fully backward compatible. The Content[0].Text field is unchanged — existing clients that only read text see no difference. structuredContent is additive per the MCP spec. This is the same pattern used by configuration_contexts_list (#1151).

Checks

make build    # clean
make lint     # 0 issues
go test ./pkg/mcp/ -run "TestResources$" -v -count=1  # all pass

Refs #920

Made with Cursor

…_list

resources_get and resources_list now return structuredContent alongside
the existing text output, enabling programmatic MCP clients to consume
K8s objects directly without parsing YAML or table strings.

This follows Recipe 1 from docs/specs/structured-output.md, using the
PrintObjStructured + NewToolCallResultFull infrastructure already on
main (PR containers#960). The text Content field is unchanged -- existing clients
that only read Content[0].Text see no difference.

For resources_get (single object, always YAML):
- StructuredContent is map[string]any (the K8s object)

For resources_list (respects --list-output config):
- YAML: StructuredContent is {"items": [...]} with each item as map[string]any
- Table: StructuredContent is {"items": [...]} with column-keyed maps

Refs containers#920

Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Jordi Gil <jgil@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@jordigilh
jordigilh force-pushed the feat/resources-structured-content branch from 2297eb1 to b28bb03 Compare June 28, 2026 21:44
@Cali0707 Cali0707 changed the title feat(resources): add structuredContent to resources_get and resources_list feat(core): add structuredContent to resources_get and resources_list Jun 29, 2026
@Cali0707

Copy link
Copy Markdown
Collaborator

/run-mcpchecker core

@github-actions

Copy link
Copy Markdown
Contributor

mcpchecker MCP Evaluation Results

Commit: b28bb03
Summary: 24/29 tasks passed (82.8%)

Metric Result
Tasks Passed 24/29
Assertions Passed 81/87
Overall ✅ Passed

Diff vs. Baseline (main)

Click to expand mcpchecker diff

📊 Evaluation Results

Metric Base Head Change
Tasks 25/29 (86.2%) 24/29 (82.8%) 🔴 -3.4%
Assertions 86/87 (98.9%) 81/87 (93.1%) 🔴 -5.7%
Tokens 1.1M 1.2M 🔴 +23.6K (+2.1%)
MCP Schema 95.5K 95.5K ➖ 0

❌ Regressions (2)

  • fix-service-with-no-endpoints: PASSED → FAILED - Too many tool calls: expected <= 20, got 25
  • setup-dev-cluster: PASSED → FAILED - verification failed: verify[0] failed: script execution failed: exit status 1
    output: Starting comprehensive verification of dev cluster setup...
    Checking namespaces...
    Namespace 'dev-alice' does not exist
    Cleaning up test resources...
    Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
    Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
    Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
    Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
    Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
    Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
    Cleanup complete.

View full results

@Cali0707 Cali0707 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, thanks @jordigilh !

@Cali0707
Cali0707 merged commit 28a4f1e into containers:main Jun 29, 2026
11 checks passed
@manusa manusa added this to the 0.1.0 milestone Jun 29, 2026
manusa added a commit to marcnuri-forks/kubernetes-mcp-server that referenced this pull request Jun 29, 2026
The Recipe 1 status note said the pattern had no in-tree adopter yet. It now does: resources_get/list landed in containers#1232, and this PR converts namespacesList and the pod list tools. Update the note to name those handlers as the canonical reference and drop the stale wording. Also fix the prose that still described namespacesList as unconverted.

Signed-off-by: Marc Nuri <marc@marcnuri.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

3 participants