This repository has been archived on 2026-06-28. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
a2a-mcp/src/api.ts
Robert 024f14000e
All checks were successful
build / test (push) Successful in 29s
publish / npm (push) Successful in 30s
release: 0.1.4 — forward cp_jwt + bucket via params._meta
On login the gateway now captures user.id from /v1/auth/login, derives
the user's MinIO bucket (user-<id>-files), and persists both in
~/.a2a/credentials.json. UpstreamAgent.callTool injects
``params._meta = { cp_jwt, cp_url, bucket }`` on every tools/call so
upstream agents see the same caller context the platform orchestrator
provides. Unauthenticated clients omit _meta — back-compat preserved.

Requires a2a-pack with the matching _meta handler in
``a2a_pack/mcp/server.py`` (companion change in apps/a2a).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 20:53:07 -03:00

80 lines
2.0 KiB
TypeScript

/**
* Thin control-plane client. Mirrors the relevant subset of
* a2a_pack.cli.api_client.ControlPlaneClient.
*/
export class ApiError extends Error {
constructor(public status: number, message: string) {
super(`API ${status}: ${message}`);
this.name = "ApiError";
}
}
export interface AgentRow {
name: string;
version: string;
status: string;
url?: string;
description?: string;
}
export class ControlPlaneClient {
constructor(
private apiUrl: string,
private token: string | null,
) {
this.apiUrl = apiUrl.replace(/\/+$/, "");
}
private headers(): Record<string, string> {
const h: Record<string, string> = { "content-type": "application/json" };
if (this.token) h["authorization"] = `bearer ${this.token}`;
return h;
}
private async request<T>(method: string, path: string, body?: unknown): Promise<T> {
const resp = await fetch(`${this.apiUrl}${path}`, {
method,
headers: this.headers(),
body: body !== undefined ? JSON.stringify(body) : undefined,
});
if (!resp.ok) {
let detail: string;
try {
const j: any = await resp.json();
detail = j?.detail ?? JSON.stringify(j);
} catch {
detail = await resp.text();
}
throw new ApiError(resp.status, detail);
}
if (resp.status === 204) return undefined as T;
return (await resp.json()) as T;
}
login(email: string, password: string) {
return this.request<{
access_token: string;
user: { id: number; email: string };
}>("POST", "/v1/auth/login", { email, password });
}
signup(email: string, password: string) {
return this.request<{
access_token: string;
user: { id: number; email: string };
}>("POST", "/v1/auth/signup", { email, password });
}
me() {
return this.request<{ id: number; email: string }>("GET", "/v1/me");
}
listAgents() {
return this.request<AgentRow[]>("GET", "/v1/agents");
}
getAgent(name: string) {
return this.request<AgentRow>("GET", `/v1/agents/${encodeURIComponent(name)}`);
}
}