authflow-cli 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 (57) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +260 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +33 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/connect.d.ts +7 -0
  7. package/dist/commands/connect.js +84 -0
  8. package/dist/commands/connect.js.map +1 -0
  9. package/dist/commands/doctor.d.ts +2 -0
  10. package/dist/commands/doctor.js +16 -0
  11. package/dist/commands/doctor.js.map +1 -0
  12. package/dist/commands/init.d.ts +12 -0
  13. package/dist/commands/init.js +182 -0
  14. package/dist/commands/init.js.map +1 -0
  15. package/dist/commands/mcp.d.ts +2 -0
  16. package/dist/commands/mcp.js +24 -0
  17. package/dist/commands/mcp.js.map +1 -0
  18. package/dist/commands/mint-header.d.ts +2 -0
  19. package/dist/commands/mint-header.js +69 -0
  20. package/dist/commands/mint-header.js.map +1 -0
  21. package/dist/commands/probe.d.ts +2 -0
  22. package/dist/commands/probe.js +49 -0
  23. package/dist/commands/probe.js.map +1 -0
  24. package/dist/commands/register.d.ts +2 -0
  25. package/dist/commands/register.js +78 -0
  26. package/dist/commands/register.js.map +1 -0
  27. package/dist/commands/scaffold.d.ts +2 -0
  28. package/dist/commands/scaffold.js +72 -0
  29. package/dist/commands/scaffold.js.map +1 -0
  30. package/dist/commands/set-origin.d.ts +6 -0
  31. package/dist/commands/set-origin.js +38 -0
  32. package/dist/commands/set-origin.js.map +1 -0
  33. package/dist/commands/signup.d.ts +2 -0
  34. package/dist/commands/signup.js +53 -0
  35. package/dist/commands/signup.js.map +1 -0
  36. package/dist/config.d.ts +47 -0
  37. package/dist/config.js +56 -0
  38. package/dist/config.js.map +1 -0
  39. package/dist/constants.d.ts +12 -0
  40. package/dist/constants.js +13 -0
  41. package/dist/constants.js.map +1 -0
  42. package/dist/doctor.d.ts +24 -0
  43. package/dist/doctor.js +230 -0
  44. package/dist/doctor.js.map +1 -0
  45. package/dist/integration.d.ts +44 -0
  46. package/dist/integration.js +247 -0
  47. package/dist/integration.js.map +1 -0
  48. package/dist/mcp/server.d.ts +3 -0
  49. package/dist/mcp/server.js +362 -0
  50. package/dist/mcp/server.js.map +1 -0
  51. package/dist/rail.d.ts +80 -0
  52. package/dist/rail.js +115 -0
  53. package/dist/rail.js.map +1 -0
  54. package/dist/secrets.d.ts +28 -0
  55. package/dist/secrets.js +117 -0
  56. package/dist/secrets.js.map +1 -0
  57. package/package.json +56 -0
