@trusty-squire/mcp 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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/dist/api-client.d.ts +130 -0
  4. package/dist/api-client.d.ts.map +1 -0
  5. package/dist/api-client.js +156 -0
  6. package/dist/api-client.js.map +1 -0
  7. package/dist/install/agents.d.ts +16 -0
  8. package/dist/install/agents.d.ts.map +1 -0
  9. package/dist/install/agents.js +171 -0
  10. package/dist/install/agents.js.map +1 -0
  11. package/dist/install/cli.d.ts +24 -0
  12. package/dist/install/cli.d.ts.map +1 -0
  13. package/dist/install/cli.js +277 -0
  14. package/dist/install/cli.js.map +1 -0
  15. package/dist/server.d.ts +4 -0
  16. package/dist/server.d.ts.map +1 -0
  17. package/dist/server.js +100 -0
  18. package/dist/server.js.map +1 -0
  19. package/dist/session.d.ts +25 -0
  20. package/dist/session.d.ts.map +1 -0
  21. package/dist/session.js +112 -0
  22. package/dist/session.js.map +1 -0
  23. package/dist/tools/cancel.d.ts +12 -0
  24. package/dist/tools/cancel.d.ts.map +1 -0
  25. package/dist/tools/cancel.js +34 -0
  26. package/dist/tools/cancel.js.map +1 -0
  27. package/dist/tools/get-credential.d.ts +15 -0
  28. package/dist/tools/get-credential.d.ts.map +1 -0
  29. package/dist/tools/get-credential.js +44 -0
  30. package/dist/tools/get-credential.js.map +1 -0
  31. package/dist/tools/get-usage.d.ts +6 -0
  32. package/dist/tools/get-usage.d.ts.map +1 -0
  33. package/dist/tools/get-usage.js +24 -0
  34. package/dist/tools/get-usage.js.map +1 -0
  35. package/dist/tools/index.d.ts +23 -0
  36. package/dist/tools/index.d.ts.map +1 -0
  37. package/dist/tools/index.js +48 -0
  38. package/dist/tools/index.js.map +1 -0
  39. package/dist/tools/list-services.d.ts +15 -0
  40. package/dist/tools/list-services.d.ts.map +1 -0
  41. package/dist/tools/list-services.js +55 -0
  42. package/dist/tools/list-services.js.map +1 -0
  43. package/dist/tools/list-subscriptions.d.ts +6 -0
  44. package/dist/tools/list-subscriptions.d.ts.map +1 -0
  45. package/dist/tools/list-subscriptions.js +25 -0
  46. package/dist/tools/list-subscriptions.js.map +1 -0
  47. package/dist/tools/provision-any.d.ts +120 -0
  48. package/dist/tools/provision-any.d.ts.map +1 -0
  49. package/dist/tools/provision-any.js +243 -0
  50. package/dist/tools/provision-any.js.map +1 -0
  51. package/dist/tools/provision.d.ts +30 -0
  52. package/dist/tools/provision.d.ts.map +1 -0
  53. package/dist/tools/provision.js +108 -0
  54. package/dist/tools/provision.js.map +1 -0
  55. package/dist/tools/rotate-credential.d.ts +12 -0
  56. package/dist/tools/rotate-credential.d.ts.map +1 -0
  57. package/dist/tools/rotate-credential.js +43 -0
  58. package/dist/tools/rotate-credential.js.map +1 -0
  59. package/dist/tools/wait-for-approval.d.ts +28 -0
  60. package/dist/tools/wait-for-approval.d.ts.map +1 -0
  61. package/dist/tools/wait-for-approval.js +82 -0
  62. package/dist/tools/wait-for-approval.js.map +1 -0
  63. package/package.json +43 -0
