@pasteapp/mcp
Advanced tools
| // Identify which AI tool spawned the bridge so Paste's `Client.Kind.inferred` | ||
| // can pick the right icon and label in the MCP & AI Tools list. Walks the | ||
| // parent-process tree via `ps`, stepping past shell/node/npx wrappers, and | ||
| // matches the first ancestor whose argv mentions a known AI tool. Falls back | ||
| // to the npm package slug when nothing matches. | ||
| // | ||
| // The returned name MUST contain a substring that Paste's Swift | ||
| // `Client.Kind.inferred(fromClientName:)` recognizes — "claude code", | ||
| // "claude", "cursor", "codex", "windsurf", "vscode"/"vs code" — otherwise | ||
| // the client lands as `.custom` with the slug below as its display name. | ||
| // (OpenCode is detected here so it shows up labeled, but Paste still maps | ||
| // it to `.custom` until the Swift side gains a case for it.) | ||
| import { execFile } from 'node:child_process'; | ||
| import { promisify } from 'node:util'; | ||
| const execFileAsync = promisify(execFile); | ||
| const DEFAULT_NAME = '@pasteapp/mcp'; | ||
| // More specific first — `Claude Code` must be tested before `Claude Desktop` | ||
| // because the Code CLI's argv also contains the substring "claude". | ||
| const CLIENT_PATTERNS = [ | ||
| { pattern: /@anthropic-ai\/claude-code|\.claude\/local\/.*\bclaude\b|\bclaude\b[^ ]*cli/i, name: 'Claude Code' }, | ||
| { pattern: /Claude\.app\b/, name: 'Claude Desktop' }, | ||
| { pattern: /Cursor\.app\b/, name: 'Cursor' }, | ||
| { pattern: /Windsurf\.app\b/i, name: 'Windsurf' }, | ||
| { pattern: /Visual Studio Code\.app\b|\/Code\.app\b/i, name: 'VS Code' }, | ||
| { pattern: /@openai\/codex|\bcodex\b/i, name: 'Codex' }, | ||
| { pattern: /\bopencode\b/i, name: 'OpenCode' }, | ||
| ]; | ||
| // Processes we step past when walking up — they're shell/runtime wrappers, | ||
| // not the actual host. Matched only AFTER the client patterns fail. | ||
| const WRAPPER_PATTERNS = [ | ||
| /\bnpx\b/, | ||
| /\bnode\b/, | ||
| /\bsh\b|\bbash\b|\bzsh\b|\bfish\b/, | ||
| ]; | ||
| async function defaultReadProcessArgs(pid) { | ||
| try { | ||
| const { stdout } = await execFileAsync('/bin/ps', ['-p', String(pid), '-o', 'ppid=,args='], { timeout: 500 }); | ||
| const match = stdout.trim().match(/^\s*(\d+)\s+(.+)$/); | ||
| if (!match) | ||
| return null; | ||
| return { ppid: Number.parseInt(match[1], 10), args: match[2] }; | ||
| } | ||
| catch { | ||
| return null; | ||
| } | ||
| } | ||
| function matchClient(args) { | ||
| for (const { pattern, name } of CLIENT_PATTERNS) { | ||
| if (pattern.test(args)) | ||
| return name; | ||
| } | ||
| return null; | ||
| } | ||
| function isWrapper(args) { | ||
| return WRAPPER_PATTERNS.some((p) => p.test(args)); | ||
| } | ||
| export async function detectClientName(opts = {}) { | ||
| const read = opts.readProcessArgs ?? defaultReadProcessArgs; | ||
| let pid = opts.startPid ?? process.ppid; | ||
| for (let i = 0; i < 8; i++) { | ||
| const result = await read(pid); | ||
| if (!result) | ||
| break; | ||
| const matched = matchClient(result.args); | ||
| if (matched) | ||
| return matched; | ||
| // Stop the moment we hit a non-wrapper we don't recognize — going past it | ||
| // would just walk into the user's shell / WindowServer / launchd. | ||
| if (!isWrapper(result.args)) | ||
| break; | ||
| if (result.ppid <= 1 || result.ppid === pid) | ||
| break; | ||
| pid = result.ppid; | ||
| } | ||
| return DEFAULT_NAME; | ||
| } | ||
| //# sourceMappingURL=client-name.js.map |
| {"version":3,"file":"client-name.js","sourceRoot":"","sources":["../src/client-name.ts"],"names":[],"mappings":"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"} |
@@ -11,4 +11,7 @@ // Local HTTP listener that catches the OAuth authorization-code redirect. | ||
| // embed it in the `/authorize` request. | ||
| import { randomBytes } from 'node:crypto'; | ||
| import { createServer } from 'node:http'; | ||
| import { generateState } from './pkce.js'; | ||
| function generateState() { | ||
| return randomBytes(16).toString('base64url'); | ||
| } | ||
| const PAGE_HTML = '<!doctype html>' | ||
@@ -15,0 +18,0 @@ + '<html lang="en"><head><meta charset="utf-8"><title>Paste connected</title>' |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"callback.js","sourceRoot":"","sources":["../../src/oauth/callback.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"callback.js","sourceRoot":"","sources":["../../src/oauth/callback.ts"],"names":[],"mappings":"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"} |
+151
-137
@@ -1,64 +0,73 @@ | ||
| // OAuth client for Paste's loopback MCP server. Implements the canonical MCP | ||
| // authorization dance: RFC 9728 protected-resource metadata → RFC 8414 auth | ||
| // server metadata → RFC 7591 dynamic client registration → authorization code | ||
| // + PKCE → token exchange. Tokens cached on disk between invocations. | ||
| // OAuth client for Paste's loopback MCP server, built on the official | ||
| // `@modelcontextprotocol/sdk` `auth()` function. The SDK handles metadata | ||
| // discovery (RFC 9728 protected-resource + RFC 8414 + OIDC fallback), | ||
| // dynamic client registration (RFC 7591), PKCE generation/verification, | ||
| // the `resource` indicator (RFC 8707), token exchange, and refresh-token | ||
| // rotation. We provide the storage backing and the side effects (open | ||
| // browser, wait on the loopback callback). | ||
| import { spawn } from 'node:child_process'; | ||
| import { auth, } from '@modelcontextprotocol/sdk/client/auth.js'; | ||
| import { detectClientName } from '../client-name.js'; | ||
| import { startCallbackServer } from './callback.js'; | ||
| import { generatePKCE } from './pkce.js'; | ||
| import { TokenStore } from './store.js'; | ||
| const CLIENT_NAME = 'Paste MCP Bridge'; | ||
| const TOKEN_ERROR_BODY_CAP = 500; | ||
| export class OAuthClient { | ||
| serverURL; | ||
| store; | ||
| opts; | ||
| fetchImpl; | ||
| openBrowserImpl; | ||
| startCallbackServerImpl; | ||
| nowImpl; | ||
| constructor(serverURL, store = new TokenStore(), opts = {}) { | ||
| this.serverURL = serverURL; | ||
| this.store = store; | ||
| this.opts = opts; | ||
| this.fetchImpl = opts.fetch ?? fetch; | ||
| this.openBrowserImpl = opts.openBrowser ?? defaultOpenBrowser; | ||
| this.startCallbackServerImpl = opts.startCallbackServer ?? startCallbackServer; | ||
| this.nowImpl = opts.now ?? (() => new Date()); | ||
| } | ||
| async accessToken() { | ||
| const cached = await this.store.load(); | ||
| if (cached && cached.accessToken && cached.serverURL === this.serverURL.toString() && !this.isExpired(cached)) { | ||
| return cached.accessToken; | ||
| if (cached && cached.serverURL === this.serverURL.toString() && cached.tokens?.access_token) { | ||
| // Short-circuit: Paste issues long-lived access tokens without | ||
| // refresh_tokens, so SDK's `auth()` would always fall through to a | ||
| // fresh authorization. The bridge's transport will call `invalidate()` | ||
| // on 401 if the token actually went stale. | ||
| return cached.tokens.access_token; | ||
| } | ||
| return await this.runFlow(); | ||
| } | ||
| async invalidate() { | ||
| await this.store.clear(); | ||
| } | ||
| isExpired(token) { | ||
| if (token.expiresAt === null) | ||
| return false; | ||
| const expiresAt = Date.parse(token.expiresAt); | ||
| if (!Number.isFinite(expiresAt)) | ||
| return false; | ||
| // 30-second skew so we don't hand out a token that's about to die in flight. | ||
| return expiresAt <= this.nowImpl().getTime() + 30_000; | ||
| } | ||
| async runFlow() { | ||
| const metadata = await discoverAuthServer(this.serverURL, this.fetchImpl); | ||
| // Different server URL (port changed, channel switched) → drop the cache. | ||
| if (cached && cached.serverURL !== this.serverURL.toString()) { | ||
| await this.store.clear(); | ||
| } | ||
| const callback = await this.startCallbackServerImpl(); | ||
| const redirectUri = `http://127.0.0.1:${callback.port}/cb`; | ||
| const provider = new BridgeProvider({ | ||
| serverURL: this.serverURL.toString(), | ||
| redirectUrl: `http://127.0.0.1:${callback.port}/cb`, | ||
| state: callback.state, | ||
| store: this.store, | ||
| openBrowser: this.openBrowserImpl, | ||
| clientName: await this.resolveClientName(), | ||
| }); | ||
| try { | ||
| const clientId = await registerClient(metadata, redirectUri, this.fetchImpl); | ||
| const { accessToken, expiresIn } = await this.authorize(metadata, clientId, redirectUri, callback); | ||
| const expiresAt = expiresIn != null | ||
| ? new Date(this.nowImpl().getTime() + expiresIn * 1_000).toISOString() | ||
| : null; | ||
| const stored = { | ||
| serverURL: this.serverURL.toString(), | ||
| clientId, | ||
| accessToken, | ||
| expiresAt, | ||
| createdAt: this.nowImpl().toISOString(), | ||
| }; | ||
| await this.store.save(stored); | ||
| return accessToken; | ||
| const first = await auth(provider, { | ||
| serverUrl: this.serverURL, | ||
| fetchFn: this.fetchImpl, | ||
| }); | ||
| if (first === 'AUTHORIZED') | ||
| return await readToken(provider); | ||
| const cb = await callback.waitForCallback(); | ||
| if (cb.error) { | ||
| const detail = cb.errorDescription ? ` — ${cb.errorDescription}` : ''; | ||
| throw new Error(`OAuth error: ${cb.error}${detail}`); | ||
| } | ||
| if (!cb.code) | ||
| throw new Error('OAuth callback missing `code`'); | ||
| const second = await auth(provider, { | ||
| serverUrl: this.serverURL, | ||
| authorizationCode: cb.code, | ||
| fetchFn: this.fetchImpl, | ||
| }); | ||
| if (second !== 'AUTHORIZED') { | ||
| throw new Error(`OAuth handshake did not authorize (returned ${second})`); | ||
| } | ||
| return await readToken(provider); | ||
| } | ||
@@ -69,101 +78,111 @@ finally { | ||
| } | ||
| async authorize(metadata, clientId, redirectUri, callback) { | ||
| const pkce = generatePKCE(); | ||
| await this.openBrowserImpl(buildAuthURL(metadata, clientId, redirectUri, pkce.challenge, callback.state)); | ||
| const result = await callback.waitForCallback(); | ||
| if (result.error) { | ||
| const detail = result.errorDescription ? ` — ${result.errorDescription}` : ''; | ||
| throw new Error(`OAuth error: ${result.error}${detail}`); | ||
| } | ||
| if (!result.code) | ||
| throw new Error('OAuth callback missing `code`'); | ||
| // Belt-and-braces: CallbackServer enforces state too, but a mismatch here | ||
| // means the callback contract drifted — fail loud rather than proceed. | ||
| if (result.state !== callback.state) | ||
| throw new Error('OAuth state mismatch'); | ||
| return await exchangeCode(metadata, clientId, result.code, redirectUri, pkce.verifier, this.fetchImpl); | ||
| async invalidate() { | ||
| await this.store.clear(); | ||
| } | ||
| async resolveClientName() { | ||
| const override = this.opts.clientName; | ||
| if (typeof override === 'string') | ||
| return override; | ||
| if (typeof override === 'function') | ||
| return await override(); | ||
| return await detectClientName(); | ||
| } | ||
| } | ||
| async function discoverAuthServer(serverURL, fetchImpl) { | ||
| const origin = serverURL.origin; | ||
| let authBase = origin; | ||
| try { | ||
| const meta = await fetchJSON(`${origin}/.well-known/oauth-protected-resource`, fetchImpl); | ||
| const first = meta.authorization_servers?.[0]; | ||
| if (first) | ||
| authBase = first.replace(/\/$/, ''); | ||
| async function readToken(provider) { | ||
| const tokens = await provider.tokens(); | ||
| if (!tokens?.access_token) | ||
| throw new Error('OAuth flow completed but no access token was returned'); | ||
| return tokens.access_token; | ||
| } | ||
| class BridgeProvider { | ||
| opts; | ||
| constructor(opts) { | ||
| this.opts = opts; | ||
| } | ||
| catch { | ||
| // Resource metadata is optional per the spec — fall back to assuming the | ||
| // server is its own authorization server (Paste's setup). | ||
| get redirectUrl() { | ||
| return this.opts.redirectUrl; | ||
| } | ||
| const metadata = await fetchJSON(`${authBase}/.well-known/oauth-authorization-server`, fetchImpl); | ||
| if (typeof metadata.authorization_endpoint !== 'string' | ||
| || typeof metadata.token_endpoint !== 'string' | ||
| || typeof metadata.registration_endpoint !== 'string') { | ||
| throw new Error('Authorization server metadata is missing required endpoints'); | ||
| } | ||
| return metadata; | ||
| } | ||
| async function registerClient(metadata, redirectUri, fetchImpl) { | ||
| const response = await fetchImpl(metadata.registration_endpoint, { | ||
| method: 'POST', | ||
| headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, | ||
| body: JSON.stringify({ | ||
| client_name: CLIENT_NAME, | ||
| redirect_uris: [redirectUri], | ||
| get clientMetadata() { | ||
| return { | ||
| client_name: this.opts.clientName, | ||
| redirect_uris: [this.opts.redirectUrl], | ||
| token_endpoint_auth_method: 'none', | ||
| grant_types: ['authorization_code'], | ||
| grant_types: ['authorization_code', 'refresh_token'], | ||
| response_types: ['code'], | ||
| }), | ||
| }); | ||
| if (!response.ok) { | ||
| throw new Error(`Dynamic client registration failed: HTTP ${response.status}`); | ||
| }; | ||
| } | ||
| const data = (await response.json()); | ||
| if (typeof data.client_id !== 'string' || data.client_id.length === 0) { | ||
| throw new Error('Dynamic client registration response missing `client_id`'); | ||
| // Per-flow state for CSRF defense. Our callback server validates this on | ||
| // its side too — defense in depth. | ||
| state() { | ||
| return this.opts.state; | ||
| } | ||
| return data.client_id; | ||
| } | ||
| async function exchangeCode(metadata, clientId, code, redirectUri, verifier, fetchImpl) { | ||
| const body = new URLSearchParams({ | ||
| grant_type: 'authorization_code', | ||
| code, | ||
| redirect_uri: redirectUri, | ||
| client_id: clientId, | ||
| code_verifier: verifier, | ||
| }).toString(); | ||
| const response = await fetchImpl(metadata.token_endpoint, { | ||
| method: 'POST', | ||
| headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json' }, | ||
| body, | ||
| }); | ||
| if (!response.ok) { | ||
| // Capping the error body keeps verifier/code material out of stderr if | ||
| // the AS ever echoes them back in a regression. | ||
| const detail = (await response.text()).slice(0, TOKEN_ERROR_BODY_CAP); | ||
| throw new Error(`Token exchange failed: HTTP ${response.status}: ${detail}`); | ||
| async clientInformation() { | ||
| return (await this.loadCache()).clientInformation; | ||
| } | ||
| const data = (await response.json()); | ||
| if (typeof data.access_token !== 'string' || data.access_token.length === 0) { | ||
| throw new Error('Token response missing `access_token`'); | ||
| async saveClientInformation(info) { | ||
| await this.mergeCache({ clientInformation: info }); | ||
| } | ||
| return { | ||
| accessToken: data.access_token, | ||
| ...(typeof data.expires_in === 'number' && data.expires_in > 0 | ||
| ? { expiresIn: data.expires_in } | ||
| : {}), | ||
| }; | ||
| async tokens() { | ||
| return (await this.loadCache()).tokens; | ||
| } | ||
| async saveTokens(tokens) { | ||
| // The verifier is single-use; once tokens land we don't need it on disk. | ||
| const cached = await this.loadCache(); | ||
| const next = { | ||
| serverURL: this.opts.serverURL, | ||
| tokens, | ||
| ...(cached.clientInformation ? { clientInformation: cached.clientInformation } : {}), | ||
| }; | ||
| await this.opts.store.save(next); | ||
| } | ||
| async saveCodeVerifier(verifier) { | ||
| await this.mergeCache({ codeVerifier: verifier }); | ||
| } | ||
| async codeVerifier() { | ||
| const cached = await this.loadCache(); | ||
| if (!cached.codeVerifier) { | ||
| throw new Error('No PKCE code verifier in cache — OAuth state was cleared between auth() calls'); | ||
| } | ||
| return cached.codeVerifier; | ||
| } | ||
| async redirectToAuthorization(authorizationUrl) { | ||
| // Enforced here (not just in defaultOpenBrowser) so an injected opener | ||
| // can't bypass the guard. The AS-supplied `authorization_endpoint` is | ||
| // attacker-influenceable if the discovered port has been hijacked. | ||
| assertLoopbackHTTPURL(authorizationUrl.toString()); | ||
| await this.opts.openBrowser(authorizationUrl.toString()); | ||
| } | ||
| async invalidateCredentials(scope) { | ||
| if (scope === 'all') { | ||
| await this.opts.store.clear(); | ||
| return; | ||
| } | ||
| const cached = await this.opts.store.load(); | ||
| if (!cached) | ||
| return; | ||
| const next = { ...cached }; | ||
| if (scope === 'client') | ||
| delete next.clientInformation; | ||
| if (scope === 'tokens') | ||
| delete next.tokens; | ||
| if (scope === 'verifier') | ||
| delete next.codeVerifier; | ||
| // 'discovery' — we don't cache discovery state, nothing to do. | ||
| await this.opts.store.save(next); | ||
| } | ||
| async loadCache() { | ||
| const stored = await this.opts.store.load(); | ||
| // Cache must belong to the server we were constructed for. A stale entry | ||
| // for a different server gets dropped here rather than overwritten — the | ||
| // alternative (always stamping `serverURL: this.opts.serverURL` on save) | ||
| // would silently graft another server's tokens onto our cache. | ||
| if (stored && stored.serverURL === this.opts.serverURL) | ||
| return stored; | ||
| return { serverURL: this.opts.serverURL }; | ||
| } | ||
| async mergeCache(patch) { | ||
| const cached = await this.loadCache(); | ||
| await this.opts.store.save({ ...cached, ...patch, serverURL: this.opts.serverURL }); | ||
| } | ||
| } | ||
| function buildAuthURL(metadata, clientId, redirectUri, challenge, state) { | ||
| const url = new URL(metadata.authorization_endpoint); | ||
| url.searchParams.set('response_type', 'code'); | ||
| url.searchParams.set('client_id', clientId); | ||
| url.searchParams.set('redirect_uri', redirectUri); | ||
| url.searchParams.set('code_challenge', challenge); | ||
| url.searchParams.set('code_challenge_method', 'S256'); | ||
| url.searchParams.set('state', state); | ||
| return url.toString(); | ||
| } | ||
| // Refuse to launch anything but an HTTP(S) URL pointing at loopback. An | ||
@@ -184,3 +203,4 @@ // attacker who took over the discovered port could otherwise feed us an | ||
| function defaultOpenBrowser(url) { | ||
| assertLoopbackHTTPURL(url); | ||
| // URL guard lives in BridgeProvider.redirectToAuthorization so an injected | ||
| // opener can't bypass it; here we just spawn `/usr/bin/open`. | ||
| const child = spawn('/usr/bin/open', [url], { stdio: 'ignore', detached: true }); | ||
@@ -193,8 +213,2 @@ // Without this listener, a missing `/usr/bin/open` (non-macOS) would crash | ||
| } | ||
| async function fetchJSON(url, fetchImpl, init) { | ||
| const response = await fetchImpl(url, init); | ||
| if (!response.ok) | ||
| throw new Error(`HTTP ${response.status} fetching ${url}`); | ||
| return (await response.json()); | ||
| } | ||
| //# sourceMappingURL=client.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/oauth/client.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/oauth/client.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,0EAA0E;AAC1E,sEAAsE;AACtE,wEAAwE;AACxE,yEAAyE;AACzE,sEAAsE;AACtE,2CAA2C;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EACL,IAAI,GAEL,MAAM,0CAA0C,CAAC;AAMlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAuB,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,UAAU,EAAyB,MAAM,YAAY,CAAC;AAc/D,MAAM,OAAO,WAAW;IAMJ;IACC;IACA;IAPF,SAAS,CAAe;IACxB,eAAe,CAAc;IAC7B,uBAAuB,CAAsB;IAE9D,YACkB,SAAc,EACb,QAAoB,IAAI,UAAU,EAAE,EACpC,OAA2B,EAAE;QAF9B,cAAS,GAAT,SAAS,CAAK;QACb,UAAK,GAAL,KAAK,CAA+B;QACpC,SAAI,GAAJ,IAAI,CAAyB;QAE9C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC;QACrC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,WAAW,IAAI,kBAAkB,CAAC;QAC9D,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,mBAAmB,IAAI,mBAAmB,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACvC,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC;YAC5F,+DAA+D;YAC/D,mEAAmE;YACnE,uEAAuE;YACvE,2CAA2C;YAC3C,OAAO,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;QACpC,CAAC;QACD,0EAA0E;QAC1E,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC7D,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3B,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACtD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC;YAClC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE;YACpC,WAAW,EAAE,oBAAoB,QAAQ,CAAC,IAAI,KAAK;YACnD,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,eAAe;YACjC,UAAU,EAAE,MAAM,IAAI,CAAC,iBAAiB,EAAE;SAC3C,CAAC,CAAC;QACH,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;gBACjC,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,OAAO,EAAE,IAAI,CAAC,SAAS;aACxB,CAAC,CAAC;YACH,IAAI,KAAK,KAAK,YAAY;gBAAE,OAAO,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;YAE7D,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,eAAe,EAAE,CAAC;YAC5C,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;gBACb,MAAM,MAAM,GAAG,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtE,MAAM,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC,KAAK,GAAG,MAAM,EAAE,CAAC,CAAC;YACvD,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAE/D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;gBAClC,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,iBAAiB,EAAE,EAAE,CAAC,IAAI;gBAC1B,OAAO,EAAE,IAAI,CAAC,SAAS;aACxB,CAAC,CAAC;YACH,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,+CAA+C,MAAM,GAAG,CAAC,CAAC;YAC5E,CAAC;YACD,OAAO,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC;gBAAS,CAAC;YACT,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QACtC,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAClD,IAAI,OAAO,QAAQ,KAAK,UAAU;YAAE,OAAO,MAAM,QAAQ,EAAE,CAAC;QAC5D,OAAO,MAAM,gBAAgB,EAAE,CAAC;IAClC,CAAC;CACF;AAED,KAAK,UAAU,SAAS,CAAC,QAA6B;IACpD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;IACvC,IAAI,CAAC,MAAM,EAAE,YAAY;QAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IACpG,OAAO,MAAM,CAAC,YAAY,CAAC;AAC7B,CAAC;AAWD,MAAM,cAAc;IACW;IAA7B,YAA6B,IAA2B;QAA3B,SAAI,GAAJ,IAAI,CAAuB;IAAG,CAAC;IAE5D,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;IAC/B,CAAC;IAED,IAAI,cAAc;QAChB,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU;YACjC,aAAa,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;YACtC,0BAA0B,EAAE,MAAM;YAClC,WAAW,EAAE,CAAC,oBAAoB,EAAE,eAAe,CAAC;YACpD,cAAc,EAAE,CAAC,MAAM,CAAC;SACzB,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,mCAAmC;IACnC,KAAK;QACH,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,iBAAiB,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,IAAiC;QAC3D,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,MAAM;QACV,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAmB;QAClC,yEAAyE;QACzE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,MAAM,IAAI,GAAqB;YAC7B,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS;YAC9B,MAAM;YACN,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACrF,CAAC;QACF,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QACrC,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC;QACnG,CAAC;QACD,OAAO,MAAM,CAAC,YAAY,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,gBAAqB;QACjD,uEAAuE;QACvE,sEAAsE;QACtE,mEAAmE;QACnE,qBAAqB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnD,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,KAA6D;QACvF,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;YACpB,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,IAAI,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,iBAAiB,CAAC;QACtD,IAAI,KAAK,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC;QAC3C,IAAI,KAAK,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC;QACnD,+DAA+D;QAC/D,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC5C,yEAAyE;QACzE,yEAAyE;QACzE,yEAAyE;QACzE,+DAA+D;QAC/D,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO,MAAM,CAAC;QACtE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IAC5C,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,KAAgC;QACvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACtF,CAAC;CACF;AAED,wEAAwE;AACxE,wEAAwE;AACxE,uEAAuE;AACvE,yEAAyE;AACzE,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,qCAAqC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;QACpG,MAAM,IAAI,KAAK,CAAC,sCAAsC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAW;IACrC,2EAA2E;IAC3E,8DAA8D;IAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACjF,2EAA2E;IAC3E,uEAAuE;IACvE,oDAAoD;IACpD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAiB,CAAC,CAAC,CAAC;IAC3C,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"} |
+9
-12
@@ -1,3 +0,4 @@ | ||
| // On-disk cache of an OAuth client_id + access token, keyed implicitly to the | ||
| // server URL it was issued for. Mode 0600 — same convention as ~/.pgpass, | ||
| // On-disk cache of an OAuth flow's state — client registration (DCR), the | ||
| // access/refresh tokens, and the transient PKCE code verifier the SDK needs | ||
| // to bridge two `auth()` calls. Mode 0600 — same convention as ~/.pgpass, | ||
| // ~/.aws/credentials, mcp-remote's ~/.mcp-auth, and ssh keys. | ||
@@ -32,16 +33,12 @@ import { promises as fs } from 'node:fs'; | ||
| } | ||
| if (typeof parsed.serverURL !== 'string' | ||
| || typeof parsed.clientId !== 'string' | ||
| || typeof parsed.accessToken !== 'string') { | ||
| if (typeof parsed.serverURL !== 'string') | ||
| return null; | ||
| } | ||
| return { | ||
| serverURL: parsed.serverURL, | ||
| clientId: parsed.clientId, | ||
| accessToken: parsed.accessToken, | ||
| expiresAt: typeof parsed.expiresAt === 'string' ? parsed.expiresAt : null, | ||
| createdAt: typeof parsed.createdAt === 'string' ? parsed.createdAt : new Date().toISOString(), | ||
| ...(parsed.clientInformation ? { clientInformation: parsed.clientInformation } : {}), | ||
| ...(parsed.tokens ? { tokens: parsed.tokens } : {}), | ||
| ...(parsed.codeVerifier ? { codeVerifier: parsed.codeVerifier } : {}), | ||
| }; | ||
| } | ||
| async save(token) { | ||
| async save(state) { | ||
| await fs.mkdir(dirname(this.path), { recursive: true }); | ||
@@ -54,3 +51,3 @@ // Atomic write: stage to a unique temp file then rename. POSIX rename is | ||
| try { | ||
| await fs.writeFile(tmp, JSON.stringify(token, null, 2), { mode: 0o600 }); | ||
| await fs.writeFile(tmp, JSON.stringify(state, null, 2), { mode: 0o600 }); | ||
| await fs.chmod(tmp, 0o600); // umask-resistant | ||
@@ -57,0 +54,0 @@ await fs.rename(tmp, this.path); |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/oauth/store.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/oauth/store.ts"],"names":[],"mappings":"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"} |
+16
-1
| { | ||
| "name": "@pasteapp/mcp", | ||
| "version": "0.1.0", | ||
| "version": "0.1.1", | ||
| "description": "Local MCP server bridge for Paste — give Claude Desktop, Claude Code, Cursor, Codex, and other AI tools access to your Mac clipboard history and pinboards.", | ||
@@ -42,3 +42,18 @@ "keywords": [ | ||
| "node": ">=18" | ||
| }, | ||
| "scripts": { | ||
| "build": "rm -rf dist && tsc && chmod +x dist/index.js", | ||
| "test": "vitest run", | ||
| "dev": "tsx src/index.ts", | ||
| "prepublishOnly": "npm run build && npm test" | ||
| }, | ||
| "dependencies": { | ||
| "@modelcontextprotocol/sdk": "^1.21.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "^22.10.0", | ||
| "tsx": "^4.19.0", | ||
| "typescript": "^5.7.0", | ||
| "vitest": "^4.1.0" | ||
| } | ||
| } |
| import { createHash, randomBytes } from 'node:crypto'; | ||
| function base64URL(buf) { | ||
| return buf.toString('base64url'); | ||
| } | ||
| export function generatePKCE() { | ||
| const verifier = base64URL(randomBytes(32)); | ||
| const challenge = base64URL(createHash('sha256').update(verifier).digest()); | ||
| return { verifier, challenge }; | ||
| } | ||
| export function generateState() { | ||
| return base64URL(randomBytes(16)); | ||
| } | ||
| //# sourceMappingURL=pkce.js.map |
| {"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/oauth/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAOtD,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,QAAQ,GAAG,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;AACpC,CAAC"} |
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
59427
7.89%731
11.94%1
-50%1
Infinity%4
Infinity%8
14.29%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added