@@ -0,0 +1,247 @@
1
+ import { originApiKeyConfigKey, originApiKeyEnvVar } from "./secrets.js";
2
+ /**
3
+ * Framework-specific integration instructions, emitted as structured data rather than prose.
4
+ *
5
+ * The consumer is usually not a human: it is the creator's own coding agent, which already has the
6
+ * codebase open. The rail cannot see their files and should not try to — it supplies the plan, the
7
+ * agent applies it. That split is also what keeps this honest as a public contract: everything here
8
+ * is derived from the receipt and the published spec, never from rail internals.
9
+ */
10
+ export const integrationFrameworks = ["dotnet", "typescript", "python", "proxy"];
11
+ export function isIntegrationFramework(value) {
12
+ return integrationFrameworks.includes(value);
13
+ }
14
+ export function buildIntegrationPlan(framework, receipt) {
15
+ return {
16
+ ...frameworkPlan(framework, receipt),
17
+ metering: meteringAdvice(receipt.metering_mode === "gateway_metered"),
18
+ };
19
+ }
20
+ function frameworkPlan(framework, receipt) {
21
+ const issuer = receipt.issuer ?? "";
22
+ const resource = receipt.resource ?? receipt.gateway_url ?? "";
23
+ const slug = receipt.slug ?? "";
24
+ const configuration = {
25
+ AUTHFLOW_ISSUER: issuer,
26
+ AUTHFLOW_RESOURCE: resource,
27
+ };
28
+ const secrets = {
29
+ key: originApiKeyConfigKey,
30
+ envVar: originApiKeyEnvVar,
31
+ note: "Shown once at registration. Store it in a secret store (dotnet user-secrets locally, Key " +
32
+ "Vault in Azure) — never in a committed config file or a receipt left on disk.",
33
+ };
34
+ const invariants = [
35
+ "Serve MCP at /mcp on the origin. The gateway appends /mcp to the origin base URI, so an " +
36
+ "origin base URI that already ends in /mcp would be called at /mcp/mcp.",
37
+ "Verify X-Authflow-Identity on every request to /mcp and fail closed with HTTP 403 and no " +
38
+ "WWW-Authenticate. Never 401 from the origin: that kicks clients into OAuth against you.",
39
+ "Never return a payment URL as tool output. Credit exhaustion is a plain tool error.",
40
+ "Never cache remaining_credits or infer entitlements. The rail's counter is the only source.",
41
+ "Publish only the gateway URL to clients. The origin hostname is never client-facing.",
42
+ "Every MCP tool must declare title and readOnlyHint/destructiveHint.",
43
+ ];
44
+ const verification = [
45
+ "Unauthenticated POST to the origin's /mcp returns 403 with no WWW-Authenticate.",
46
+ `Run the conformance probe (authflow probe) — it must pass before the resource takes paid traffic.`,
47
+ `Add the gateway URL ${resource} to Claude or Cursor. First connect must 401 from the gateway, not from the origin.`,
48
+ ];
49
+ switch (framework) {
50
+ case "dotnet":
51
+ return {
52
+ framework,
53
+ summary: "ASP.NET Core origin using the Authflow.Origin package, which implements identity-header " +
54
+ "verification and the usage-reporting client from the published spec.",
55
+ configuration,
56
+ secrets,
57
+ steps: [
58
+ {
59
+ title: "Add the package",
60
+ action: "Add the Authflow.Origin NuGet package to the MCP server project.",
61
+ command: "dotnet add package Authflow.Origin",
62
+ },
63
+ {
64
+ title: "Wire the middleware",
65
+ action: "Register Authflow services, warm the key ring at startup, and add the middleware " +
66
+ "before the MCP endpoints are mapped so unsigned requests never reach a tool.",
67
+ file: "Program.cs",
68
+ snippet: [
69
+ "builder.Services.AddAuthflowOrigin(builder.Configuration);",
70
+ "",
71
+ "var app = builder.Build();",
72
+ "",
73
+ "await app.WarmAuthflowOriginKeysAsync();",
74
+ "app.UseAuthflowOrigin();",
75
+ "app.MapMcp(\"/mcp\");",
76
+ ].join("\n"),
77
+ },
78
+ {
79
+ title: "Configure issuer and resource",
80
+ action: "Add the Authflow section to appsettings.json (these are not secrets).",
81
+ file: "appsettings.json",
82
+ snippet: JSON.stringify({ Authflow: { Issuer: issuer, Resource: resource } }, null, 2),
83
+ },
84
+ {
85
+ title: "Store the origin API key",
86
+ action: "Put the origin API key in user-secrets. The CLI can do this for you at registration " +
87
+ "with --write-secrets user-secrets.",
88
+ command: `dotnet user-secrets set "${originApiKeyConfigKey}" "<origin-api-key>"`,
89
+ },
90
+ {
91
+ title: "Read the verified caller",
92
+ action: "In each billable tool, take the caller from the verified identity rather than from " +
93
+ "anything client-supplied.",
94
+ snippet: "var identity = context.RequireAuthflowIdentity(); // identity.Subject, identity.Tier",
95
+ },
96
+ ],
97
+ verification,
98
+ invariants,
99
+ };
100
+ case "typescript":
101
+ return {
102
+ framework,
103
+ summary: "TypeScript/Node origin implementing Origin Protocol v1 in-process. There is no published " +
104
+ "npm middleware yet, so the verification steps are implemented against the spec.",
105
+ configuration,
106
+ secrets,
107
+ steps: [
108
+ {
109
+ title: "Fetch and cache the verification keys",
110
+ action: `At startup, GET ${issuer}${"/.well-known/authflow-origin-keys"} and cache it. Cap the ` +
111
+ "cache at 3600s, refresh once on an unknown kid, and keep the last good document if a " +
112
+ "refresh fails. Reject any document whose issuer is not exactly your configured issuer.",
113
+ },
114
+ {
115
+ title: "Verify the identity header on every /mcp request",
116
+ action: "Parse X-Authflow-Identity as v1;<claims_b64>;<signature_b64>. Verify the Ed25519 " +
117
+ "signature over the ASCII bytes of \"v1;\" + claims_b64. Then check the claims: issuer " +
118
+ "and resource byte-equal to your configuration, iat/exp within 60s leeway, TTL <= 300s, " +
119
+ "and the nonce unseen. Reject with 403 and the exact spec §6.2 body.",
120
+ snippet: [
121
+ "// Node has Ed25519 built in — no dependency needed.",
122
+ "import { verify, createPublicKey } from \"node:crypto\";",
123
+ "",
124
+ "const signingInput = Buffer.from(`v1;${claimsB64}`, \"ascii\");",
125
+ "const ok = verify(null, signingInput, publicKey, signature);",
126
+ ].join("\n"),
127
+ },
128
+ {
129
+ title: "Return the fail-closed 403",
130
+ action: "On any verification failure, return this exact shape. No WWW-Authenticate header.",
131
+ snippet: JSON.stringify({ error: "invalid_origin_identity", error_code: "<spec §6.2 code>" }, null, 2),
132
+ },
133
+ {
134
+ title: "Debit before calling your provider",
135
+ action: `POST ${issuer}${"/origin/v1/usage"} with Authorization: Bearer <origin API key> and an ` +
136
+ "Idempotency-Key header equal to the body's idempotency_key. Do this BEFORE the provider " +
137
+ "call. On 409 insufficient_credits, return a tool error with no payment URL.",
138
+ },
139
+ {
140
+ title: "Compensate on failure",
141
+ action: "If the provider call or artifact persistence fails after a successful debit, POST a " +
142
+ "credit whose compensates field is the debit's idempotency key.",
143
+ },
144
+ ],
145
+ verification,
146
+ invariants,
147
+ };
148
+ case "python":
149
+ return {
150
+ framework,
151
+ summary: "Python origin implementing Origin Protocol v1 in-process. No published package yet, so " +
152
+ "verification is implemented against the spec.",
153
+ configuration,
154
+ secrets,
155
+ steps: [
156
+ {
157
+ title: "Install an Ed25519 implementation",
158
+ action: "Python has no stdlib Ed25519 verifier.",
159
+ command: "pip install cryptography",
160
+ },
161
+ {
162
+ title: "Fetch and cache the verification keys",
163
+ action: `At startup, GET ${issuer}${"/.well-known/authflow-origin-keys"} and cache it (cap 3600s, ` +
164
+ "one forced refresh on unknown kid, keep last good on failure). Reject a document whose " +
165
+ "issuer is not exactly your configured issuer.",
166
+ },
167
+ {
168
+ title: "Verify the identity header on every /mcp request",
169
+ action: "Parse v1;<claims_b64>;<signature_b64>, verify Ed25519 over b\"v1;\" + claims_b64, then " +
170
+ "validate issuer, resource, iat/exp (60s leeway), TTL <= 300s, and nonce replay.",
171
+ snippet: [
172
+ "from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey",
173
+ "",
174
+ "signing_input = b\"v1;\" + claims_b64.encode(\"ascii\")",
175
+ "Ed25519PublicKey.from_public_bytes(x).verify(signature, signing_input)",
176
+ ].join("\n"),
177
+ },
178
+ {
179
+ title: "Return the fail-closed 403",
180
+ action: "On any verification failure return the spec §6.2 body with HTTP 403 and no WWW-Authenticate.",
181
+ },
182
+ {
183
+ title: "Debit before the provider, compensate on failure",
184
+ action: `POST ${issuer}${"/origin/v1/usage"} with a Bearer origin API key and an Idempotency-Key ` +
185
+ "header matching the body. Debit before the provider call; credit with compensates set " +
186
+ "if the user does not get a successful result.",
187
+ },
188
+ ],
189
+ verification,
190
+ invariants,
191
+ };
192
+ case "proxy":
193
+ return {
194
+ framework,
195
+ summary: "Language-agnostic: run the authflow-origin-proxy sidecar in front of the existing MCP " +
196
+ "server. The proxy verifies the identity header and forwards plain headers upstream, so " +
197
+ "the MCP server itself needs no changes.",
198
+ configuration: {
199
+ ...configuration,
200
+ AUTHFLOW_UPSTREAM_BASE_URI: "http://upstream:3000",
201
+ },
202
+ secrets,
203
+ steps: [
204
+ {
205
+ title: "Register the proxy as the origin",
206
+ action: "The proxy is what the gateway talks to, so origin_base_uri must be the proxy's URL, " +
207
+ "not the upstream MCP server's.",
208
+ command: `authflow set-origin --slug ${slug} --origin-url https://your-proxy.example`,
209
+ },
210
+ {
211
+ title: "Generate the compose and env files",
212
+ action: "Scaffold the sidecar configuration from the receipt.",
213
+ command: "authflow scaffold --receipt receipt.json --upstream http://upstream:3000",
214
+ },
215
+ {
216
+ title: "Consume the forwarded identity",
217
+ action: "Upstream receives X-Authflow-User, X-Authflow-Tier, and X-Authflow-Nonce after " +
218
+ "verification. Trust these only because the proxy is the sole ingress — do not expose " +
219
+ "the upstream directly.",
220
+ },
221
+ {
222
+ title: "Set a shared nonce cache before scaling",
223
+ action: "Replay protection is process-local by default, so more than one replica reopens a " +
224
+ "replay window. Set Authflow__NonceCacheRedis before raising replicas above 1.",
225
+ },
226
+ ],
227
+ verification,
228
+ invariants,
229
+ };
230
+ }
231
+ }
232
+ /**
233
+ * Origins that bill exactly one unit per tool call can skip debit/compensate entirely by declaring
234
+ * per-tool costs at registration. It is the largest and subtlest part of the integration, so the
235
+ * plan should say so rather than leaving it to be discovered in §9 of the quickstart.
236
+ */
237
+ export function meteringAdvice(gatewayMetered) {
238
+ return gatewayMetered
239
+ ? "This resource is gateway_metered: the rail debits before forwarding, returns the credit-exhaustion " +
240
+ "tool error itself, and compensates automatically on a transport error or an isError result. " +
241
+ "Do not write any billing code in the origin. Verify the identity header and serve MCP."
242
+ : "This resource is origin_reported: the origin must debit before calling its provider and post a " +
243
+ "compensating credit when the user does not get a successful result. If you bill one unit per " +
244
+ "tool call and do not stream responses, re-registering as gateway_metered removes all of that " +
245
+ "code — it is a registration change, not an origin change.";
246
+ }
247
+ //# sourceMappingURL=integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.js","sourceRoot":"","sources":["../src/integration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createOnboardingServer(): McpServer;
3
+ export declare function runStdioServer(): Promise<void>;
@@ -0,0 +1,362 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import { requireAdminKey, requireIssuer } from "../config.js";
5
+ import { formatDoctorReport, runDoctor } from "../doctor.js";
6
+ import { buildIntegrationPlan, integrationFrameworks, isIntegrationFramework, } from "../integration.js";
7
+ import { describePending, getResource, mintDevHeader, probeConformance, registerResource, rotateOriginKey, setConnectedAccount, setOrigin, signupTenant, startConnect, } from "../rail.js";
8
+ import { secretTargets, writeAdminApiKey, writeOriginApiKey } from "../secrets.js";
9
+ function ok(payload) {
10
+ const text = typeof payload === "string" ? payload : JSON.stringify(payload, null, 2);
11
+ return { content: [{ type: "text", text }] };
12
+ }
13
+ /**
14
+ * Failures come back as tool errors with the rail's own message rather than thrown exceptions:
15
+ * the agent can act on "connected_account_id is required" but not on a stack trace.
16
+ */
17
+ function fail(message) {
18
+ return { content: [{ type: "text", text: message }], isError: true };
19
+ }
20
+ async function attempt(run) {
21
+ try {
22
+ return await run();
23
+ }
24
+ catch (err) {
25
+ return fail(err instanceof Error ? err.message : String(err));
26
+ }
27
+ }
28
+ /** Resolved per call, so a credential that appears after startup is picked up without a restart. */
29
+ function adminAuth(issuer, adminKey) {
30
+ return { issuer: requireIssuer(issuer), adminKey: requireAdminKey(adminKey) };
31
+ }
32
+ /** The receipt plus the one thing an agent actually needs next. */
33
+ function withNextSteps(receipt) {
34
+ const pending = receipt.pending_requirements ?? [];
35
+ return {
36
+ ...receipt,
37
+ next_steps: pending.map((requirement) => describePending(requirement, receipt.slug ?? "")),
38
+ ready_for_traffic: pending.length === 0 && receipt.status === "live",
39
+ };
40
+ }
41
+ const issuerArg = z
42
+ .string()
43
+ .optional()
44
+ .describe("Authflow issuer base URL. Defaults to the AUTHFLOW_ISSUER environment variable.");
45
+ const adminKeyArg = z
46
+ .string()
47
+ .optional()
48
+ .describe("Admin API key. Defaults to the AUTHFLOW_ADMIN_API_KEY environment variable.");
49
+ export function createOnboardingServer() {
50
+ const server = new McpServer({ name: "authflow-onboarding", version: "0.1.0" }, {
51
+ instructions: "Onboard an MCP server onto the Authflow rail. Typical order: authflow_doctor to confirm " +
52
+ "the rail is reachable, authflow_signup if AUTHFLOW_ADMIN_API_KEY is missing, " +
53
+ "authflow_register_resource to create a draft and capture the origin API key, " +
54
+ "authflow_integration_plan to get framework-specific code to apply to the user's " +
55
+ "codebase, authflow_start_stripe_connect for the hosted KYC link, authflow_set_origin once " +
56
+ "the origin is deployed, then authflow_probe before real traffic. Read pending_requirements " +
57
+ "on any receipt to see what still blocks go-live.",
58
+ });
59
+ server.registerTool("authflow_signup", {
60
+ title: "Mint a per-tenant admin API key",
61
+ description: "Create a tenant and return an afa_ admin API key shown once. No existing credential is " +
62
+ "required. Prefer write_secrets so the key lands in an env file instead of the chat. Tell " +
63
+ "the user to put AUTHFLOW_ADMIN_API_KEY in their MCP config and restart the server before " +
64
+ "calling register. Duplicate emails return already_registered — the previous key is not " +
65
+ "re-issued.",
66
+ inputSchema: {
67
+ email: z.string().describe("Email that owns the tenant."),
68
+ write_secrets: z
69
+ .boolean()
70
+ .optional()
71
+ .describe("Write AUTHFLOW_ADMIN_API_KEY to an env file. Strongly preferred."),
72
+ secret_destination: z.string().optional().describe("Env-file path. Defaults to .env.local."),
73
+ issuer: issuerArg,
74
+ },
75
+ annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
76
+ }, async ({ email, write_secrets, secret_destination, issuer }) => attempt(async () => {
77
+ const receipt = await signupTenant(requireIssuer(issuer), email);
78
+ if (write_secrets !== false) {
79
+ const storedAt = await writeAdminApiKey({
80
+ value: receipt.admin_api_key,
81
+ destination: secret_destination,
82
+ });
83
+ receipt.admin_api_key = `<stored in ${storedAt}>`;
84
+ }
85
+ return ok({
86
+ ...receipt,
87
+ next_steps: [
88
+ "Put AUTHFLOW_ADMIN_API_KEY in the MCP server env (or load the env file) and restart it.",
89
+ "Then call authflow_register_resource with a slug.",
90
+ ],
91
+ });
92
+ }));
93
+ server.registerTool("authflow_doctor", {
94
+ title: "Check the Authflow rail is reachable and correctly configured",
95
+ description: "Preflight a rail deployment: issuer reachable, Origin Protocol keys document served and " +
96
+ "self-consistent, and (with a slug) the resource's PRM document and gateway 401 challenge. " +
97
+ "Run this first, and run it again whenever something looks broken — it distinguishes a " +
98
+ "misconfigured hostname from an actual rail outage, which look identical from the outside.",
99
+ inputSchema: {
100
+ issuer: issuerArg,
101
+ slug: z
102
+ .string()
103
+ .optional()
104
+ .describe("Resource slug. Adds PRM and gateway-challenge checks for that resource."),
105
+ },
106
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
107
+ }, async ({ issuer, slug }) => attempt(async () => {
108
+ const report = await runDoctor(requireIssuer(issuer), slug);
109
+ return ok(`${formatDoctorReport(report)}\n\n${JSON.stringify(report, null, 2)}`);
110
+ }));
111
+ server.registerTool("authflow_register_resource", {
112
+ title: "Register a resource on the rail",
113
+ description: "Create a resource and return its registration receipt: canonical resource URI, gateway " +
114
+ "URL, PRM URL, issuer, keys URL, usage URL, and the origin API key (shown once). Neither a " +
115
+ "Stripe account nor a deployed origin is required — omit them to register a draft and fill " +
116
+ "them in later. Prices and per-tool credit costs live in the rail registry, never in the " +
117
+ "creator's Stripe account. Set write_secrets to store the origin API key in a real secret " +
118
+ "store instead of returning it in the response.",
119
+ inputSchema: {
120
+ slug: z
121
+ .string()
122
+ .describe("URL path segment under the gateway. 1-32 chars, ^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?$"),
123
+ display_name: z.string().optional().describe("Name shown on Checkout and the subscriptions page."),
124
+ price_amount_minor: z
125
+ .number()
126
+ .int()
127
+ .nonnegative()
128
+ .default(900)
129
+ .describe("Subscription price in minor units. 900 = $9.00."),
130
+ credits_per_period: z
131
+ .number()
132
+ .int()
133
+ .nonnegative()
134
+ .default(12)
135
+ .describe("Credits granted each billing period."),
136
+ currency: z.string().default("usd").describe("ISO 4217, lowercase."),
137
+ connected_account_id: z
138
+ .string()
139
+ .optional()
140
+ .describe("Existing Stripe Standard account (acct_...). Omit to connect Stripe later."),
141
+ origin_base_uri: z
142
+ .string()
143
+ .optional()
144
+ .describe("Origin scheme+host, no path and no /mcp suffix. Omit if not deployed yet."),
145
+ metering_mode: z
146
+ .enum(["origin_reported", "gateway_metered"])
147
+ .optional()
148
+ .describe("gateway_metered lets the rail debit and compensate so the origin needs no billing " +
149
+ "code. Only valid when billing one unit per tool call and not streaming responses."),
150
+ metering_default_units: z
151
+ .number()
152
+ .int()
153
+ .nonnegative()
154
+ .optional()
155
+ .describe("Credits charged for a tool not named in tool_units."),
156
+ tool_units: z
157
+ .record(z.string(), z.number().int().nonnegative())
158
+ .optional()
159
+ .describe("Per-tool credit costs. 0 declares a tool free (read-only)."),
160
+ write_secrets: z
161
+ .enum(secretTargets)
162
+ .optional()
163
+ .describe("Where to store the origin API key. Strongly preferred over returning it."),
164
+ secret_destination: z
165
+ .string()
166
+ .optional()
167
+ .describe("user-secrets: project directory. env-file: file path. keyvault: vault name."),
168
+ issuer: issuerArg,
169
+ admin_key: adminKeyArg,
170
+ },
171
+ annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
172
+ }, async (args) => attempt(async () => {
173
+ const auth = adminAuth(args.issuer, args.admin_key);
174
+ const receipt = await registerResource(auth, {
175
+ slug: args.slug,
176
+ display_name: args.display_name ?? args.slug,
177
+ currency: args.currency,
178
+ price_amount_minor: args.price_amount_minor,
179
+ credits_per_period: args.credits_per_period,
180
+ connected_account_id: args.connected_account_id ?? null,
181
+ origin_base_uri: args.origin_base_uri ?? null,
182
+ metering_mode: args.metering_mode,
183
+ metering_default_units: args.metering_default_units,
184
+ tool_units: args.tool_units,
185
+ });
186
+ // Store before returning: an origin API key that reaches the transcript is a credential in
187
+ // a chat log, and it is shown exactly once so there is no second chance to place it well.
188
+ const originApiKey = receipt.origin_api_key;
189
+ if (args.write_secrets && originApiKey) {
190
+ const storedAt = await writeOriginApiKey({
191
+ target: args.write_secrets,
192
+ value: originApiKey,
193
+ destination: args.secret_destination,
194
+ });
195
+ receipt.origin_api_key = `<stored in ${storedAt}>`;
196
+ }
197
+ return ok(withNextSteps(receipt));
198
+ }));
199
+ server.registerTool("authflow_get_resource", {
200
+ title: "Get a resource's registration receipt",
201
+ description: "Return the current receipt for a slug, including status and pending_requirements. Does " +
202
+ "not include the origin API key — rotate it if it was lost.",
203
+ inputSchema: { slug: z.string(), issuer: issuerArg, admin_key: adminKeyArg },
204
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
205
+ }, async ({ slug, issuer, admin_key }) => attempt(async () => ok(withNextSteps(await getResource(adminAuth(issuer, admin_key), slug)))));
206
+ server.registerTool("authflow_integration_plan", {
207
+ title: "Get framework-specific code and configuration for the origin",
208
+ description: "Return the exact configuration, code snippets, verification steps, and hard invariants " +
209
+ "for wiring an origin MCP server to this resource. Apply the result to the user's codebase " +
210
+ "yourself — this tool has no access to their files. Use framework 'proxy' when the origin " +
211
+ "is in a language with no in-process option or should not be modified at all.",
212
+ inputSchema: {
213
+ slug: z.string(),
214
+ framework: z
215
+ .enum(integrationFrameworks)
216
+ .describe("Origin implementation: dotnet, typescript, python, or proxy."),
217
+ issuer: issuerArg,
218
+ admin_key: adminKeyArg,
219
+ },
220
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
221
+ }, async ({ slug, framework, issuer, admin_key }) => attempt(async () => {
222
+ if (!isIntegrationFramework(framework)) {
223
+ return fail(`Unknown framework '${framework}'. Use one of: ${integrationFrameworks.join(", ")}.`);
224
+ }
225
+ const receipt = await getResource(adminAuth(issuer, admin_key), slug);
226
+ return ok(buildIntegrationPlan(framework, receipt));
227
+ }));
228
+ server.registerTool("authflow_start_stripe_connect", {
229
+ title: "Start or resume Stripe Connect onboarding",
230
+ description: "Return a Stripe-hosted onboarding URL for the creator to open in a browser and complete " +
231
+ "KYC. Give them the URL — do not attempt to fill the form. Account links are single-use and " +
232
+ "expire in minutes, so call this again for a fresh link; it resumes the same Stripe account " +
233
+ "rather than creating another. Call it again after they finish to confirm charges_enabled " +
234
+ "and promote the resource. onboarding_url is null once there is nothing left to do.",
235
+ inputSchema: {
236
+ slug: z.string(),
237
+ email: z.string().optional().describe("Pre-fills the Stripe form. Optional."),
238
+ issuer: issuerArg,
239
+ admin_key: adminKeyArg,
240
+ },
241
+ annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
242
+ }, async ({ slug, email, issuer, admin_key }) => attempt(async () => {
243
+ const result = await startConnect(adminAuth(issuer, admin_key), slug, email);
244
+ return ok({
245
+ ...result,
246
+ next_steps: result.charges_enabled
247
+ ? result.pending_requirements.map((r) => describePending(r, slug))
248
+ : [`Open ${result.onboarding_url} in a browser and complete Stripe onboarding, then call this tool again.`],
249
+ });
250
+ }));
251
+ server.registerTool("authflow_set_connected_account", {
252
+ title: "Attach an existing Stripe account to a resource",
253
+ description: "Use when the creator already has a Stripe Standard account connected to the platform. For " +
254
+ "a creator who has not onboarded yet, use authflow_start_stripe_connect instead.",
255
+ inputSchema: {
256
+ slug: z.string(),
257
+ connected_account_id: z.string().describe("Stripe Standard account id (acct_...)."),
258
+ issuer: issuerArg,
259
+ admin_key: adminKeyArg,
260
+ },
261
+ annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
262
+ }, async ({ slug, connected_account_id, issuer, admin_key }) => attempt(async () => ok(withNextSteps(await setConnectedAccount(adminAuth(issuer, admin_key), slug, connected_account_id)))));
263
+ server.registerTool("authflow_set_origin", {
264
+ title: "Point the rail at the deployed origin",
265
+ description: "Supply the origin base URI and promote the resource to live if nothing else is pending. " +
266
+ "The URL is scheme and host only — no path, and no /mcp suffix, because the gateway appends " +
267
+ "it. Also the supported way to move a live origin to a new hostname.",
268
+ inputSchema: {
269
+ slug: z.string(),
270
+ origin_base_uri: z.string().describe("e.g. https://video-xyz.azurecontainerapps.io"),
271
+ issuer: issuerArg,
272
+ admin_key: adminKeyArg,
273
+ },
274
+ annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
275
+ }, async ({ slug, origin_base_uri, issuer, admin_key }) => attempt(async () => ok(withNextSteps(await setOrigin(adminAuth(issuer, admin_key), slug, origin_base_uri)))));
276
+ server.registerTool("authflow_probe", {
277
+ title: "Verify the origin fails closed before it takes paid traffic",
278
+ description: "The rail posts valid and deliberately broken identity headers at the origin's /mcp path " +
279
+ "and reports pass/fail per spec §6.2. A failure means the origin would serve MCP to " +
280
+ "unauthenticated callers — a paywall bypass. Do not cut over on a failing probe. " +
281
+ "Authenticates with the origin API key, which is bound to one resource.",
282
+ inputSchema: {
283
+ origin_api_key: z
284
+ .string()
285
+ .optional()
286
+ .describe("Defaults to the AUTHFLOW_ORIGIN_API_KEY environment variable."),
287
+ issuer: issuerArg,
288
+ },
289
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
290
+ }, async ({ origin_api_key, issuer }) => attempt(async () => {
291
+ const key = (origin_api_key ?? process.env.AUTHFLOW_ORIGIN_API_KEY ?? "").trim();
292
+ if (!key) {
293
+ return fail("Set AUTHFLOW_ORIGIN_API_KEY or pass origin_api_key.");
294
+ }
295
+ const report = await probeConformance(requireIssuer(issuer), key);
296
+ return ok(report);
297
+ }));
298
+ server.registerTool("authflow_mint_test_header", {
299
+ title: "Mint a signed identity header for local testing",
300
+ description: "Local and staging only: mint a real X-Authflow-Identity header so the origin's verifier " +
301
+ "can be exercised without the OAuth and Checkout loop. Refuses live keys. This is a test " +
302
+ "aid, not a substitute for the paid flow.",
303
+ inputSchema: {
304
+ origin_api_key: z
305
+ .string()
306
+ .optional()
307
+ .describe("Defaults to the AUTHFLOW_ORIGIN_API_KEY environment variable."),
308
+ tier: z.string().optional(),
309
+ ttl_seconds: z.number().int().min(1).max(300).optional(),
310
+ grant_credits: z.number().int().nonnegative().optional(),
311
+ subject: z.string().optional(),
312
+ issuer: issuerArg,
313
+ },
314
+ annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
315
+ }, async (args) => attempt(async () => {
316
+ const key = (args.origin_api_key ?? process.env.AUTHFLOW_ORIGIN_API_KEY ?? "").trim();
317
+ if (!key) {
318
+ return fail("Set AUTHFLOW_ORIGIN_API_KEY or pass origin_api_key.");
319
+ }
320
+ return ok(await mintDevHeader(requireIssuer(args.issuer), key, {
321
+ subject: args.subject,
322
+ tier: args.tier,
323
+ ttlSeconds: args.ttl_seconds,
324
+ grantCredits: args.grant_credits,
325
+ }));
326
+ }));
327
+ server.registerTool("authflow_rotate_origin_key", {
328
+ title: "Rotate a resource's origin API key",
329
+ description: "Issue a new origin API key and invalidate the previous one immediately. Usage reports, " +
330
+ "probes, and mint-header calls with the old key stop working the moment this returns, so " +
331
+ "update the origin's secret store straight away. The new key is shown once.",
332
+ inputSchema: {
333
+ slug: z.string(),
334
+ write_secrets: z
335
+ .enum(secretTargets)
336
+ .optional()
337
+ .describe("Where to store the new key."),
338
+ secret_destination: z.string().optional(),
339
+ issuer: issuerArg,
340
+ admin_key: adminKeyArg,
341
+ },
342
+ annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
343
+ }, async (args) => attempt(async () => {
344
+ const receipt = await rotateOriginKey(adminAuth(args.issuer, args.admin_key), args.slug);
345
+ const key = receipt.origin_api_key;
346
+ if (args.write_secrets && key) {
347
+ const storedAt = await writeOriginApiKey({
348
+ target: args.write_secrets,
349
+ value: key,
350
+ destination: args.secret_destination,
351
+ });
352
+ receipt.origin_api_key = `<stored in ${storedAt}>`;
353
+ }
354
+ return ok(receipt);
355
+ }));
356
+ return server;
357
+ }
358
+ export async function runStdioServer() {
359
+ const server = createOnboardingServer();
360
+ await server.connect(new StdioServerTransport());
361
+ }
362
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}