@@ -0,0 +1,277 @@
1
+ #!/usr/bin/env node
2
+ // Install / pair / logout CLI.
3
+ //
4
+ // Tier 0 install (default) — friction-free:
5
+ // npx @trusty-squire/mcp install --target=claude-code
6
+ // → issues an anonymous machine token, writes MCP config, done.
7
+ //
8
+ // Tier 1+ pair (opt-in, on quota hit or user request):
9
+ // npx @trusty-squire/mcp pair
10
+ // → opens browser, pairs machine, upgrades session to a real account.
11
+ //
12
+ // Logout:
13
+ // npx @trusty-squire/mcp logout
14
+ //
15
+ // Flags:
16
+ // --target=<agent> skip auto-detection
17
+ // --api-base=<url> override the API base URL
18
+ // --pair run pairing as part of install (Tier 1 from minute 1)
19
+ import process from "node:process";
20
+ import { pairInitiate, pairPoll, issueMachineToken } from "../api-client.js";
21
+ import { openSessionStorage } from "../session.js";
22
+ import { AGENTS, detectInstalledAgents } from "./agents.js";
23
+ import { detectAsn } from "@trusty-squire/universal-bot";
24
+ const DEFAULT_API_BASE = process.env.TRUSTY_SQUIRE_API_BASE ?? "https://trusty-squire-api.fly.dev";
25
+ function parseArgs(argv) {
26
+ const positional = argv.filter((a) => !a.startsWith("--"));
27
+ const command = positional[0] ?? "install";
28
+ let target;
29
+ let apiBase = DEFAULT_API_BASE;
30
+ let withPair = false;
31
+ for (const arg of argv) {
32
+ if (arg.startsWith("--target=")) {
33
+ const t = arg.slice("--target=".length);
34
+ if (isAgentTarget(t))
35
+ target = t;
36
+ }
37
+ else if (arg.startsWith("--api-base=")) {
38
+ apiBase = arg.slice("--api-base=".length);
39
+ }
40
+ else if (arg === "--pair") {
41
+ withPair = true;
42
+ }
43
+ }
44
+ return target !== undefined
45
+ ? { command, target, apiBase, withPair }
46
+ : { command, apiBase, withPair };
47
+ }
48
+ function isAgentTarget(s) {
49
+ return s === "claude-code" || s === "cursor" || s === "goose" || s === "cline" || s === "continue";
50
+ }
51
+ async function main() {
52
+ const args = parseArgs(process.argv.slice(2));
53
+ switch (args.command) {
54
+ case "install":
55
+ await install(args);
56
+ return;
57
+ case "pair":
58
+ await pair(args);
59
+ return;
60
+ case "logout":
61
+ await logout();
62
+ return;
63
+ case "help":
64
+ printHelp();
65
+ return;
66
+ default:
67
+ console.error(`unknown command: ${args.command}`);
68
+ printHelp();
69
+ process.exit(64);
70
+ }
71
+ }
72
+ async function install(args) {
73
+ const target = await resolveTarget(args.target);
74
+ const agent = AGENTS[target];
75
+ // ── Detect egress class ───────────────────────────────────
76
+ // We do this before issuing the machine token so the asn class can
77
+ // be sent in the install payload (lets the API pre-correlate captcha
78
+ // failures with network class for analytics). Best-effort — a network
79
+ // failure here just means "unknown" gets sent.
80
+ const asn = await detectAsn();
81
+ // ── Tier 0: get a machine token (zero clicks) ─────────────
82
+ console.warn(`Setting up Trusty Squire on this machine…`);
83
+ const machine = await issueMachineToken(args.apiBase, fetch, asn ?? undefined);
84
+ console.warn(`✓ Got ${machine.quota_limit} free signups. No account needed yet.`);
85
+ // ── Warn datacenter users explicitly ──────────────────────
86
+ // The whole captcha-bypass story depends on a residential egress IP.
87
+ // Datacenter ASNs (Hetzner, AWS, Codespaces) get auto-rejected by
88
+ // reCAPTCHA v2 regardless of fingerprint quality. We don't try to
89
+ // hide this — better to set expectations now than have the user
90
+ // file a "Postmark signup doesn't work" bug later.
91
+ if (asn !== null) {
92
+ printAsnWarning(asn);
93
+ }
94
+ const storage = await openSessionStorage();
95
+ const baseSession = {
96
+ api_base_url: args.apiBase,
97
+ saved_at: new Date().toISOString(),
98
+ machine_token: machine.machine_token,
99
+ };
100
+ // ── Optional Tier 1: pair if --pair was passed ────────────
101
+ let finalSession = baseSession;
102
+ if (args.withPair) {
103
+ const upgraded = await runPair(args.apiBase, target, baseSession);
104
+ if (upgraded === null) {
105
+ console.warn("Pairing didn't complete — keeping Tier 0 session. Run `squire-mcp pair` later to upgrade.");
106
+ }
107
+ else {
108
+ finalSession = upgraded;
109
+ }
110
+ }
111
+ await storage.write(finalSession);
112
+ console.warn(`✓ Session saved (${storage.backendName()}).`);
113
+ // ── Write the MCP config into the host agent ──────────────
114
+ //
115
+ // Env vars passed to the MCP child:
116
+ // - TRUSTY_SQUIRE_AGENT_IDENTITY: which host agent we're running under
117
+ // - UNIVERSAL_BOT_PREFER_CHEAP=true: cheap-mode is the right default
118
+ // for free Tier-0 signups; the proxy enforces this server-side
119
+ // anyway, but setting it here means users who run the bot CLI
120
+ // directly (outside MCP) also get the cheap path by default.
121
+ //
122
+ // The machine token itself is NOT in the env — the MCP server reads it
123
+ // from session storage (keychain / file), which keeps it out of any
124
+ // child-process listing or shell history.
125
+ await agent.writeConfig({
126
+ command: "npx",
127
+ args: ["-y", "@trusty-squire/mcp"],
128
+ env: {
129
+ TRUSTY_SQUIRE_AGENT_IDENTITY: target,
130
+ UNIVERSAL_BOT_PREFER_CHEAP: "true",
131
+ },
132
+ });
133
+ console.warn(`✓ Wrote ${agent.display_name} MCP config at ${agent.config_path()}.`);
134
+ console.warn(``);
135
+ console.warn(`You're done. Restart ${agent.display_name} to pick up the new tools.`);
136
+ console.warn(``);
137
+ console.warn(`Free signups available: ${machine.quota_limit - machine.quota_used}. ` +
138
+ `When you hit the limit, run \`npx @trusty-squire/mcp pair\` to upgrade.`);
139
+ }
140
+ async function pair(args) {
141
+ const storage = await openSessionStorage();
142
+ const existing = (await storage.read()) ?? {
143
+ api_base_url: args.apiBase,
144
+ saved_at: new Date().toISOString(),
145
+ };
146
+ const target = await resolveTarget(args.target);
147
+ const upgraded = await runPair(args.apiBase, target, existing);
148
+ if (upgraded === null) {
149
+ console.error("Pairing failed or expired. Try again with `npx @trusty-squire/mcp pair`.");
150
+ process.exit(1);
151
+ }
152
+ await storage.write(upgraded);
153
+ console.warn(`✓ Paired. You can now use vault + paid-service provisioning.`);
154
+ }
155
+ // Runs the browser-based pair flow. Returns an upgraded SessionData on
156
+ // success, null on timeout/expiry. Preserves any existing machine_token
157
+ // so quota tracking continues to work post-pair.
158
+ async function runPair(apiBase, target, existing) {
159
+ console.warn(`Pairing this machine with Trusty Squire…`);
160
+ const initiate = await pairInitiate(apiBase, target, existing.machine_token ?? null);
161
+ console.warn(`Open this URL in your browser to confirm:`);
162
+ console.warn(` ${initiate.pair_url}`);
163
+ try {
164
+ const openMod = await import("open");
165
+ await openMod.default(initiate.pair_url);
166
+ }
167
+ catch {
168
+ // ignore — user copies the URL
169
+ }
170
+ const claim = await pollForClaim(apiBase, initiate.pair_token);
171
+ if (claim === null)
172
+ return null;
173
+ return {
174
+ ...existing,
175
+ api_base_url: apiBase,
176
+ saved_at: new Date().toISOString(),
177
+ agent_session_token: claim.token,
178
+ account_id: claim.account_id,
179
+ };
180
+ }
181
+ async function resolveTarget(explicit) {
182
+ if (explicit !== undefined)
183
+ return explicit;
184
+ const detected = await detectInstalledAgents();
185
+ if (detected.length === 1) {
186
+ console.warn(`Detected ${detected[0].display_name}. Configuring squire for it.`);
187
+ return detected[0].target;
188
+ }
189
+ if (detected.length > 1) {
190
+ console.error("Multiple agents detected. Please pass --target=<agent>:");
191
+ for (const a of detected)
192
+ console.error(` --target=${a.target} (${a.display_name})`);
193
+ process.exit(2);
194
+ }
195
+ console.error("No coding agents auto-detected. Pass --target= explicitly:");
196
+ for (const a of Object.values(AGENTS)) {
197
+ console.error(` --target=${a.target} (${a.display_name})`);
198
+ }
199
+ process.exit(2);
200
+ }
201
+ async function logout() {
202
+ const storage = await openSessionStorage();
203
+ await storage.clear();
204
+ console.warn(`✓ Cleared local session (${storage.backendName()}).`);
205
+ }
206
+ function printHelp() {
207
+ console.warn(`squire-mcp — install Trusty Squire MCP into a coding agent`);
208
+ console.warn(``);
209
+ console.warn(`Commands:`);
210
+ console.warn(` install [--target=<agent>] [--api-base=<url>] [--pair]`);
211
+ console.warn(` pair [--target=<agent>] [--api-base=<url>]`);
212
+ console.warn(` logout`);
213
+ console.warn(``);
214
+ console.warn(`Agents: ${Object.keys(AGENTS).join(", ")}`);
215
+ console.warn(``);
216
+ console.warn(`The default \`install\` runs Tier 0: zero clicks, issues a machine token`);
217
+ console.warn(`good for a handful of free signups. Run \`pair\` later to upgrade.`);
218
+ console.warn(`Use \`install --pair\` to do both at once.`);
219
+ }
220
+ async function pollForClaim(apiBase, pairToken, intervalMsOrOpts = {}, timeoutMsArg) {
221
+ const opts = typeof intervalMsOrOpts === "number"
222
+ ? { intervalMs: intervalMsOrOpts, timeoutMs: timeoutMsArg }
223
+ : intervalMsOrOpts;
224
+ const intervalMs = opts.intervalMs ?? 1500;
225
+ const timeoutMs = opts.timeoutMs ?? 5 * 60 * 1000;
226
+ const deadline = Date.now() + timeoutMs;
227
+ while (Date.now() < deadline) {
228
+ const status = await pairPoll(apiBase, pairToken);
229
+ if (status.status === "claimed" && status.agent_session_token !== undefined) {
230
+ return {
231
+ token: status.agent_session_token,
232
+ account_id: status.account_id ?? "",
233
+ };
234
+ }
235
+ if (status.status === "expired")
236
+ return null;
237
+ await new Promise((r) => setTimeout(r, intervalMs));
238
+ }
239
+ return null;
240
+ }
241
+ // Print a class-appropriate message about the network we detected.
242
+ // Datacenter gets a clear warning + link; residential gets a brief
243
+ // confirmation; unknown gets a heads-up. All to stderr.
244
+ function printAsnWarning(asn) {
245
+ const orgDisplay = asn.org ?? "(unknown ASN)";
246
+ switch (asn.class) {
247
+ case "datacenter":
248
+ console.warn(``);
249
+ console.warn(`⚠ Detected network: ${orgDisplay}`);
250
+ console.warn(` This looks like a datacenter / cloud network (Codespaces, AWS,`);
251
+ console.warn(` Hetzner, etc.). Some signups — especially those gated by`);
252
+ console.warn(` reCAPTCHA v2 — are likely to be blocked because anti-bot`);
253
+ console.warn(` scoring weighs network reputation heavily.`);
254
+ console.warn(``);
255
+ console.warn(` For best results: run Trusty Squire from a laptop/desktop`);
256
+ console.warn(` on a home or office network. Cloud dev environments can`);
257
+ console.warn(` still provision services that don't gate signup with`);
258
+ console.warn(` reCAPTCHA (Resend, IPInfo, etc.), but Postmark/MailerSend`);
259
+ console.warn(` and similar will likely fail.`);
260
+ console.warn(``);
261
+ return;
262
+ case "residential":
263
+ console.warn(`✓ Detected network: ${orgDisplay} (residential — captchas should pass cleanly).`);
264
+ return;
265
+ case "unknown":
266
+ console.warn(`ℹ Detected network: ${orgDisplay} (couldn't classify — proceed and we'll see).`);
267
+ return;
268
+ }
269
+ }
270
+ if (import.meta.url === `file://${process.argv[1]}`) {
271
+ main().catch((err) => {
272
+ console.error(err instanceof Error ? err.message : String(err));
273
+ process.exit(1);
274
+ });
275
+ }
276
+ export { install, pair, logout, parseArgs, pollForClaim, printAsnWarning };
277
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/install/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { ApiClient } from "./api-client.js";
3
+ export declare function buildServer(api: ApiClient | null): Promise<Server>;
4
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAMnE,OAAO,EAAE,SAAS,EAAuB,MAAM,iBAAiB,CAAC;AASjE,wBAAsB,WAAW,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAwDxE"}
package/dist/server.js ADDED
@@ -0,0 +1,100 @@
1
+ // MCP server entry point. Reads the session from keytar/file, sets up
2
+ // an ApiClient against the configured API base URL, and exposes the
3
+ // registered tools over stdio.
4
+ //
5
+ // The server is what a coding agent (Claude Code, Cursor, etc.)
6
+ // launches as a child process via the MCP config it found in
7
+ // `~/.claude/mcp.json` or equivalent.
8
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
9
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
10
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
11
+ import { ApiClient, MissingSessionError } from "./api-client.js";
12
+ import { TOOLS, findTool } from "./tools/index.js";
13
+ import { openSessionStorage } from "./session.js";
14
+ const SERVER_NAME = "trusty-squire";
15
+ const SERVER_VERSION = "0.1.0";
16
+ const DEFAULT_REGISTRY_BASE = process.env.ADAPTER_REGISTRY_URL ?? "https://registry.trustysquire.ai";
17
+ export async function buildServer(api) {
18
+ const server = new Server({ name: SERVER_NAME, version: SERVER_VERSION }, { capabilities: { tools: {} } });
19
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
20
+ tools: TOOLS.map((t) => ({
21
+ name: t.name,
22
+ description: t.description,
23
+ inputSchema: t.jsonInputSchema,
24
+ })),
25
+ }));
26
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
27
+ const tool = findTool(req.params.name);
28
+ if (tool === null) {
29
+ return errorContent(`unknown tool '${req.params.name}'`);
30
+ }
31
+ const parsed = tool.inputSchema.safeParse(req.params.arguments ?? {});
32
+ if (!parsed.success) {
33
+ return errorContent(`invalid arguments: ${parsed.error.issues.map((i) => i.message).join("; ")}`);
34
+ }
35
+ try {
36
+ // provision_any_service doesn't need API client (anonymous mode)
37
+ if (tool.name === "provision_any_service") {
38
+ const result = await tool.handler(parsed.data, null);
39
+ return {
40
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
41
+ };
42
+ }
43
+ // Other tools require an authenticated (Tier 1+) agent_session_token.
44
+ // provision_any_service is the Tier 0 escape hatch and handles its own
45
+ // session check above, so users who only need universal signup don't
46
+ // need to pair at all.
47
+ if (api === null) {
48
+ return errorContent(`This tool requires pairing (Tier 1+). For local dev: ` +
49
+ `\`node /home/chode/trusty-squire/apps/mcp/dist/install/cli.js install --target=goose --pair\`. ` +
50
+ `In production: \`npx @trusty-squire/mcp install --target=<agent> --pair\`. ` +
51
+ `If you just want to sign up for a free service, call \`provision_any_service\` instead — ` +
52
+ `it works with a Tier 0 machine_token and doesn't need pairing.`);
53
+ }
54
+ const result = await tool.handler(parsed.data, api);
55
+ return {
56
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
57
+ };
58
+ }
59
+ catch (err) {
60
+ return errorContent(err instanceof Error ? err.message : String(err));
61
+ }
62
+ });
63
+ return server;
64
+ }
65
+ function errorContent(message) {
66
+ return {
67
+ isError: true,
68
+ content: [{ type: "text", text: message }],
69
+ };
70
+ }
71
+ async function main() {
72
+ const storage = await openSessionStorage();
73
+ const session = await storage.read();
74
+ // Tier-aware ApiClient: only paired (Tier 1+) sessions can call the
75
+ // authenticated API. Tier 0 machine-token-only sessions get a null
76
+ // ApiClient — provision_any_service uses session.machine_token via the
77
+ // InboxClient directly, no agent session required.
78
+ const api = session !== null && session.agent_session_token !== undefined
79
+ ? new ApiClient({
80
+ apiBaseUrl: session.api_base_url,
81
+ registryBaseUrl: DEFAULT_REGISTRY_BASE,
82
+ agentSessionToken: session.agent_session_token,
83
+ agentIdentity: process.env.TRUSTY_SQUIRE_AGENT_IDENTITY ?? "unknown",
84
+ })
85
+ : null;
86
+ const server = await buildServer(api);
87
+ const transport = new StdioServerTransport();
88
+ await server.connect(transport);
89
+ }
90
+ if (import.meta.url === `file://${process.argv[1]}`) {
91
+ main().catch((err) => {
92
+ // stderr goes to the coding agent's MCP log — keep the message
93
+ // useful for debugging without leaking secrets.
94
+ console.error(err instanceof MissingSessionError
95
+ ? err.message
96
+ : `[trusty-squire] startup failed: ${err instanceof Error ? err.message : String(err)}`);
97
+ process.exit(1);
98
+ });
99
+ }
100
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export interface SessionData {
2
+ api_base_url: string;
3
+ saved_at: string;
4
+ machine_token?: string;
5
+ agent_session_token?: string;
6
+ account_id?: string;
7
+ }
8
+ export interface SessionStorage {
9
+ read(): Promise<SessionData | null>;
10
+ write(data: SessionData): Promise<void>;
11
+ clear(): Promise<void>;
12
+ backendName(): string;
13
+ }
14
+ export declare function openSessionStorage(options?: {
15
+ preferFile?: boolean;
16
+ }): Promise<SessionStorage>;
17
+ export declare class FileStorage implements SessionStorage {
18
+ private readonly filePath;
19
+ constructor(filePath?: string);
20
+ read(): Promise<SessionData | null>;
21
+ write(data: SessionData): Promise<void>;
22
+ clear(): Promise<void>;
23
+ backendName(): string;
24
+ }
25
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IAEjB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACpC,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,WAAW,IAAI,MAAM,CAAC;CACvB;AAKD,wBAAsB,kBAAkB,CACtC,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACrC,OAAO,CAAC,cAAc,CAAC,CAMzB;AAiED,qBAAa,WAAY,YAAW,cAAc;IAEpC,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,GAAE,MAAsB;IAEvD,IAAI,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAUnC,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,WAAW,IAAI,MAAM;CAGtB"}
@@ -0,0 +1,112 @@
1
+ // MCP session storage.
2
+ //
3
+ // Prefer keytar (OS keychain) when available. Fall back to a 0600
4
+ // file at $XDG_CONFIG_HOME/trusty-squire/session.json (or
5
+ // ~/.config/trusty-squire/session.json) so the install works on
6
+ // minimal Linux containers and CI machines without libsecret.
7
+ import { promises as fs } from "node:fs";
8
+ import os from "node:os";
9
+ import path from "node:path";
10
+ const KEYTAR_SERVICE = "trusty-squire";
11
+ const KEYTAR_ACCOUNT = "session";
12
+ const FALLBACK_DIR = path.join(process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config"), "trusty-squire");
13
+ const FALLBACK_FILE = path.join(FALLBACK_DIR, "session.json");
14
+ // Tries keytar first. Falls back to the file backend if keytar isn't
15
+ // installed or its native binding can't load. The fallback is also the
16
+ // chosen backend for CI / tests.
17
+ export async function openSessionStorage(options = {}) {
18
+ if (options.preferFile !== true) {
19
+ const keytar = await tryLoadKeytar();
20
+ if (keytar !== null)
21
+ return new KeytarStorage(keytar);
22
+ }
23
+ return new FileStorage();
24
+ }
25
+ async function tryLoadKeytar() {
26
+ // Two things can fail here:
27
+ // 1. The module itself can't load (no native binding for this Node
28
+ // version, or the package isn't installed).
29
+ // 2. The module loads but the OS keychain isn't available (no
30
+ // D-Bus secrets daemon on a headless Linux box, locked Keychain
31
+ // on macOS, etc.) — load succeeds, the first call throws.
32
+ // Probe with a write to a throwaway entry: getPassword() can succeed
33
+ // (returning null) on a half-broken D-Bus where the secrets service
34
+ // is present but no collection is unlocked — only setPassword
35
+ // surfaces that. We delete the probe right after so we don't pollute
36
+ // the keychain.
37
+ try {
38
+ const mod = await import("keytar");
39
+ const probeAccount = `${KEYTAR_ACCOUNT}__probe`;
40
+ await mod.default.setPassword(KEYTAR_SERVICE, probeAccount, "1");
41
+ await mod.default.deletePassword(KEYTAR_SERVICE, probeAccount);
42
+ return {
43
+ getPassword: mod.default.getPassword,
44
+ setPassword: mod.default.setPassword,
45
+ deletePassword: mod.default.deletePassword,
46
+ };
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ class KeytarStorage {
53
+ kt;
54
+ constructor(kt) {
55
+ this.kt = kt;
56
+ }
57
+ async read() {
58
+ const raw = await this.kt.getPassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
59
+ if (raw === null)
60
+ return null;
61
+ try {
62
+ return JSON.parse(raw);
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ async write(data) {
69
+ await this.kt.setPassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT, JSON.stringify(data));
70
+ }
71
+ async clear() {
72
+ await this.kt.deletePassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
73
+ }
74
+ backendName() {
75
+ return "keytar";
76
+ }
77
+ }
78
+ export class FileStorage {
79
+ filePath;
80
+ // Allow tests to override the default file path.
81
+ constructor(filePath = FALLBACK_FILE) {
82
+ this.filePath = filePath;
83
+ }
84
+ async read() {
85
+ try {
86
+ const raw = await fs.readFile(this.filePath, "utf8");
87
+ return JSON.parse(raw);
88
+ }
89
+ catch (err) {
90
+ if (err.code === "ENOENT")
91
+ return null;
92
+ throw err;
93
+ }
94
+ }
95
+ async write(data) {
96
+ await fs.mkdir(path.dirname(this.filePath), { recursive: true, mode: 0o700 });
97
+ await fs.writeFile(this.filePath, JSON.stringify(data, null, 2), { mode: 0o600 });
98
+ }
99
+ async clear() {
100
+ try {
101
+ await fs.unlink(this.filePath);
102
+ }
103
+ catch (err) {
104
+ if (err.code !== "ENOENT")
105
+ throw err;
106
+ }
107
+ }
108
+ backendName() {
109
+ return "file";
110
+ }
111
+ }
112
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { z } from "zod";
2
+ import { type Tool } from "./index.js";
3
+ declare const inputSchema: z.ZodObject<{
4
+ subscription_id: z.ZodString;
5
+ }, "strip", z.ZodTypeAny, {
6
+ subscription_id: string;
7
+ }, {
8
+ subscription_id: string;
9
+ }>;
10
+ export declare const cancelTool: Tool<z.infer<typeof inputSchema>>;
11
+ export {};
12
+ //# sourceMappingURL=cancel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancel.d.ts","sourceRoot":"","sources":["../../src/tools/cancel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAgB,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAErD,QAAA,MAAM,WAAW;;;;;;EAEf,CAAC;AAiBH,eAAO,MAAM,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAaxD,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ import { assertPaired } from "./index.js";
3
+ const inputSchema = z.object({
4
+ subscription_id: z.string().min(1),
5
+ });
6
+ const DESCRIPTION = `Cancel one of the user's subscriptions. The user has pre-authorized
7
+ cancellation in their spending policy (default confidence: low) so
8
+ this completes without an approval prompt.
9
+
10
+ WHEN TO CALL THIS TOOL:
11
+ - The user explicitly asks to cancel a service
12
+ - A migration / consolidation makes a subscription redundant
13
+
14
+ BEHAVIOR:
15
+ - Initiates the adapter's cancel flow asynchronously
16
+ - Returns 202 immediately; poll list_subscriptions to confirm
17
+ - Idempotent on subscription_id
18
+ - In v0 the cancel flow is wired but the runtime's flow selector
19
+ doesn't pick the cancel flow yet — see chunk 11+ roadmap`;
20
+ export const cancelTool = {
21
+ name: "cancel",
22
+ description: DESCRIPTION,
23
+ inputSchema,
24
+ jsonInputSchema: {
25
+ type: "object",
26
+ required: ["subscription_id"],
27
+ properties: { subscription_id: { type: "string" } },
28
+ },
29
+ async handler(args, api) {
30
+ assertPaired(api);
31
+ return api.cancelSubscription(args.subscription_id);
32
+ },
33
+ };
34
+ //# sourceMappingURL=cancel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancel.js","sourceRoot":"","sources":["../../src/tools/cancel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAa,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACnC,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG;;;;;;;;;;;;;2DAauC,CAAC;AAE5D,MAAM,CAAC,MAAM,UAAU,GAAsC;IAC3D,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,WAAW;IACxB,WAAW;IACX,eAAe,EAAE;QACf,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,iBAAiB,CAAC;QAC7B,UAAU,EAAE,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;KACpD;IACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,YAAY,CAAC,GAAG,CAAC,CAAC;QAClB,OAAO,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACtD,CAAC;CACF,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ import { type Tool } from "./index.js";
3
+ declare const inputSchema: z.ZodObject<{
4
+ reference: z.ZodString;
5
+ purpose: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ reference: string;
8
+ purpose: string;
9
+ }, {
10
+ reference: string;
11
+ purpose: string;
12
+ }>;
13
+ export declare const getCredentialTool: Tool<z.infer<typeof inputSchema>>;
14
+ export {};
15
+ //# sourceMappingURL=get-credential.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-credential.d.ts","sourceRoot":"","sources":["../../src/tools/get-credential.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAgB,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAErD,QAAA,MAAM,WAAW;;;;;;;;;EAGf,CAAC;AAkBH,eAAO,MAAM,iBAAiB,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAqB/D,CAAC"}