Skip to content

feat(mcp): answer with Markdown and compact typed data - #562

Merged
harlan-zw merged 2 commits into
mainfrom
feat/mcp-compact-responses
Oct 7, 2026
Merged

harlan-zw merged 2 commits into
mainfrom
feat/mcp-compact-responses

Conversation

@harlan-zw

Copy link
Copy Markdown
Collaborator

🔗 Linked issue

Related to #548

❓ Type of change

  • 📖 Documentation
  • 🐞 Bug fix
  • 👌 Enhancement
  • ✨ New feature
  • 🧹 Chore
  • ⚠️ Breaking change

📚 Description

An MCP client puts every tool answer into the model's context. Each tool used to return the public API answer twice: pretty-printed JSON in content, and the same object in structuredContent. The answers also carried fields a model has no use for: likes: 0, empty arrays, full ISO timestamps, long descriptions, whole post texts, and an install command on every list row.

The new presenters in layers/mcp/shared/mcp-presenters.ts shape each answer twice, for two readers:

  • content is Markdown a model can relay as it is. Each Skill is a linked name, its owner/repository, its stars, a trimmed description, and its run command. Some clients read only this.
  • structuredContent is a compact copy of the same facts. Each tool now declares it as an outputSchema, so the MCP SDK checks every answer against it.

Every Skill keeps its repository and its skilld.dev page (VISION principle 1). Run commands come before install commands. get_skill still returns the full SKILL.md, fenced so its own code blocks stay inside. A trending row still states why it is on the board, with one post's author, date, and link. The public API and skilld-sdk are unchanged, so the CLI sees no difference.

Tokens per call on production answers recorded on 2026-10-07, counting content plus structuredContent:

Tool (rows) Before After Change
search_skills (5) 1,534 853 -44%
get_skill 1,337 1,037 -22%
list_tracks (14) 1,509 1,217 -19%
get_track (10) 4,228 1,807 -57%
list_trending (10) 8,690 2,704 -69%
get_repository (9) 4,386 1,822 -58%
submit_repository (indexed, 9) 4,271 71 -98%
install_command 189 118 -38%

get_skill shrinks least because it keeps the full SKILL.md in both forms. The presenter tests run on those recorded answers, saved under test/fixtures/mcp/.

skilld-sdk 0.1.2 types the items of the track list and trending answers as unknown, although its client parses them with trackSummarySchema and trendingSkillSchema. The presenters take their types from those exported schemas.

🤖 AI disclosure: Harlan Agent Kit modified this description. My AI open-source policy.

Every MCP tool returned the public API answer twice: as pretty-printed
JSON in content and again in structuredContent. A ten-row trending call
cost about 8,700 tokens, much of it duplicate fields, empty values, and
install commands on every row.

Presenters in layers/mcp/shared/mcp-presenters.ts now shape each answer:
Markdown a model can relay in content, and a compact copy in
structuredContent that each tool declares as an outputSchema, so the MCP
SDK checks it. Every Skill keeps its repository and its page link. The
public API and the SDK are unchanged.
@harlan-zw harlan-zw added the harlan-agent-review Pull request triage requires an adversarial Review. Adding this label manually always forces one. label Oct 7, 2026
@harlan-github-agent harlan-github-agent Bot added harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. and removed harlan-agent-review Pull request triage requires an adversarial Review. Adding this label manually always forces one. labels Oct 7, 2026
@harlan-zw
harlan-zw merged commit 7433913 into main Oct 7, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant