Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

feat: add config-driven MCP server tool registration

Aperta
#1,336 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@avoidwork ci sta già lavorando.

Dal 9/10/2026.

  • #1337 di @avoidwork — aperta

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

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

approved feature in progress

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-adapters v2 deprecates these in favor of MCPAdapter, { servers: { ... } }, and listTools().
  • Registering MCP tools only to the orchestrator — Rejected: subagents need access to domain-specific MCP tools too (e.g., a coding subagent 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 mcp Zod 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 mcp section (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.env via the existing env-var sync, never hardcoded in config.yaml.
  • Input validation: Validate all mcp config against a Zod schema before use. Validate outbound server URLs against the sandbox URL allowlist (AGENTS.md 1.2 — disallow file://, 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:

  1. Run /opsx:propose to generate a full proposal with specs and tasks
  2. Iterate on the design before any code is written
  3. 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 ConfigSchema object. Add an mcp key 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 McpSchema alongside 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). Use z.discriminatedUnion(transport, [...]) to mirror @langchain/mcp-adapters v2's Connection schema.
  • src/config/loader.js — The DROPPED_KEYS list controls which container keys are excluded from env-var names. If mcp servers carry env vars (e.g., mcp.servers.<name>.env.API_KEY), decide whether mcp should be dropped from the env-var prefix (so MCP_SERVERS_FOO_ENV_API_KEY maps correctly) or kept. The schema-driven reverse map in buildReverseMap() 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 static TOOLS map. Add an async step that constructs an MCPAdapter from config.mcp.servers, calls adapter.listTools(), and appends the returned DynamicStructuredTool[] to the tools array. 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 via getToolsForAgentTypes(classifications, TOOLS), which reads the static TOOLS map. 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-server agents list in config, or a naming convention) and extend getToolsForAgentTypes() or the subagent builder to include them.
  • src/agent/deepAgents.js — createDeepAgent() receives tools: orchestratorTools. MCP tools intended for the orchestrator must be added here. The ORCHESTRATOR_TOOLS set in src/tools/index.js filters 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

  1. Add the dependency — Run npm install @langchain/mcp-adapters@^2.0.1 and confirm it resolves. Verify the adapter's MCPAdapter, { servers: { ... } }, and listTools() API.
  2. Create the schema — Add src/config/schemas/mcp.js with a McpSchema using z.discriminatedUnion(transport, [...]) for stdio/http/sse. Re-export it from src/config/schemas/index.js and add mcp: McpSchema.default({}) to ConfigSchema in src/config/config.js.
  3. Wire the tool builder — In src/tools/index.js buildToolConfig(), construct an MCPAdapter from config.mcp.servers, call adapter.listTools(), and append the results to the tools array. Handle per-server connection failures gracefully (warn and skip, don't crash startup).
  4. Expose the adapter for shutdown — Return the MCPAdapter (or a close function) from buildToolConfig() so createDeepAgent() can call adapter.close() on shutdown. Track it alongside the agent.
  5. Classify MCP tools for subagents — Decide how MCP tools map to agent types (per-server agents config list, or a naming convention). Extend getToolsForAgentTypes() and createSubagentDefinitions() in src/agent/deepAgents.js so MCP tools reach the right subagents.
  6. Update orchestrator filtering — Ensure ORCHESTRATOR_TOOLS filtering in src/tools/index.js doesn't drop MCP tools intended for the orchestrator (dynamic names).
  7. Write tests — Add tests/unit/config/schemas/mcp.test.js for schema validation, and an integration test that spins up a local stdio MCP server and verifies tool discovery.
  8. Verify — Run npm run test, npm run lint, and npm run coverage to confirm no regressions.
Lingua principale
JavaScript
Stelle
2
Fork
0
Merge medio
1h 17m
PR unite (30g)
242

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di avoidwork/madz

Tutte le issue di avoidwork/madz

Issue simili

Altre issue su JavaScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.