From 5e2710fd774ca954dd23b2e520b826d0c7a0a5fd Mon Sep 17 00:00:00 2001 From: John | Elite Encoder Date: Thu, 3 Sep 2026 00:06:05 -0400 Subject: [PATCH 1/2] chore: update @pymthouse/gateway-web to version 0.3.0 and add attribution source to inference requests - Bumped the version of @pymthouse/gateway-web in package.json. - Added attributionSource parameter to inference requests in gateway.ts. - Introduced gatewayRequestId in mcp-server.ts for tracking requests. - Updated Asset type in store.ts to include gatewayRequestId for better tracking. --- lib/mcp/gateway.ts | 3 ++- lib/mcp/mcp-server.ts | 14 +++++++++++++- lib/mcp/store.ts | 2 ++ package.json | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/mcp/gateway.ts b/lib/mcp/gateway.ts index 962ffaf..40af89c 100644 --- a/lib/mcp/gateway.ts +++ b/lib/mcp/gateway.ts @@ -21,7 +21,8 @@ export async function runInference( signerHeaders: { Authorization: `Bearer ${signerJwt}` }, discoveryUrl: session.discovery_url, insecureTls: true, - timeoutMs + timeoutMs, + attributionSource: "pymthouse_gateway" }); return gw.runInference(request); }; diff --git a/lib/mcp/mcp-server.ts b/lib/mcp/mcp-server.ts index 5e31d44..5afea9a 100644 --- a/lib/mcp/mcp-server.ts +++ b/lib/mcp/mcp-server.ts @@ -206,6 +206,7 @@ export function buildRawMcpServer(principal: McpPrincipal): McpServer { return text(err instanceof Error ? err.message : String(err), true); } + const gatewayRequestId = newId("job"); try { const result = await runInference(principal, { capability, @@ -213,6 +214,7 @@ export function buildRawMcpServer(principal: McpPrincipal): McpServer { prompt, endpoint, timeoutMs: 780_000, + gatewayRequestId, }); const url = result.url ?? result.imageUrl ?? result.videoUrl ?? result.audioUrl; if (url) { @@ -221,6 +223,7 @@ export function buildRawMcpServer(principal: McpPrincipal): McpServer { url, capability, createdAt: new Date().toISOString(), + gatewayRequestId: result.gatewayRequestId, }); } return text({ @@ -228,9 +231,18 @@ export function buildRawMcpServer(principal: McpPrincipal): McpServer { url, orchestrator: result.orchestrator, elapsed_ms: result.elapsedMs, + gateway_request_id: result.gatewayRequestId, }); } catch (err) { - return text(err instanceof Error ? err.message : String(err), true); + // A call can fail after tickets were already paid, so the id must be + // reported here too or that spend is unattributable. + return text( + { + error: err instanceof Error ? err.message : String(err), + gateway_request_id: gatewayRequestId, + }, + true + ); } }, ); diff --git a/lib/mcp/store.ts b/lib/mcp/store.ts index 367e459..b664f6d 100644 --- a/lib/mcp/store.ts +++ b/lib/mcp/store.ts @@ -3,6 +3,8 @@ export type Asset = { url: string; capability: string; createdAt: string; + /** Joins this asset to its ticket rows in PymtHouse metering. */ + gatewayRequestId: string; }; const assets = new Map(); diff --git a/package.json b/package.json index 0d21b62..ddc61f2 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@auth0/nextjs-auth0": "^4.27.0", "@modelcontextprotocol/sdk": "^1.30.0", "@pymthouse/builder-sdk": "^0.6.5", - "@pymthouse/gateway-web": "^0.2.0", + "@pymthouse/gateway-web": "^0.3.0", "framer-motion": "^11.15.0", "geist": "^1.7.0", "jose": "^6.2.10", From 995f160ddb8c6b8697e0fe6ef00f6e27699ef751 Mon Sep 17 00:00:00 2001 From: John | Elite Encoder Date: Thu, 3 Sep 2026 01:14:19 -0400 Subject: [PATCH 2/2] feat(mcp): supply a rotating signer credential to the gateway MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build one gateway per inference call with a signerHeaders provider backed by resolveSignerSession, seeding the first exchange so we do not mint twice. Drop the outer SignerRefreshRequired rebuild — the library now refreshes the bearer itself. --- lib/mcp/gateway.ts | 43 +++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/lib/mcp/gateway.ts b/lib/mcp/gateway.ts index 40af89c..aa41cb6 100644 --- a/lib/mcp/gateway.ts +++ b/lib/mcp/gateway.ts @@ -1,8 +1,7 @@ import { createGateway, - SignerRefreshRequired, type InferenceRequest, - type InferenceResult + type InferenceResult, } from "@pymthouse/gateway-web"; import { pymthouseSignerUrl } from "./env"; import type { McpPrincipal } from "./jwt"; @@ -12,28 +11,24 @@ export async function runInference( principal: McpPrincipal, request: InferenceRequest ): Promise { - let session = await resolveSignerSession(principal); + const session = await resolveSignerSession(principal); const timeoutMs = request.timeoutMs ?? request.timeout ?? 120_000; + let seeded: typeof session | null = session; - const attempt = async (signerJwt: string) => { - const gw = createGateway({ - signerUrl: session.signer_url || pymthouseSignerUrl(), - signerHeaders: { Authorization: `Bearer ${signerJwt}` }, - discoveryUrl: session.discovery_url, - insecureTls: true, - timeoutMs, - attributionSource: "pymthouse_gateway" - }); - return gw.runInference(request); - }; - - try { - return await attempt(session.access_token); - } catch (err) { - if (err instanceof SignerRefreshRequired) { - session = await resolveSignerSession(principal); - return attempt(session.access_token); - } - throw err; - } + const gw = createGateway({ + signerUrl: session.signer_url || pymthouseSignerUrl(), + discoveryUrl: session.discovery_url, + signerHeaders: async () => { + const next = seeded ?? (await resolveSignerSession(principal)); + seeded = null; + return { + headers: { Authorization: `Bearer ${next.access_token}` }, + expiresInSeconds: next.expires_in, + }; + }, + insecureTls: true, + timeoutMs, + attributionSource: "pymthouse_gateway", + }); + return gw.runInference(request); } diff --git a/package.json b/package.json index ddc61f2..d615cc1 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@auth0/nextjs-auth0": "^4.27.0", "@modelcontextprotocol/sdk": "^1.30.0", "@pymthouse/builder-sdk": "^0.6.5", - "@pymthouse/gateway-web": "^0.3.0", + "@pymthouse/gateway-web": "^0.4.0", "framer-motion": "^11.15.0", "geist": "^1.7.0", "jose": "^6.2.10",