feat: add config-driven MCP server tool registration
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 12/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Da chiarire
- Stato di attività
- Ferma
- Stack tecnologico
- javascript, nodejs
- Ambito
- ai-infra-agents
Direzione di ricerca
Work is already in progress in linked pull request #1337, and the classification scheme for MCP tools (per-server agents list or naming convention) is still undecided, so start by reading that PR and the config schema in src/config/config.js and src/config/schemas/index.js. The tool wiring lives in buildToolConfig() in src/tools/index.js and getToolsForAgentTypes() in src/agent/deepAgents.js. Done would mean a config-driven mcp section that validates, discovers tools at startup, and skips failed servers without crashing, which needs maintainer agreement on the design first.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
Add support for registering Model Context Protocol (MCP) servers via config.yaml so users can expose MCP server tools to the orchestrator and subagents. A new root-level mcp config key defines servers (stdio, Streamable HTTP, or SSE transports), and their tools are discovered at startup and registered alongside the built-in tools.
Motivation
MCP is now the standard way to connect AI agents to external tools and data sources. Today madz only supports its built-in LangChain tools. Users who want to reach an MCP server (filesystem, database, GitHub, Stripe, etc.) have no way to register it without forking the code. A config-driven mcp section lets users plug in any MCP server declaratively, matching how the rest of the config works.
Proposed Solution
Add a root-level mcp config key that defines named MCP servers. Each server specifies a transport and its connection parameters. At startup, madz connects to each server, discovers its tools via MCPAdapter.listTools(), and registers them alongside the built-in tools.
Example config.yaml:
mcp:
servers:
docs:
transport: http
url: https://docs.langchain.com/mcp
local-fs:
transport: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path"]
env:
API_KEY: ${MCP_API_KEY}
legacy:
transport: sse
url: https://example.com/mcp
Supported transports (matching @langchain/mcp-adapters v2):
stdio—{ transport: "stdio", command, args, env? }(local process-spawned server)http—{ transport: "http", url }(Streamable HTTP, the default for remote servers)sse—{ transport: "sse", url }(HTTP + SSE, backwards compatibility)
The adapter stays open for the lifetime of the agent and is closed on shutdown. MCP tools are dynamic (discovered at runtime), so they are appended to the tool list rather than added to the static TOOLS map. A config-driven classification or naming scheme determines which agent types receive which MCP tools.
Alternatives Considered
- Static tool wrappers per server — Rejected: requires hand-writing a wrapper for every MCP server, defeating the purpose of the protocol.
- Using the deprecated
MultiServerMCPClient/mcpServers/getTools()API — Rejected:@langchain/mcp-adaptersv2 deprecates these in favor ofMCPAdapter,{ servers: { ... } }, andlistTools(). - Registering MCP tools only to the orchestrator — Rejected: subagents need access to domain-specific MCP tools too (e.g., a
codingsubagent reaching a filesystem MCP server).
Dependencies
- @langchain/mcp-adapters (v2.0.1+ — the current LangChain MCP adapter;
MCPAdapter+listTools(); requires Node >=20.10.0) - @modelcontextprotocol/sdk (v1.32.1+ — the MCP protocol SDK; requires Node >=18)
- @modelcontextprotocol/client (v2.3.1+ — the new MCP client package used by the adapter; requires Node >=20)
Note: @langchain/mcp-adapters v2 pulls in @modelcontextprotocol/client and @modelcontextprotocol/core as dependencies, so the SDK may not need to be a direct dependency depending on what the adapter re-exports.
Testing Strategy
- Unit tests: Validate the
mcpZod schema (transport enum, required fields per transport, env record shape). Test that invalid config is rejected. - Integration test: Spin up a local stdio MCP server (e.g., the filesystem server) and verify its tools are discovered and registered. Test an http server against a mock endpoint.
- Edge cases: Empty
mcpsection (no-op), a server that fails to connect (should warn and skip, not crash startup), duplicate tool names across servers (naming/prefix collision), env var interpolation.
Security Considerations
- Credential storage: MCP server env vars (e.g., API keys) should resolve from
process.envvia the existing env-var sync, never hardcoded in config.yaml. - Input validation: Validate all
mcpconfig against a Zod schema before use. Validate outbound server URLs against the sandbox URL allowlist (AGENTS.md 1.2 — disallowfile://,gopher://,dict://). - OWASP: stdio servers execute arbitrary local commands — treat this as a privileged capability gated by sandbox permissions. Restrict which agent types can invoke MCP tools. Consider a per-server permission/allowlist.
OpenSpec Note
This project uses OpenSpec for feature development. If this request is approved, I will:
- Run
/opsx:proposeto generate a full proposal with specs and tasks - Iterate on the design before any code is written
- Follow the task-driven implementation workflow
Environment
- OS: Linux 7.0.14-17-pve
- Node.js: v25.8.1
- madz version: 1.106.0
- LLM provider: Unknown — user to confirm
Additional Context
This is a greenfield capability — no MCP handling exists anywhere in the codebase today (no mcp references in src/, config.yaml, or package.json). The feature touches the config schema, the tool builder, and the subagent wiring.
Audit Findings (for Issue #1336)
- src/config/config.js — Root
ConfigSchemaobject. Add anmcpkey here (e.g.,mcp: McpSchema.default({})). This is the single source of truth for config validation and the env-var reverse map. - src/config/schemas/index.js — Re-export the new
McpSchemaalongside the other schemas. - src/config/schemas/mcp.js (new) — Define the Zod schema. Transport is a discriminated union:
stdio(command,args,env?),http(url),sse(url). Usez.discriminatedUnion(transport, [...])to mirror@langchain/mcp-adaptersv2'sConnectionschema. - src/config/loader.js — The
DROPPED_KEYSlist controls which container keys are excluded from env-var names. Ifmcpservers carry env vars (e.g.,mcp.servers.<name>.env.API_KEY), decide whethermcpshould be dropped from the env-var prefix (soMCP_SERVERS_FOO_ENV_API_KEYmaps correctly) or kept. The schema-driven reverse map inbuildReverseMap()handles records via__record__markers. - src/tools/index.js —
buildToolConfig()is where tools are assembled. MCP tools are dynamic (discovered at runtime), so they cannot live in the staticTOOLSmap. Add an async step that constructs anMCPAdapterfromconfig.mcp.servers, callsadapter.listTools(), and appends the returnedDynamicStructuredTool[]to thetoolsarray. The adapter must be kept open for the agent's lifetime and closed on shutdown. - src/agent/deepAgents.js —
createSubagentDefinitions()maps tool names to instances viagetToolsForAgentTypes(classifications, TOOLS), which reads the staticTOOLSmap. MCP tools are not in that map, so they won't be assigned to subagents. Decide how MCP tools are classified (e.g., a per-serveragentslist in config, or a naming convention) and extendgetToolsForAgentTypes()or the subagent builder to include them. - src/agent/deepAgents.js —
createDeepAgent()receivestools: orchestratorTools. MCP tools intended for the orchestrator must be added here. TheORCHESTRATOR_TOOLSset insrc/tools/index.jsfilters orchestrator tools by name — MCP tool names are dynamic, so this filter needs to account for them. - package.json — Add
@langchain/mcp-adapters(^2.0.1). Node engine is already >=24, which satisfies the adapter's >=20.10.0 requirement.
Fix Steps
- Add the dependency — Run
npm install @langchain/mcp-adapters@^2.0.1and confirm it resolves. Verify the adapter'sMCPAdapter,{ servers: { ... } }, andlistTools()API. - Create the schema — Add
src/config/schemas/mcp.jswith aMcpSchemausingz.discriminatedUnion(transport, [...])forstdio/http/sse. Re-export it fromsrc/config/schemas/index.jsand addmcp: McpSchema.default({})toConfigSchemainsrc/config/config.js. - Wire the tool builder — In
src/tools/index.jsbuildToolConfig(), construct anMCPAdapterfromconfig.mcp.servers, calladapter.listTools(), and append the results to thetoolsarray. Handle per-server connection failures gracefully (warn and skip, don't crash startup). - Expose the adapter for shutdown — Return the
MCPAdapter(or a close function) frombuildToolConfig()socreateDeepAgent()can calladapter.close()on shutdown. Track it alongside the agent. - Classify MCP tools for subagents — Decide how MCP tools map to agent types (per-server
agentsconfig list, or a naming convention). ExtendgetToolsForAgentTypes()andcreateSubagentDefinitions()insrc/agent/deepAgents.jsso MCP tools reach the right subagents. - Update orchestrator filtering — Ensure
ORCHESTRATOR_TOOLSfiltering insrc/tools/index.jsdoesn't drop MCP tools intended for the orchestrator (dynamic names). - Write tests — Add
tests/unit/config/schemas/mcp.test.jsfor schema validation, and an integration test that spins up a local stdio MCP server and verifies tool discovery. - Verify — Run
npm run test,npm run lint, andnpm run coverageto confirm no regressions.
- Lingua principale
- JavaScript
- Stelle
- 2
- Fork
- 0
- Merge medio
- 1h 17m
- PR unite (30g)
- 242
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di avoidwork/madz
-
feature
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di avoidwork/madz
Issue simili
-
Remove: Fox Deportes SDApertacheck:passed feeds:remove
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 65/100
iptv-org/database#37176 · 1 commento · 1 reazione ·
I maintainer di solito rispondono entro 9 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
hawk-digital-environments/HAWKI#443 ·
I maintainer di solito rispondono entro 1 giorno
-
documentation v2
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
modelcontextprotocol/python-sdk#3662 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
I maintainer di solito rispondono entro 1 giorno
-
feedback simulation workshop
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
githubnext/gh-aw-workshop#4370 ·
I maintainer di solito rispondono entro 1 giorno