capix-mcp 2.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.
- package/CONTRIBUTING.md +168 -0
- package/LICENSE +201 -0
- package/README.md +309 -0
- package/bin/capix-mcp.js +2 -0
- package/dist/capixClient.d.ts +127 -0
- package/dist/capixClient.d.ts.map +1 -0
- package/dist/capixClient.js +77 -0
- package/dist/capixClient.js.map +1 -0
- package/dist/client.d.ts +119 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +308 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +307 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.d.ts +28 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +203 -0
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +28 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +101 -0
- package/dist/resources.js.map +1 -0
- package/dist/server.d.ts +61 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +223 -0
- package/dist/server.js.map +1 -0
- package/dist/tools.d.ts +32 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +1101 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +194 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +43 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capix API client — thin wrapper over the Capix network REST API.
|
|
3
|
+
*
|
|
4
|
+
* All deploy/destroy/status/billing calls go through capix.network.
|
|
5
|
+
* The session token is passed as a Bearer header — same as the web console
|
|
6
|
+
* and the Capix IDE extension. So a user who's authenticated anywhere
|
|
7
|
+
* is authenticated everywhere.
|
|
8
|
+
*/
|
|
9
|
+
export interface CatalogModel {
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
family: string;
|
|
13
|
+
category: string;
|
|
14
|
+
paramB: number;
|
|
15
|
+
minVramGb: number;
|
|
16
|
+
gpuCount: number;
|
|
17
|
+
maxModelLen: number;
|
|
18
|
+
quantization: string;
|
|
19
|
+
gated: boolean;
|
|
20
|
+
tagline: string;
|
|
21
|
+
description: string;
|
|
22
|
+
partner?: string;
|
|
23
|
+
uncensored?: boolean;
|
|
24
|
+
multimodal?: boolean;
|
|
25
|
+
featured?: boolean;
|
|
26
|
+
badge?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function getCatalog(): Promise<CatalogModel[]>;
|
|
29
|
+
export interface GpuOffer {
|
|
30
|
+
askId: number;
|
|
31
|
+
gpu: string;
|
|
32
|
+
numGpus: number;
|
|
33
|
+
vramGb: number;
|
|
34
|
+
totalVramGb: number;
|
|
35
|
+
cpuCores: number;
|
|
36
|
+
ramGb: number;
|
|
37
|
+
pricePerHr: number;
|
|
38
|
+
roundedPricePerHr: number;
|
|
39
|
+
location: string;
|
|
40
|
+
reliability: number;
|
|
41
|
+
}
|
|
42
|
+
export declare function getOffers(modelId: string, region?: string): Promise<GpuOffer[]>;
|
|
43
|
+
export interface DeployResult {
|
|
44
|
+
ok: boolean;
|
|
45
|
+
instanceId: number;
|
|
46
|
+
apiKey: string;
|
|
47
|
+
model: {
|
|
48
|
+
id: string;
|
|
49
|
+
label: string;
|
|
50
|
+
maxModelLen: number;
|
|
51
|
+
};
|
|
52
|
+
gpu: string;
|
|
53
|
+
location: string;
|
|
54
|
+
pricePerHr: number;
|
|
55
|
+
chargedUsd: number;
|
|
56
|
+
endpoint: string | null;
|
|
57
|
+
error?: string;
|
|
58
|
+
}
|
|
59
|
+
export declare function deployModel(modelId: string, askId: number, durationHours: number, hfToken?: string): Promise<DeployResult>;
|
|
60
|
+
export declare function deployCustomModel(opts: {
|
|
61
|
+
link: string;
|
|
62
|
+
askId: number;
|
|
63
|
+
durationHours: number;
|
|
64
|
+
minVramGb?: number;
|
|
65
|
+
gpuCount?: number;
|
|
66
|
+
hfToken?: string;
|
|
67
|
+
manual?: boolean;
|
|
68
|
+
}): Promise<DeployResult & {
|
|
69
|
+
error?: string;
|
|
70
|
+
}>;
|
|
71
|
+
export interface DeployStatus {
|
|
72
|
+
ok: boolean;
|
|
73
|
+
instanceId: number;
|
|
74
|
+
modelLabel: string;
|
|
75
|
+
hasApiKey: boolean;
|
|
76
|
+
state: "loading" | "running" | "stopped" | "unknown";
|
|
77
|
+
endpoint: string | null;
|
|
78
|
+
ready: boolean;
|
|
79
|
+
baseOpenAiUrl: string | null;
|
|
80
|
+
gpu: string;
|
|
81
|
+
location: string;
|
|
82
|
+
pricePerHr: number;
|
|
83
|
+
sshHost: string | null;
|
|
84
|
+
sshPort: number | null;
|
|
85
|
+
}
|
|
86
|
+
export declare function getDeployStatus(instanceId: number): Promise<DeployStatus>;
|
|
87
|
+
export declare function getDeployApiKey(instanceId: number): Promise<{
|
|
88
|
+
ok: boolean;
|
|
89
|
+
apiKey?: string;
|
|
90
|
+
error?: string;
|
|
91
|
+
}>;
|
|
92
|
+
export declare function listDeploys(): Promise<{
|
|
93
|
+
ok: boolean;
|
|
94
|
+
deploys: unknown[];
|
|
95
|
+
}>;
|
|
96
|
+
export declare function destroyDeploy(instanceId: number): Promise<{
|
|
97
|
+
ok: boolean;
|
|
98
|
+
}>;
|
|
99
|
+
export interface BillingData {
|
|
100
|
+
ok: boolean;
|
|
101
|
+
balance: {
|
|
102
|
+
usd: number;
|
|
103
|
+
sol: number;
|
|
104
|
+
usdc: number;
|
|
105
|
+
};
|
|
106
|
+
activeInstances: number;
|
|
107
|
+
totalSpent: number;
|
|
108
|
+
}
|
|
109
|
+
export declare function getBalance(): Promise<BillingData>;
|
|
110
|
+
export interface HostedEndpoint {
|
|
111
|
+
modelId: string;
|
|
112
|
+
modelLabel: string;
|
|
113
|
+
baseUrl: string;
|
|
114
|
+
region: string;
|
|
115
|
+
healthy: boolean;
|
|
116
|
+
isSuperGemma: boolean;
|
|
117
|
+
apiKeyMasked: string;
|
|
118
|
+
}
|
|
119
|
+
export declare function getHostedEndpoints(): Promise<HostedEndpoint[]>;
|
|
120
|
+
export declare function revealHostedKey(modelId: string): Promise<{
|
|
121
|
+
ok: boolean;
|
|
122
|
+
apiKey?: string;
|
|
123
|
+
error?: string;
|
|
124
|
+
}>;
|
|
125
|
+
export declare const configured: () => boolean;
|
|
126
|
+
export declare const baseUrl: () => string;
|
|
127
|
+
//# sourceMappingURL=capixClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capixClient.d.ts","sourceRoot":"","sources":["../src/capixClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capix API client — thin wrapper over the Capix network REST API.
|
|
3
|
+
*
|
|
4
|
+
* All deploy/destroy/status/billing calls go through capix.network.
|
|
5
|
+
* The session token is passed as a Bearer header — same as the web console
|
|
6
|
+
* and the Capix IDE extension. So a user who's authenticated anywhere
|
|
7
|
+
* is authenticated everywhere.
|
|
8
|
+
*/
|
|
9
|
+
const CAPIX_BASE_URL = process.env.CAPIX_BASE_URL?.replace(/\/$/, "") || "https://capix.network";
|
|
10
|
+
const CAPIX_API_KEY = process.env.CAPIX_API_KEY || "";
|
|
11
|
+
function authHeaders() {
|
|
12
|
+
return CAPIX_API_KEY ? { Authorization: `Bearer ${CAPIX_API_KEY}` } : {};
|
|
13
|
+
}
|
|
14
|
+
async function apiRequest(path, method = "GET", body, params) {
|
|
15
|
+
const url = new URL(`${CAPIX_BASE_URL}${path}`);
|
|
16
|
+
if (params)
|
|
17
|
+
for (const [k, v] of Object.entries(params))
|
|
18
|
+
url.searchParams.set(k, v);
|
|
19
|
+
const res = await fetch(url.toString(), {
|
|
20
|
+
method,
|
|
21
|
+
headers: { "Content-Type": "application/json", ...authHeaders() },
|
|
22
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
23
|
+
});
|
|
24
|
+
return res.json();
|
|
25
|
+
}
|
|
26
|
+
export async function getCatalog() {
|
|
27
|
+
const res = await apiRequest("/api/llm/models");
|
|
28
|
+
return res.ok ? res.models : [];
|
|
29
|
+
}
|
|
30
|
+
export async function getOffers(modelId, region) {
|
|
31
|
+
const params = { modelId };
|
|
32
|
+
if (region && region !== "global")
|
|
33
|
+
params.region = region;
|
|
34
|
+
const res = await apiRequest("/api/llm/offers", "GET", undefined, params);
|
|
35
|
+
return res.ok ? res.offers : [];
|
|
36
|
+
}
|
|
37
|
+
export async function deployModel(modelId, askId, durationHours, hfToken) {
|
|
38
|
+
return apiRequest("/api/llm/deploy", "POST", {
|
|
39
|
+
modelId,
|
|
40
|
+
askId,
|
|
41
|
+
durationHours,
|
|
42
|
+
hfToken,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
// ── Deploy a custom model (Hugging Face link) ──────────────────────────────
|
|
46
|
+
export async function deployCustomModel(opts) {
|
|
47
|
+
return apiRequest("/api/llm/custom", "POST", {
|
|
48
|
+
action: "deploy",
|
|
49
|
+
...opts,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
export async function getDeployStatus(instanceId) {
|
|
53
|
+
return apiRequest(`/api/llm/${instanceId}?action=status`);
|
|
54
|
+
}
|
|
55
|
+
export async function getDeployApiKey(instanceId) {
|
|
56
|
+
return apiRequest(`/api/llm/${instanceId}?action=reveal-key`);
|
|
57
|
+
}
|
|
58
|
+
// ── List + destroy ─────────────────────────────────────────────────────────
|
|
59
|
+
export async function listDeploys() {
|
|
60
|
+
return apiRequest("/api/llm/0?action=list");
|
|
61
|
+
}
|
|
62
|
+
export async function destroyDeploy(instanceId) {
|
|
63
|
+
return apiRequest(`/api/llm/${instanceId}`, "DELETE");
|
|
64
|
+
}
|
|
65
|
+
export async function getBalance() {
|
|
66
|
+
return apiRequest("/api/cloud/billing");
|
|
67
|
+
}
|
|
68
|
+
export async function getHostedEndpoints() {
|
|
69
|
+
const res = await apiRequest("/api/llm/hosted");
|
|
70
|
+
return res.ok ? res.endpoints : [];
|
|
71
|
+
}
|
|
72
|
+
export async function revealHostedKey(modelId) {
|
|
73
|
+
return apiRequest(`/api/llm/hosted?reveal=true&modelId=${encodeURIComponent(modelId)}`);
|
|
74
|
+
}
|
|
75
|
+
export const configured = () => Boolean(CAPIX_API_KEY);
|
|
76
|
+
export const baseUrl = () => CAPIX_BASE_URL;
|
|
77
|
+
//# sourceMappingURL=capixClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capixClient.js","sourceRoot":"","sources":["../src/capixClient.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,uBAAuB,CAAC;AACjG,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;AAEtD,SAAS,WAAW;IAClB,OAAO,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3E,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,IAAY,EACZ,SAAoC,KAAK,EACzC,IAAc,EACd,MAA+B;IAE/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,cAAc,GAAG,IAAI,EAAE,CAAC,CAAC;IAChD,IAAI,MAAM;QAAE,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEpF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;QACtC,MAAM;QACN,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,WAAW,EAAE,EAAE;QACjE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC9C,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAwBD,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,GAAG,GAAG,MAAM,UAAU,CAA0C,iBAAiB,CAAC,CAAC;IACzF,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;AAClC,CAAC;AAkBD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,MAAe;IAC9D,MAAM,MAAM,GAA2B,EAAE,OAAO,EAAE,CAAC;IACnD,IAAI,MAAM,IAAI,MAAM,KAAK,QAAQ;QAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,UAAU,CAAsC,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC/G,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;AAClC,CAAC;AAiBD,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAe,EACf,KAAa,EACb,aAAqB,EACrB,OAAgB;IAEhB,OAAO,UAAU,CAAe,iBAAiB,EAAE,MAAM,EAAE;QACzD,OAAO;QACP,KAAK;QACL,aAAa;QACb,OAAO;KACR,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAQvC;IACC,OAAO,UAAU,CAAoC,iBAAiB,EAAE,MAAM,EAAE;QAC9E,MAAM,EAAE,QAAQ;QAChB,GAAG,IAAI;KACR,CAAC,CAAC;AACL,CAAC;AAoBD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB;IACtD,OAAO,UAAU,CAAe,YAAY,UAAU,gBAAgB,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB;IACtD,OAAO,UAAU,CAAC,YAAY,UAAU,oBAAoB,CAAC,CAAC;AAChE,CAAC;AAED,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,UAAU,CAAC,wBAAwB,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAAkB;IACpD,OAAO,UAAU,CAAC,YAAY,UAAU,EAAE,EAAE,QAAQ,CAAC,CAAC;AACxD,CAAC;AAWD,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,OAAO,UAAU,CAAc,oBAAoB,CAAC,CAAC;AACvD,CAAC;AAcD,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,GAAG,GAAG,MAAM,UAAU,CAA+C,iBAAiB,CAAC,CAAC;IAC9F,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAe;IACnD,OAAO,UAAU,CAAC,uCAAuC,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;AACvD,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,cAAc,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capix API client — the canonical HTTP boundary for the MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Every tool handler delegates to an instance of this class; the client is the
|
|
5
|
+
* only place that touches `fetch`, auth headers, problem+json parsing, or
|
|
6
|
+
* idempotency keys. Mirrors the conventions of
|
|
7
|
+
* services/intelligence/mcp-bridge.ts and Capix-Backend API routes.
|
|
8
|
+
*
|
|
9
|
+
* Design guarantees:
|
|
10
|
+
*
|
|
11
|
+
* - canonical endpoints — all calls go to `/api/v1/*` (never legacy
|
|
12
|
+
* `/api/llm/*` or `/api/cloud/*` paths).
|
|
13
|
+
* - problem+json — non-2xx responses are parsed as RFC 7807
|
|
14
|
+
* ProblemDetail and surfaced as CapixApiError.
|
|
15
|
+
* - idempotency keys — POST/DELETE mutations get an `Idempotency-Key`
|
|
16
|
+
* header derived from the request body so retries
|
|
17
|
+
* are safe (§4 ledger holds are deduped upstream).
|
|
18
|
+
* - approval tokens — billable mutations forward the bound
|
|
19
|
+
* approvalToken as `X-Capix-Approval-Token`.
|
|
20
|
+
* - auth broker first — when `@capix/auth-broker` is importable and a
|
|
21
|
+
* stored refresh token exists, the client obtains
|
|
22
|
+
* a fresh OAuth access token via the broker's
|
|
23
|
+
* crash-safe dual-slot rotation. Otherwise it
|
|
24
|
+
* falls back to the `CAPIX_API_KEY` env var.
|
|
25
|
+
*/
|
|
26
|
+
import type { AccountInfo, AuthBrokerLike, AuthState, CapixClientLike, TokenSet } from "./types.js";
|
|
27
|
+
/** A pluggable source of a Bearer access token for the API client. */
|
|
28
|
+
export interface AuthProvider {
|
|
29
|
+
getToken(): Promise<string | null>;
|
|
30
|
+
isAuthenticated(): boolean;
|
|
31
|
+
getAccount(): AccountInfo | null;
|
|
32
|
+
}
|
|
33
|
+
/** Stateless provider that returns a static API key from the environment. */
|
|
34
|
+
export declare class ApiKeyAuthProvider implements AuthProvider {
|
|
35
|
+
private readonly apiKey;
|
|
36
|
+
constructor(apiKey: string);
|
|
37
|
+
getToken(): Promise<string | null>;
|
|
38
|
+
isAuthenticated(): boolean;
|
|
39
|
+
getAccount(): AccountInfo | null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Provider backed by the shared @capix/auth-broker. The broker itself is
|
|
43
|
+
* dynamically imported so this package has no hard dependency on the private
|
|
44
|
+
* protocol workspace.
|
|
45
|
+
*/
|
|
46
|
+
export declare class BrokerAuthProvider implements AuthProvider {
|
|
47
|
+
private readonly broker;
|
|
48
|
+
private cached;
|
|
49
|
+
constructor(broker: AuthBrokerLike);
|
|
50
|
+
getToken(): Promise<string | null>;
|
|
51
|
+
isAuthenticated(): boolean;
|
|
52
|
+
getAccount(): AccountInfo | null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Try to construct a BrokerAuthProvider by dynamically importing
|
|
56
|
+
* `@capix/auth-broker`. Returns null when the package is not installed or no
|
|
57
|
+
* stored credentials are present, so the caller can fall back to an API key.
|
|
58
|
+
*/
|
|
59
|
+
export declare function tryCreateBrokerAuthProvider(opts?: {
|
|
60
|
+
baseUrl?: string;
|
|
61
|
+
clientId?: string;
|
|
62
|
+
scope?: string;
|
|
63
|
+
}): Promise<BrokerAuthProvider | null>;
|
|
64
|
+
/** Resolve the best available auth provider: broker first, then API key. */
|
|
65
|
+
export declare function resolveAuthProvider(opts?: {
|
|
66
|
+
baseUrl?: string;
|
|
67
|
+
apiKey?: string;
|
|
68
|
+
}): Promise<AuthProvider>;
|
|
69
|
+
export interface CapixClientOptions {
|
|
70
|
+
baseUrl: string;
|
|
71
|
+
authProvider: AuthProvider;
|
|
72
|
+
/** Default project id used for unscoped read calls. */
|
|
73
|
+
projectId?: string;
|
|
74
|
+
/** Optional fetch override (for tests). */
|
|
75
|
+
fetchImpl?: typeof fetch;
|
|
76
|
+
/** Logger for diagnostic stderr output. */
|
|
77
|
+
log?: (msg: string) => void;
|
|
78
|
+
}
|
|
79
|
+
export declare class CapixClient implements CapixClientLike {
|
|
80
|
+
private readonly baseUrl;
|
|
81
|
+
private readonly auth;
|
|
82
|
+
private readonly projectId?;
|
|
83
|
+
private readonly fetchImpl;
|
|
84
|
+
private readonly log;
|
|
85
|
+
constructor(opts: CapixClientOptions);
|
|
86
|
+
isAuthenticated(): boolean;
|
|
87
|
+
getAccount(): AccountInfo | null;
|
|
88
|
+
getProjectId(): string | undefined;
|
|
89
|
+
get<T = unknown>(path: string, params?: Record<string, unknown>): Promise<T>;
|
|
90
|
+
post<T = unknown>(path: string, body?: Record<string, unknown>, opts?: {
|
|
91
|
+
idempotent?: boolean;
|
|
92
|
+
approvalToken?: string;
|
|
93
|
+
}): Promise<T>;
|
|
94
|
+
delete<T = unknown>(path: string): Promise<T>;
|
|
95
|
+
private buildUrl;
|
|
96
|
+
private headers;
|
|
97
|
+
private requireToken;
|
|
98
|
+
/**
|
|
99
|
+
* Derive a stable idempotency key from the request path + body hash + a
|
|
100
|
+
* fresh nonce. The nonce ensures that the *caller's* retries (same args)
|
|
101
|
+
* collapse while distinct invocations get distinct keys.
|
|
102
|
+
*/
|
|
103
|
+
private idempotencyKey;
|
|
104
|
+
/**
|
|
105
|
+
* Parse a fetch Response. Non-2xx responses are decoded as problem+json
|
|
106
|
+
* (RFC 7807) and thrown as CapixApiError. Empty 204 responses yield null.
|
|
107
|
+
*/
|
|
108
|
+
private parse;
|
|
109
|
+
private fallbackProblem;
|
|
110
|
+
}
|
|
111
|
+
/** Build a CapixClient from environment defaults (broker → API key fallback). */
|
|
112
|
+
export declare function createClient(opts?: {
|
|
113
|
+
baseUrl?: string;
|
|
114
|
+
apiKey?: string;
|
|
115
|
+
projectId?: string;
|
|
116
|
+
log?: (msg: string) => void;
|
|
117
|
+
}): Promise<CapixClient>;
|
|
118
|
+
export type { AuthState, TokenSet };
|
|
119
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capix API client — the canonical HTTP boundary for the MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Every tool handler delegates to an instance of this class; the client is the
|
|
5
|
+
* only place that touches `fetch`, auth headers, problem+json parsing, or
|
|
6
|
+
* idempotency keys. Mirrors the conventions of
|
|
7
|
+
* services/intelligence/mcp-bridge.ts and Capix-Backend API routes.
|
|
8
|
+
*
|
|
9
|
+
* Design guarantees:
|
|
10
|
+
*
|
|
11
|
+
* - canonical endpoints — all calls go to `/api/v1/*` (never legacy
|
|
12
|
+
* `/api/llm/*` or `/api/cloud/*` paths).
|
|
13
|
+
* - problem+json — non-2xx responses are parsed as RFC 7807
|
|
14
|
+
* ProblemDetail and surfaced as CapixApiError.
|
|
15
|
+
* - idempotency keys — POST/DELETE mutations get an `Idempotency-Key`
|
|
16
|
+
* header derived from the request body so retries
|
|
17
|
+
* are safe (§4 ledger holds are deduped upstream).
|
|
18
|
+
* - approval tokens — billable mutations forward the bound
|
|
19
|
+
* approvalToken as `X-Capix-Approval-Token`.
|
|
20
|
+
* - auth broker first — when `@capix/auth-broker` is importable and a
|
|
21
|
+
* stored refresh token exists, the client obtains
|
|
22
|
+
* a fresh OAuth access token via the broker's
|
|
23
|
+
* crash-safe dual-slot rotation. Otherwise it
|
|
24
|
+
* falls back to the `CAPIX_API_KEY` env var.
|
|
25
|
+
*/
|
|
26
|
+
import { randomUUID, createHash } from "node:crypto";
|
|
27
|
+
import { homedir } from "node:os";
|
|
28
|
+
import { join } from "node:path";
|
|
29
|
+
import { CapixApiError, DEFAULT_CAPIX_BASE_URL, DEFAULT_OAUTH_CLIENT_ID, DEFAULT_OAUTH_SCOPE } from "./types.js";
|
|
30
|
+
/** Stateless provider that returns a static API key from the environment. */
|
|
31
|
+
export class ApiKeyAuthProvider {
|
|
32
|
+
apiKey;
|
|
33
|
+
constructor(apiKey) {
|
|
34
|
+
this.apiKey = apiKey;
|
|
35
|
+
}
|
|
36
|
+
async getToken() {
|
|
37
|
+
return this.apiKey || null;
|
|
38
|
+
}
|
|
39
|
+
isAuthenticated() {
|
|
40
|
+
return Boolean(this.apiKey);
|
|
41
|
+
}
|
|
42
|
+
getAccount() {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Provider backed by the shared @capix/auth-broker. The broker itself is
|
|
48
|
+
* dynamically imported so this package has no hard dependency on the private
|
|
49
|
+
* protocol workspace.
|
|
50
|
+
*/
|
|
51
|
+
export class BrokerAuthProvider {
|
|
52
|
+
broker;
|
|
53
|
+
cached = null;
|
|
54
|
+
constructor(broker) {
|
|
55
|
+
this.broker = broker;
|
|
56
|
+
}
|
|
57
|
+
async getToken() {
|
|
58
|
+
if (this.broker.getState() !== "authenticated")
|
|
59
|
+
return null;
|
|
60
|
+
if (this.cached && this.cached.expiresAt > Date.now() + 60_000) {
|
|
61
|
+
return this.cached.token;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const token = await this.broker.getAccessToken();
|
|
65
|
+
const account = this.broker.getAccount();
|
|
66
|
+
this.cached = { token, expiresAt: account?.expiresAt ?? Date.now() + 3_600_000 };
|
|
67
|
+
return token;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
isAuthenticated() {
|
|
74
|
+
return this.broker.getState() === "authenticated";
|
|
75
|
+
}
|
|
76
|
+
getAccount() {
|
|
77
|
+
return this.broker.getAccount();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Try to construct a BrokerAuthProvider by dynamically importing
|
|
82
|
+
* `@capix/auth-broker`. Returns null when the package is not installed or no
|
|
83
|
+
* stored credentials are present, so the caller can fall back to an API key.
|
|
84
|
+
*/
|
|
85
|
+
export async function tryCreateBrokerAuthProvider(opts) {
|
|
86
|
+
const baseUrl = opts?.baseUrl ?? process.env.CAPIX_BASE_URL ?? DEFAULT_CAPIX_BASE_URL;
|
|
87
|
+
const clientId = opts?.clientId ?? process.env.CAPIX_OAUTH_CLIENT_ID ?? DEFAULT_OAUTH_CLIENT_ID;
|
|
88
|
+
const scope = opts?.scope ?? DEFAULT_OAUTH_SCOPE;
|
|
89
|
+
// Dynamic import of the optional @capix/auth-broker peer dependency. The
|
|
90
|
+
// ambient declaration in src/auth-broker.d.ts lets TypeScript resolve the
|
|
91
|
+
// module at compile time; the runtime import succeeds only when the package
|
|
92
|
+
// is actually installed.
|
|
93
|
+
let mod = null;
|
|
94
|
+
try {
|
|
95
|
+
mod = await import("@capix/auth-broker");
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
if (!mod)
|
|
101
|
+
return null;
|
|
102
|
+
// Prefer the OS keyring (KeytarCredentialStore); fall back to a 0600 file.
|
|
103
|
+
let store;
|
|
104
|
+
try {
|
|
105
|
+
store = new mod.KeytarCredentialStore(clientId);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
store = new mod.FileCredentialStore(join(homedir(), ".capix", "credentials.json"));
|
|
109
|
+
}
|
|
110
|
+
const config = { baseUrl, clientId, scope };
|
|
111
|
+
const broker = new mod.AuthBroker(config, store);
|
|
112
|
+
// If there's no stored refresh token we cannot authenticate headlessly.
|
|
113
|
+
const active = await store.get(clientId, "refresh-token:active").catch(() => null);
|
|
114
|
+
if (!active)
|
|
115
|
+
return null;
|
|
116
|
+
return new BrokerAuthProvider(broker);
|
|
117
|
+
}
|
|
118
|
+
/** Resolve the best available auth provider: broker first, then API key. */
|
|
119
|
+
export async function resolveAuthProvider(opts) {
|
|
120
|
+
const broker = await tryCreateBrokerAuthProvider({ baseUrl: opts?.baseUrl });
|
|
121
|
+
if (broker)
|
|
122
|
+
return broker;
|
|
123
|
+
const key = opts?.apiKey ?? process.env.CAPIX_API_KEY ?? "";
|
|
124
|
+
return new ApiKeyAuthProvider(key);
|
|
125
|
+
}
|
|
126
|
+
export class CapixClient {
|
|
127
|
+
baseUrl;
|
|
128
|
+
auth;
|
|
129
|
+
projectId;
|
|
130
|
+
fetchImpl;
|
|
131
|
+
log;
|
|
132
|
+
constructor(opts) {
|
|
133
|
+
this.baseUrl = opts.baseUrl.replace(/\/$/, "");
|
|
134
|
+
this.auth = opts.authProvider;
|
|
135
|
+
this.projectId = opts.projectId ?? process.env.CAPIX_PROJECT_ID;
|
|
136
|
+
this.fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
137
|
+
this.log = opts.log ?? (() => { });
|
|
138
|
+
}
|
|
139
|
+
isAuthenticated() {
|
|
140
|
+
return this.auth.isAuthenticated();
|
|
141
|
+
}
|
|
142
|
+
getAccount() {
|
|
143
|
+
return this.auth.getAccount();
|
|
144
|
+
}
|
|
145
|
+
getProjectId() {
|
|
146
|
+
return this.projectId;
|
|
147
|
+
}
|
|
148
|
+
// -------------------------------------------------------------------------
|
|
149
|
+
// Core HTTP methods — all canonical /api/v1/* paths.
|
|
150
|
+
// -------------------------------------------------------------------------
|
|
151
|
+
async get(path, params) {
|
|
152
|
+
const url = this.buildUrl(path, params);
|
|
153
|
+
const token = await this.requireToken();
|
|
154
|
+
const res = await this.fetchImpl(url, {
|
|
155
|
+
method: "GET",
|
|
156
|
+
headers: this.headers(token),
|
|
157
|
+
});
|
|
158
|
+
return this.parse(res, "GET", path);
|
|
159
|
+
}
|
|
160
|
+
async post(path, body, opts) {
|
|
161
|
+
const url = this.buildUrl(path);
|
|
162
|
+
const token = await this.requireToken();
|
|
163
|
+
const headers = this.headers(token);
|
|
164
|
+
if (opts?.idempotent) {
|
|
165
|
+
headers["Idempotency-Key"] = this.idempotencyKey(path, body);
|
|
166
|
+
}
|
|
167
|
+
if (opts?.approvalToken) {
|
|
168
|
+
headers["X-Capix-Approval-Token"] = opts.approvalToken;
|
|
169
|
+
}
|
|
170
|
+
const res = await this.fetchImpl(url, {
|
|
171
|
+
method: "POST",
|
|
172
|
+
headers,
|
|
173
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
174
|
+
});
|
|
175
|
+
return this.parse(res, "POST", path);
|
|
176
|
+
}
|
|
177
|
+
async delete(path) {
|
|
178
|
+
const url = this.buildUrl(path);
|
|
179
|
+
const token = await this.requireToken();
|
|
180
|
+
const headers = this.headers(token);
|
|
181
|
+
headers["Idempotency-Key"] = this.idempotencyKey(path);
|
|
182
|
+
const res = await this.fetchImpl(url, { method: "DELETE", headers });
|
|
183
|
+
return this.parse(res, "DELETE", path);
|
|
184
|
+
}
|
|
185
|
+
// -------------------------------------------------------------------------
|
|
186
|
+
// Internal helpers
|
|
187
|
+
// -------------------------------------------------------------------------
|
|
188
|
+
buildUrl(path, params) {
|
|
189
|
+
const url = new URL(this.baseUrl + path);
|
|
190
|
+
if (params) {
|
|
191
|
+
for (const [k, v] of Object.entries(params)) {
|
|
192
|
+
if (v === undefined || v === null)
|
|
193
|
+
continue;
|
|
194
|
+
if (Array.isArray(v)) {
|
|
195
|
+
for (const item of v)
|
|
196
|
+
url.searchParams.append(k, String(item));
|
|
197
|
+
}
|
|
198
|
+
else if (typeof v === "object") {
|
|
199
|
+
url.searchParams.set(k, JSON.stringify(v));
|
|
200
|
+
}
|
|
201
|
+
else if (typeof v === "boolean") {
|
|
202
|
+
url.searchParams.set(k, v ? "true" : "false");
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
url.searchParams.set(k, String(v));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return url.toString();
|
|
210
|
+
}
|
|
211
|
+
headers(token) {
|
|
212
|
+
const h = {
|
|
213
|
+
"Content-Type": "application/json",
|
|
214
|
+
Accept: "application/json",
|
|
215
|
+
};
|
|
216
|
+
if (token)
|
|
217
|
+
h.Authorization = `Bearer ${token}`;
|
|
218
|
+
if (this.projectId)
|
|
219
|
+
h["X-Capix-Project"] = this.projectId;
|
|
220
|
+
return h;
|
|
221
|
+
}
|
|
222
|
+
async requireToken() {
|
|
223
|
+
const token = await this.auth.getToken();
|
|
224
|
+
if (!token) {
|
|
225
|
+
const problem = {
|
|
226
|
+
type: "about:blank",
|
|
227
|
+
title: "Not authenticated",
|
|
228
|
+
status: 401,
|
|
229
|
+
detail: "No Capix credentials available. Run `capix-mcp login` to authenticate via OAuth, or set CAPIX_API_KEY.",
|
|
230
|
+
capixCode: "not_authenticated",
|
|
231
|
+
retryClass: "none",
|
|
232
|
+
};
|
|
233
|
+
throw new CapixApiError(problem);
|
|
234
|
+
}
|
|
235
|
+
return token;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Derive a stable idempotency key from the request path + body hash + a
|
|
239
|
+
* fresh nonce. The nonce ensures that the *caller's* retries (same args)
|
|
240
|
+
* collapse while distinct invocations get distinct keys.
|
|
241
|
+
*/
|
|
242
|
+
idempotencyKey(path, body) {
|
|
243
|
+
const nonce = randomUUID();
|
|
244
|
+
const bodyHash = body ? createHash("sha256").update(JSON.stringify(body)).digest("hex").slice(0, 16) : "0";
|
|
245
|
+
const pathHash = createHash("sha256").update(path).digest("hex").slice(0, 16);
|
|
246
|
+
return `capix-${pathHash}-${bodyHash}-${nonce}`;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Parse a fetch Response. Non-2xx responses are decoded as problem+json
|
|
250
|
+
* (RFC 7807) and thrown as CapixApiError. Empty 204 responses yield null.
|
|
251
|
+
*/
|
|
252
|
+
async parse(res, method, path) {
|
|
253
|
+
if (res.status === 204)
|
|
254
|
+
return null;
|
|
255
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
256
|
+
if (!res.ok) {
|
|
257
|
+
let problem;
|
|
258
|
+
if (contentType.includes("application/problem+json") || contentType.includes("application/json")) {
|
|
259
|
+
try {
|
|
260
|
+
problem = (await res.json());
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
problem = this.fallbackProblem(res, method, path);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
problem = this.fallbackProblem(res, method, path);
|
|
268
|
+
}
|
|
269
|
+
if (!problem.capixCode)
|
|
270
|
+
problem.capixCode = "http_error";
|
|
271
|
+
if (!problem.status)
|
|
272
|
+
problem.status = res.status;
|
|
273
|
+
this.log(`${method} ${path} → ${res.status} (${problem.capixCode})`);
|
|
274
|
+
throw new CapixApiError(problem);
|
|
275
|
+
}
|
|
276
|
+
if (contentType.includes("application/json")) {
|
|
277
|
+
return (await res.json());
|
|
278
|
+
}
|
|
279
|
+
// Fallback: treat as text.
|
|
280
|
+
const text = await res.text();
|
|
281
|
+
return (text || null);
|
|
282
|
+
}
|
|
283
|
+
fallbackProblem(res, method, path) {
|
|
284
|
+
return {
|
|
285
|
+
type: "about:blank",
|
|
286
|
+
title: `${method} ${path} failed`,
|
|
287
|
+
status: res.status,
|
|
288
|
+
detail: `Capix API returned ${res.status} ${res.statusText} for ${method} ${path}`,
|
|
289
|
+
capixCode: res.status >= 500 ? "upstream_error" : "http_error",
|
|
290
|
+
retryClass: res.status >= 500 ? "retry-after" : "none",
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// ===========================================================================
|
|
295
|
+
// Convenience factory
|
|
296
|
+
// ===========================================================================
|
|
297
|
+
/** Build a CapixClient from environment defaults (broker → API key fallback). */
|
|
298
|
+
export async function createClient(opts) {
|
|
299
|
+
const baseUrl = opts?.baseUrl ?? process.env.CAPIX_BASE_URL ?? DEFAULT_CAPIX_BASE_URL;
|
|
300
|
+
const authProvider = await resolveAuthProvider({ baseUrl, apiKey: opts?.apiKey });
|
|
301
|
+
return new CapixClient({
|
|
302
|
+
baseUrl,
|
|
303
|
+
authProvider,
|
|
304
|
+
projectId: opts?.projectId,
|
|
305
|
+
log: opts?.log,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|