Repository navigation
[EPIC-D][LOU-D20] mcpServers is a first-class, validated AgentSpec field - #73
Merged
Merged
Conversation
Adds AgentSpec.mcpServers (stdio command/args/env or HTTP url/headers) with zod validation and entry-named errors, makes `loushy doctor` read the validated field instead of the raw file, and exposes the parsed servers on specToAgent()'s result (connecting is TODO(LOU-D20.2)). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR
# Conflicts: # CHANGELOG.md
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.
What
AgentSpec.mcpServers?: Record<string, McpServerSpec>whereMcpServerSpecis stdio (command, optionalargs,env) or HTTP (url, optionalheaders), validated by zod withAgentSpec validation failed: ...messages. Issue paths carry the entry name (mcpServers.<name>...), soloadSpecerrors name the entry.loushy doctornow reads MCP servers from the validated spec (spec.mcpServers); the raw-file reader (DoctorEnvironment.readRawSpec) is removed.specToAgent()does NOT connect the servers: it returnsSpecAgent(=SimpleAgent & { mcpServers }) exposing the parsed servers, with a documentedTODO(LOU-D20.2).docs/configuration.md(YAML block + type-checked ts snippet), CHANGELOG entry, regeneratedllms-full.txt.Why
MCP servers were read by doctor from the raw YAML/JSON because the schema had no field. Making it a validated field gives one source of truth and early, named errors.
Connect vs TODO decision:
specToAgent()is synchronous and the SDK has no helper that opens an MCP client transport (stdio spawn / HTTP); onlyloadMcpTools(client, ...)for an already-connectedClientexists. Adding transports, lifecycle/cleanup and an async variant is clearly more than ~40 lines, so I exposedagent.mcpServersfor a host to connect and leftTODO(LOU-D20.2).Backward compatibility: specs without the field are unchanged. The pre-existing list form doctor accepted (
[{ name, command | url }], unnamed entries keyed#N) is normalized into the map by the schema, so such specs keep validating and doctor ids (spec.mcp.#3) are unchanged. Doctor message text is unchanged.Test changes in existing files: removed doctorCore's raw-spec tests ("list or map", "survives an unreadable raw spec") and replaced them with tests against the validated field;
doctor.test.tsnow assertsloadSpec(...).mcpServersinstead ofreadRawSpec. These changed becausereadRawSpecno longer exists, not because of message text.Acceptance criteria
AgentSpec.mcpServers?: Record<string, McpServerSpec>, stdio/HTTP union, zod-validated withAgentSpec validation failed:messages; existing specs validate unchangedloadSpecsurfaces bad entries with the entry name in the messageloushy doctorreads from the validated spec; existing doctor tests pass (only tests tied toreadRawSpecwere changed, see above)specToAgent: documentedTODO(LOU-D20.2)+ parsedmcpServersexposed on the result (reason above)docs/configuration.md, llms regeneratedHow verified
npx tsc --noEmit- passnpm run lint- 0 errors, 433 warnings (same as main's 433)npm run test:types- pass (4 files, 19 tests)npx vitest run- 133 files passed, 1962 passed / 3 skipped (needsnpm run buildfirst for CLI/dist-dependent tests)npm run build && npm run build --workspace=packages/create-loushy-agent- passnpm run docs:verify-snippets -- --skip-build- all 85 snippets type-checknpm run docs:llms:check- passnpm run test:coverage- 133 files passed;npm run fallow- exit 0 (after splitting a complexity-flagged refine intomcpServerProblem)🤖 Generated with Claude Code
https://claude.ai/code/session_016bY29ibQgv3MDdjAbUT4YR
Generated by Claude Code