Skip to content

feat(mcp): load MCP servers from JSON#2947

Draft
gautamsirdeshmukh wants to merge 1 commit into
strands-agents:mainfrom
gautamsirdeshmukh:feat/mcp-from-json
Draft

feat(mcp): load MCP servers from JSON#2947
gautamsirdeshmukh wants to merge 1 commit into
strands-agents:mainfrom
gautamsirdeshmukh:feat/mcp-from-json

Conversation

@gautamsirdeshmukh

Copy link
Copy Markdown
Contributor

Description

Related Issues

Documentation PR

Type of Change

Bug fix
New feature
Breaking change
Documentation update
Other (please describe):

Testing

How have you tested the change? Verify that the changes do not break functionality or introduce new warnings.

  • I ran hatch run prepare

Checklist

  • I have read the CONTRIBUTING document
  • I have reviewed and understand every line of code in this PR, including any generated by AI tools, and I can explain why it works
  • My change is focused and reasonably small; I have split unrelated work into separate PRs
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@github-actions github-actions Bot added size/l area-mcp MCP related area-config Related to config-based agents or mcp-config enhancement New feature or request python Pull requests that update python code strands-running labels Jun 24, 2026
it('creates McpClient with url when url is present', async () => {
const clients = await McpClient.loadServers({
'remote-server': { url: 'https://example.com/mcp' },
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Issue: This test asserts only toHaveLength(1) and that other transports weren't called, but never verifies a StreamableHTTPClientTransport was actually constructed with the expected URL — so a regression in URL→streamable-http detection wouldn't be caught here.

Suggestion: Assert the positive case, e.g. expect(StreamableHTTPClientTransport).toHaveBeenCalledWith(new URL('https://example.com/mcp'), ...), mirroring how the SSE tests verify the constructed transport.

}

function baseOptions(name: string, server: McpServerConfig, defaults?: McpClientOptions): McpClientOptions {
const opts: McpClientOptions = { ...defaults, applicationName: defaults?.applicationName ?? name }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Issue: When defaults.applicationName is set, every loaded client gets that same name (defaults?.applicationName ?? name), so the per-server key is discarded and all clients share one identity. The test uses defaults applicationName over server name codifies this.

Suggestion: Confirm this is intended. The more useful default for a multi-server load is usually the distinct server key per client; a shared applicationName from defaults collapses that. If intentional, a one-line doc note on loadServers's defaults param explaining the precedence would prevent surprise.


for (const [name, server] of Object.entries(servers)) {
if (!server || typeof server !== 'object' || Array.isArray(server)) {
throw new Error(`Server "${name}" must be an object, got ${Array.isArray(server) ? 'array' : typeof server}`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Issue: This object-shape validation runs before continueOnError is resolved (line 36) and outside the try/catch. A single malformed entry (e.g. a server value that is a string or array) throws and aborts the entire load — even when the caller passed defaults.continueOnError: true or set it on other servers.

Suggestion: Move this check inside the try block (resolving continueOnError first from defaults for the non-object case), so a bad entry is skipped consistently with every other config error. Worth a test covering "malformed entry skipped under continueOnError".

@github-actions

Copy link
Copy Markdown
Contributor

Assessment: Comment

Solid, focused change: the mcp.tsmcp/ split is clean (no stale sourceLinks or stragglers), build/lint/format and the 33 Node unit tests pass locally, and the default-slot pattern is a nice way to keep Node-only deps out of the browser bundle while still giving an actionable error. One behavioral edge case in continueOnError and a couple of process gaps stand out.

Review themes
  • Correctness: continueOnError doesn't cover the non-object-entry validation path — a single malformed server aborts the whole load (inline comment).
  • API process: This adds a new public API (McpClient.loadServers) and type (McpServerConfig), but the PR description is the unfilled template. Per team/API_BAR_RAISING.md, please populate use cases, example usage, full signatures/defaults, and module exports, and add the api/needs-review label.
  • Docs: No site/ docs or example for the new feature (checklist item left unchecked) — a short MCP-from-JSON example would help discoverability.
  • Tests: Coverage is good overall; a few transport-detection cases assert only count/negatives rather than the constructed transport (inline comment).
  • API design (worth confirming): defaults.applicationName overrides every server's key, collapsing all clients to one identity (inline comment).

Nice work — the env interpolation, exhaustive transport switch, and error messages are clear and well tested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-config Related to config-based agents or mcp-config area-mcp MCP related enhancement New feature or request python Pull requests that update python code size/l

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants