truss-mcp-a2a-gateway 1.0.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/README.md +111 -0
- package/dist/a2a-handler.d.ts +41 -0
- package/dist/a2a-handler.d.ts.map +1 -0
- package/dist/a2a-handler.js +285 -0
- package/dist/a2a-handler.js.map +1 -0
- package/dist/agent-card-generator.d.ts +17 -0
- package/dist/agent-card-generator.d.ts.map +1 -0
- package/dist/agent-card-generator.js +109 -0
- package/dist/agent-card-generator.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +145 -0
- package/dist/cli.js.map +1 -0
- package/dist/gateway.d.ts +40 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +219 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +12 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +53 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-client.d.ts +38 -0
- package/dist/mcp-client.d.ts.map +1 -0
- package/dist/mcp-client.js +119 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/task-manager.d.ts +68 -0
- package/dist/task-manager.d.ts.map +1 -0
- package/dist/task-manager.js +205 -0
- package/dist/task-manager.js.map +1 -0
- package/dist/tool-router.d.ts +26 -0
- package/dist/tool-router.d.ts.map +1 -0
- package/dist/tool-router.js +199 -0
- package/dist/tool-router.js.map +1 -0
- package/dist/types.d.ts +175 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +65 -0
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# @truss/mcp-a2a-gateway
|
|
2
|
+
|
|
3
|
+
Bridge any MCP server to Google's A2A (Agent-to-Agent) protocol. Expose your MCP tools as A2A-compatible agent skills, discoverable by LangGraph, CrewAI, Google ADK, AutoGen, and any A2A-compliant framework.
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
MCP tools are powerful but locked into the MCP ecosystem. The A2A protocol is Google's open standard for agent interoperability with 50+ technology partners. This gateway bridges the two — install it, point it at any MCP server, and it becomes an A2A agent with zero code changes.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Auto-generated Agent Cards** — Reads your MCP server's tool list and generates a compliant `/.well-known/agent.json`
|
|
12
|
+
- **Full A2A task lifecycle** — `submitted` → `working` → `completed`/`failed`/`canceled`
|
|
13
|
+
- **JSON-RPC endpoint** — `message/send`, `tasks/get`, `tasks/cancel` per A2A spec
|
|
14
|
+
- **SSE streaming** — Real-time task updates via `message/stream`
|
|
15
|
+
- **Stdio + SSE transports** — Connect to any MCP server via subprocess or HTTP
|
|
16
|
+
- **Zero code changes** — Your MCP server stays unchanged
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g @truss/mcp-a2a-gateway
|
|
22
|
+
|
|
23
|
+
# Bridge any MCP server:
|
|
24
|
+
truss-a2a-gateway --command "npx" --args "-y,truss-seo-mcp" --port 3000
|
|
25
|
+
|
|
26
|
+
# Or with a local server:
|
|
27
|
+
truss-a2a-gateway --command "node" --args "dist/index.js" --port 3000
|
|
28
|
+
|
|
29
|
+
# Or connect to an SSE server:
|
|
30
|
+
truss-a2a-gateway --url "http://localhost:8080/sse" --port 3000
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Your MCP server is now accessible at:
|
|
34
|
+
- `GET /.well-known/agent.json` — Agent Card for discovery
|
|
35
|
+
- `POST /` — JSON-RPC endpoint for A2A task execution
|
|
36
|
+
- `POST /stream` — SSE streaming endpoint
|
|
37
|
+
- `GET /health` — Health check
|
|
38
|
+
|
|
39
|
+
## Usage as Library
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { Gateway } from '@truss/mcp-a2a-gateway';
|
|
43
|
+
|
|
44
|
+
const gateway = new Gateway({
|
|
45
|
+
port: 3000,
|
|
46
|
+
host: '127.0.0.1',
|
|
47
|
+
agentName: 'My SEO Agent',
|
|
48
|
+
agentDescription: 'AI-powered SEO analysis',
|
|
49
|
+
providerOrg: 'My Company',
|
|
50
|
+
mcpServer: {
|
|
51
|
+
command: 'npx',
|
|
52
|
+
args: ['-y', 'truss-seo-mcp'],
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
await gateway.start();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## CLI Options
|
|
60
|
+
|
|
61
|
+
| Option | Description | Default |
|
|
62
|
+
|--------|-------------|---------|
|
|
63
|
+
| `--command` | MCP server command (stdio transport) | — |
|
|
64
|
+
| `--args` | Comma-separated args for the command | — |
|
|
65
|
+
| `--url` | MCP server URL (SSE transport) | — |
|
|
66
|
+
| `--port` | Gateway port | 3000 |
|
|
67
|
+
| `--host` | Gateway host | 127.0.0.1 |
|
|
68
|
+
| `--name` | Agent name override | Auto-detected |
|
|
69
|
+
| `--description` | Agent description override | Auto-detected |
|
|
70
|
+
| `--provider` | Provider organization | — |
|
|
71
|
+
| `--base-url` | Base URL for the agent | Auto-detected |
|
|
72
|
+
| `--log-level` | Log level (debug/info/warn/error) | info |
|
|
73
|
+
|
|
74
|
+
## A2A Protocol Support
|
|
75
|
+
|
|
76
|
+
Implements the [A2A Protocol Specification v0.3](https://a2a-protocol.org/latest/specification/):
|
|
77
|
+
|
|
78
|
+
- **Agent Card** at `/.well-known/agent.json`
|
|
79
|
+
- **message/send** — Synchronous task execution via JSON-RPC
|
|
80
|
+
- **message/stream** — SSE streaming with `TaskStatusUpdate` and `TaskArtifactUpdate` events
|
|
81
|
+
- **tasks/get** — Retrieve task state and history
|
|
82
|
+
- **tasks/cancel** — Cancel running tasks
|
|
83
|
+
|
|
84
|
+
## How It Works
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
[A2A Client] ──HTTP/JSON-RPC──▶ [Gateway] ──MCP Protocol──▶ [MCP Server]
|
|
88
|
+
│
|
|
89
|
+
Translates A2A tasks
|
|
90
|
+
to MCP tool calls
|
|
91
|
+
│
|
|
92
|
+
Auto-generates
|
|
93
|
+
Agent Card from
|
|
94
|
+
MCP tool list
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
1. Gateway connects to your MCP server and discovers available tools
|
|
98
|
+
2. It generates an A2A Agent Card with one skill per MCP tool
|
|
99
|
+
3. When an A2A client sends a message, the gateway parses it for tool invocations
|
|
100
|
+
4. Tool calls are forwarded to the MCP server, results returned as A2A artifacts
|
|
101
|
+
|
|
102
|
+
## Pricing
|
|
103
|
+
|
|
104
|
+
- **Individual**: $49/mo — 1 MCP server bridge
|
|
105
|
+
- **Team**: $99/mo — Unlimited servers, priority support
|
|
106
|
+
|
|
107
|
+
Purchase: [Individual](https://buy.stripe.com/cNi3cu2JF7ic34OdPD7wA0j) | [Team](https://buy.stripe.com/aFacN4ac7auobBk6nb7wA0k)
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A2A Protocol Handler — processes JSON-RPC requests per the A2A specification.
|
|
3
|
+
*
|
|
4
|
+
* Implements:
|
|
5
|
+
* - message/send (synchronous task execution)
|
|
6
|
+
* - message/stream (SSE streaming)
|
|
7
|
+
* - tasks/get (task retrieval)
|
|
8
|
+
* - tasks/cancel (task cancellation)
|
|
9
|
+
*/
|
|
10
|
+
import type { JsonRpcRequest, JsonRpcResponse, StreamingEvent } from './types.js';
|
|
11
|
+
import type { McpClientWrapper } from './mcp-client.js';
|
|
12
|
+
import { TaskManager } from './task-manager.js';
|
|
13
|
+
export declare class A2AHandler {
|
|
14
|
+
private mcpClient;
|
|
15
|
+
private taskManager;
|
|
16
|
+
constructor(mcpClient: McpClientWrapper, taskManager: TaskManager);
|
|
17
|
+
/**
|
|
18
|
+
* Handle a JSON-RPC request and return a response.
|
|
19
|
+
*/
|
|
20
|
+
handleRequest(request: JsonRpcRequest): Promise<JsonRpcResponse>;
|
|
21
|
+
/**
|
|
22
|
+
* Handle message/send — execute tool calls synchronously and return the completed task.
|
|
23
|
+
*/
|
|
24
|
+
private handleSendMessage;
|
|
25
|
+
/**
|
|
26
|
+
* Handle message/send with streaming — yields SSE events.
|
|
27
|
+
*/
|
|
28
|
+
handleSendMessageStream(request: JsonRpcRequest): AsyncGenerator<StreamingEvent>;
|
|
29
|
+
/**
|
|
30
|
+
* Handle tasks/get — retrieve a task by ID.
|
|
31
|
+
*/
|
|
32
|
+
private handleGetTask;
|
|
33
|
+
/**
|
|
34
|
+
* Handle tasks/cancel — cancel a running task.
|
|
35
|
+
*/
|
|
36
|
+
private handleCancelTask;
|
|
37
|
+
private makeStatusUpdate;
|
|
38
|
+
private successResponse;
|
|
39
|
+
private errorResponse;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=a2a-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a2a-handler.d.ts","sourceRoot":"","sources":["../src/a2a-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EASf,cAAc,EAGf,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAyC,MAAM,mBAAmB,CAAC;AAkBvF,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,WAAW,CAAc;gBAErB,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW;IAKjE;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IA8BtE;;OAEG;YACW,iBAAiB;IAyG/B;;OAEG;IACI,uBAAuB,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAAC,cAAc,CAAC;IAkFvF;;OAEG;IACH,OAAO,CAAC,aAAa;IAcrB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,aAAa;CAOtB"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* A2A Protocol Handler — processes JSON-RPC requests per the A2A specification.
|
|
4
|
+
*
|
|
5
|
+
* Implements:
|
|
6
|
+
* - message/send (synchronous task execution)
|
|
7
|
+
* - message/stream (SSE streaming)
|
|
8
|
+
* - tasks/get (task retrieval)
|
|
9
|
+
* - tasks/cancel (task cancellation)
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.A2AHandler = void 0;
|
|
13
|
+
const task_manager_js_1 = require("./task-manager.js");
|
|
14
|
+
const tool_router_js_1 = require("./tool-router.js");
|
|
15
|
+
const logger_js_1 = require("./logger.js");
|
|
16
|
+
const log = (0, logger_js_1.createLogger)('a2a-handler');
|
|
17
|
+
// ─── JSON-RPC Error Codes ────────────────────────────────────────────────────
|
|
18
|
+
const JSONRPC_PARSE_ERROR = -32700;
|
|
19
|
+
const JSONRPC_INVALID_REQUEST = -32600;
|
|
20
|
+
const JSONRPC_METHOD_NOT_FOUND = -32601;
|
|
21
|
+
const JSONRPC_INVALID_PARAMS = -32602;
|
|
22
|
+
const JSONRPC_INTERNAL_ERROR = -32603;
|
|
23
|
+
// A2A-specific error codes
|
|
24
|
+
const A2A_TASK_NOT_FOUND = -32001;
|
|
25
|
+
const A2A_INVALID_STATE = -32002;
|
|
26
|
+
class A2AHandler {
|
|
27
|
+
mcpClient;
|
|
28
|
+
taskManager;
|
|
29
|
+
constructor(mcpClient, taskManager) {
|
|
30
|
+
this.mcpClient = mcpClient;
|
|
31
|
+
this.taskManager = taskManager;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Handle a JSON-RPC request and return a response.
|
|
35
|
+
*/
|
|
36
|
+
async handleRequest(request) {
|
|
37
|
+
log.debug('Handling JSON-RPC request', { method: request.method, id: request.id });
|
|
38
|
+
try {
|
|
39
|
+
switch (request.method) {
|
|
40
|
+
case 'message/send':
|
|
41
|
+
return await this.handleSendMessage(request);
|
|
42
|
+
case 'tasks/get':
|
|
43
|
+
return this.handleGetTask(request);
|
|
44
|
+
case 'tasks/cancel':
|
|
45
|
+
return this.handleCancelTask(request);
|
|
46
|
+
default:
|
|
47
|
+
return this.errorResponse(request.id, JSONRPC_METHOD_NOT_FOUND, `Method not found: ${request.method}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
log.error('Unhandled error processing request', {
|
|
52
|
+
method: request.method,
|
|
53
|
+
error: String(err),
|
|
54
|
+
});
|
|
55
|
+
return this.errorResponse(request.id, JSONRPC_INTERNAL_ERROR, 'Internal error processing request');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Handle message/send — execute tool calls synchronously and return the completed task.
|
|
60
|
+
*/
|
|
61
|
+
async handleSendMessage(request) {
|
|
62
|
+
const params = request.params;
|
|
63
|
+
if (!params?.message) {
|
|
64
|
+
return this.errorResponse(request.id, JSONRPC_INVALID_PARAMS, 'Missing "message" in params');
|
|
65
|
+
}
|
|
66
|
+
const message = params.message;
|
|
67
|
+
// Create task
|
|
68
|
+
const task = this.taskManager.createTask(message);
|
|
69
|
+
// Transition to working
|
|
70
|
+
this.taskManager.updateStatus(task.id, 'working');
|
|
71
|
+
try {
|
|
72
|
+
// Resolve which tools to call
|
|
73
|
+
const invocations = (0, tool_router_js_1.resolveToolInvocations)(message, this.mcpClient.getTools());
|
|
74
|
+
if (invocations.length === 0) {
|
|
75
|
+
// No tool matched — return helpful error with available tools
|
|
76
|
+
const listing = (0, tool_router_js_1.buildToolListingText)(this.mcpClient.getTools());
|
|
77
|
+
const agentMsg = (0, task_manager_js_1.createAgentMessage)(listing);
|
|
78
|
+
this.taskManager.addMessage(task.id, agentMsg);
|
|
79
|
+
this.taskManager.updateStatus(task.id, 'completed', agentMsg);
|
|
80
|
+
return this.successResponse(request.id, this.taskManager.serializeTask(task.id));
|
|
81
|
+
}
|
|
82
|
+
// Execute each tool invocation
|
|
83
|
+
const allParts = [];
|
|
84
|
+
let hasError = false;
|
|
85
|
+
for (const invocation of invocations) {
|
|
86
|
+
log.info('Executing MCP tool', {
|
|
87
|
+
taskId: task.id,
|
|
88
|
+
tool: invocation.toolName,
|
|
89
|
+
});
|
|
90
|
+
try {
|
|
91
|
+
const result = await this.mcpClient.callTool(invocation.toolName, invocation.arguments);
|
|
92
|
+
if (result.isError) {
|
|
93
|
+
hasError = true;
|
|
94
|
+
}
|
|
95
|
+
// Convert MCP result to A2A parts
|
|
96
|
+
for (const content of result.content) {
|
|
97
|
+
if (content.type === 'text' && content.text) {
|
|
98
|
+
allParts.push({ kind: 'text', text: content.text });
|
|
99
|
+
}
|
|
100
|
+
else if (content.type === 'image' && content.data) {
|
|
101
|
+
// For non-text content, serialize as JSON text
|
|
102
|
+
allParts.push({
|
|
103
|
+
kind: 'text',
|
|
104
|
+
text: JSON.stringify({
|
|
105
|
+
type: content.type,
|
|
106
|
+
mimeType: content.mimeType,
|
|
107
|
+
dataLength: content.data.length,
|
|
108
|
+
}),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else if (content.type === 'resource' || content.type === 'embedded_resource') {
|
|
112
|
+
allParts.push({
|
|
113
|
+
kind: 'text',
|
|
114
|
+
text: JSON.stringify(content),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (toolErr) {
|
|
120
|
+
hasError = true;
|
|
121
|
+
allParts.push({
|
|
122
|
+
kind: 'text',
|
|
123
|
+
text: `Error calling tool "${invocation.toolName}": ${String(toolErr)}`,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Add artifact with results
|
|
128
|
+
if (allParts.length > 0) {
|
|
129
|
+
const artifactName = invocations.length === 1
|
|
130
|
+
? `${invocations[0].toolName}-result`
|
|
131
|
+
: 'tool-results';
|
|
132
|
+
this.taskManager.addArtifact(task.id, allParts, artifactName);
|
|
133
|
+
}
|
|
134
|
+
// Build agent response message
|
|
135
|
+
const responseText = allParts
|
|
136
|
+
.map(p => p.text)
|
|
137
|
+
.join('\n');
|
|
138
|
+
const agentMsg = (0, task_manager_js_1.createAgentMessage)(responseText);
|
|
139
|
+
this.taskManager.addMessage(task.id, agentMsg);
|
|
140
|
+
// Final state
|
|
141
|
+
const finalState = hasError ? 'failed' : 'completed';
|
|
142
|
+
this.taskManager.updateStatus(task.id, finalState, agentMsg);
|
|
143
|
+
return this.successResponse(request.id, this.taskManager.serializeTask(task.id));
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
const errorMsg = (0, task_manager_js_1.createAgentMessage)(`Task execution failed: ${String(err)}`);
|
|
147
|
+
this.taskManager.addMessage(task.id, errorMsg);
|
|
148
|
+
this.taskManager.updateStatus(task.id, 'failed', errorMsg);
|
|
149
|
+
return this.successResponse(request.id, this.taskManager.serializeTask(task.id));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Handle message/send with streaming — yields SSE events.
|
|
154
|
+
*/
|
|
155
|
+
async *handleSendMessageStream(request) {
|
|
156
|
+
const params = request.params;
|
|
157
|
+
if (!params?.message) {
|
|
158
|
+
throw new Error('Missing "message" in params');
|
|
159
|
+
}
|
|
160
|
+
const message = params.message;
|
|
161
|
+
const task = this.taskManager.createTask(message);
|
|
162
|
+
// Emit initial task
|
|
163
|
+
yield { ...this.taskManager.serializeTask(task.id) };
|
|
164
|
+
// Transition to working
|
|
165
|
+
this.taskManager.updateStatus(task.id, 'working');
|
|
166
|
+
yield this.makeStatusUpdate(task.id, 'working', false);
|
|
167
|
+
try {
|
|
168
|
+
const invocations = (0, tool_router_js_1.resolveToolInvocations)(message, this.mcpClient.getTools());
|
|
169
|
+
if (invocations.length === 0) {
|
|
170
|
+
const listing = (0, tool_router_js_1.buildToolListingText)(this.mcpClient.getTools());
|
|
171
|
+
const agentMsg = (0, task_manager_js_1.createAgentMessage)(listing);
|
|
172
|
+
this.taskManager.addMessage(task.id, agentMsg);
|
|
173
|
+
this.taskManager.updateStatus(task.id, 'completed', agentMsg);
|
|
174
|
+
yield this.makeStatusUpdate(task.id, 'completed', true);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
for (const invocation of invocations) {
|
|
178
|
+
try {
|
|
179
|
+
const result = await this.mcpClient.callTool(invocation.toolName, invocation.arguments);
|
|
180
|
+
const parts = [];
|
|
181
|
+
for (const content of result.content) {
|
|
182
|
+
if (content.type === 'text' && content.text) {
|
|
183
|
+
parts.push({ kind: 'text', text: content.text });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (parts.length > 0) {
|
|
187
|
+
const artifact = this.taskManager.addArtifact(task.id, parts, `${invocation.toolName}-result`);
|
|
188
|
+
// Emit artifact update
|
|
189
|
+
const artifactUpdate = {
|
|
190
|
+
taskId: task.id,
|
|
191
|
+
contextId: this.taskManager.getTask(task.id)?.contextId,
|
|
192
|
+
artifact,
|
|
193
|
+
append: false,
|
|
194
|
+
lastChunk: true,
|
|
195
|
+
kind: 'artifact-update',
|
|
196
|
+
};
|
|
197
|
+
yield artifactUpdate;
|
|
198
|
+
}
|
|
199
|
+
if (result.isError) {
|
|
200
|
+
this.taskManager.updateStatus(task.id, 'failed');
|
|
201
|
+
yield this.makeStatusUpdate(task.id, 'failed', true);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch (toolErr) {
|
|
206
|
+
const errorMsg = (0, task_manager_js_1.createAgentMessage)(`Error: ${String(toolErr)}`);
|
|
207
|
+
this.taskManager.addMessage(task.id, errorMsg);
|
|
208
|
+
this.taskManager.updateStatus(task.id, 'failed', errorMsg);
|
|
209
|
+
yield this.makeStatusUpdate(task.id, 'failed', true);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// All tools succeeded
|
|
214
|
+
this.taskManager.updateStatus(task.id, 'completed');
|
|
215
|
+
yield this.makeStatusUpdate(task.id, 'completed', true);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
this.taskManager.updateStatus(task.id, 'failed');
|
|
219
|
+
yield this.makeStatusUpdate(task.id, 'failed', true);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Handle tasks/get — retrieve a task by ID.
|
|
224
|
+
*/
|
|
225
|
+
handleGetTask(request) {
|
|
226
|
+
const params = request.params;
|
|
227
|
+
if (!params?.id) {
|
|
228
|
+
return this.errorResponse(request.id, JSONRPC_INVALID_PARAMS, 'Missing "id" in params');
|
|
229
|
+
}
|
|
230
|
+
const task = this.taskManager.serializeTask(params.id, params.historyLength);
|
|
231
|
+
if (!task) {
|
|
232
|
+
return this.errorResponse(request.id, A2A_TASK_NOT_FOUND, `Task not found: ${params.id}`);
|
|
233
|
+
}
|
|
234
|
+
return this.successResponse(request.id, task);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Handle tasks/cancel — cancel a running task.
|
|
238
|
+
*/
|
|
239
|
+
handleCancelTask(request) {
|
|
240
|
+
const params = request.params;
|
|
241
|
+
if (!params?.id) {
|
|
242
|
+
return this.errorResponse(request.id, JSONRPC_INVALID_PARAMS, 'Missing "id" in params');
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
const task = this.taskManager.cancelTask(params.id);
|
|
246
|
+
return this.successResponse(request.id, this.taskManager.serializeTask(task.id));
|
|
247
|
+
}
|
|
248
|
+
catch (err) {
|
|
249
|
+
if (err instanceof task_manager_js_1.TaskNotFoundError) {
|
|
250
|
+
return this.errorResponse(request.id, A2A_TASK_NOT_FOUND, err.message);
|
|
251
|
+
}
|
|
252
|
+
return this.errorResponse(request.id, A2A_INVALID_STATE, String(err));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────
|
|
256
|
+
makeStatusUpdate(taskId, state, final) {
|
|
257
|
+
const task = this.taskManager.getTask(taskId);
|
|
258
|
+
return {
|
|
259
|
+
taskId,
|
|
260
|
+
contextId: task?.contextId,
|
|
261
|
+
status: {
|
|
262
|
+
state: state,
|
|
263
|
+
timestamp: new Date().toISOString(),
|
|
264
|
+
},
|
|
265
|
+
final,
|
|
266
|
+
kind: 'status-update',
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
successResponse(id, result) {
|
|
270
|
+
return {
|
|
271
|
+
jsonrpc: '2.0',
|
|
272
|
+
id,
|
|
273
|
+
result,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
errorResponse(id, code, message) {
|
|
277
|
+
return {
|
|
278
|
+
jsonrpc: '2.0',
|
|
279
|
+
id: id ?? 0,
|
|
280
|
+
error: { code, message },
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
exports.A2AHandler = A2AHandler;
|
|
285
|
+
//# sourceMappingURL=a2a-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a2a-handler.js","sourceRoot":"","sources":["../src/a2a-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Card Generator — auto-generates an A2A Agent Card from MCP server capabilities.
|
|
3
|
+
*
|
|
4
|
+
* Maps MCP tools to A2A skills and constructs a compliant Agent Card
|
|
5
|
+
* for discovery at /.well-known/agent.json
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentCard, GatewayConfig } from './types.js';
|
|
8
|
+
import type { McpTool } from './mcp-client.js';
|
|
9
|
+
/**
|
|
10
|
+
* Generate a complete A2A Agent Card from MCP server info and tools.
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateAgentCard(config: GatewayConfig, tools: McpTool[], serverName: string, serverVersion: string): AgentCard;
|
|
13
|
+
/**
|
|
14
|
+
* Re-generate the Agent Card after tool changes (e.g., dynamic tool registration).
|
|
15
|
+
*/
|
|
16
|
+
export declare function refreshAgentCard(existingCard: AgentCard, tools: McpTool[]): AgentCard;
|
|
17
|
+
//# sourceMappingURL=agent-card-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-card-generator.d.ts","sourceRoot":"","sources":["../src/agent-card-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAc,aAAa,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAyD/C;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,OAAO,EAAE,EAChB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,GACpB,SAAS,CAwCX;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,SAAS,EACvB,KAAK,EAAE,OAAO,EAAE,GACf,SAAS,CAWX"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Agent Card Generator — auto-generates an A2A Agent Card from MCP server capabilities.
|
|
4
|
+
*
|
|
5
|
+
* Maps MCP tools to A2A skills and constructs a compliant Agent Card
|
|
6
|
+
* for discovery at /.well-known/agent.json
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.generateAgentCard = generateAgentCard;
|
|
10
|
+
exports.refreshAgentCard = refreshAgentCard;
|
|
11
|
+
const logger_js_1 = require("./logger.js");
|
|
12
|
+
const log = (0, logger_js_1.createLogger)('agent-card');
|
|
13
|
+
/**
|
|
14
|
+
* Derive tags from a tool name by splitting on common separators.
|
|
15
|
+
*/
|
|
16
|
+
function deriveTagsFromName(name) {
|
|
17
|
+
const parts = name
|
|
18
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2') // camelCase -> kebab-case
|
|
19
|
+
.toLowerCase()
|
|
20
|
+
.split(/[-_./]/)
|
|
21
|
+
.filter(p => p.length > 1);
|
|
22
|
+
return [...new Set(parts)];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generate an example prompt for a tool based on its name and description.
|
|
26
|
+
*/
|
|
27
|
+
function generateExample(tool) {
|
|
28
|
+
if (tool.description) {
|
|
29
|
+
// Take the first sentence of the description as a natural language example
|
|
30
|
+
const firstSentence = tool.description.split(/[.!?]/)[0].trim();
|
|
31
|
+
if (firstSentence.length > 10) {
|
|
32
|
+
return firstSentence;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Fallback: convert tool name to readable text
|
|
36
|
+
const readable = tool.name
|
|
37
|
+
.replace(/[-_]/g, ' ')
|
|
38
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
39
|
+
.toLowerCase();
|
|
40
|
+
return `Use ${readable}`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Convert a single MCP tool to an A2A skill.
|
|
44
|
+
*/
|
|
45
|
+
function mcpToolToSkill(tool) {
|
|
46
|
+
const skill = {
|
|
47
|
+
id: tool.name,
|
|
48
|
+
name: tool.name
|
|
49
|
+
.replace(/[-_]/g, ' ')
|
|
50
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
51
|
+
.replace(/\b\w/g, c => c.toUpperCase()),
|
|
52
|
+
description: tool.description || `Execute the ${tool.name} tool`,
|
|
53
|
+
tags: deriveTagsFromName(tool.name),
|
|
54
|
+
examples: [generateExample(tool)],
|
|
55
|
+
inputModes: ['text/plain', 'application/json'],
|
|
56
|
+
outputModes: ['text/plain', 'application/json'],
|
|
57
|
+
};
|
|
58
|
+
return skill;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generate a complete A2A Agent Card from MCP server info and tools.
|
|
62
|
+
*/
|
|
63
|
+
function generateAgentCard(config, tools, serverName, serverVersion) {
|
|
64
|
+
const baseUrl = config.baseUrl || `http://${config.host}:${config.port}`;
|
|
65
|
+
const skills = tools.map(mcpToolToSkill);
|
|
66
|
+
const agentName = config.agentName || serverName || 'MCP Agent';
|
|
67
|
+
const agentDescription = config.agentDescription
|
|
68
|
+
|| `A2A-compatible agent bridging MCP server "${serverName}" with ${tools.length} available tools`;
|
|
69
|
+
const card = {
|
|
70
|
+
name: agentName,
|
|
71
|
+
description: agentDescription,
|
|
72
|
+
url: baseUrl,
|
|
73
|
+
version: config.agentVersion || serverVersion || '1.0.0',
|
|
74
|
+
capabilities: {
|
|
75
|
+
streaming: true,
|
|
76
|
+
pushNotifications: false,
|
|
77
|
+
stateTransitionHistory: true,
|
|
78
|
+
},
|
|
79
|
+
authentication: {
|
|
80
|
+
schemes: ['none'],
|
|
81
|
+
},
|
|
82
|
+
defaultInputModes: ['text/plain', 'application/json'],
|
|
83
|
+
defaultOutputModes: ['text/plain', 'application/json'],
|
|
84
|
+
skills,
|
|
85
|
+
};
|
|
86
|
+
if (config.providerOrg) {
|
|
87
|
+
card.provider = {
|
|
88
|
+
organization: config.providerOrg,
|
|
89
|
+
url: config.providerUrl,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
log.info('Generated Agent Card', {
|
|
93
|
+
name: card.name,
|
|
94
|
+
skills: card.skills.length,
|
|
95
|
+
});
|
|
96
|
+
return card;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Re-generate the Agent Card after tool changes (e.g., dynamic tool registration).
|
|
100
|
+
*/
|
|
101
|
+
function refreshAgentCard(existingCard, tools) {
|
|
102
|
+
const updatedSkills = tools.map(mcpToolToSkill);
|
|
103
|
+
return {
|
|
104
|
+
...existingCard,
|
|
105
|
+
skills: updatedSkills,
|
|
106
|
+
description: existingCard.description.replace(/\d+ available tools/, `${tools.length} available tools`),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=agent-card-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-card-generator.js","sourceRoot":"","sources":["../src/agent-card-generator.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point for truss-a2a-gateway.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* truss-a2a-gateway --command "npx -y @anthropic/mcp-server-files" --args "/tmp"
|
|
7
|
+
* truss-a2a-gateway --url "http://localhost:8080/sse"
|
|
8
|
+
* truss-a2a-gateway --config gateway.json
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG"}
|