mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-27 04:30:59 +00:00
Permissions working... ish
This commit is contained in:
999
package-lock.json
generated
999
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"start": "node dist/acp-agent.js",
|
||||
"start": "node dist/index.js",
|
||||
"dev": "npm run build && npm run start",
|
||||
"lint": "eslint src --ext .ts"
|
||||
},
|
||||
@@ -23,10 +23,15 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/claude-code": "^1.0.92",
|
||||
"@zed-industries/agent-client-protocol": "0.0.32",
|
||||
"@modelcontextprotocol/sdk": "^1.17.4",
|
||||
"@types/express": "^5.0.3",
|
||||
"@zed-industries/agent-client-protocol": "0.1.0",
|
||||
"express": "^5.1.0",
|
||||
"minimist": "^1.2.8",
|
||||
"uuid": "11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/minimist": "^1.2.5",
|
||||
"@types/node": "^20.11.30",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"eslint": "^8.56.0",
|
||||
|
||||
@@ -30,6 +30,8 @@ import {
|
||||
} from "./utils.js";
|
||||
import { ContentBlock } from "@zed-industries/agent-client-protocol";
|
||||
import { SessionNotification } from "@zed-industries/agent-client-protocol";
|
||||
import { createMcpServer } from "./mcp-server.js";
|
||||
import { AddressInfo } from "node:net";
|
||||
|
||||
// Implement the ACP Agent interface
|
||||
class ClaudeAcpAgent implements Agent {
|
||||
@@ -68,10 +70,27 @@ class ClaudeAcpAgent implements Agent {
|
||||
}
|
||||
|
||||
// todo!() auth, permissionPromptToolName
|
||||
let server = await createMcpServer();
|
||||
let address = server.address() as AddressInfo;
|
||||
mcpServers["acp"] = {
|
||||
type: "http",
|
||||
url: "http://127.0.0.1:" + address.port + "/mcp",
|
||||
headers: {
|
||||
"x-acp-proxy-session-id": sessionId,
|
||||
},
|
||||
};
|
||||
console.error(mcpServers);
|
||||
|
||||
let q = query({
|
||||
prompt: input,
|
||||
options: { cwd: params.cwd, mcpServers },
|
||||
options: {
|
||||
cwd: params.cwd,
|
||||
mcpServers,
|
||||
executableArgs: ["--debug"],
|
||||
strictMcpConfig: true,
|
||||
permissionPromptToolName: "mcp__acp__permission",
|
||||
stderr: (err) => console.error(err),
|
||||
},
|
||||
});
|
||||
this.sessions[sessionId] = { query: q, input: input };
|
||||
|
||||
@@ -90,7 +109,6 @@ class ClaudeAcpAgent implements Agent {
|
||||
}
|
||||
|
||||
const { query, input } = this.sessions[params.sessionId];
|
||||
query.interrupt();
|
||||
input.push(promptToClaude(params));
|
||||
while (true) {
|
||||
let { value: message, done } = await query.next();
|
||||
@@ -269,20 +287,19 @@ function toAcpNotifications(
|
||||
default:
|
||||
throw new Error("unhandled chunk type: " + chunk.type);
|
||||
}
|
||||
output.push({ sessionId: message.session_id, update });
|
||||
output.push({ sessionId, update });
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
export function runAcp() {
|
||||
new AgentSideConnection(
|
||||
(client) => new ClaudeAcpAgent(client),
|
||||
nodeToWebWritable(process.stdout),
|
||||
nodeToWebReadable(process.stdin),
|
||||
);
|
||||
|
||||
// Keep process alive
|
||||
process.stdin.resume();
|
||||
}
|
||||
|
||||
type ContentChunk =
|
||||
| { type: "text"; text: string }
|
||||
|
||||
5
src/index.ts
Normal file
5
src/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { runAcp as runAcp } from "./acp-agent.js";
|
||||
runAcp();
|
||||
|
||||
// Keep process alive
|
||||
process.stdin.resume();
|
||||
89
src/mcp-server.ts
Normal file
89
src/mcp-server.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import express from "express";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
||||
import { z } from "zod";
|
||||
import { Server } from "node:http";
|
||||
|
||||
export function createMcpServer(): Promise<Server> {
|
||||
// Create MCP server
|
||||
const server = new McpServer({
|
||||
name: "acp-mcp-server",
|
||||
version: "1.0.0",
|
||||
});
|
||||
|
||||
// Register a simple echo tool (for demonstration)
|
||||
server.registerTool(
|
||||
"permission",
|
||||
{
|
||||
title: "Permission Tool",
|
||||
description: "Used to request tool permissions",
|
||||
inputSchema: {
|
||||
tool_name: z.string(),
|
||||
input: z.any(),
|
||||
tool_use_id: z.string().optional(),
|
||||
},
|
||||
},
|
||||
async (input) => {
|
||||
console.error("PERMISSION TOOl", input);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: JSON.stringify({
|
||||
behavior: "allow",
|
||||
updatedInput: input.input,
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
app.post("/mcp", async (req, res) => {
|
||||
try {
|
||||
const transport: StreamableHTTPServerTransport =
|
||||
new StreamableHTTPServerTransport({
|
||||
sessionIdGenerator: undefined,
|
||||
});
|
||||
res.on("close", () => {
|
||||
transport.close();
|
||||
server.close();
|
||||
});
|
||||
await server.connect(transport);
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
} catch (error) {
|
||||
console.error("Error handling MCP request:", error);
|
||||
if (!res.headersSent) {
|
||||
res.status(500).json({
|
||||
jsonrpc: "2.0",
|
||||
error: {
|
||||
code: -32603,
|
||||
message: "Internal server error",
|
||||
},
|
||||
id: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const listener = app.listen(0, "127.0.0.1", (error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
const address = listener.address();
|
||||
console.error(address);
|
||||
if (typeof address === "object" && address && "port" in address) {
|
||||
console.error(
|
||||
`MCP HTTP server listening on http://127.0.0.1:${address.port}/mcp`,
|
||||
);
|
||||
}
|
||||
resolve(listener);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user