@01.software/cli 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +205 -28
- package/dist/index.js.map +1 -1
- package/dist/mcp/{chunk-GJOQ4SE2.js → chunk-CADO6WG6.js} +657 -391
- package/dist/mcp/chunk-CADO6WG6.js.map +1 -0
- package/dist/mcp/http.js +30 -8
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/stdio.js +1 -1
- package/dist/mcp/vercel.js +678 -396
- package/package.json +2 -2
- 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-CADO6WG6.js";
|
|
12
15
|
|
|
13
16
|
// src/transport/http.ts
|
|
14
17
|
import { createServer as createServer2 } from "http";
|
|
@@ -316,9 +319,9 @@ Resources (12): config, collections-schema, getting-started, guides, api, query-
|
|
|
316
319
|
Links
|
|
317
320
|
-----
|
|
318
321
|
|
|
319
|
-
Docs https://01.software/docs/integrations/mcp
|
|
320
|
-
SDK https://01.software/docs/sdk/client
|
|
321
|
-
API Reference https://01.software/docs/api/rest-api
|
|
322
|
+
Docs https://docs.01.software/docs/developers/integrations/mcp
|
|
323
|
+
SDK https://docs.01.software/docs/developers/sdk/client
|
|
324
|
+
API Reference https://docs.01.software/docs/developers/api/rest-api
|
|
322
325
|
Console https://console.01.software
|
|
323
326
|
`;
|
|
324
327
|
var PROTECTED_RESOURCE_METADATA = JSON.stringify({
|
|
@@ -326,14 +329,23 @@ var PROTECTED_RESOURCE_METADATA = JSON.stringify({
|
|
|
326
329
|
authorization_servers: [MCP_OAUTH_ISSUER],
|
|
327
330
|
scopes_supported: [MCP_SCOPES.read, MCP_SCOPES.write]
|
|
328
331
|
});
|
|
332
|
+
var PROTECTED_RESOURCE_METADATA_URL = new URL(
|
|
333
|
+
MCP_PROTECTED_RESOURCE_METADATA_PATH,
|
|
334
|
+
MCP_RESOURCE_AUDIENCE
|
|
335
|
+
).toString();
|
|
329
336
|
var SERVICE_JWKS_PATH = "/.well-known/service-jwks.json";
|
|
330
337
|
function writeOAuthError(res, status, error, description) {
|
|
331
338
|
res.writeHead(status, {
|
|
332
339
|
"Content-Type": "application/json",
|
|
333
|
-
"WWW-Authenticate": `Bearer resource_metadata="${
|
|
340
|
+
"WWW-Authenticate": `Bearer resource_metadata="${PROTECTED_RESOURCE_METADATA_URL}", error="${error}", error_description="${description}"`
|
|
334
341
|
});
|
|
335
342
|
res.end(JSON.stringify({ error, error_description: description }));
|
|
336
343
|
}
|
|
344
|
+
function acceptsEventStream(req) {
|
|
345
|
+
const accept = getHeaderValue(req.headers, "accept");
|
|
346
|
+
if (!accept) return false;
|
|
347
|
+
return accept.split(",").some((entry) => entry.trim().split(";")[0]?.toLowerCase() === "text/event-stream");
|
|
348
|
+
}
|
|
337
349
|
async function handler(req, res) {
|
|
338
350
|
setCors(res);
|
|
339
351
|
if (req.method === "OPTIONS") {
|
|
@@ -366,6 +378,11 @@ async function handler(req, res) {
|
|
|
366
378
|
}
|
|
367
379
|
return;
|
|
368
380
|
}
|
|
381
|
+
if (acceptsEventStream(req)) {
|
|
382
|
+
res.writeHead(405, { "Content-Type": "application/json" });
|
|
383
|
+
res.end(METHOD_NOT_ALLOWED);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
369
386
|
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
|
|
370
387
|
res.end(HOME_PAGE);
|
|
371
388
|
return;
|
|
@@ -402,14 +419,19 @@ async function handler(req, res) {
|
|
|
402
419
|
if (typeof value === "string") headers.set(key, value);
|
|
403
420
|
else if (Array.isArray(value)) headers.set(key, value.join(", "));
|
|
404
421
|
}
|
|
422
|
+
const telemetrySummary = createMcpTelemetrySummary("http");
|
|
405
423
|
await requestContext.run({ headers, auth: auth.context }, async () => {
|
|
406
424
|
try {
|
|
407
|
-
|
|
408
|
-
|
|
425
|
+
await runWithMcpTelemetry(telemetrySummary, async () => {
|
|
426
|
+
const body = req.body ?? JSON.parse(await readBody(req));
|
|
427
|
+
await transport.handleRequest(req, res, body);
|
|
428
|
+
});
|
|
409
429
|
} catch (err) {
|
|
410
430
|
writeRequestError(res, err);
|
|
411
431
|
} finally {
|
|
432
|
+
telemetrySummary.durationMs = Date.now() - telemetrySummary.startedAtMs;
|
|
412
433
|
await close();
|
|
434
|
+
await flushMcpTelemetrySummary(telemetrySummary);
|
|
413
435
|
}
|
|
414
436
|
});
|
|
415
437
|
}
|
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('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://docs.01.software/docs/developers/integrations/mcp\nSDK https://docs.01.software/docs/developers/sdk/client\nAPI Reference https://docs.01.software/docs/developers/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 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(res: ServerResponse, status: number, error: string, description: string) {\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((entry) => entry.trim().split(';')[0]?.toLowerCase() === 'text/event-stream')\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 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(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 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 =\n 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"]}
|