@illuma-ai/agents 1.3.2 → 1.4.0-alpha.1
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 +56 -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/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 +13 -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/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/index.d.ts +12 -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 +16 -1
- package/src/graphs/Graph.ts +0 -23
- package/src/index.ts +4 -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/index.ts +68 -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,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the A2A capability provider.
|
|
3
|
+
*
|
|
4
|
+
* A2A (Agent-to-Agent) is a public HTTP + JSON-RPC 2.0 protocol for
|
|
5
|
+
* invoking one agent from another. When an agent has been served over
|
|
6
|
+
* A2A (e.g., via `ranger agents serve` or any compliant runtime), a
|
|
7
|
+
* caller agent can use `A2ACapabilityProvider` to:
|
|
8
|
+
* - discover the remote agent's skills via `GET /.well-known/agent.json`
|
|
9
|
+
* - invoke it by POSTing JSON-RPC `tasks/send` to its base URL
|
|
10
|
+
*
|
|
11
|
+
* The types here mirror the public A2A protocol shape at the subset
|
|
12
|
+
* needed for client-side integration.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Capabilities advertised on the remote agent's agent card. */
|
|
16
|
+
export interface A2ACardCapabilities {
|
|
17
|
+
/** True when the agent supports SSE streaming via `tasks/sendSubscribe`. */
|
|
18
|
+
streaming: boolean;
|
|
19
|
+
pushNotifications?: boolean;
|
|
20
|
+
stateTransitionHistory?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** A single skill exposed by a remote agent on its agent card. */
|
|
24
|
+
export interface A2ASkill {
|
|
25
|
+
/** Stable skill identifier. */
|
|
26
|
+
id: string;
|
|
27
|
+
/** Human-readable name. */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Description of what the skill does. */
|
|
30
|
+
description: string;
|
|
31
|
+
/** Optional tags (e.g., "search", "analysis"). */
|
|
32
|
+
tags?: string[];
|
|
33
|
+
/** Optional example inputs. */
|
|
34
|
+
examples?: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Shape served at `GET /.well-known/agent.json`. */
|
|
38
|
+
export interface A2AAgentCard {
|
|
39
|
+
name: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
/** Base URL clients should POST task requests to. */
|
|
42
|
+
url: string;
|
|
43
|
+
/** Card version — independent of the underlying model/agent version. */
|
|
44
|
+
version: string;
|
|
45
|
+
capabilities: A2ACardCapabilities;
|
|
46
|
+
defaultInputModes?: string[];
|
|
47
|
+
defaultOutputModes?: string[];
|
|
48
|
+
skills: A2ASkill[];
|
|
49
|
+
provider?: {
|
|
50
|
+
organization: string;
|
|
51
|
+
url?: string;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Spec describing one remote A2A-served agent the provider should connect to. */
|
|
56
|
+
export interface A2ARemoteSpec {
|
|
57
|
+
/**
|
|
58
|
+
* Base URL of the remote A2A endpoint. The provider will fetch the
|
|
59
|
+
* card from `<url>/.well-known/agent.json` and POST task requests to
|
|
60
|
+
* `<url>/` (JSON-RPC root).
|
|
61
|
+
*/
|
|
62
|
+
url: string;
|
|
63
|
+
/**
|
|
64
|
+
* Optional static headers to include on every request. Auth headers
|
|
65
|
+
* should be provided via the `getAuthHeaders` callback instead, so
|
|
66
|
+
* token refresh doesn't require rebuilding the provider.
|
|
67
|
+
*/
|
|
68
|
+
headers?: Record<string, string>;
|
|
69
|
+
/**
|
|
70
|
+
* When true, expose the remote agent as a single coarse-grained
|
|
71
|
+
* Capability (one per remote, named after the agent). When false
|
|
72
|
+
* (default), expose one Capability per skill advertised on the card.
|
|
73
|
+
*/
|
|
74
|
+
flattenAsSingleTool?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Optional override of the agent card URL. Defaults to
|
|
77
|
+
* `<url>/.well-known/agent.json`.
|
|
78
|
+
*/
|
|
79
|
+
cardPath?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Optional override of the JSON-RPC endpoint path. Defaults to `/`.
|
|
82
|
+
*/
|
|
83
|
+
rpcPath?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Configuration for the A2A capability provider. */
|
|
87
|
+
export interface A2AProviderConfig {
|
|
88
|
+
/**
|
|
89
|
+
* Map of remoteName → spec. Remote names are stable identifiers used
|
|
90
|
+
* as the capability name prefix and as keys for `getAuthHeaders`.
|
|
91
|
+
*/
|
|
92
|
+
remotes: Record<string, A2ARemoteSpec>;
|
|
93
|
+
/**
|
|
94
|
+
* Optional callback to resolve auth headers for a given remote at
|
|
95
|
+
* connect-time. Returns a header map merged over `spec.headers`.
|
|
96
|
+
*
|
|
97
|
+
* The library never stores tokens — the host owns auth lifecycle and
|
|
98
|
+
* provides resolved values here.
|
|
99
|
+
*/
|
|
100
|
+
getAuthHeaders?: (
|
|
101
|
+
remoteName: string
|
|
102
|
+
) =>
|
|
103
|
+
| Promise<Record<string, string> | undefined>
|
|
104
|
+
| Record<string, string>
|
|
105
|
+
| undefined;
|
|
106
|
+
/**
|
|
107
|
+
* Identity announced to remotes on every request via `user-agent` /
|
|
108
|
+
* provider headers. Defaults to env vars (`A2A_CLIENT_NAME` /
|
|
109
|
+
* `A2A_CLIENT_VERSION`) or a library fallback.
|
|
110
|
+
*/
|
|
111
|
+
clientInfo?: { name: string; version: string };
|
|
112
|
+
/** HTTP request timeout in ms. Defaults to 30_000. */
|
|
113
|
+
timeoutMs?: number;
|
|
114
|
+
/** Optional logger. Defaults to a console-based one. */
|
|
115
|
+
logger?: A2ALogger;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Minimal logger interface — matches pino-style signatures. */
|
|
119
|
+
export interface A2ALogger {
|
|
120
|
+
debug: (...args: unknown[]) => void;
|
|
121
|
+
info: (...args: unknown[]) => void;
|
|
122
|
+
warn: (...args: unknown[]) => void;
|
|
123
|
+
error: (...args: unknown[]) => void;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// JSON-RPC 2.0 shapes (subset used by the provider)
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
export interface JsonRpcRequest<P = unknown> {
|
|
131
|
+
jsonrpc: '2.0';
|
|
132
|
+
id: string | number | null;
|
|
133
|
+
method: string;
|
|
134
|
+
params?: P;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface JsonRpcSuccess<R = unknown> {
|
|
138
|
+
jsonrpc: '2.0';
|
|
139
|
+
id: string | number | null;
|
|
140
|
+
result: R;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface JsonRpcErrorResponse {
|
|
144
|
+
jsonrpc: '2.0';
|
|
145
|
+
id: string | number | null;
|
|
146
|
+
error: { code: number; message: string; data?: unknown };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export type JsonRpcResponse<R = unknown> =
|
|
150
|
+
| JsonRpcSuccess<R>
|
|
151
|
+
| JsonRpcErrorResponse;
|
|
152
|
+
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// A2A task message shapes
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
|
|
157
|
+
export interface A2AMessage {
|
|
158
|
+
role: 'user' | 'agent';
|
|
159
|
+
parts: Array<{ type: 'text'; text: string }>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface A2ATaskParams {
|
|
163
|
+
/** Caller-assigned task id — echoed back by the server. */
|
|
164
|
+
id: string;
|
|
165
|
+
/** Optional session id for multi-turn continuity. */
|
|
166
|
+
sessionId?: string;
|
|
167
|
+
/** The message to deliver to the remote agent. */
|
|
168
|
+
message: A2AMessage;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export type A2ATaskState =
|
|
172
|
+
| 'submitted'
|
|
173
|
+
| 'working'
|
|
174
|
+
| 'input-required'
|
|
175
|
+
| 'completed'
|
|
176
|
+
| 'failed'
|
|
177
|
+
| 'canceled';
|
|
178
|
+
|
|
179
|
+
export interface A2ATaskStatus {
|
|
180
|
+
state: A2ATaskState;
|
|
181
|
+
timestamp: string;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface A2ATask {
|
|
185
|
+
id: string;
|
|
186
|
+
sessionId?: string;
|
|
187
|
+
status: A2ATaskStatus;
|
|
188
|
+
/** Final agent response — populated when status is `completed`. */
|
|
189
|
+
artifacts?: Array<{ parts: Array<{ type: 'text'; text: string }> }>;
|
|
190
|
+
error?: { code: number; message: string };
|
|
191
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared capability-name encoding used by source-specific providers
|
|
3
|
+
* (MCP, A2A, and future providers that expose multi-level namespaces).
|
|
4
|
+
*
|
|
5
|
+
* A capability name encodes `<sourceName>__<itemName>` where:
|
|
6
|
+
* - `sourceName` is the provider-level identifier (MCP server name,
|
|
7
|
+
* A2A remote name, etc.)
|
|
8
|
+
* - `itemName` is the per-source sub-unit (MCP tool name, A2A skill id)
|
|
9
|
+
*
|
|
10
|
+
* Centralizing the separator + parsing here keeps both providers in lockstep
|
|
11
|
+
* and prevents collisions when re-exported from the provider barrel.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Separator between source and item in an encoded capability name. */
|
|
15
|
+
export const CAPABILITY_NAME_SEPARATOR = '__';
|
|
16
|
+
|
|
17
|
+
/** Compose a capability name. If `itemName` is omitted, returns just `sourceName`. */
|
|
18
|
+
export function formatCapabilityName(
|
|
19
|
+
sourceName: string,
|
|
20
|
+
itemName?: string
|
|
21
|
+
): string {
|
|
22
|
+
return itemName
|
|
23
|
+
? `${sourceName}${CAPABILITY_NAME_SEPARATOR}${itemName}`
|
|
24
|
+
: sourceName;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Parse a capability name into its components. Returns `null` when `name`
|
|
29
|
+
* is empty. When the name has no separator, `itemName` is undefined
|
|
30
|
+
* (the caller can treat that as a whole-source invocation).
|
|
31
|
+
*/
|
|
32
|
+
export function parseCapabilityName(
|
|
33
|
+
name: string
|
|
34
|
+
): { sourceName: string; itemName?: string } | null {
|
|
35
|
+
if (!name) return null;
|
|
36
|
+
const sepIdx = name.indexOf(CAPABILITY_NAME_SEPARATOR);
|
|
37
|
+
if (sepIdx < 0) return { sourceName: name };
|
|
38
|
+
return {
|
|
39
|
+
sourceName: name.slice(0, sepIdx),
|
|
40
|
+
itemName: name.slice(sepIdx + CAPABILITY_NAME_SEPARATOR.length),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability provider abstraction.
|
|
3
|
+
*
|
|
4
|
+
* See docs/architecture-capability-layer.md for the full design rationale.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from './types';
|
|
8
|
+
// Shared capability-name helpers — single source of truth so both MCP and
|
|
9
|
+
// A2A consumers get the same encoding without re-export duplication.
|
|
10
|
+
export * from './capabilityNaming';
|
|
11
|
+
export * from './tools-server';
|
|
12
|
+
// Hosts compose multiple providers by iterating a plain array and
|
|
13
|
+
// concatenating tools — see docs/capability-providers.md. No wrapper
|
|
14
|
+
// class is provided because the loop is trivial and keeps host code
|
|
15
|
+
// transparent.
|
|
16
|
+
// MCP + A2A barrels intentionally namespaced to avoid re-exporting
|
|
17
|
+
// `CAPABILITY_NAME_SEPARATOR` / `formatCapabilityName` twice (each
|
|
18
|
+
// provider module re-exports them internally; the canonical export
|
|
19
|
+
// comes from `./capabilityNaming` above).
|
|
20
|
+
export {
|
|
21
|
+
MCPCapabilityProvider,
|
|
22
|
+
flattenToolCallResponse,
|
|
23
|
+
createTransport,
|
|
24
|
+
mcpConsoleLogger,
|
|
25
|
+
getMCPEnvDefaults,
|
|
26
|
+
} from './mcp';
|
|
27
|
+
export type {
|
|
28
|
+
MCPLogger,
|
|
29
|
+
MCPProviderConfig,
|
|
30
|
+
MCPServerSpec,
|
|
31
|
+
MCPTransportKind,
|
|
32
|
+
StdioSpec,
|
|
33
|
+
SSESpec,
|
|
34
|
+
StreamableHTTPSpec,
|
|
35
|
+
WebSocketSpec,
|
|
36
|
+
MCPToolDescriptor,
|
|
37
|
+
MCPToolCallResult,
|
|
38
|
+
MCPStructuredTool,
|
|
39
|
+
} from './mcp';
|
|
40
|
+
export {
|
|
41
|
+
A2ACapabilityProvider,
|
|
42
|
+
A2AClient,
|
|
43
|
+
extractTaskText,
|
|
44
|
+
generateRpcId,
|
|
45
|
+
skillToCapability,
|
|
46
|
+
coerceInputToA2AMessage,
|
|
47
|
+
MESSAGE_INPUT_SCHEMA,
|
|
48
|
+
a2aConsoleLogger,
|
|
49
|
+
getA2AEnvDefaults,
|
|
50
|
+
} from './a2a';
|
|
51
|
+
export type {
|
|
52
|
+
A2AAgentCard,
|
|
53
|
+
A2ACardCapabilities,
|
|
54
|
+
A2AClientOptions,
|
|
55
|
+
A2ALogger,
|
|
56
|
+
A2AMessage,
|
|
57
|
+
A2AProviderConfig,
|
|
58
|
+
A2ARemoteSpec,
|
|
59
|
+
A2ASkill,
|
|
60
|
+
A2ATask,
|
|
61
|
+
A2ATaskParams,
|
|
62
|
+
A2ATaskState,
|
|
63
|
+
A2ATaskStatus,
|
|
64
|
+
JsonRpcRequest,
|
|
65
|
+
JsonRpcResponse,
|
|
66
|
+
JsonRpcSuccess,
|
|
67
|
+
JsonRpcErrorResponse,
|
|
68
|
+
} from './a2a';
|
|
@@ -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
|
+
}
|