@beepflow/mcp 2026.4.2 → 2026.4.4

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.
Files changed (3) hide show
  1. package/README.md +21 -53
  2. package/dist/index.js +1 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,67 +1,35 @@
1
1
  # @beepflow/mcp
2
2
 
3
- MCP server for Beepflow. Current tool: list spaces.
3
+ Beepflow MCP server (stdio).
4
4
 
5
- ## Run (dev)
6
- Node `v24.6.0` (see `.nvmrc`).
5
+ ## Install
7
6
 
7
+ ### OpenAI Codex
8
8
  ```sh
9
- export BEEPFLOW_ENV=dev
10
- node --experimental-strip-types src/index.ts
11
- ```
12
-
13
- ## Run (npx)
14
- ```sh
15
- export BEEPFLOW_ENV=dev
16
- npx -y @beepflow/mcp
17
- ```
18
-
19
- ## Publish (npm)
20
- ```sh
21
- make -C mcp publish-dry-run
22
- make -C mcp publish
9
+ codex mcp add beepflow -- npx -y @beepflow/mcp
23
10
  ```
24
11
 
25
- Publish auto tags version using `year.month.counter`:
26
- - `major` = current year
27
- - `minor` = current month (no leading zero)
28
- - `patch` = counter for year+month starting at `0`
29
-
30
- Check next version:
12
+ ### Claude Code
31
13
  ```sh
32
- make -C mcp compute-next-version
14
+ claude mcp add beepflow -- npx -y @beepflow/mcp
33
15
  ```
34
16
 
35
- ## Codex MCP install (local)
36
- ```sh
37
- make -C mcp codex-install-dev
38
- make -C mcp codex-install-live
17
+ ### OpenCode
18
+ Add to `opencode.json` (or `opencode.jsonc`):
19
+ ```json
20
+ {
21
+ "$schema": "https://opencode.ai/config.json",
22
+ "mcp": {
23
+ "beepflow": {
24
+ "type": "local",
25
+ "command": ["npx", "-y", "@beepflow/mcp"],
26
+ "enabled": true
27
+ }
28
+ }
29
+ }
39
30
  ```
40
31
 
41
- Public install:
32
+ ### Gemini CLI
42
33
  ```sh
43
- codex mcp add beepflow -- npx -y @beepflow/mcp
34
+ gemini mcp add beepflow npx -y @beepflow/mcp
44
35
  ```
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
-
50
- ## Auth tools
51
- - `auth_email_request_code` `{ "email": "you@domain.com" }`
52
- - `auth_email_verify_code` `{ "email": "you@domain.com", "code": "123456" }`
53
- - `auth_google_start` (optional `{ "scopes": "openid email profile" }`)
54
- - `auth_google_get_token` `{ "requestId": "..." }`
55
- - `auth_sign_out`
56
-
57
- ## Spaces tool
58
- - `spaces_list`
59
-
60
- ## Config
61
- - `BEEPFLOW_ENV=dev|live` (default `live`)
62
- - Override:
63
- - `BEEPFLOW_WORKSPACE_URL`
64
- - `BEEPFLOW_JWT`
65
- - `BEEPFLOW_AUTH_URL`
66
- - `BEEPFLOW_AUTH_DOMAIN`
67
- - `BEEPFLOW_TOKEN_STORE_PATH`
package/dist/index.js CHANGED
@@ -2,5 +2,5 @@
2
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}`}})+`
3
3
  `)}catch{}}}function c(p){for(o+=p;;){let d=o.indexOf(`
4
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)+`
5
- `)}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)+`
6
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.2",
3
+ "version": "2026.4.4",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=24.6.0"