@agentrq/acp-gateway 0.1.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.
@@ -0,0 +1,137 @@
1
+ /**
2
+ * mcpClient.ts
3
+ *
4
+ * Connects to the agentrq MCP server using the MCP TypeScript SDK.
5
+ * Listens for 'notifications/claude/channel' and handles tool calls.
6
+ */
7
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
8
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
9
+ import { EventEmitter } from "node:events";
10
+ import { z } from "zod";
11
+ export class MCPBridge extends EventEmitter {
12
+ config;
13
+ client;
14
+ transport;
15
+ getSessionId() {
16
+ return this.transport._sessionId;
17
+ }
18
+ constructor(config) {
19
+ super();
20
+ this.config = config;
21
+ if (!config.url) {
22
+ throw new Error(`MCP server ${config.name} has no URL`);
23
+ }
24
+ const url = new URL(config.url);
25
+ this.transport = new StreamableHTTPClientTransport(url);
26
+ this.client = new Client({
27
+ name: "acp-gateway",
28
+ version: "0.1.0",
29
+ }, {
30
+ capabilities: {},
31
+ });
32
+ }
33
+ isConnected = false;
34
+ isConnecting = false;
35
+ async connect() {
36
+ if (this.isConnecting || this.isConnected)
37
+ return;
38
+ this.isConnecting = true;
39
+ let attempt = 0;
40
+ const initialDelay = 1000;
41
+ const maxDelay = 30000;
42
+ while (!this.isConnected) {
43
+ try {
44
+ await this._connectOnce();
45
+ this.isConnected = true;
46
+ this.isConnecting = false;
47
+ console.error(`[mcp] Connected to ${this.config.name}`);
48
+ }
49
+ catch (error) {
50
+ const delay = Math.min(initialDelay * Math.pow(2, attempt), maxDelay);
51
+ console.error(`[mcp] Connection failed to ${this.config.name}. Retrying in ${delay / 1000}s...`);
52
+ await new Promise((resolve) => setTimeout(resolve, delay));
53
+ attempt++;
54
+ }
55
+ }
56
+ }
57
+ async _connectOnce() {
58
+ if (this.transport) {
59
+ await this.transport.close().catch(() => { });
60
+ }
61
+ if (!this.config.url) {
62
+ throw new Error("MCP server URL is not configured");
63
+ }
64
+ const url = new URL(this.config.url);
65
+ this.transport = new StreamableHTTPClientTransport(url);
66
+ // Set up transport hooks for disconnection
67
+ this.transport.onclose = () => {
68
+ if (this.isConnected) {
69
+ console.error(`[mcp] Connection to ${this.config.name} lost.`);
70
+ this.isConnected = false;
71
+ this.connect(); // Start reconnection loop
72
+ }
73
+ };
74
+ this.transport.onerror = (error) => {
75
+ console.error(`[mcp] Transport error:`, error.message || error);
76
+ };
77
+ await this.client.connect(this.transport);
78
+ // Set notification handler for directives from the MCP server.
79
+ this.client.setNotificationHandler(z.object({
80
+ method: z.literal("notifications/claude/channel"),
81
+ params: z.object({
82
+ content: z.string(),
83
+ meta: z.any().optional(),
84
+ }),
85
+ }), (notification) => {
86
+ console.error("[mcp] Received channel notification");
87
+ const { content, meta } = notification.params;
88
+ this.emit("task", { content, meta });
89
+ });
90
+ // Set notification handler for permission verdicts
91
+ this.client.setNotificationHandler(z.object({
92
+ method: z.literal("notifications/claude/channel/permission"),
93
+ params: z.object({
94
+ request_id: z.string(),
95
+ behavior: z.string(), // "allow" | "deny"
96
+ }),
97
+ }), (notification) => {
98
+ console.error("[mcp] Received permission verdict");
99
+ const { request_id, behavior } = notification.params;
100
+ this.emit("verdict", { requestId: request_id, behavior });
101
+ });
102
+ }
103
+ async ensureConnected() {
104
+ if (this.isConnected)
105
+ return;
106
+ if (!this.isConnecting) {
107
+ this.connect();
108
+ }
109
+ // Wait up to 10 seconds for connection
110
+ let waited = 0;
111
+ while (!this.isConnected && waited < 10000) {
112
+ await new Promise((resolve) => setTimeout(resolve, 500));
113
+ waited += 500;
114
+ }
115
+ if (!this.isConnected) {
116
+ throw new Error(`MCP not connected after 10s timeout`);
117
+ }
118
+ }
119
+ async callTool(name, args = {}) {
120
+ await this.ensureConnected();
121
+ return await this.client.callTool({
122
+ name,
123
+ arguments: args,
124
+ });
125
+ }
126
+ async sendNotification(method, params) {
127
+ await this.ensureConnected();
128
+ await this.client.notification({
129
+ method,
130
+ params,
131
+ });
132
+ }
133
+ async close() {
134
+ await this.client.close();
135
+ }
136
+ }
137
+ //# sourceMappingURL=mcpClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpClient.js","sourceRoot":"","sources":["../src/mcpClient.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@agentrq/acp-gateway",
3
+ "version": "0.1.0",
4
+ "description": "ACP+MCP bridge CLI for agentrq workspaces",
5
+ "type": "module",
6
+ "publishConfig": {
7
+ "access": "public",
8
+ "provenance": true
9
+ },
10
+ "bin": {
11
+ "acp-gateway": "./dist/index.js"
12
+ },
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsx src/index.ts",
16
+ "typecheck": "tsc --noEmit",
17
+ "test": "vitest run",
18
+ "prepare": "npm run build",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "engines": {
27
+ "node": ">=20"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/agentrq/acp-gateway"
32
+ },
33
+ "keywords": [
34
+ "acp",
35
+ "mcp",
36
+ "gateway",
37
+ "bridge",
38
+ "agentrq"
39
+ ],
40
+ "dependencies": {
41
+ "@agentclientprotocol/sdk": "^0.19.0",
42
+ "@modelcontextprotocol/sdk": "^1.10.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^22",
46
+ "@vitest/coverage-v8": "^4.1.4",
47
+ "tsx": "^4.19.2",
48
+ "typescript": "^5.8.3",
49
+ "vitest": "^4.1.4"
50
+ }
51
+ }