@illuma-ai/agents 1.3.2 → 1.4.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/graphs/Graph.cjs +3 -18
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +3 -0
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +58 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/providers/a2a/A2ACapabilityProvider.cjs +288 -0
- package/dist/cjs/providers/a2a/A2ACapabilityProvider.cjs.map +1 -0
- package/dist/cjs/providers/a2a/client.cjs +92 -0
- package/dist/cjs/providers/a2a/client.cjs.map +1 -0
- package/dist/cjs/providers/a2a/config.cjs +38 -0
- package/dist/cjs/providers/a2a/config.cjs.map +1 -0
- package/dist/cjs/providers/capabilityNaming.cjs +43 -0
- package/dist/cjs/providers/capabilityNaming.cjs.map +1 -0
- package/dist/cjs/providers/composite/CompositeCapabilityProvider.cjs +80 -0
- package/dist/cjs/providers/composite/CompositeCapabilityProvider.cjs.map +1 -0
- package/dist/cjs/providers/mcp/MCPCapabilityProvider.cjs +244 -0
- package/dist/cjs/providers/mcp/MCPCapabilityProvider.cjs.map +1 -0
- package/dist/cjs/providers/mcp/config.cjs +42 -0
- package/dist/cjs/providers/mcp/config.cjs.map +1 -0
- package/dist/cjs/providers/mcp/transport.cjs +65 -0
- package/dist/cjs/providers/mcp/transport.cjs.map +1 -0
- package/dist/cjs/providers/tools-server/ToolsServerCapabilityProvider.cjs +121 -0
- package/dist/cjs/providers/tools-server/ToolsServerCapabilityProvider.cjs.map +1 -0
- package/dist/cjs/providers/types.cjs +51 -0
- package/dist/cjs/providers/types.cjs.map +1 -0
- package/dist/cjs/tools/ToolNode.cjs +3 -0
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/proxyTool.cjs +100 -0
- package/dist/cjs/tools/proxyTool.cjs.map +1 -0
- package/dist/cjs/utils/credentials.cjs +142 -0
- package/dist/cjs/utils/credentials.cjs.map +1 -0
- package/dist/cjs/utils/httpClient.cjs +74 -0
- package/dist/cjs/utils/httpClient.cjs.map +1 -0
- package/dist/cjs/utils/toolManifest.cjs +100 -0
- package/dist/cjs/utils/toolManifest.cjs.map +1 -0
- package/dist/esm/graphs/Graph.mjs +3 -18
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +3 -0
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +14 -0
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/providers/a2a/A2ACapabilityProvider.mjs +281 -0
- package/dist/esm/providers/a2a/A2ACapabilityProvider.mjs.map +1 -0
- package/dist/esm/providers/a2a/client.mjs +88 -0
- package/dist/esm/providers/a2a/client.mjs.map +1 -0
- package/dist/esm/providers/a2a/config.mjs +35 -0
- package/dist/esm/providers/a2a/config.mjs.map +1 -0
- package/dist/esm/providers/capabilityNaming.mjs +39 -0
- package/dist/esm/providers/capabilityNaming.mjs.map +1 -0
- package/dist/esm/providers/composite/CompositeCapabilityProvider.mjs +78 -0
- package/dist/esm/providers/composite/CompositeCapabilityProvider.mjs.map +1 -0
- package/dist/esm/providers/mcp/MCPCapabilityProvider.mjs +240 -0
- package/dist/esm/providers/mcp/MCPCapabilityProvider.mjs.map +1 -0
- package/dist/esm/providers/mcp/config.mjs +39 -0
- package/dist/esm/providers/mcp/config.mjs.map +1 -0
- package/dist/esm/providers/mcp/transport.mjs +63 -0
- package/dist/esm/providers/mcp/transport.mjs.map +1 -0
- package/dist/esm/providers/tools-server/ToolsServerCapabilityProvider.mjs +119 -0
- package/dist/esm/providers/tools-server/ToolsServerCapabilityProvider.mjs.map +1 -0
- package/dist/esm/providers/types.mjs +51 -0
- package/dist/esm/providers/types.mjs.map +1 -0
- package/dist/esm/tools/ToolNode.mjs +3 -0
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/proxyTool.mjs +98 -0
- package/dist/esm/tools/proxyTool.mjs.map +1 -0
- package/dist/esm/utils/credentials.mjs +135 -0
- package/dist/esm/utils/credentials.mjs.map +1 -0
- package/dist/esm/utils/httpClient.mjs +70 -0
- package/dist/esm/utils/httpClient.mjs.map +1 -0
- package/dist/esm/utils/toolManifest.mjs +96 -0
- package/dist/esm/utils/toolManifest.mjs.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/providers/a2a/A2ACapabilityProvider.d.ts +89 -0
- package/dist/types/providers/a2a/client.d.ts +47 -0
- package/dist/types/providers/a2a/config.d.ts +18 -0
- package/dist/types/providers/a2a/index.d.ts +6 -0
- package/dist/types/providers/a2a/types.d.ts +173 -0
- package/dist/types/providers/capabilityNaming.d.ts +25 -0
- package/dist/types/providers/composite/CompositeCapabilityProvider.d.ts +22 -0
- package/dist/types/providers/composite/index.d.ts +1 -0
- package/dist/types/providers/index.d.ts +13 -0
- package/dist/types/providers/mcp/MCPCapabilityProvider.d.ts +54 -0
- package/dist/types/providers/mcp/config.d.ts +20 -0
- package/dist/types/providers/mcp/index.d.ts +5 -0
- package/dist/types/providers/mcp/transport.d.ts +18 -0
- package/dist/types/providers/mcp/types.d.ts +112 -0
- package/dist/types/providers/tools-server/ToolsServerCapabilityProvider.d.ts +45 -0
- package/dist/types/providers/tools-server/index.d.ts +1 -0
- package/dist/types/providers/types.d.ts +170 -0
- package/dist/types/tools/proxyTool.d.ts +55 -0
- package/dist/types/utils/credentials.d.ts +77 -0
- package/dist/types/utils/httpClient.d.ts +46 -0
- package/dist/types/utils/index.d.ts +3 -0
- package/dist/types/utils/toolManifest.d.ts +49 -0
- package/package.json +21 -1
- package/src/graphs/Graph.ts +0 -23
- package/src/index.ts +4 -0
- package/src/providers/__tests__/CompositeCapabilityProvider.test.ts +93 -0
- package/src/providers/__tests__/ToolsServerCapabilityProvider.integration.spec.ts +79 -0
- package/src/providers/__tests__/ToolsServerCapabilityProvider.test.ts +206 -0
- package/src/providers/__tests__/types.test.ts +64 -0
- package/src/providers/a2a/A2ACapabilityProvider.ts +384 -0
- package/src/providers/a2a/__tests__/A2ACapabilityProvider.integration.spec.ts +345 -0
- package/src/providers/a2a/__tests__/A2ACapabilityProvider.test.ts +460 -0
- package/src/providers/a2a/client.ts +115 -0
- package/src/providers/a2a/config.ts +40 -0
- package/src/providers/a2a/index.ts +29 -0
- package/src/providers/a2a/types.ts +191 -0
- package/src/providers/capabilityNaming.ts +42 -0
- package/src/providers/composite/CompositeCapabilityProvider.ts +112 -0
- package/src/providers/composite/index.ts +1 -0
- package/src/providers/index.ts +65 -0
- package/src/providers/mcp/MCPCapabilityProvider.ts +345 -0
- package/src/providers/mcp/__tests__/MCPCapabilityProvider.integration.spec.ts +386 -0
- package/src/providers/mcp/__tests__/MCPCapabilityProvider.test.ts +371 -0
- package/src/providers/mcp/config.ts +45 -0
- package/src/providers/mcp/index.ts +21 -0
- package/src/providers/mcp/transport.ts +76 -0
- package/src/providers/mcp/types.ts +139 -0
- package/src/providers/tools-server/ToolsServerCapabilityProvider.ts +220 -0
- package/src/providers/tools-server/index.ts +1 -0
- package/src/providers/types.ts +187 -0
- package/src/tools/proxyTool.ts +146 -0
- package/src/utils/__tests__/credentials.test.ts +130 -0
- package/src/utils/__tests__/httpClient.test.ts +75 -0
- package/src/utils/__tests__/toolManifest.test.ts +116 -0
- package/src/utils/credentials.ts +157 -0
- package/src/utils/httpClient.ts +92 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/toolManifest.ts +109 -0
- package/src/agents/AgentContext.js.map +0 -1
- package/src/agents/AgentContext.test.js.map +0 -1
- package/src/agents/__tests__/AgentContext.test.js.map +0 -1
- package/src/agents/__tests__/resolveStructuredOutputMode.test.js.map +0 -1
- package/src/common/enum.js.map +0 -1
- package/src/common/index.js.map +0 -1
- package/src/events.js.map +0 -1
- package/src/graphs/Graph.js.map +0 -1
- package/src/graphs/MultiAgentGraph.js.map +0 -1
- package/src/graphs/__tests__/structured-output.integration.test.js.map +0 -1
- package/src/graphs/__tests__/structured-output.test.js.map +0 -1
- package/src/graphs/contextManagement.e2e.test.js.map +0 -1
- package/src/graphs/contextManagement.test.js.map +0 -1
- package/src/graphs/handoffValidation.test.js.map +0 -1
- package/src/graphs/index.js.map +0 -1
- package/src/index.js.map +0 -1
- package/src/instrumentation.js.map +0 -1
- package/src/llm/anthropic/index.js.map +0 -1
- package/src/llm/anthropic/types.js.map +0 -1
- package/src/llm/anthropic/utils/message_inputs.js.map +0 -1
- package/src/llm/anthropic/utils/message_outputs.js.map +0 -1
- package/src/llm/anthropic/utils/output_parsers.js.map +0 -1
- package/src/llm/anthropic/utils/tools.js.map +0 -1
- package/src/llm/bedrock/__tests__/bedrock-caching.test.js.map +0 -1
- package/src/llm/bedrock/index.js.map +0 -1
- package/src/llm/bedrock/types.js.map +0 -1
- package/src/llm/bedrock/utils/index.js.map +0 -1
- package/src/llm/bedrock/utils/message_inputs.js.map +0 -1
- package/src/llm/bedrock/utils/message_outputs.js.map +0 -1
- package/src/llm/fake.js.map +0 -1
- package/src/llm/google/index.js.map +0 -1
- package/src/llm/google/types.js.map +0 -1
- package/src/llm/google/utils/common.js.map +0 -1
- package/src/llm/google/utils/tools.js.map +0 -1
- package/src/llm/google/utils/zod_to_genai_parameters.js.map +0 -1
- package/src/llm/openai/index.js.map +0 -1
- package/src/llm/openai/types.js.map +0 -1
- package/src/llm/openai/utils/index.js.map +0 -1
- package/src/llm/openai/utils/isReasoningModel.test.js.map +0 -1
- package/src/llm/openrouter/index.js.map +0 -1
- package/src/llm/openrouter/reasoning.test.js.map +0 -1
- package/src/llm/providers.js.map +0 -1
- package/src/llm/text.js.map +0 -1
- package/src/llm/vertexai/index.js.map +0 -1
- package/src/messages/__tests__/tools.test.js.map +0 -1
- package/src/messages/cache.js.map +0 -1
- package/src/messages/cache.test.js.map +0 -1
- package/src/messages/content.js.map +0 -1
- package/src/messages/content.test.js.map +0 -1
- package/src/messages/core.js.map +0 -1
- package/src/messages/ensureThinkingBlock.test.js.map +0 -1
- package/src/messages/format.js.map +0 -1
- package/src/messages/formatAgentMessages.test.js.map +0 -1
- package/src/messages/formatAgentMessages.tools.test.js.map +0 -1
- package/src/messages/formatMessage.test.js.map +0 -1
- package/src/messages/ids.js.map +0 -1
- package/src/messages/index.js.map +0 -1
- package/src/messages/labelContentByAgent.test.js.map +0 -1
- package/src/messages/prune.js.map +0 -1
- package/src/messages/reducer.js.map +0 -1
- package/src/messages/shiftIndexTokenCountMap.test.js.map +0 -1
- package/src/messages/summarize.js.map +0 -1
- package/src/messages/summarize.test.js.map +0 -1
- package/src/messages/tools.js.map +0 -1
- package/src/mockStream.js.map +0 -1
- package/src/prompts/collab.js.map +0 -1
- package/src/prompts/index.js.map +0 -1
- package/src/prompts/taskmanager.js.map +0 -1
- package/src/run.js.map +0 -1
- package/src/schemas/index.js.map +0 -1
- package/src/schemas/schema-preparation.test.js.map +0 -1
- package/src/schemas/validate.js.map +0 -1
- package/src/schemas/validate.test.js.map +0 -1
- package/src/scripts/abort.js.map +0 -1
- package/src/scripts/ant_web_search.js.map +0 -1
- package/src/scripts/ant_web_search_edge_case.js.map +0 -1
- package/src/scripts/ant_web_search_error_edge_case.js.map +0 -1
- package/src/scripts/args.js.map +0 -1
- package/src/scripts/bedrock-cache-debug.js.map +0 -1
- package/src/scripts/bedrock-content-aggregation-test.js.map +0 -1
- package/src/scripts/bedrock-merge-test.js.map +0 -1
- package/src/scripts/bedrock-parallel-tools-test.js.map +0 -1
- package/src/scripts/caching.js.map +0 -1
- package/src/scripts/cli.js.map +0 -1
- package/src/scripts/cli2.js.map +0 -1
- package/src/scripts/cli3.js.map +0 -1
- package/src/scripts/cli4.js.map +0 -1
- package/src/scripts/cli5.js.map +0 -1
- package/src/scripts/code_exec.js.map +0 -1
- package/src/scripts/code_exec_files.js.map +0 -1
- package/src/scripts/code_exec_multi_session.js.map +0 -1
- package/src/scripts/code_exec_ptc.js.map +0 -1
- package/src/scripts/code_exec_session.js.map +0 -1
- package/src/scripts/code_exec_simple.js.map +0 -1
- package/src/scripts/content.js.map +0 -1
- package/src/scripts/empty_input.js.map +0 -1
- package/src/scripts/handoff-test.js.map +0 -1
- package/src/scripts/image.js.map +0 -1
- package/src/scripts/memory.js.map +0 -1
- package/src/scripts/multi-agent-chain.js.map +0 -1
- package/src/scripts/multi-agent-conditional.js.map +0 -1
- package/src/scripts/multi-agent-document-review-chain.js.map +0 -1
- package/src/scripts/multi-agent-hybrid-flow.js.map +0 -1
- package/src/scripts/multi-agent-parallel-start.js.map +0 -1
- package/src/scripts/multi-agent-parallel.js.map +0 -1
- package/src/scripts/multi-agent-sequence.js.map +0 -1
- package/src/scripts/multi-agent-supervisor.js.map +0 -1
- package/src/scripts/multi-agent-test.js.map +0 -1
- package/src/scripts/parallel-asymmetric-tools-test.js.map +0 -1
- package/src/scripts/parallel-full-metadata-test.js.map +0 -1
- package/src/scripts/parallel-tools-test.js.map +0 -1
- package/src/scripts/programmatic_exec.js.map +0 -1
- package/src/scripts/programmatic_exec_agent.js.map +0 -1
- package/src/scripts/search.js.map +0 -1
- package/src/scripts/sequential-full-metadata-test.js.map +0 -1
- package/src/scripts/simple.js.map +0 -1
- package/src/scripts/single-agent-metadata-test.js.map +0 -1
- package/src/scripts/stream.js.map +0 -1
- package/src/scripts/test-custom-prompt-key.js.map +0 -1
- package/src/scripts/test-handoff-input.js.map +0 -1
- package/src/scripts/test-handoff-preamble.js.map +0 -1
- package/src/scripts/test-handoff-steering.js.map +0 -1
- package/src/scripts/test-multi-agent-list-handoff.js.map +0 -1
- package/src/scripts/test-parallel-agent-labeling.js.map +0 -1
- package/src/scripts/test-parallel-handoffs.js.map +0 -1
- package/src/scripts/test-thinking-handoff-bedrock.js.map +0 -1
- package/src/scripts/test-thinking-handoff.js.map +0 -1
- package/src/scripts/test-thinking-to-thinking-handoff-bedrock.js.map +0 -1
- package/src/scripts/test-tool-before-handoff-role-order.js.map +0 -1
- package/src/scripts/test-tools-before-handoff.js.map +0 -1
- package/src/scripts/test_code_api.js.map +0 -1
- package/src/scripts/thinking-bedrock.js.map +0 -1
- package/src/scripts/thinking-vertexai.js.map +0 -1
- package/src/scripts/thinking.js.map +0 -1
- package/src/scripts/tool_search.js.map +0 -1
- package/src/scripts/tools.js.map +0 -1
- package/src/specs/agent-handoffs-bedrock.integration.test.js.map +0 -1
- package/src/specs/agent-handoffs.test.js.map +0 -1
- package/src/specs/anthropic.simple.test.js.map +0 -1
- package/src/specs/azure.simple.test.js.map +0 -1
- package/src/specs/cache.simple.test.js.map +0 -1
- package/src/specs/custom-event-await.test.js.map +0 -1
- package/src/specs/deepseek.simple.test.js.map +0 -1
- package/src/specs/emergency-prune.test.js.map +0 -1
- package/src/specs/moonshot.simple.test.js.map +0 -1
- package/src/specs/observability.integration.test.js.map +0 -1
- package/src/specs/openai.simple.test.js.map +0 -1
- package/src/specs/openrouter.simple.test.js.map +0 -1
- package/src/specs/prune.test.js.map +0 -1
- package/src/specs/reasoning.test.js.map +0 -1
- package/src/specs/spec.utils.js.map +0 -1
- package/src/specs/thinking-handoff.test.js.map +0 -1
- package/src/specs/thinking-prune.test.js.map +0 -1
- package/src/specs/token-distribution-edge-case.test.js.map +0 -1
- package/src/specs/token-memoization.test.js.map +0 -1
- package/src/specs/tokens.test.js.map +0 -1
- package/src/specs/tool-error.test.js.map +0 -1
- package/src/splitStream.js.map +0 -1
- package/src/splitStream.test.js.map +0 -1
- package/src/stream.js.map +0 -1
- package/src/stream.test.js.map +0 -1
- package/src/test/mockTools.js.map +0 -1
- package/src/tools/BrowserTools.js.map +0 -1
- package/src/tools/Calculator.js.map +0 -1
- package/src/tools/Calculator.test.js.map +0 -1
- package/src/tools/CodeExecutor.js.map +0 -1
- package/src/tools/ProgrammaticToolCalling.js.map +0 -1
- package/src/tools/StreamingToolCallBuffer.js.map +0 -1
- package/src/tools/ToolNode.js.map +0 -1
- package/src/tools/ToolSearch.js.map +0 -1
- package/src/tools/__tests__/BrowserTools.test.js.map +0 -1
- package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.js.map +0 -1
- package/src/tools/__tests__/ProgrammaticToolCalling.test.js.map +0 -1
- package/src/tools/__tests__/StreamingToolCallBuffer.test.js.map +0 -1
- package/src/tools/__tests__/ToolApproval.test.js.map +0 -1
- package/src/tools/__tests__/ToolNode.recovery.test.js.map +0 -1
- package/src/tools/__tests__/ToolNode.session.test.js.map +0 -1
- package/src/tools/__tests__/ToolSearch.integration.test.js.map +0 -1
- package/src/tools/__tests__/ToolSearch.test.js.map +0 -1
- package/src/tools/__tests__/handlers.test.js.map +0 -1
- package/src/tools/__tests__/truncation-recovery.integration.test.js.map +0 -1
- package/src/tools/handlers.js.map +0 -1
- package/src/tools/schema.js.map +0 -1
- package/src/tools/search/anthropic.js.map +0 -1
- package/src/tools/search/content.js.map +0 -1
- package/src/tools/search/content.test.js.map +0 -1
- package/src/tools/search/firecrawl.js.map +0 -1
- package/src/tools/search/format.js.map +0 -1
- package/src/tools/search/highlights.js.map +0 -1
- package/src/tools/search/index.js.map +0 -1
- package/src/tools/search/jina-reranker.test.js.map +0 -1
- package/src/tools/search/rerankers.js.map +0 -1
- package/src/tools/search/schema.js.map +0 -1
- package/src/tools/search/search.js.map +0 -1
- package/src/tools/search/serper-scraper.js.map +0 -1
- package/src/tools/search/test.js.map +0 -1
- package/src/tools/search/tool.js.map +0 -1
- package/src/tools/search/types.js.map +0 -1
- package/src/tools/search/utils.js.map +0 -1
- package/src/types/graph.js.map +0 -1
- package/src/types/graph.test.js.map +0 -1
- package/src/types/index.js.map +0 -1
- package/src/types/llm.js.map +0 -1
- package/src/types/messages.js.map +0 -1
- package/src/types/run.js.map +0 -1
- package/src/types/stream.js.map +0 -1
- package/src/types/tools.js.map +0 -1
- package/src/utils/contextAnalytics.js.map +0 -1
- package/src/utils/contextAnalytics.test.js.map +0 -1
- package/src/utils/events.js.map +0 -1
- package/src/utils/graph.js.map +0 -1
- package/src/utils/handlers.js.map +0 -1
- package/src/utils/index.js.map +0 -1
- package/src/utils/llm.js.map +0 -1
- package/src/utils/llmConfig.js.map +0 -1
- package/src/utils/logging.js.map +0 -1
- package/src/utils/misc.js.map +0 -1
- package/src/utils/run.js.map +0 -1
- package/src/utils/schema.js.map +0 -1
- package/src/utils/title.js.map +0 -1
- package/src/utils/tokens.js.map +0 -1
- package/src/utils/toonFormat.js.map +0 -1
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPCapabilityProvider — connects to MCP servers via the official MCP SDK
|
|
3
|
+
* and exposes their tools as `Capability` / `StructuredToolInterface`.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the pattern of `ToolsServerCapabilityProvider`: thin adapter,
|
|
6
|
+
* protocol-specific transport, stateless as far as tokens/OAuth are
|
|
7
|
+
* concerned (all auth is host-resolved and forwarded via `getAuthHeaders`).
|
|
8
|
+
*
|
|
9
|
+
* What the host supplies:
|
|
10
|
+
* - `servers`: unified spec map (normalized from whatever source:
|
|
11
|
+
* programmatic, YAML, DB, marketplace catalog).
|
|
12
|
+
* - `getAuthHeaders?`: per-server header resolver. Called at connect
|
|
13
|
+
* time. OAuth orchestration / token refresh happens in the host.
|
|
14
|
+
*
|
|
15
|
+
* What the library does:
|
|
16
|
+
* - Picks the right SDK transport per spec.
|
|
17
|
+
* - Connects, calls `listTools()`, wraps each tool as a `Capability`.
|
|
18
|
+
* - `createRunnables()` returns `StructuredTool`s that invoke the
|
|
19
|
+
* server's tools on demand, streaming the string result back to the
|
|
20
|
+
* agent.
|
|
21
|
+
* - Caches open connections per-instance so repeated `fetchManifest` /
|
|
22
|
+
* `createRunnables` calls reuse them.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { tool, type StructuredToolInterface } from '@langchain/core/tools';
|
|
26
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
27
|
+
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
28
|
+
|
|
29
|
+
import {
|
|
30
|
+
CapabilityKind,
|
|
31
|
+
type Capability,
|
|
32
|
+
type CapabilityFilter,
|
|
33
|
+
type CapabilityProvider,
|
|
34
|
+
type CredentialMap,
|
|
35
|
+
} from '@/providers/types';
|
|
36
|
+
import {
|
|
37
|
+
CAPABILITY_NAME_SEPARATOR,
|
|
38
|
+
formatCapabilityName,
|
|
39
|
+
parseCapabilityName,
|
|
40
|
+
} from '@/providers/capabilityNaming';
|
|
41
|
+
import { createTransport } from './transport';
|
|
42
|
+
import { consoleLogger, getMCPEnvDefaults } from './config';
|
|
43
|
+
import type {
|
|
44
|
+
MCPLogger,
|
|
45
|
+
MCPProviderConfig,
|
|
46
|
+
MCPServerSpec,
|
|
47
|
+
MCPToolCallResult,
|
|
48
|
+
MCPToolDescriptor,
|
|
49
|
+
} from './types';
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Per-server connection state kept inside the provider. Reused across
|
|
53
|
+
* manifest fetches and tool invocations.
|
|
54
|
+
*/
|
|
55
|
+
interface ServerConnection {
|
|
56
|
+
serverName: string;
|
|
57
|
+
spec: MCPServerSpec;
|
|
58
|
+
client: Client;
|
|
59
|
+
transport: Transport;
|
|
60
|
+
tools: MCPToolDescriptor[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class MCPCapabilityProvider implements CapabilityProvider {
|
|
64
|
+
readonly providerId: string;
|
|
65
|
+
private readonly config: Required<
|
|
66
|
+
Pick<
|
|
67
|
+
MCPProviderConfig,
|
|
68
|
+
'connectTimeoutMs' | 'requestTimeoutMs' | 'clientInfo'
|
|
69
|
+
>
|
|
70
|
+
> &
|
|
71
|
+
Pick<MCPProviderConfig, 'servers' | 'getAuthHeaders'>;
|
|
72
|
+
private readonly logger: MCPLogger;
|
|
73
|
+
private readonly connections = new Map<string, ServerConnection>();
|
|
74
|
+
|
|
75
|
+
constructor(config: MCPProviderConfig) {
|
|
76
|
+
if (!config.servers || Object.keys(config.servers).length === 0) {
|
|
77
|
+
throw new Error('MCPCapabilityProvider: at least one server is required');
|
|
78
|
+
}
|
|
79
|
+
const env = getMCPEnvDefaults();
|
|
80
|
+
this.config = {
|
|
81
|
+
servers: config.servers,
|
|
82
|
+
getAuthHeaders: config.getAuthHeaders,
|
|
83
|
+
clientInfo: config.clientInfo ?? {
|
|
84
|
+
name: env.clientName,
|
|
85
|
+
version: env.clientVersion,
|
|
86
|
+
},
|
|
87
|
+
connectTimeoutMs: config.connectTimeoutMs ?? env.connectTimeoutMs,
|
|
88
|
+
requestTimeoutMs: config.requestTimeoutMs ?? env.requestTimeoutMs,
|
|
89
|
+
};
|
|
90
|
+
this.logger = config.logger ?? consoleLogger;
|
|
91
|
+
const names = Object.keys(config.servers).sort().join(',');
|
|
92
|
+
this.providerId = `mcp:${names}`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async fetchManifest(filter?: CapabilityFilter): Promise<Capability[]> {
|
|
96
|
+
// MCP only emits kind='mcp' — short-circuit if filter excludes us.
|
|
97
|
+
if (filter?.kind && filter.kind !== CapabilityKind.MCP) return [];
|
|
98
|
+
|
|
99
|
+
const capabilities: Capability[] = [];
|
|
100
|
+
|
|
101
|
+
for (const serverName of Object.keys(this.config.servers)) {
|
|
102
|
+
try {
|
|
103
|
+
const conn = await this.ensureConnection(serverName);
|
|
104
|
+
for (const toolDesc of conn.tools) {
|
|
105
|
+
const cap = this.toolToCapability(serverName, toolDesc);
|
|
106
|
+
if (this.capabilityMatchesFilter(cap, filter)) {
|
|
107
|
+
capabilities.push(cap);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} catch (err) {
|
|
111
|
+
// One server failing should not block the others — log and continue.
|
|
112
|
+
this.logger.warn(
|
|
113
|
+
`[mcp] failed to fetch manifest for server "${serverName}":`,
|
|
114
|
+
err instanceof Error ? err.message : err
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
this.logger.debug(
|
|
120
|
+
`[mcp] manifest assembled — ${capabilities.length} capabilities across ${this.connections.size}/${Object.keys(this.config.servers).length} connected servers`
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return capabilities;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async createRunnables(
|
|
127
|
+
capabilities: Capability[],
|
|
128
|
+
_credentials: CredentialMap
|
|
129
|
+
): Promise<StructuredToolInterface[]> {
|
|
130
|
+
const runnables: StructuredToolInterface[] = [];
|
|
131
|
+
|
|
132
|
+
for (const cap of capabilities) {
|
|
133
|
+
if (cap.kind !== CapabilityKind.MCP) continue;
|
|
134
|
+
|
|
135
|
+
const parsed = parseCapabilityName(cap.name);
|
|
136
|
+
const serverName = parsed?.sourceName;
|
|
137
|
+
const toolName = parsed?.itemName;
|
|
138
|
+
if (!serverName || !toolName) {
|
|
139
|
+
this.logger.warn(
|
|
140
|
+
`[mcp] skipping capability "${cap.name}" — unparseable`
|
|
141
|
+
);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const runnable = this.buildProxyTool(serverName, toolName, cap);
|
|
146
|
+
runnables.push(runnable);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return runnables;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Disconnect all open MCP client connections. Callers should invoke this
|
|
154
|
+
* on shutdown to release transports and child processes (for stdio).
|
|
155
|
+
*/
|
|
156
|
+
async close(): Promise<void> {
|
|
157
|
+
for (const [serverName, conn] of this.connections.entries()) {
|
|
158
|
+
try {
|
|
159
|
+
await conn.client.close();
|
|
160
|
+
} catch (err) {
|
|
161
|
+
this.logger.warn(
|
|
162
|
+
`[mcp] error closing connection to "${serverName}":`,
|
|
163
|
+
err instanceof Error ? err.message : err
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
this.connections.clear();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// --- internals ---------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
private async ensureConnection(
|
|
173
|
+
serverName: string
|
|
174
|
+
): Promise<ServerConnection> {
|
|
175
|
+
const existing = this.connections.get(serverName);
|
|
176
|
+
if (existing) return existing;
|
|
177
|
+
|
|
178
|
+
const spec = this.config.servers[serverName];
|
|
179
|
+
if (!spec) {
|
|
180
|
+
throw new Error(`[mcp] server "${serverName}" not in config`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const authHeaders = await this.resolveAuthHeaders(serverName);
|
|
184
|
+
const transport = createTransport(spec, authHeaders);
|
|
185
|
+
const client = new Client(this.config.clientInfo, {
|
|
186
|
+
capabilities: {},
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
this.logger.debug(`[mcp] connecting to "${serverName}" (${spec.type})`);
|
|
190
|
+
await client.connect(transport);
|
|
191
|
+
|
|
192
|
+
const { tools } = await client.listTools();
|
|
193
|
+
this.logger.debug(
|
|
194
|
+
`[mcp] connected to "${serverName}" — ${tools.length} tools discovered`
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
const conn: ServerConnection = {
|
|
198
|
+
serverName,
|
|
199
|
+
spec,
|
|
200
|
+
client,
|
|
201
|
+
transport,
|
|
202
|
+
tools: tools as MCPToolDescriptor[],
|
|
203
|
+
};
|
|
204
|
+
this.connections.set(serverName, conn);
|
|
205
|
+
return conn;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private async resolveAuthHeaders(
|
|
209
|
+
serverName: string
|
|
210
|
+
): Promise<Record<string, string> | undefined> {
|
|
211
|
+
if (!this.config.getAuthHeaders) return undefined;
|
|
212
|
+
try {
|
|
213
|
+
return await this.config.getAuthHeaders(serverName);
|
|
214
|
+
} catch (err) {
|
|
215
|
+
this.logger.warn(
|
|
216
|
+
`[mcp] getAuthHeaders("${serverName}") threw:`,
|
|
217
|
+
err instanceof Error ? err.message : err
|
|
218
|
+
);
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private toolToCapability(
|
|
224
|
+
serverName: string,
|
|
225
|
+
toolDesc: MCPToolDescriptor
|
|
226
|
+
): Capability {
|
|
227
|
+
return {
|
|
228
|
+
kind: CapabilityKind.MCP,
|
|
229
|
+
name: formatCapabilityName(serverName, toolDesc.name),
|
|
230
|
+
description:
|
|
231
|
+
toolDesc.description ?? `${toolDesc.name} (via ${serverName})`,
|
|
232
|
+
schema: toolDesc.inputSchema ?? {
|
|
233
|
+
type: 'object',
|
|
234
|
+
properties: {},
|
|
235
|
+
},
|
|
236
|
+
authConfig: [],
|
|
237
|
+
metadata: {
|
|
238
|
+
category: 'mcp',
|
|
239
|
+
tags: [serverName],
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private capabilityMatchesFilter(
|
|
245
|
+
cap: Capability,
|
|
246
|
+
filter?: CapabilityFilter
|
|
247
|
+
): boolean {
|
|
248
|
+
if (!filter) return true;
|
|
249
|
+
if (filter.kind && cap.kind !== filter.kind) return false;
|
|
250
|
+
if (filter.names && !filter.names.includes(cap.name)) return false;
|
|
251
|
+
if (filter.tags?.length) {
|
|
252
|
+
const capTags = new Set(cap.metadata.tags ?? []);
|
|
253
|
+
if (!filter.tags.some((t) => capTags.has(t))) return false;
|
|
254
|
+
}
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private buildProxyTool(
|
|
259
|
+
serverName: string,
|
|
260
|
+
toolName: string,
|
|
261
|
+
cap: Capability
|
|
262
|
+
): StructuredToolInterface {
|
|
263
|
+
// Arrow-function closures would capture `this` correctly but LangChain's
|
|
264
|
+
// `tool()` helper expects a plain async function; bind the methods we
|
|
265
|
+
// need up-front so the closure body stays clean and strict-lint-friendly.
|
|
266
|
+
const logger = this.logger;
|
|
267
|
+
const ensureConnection = this.ensureConnection.bind(this);
|
|
268
|
+
return tool(
|
|
269
|
+
async (input: unknown): Promise<string> => {
|
|
270
|
+
// DEBUG: log tool invocation (remove after POC stabilizes)
|
|
271
|
+
logger.debug(
|
|
272
|
+
`[mcp] invoking ${serverName}:${toolName}`,
|
|
273
|
+
input && typeof input === 'object'
|
|
274
|
+
? `inputKeys=${Object.keys(input as object).length}`
|
|
275
|
+
: ''
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
const conn = await ensureConnection(serverName);
|
|
279
|
+
const response = await conn.client.callTool({
|
|
280
|
+
name: toolName,
|
|
281
|
+
arguments: (input as Record<string, unknown>) ?? {},
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const result = flattenToolCallResponse(response);
|
|
285
|
+
if (result.isError) {
|
|
286
|
+
throw new Error(
|
|
287
|
+
`MCP tool "${serverName}:${toolName}" failed: ${result.text}`
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
return result.text;
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
name: cap.name,
|
|
294
|
+
description: cap.description,
|
|
295
|
+
schema: (cap.schema as object) ?? { type: 'object', properties: {} },
|
|
296
|
+
responseFormat: 'content',
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ---------------------------------------------------------------------------
|
|
303
|
+
// Helpers exported for testing
|
|
304
|
+
// ---------------------------------------------------------------------------
|
|
305
|
+
|
|
306
|
+
// CAPABILITY_NAME_SEPARATOR + formatCapabilityName live in the shared
|
|
307
|
+
// `@/providers/capabilityNaming` module so MCP and A2A providers stay in
|
|
308
|
+
// lockstep on name encoding. Re-exported here for callers that already
|
|
309
|
+
// import from the MCP barrel.
|
|
310
|
+
export { CAPABILITY_NAME_SEPARATOR, formatCapabilityName };
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Flatten the MCP SDK's callTool response into a plain text + error flag.
|
|
314
|
+
* Concatenates any `text`-type content parts; non-text parts are
|
|
315
|
+
* JSON-stringified so the LLM sees something rather than silently
|
|
316
|
+
* dropping output.
|
|
317
|
+
*/
|
|
318
|
+
export function flattenToolCallResponse(response: unknown): MCPToolCallResult {
|
|
319
|
+
const resp = response as {
|
|
320
|
+
content?: Array<{ type?: string; text?: string; [k: string]: unknown }>;
|
|
321
|
+
isError?: boolean;
|
|
322
|
+
} | null;
|
|
323
|
+
|
|
324
|
+
const rawContent = resp?.content ?? [];
|
|
325
|
+
const isError = resp?.isError === true;
|
|
326
|
+
|
|
327
|
+
if (!Array.isArray(rawContent) || rawContent.length === 0) {
|
|
328
|
+
return {
|
|
329
|
+
text: isError ? '(error with no content)' : '(empty response)',
|
|
330
|
+
rawContent,
|
|
331
|
+
isError,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const parts = rawContent.map((item) => {
|
|
336
|
+
if (item.type === 'text' && typeof item.text === 'string') return item.text;
|
|
337
|
+
try {
|
|
338
|
+
return JSON.stringify(item);
|
|
339
|
+
} catch {
|
|
340
|
+
return '[unserializable content part]';
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
return { text: parts.join('\n\n'), rawContent, isError };
|
|
345
|
+
}
|