@beepflow/mcp 2026.4.0 → 2026.4.3

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/README.md CHANGED
@@ -32,6 +32,21 @@ Check next version:
32
32
  make -C mcp compute-next-version
33
33
  ```
34
34
 
35
+ ## Codex MCP install (local)
36
+ ```sh
37
+ make -C mcp codex-install-dev
38
+ make -C mcp codex-install-live
39
+ ```
40
+
41
+ Public install:
42
+ ```sh
43
+ codex mcp add beepflow -- npx -y @beepflow/mcp
44
+ ```
45
+
46
+ Switch easy: both targets install same MCP name `beepflow`.
47
+ - `codex-install-dev`: local `src/index.ts`
48
+ - `codex-install-live`: published `npx -y @beepflow/mcp`
49
+
35
50
  ## Auth tools
36
51
  - `auth_email_request_code` `{ "email": "you@domain.com" }`
37
52
  - `auth_email_verify_code` `{ "email": "you@domain.com", "code": "123456" }`
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
+ #!/usr/bin/env node
1
2
  import{stdin as k,stdout as R}from"node:process";function U(e){let t=new Map;for(let p of e.tools)t.set(p.name,p);let n=!1,o="",s={start:()=>{k.setEncoding("utf8"),k.on("data",p=>c(typeof p=="string"?p:p.toString("utf8"))),k.on("end",()=>r("stdin-end")),k.on("error",()=>r("stdin-error"))}};function r(p){if(!n){n=!0;try{R.write(JSON.stringify({jsonrpc:"2.0",method:"notifications/message",params:{level:"info",data:`server closing: ${p}`}})+`
2
3
  `)}catch{}}}function c(p){for(o+=p;;){let d=o.indexOf(`
3
4
  `);if(d===-1)return;let u=o.slice(0,d).trim();if(o=o.slice(d+1),!u)continue;let f;try{f=JSON.parse(u)}catch{continue}i(f)}}async function i(p){if(n)return;let d=p.id===void 0,u=p.id??null;try{switch(p.method){case"initialize":{let h={protocolVersion:(p.params??{}).protocolVersion??"2024-11-05",serverInfo:{name:e.serverName,version:e.serverVersion},capabilities:{tools:{}}};if(d)return;a({jsonrpc:"2.0",id:u,result:h});return}case"notifications/initialized":return;case"notifications/cancelled":return;case"logging/setLevel":{if(d)return;a({jsonrpc:"2.0",id:u,result:{}});return}case"ping":{if(d)return;a({jsonrpc:"2.0",id:u,result:{}});return}case"tools/list":{if(d)return;let f=e.tools.map(m=>({name:m.name,description:m.description,inputSchema:m.inputSchema}));a({jsonrpc:"2.0",id:u,result:{tools:f}});return}case"tools/call":{if(d)return;let f=p.params??{},m=typeof f.name=="string"?f.name:"",h=t.get(m);if(!h){a({jsonrpc:"2.0",id:u,error:{code:-32601,message:`unknown tool: ${m}`}});return}let G=await h.call(f.arguments);a({jsonrpc:"2.0",id:u,result:G});return}case"resources/list":{if(d)return;a({jsonrpc:"2.0",id:u,result:{resources:[]}});return}case"prompts/list":{if(d)return;a({jsonrpc:"2.0",id:u,result:{prompts:[]}});return}default:{if(d)return;a({jsonrpc:"2.0",id:u,error:{code:-32601,message:`method not found: ${p.method}`}})}}}catch(f){if(d)return;a({jsonrpc:"2.0",id:u,error:{code:-32603,message:f?.message??"internal error"}})}}function a(p){n||R.write(JSON.stringify(p)+`
