@01.software/cli 0.9.0 → 0.10.1
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/dist/index.js +414 -28
- package/dist/index.js.map +1 -1
- package/dist/mcp/{chunk-GJOQ4SE2.js → chunk-2ECTVUKU.js} +1127 -531
- package/dist/mcp/chunk-2ECTVUKU.js.map +1 -0
- package/dist/mcp/http.js +43 -11
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/stdio.js +1 -1
- package/dist/mcp/vercel.js +1162 -540
- package/package.json +17 -9
- package/dist/mcp/chunk-GJOQ4SE2.js.map +0 -1
package/dist/mcp/http.js
CHANGED
|
@@ -5,10 +5,13 @@ import {
|
|
|
5
5
|
MCP_SCOPES,
|
|
6
6
|
MCP_TENANT_CLAIM,
|
|
7
7
|
MCP_TENANT_ROLE_CLAIM,
|
|
8
|
+
createMcpTelemetrySummary,
|
|
8
9
|
createServer,
|
|
10
|
+
flushMcpTelemetrySummary,
|
|
9
11
|
mcpServicePublicJwks,
|
|
10
|
-
requestContext
|
|
11
|
-
|
|
12
|
+
requestContext,
|
|
13
|
+
runWithMcpTelemetry
|
|
14
|
+
} from "./chunk-2ECTVUKU.js";
|
|
12
15
|
|
|
13
16
|
// src/transport/http.ts
|
|
14
17
|
import { createServer as createServer2 } from "http";
|
|
@@ -217,7 +220,10 @@ function setCors(res) {
|
|
|
217
220
|
"Access-Control-Allow-Headers",
|
|
218
221
|
"Authorization, Content-Type, mcp-session-id"
|
|
219
222
|
);
|
|
220
|
-
res.setHeader(
|
|
223
|
+
res.setHeader(
|
|
224
|
+
"Access-Control-Expose-Headers",
|
|
225
|
+
"Mcp-Session-Id, Mcp-Protocol-Version"
|
|
226
|
+
);
|
|
221
227
|
}
|
|
222
228
|
function getHeaderValue(headers, name) {
|
|
223
229
|
const value = headers[name.toLowerCase()];
|
|
@@ -297,7 +303,7 @@ HTTP OAuth Tools
|
|
|
297
303
|
----------------
|
|
298
304
|
|
|
299
305
|
Schema get-collection-schema
|
|
300
|
-
Context get-tenant-context
|
|
306
|
+
Context get-tenant-context, check-feature-progress
|
|
301
307
|
Field Config list-configurable-fields, update-field-config
|
|
302
308
|
Guidance sdk-get-recipe, sdk-search-docs, sdk-get-auth-setup, sdk-get-collection-pattern
|
|
303
309
|
|
|
@@ -316,9 +322,9 @@ Resources (12): config, collections-schema, getting-started, guides, api, query-
|
|
|
316
322
|
Links
|
|
317
323
|
-----
|
|
318
324
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
325
|
+
Integrations https://docs.01.software/integrations
|
|
326
|
+
Readiness https://docs.01.software/readiness
|
|
327
|
+
OpenAPI https://docs.01.software/api/openapi
|
|
322
328
|
Console https://console.01.software
|
|
323
329
|
`;
|
|
324
330
|
var PROTECTED_RESOURCE_METADATA = JSON.stringify({
|
|
@@ -326,14 +332,25 @@ var PROTECTED_RESOURCE_METADATA = JSON.stringify({
|
|
|
326
332
|
authorization_servers: [MCP_OAUTH_ISSUER],
|
|
327
333
|
scopes_supported: [MCP_SCOPES.read, MCP_SCOPES.write]
|
|
328
334
|
});
|
|
335
|
+
var PROTECTED_RESOURCE_METADATA_URL = new URL(
|
|
336
|
+
MCP_PROTECTED_RESOURCE_METADATA_PATH,
|
|
337
|
+
MCP_RESOURCE_AUDIENCE
|
|
338
|
+
).toString();
|
|
329
339
|
var SERVICE_JWKS_PATH = "/.well-known/service-jwks.json";
|
|
330
340
|
function writeOAuthError(res, status, error, description) {
|
|
331
341
|
res.writeHead(status, {
|
|
332
342
|
"Content-Type": "application/json",
|
|
333
|
-
"WWW-Authenticate": `Bearer resource_metadata="${
|
|
343
|
+
"WWW-Authenticate": `Bearer resource_metadata="${PROTECTED_RESOURCE_METADATA_URL}", error="${error}", error_description="${description}"`
|
|
334
344
|
});
|
|
335
345
|
res.end(JSON.stringify({ error, error_description: description }));
|
|
336
346
|
}
|
|
347
|
+
function acceptsEventStream(req) {
|
|
348
|
+
const accept = getHeaderValue(req.headers, "accept");
|
|
349
|
+
if (!accept) return false;
|
|
350
|
+
return accept.split(",").some(
|
|
351
|
+
(entry) => entry.trim().split(";")[0]?.toLowerCase() === "text/event-stream"
|
|
352
|
+
);
|
|
353
|
+
}
|
|
337
354
|
async function handler(req, res) {
|
|
338
355
|
setCors(res);
|
|
339
356
|
if (req.method === "OPTIONS") {
|
|
@@ -366,6 +383,11 @@ async function handler(req, res) {
|
|
|
366
383
|
}
|
|
367
384
|
return;
|
|
368
385
|
}
|
|
386
|
+
if (acceptsEventStream(req)) {
|
|
387
|
+
res.writeHead(405, { "Content-Type": "application/json" });
|
|
388
|
+
res.end(METHOD_NOT_ALLOWED);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
369
391
|
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
|
|
370
392
|
res.end(HOME_PAGE);
|
|
371
393
|
return;
|
|
@@ -379,7 +401,12 @@ async function handler(req, res) {
|
|
|
379
401
|
getHeaderValue(req.headers, "authorization")
|
|
380
402
|
);
|
|
381
403
|
if (!auth.valid) {
|
|
382
|
-
writeOAuthError(
|
|
404
|
+
writeOAuthError(
|
|
405
|
+
res,
|
|
406
|
+
auth.error === "insufficient_scope" ? 403 : 401,
|
|
407
|
+
auth.error,
|
|
408
|
+
auth.errorDescription
|
|
409
|
+
);
|
|
383
410
|
return;
|
|
384
411
|
}
|
|
385
412
|
const server = createServer({ toolSurface: "oauth" });
|
|
@@ -402,14 +429,19 @@ async function handler(req, res) {
|
|
|
402
429
|
if (typeof value === "string") headers.set(key, value);
|
|
403
430
|
else if (Array.isArray(value)) headers.set(key, value.join(", "));
|
|
404
431
|
}
|
|
432
|
+
const telemetrySummary = createMcpTelemetrySummary("http");
|
|
405
433
|
await requestContext.run({ headers, auth: auth.context }, async () => {
|
|
406
434
|
try {
|
|
407
|
-
|
|
408
|
-
|
|
435
|
+
await runWithMcpTelemetry(telemetrySummary, async () => {
|
|
436
|
+
const body = req.body ?? JSON.parse(await readBody(req));
|
|
437
|
+
await transport.handleRequest(req, res, body);
|
|
438
|
+
});
|
|
409
439
|
} catch (err) {
|
|
410
440
|
writeRequestError(res, err);
|
|
411
441
|
} finally {
|
|
442
|
+
telemetrySummary.durationMs = Date.now() - telemetrySummary.startedAtMs;
|
|
412
443
|
await close();
|
|
444
|
+
await flushMcpTelemetrySummary(telemetrySummary);
|
|
413
445
|
}
|
|
414
446
|
});
|
|
415
447
|
}
|
package/dist/mcp/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/transport/http.ts","../src/handler.ts","../src/auth.ts"],"sourcesContent":["import { createServer } from 'node:http'\nimport handler from '../handler'\n\nconst port = parseInt(process.env.PORT || '3001', 10)\n\ncreateServer(handler).listen(port, () => {\n console.log(`MCP server listening on http://localhost:${port}`)\n})\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'\nimport {\n MCP_OAUTH_ISSUER,\n MCP_PROTECTED_RESOURCE_METADATA_PATH,\n MCP_RESOURCE_AUDIENCE,\n MCP_SCOPES,\n} from '@01.software/auth-contracts'\nimport { createServer } from './server'\nimport { requestContext } from './lib/request-context'\nimport { validateBearerAuthorizationHeaderAsync } from './auth'\nimport { mcpServicePublicJwks } from './service-auth'\n\nconst MAX_REQUEST_BODY_BYTES = 1024 * 1024\nconst MCP_ALLOWED_BROWSER_ORIGIN = 'https://01.software'\nconst METHOD_NOT_ALLOWED = JSON.stringify({\n jsonrpc: '2.0',\n error: {\n code: -32000,\n message: 'Method not allowed.',\n },\n id: null,\n})\n\nfunction setCors(res: ServerResponse) {\n res.setHeader('Access-Control-Allow-Origin', MCP_ALLOWED_BROWSER_ORIGIN)\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS')\n res.setHeader(\n 'Access-Control-Allow-Headers',\n 'Authorization, Content-Type, mcp-session-id',\n )\n res.setHeader('Access-Control-Expose-Headers', 'Mcp-Session-Id, Mcp-Protocol-Version')\n}\n\nfunction getHeaderValue(\n headers: IncomingMessage['headers'],\n name: string,\n): string | undefined {\n const value = headers[name.toLowerCase()]\n if (Array.isArray(value)) return value[0]\n return value\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n let size = 0\n req.on('data', (chunk: Buffer) => {\n size += chunk.length\n if (size > MAX_REQUEST_BODY_BYTES) {\n req.destroy()\n reject(new Error('Request body too large'))\n return\n }\n chunks.push(chunk)\n })\n req.on('end', () => resolve(Buffer.concat(chunks).toString()))\n req.on('error', reject)\n })\n}\n\nconst HOME_PAGE = `01.software MCP Server\n======================\n\nMCP server for AI agents to interact with the 01.software API.\nConnect over HTTP with OAuth, or use the local CLI stdio transport for full\nserver-key operations.\n\n\nAuthentication\n--------------\n\nHTTP MCP uses OAuth discovery and Authorization Code + PKCE.\nClients should connect to:\n\nConnect\n-------\n\nClaude Code:\n\n claude mcp add --transport http 01software https://mcp.01.software/mcp\n\nCodex (.codex/config.toml):\n\n [mcp_servers.01software]\n url = \"https://mcp.01.software/mcp\"\n\nCursor / Claude Desktop / other JSON clients:\n\n {\n \"mcpServers\": {\n \"01software\": {\n \"type\": \"http\",\n \"url\": \"https://mcp.01.software/mcp\"\n }\n }\n }\n\nWindsurf (~/.codeium/windsurf/mcp_config.json):\n\n {\n \"mcpServers\": {\n \"01software\": {\n \"serverUrl\": \"https://mcp.01.software/mcp\"\n }\n }\n }\n\nCLI (stdio):\n\n npx @01.software/cli mcp\n\n\nHTTP OAuth Tools\n----------------\n\nSchema get-collection-schema\nContext get-tenant-context\nField Config list-configurable-fields, update-field-config\nGuidance sdk-get-recipe, sdk-search-docs, sdk-get-auth-setup, sdk-get-collection-pattern\n\nFull Tool Surface\n-----------------\n\nThe local CLI stdio transport exposes CRUD, commerce, cart, validation, product,\nschema, context, field-config, and guidance tools:\n\n npx @01.software/cli mcp\n\nPrompts (4): sdk-usage-guide, collection-query-help, order-flow-guide, feature-setup-guide\nResources (12): config, collections-schema, getting-started, guides, api, query-builder, react-query, server-api, customer-auth, browser-vs-server, file-upload, webhook\n\n\nLinks\n-----\n\nDocs https://01.software/docs/integrations/mcp\nSDK https://01.software/docs/sdk/client\nAPI Reference https://01.software/docs/api/rest-api\nConsole https://console.01.software\n`\n\nconst PROTECTED_RESOURCE_METADATA = JSON.stringify({\n resource: MCP_RESOURCE_AUDIENCE,\n authorization_servers: [MCP_OAUTH_ISSUER],\n scopes_supported: [MCP_SCOPES.read, MCP_SCOPES.write],\n})\nconst SERVICE_JWKS_PATH = '/.well-known/service-jwks.json'\n\nfunction writeOAuthError(res: ServerResponse, status: number, error: string, description: string) {\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'WWW-Authenticate': `Bearer resource_metadata=\"${MCP_PROTECTED_RESOURCE_METADATA_PATH}\", error=\"${error}\", error_description=\"${description}\"`,\n })\n res.end(JSON.stringify({ error, error_description: description }))\n}\n\nexport default async function handler(req: IncomingMessage, res: ServerResponse) {\n setCors(res)\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method === 'GET') {\n const pathname = new URL(req.url ?? '/', MCP_RESOURCE_AUDIENCE).pathname\n if (pathname === MCP_PROTECTED_RESOURCE_METADATA_PATH) {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(PROTECTED_RESOURCE_METADATA)\n return\n }\n\n if (pathname === SERVICE_JWKS_PATH) {\n res.setHeader('Access-Control-Allow-Origin', '*')\n try {\n res.writeHead(200, {\n 'Cache-Control': 'public, max-age=60',\n 'Content-Type': 'application/json',\n })\n res.end(JSON.stringify(mcpServicePublicJwks()))\n } catch {\n res.writeHead(503, {\n 'Cache-Control': 'no-store',\n 'Content-Type': 'application/json',\n })\n res.end(JSON.stringify({ keys: [] }))\n }\n return\n }\n\n res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })\n res.end(HOME_PAGE)\n return\n }\n\n // Stateless Streamable HTTP should only accept POST requests.\n if (req.method !== 'POST') {\n res.writeHead(405, { 'Content-Type': 'application/json' })\n res.end(METHOD_NOT_ALLOWED)\n return\n }\n\n const auth = await validateBearerAuthorizationHeaderAsync(\n getHeaderValue(req.headers, 'authorization'),\n )\n if (!auth.valid) {\n writeOAuthError(res, auth.error === 'insufficient_scope' ? 403 : 401, auth.error, auth.errorDescription)\n return\n }\n\n const server = createServer({ toolSurface: 'oauth' })\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n })\n let closed = false\n\n const close = async () => {\n if (closed) return\n closed = true\n await transport.close()\n await server.close()\n }\n\n res.on('close', () => {\n void close()\n })\n\n await server.connect(transport)\n\n const headers = new Headers()\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === 'string') headers.set(key, value)\n else if (Array.isArray(value)) headers.set(key, value.join(', '))\n }\n\n await requestContext.run({ headers, auth: auth.context }, async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const body = (req as any).body ?? JSON.parse(await readBody(req))\n await transport.handleRequest(req, res, body)\n } catch (err) {\n writeRequestError(res, err)\n } finally {\n await close()\n }\n })\n}\n\nfunction writeRequestError(res: ServerResponse, err: unknown) {\n if (res.headersSent) return\n if (err instanceof SyntaxError) {\n res.writeHead(400, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ error: 'Invalid JSON body' }))\n return\n }\n if (err instanceof Error && err.message === 'Request body too large') {\n res.writeHead(413, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ error: 'Request body too large' }))\n return\n }\n res.writeHead(500, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ error: 'Internal server error' }))\n}\n","import { createPublicKey, verify as verifySignature } from 'node:crypto'\nimport {\n MCP_OAUTH_ISSUER,\n MCP_RESOURCE_AUDIENCE,\n MCP_SCOPES,\n MCP_TENANT_CLAIM,\n MCP_TENANT_ROLE_CLAIM,\n} from '@01.software/auth-contracts'\n\nconst ALLOWED_ALGORITHMS = new Set(['RS256', 'ES256'])\nconst DEFAULT_CLOCK_SKEW_SECONDS = 30\nconst DEFAULT_JWKS_URI = `${MCP_OAUTH_ISSUER}/.well-known/jwks.json`\nconst MAX_ACCESS_TOKEN_LIFETIME_SECONDS = 300\ntype McpScope = (typeof MCP_SCOPES)[keyof typeof MCP_SCOPES]\ntype McpTenantRole = 'tenant-admin' | 'tenant-editor' | 'tenant-viewer'\n\ninterface JwtHeader {\n alg?: unknown\n kid?: unknown\n}\n\ninterface JwtPayload {\n aud?: unknown\n exp?: unknown\n iat?: unknown\n iss?: unknown\n nbf?: unknown\n scope?: unknown\n scp?: unknown\n sub?: unknown\n [MCP_TENANT_CLAIM]?: unknown\n [MCP_TENANT_ROLE_CLAIM]?: unknown\n}\n\nexport interface TenantAuthContext {\n tenantId: string\n principalId?: string\n scopes: McpScope[]\n tenantRole: McpTenantRole\n authMode: 'oauth'\n}\n\nexport type AuthResult =\n | {\n valid: true\n context: TenantAuthContext\n }\n | {\n valid: false\n error: 'invalid_token' | 'insufficient_scope'\n errorDescription: string\n context?: undefined\n }\n\nexport interface JsonWebKeySet {\n keys: Array<Record<string, unknown>>\n}\n\nexport interface ValidateAccessTokenOptions {\n audience?: string\n clockSkewSeconds?: number\n fetchImpl?: typeof fetch\n issuer?: string\n jwks?: JsonWebKeySet\n jwksUri?: string\n now?: Date\n requiredScopes?: McpScope[]\n}\n\nfunction invalid(errorDescription: string): AuthResult {\n return { valid: false, error: 'invalid_token', errorDescription }\n}\n\nfunction isProduction(): boolean {\n return process.env.NODE_ENV === 'production'\n}\n\nfunction insufficientScope(errorDescription: string): AuthResult {\n return { valid: false, error: 'insufficient_scope', errorDescription }\n}\n\nfunction decodeBase64UrlJson<T>(value: string): T | null {\n try {\n return JSON.parse(Buffer.from(value, 'base64url').toString('utf8')) as T\n } catch {\n return null\n }\n}\n\nfunction parseScopes(payload: JwtPayload): McpScope[] {\n const rawScopes =\n typeof payload.scope === 'string'\n ? payload.scope.split(/\\s+/).filter(Boolean)\n : Array.isArray(payload.scp)\n ? payload.scp\n : []\n\n return rawScopes.filter(\n (scope): scope is McpScope =>\n scope === MCP_SCOPES.read || scope === MCP_SCOPES.write,\n )\n}\n\nfunction audienceMatches(aud: unknown, expected: string): boolean {\n if (typeof aud === 'string') return aud === expected\n return Array.isArray(aud) && aud.includes(expected)\n}\n\nfunction verifyJwtSignature(\n alg: string,\n jwk: Record<string, unknown>,\n signingInput: string,\n signature: Buffer,\n): boolean {\n const key = createPublicKey({ key: jwk, format: 'jwk' })\n const input = Buffer.from(signingInput)\n\n if (alg === 'RS256') {\n return verifySignature('RSA-SHA256', input, key, signature)\n }\n\n if (alg === 'ES256') {\n return verifySignature('SHA256', input, { key, dsaEncoding: 'ieee-p1363' }, signature)\n }\n\n return false\n}\n\nlet cachedRemoteJwks:\n | { expiresAt: number; jwks: JsonWebKeySet; uri: string }\n | null = null\n\nfunction jwksUriFor(options: ValidateAccessTokenOptions): string | null {\n const raw = isProduction()\n ? DEFAULT_JWKS_URI\n : options.jwksUri ?? DEFAULT_JWKS_URI\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n return null\n }\n if (\n url.protocol !== 'https:' ||\n url.username ||\n url.password ||\n url.search ||\n url.hash\n ) {\n return null\n }\n return url.toString()\n}\n\nasync function remoteJwks(\n options: ValidateAccessTokenOptions = {},\n forceRefresh = false,\n): Promise<JsonWebKeySet | null> {\n const uri = jwksUriFor(options)\n if (!uri) return null\n const now = Date.now()\n if (\n !forceRefresh &&\n cachedRemoteJwks &&\n cachedRemoteJwks.uri === uri &&\n cachedRemoteJwks.expiresAt > now\n ) {\n return cachedRemoteJwks.jwks\n }\n\n const fetchImpl = options.fetchImpl ?? fetch\n let response: Response\n try {\n response = await fetchImpl(uri, {\n headers: { Accept: 'application/json' },\n })\n } catch {\n return null\n }\n if (!response.ok) return null\n const parsed = (await response.json().catch(() => null)) as JsonWebKeySet | null\n if (!parsed || !Array.isArray(parsed.keys)) return null\n cachedRemoteJwks = {\n expiresAt: now + 300_000,\n jwks: parsed,\n uri,\n }\n return parsed\n}\n\nexport function validateAccessToken(\n token: string,\n options: ValidateAccessTokenOptions = {},\n): AuthResult {\n const parts = token.split('.')\n if (parts.length !== 3 || parts.some((part) => part.length === 0)) {\n return invalid('Bearer token must be a compact JWT')\n }\n\n const [encodedHeader, encodedPayload, encodedSignature] = parts\n const header = decodeBase64UrlJson<JwtHeader>(encodedHeader)\n const payload = decodeBase64UrlJson<JwtPayload>(encodedPayload)\n if (!header || !payload) return invalid('Bearer token contains invalid JSON')\n\n if (typeof header.alg !== 'string' || !ALLOWED_ALGORITHMS.has(header.alg)) {\n return invalid('Bearer token uses an unsupported signing algorithm')\n }\n\n if (typeof header.kid !== 'string' || header.kid.length === 0) {\n return invalid('Bearer token is missing kid')\n }\n\n const jwks = options.jwks\n if (!jwks) return invalid('JWKS is not configured')\n\n const jwk = jwks.keys.find((key) => key.kid === header.kid)\n if (!jwk) return invalid('Bearer token kid is unknown')\n\n const signingInput = `${encodedHeader}.${encodedPayload}`\n const signature = Buffer.from(encodedSignature, 'base64url')\n if (!verifyJwtSignature(header.alg, jwk, signingInput, signature)) {\n return invalid('Bearer token signature is invalid')\n }\n\n const issuer = options.issuer ?? MCP_OAUTH_ISSUER\n if (payload.iss !== issuer) return invalid('Bearer token issuer is invalid')\n\n const audience = options.audience ?? MCP_RESOURCE_AUDIENCE\n if (!audienceMatches(payload.aud, audience)) {\n return invalid('Bearer token audience is invalid')\n }\n\n if (typeof payload.iat !== 'number') return invalid('Bearer token is missing iat')\n if (typeof payload.exp !== 'number') return invalid('Bearer token is missing exp')\n if (payload.exp <= payload.iat) {\n return invalid('Bearer token lifetime is invalid')\n }\n if (payload.exp - payload.iat > MAX_ACCESS_TOKEN_LIFETIME_SECONDS) {\n return invalid('Bearer token lifetime exceeds 300 seconds')\n }\n\n const nowSeconds = Math.floor((options.now ?? new Date()).getTime() / 1000)\n const leeway = options.clockSkewSeconds ?? DEFAULT_CLOCK_SKEW_SECONDS\n if (payload.iat > nowSeconds + leeway) {\n return invalid('Bearer token iat is too far in the future')\n }\n if (typeof payload.nbf === 'number' && payload.nbf > nowSeconds + leeway) {\n return invalid('Bearer token is not yet valid')\n }\n if (payload.exp < nowSeconds - leeway) return invalid('Bearer token is expired')\n\n const tenantId = payload[MCP_TENANT_CLAIM]\n if (typeof tenantId !== 'string' || tenantId.length === 0) {\n return invalid('Bearer token tenant_id claim is invalid')\n }\n\n const tenantRole = payload[MCP_TENANT_ROLE_CLAIM]\n if (\n tenantRole !== 'tenant-admin' &&\n tenantRole !== 'tenant-editor' &&\n tenantRole !== 'tenant-viewer'\n ) {\n return invalid('Bearer token tenant_role claim is invalid')\n }\n\n if (typeof payload.sub !== 'string' || payload.sub.length === 0) {\n return invalid('Bearer token subject claim is invalid')\n }\n\n const scopes = parseScopes(payload)\n const requiredScopes = options.requiredScopes ?? [MCP_SCOPES.read]\n const missingScope = requiredScopes.find((scope) => !scopes.includes(scope))\n if (missingScope) return insufficientScope(`Bearer token is missing ${missingScope}`)\n\n return {\n valid: true,\n context: {\n tenantId,\n principalId: payload.sub,\n scopes,\n tenantRole,\n authMode: 'oauth',\n },\n }\n}\n\nexport function validateBearerAuthorizationHeader(\n authorization: string | null | undefined,\n options?: ValidateAccessTokenOptions,\n): AuthResult {\n if (!authorization) return invalid('Authorization Bearer token is required')\n\n const match = authorization.match(/^Bearer\\s+(.+)$/i)\n if (!match) return invalid('Authorization header must use Bearer')\n\n return validateAccessToken(match[1], options)\n}\n\nfunction shouldRefreshRemoteJwks(result: AuthResult): boolean {\n return (\n !result.valid &&\n (\n result.errorDescription === 'Bearer token kid is unknown' ||\n result.errorDescription === 'Bearer token signature is invalid'\n )\n )\n}\n\nexport async function validateBearerAuthorizationHeaderAsync(\n authorization: string | null | undefined,\n options?: ValidateAccessTokenOptions,\n): Promise<AuthResult> {\n if (!authorization) return invalid('Authorization Bearer token is required')\n\n const match = authorization.match(/^Bearer\\s+(.+)$/i)\n if (!match) return invalid('Authorization header must use Bearer')\n\n if (options?.jwks) {\n return validateAccessToken(match[1], options)\n }\n\n const jwks = await remoteJwks(options)\n const result = validateAccessToken(match[1], {\n ...options,\n jwks: jwks ?? undefined,\n })\n\n if (shouldRefreshRemoteJwks(result)) {\n const refreshedJwks = await remoteJwks(options, true)\n if (refreshedJwks) {\n return validateAccessToken(match[1], {\n ...options,\n jwks: refreshedJwks,\n })\n }\n }\n\n return result\n}\n"],"mappings":"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","names":["createServer","createServer"]}
|
|
1
|
+
{"version":3,"sources":["../src/transport/http.ts","../src/handler.ts","../src/auth.ts"],"sourcesContent":["import { createServer } from 'node:http'\nimport handler from '../handler'\n\nconst port = parseInt(process.env.PORT || '3001', 10)\n\ncreateServer(handler).listen(port, () => {\n console.log(`MCP server listening on http://localhost:${port}`)\n})\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'\nimport {\n MCP_OAUTH_ISSUER,\n MCP_PROTECTED_RESOURCE_METADATA_PATH,\n MCP_RESOURCE_AUDIENCE,\n MCP_SCOPES,\n} from '@01.software/auth-contracts'\nimport { createServer } from './server'\nimport { requestContext } from './lib/request-context'\nimport { validateBearerAuthorizationHeaderAsync } from './auth'\nimport { mcpServicePublicJwks } from './service-auth'\nimport {\n createMcpTelemetrySummary,\n flushMcpTelemetrySummary,\n runWithMcpTelemetry,\n} from './lib/mcp-telemetry'\n\nconst MAX_REQUEST_BODY_BYTES = 1024 * 1024\nconst MCP_ALLOWED_BROWSER_ORIGIN = 'https://01.software'\nconst METHOD_NOT_ALLOWED = JSON.stringify({\n jsonrpc: '2.0',\n error: {\n code: -32000,\n message: 'Method not allowed.',\n },\n id: null,\n})\n\nfunction setCors(res: ServerResponse) {\n res.setHeader('Access-Control-Allow-Origin', MCP_ALLOWED_BROWSER_ORIGIN)\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS')\n res.setHeader(\n 'Access-Control-Allow-Headers',\n 'Authorization, Content-Type, mcp-session-id',\n )\n res.setHeader(\n 'Access-Control-Expose-Headers',\n 'Mcp-Session-Id, Mcp-Protocol-Version',\n )\n}\n\nfunction getHeaderValue(\n headers: IncomingMessage['headers'],\n name: string,\n): string | undefined {\n const value = headers[name.toLowerCase()]\n if (Array.isArray(value)) return value[0]\n return value\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n let size = 0\n req.on('data', (chunk: Buffer) => {\n size += chunk.length\n if (size > MAX_REQUEST_BODY_BYTES) {\n req.destroy()\n reject(new Error('Request body too large'))\n return\n }\n chunks.push(chunk)\n })\n req.on('end', () => resolve(Buffer.concat(chunks).toString()))\n req.on('error', reject)\n })\n}\n\nconst HOME_PAGE = `01.software MCP Server\n======================\n\nMCP server for AI agents to interact with the 01.software API.\nConnect over HTTP with OAuth, or use the local CLI stdio transport for full\nserver-key operations.\n\n\nAuthentication\n--------------\n\nHTTP MCP uses OAuth discovery and Authorization Code + PKCE.\nClients should connect to:\n\nConnect\n-------\n\nClaude Code:\n\n claude mcp add --transport http 01software https://mcp.01.software/mcp\n\nCodex (.codex/config.toml):\n\n [mcp_servers.01software]\n url = \"https://mcp.01.software/mcp\"\n\nCursor / Claude Desktop / other JSON clients:\n\n {\n \"mcpServers\": {\n \"01software\": {\n \"type\": \"http\",\n \"url\": \"https://mcp.01.software/mcp\"\n }\n }\n }\n\nWindsurf (~/.codeium/windsurf/mcp_config.json):\n\n {\n \"mcpServers\": {\n \"01software\": {\n \"serverUrl\": \"https://mcp.01.software/mcp\"\n }\n }\n }\n\nCLI (stdio):\n\n npx @01.software/cli mcp\n\n\nHTTP OAuth Tools\n----------------\n\nSchema get-collection-schema\nContext get-tenant-context, check-feature-progress\nField Config list-configurable-fields, update-field-config\nGuidance sdk-get-recipe, sdk-search-docs, sdk-get-auth-setup, sdk-get-collection-pattern\n\nFull Tool Surface\n-----------------\n\nThe local CLI stdio transport exposes CRUD, commerce, cart, validation, product,\nschema, context, field-config, and guidance tools:\n\n npx @01.software/cli mcp\n\nPrompts (4): sdk-usage-guide, collection-query-help, order-flow-guide, feature-setup-guide\nResources (12): config, collections-schema, getting-started, guides, api, query-builder, react-query, server-api, customer-auth, browser-vs-server, file-upload, webhook\n\n\nLinks\n-----\n\nIntegrations https://docs.01.software/integrations\nReadiness https://docs.01.software/readiness\nOpenAPI https://docs.01.software/api/openapi\nConsole https://console.01.software\n`\n\nconst PROTECTED_RESOURCE_METADATA = JSON.stringify({\n resource: MCP_RESOURCE_AUDIENCE,\n authorization_servers: [MCP_OAUTH_ISSUER],\n scopes_supported: [MCP_SCOPES.read, MCP_SCOPES.write],\n})\nconst PROTECTED_RESOURCE_METADATA_URL = new URL(\n MCP_PROTECTED_RESOURCE_METADATA_PATH,\n MCP_RESOURCE_AUDIENCE,\n).toString()\nconst SERVICE_JWKS_PATH = '/.well-known/service-jwks.json'\n\nfunction writeOAuthError(\n res: ServerResponse,\n status: number,\n error: string,\n description: string,\n) {\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'WWW-Authenticate': `Bearer resource_metadata=\"${PROTECTED_RESOURCE_METADATA_URL}\", error=\"${error}\", error_description=\"${description}\"`,\n })\n res.end(JSON.stringify({ error, error_description: description }))\n}\n\nfunction acceptsEventStream(req: IncomingMessage): boolean {\n const accept = getHeaderValue(req.headers, 'accept')\n if (!accept) return false\n return accept\n .split(',')\n .some(\n (entry) =>\n entry.trim().split(';')[0]?.toLowerCase() === 'text/event-stream',\n )\n}\n\nexport default async function handler(\n req: IncomingMessage,\n res: ServerResponse,\n) {\n setCors(res)\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method === 'GET') {\n const pathname = new URL(req.url ?? '/', MCP_RESOURCE_AUDIENCE).pathname\n if (pathname === MCP_PROTECTED_RESOURCE_METADATA_PATH) {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(PROTECTED_RESOURCE_METADATA)\n return\n }\n\n if (pathname === SERVICE_JWKS_PATH) {\n res.setHeader('Access-Control-Allow-Origin', '*')\n try {\n res.writeHead(200, {\n 'Cache-Control': 'public, max-age=60',\n 'Content-Type': 'application/json',\n })\n res.end(JSON.stringify(mcpServicePublicJwks()))\n } catch {\n res.writeHead(503, {\n 'Cache-Control': 'no-store',\n 'Content-Type': 'application/json',\n })\n res.end(JSON.stringify({ keys: [] }))\n }\n return\n }\n\n if (acceptsEventStream(req)) {\n res.writeHead(405, { 'Content-Type': 'application/json' })\n res.end(METHOD_NOT_ALLOWED)\n return\n }\n\n res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })\n res.end(HOME_PAGE)\n return\n }\n\n // Stateless Streamable HTTP should only accept POST requests.\n if (req.method !== 'POST') {\n res.writeHead(405, { 'Content-Type': 'application/json' })\n res.end(METHOD_NOT_ALLOWED)\n return\n }\n\n const auth = await validateBearerAuthorizationHeaderAsync(\n getHeaderValue(req.headers, 'authorization'),\n )\n if (!auth.valid) {\n writeOAuthError(\n res,\n auth.error === 'insufficient_scope' ? 403 : 401,\n auth.error,\n auth.errorDescription,\n )\n return\n }\n\n const server = createServer({ toolSurface: 'oauth' })\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n })\n let closed = false\n\n const close = async () => {\n if (closed) return\n closed = true\n await transport.close()\n await server.close()\n }\n\n res.on('close', () => {\n void close()\n })\n\n await server.connect(transport)\n\n const headers = new Headers()\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === 'string') headers.set(key, value)\n else if (Array.isArray(value)) headers.set(key, value.join(', '))\n }\n\n const telemetrySummary = createMcpTelemetrySummary('http')\n\n await requestContext.run({ headers, auth: auth.context }, async () => {\n try {\n await runWithMcpTelemetry(telemetrySummary, async () => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const body = (req as any).body ?? JSON.parse(await readBody(req))\n await transport.handleRequest(req, res, body)\n })\n } catch (err) {\n writeRequestError(res, err)\n } finally {\n telemetrySummary.durationMs = Date.now() - telemetrySummary.startedAtMs\n await close()\n await flushMcpTelemetrySummary(telemetrySummary)\n }\n })\n}\n\nfunction writeRequestError(res: ServerResponse, err: unknown) {\n if (res.headersSent) return\n if (err instanceof SyntaxError) {\n res.writeHead(400, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ error: 'Invalid JSON body' }))\n return\n }\n if (err instanceof Error && err.message === 'Request body too large') {\n res.writeHead(413, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ error: 'Request body too large' }))\n return\n }\n res.writeHead(500, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ error: 'Internal server error' }))\n}\n","import { createPublicKey, verify as verifySignature } from 'node:crypto'\nimport {\n MCP_OAUTH_ISSUER,\n MCP_RESOURCE_AUDIENCE,\n MCP_SCOPES,\n MCP_TENANT_CLAIM,\n MCP_TENANT_ROLE_CLAIM,\n} from '@01.software/auth-contracts'\n\nconst ALLOWED_ALGORITHMS = new Set(['RS256', 'ES256'])\nconst DEFAULT_CLOCK_SKEW_SECONDS = 30\nconst DEFAULT_JWKS_URI = `${MCP_OAUTH_ISSUER}/.well-known/jwks.json`\nconst MAX_ACCESS_TOKEN_LIFETIME_SECONDS = 300\ntype McpScope = (typeof MCP_SCOPES)[keyof typeof MCP_SCOPES]\ntype McpTenantRole = 'tenant-admin' | 'tenant-editor' | 'tenant-viewer'\n\ninterface JwtHeader {\n alg?: unknown\n kid?: unknown\n}\n\ninterface JwtPayload {\n aud?: unknown\n exp?: unknown\n iat?: unknown\n iss?: unknown\n nbf?: unknown\n scope?: unknown\n scp?: unknown\n sub?: unknown\n [MCP_TENANT_CLAIM]?: unknown\n [MCP_TENANT_ROLE_CLAIM]?: unknown\n}\n\nexport interface TenantAuthContext {\n tenantId: string\n principalId?: string\n scopes: McpScope[]\n tenantRole: McpTenantRole\n authMode: 'oauth'\n}\n\nexport type AuthResult =\n | {\n valid: true\n context: TenantAuthContext\n }\n | {\n valid: false\n error: 'invalid_token' | 'insufficient_scope'\n errorDescription: string\n context?: undefined\n }\n\nexport interface JsonWebKeySet {\n keys: Array<Record<string, unknown>>\n}\n\nexport interface ValidateAccessTokenOptions {\n audience?: string\n clockSkewSeconds?: number\n fetchImpl?: typeof fetch\n issuer?: string\n jwks?: JsonWebKeySet\n jwksUri?: string\n now?: Date\n requiredScopes?: McpScope[]\n}\n\nfunction invalid(errorDescription: string): AuthResult {\n return { valid: false, error: 'invalid_token', errorDescription }\n}\n\nfunction isProduction(): boolean {\n return process.env.NODE_ENV === 'production'\n}\n\nfunction insufficientScope(errorDescription: string): AuthResult {\n return { valid: false, error: 'insufficient_scope', errorDescription }\n}\n\nfunction decodeBase64UrlJson<T>(value: string): T | null {\n try {\n return JSON.parse(Buffer.from(value, 'base64url').toString('utf8')) as T\n } catch {\n return null\n }\n}\n\nfunction parseScopes(payload: JwtPayload): McpScope[] {\n const rawScopes =\n typeof payload.scope === 'string'\n ? payload.scope.split(/\\s+/).filter(Boolean)\n : Array.isArray(payload.scp)\n ? payload.scp\n : []\n\n return rawScopes.filter(\n (scope): scope is McpScope =>\n scope === MCP_SCOPES.read || scope === MCP_SCOPES.write,\n )\n}\n\nfunction audienceMatches(aud: unknown, expected: string): boolean {\n if (typeof aud === 'string') return aud === expected\n return Array.isArray(aud) && aud.includes(expected)\n}\n\nfunction verifyJwtSignature(\n alg: string,\n jwk: Record<string, unknown>,\n signingInput: string,\n signature: Buffer,\n): boolean {\n const key = createPublicKey({ key: jwk, format: 'jwk' })\n const input = Buffer.from(signingInput)\n\n if (alg === 'RS256') {\n return verifySignature('RSA-SHA256', input, key, signature)\n }\n\n if (alg === 'ES256') {\n return verifySignature('SHA256', input, { key, dsaEncoding: 'ieee-p1363' }, signature)\n }\n\n return false\n}\n\nlet cachedRemoteJwks:\n | { expiresAt: number; jwks: JsonWebKeySet; uri: string }\n | null = null\n\nfunction jwksUriFor(options: ValidateAccessTokenOptions): string | null {\n const raw = isProduction()\n ? DEFAULT_JWKS_URI\n : options.jwksUri ?? DEFAULT_JWKS_URI\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n return null\n }\n if (\n url.protocol !== 'https:' ||\n url.username ||\n url.password ||\n url.search ||\n url.hash\n ) {\n return null\n }\n return url.toString()\n}\n\nasync function remoteJwks(\n options: ValidateAccessTokenOptions = {},\n forceRefresh = false,\n): Promise<JsonWebKeySet | null> {\n const uri = jwksUriFor(options)\n if (!uri) return null\n const now = Date.now()\n if (\n !forceRefresh &&\n cachedRemoteJwks &&\n cachedRemoteJwks.uri === uri &&\n cachedRemoteJwks.expiresAt > now\n ) {\n return cachedRemoteJwks.jwks\n }\n\n const fetchImpl = options.fetchImpl ?? fetch\n let response: Response\n try {\n response = await fetchImpl(uri, {\n headers: { Accept: 'application/json' },\n })\n } catch {\n return null\n }\n if (!response.ok) return null\n const parsed = (await response.json().catch(() => null)) as JsonWebKeySet | null\n if (!parsed || !Array.isArray(parsed.keys)) return null\n cachedRemoteJwks = {\n expiresAt: now + 300_000,\n jwks: parsed,\n uri,\n }\n return parsed\n}\n\nexport function validateAccessToken(\n token: string,\n options: ValidateAccessTokenOptions = {},\n): AuthResult {\n const parts = token.split('.')\n if (parts.length !== 3 || parts.some((part) => part.length === 0)) {\n return invalid('Bearer token must be a compact JWT')\n }\n\n const [encodedHeader, encodedPayload, encodedSignature] = parts\n const header = decodeBase64UrlJson<JwtHeader>(encodedHeader)\n const payload = decodeBase64UrlJson<JwtPayload>(encodedPayload)\n if (!header || !payload) return invalid('Bearer token contains invalid JSON')\n\n if (typeof header.alg !== 'string' || !ALLOWED_ALGORITHMS.has(header.alg)) {\n return invalid('Bearer token uses an unsupported signing algorithm')\n }\n\n if (typeof header.kid !== 'string' || header.kid.length === 0) {\n return invalid('Bearer token is missing kid')\n }\n\n const jwks = options.jwks\n if (!jwks) return invalid('JWKS is not configured')\n\n const jwk = jwks.keys.find((key) => key.kid === header.kid)\n if (!jwk) return invalid('Bearer token kid is unknown')\n\n const signingInput = `${encodedHeader}.${encodedPayload}`\n const signature = Buffer.from(encodedSignature, 'base64url')\n if (!verifyJwtSignature(header.alg, jwk, signingInput, signature)) {\n return invalid('Bearer token signature is invalid')\n }\n\n const issuer = options.issuer ?? MCP_OAUTH_ISSUER\n if (payload.iss !== issuer) return invalid('Bearer token issuer is invalid')\n\n const audience = options.audience ?? MCP_RESOURCE_AUDIENCE\n if (!audienceMatches(payload.aud, audience)) {\n return invalid('Bearer token audience is invalid')\n }\n\n if (typeof payload.iat !== 'number') return invalid('Bearer token is missing iat')\n if (typeof payload.exp !== 'number') return invalid('Bearer token is missing exp')\n if (payload.exp <= payload.iat) {\n return invalid('Bearer token lifetime is invalid')\n }\n if (payload.exp - payload.iat > MAX_ACCESS_TOKEN_LIFETIME_SECONDS) {\n return invalid('Bearer token lifetime exceeds 300 seconds')\n }\n\n const nowSeconds = Math.floor((options.now ?? new Date()).getTime() / 1000)\n const leeway = options.clockSkewSeconds ?? DEFAULT_CLOCK_SKEW_SECONDS\n if (payload.iat > nowSeconds + leeway) {\n return invalid('Bearer token iat is too far in the future')\n }\n if (typeof payload.nbf === 'number' && payload.nbf > nowSeconds + leeway) {\n return invalid('Bearer token is not yet valid')\n }\n if (payload.exp < nowSeconds - leeway) return invalid('Bearer token is expired')\n\n const tenantId = payload[MCP_TENANT_CLAIM]\n if (typeof tenantId !== 'string' || tenantId.length === 0) {\n return invalid('Bearer token tenant_id claim is invalid')\n }\n\n const tenantRole = payload[MCP_TENANT_ROLE_CLAIM]\n if (\n tenantRole !== 'tenant-admin' &&\n tenantRole !== 'tenant-editor' &&\n tenantRole !== 'tenant-viewer'\n ) {\n return invalid('Bearer token tenant_role claim is invalid')\n }\n\n if (typeof payload.sub !== 'string' || payload.sub.length === 0) {\n return invalid('Bearer token subject claim is invalid')\n }\n\n const scopes = parseScopes(payload)\n const requiredScopes = options.requiredScopes ?? [MCP_SCOPES.read]\n const missingScope = requiredScopes.find((scope) => !scopes.includes(scope))\n if (missingScope) return insufficientScope(`Bearer token is missing ${missingScope}`)\n\n return {\n valid: true,\n context: {\n tenantId,\n principalId: payload.sub,\n scopes,\n tenantRole,\n authMode: 'oauth',\n },\n }\n}\n\nexport function validateBearerAuthorizationHeader(\n authorization: string | null | undefined,\n options?: ValidateAccessTokenOptions,\n): AuthResult {\n if (!authorization) return invalid('Authorization Bearer token is required')\n\n const match = authorization.match(/^Bearer\\s+(.+)$/i)\n if (!match) return invalid('Authorization header must use Bearer')\n\n return validateAccessToken(match[1], options)\n}\n\nfunction shouldRefreshRemoteJwks(result: AuthResult): boolean {\n return (\n !result.valid &&\n (\n result.errorDescription === 'Bearer token kid is unknown' ||\n result.errorDescription === 'Bearer token signature is invalid'\n )\n )\n}\n\nexport async function validateBearerAuthorizationHeaderAsync(\n authorization: string | null | undefined,\n options?: ValidateAccessTokenOptions,\n): Promise<AuthResult> {\n if (!authorization) return invalid('Authorization Bearer token is required')\n\n const match = authorization.match(/^Bearer\\s+(.+)$/i)\n if (!match) return invalid('Authorization header must use Bearer')\n\n if (options?.jwks) {\n return validateAccessToken(match[1], options)\n }\n\n const jwks = await remoteJwks(options)\n const result = validateAccessToken(match[1], {\n ...options,\n jwks: jwks ?? undefined,\n })\n\n if (shouldRefreshRemoteJwks(result)) {\n const refreshedJwks = await remoteJwks(options, true)\n if (refreshedJwks) {\n return validateAccessToken(match[1], {\n ...options,\n jwks: refreshedJwks,\n })\n }\n }\n\n return result\n}\n"],"mappings":"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","names":["createServer","createServer"]}
|