4
- `)}return{server:s,closeServer:r}}import H from"node:os";import E from"node:path";var V={dev:{name:"dev",workspaceUrl:"http://localhost:2451/api",authUrl:"https://auth.fewlogs.com",authDomain:"beepflow.com"},live:{name:"live",workspaceUrl:"https://api.kafkaide.com:30200/api",authUrl:"https://auth.fewlogs.com",authDomain:"beepflow.com"}};function z(e){let n=W(e,"--env")??W(e,"--environment")??process.env.BEEPFLOW_ENV??"live";if(n==="dev"||n==="live")return n;throw new Error(`invalid BEEPFLOW_ENV: ${n}`)}function B(e){let t=z(e);return V[t]}function W(e,t){for(let n=0;n<e.length;n+=1){let o=e[n];if(o===t){let r=e[n+1];if(!r)throw new Error(`missing value for ${t}`);return r}let s=`${t}=`;if(o&&o.startsWith(s)){let r=o.slice(s.length);if(!r)throw new Error(`missing value for ${t}`);return r}}}function l(){let e=process.argv.slice(2),t=B(e),n=b("workspace url",[w(e,"--workspace-url"),process.env.BEEPFLOW_WORKSPACE_URL,t.workspaceUrl]),o=b("auth url",[w(e,"--auth-url"),process.env.BEEPFLOW_AUTH_URL,t.authUrl]),s=b("auth domain",[w(e,"--auth-domain"),process.env.BEEPFLOW_AUTH_DOMAIN,t.authDomain]),r=w(e,"--token-store-path")??process.env.BEEPFLOW_TOKEN_STORE_PATH??Q();return{environmentName:t.name,workspaceUrl:n.replace(/\/+$/,""),authUrl:o.replace(/\/+$/,""),authDomain:s,jwtFromEnvironment:w(e,"--jwt")??process.env.BEEPFLOW_JWT,tokenStorePath:r}}function w(e,t){for(let n=0;n<e.length;n+=1){let o=e[n];if(o===t){let r=e[n+1];if(!r)throw new Error(`missing value for ${t}`);return r}let s=`${t}=`;if(o&&o.startsWith(s)){let r=o.slice(s.length);if(!r)throw new Error(`missing value for ${t}`);return r}}}function Q(){let e=process.env.APPDATA;if(e)return E.join(e,"beepflow-mcp","workspace-access-tokens.json");let t=process.env.XDG_CONFIG_HOME;return t?E.join(t,"beepflow-mcp","workspace-access-tokens.json"):E.join(H.homedir(),".config","beepflow-mcp","workspace-access-tokens.json")}function b(e,t){for(let n of t)if(typeof n=="string"&&n.trim())return n;throw new Error(`missing ${e}`)}import x from"node:fs/promises";import Y from"node:path";import K from"node:crypto";function y(e){let t=e.split(".");if(t.length<2)return{accessToken:e,email:void 0,exp:void 0,provider:void 0};let n=X(t[1]??"");if(!n)return{accessToken:e,email:void 0,exp:void 0,provider:void 0};let o;try{o=JSON.parse(n)}catch{return{accessToken:e,email:void 0,exp:void 0,provider:void 0}}let s=typeof o.email=="string"?o.email.toLowerCase():void 0,r=typeof o.exp=="number"?o.exp:void 0,c=typeof o.provider=="string"?o.provider:void 0;return{accessToken:e,email:s,exp:r,provider:c}}function P(e){return e?e.length<=12?`${e.slice(0,4)}\u2026`:`${e.slice(0,6)}\u2026${e.slice(-4)}`:""}function j(){return K.randomBytes(9).toString("base64url")}function X(e){if(!e)return;let t=e.replace(/-/g,"+").replace(/_/g,"/"),n=(4-t.length%4)%4,o=t+"=".repeat(n);try{return Buffer.from(o,"base64").toString("utf8")}catch{return}}async function J(){let e=l();return e.jwtFromEnvironment?e.jwtFromEnvironment:(await Z(e.tokenStorePath,e.workspaceUrl))?.accessToken}async function g(e){let t=l(),n=y(e),o={accessToken:e,email:n.email,provider:n.provider,exp:n.exp};return await ee(t.tokenStorePath,t.workspaceUrl,o),o}async function _(){let e=l(),t=await T(e.tokenStorePath),n=t[e.workspaceUrl]!==void 0;return delete t[e.workspaceUrl],await $(e.tokenStorePath,t),{workspaceUrl:e.workspaceUrl,deleted:n}}function v(e){return{email:e.email,provider:e.provider,exp:e.exp,accessToken:P(e.accessToken)}}async function Z(e,t){return(await T(e))[t]}async function ee(e,t,n){let o=await T(e);o[t]=n,await $(e,o)}async function T(e){try{let t=await x.readFile(e,"utf8"),n=JSON.parse(t);return!n||typeof n!="object"?{}:n}catch{return{}}}async function $(e,t){await x.mkdir(Y.dirname(e),{recursive:!0}),await x.writeFile(e,JSON.stringify(t,null,2)+`
5
+ `)}return{server:s,closeServer:r}}import H from"node:os";import b from"node:path";var V={dev:{name:"dev",workspaceUrl:"http://localhost:2451/api",authUrl:"https://auth.fewlogs.com",authDomain:"beepflow.com"},live:{name:"live",workspaceUrl:"https://beepflow.com/api",authUrl:"https://auth.fewlogs.com",authDomain:"beepflow.com"}};function z(e){let n=W(e,"--env")??W(e,"--environment")??process.env.BEEPFLOW_ENV??"live";if(n==="dev"||n==="live")return n;throw new Error(`invalid BEEPFLOW_ENV: ${n}`)}function B(e){let t=z(e);return V[t]}function W(e,t){for(let n=0;n<e.length;n+=1){let o=e[n];if(o===t){let r=e[n+1];if(!r)throw new Error(`missing value for ${t}`);return r}let s=`${t}=`;if(o&&o.startsWith(s)){let r=o.slice(s.length);if(!r)throw new Error(`missing value for ${t}`);return r}}}function l(){let e=process.argv.slice(2),t=B(e),n=E("workspace url",[w(e,"--workspace-url"),process.env.BEEPFLOW_WORKSPACE_URL,t.workspaceUrl]),o=E("auth url",[w(e,"--auth-url"),process.env.BEEPFLOW_AUTH_URL,t.authUrl]),s=E("auth domain",[w(e,"--auth-domain"),process.env.BEEPFLOW_AUTH_DOMAIN,t.authDomain]),r=w(e,"--token-store-path")??process.env.BEEPFLOW_TOKEN_STORE_PATH??Q();return{environmentName:t.name,workspaceUrl:n.replace(/\/+$/,""),authUrl:o.replace(/\/+$/,""),authDomain:s,jwtFromEnvironment:w(e,"--jwt")??process.env.BEEPFLOW_JWT,tokenStorePath:r}}function w(e,t){for(let n=0;n<e.length;n+=1){let o=e[n];if(o===t){let r=e[n+1];if(!r)throw new Error(`missing value for ${t}`);return r}let s=`${t}=`;if(o&&o.startsWith(s)){let r=o.slice(s.length);if(!r)throw new Error(`missing value for ${t}`);return r}}}function Q(){let e=process.env.APPDATA;if(e)return b.join(e,"beepflow-mcp","workspace-access-tokens.json");let t=process.env.XDG_CONFIG_HOME;return t?b.join(t,"beepflow-mcp","workspace-access-tokens.json"):b.join(H.homedir(),".config","beepflow-mcp","workspace-access-tokens.json")}function E(e,t){for(let n of t)if(typeof n=="string"&&n.trim())return n;throw new Error(`missing ${e}`)}import x from"node:fs/promises";import Y from"node:path";import K from"node:crypto";function y(e){let t=e.split(".");if(t.length<2)return{accessToken:e,email:void 0,exp:void 0,provider:void 0};let n=X(t[1]??"");if(!n)return{accessToken:e,email:void 0,exp:void 0,provider:void 0};let o;try{o=JSON.parse(n)}catch{return{accessToken:e,email:void 0,exp:void 0,provider:void 0}}let s=typeof o.email=="string"?o.email.toLowerCase():void 0,r=typeof o.exp=="number"?o.exp:void 0,c=typeof o.provider=="string"?o.provider:void 0;return{accessToken:e,email:s,exp:r,provider:c}}function P(e){return e?e.length<=12?`${e.slice(0,4)}\u2026`:`${e.slice(0,6)}\u2026${e.slice(-4)}`:""}function j(){return K.randomBytes(9).toString("base64url")}function X(e){if(!e)return;let t=e.replace(/-/g,"+").replace(/_/g,"/"),n=(4-t.length%4)%4,o=t+"=".repeat(n);try{return Buffer.from(o,"base64").toString("utf8")}catch{return}}async function J(){let e=l();return e.jwtFromEnvironment?e.jwtFromEnvironment:(await Z(e.tokenStorePath,e.workspaceUrl))?.accessToken}async function g(e){let t=l(),n=y(e),o={accessToken:e,email:n.email,provider:n.provider,exp:n.exp};return await ee(t.tokenStorePath,t.workspaceUrl,o),o}async function _(){let e=l(),t=await T(e.tokenStorePath),n=t[e.workspaceUrl]!==void 0;return delete t[e.workspaceUrl],await $(e.tokenStorePath,t),{workspaceUrl:e.workspaceUrl,deleted:n}}function v(e){return{email:e.email,provider:e.provider,exp:e.exp,accessToken:P(e.accessToken)}}async function Z(e,t){return(await T(e))[t]}async function ee(e,t,n){let o=await T(e);o[t]=n,await $(e,o)}async function T(e){try{let t=await x.readFile(e,"utf8"),n=JSON.parse(t);return!n||typeof n!="object"?{}:n}catch{return{}}}async function $(e,t){await x.mkdir(Y.dirname(e),{recursive:!0}),await x.writeFile(e,JSON.stringify(t,null,2)+`
5
6
  `,"utf8")}async function O(e){let t=l(),n=await fetch(`${t.authUrl}/email/request-code`,{method:"POST",headers:{"content-type":"application/json",domain:t.authDomain},body:JSON.stringify({email:e})});if(!n.ok){let o=await n.text().catch(()=>"");throw new Error(`email/request-code failed: ${n.status} ${o}`.trim())}}async function I(e,t){let n=l(),o=await fetch(`${n.authUrl}/email/verify-code`,{method:"POST",headers:{"content-type":"application/json",domain:n.authDomain},body:JSON.stringify({email:e,code:t})}),s=await o.json().catch(()=>{});if(!o.ok)throw new Error(`email/verify-code failed: ${o.status}`);let r=typeof s?.access_token=="string"?s.access_token:"";if(!r)throw new Error("email/verify-code failed: missing access_token");let c=await g(r);return{workspaceUrl:n.workspaceUrl,...v(c)}}import te from"node:crypto";async function A(e){let t=l(),n=te.randomUUID(),o=new URL(`${t.authUrl}/google-form`);return o.searchParams.set("requestId",n),o.searchParams.set("scopes",e),{requestId:n,url:o.toString()}}async function C(e){let t=l(),n=new URL(`${t.authUrl}/google-auth-token`);n.searchParams.set("id",e);let o=await fetch(n.toString(),{headers:{domain:t.authDomain}}),s=await o.json().catch(()=>{});if(!o.ok)throw new Error(`google-auth-token failed: ${o.status}`);let r=typeof s?.access_token=="string"?s.access_token:"";if(!r)throw new Error("google-auth-token failed: missing access_token");let c=await g(r);return{workspaceUrl:t.workspaceUrl,...v(c)}}async function N(e){let t=l(),n=await fetch(`${t.workspaceUrl}/users/is-member`,{method:"GET",headers:{Authorization:`Bearer ${e}`}});if(!n.ok){let s=await n.text().catch(()=>"");throw new Error(`users/is-member failed: ${n.status} ${s}`.trim())}if((await n.json().catch(()=>{}))?.isMember!==!0)throw new Error("user not member of workspace")}async function M(e){let t=y(e);if(t.provider!=="google"||!t.exp)return e;let n=Date.now(),o=t.exp*1e3,s=300*1e3;if(o-n>=s)return e;let r=l(),c=await fetch(`${r.authUrl}/google-refresh`,{method:"GET",headers:{Authorization:`Bearer ${e}`}}),i=await c.json().catch(()=>{});if(!c.ok)return e;let a=typeof i?.access_token=="string"?i.access_token:"";return a?(await g(a),a):e}async function q(e,t,n,o,s){let r=l(),c=ne(r.workspaceUrl,e,t),i=await re(c,s);try{let a={resource:n,action:"snapshot",value:o};return i.send(oe("replicated-state",JSON.stringify(a))),await se(i,n,s)}finally{i.close()}}function ne(e,t,n){let o=e.replace(/^http/,"ws"),s=encodeURIComponent(t),r=encodeURIComponent(n);return`${o}/base/${s}/${r}`}function oe(e,t){return`${e};${t}`}async function re(e,t){let n=new WebSocket(e,"echo"),o=await new Promise(s=>{let r=setTimeout(()=>s({ok:!1,reason:"timeout"}),t);n.onopen=()=>{clearTimeout(r),s({ok:!0})},n.onerror=()=>{clearTimeout(r),s({ok:!1,reason:"error"})}});if(!o.ok)throw n.close(),new Error(`websocket open failed: ${o.reason??"unknown"}`);return n}async function se(e,t,n){return await new Promise((o,s)=>{let r=setTimeout(()=>s(new Error("snapshot timeout")),n);e.onerror=()=>{clearTimeout(r),s(new Error("websocket error during snapshot wait"))},e.onclose=()=>{clearTimeout(r),s(new Error("websocket closed during snapshot wait"))},e.onmessage=c=>{let i=typeof c.data=="string"?c.data:"",a=i.indexOf(";");if(a===-1||i.slice(0,a)!=="replicated-state")return;let d=i.slice(a+1),u;try{u=JSON.parse(d)}catch{return}u.action==="snapshot"&&u.resource===t&&(!u.value||typeof u.value!="object"||(clearTimeout(r),o(u.value)))}})}async function D(){let e=await J();if(!e)throw new Error("missing jwt: set BEEPFLOW_JWT or run auth tool to persist token");let t=await M(e);await N(t);let n=j(),o=await q(t,n,"spaces",{all:!0},15e3),s=[];for(let r in o){let c=o[r];if(!c||typeof c!="object")continue;let i=c,a=i.id;if(typeof a!="string"||!a)continue;let p={id:a,updatedAt:typeof i.updatedAt=="number"?i.updatedAt:void 0,label:typeof i.label=="string"?i.label:void 0,thumbnailUrl:typeof i.thumbnailUrl=="string"?i.thumbnailUrl:void 0,description:typeof i.description=="string"?i.description:void 0,isUserSpace:typeof i.isUserSpace=="boolean"?i.isUserSpace:void 0};s.push(p)}return s.sort((r,c)=>{let i=(r.label??"").toLowerCase(),a=(c.label??"").toLowerCase();return i<a?-1:i>a?1:r.id<c.id?-1:r.id>c.id?1:0}),s}function L(){return[{name:"spaces_list",description:"List authorized Beepflow spaces for current JWT.",inputSchema:{type:"object",additionalProperties:!1,properties:{}},call:async()=>{let e=await D();return{content:[{type:"text",text:JSON.stringify(e,null,2)}]}}},{name:"auth_email_request_code",description:"Request email login code via Beepflow auth service.",inputSchema:{type:"object",additionalProperties:!1,required:["email"],properties:{email:{type:"string"}}},call:async e=>{let t=S(e,"email");return await O(t),{content:[{type:"text",text:`code sent to ${t}`}]}}},{name:"auth_email_verify_code",description:"Verify email login code, persist JWT for workspace.",inputSchema:{type:"object",additionalProperties:!1,required:["email","code"],properties:{email:{type:"string"},code:{type:"string"}}},call:async e=>{let t=S(e,"email"),n=S(e,"code"),o=await I(t,n);return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}},{name:"auth_google_start",description:"Create Google OAuth login URL + request id.",inputSchema:{type:"object",additionalProperties:!1,properties:{scopes:{type:"string"}}},call:async e=>{let t=ie(e,"scopes")??"openid email profile",n=await A(t);return{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}},{name:"auth_google_get_token",description:"Fetch Google OAuth token using request id, persist JWT for workspace.",inputSchema:{type:"object",additionalProperties:!1,required:["requestId"],properties:{requestId:{type:"string"}}},call:async e=>{let t=S(e,"requestId"),n=await C(t);return{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}},{name:"auth_sign_out",description:"Delete stored JWT for current workspace.",inputSchema:{type:"object",additionalProperties:!1,properties:{}},call:async()=>{let e=await _();return{content:[{type:"text",text:JSON.stringify(e,null,2)}]}}}]}function S(e,t){if(!e||typeof e!="object")throw new Error("invalid tool arguments: expected object");let o=e[t];if(typeof o!="string"||!o.trim())throw new Error(`invalid tool arguments: ${t} must be non-empty string`);return o}function ie(e,t){if(e===void 0)return;if(!e||typeof e!="object")throw new Error("invalid tool arguments: expected object");let o=e[t];if(o!=null){if(typeof o!="string")throw new Error(`invalid tool arguments: ${t} must be string`);return o}}var{server:ae,closeServer:F}=U({serverName:"mcp",serverVersion:"0.1.0",tools:L()});process.on("SIGINT",()=>F("SIGINT"));process.on("SIGTERM",()=>F("SIGTERM"));ae.start();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beepflow/mcp",
3
- "version": "2026.4.0",
3
+ "version": "2026.4.3",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=24.6.0"
@@ -17,7 +17,7 @@
17
17
  "scripts": {
18
18
  "start:src": "node --experimental-strip-types ./src/index.ts",
19
19
  "test:src": "node --experimental-strip-types --test ./src/**/*.test.ts",
20
- "build": "node --input-type=module -e \"import fs from 'node:fs'; fs.rmSync('dist', { recursive: true, force: true });\" && tsc -p tsconfig.json --noEmit && esbuild src/index.ts --bundle --platform=node --format=esm --target=node24 --minify --outfile=dist/index.js",
20
+ "build": "node --input-type=module -e \"import fs from 'node:fs'; fs.rmSync('dist', { recursive: true, force: true });\" && tsc -p tsconfig.json --noEmit && esbuild src/index.ts --bundle --platform=node --format=esm --target=node24 --minify --banner:js='#!/usr/bin/env node' --outfile=dist/index.js && node --input-type=module -e \"import fs from 'node:fs'; fs.chmodSync('dist/index.js', 0o755);\"",
21
21
  "start": "node ./dist/index.js",
22
22
  "test": "yarn test:src && yarn build && node ./dist/index.js < /dev/null",
23
23
  "prepack": "yarn build"