
Wicket
io.github.Stixels由 GitHub 账号 Stixels 发布v1.0.0更新于 Nov 14, 2026
Search a product's docs, file bugs and feature requests, and hear back when they ship.
概览
Wicket 的 MCP 服务器让助手搜索产品文档、提交缺陷或功能请求,并查看这些报告的处理进度。
- 可以做什么
- 搜索文档索引,并读取搜索结果对应的完整正文,附带摘要与链接
- 提交缺陷或功能请求,提交前会做重复检查并返回可能已存在的工单
- 查看本人报告的状态(待处理、已计划、已修复、已拒绝),以及工单和团队回复
- 适用场景
- 适合团队已用 Wicket 提供应用内帮助,并希望 Claude Code、Claude Desktop 或 Cursor 中的助手基于同一份文档作答、直接提交或跟进报告的场景。
- 运行要求
- 通过 streamable HTTP 连接 wicketchat.com 的远程端点,需在 Authorization 请求头中提供 bearer 令牌。演示令牌需从 Wicket 网站获取,有效期为一天。自建实例需开启 MCP 服务器并配置身份密钥。
安装
在 SourceWeft 中
- 打开 控制台中的 Wicket,将其添加到工作区。
- 连接 Authorization token 凭据。它们会被私密存储,绝不会在公开页面上展示。
- 为需要使用其工具的对话启用该服务。
Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。
交给智能体安装
把这段提示词粘贴到 Claude Code、Codex、Cursor 等智能体,或 SourceWeft 对话中。智能体会读取该服务器的安装指南,先向你展示发布者、端点和登录方式,经你同意后再把它添加到你的客户端。密钥不会写进任何命令。
阅读 https://sourceweft.com/mcp/io.github.Stixels%2Fwicket/install.md,并按其中说明把这个 MCP 服务器接入我的客户端。修改任何配置之前,先告诉我它的发布者、端点和登录方式,等我确认。不要把 API 密钥写进命令或我会提交的文件;问我密钥应从哪里获取。其他 MCP 客户端
把它添加到你客户端的 mcpServers 配置中。
{
"mcpServers": {
"wicket": {
"type": "http",
"url": "https://wicketchat.com/mcp",
"headers": {
"Authorization": "Bearer <YOUR_TOKEN>"
}
}
}
}README
Wicket
A drop-in help and feedback chat for any web app, plus a Discord community and support inbox behind it. Users write one message. An assistant answers from your docs, and every conversation shows up in your team's Discord, where a reply goes straight back to the user in the app.
-
One script tag adds a chat button to your app. It captures the page, app version and recent console errors, so reports arrive with context.
-
Answers from your docs. It indexes any GitHub repo of Markdown or MDX (GitBook Git Sync, Docusaurus, Mintlify, ...), or any hosted docs site by its sitemap, and links the exact section.
-
Discord as the inbox and community. Each in-app conversation becomes a private forum post that your team answers from Discord. The same assistant can also answer new questions in your public
#helpforum. -
Hands off to a person when the user asks, is frustrated, or the docs don't cover it, and pings a role you choose.
-
Cheap to run. One Node process with SQLite. The assistant runs through the Vercel AI Gateway or Anthropic directly, and it's optional: without a key, every chat goes straight to the team.
-
Works from AI tools. Wicket is also an MCP server, so people can search your docs, file bugs and check on them from Claude Code, Claude Desktop or Cursor. See MCP server.
-
Everyone hears back. With a tracker set up, the assistant logs bugs, ideas and docs gaps itself. A repeat report becomes another report on the ticket that already exists, not a new one. Everyone who reported it gets a message in their chat (and by email if they're away) when it's fixed, and for ideas, when the team plans it or decides not to.
Run the demo (no keys needed)
The demo indexes the Escape Director docs, uses a scripted assistant and simulates Discord. To simulate a team reply, run curl -XPOST localhost:4317/__staff -H 'content-type: application/json' -d '{"body":"Hi!"}'.
Add it to your app
You can also call Wicket.open(), Wicket.close(), Wicket.toggle(), Wicket.ask("question") (opens the chat and sends it), Wicket.setContext({ roomId }), Wicket.setUser({...}), Wicket.setUserToken(...), Wicket.setTheme({...}), Wicket.setAnchor(element), Wicket.setQuiet(true), Wicket.addBreadcrumb("Paused game") and Wicket.destroy() (removes the widget, for example on sign-out; init brings it back) at any time. The latest context and a fresh userToken go with every message.
Recent activity for bug reports. The widget keeps a short trail of what the person did in your app: the last 20 steps from the last 5 minutes, made of page changes (path only, never the query string), clicks on buttons and links by their visible label or aria-label, and console errors. It never records what anyone types or the value of a field. Add your own steps with Wicket.addBreadcrumb(label), for example "Paused game" or "Sent Clue"; it works before init. The trail stays in the page and is sent only with a bug report: with the first message after "Report a bug", or right after the assistant logs a bug on its own (then it's added to that ticket as a comment). The server caps it, strips anything that looks like an email, card number or token, and puts it in the model's transcript and on the ticket under ## Recent activity, nowhere else. Turn it off with Wicket.init({ trail: false }).
Your own button
To open the chat from a button in your app's header, hide the launcher and pass the button as anchor:
- The panel opens just below the anchor, right-aligned to it, floating over the page. On phones it opens full screen as usual. If the anchor is gone or hidden, the panel uses the bottom corner.
- When a reply arrives while the chat is closed, a preview drops from under the anchor (or sits above the launcher) with the reply, a one-line reply box and Open chat. It never plays a sound.
quiet: true(orWicket.setQuiet(true)) turns the previews off, for screens other people can see;unreadstill fires so you can show the count yourself.Wicket.on(event, callback)returns a function that unsubscribes. Events:unread(the count, on every change, including back to 0 when the chat opens),open,close, andrating({ conversationId, messageId, rating }when someone rates an answer;ratingis"up","down"ornullwhen they take it back). You can subscribe beforeinit.
Each assistant answer has thumbs up and down on its name line. A thumbs down offers to pass the conversation to the team. Answers can come with How we got this (the numbers behind them) and Ask next questions under the latest one. When the server asks for a bot check, visitors pass a Cloudflare Turnstile check in the panel before their first answer.
Signed-in users
A name or id passed in user is only a label. For profiles that depend on who someone is (signed in, their plan) and for per-person budgets, your backend signs a short-lived token and the widget passes it on:
userToken takes the token or a function that returns one. Without a valid token, the person counts as a visitor. Tokens must have an expiry (exp) no more than 24 hours out; a few minutes is best. The widget asks for a fresh one with every message.
Optional claims:
Deleting someone's data
When someone deletes their account in your app, your backend signs a token with scope: "erase" and posts it to /api/erase:
Wicket deletes every conversation the person started, and with account, every conversation billed to that account. That covers messages, files, the assistant's transcript and the team's Discord post. What each answer cost stays, without any words, so budgets add up. The answer is { deleted, failed }. A 502 means some Discord posts couldn't be removed yet; those conversations are kept, so call again later until you get a 200. Calling again is always safe. Only your backend should sign these tokens: an erase token never signs anyone in, and a widget's sign-in token can't erase.
App tools
Let the assistant read the signed-in person's own data, such as their results or settings, through tools your backend offers. Wicket calls them with the person's token, so your backend checks who they are on every call and Wicket never sees data they couldn't see in your app.
GET {url}?context=<json>returns{ instructions, tools: [{ name, description, inputSchema }] }.instructionsare your rules for using the tools; they go into the assistant's prompt.inputSchemais JSON Schema.POST {url}/{name}with{ input, context, evidenceStart }returns{ content, evidence? }.contentis what the model reads.evidenceitems ({ id, label, value, period?, basis?, caveats? }) show folded under the answer as "How we got this", numbered fromevidenceStart + 1so ids stay unique within an answer. Answer with a 4xx and{ error }for a problem the model should hear about.contextis what the widget last sent withWicket.setContext(), for example the page, the record on screen and the date range. Wicket sends it to the model again whenever it changes.
Profiles with app tools get more steps per answer (AGENT_MAX_STEPS_WITH_APP_TOOLS, 20 by default).
Customizing
The widget renders in a shadow DOM, so your app's CSS can't break it and its CSS can't leak into your app. On phones it opens full screen.
Earlier conversations show under Recent on the start screen, and the clock button in the header lists all of them. The browser keeps each conversation's access token in localStorage (up to 50). For signed-in users (a verified userToken), the server also returns their conversations by user id, so their history, including reports and their progress, follows them to any device or browser. Visitors' history stays in the browser they used.
Set up Discord (community + support inbox)
-
Go to https://discord.com/developers/applications and create a New Application. Under Bot, copy the token and turn on Message Content Intent.
-
Under OAuth2 → URL Generator, pick the
botscope with these permissions: Manage Roles, Manage Channels, Move Members, View Channels, Send Messages, Send Messages in Threads, Create Public Threads, Manage Threads, Read Message History, Add Reactions, Embed Links and Manage Messages (to pin the welcome post). Manage Server is optional: with it the bot also points join messages and the Community welcome screen at#welcome. On a Community server it also keeps the rules channel (#📜・rules) in Start here with a pinned rules post, makes#announcementsa real announcement channel, and moves Discord's admin notices channel into Team. Open the URL and add the bot to your server. -
Turn on Developer Mode (User Settings → Advanced). Right-click your server and choose Copy Server ID.
-
Set
DISCORD_BOT_TOKENandDISCORD_GUILD_IDin the service variables. On every boot the service makes sure the server has a Team role and these channels, creating only what's missing:Channels are matched by name with or without the emoji, and nothing is ever deleted. An existing channel keeps its place and settings; the bot only adds the emoji while it still has the plain name, fills in an empty topic, and adds forum tags and the 👍 default reaction on
#ideaswhen they're missing. It keeps Start here at the top so new members land in#welcome, and keeps a pinned welcome post there with the house rules and where to go. Anything it can't do itself is logged asdiscord: needs you: …. To use an existing staff role, setDISCORD_TEAM_ROLEto its name. You can also run it by hand withnpm run discord:setup. -
Give your teammates the Team role.
How it behaves:
- In-app conversations become posts in
#support-inbox. The user's messages show as blue cards and the assistant's as gray cards, so your own replies (plain messages) stand out. While the assistant is working the bot shows as typing. Reply in a post to answer the user in the app. The assistant stops replying once someone from the team does. When the assistant asks for a person, it pings the Team role and tags the post Needs a person. Only a reply that fails to reach the app gets a ⚠️ reaction. - When you're done, close the post (or tag it Resolved; deleting it works too, though the transcript is then gone from Discord). The user sees "resolved" in the widget, the post is tagged Resolved, and if they write again the post reopens and the assistant takes the new question first. Posts Discord archives on its own after inactivity aren't treated as resolved.
- Tickets: with
LINEAR_API_KEYandLINEAR_TEAM_KEYset, anyone with the Team role can tag the bot anywhere in the server, e.g.@Wicket file this as a bugin a support-inbox post. It reads the conversation, writes the ticket (summary, steps, context, who reported it), files it in Linear (Triage if the team has it on, otherwise Backlog) with the matching Bug/Feature/Improvement label, and replies with the link. Messages that tag the bot are never sent to the user. To file GitHub issues instead, setGITHUB_ISSUES_REPOandGITHUB_ISSUES_TOKEN(a fine-grained token with Issues: read and write); issues get the repo'sbug,enhancement,documentationorquestionlabel when it exists, plusGITHUB_ISSUES_LABELif you set one. The tracker is an adapter, so Jira can plug in the same way.- Tag the bot with a ticket key or link (
@Wicket +1 ED-123,@Wicket same as <link>) to add the conversation to that ticket instead of filing a new one. - Tickets filed or added from a support-inbox post are linked to that app conversation, so its reporter hears back too.
- Tag the bot with a ticket key or link (
- Hearing back: Wicket asks the tracker every 15 minutes (
tickets.checkMinutes) about tickets someone is waiting on. When the assistant logs a report, the person sees a slim status row in their own words. Bugs go from Logged to Fixed. Ideas go from Logged to Planned (the team moved it out of Triage) to Shipped, or to Not planned when the team cancels it. To tell people why, comment on the issue starting withReply:(for exampleReply: It would distract players mid-game.); Wicket waits an hour after a cancel so there's time to write it, and sends the newest one. A bug canceled with aReply:comment tells its reporters too; one canceled without a word sends nothing. A ticket closed as a duplicate passes its reporters to the one it duplicates. With GitHub Issues there's no Triage, so ideas skip Planned; closing as completed counts as done and closing as not planned as declined. The check is plain tracker API calls, with no model calls. The dashboard lists each conversation's tickets. Turn off assistant filing withtickets.assistant: false. - Voice: joining
➕ Start a callcreates a voice room named after you and moves you in. It's deleted when the last person leaves.🎧 Talk to supportworks the same way, but the room is visible only to the caller and the Team role, and it pings the team. The bot needs the Move Members permission for both. - Announcements: set
announcements.feedinconfig/wicket.yamlto an RSS feed, such as your product's changelog, and each new item is posted to#📣・announcementswith its title, link, summary and date. On a Community server the post is also published, so servers that follow the channel get it. Wicket checks every 30 minutes (announcements.checkMinutes). The first check only remembers what the feed already holds, so nothing old is posted; setannouncements.latest: 1to post the newest item once so the channel doesn't start empty. To post somewhere else, setDISCORD_ANNOUNCEMENTS_CHANNEL_ID. - Community questions: with
assistant.helpForum: true, when someone opens a post in#help, the assistant answers once from the docs. If it can't, it pings the team. Everyone else can keep the thread going. It's off by default, because Discord members aren't signed in to your app, so those answers can't count toward anyone's budget.
Team dashboard
A reply inbox at /admin, for teammates who'd rather not answer from Discord. It's another place to reply, not a replacement: Wicket keeps the record, so a reply from the dashboard reaches the user's widget and shows up in the Discord post, and a reply in Discord shows up in the dashboard.
- Shared conversations. Nobody owns a conversation. The dashboard shows who has replied ("Alex and you replied"), and anyone can jump in. Teammates are linked across tools by their Discord account, so Alex replying in Discord and Alex in the dashboard are the same person.
- Online status. A dot on the user's avatar shows whether they're around: solid green while the chat is open in front of them, a green ring while they're on the site with the chat closed or in a background tab. The conversation header says "In the chat now", "On the site" or "Last seen 12m ago", so you know whether to expect a quick back-and-forth.
- Typing hints. While someone types in the dashboard or in the Discord post, the others see "Alex is typing" on the conversation, so two people don't write the same answer.
- Hand off with a note. Switch the composer to Note (or type
@) to leave a team-only note like "@Alex can you take this?". Notes never reach the user. In Discord the note pings Alex, and the dashboard lists it under Mentions until Alex writes in that conversation. In Discord, a message that starts with an @mention of a teammate or role is treated the same way: it stays with the team instead of going to the user, and gets a 📝 reaction. - Desktop notifications. Turn them on from the banner or your profile menu. You're notified when a conversation is passed to the team, when the user writes in a conversation the team has, and when a note mentions you, but not while you're looking at the dashboard. The tab title counts what you missed.
- Saved replies. Answers the team gives often, shared by everyone: the ⚡ button in the composer, or type
/in an empty reply to search them.{name}becomes the person's first name. "Save what I wrote" turns a reply you just wrote into one. - Views: Open, Needs reply (the user is waiting on the team), Mentions, Resolved, All. Resolve works like closing the Discord post. Each conversation shows the person, their plan, the page and app version they wrote from, and recent console errors.
- Attachments are up to 10 MB each (Discord's limit without server boosts), 30 per conversation, and stored on the server's volume. A teammate can delete one from the dashboard (hover it, then the bin); it's removed for everyone and the message keeps its name, marked removed. Files go automatically after
files.keepDays(90 by default, 0 keeps them) and uploads that were never sent go after a day. Copies already posted to Discord stay there.
Sign-in is with Discord, for everyone with the Team role:
- In the same Discord application as the bot, open OAuth2, copy the Client ID and Client Secret, and add a redirect:
https://YOUR-SERVER/admin/auth/callback. - Set
DISCORD_CLIENT_ID,DISCORD_CLIENT_SECRETandPUBLIC_URL(your server's address). WithDISCORD_GUILD_IDset, anyone with the Team role can sign in. To let in someone without the role, add their Discord user id toTEAM_DISCORD_IDS.
For local work, TEAM_DEV_LOGIN=true adds a one-click "local teammate" sign-in. Never set it on a public server.
Support is async, so nobody should have to keep a tab open waiting. With email set up, a team reply the user hasn't seen in the widget for 5 minutes is emailed to them (at most one email per conversation an hour, with every unread reply in it). The email links to a page with just that conversation, and replying to the email posts into the conversation, so it reaches the dashboard and Discord too. Each email has an unsubscribe link for that conversation. The address comes from the signed-in user's token, user.email in Wicket.init, or the email field in the widget (askEmail in a profile), and the "passed to the team" message adds "We'll email you when they do."
It uses Resend; the free tier is plenty for a small team.
- In Resend, verify the domain you'll send from and create an API key. Set
RESEND_API_KEY,EMAIL_FROM(e.g.Escape Director <[email protected]>) andPUBLIC_URL. - For replies by email: add a receiving domain in Resend (e.g.
reply.escapedirector.com) and set it asEMAIL_REPLY_DOMAIN. Add a webhook foremail.receivedpointing athttps://YOUR-SERVER/email/inboundand set its signing secret asRESEND_WEBHOOK_SECRET. A reply only counts if it comes from the address we emailed, to that conversation's own reply address.
MCP server
Wicket is also an MCP server, so people can reach your docs and your tracker from Claude Code, Claude Desktop, Cursor or any other MCP client. It uses the same code as the widget: the same docs index, the same tracker, the same duplicate check, and the same per-profile rules.
Each report becomes a conversation like one from the widget. The team sees it in Discord and the dashboard, and the reporter hears back in it (ticket_status reads it, and the chat_url it returns opens it in a browser). The client's own model does the writing, so MCP calls don't spend the assistant's budgets.
Over HTTP
Set MCP=true (with IDENTITY_SECRET) and the server answers at /mcp (streamable HTTP, stateless). It's off by default, since it lets people file into your tracker. Every request needs a user token, the same JWT the widget uses (see Signed-in users), as Authorization: Bearer <token>. Tokens can last up to 24 hours, so give people a way to get one in your app, like a "Connect Claude" button that signs a token for them.
Limits: each tool call counts against MAX_MESSAGES_PER_CONVERSATION_PER_HOUR for that person. Each report counts as starting a chat (MAX_CONVERSATIONS_PER_IP_PER_HOUR), both for that person and for their IP. In the demo, calls also share the widget's per-IP limits.
Claude Code:
Cursor (~/.cursor/mcp.json):
Claude Desktop's config file takes local servers, so bridge it with mcp-remote (Settings › Developer › Edit Config):
Try it on the demo
wicketchat.com/demo has a Try it from Claude Code card. It runs the bot check, then gives you a claude mcp add command with a day-long token for Sam, the demo customer. Then ask Claude Code something like "search the Escape Director docs for adding a clue", "report a bug: the clue counter doesn't go up after I send a clue", or "check on my reports". Reports go to the demo tracker and move on after a few minutes, like in the widget, and they show up in the widget's history in the same browser.
Over stdio
For a client on the machine with Wicket's config and database, such as a self-hosted install:
Claude Desktop:
It uses the same settings, database and tracker as the server, and acts as the local user, or as whoever WICKET_USER_TOKEN names. It doesn't start the Discord bot, so reports filed this way go to the tracker and the dashboard but don't open a Discord thread. Run it alongside the server, which does the ticket checks that tell reporters when things move.
Deploy on Railway
- In Railway, choose New → GitHub Repo and pick this repo. It builds from the
Dockerfileand redeploys on every push tomain. The build runs the typecheck and tests first, so a failing push never replaces the running version. - Add a Volume mounted at
/data. SQLite lives there. - Copy
.env.exampleinto the service variables and fill them in. - Generate a domain and use it in the script tag above.
Keep it to one replica. SQLite and the Discord connection expect a single instance.
Hosted demo
The public demo at wicketchat.com is a separate Wicket service with DEMO=true. It runs the real server and real assistant, but nothing it does can reach a real team, tracker or inbox:
/is the marketing site with the live widget, as a visitor. Nobody is signed in anywhere except/demowith Signed-in customer picked./demoplays an escape-room app, with a Visitor / Signed-in customer switch. Visitors get docs answers only. The customer is Sam, Owner at Treehouse Escapes, signed in by the page's ownPOST /api/demo/token. Each browser gets its own id in a cookie, so nobody sees anyone else's chats. The endpoint only exists withDEMO=trueand only signs that one user.- Tickets go to a demo tracker kept in the service's SQLite. Duplicate search only covers the backlog in
config/demo.yaml, so one visitor's ticket titles never show up in another visitor's chat. A few minutes after a report (demo.advanceMinutes), the ticket moves on (bugs to Fixed, ideas to Planned) and a reply labeled as simulated arrives in the chat. - MCP:
/demohands out a token for Claude Code after the bot check (POST /api/demo/mcp-token), for the same Sam as that browser's chats. It lasts a day, and only these tokens open the demo's/mcp: the widget's own token comes without a bot check, so it doesn't. A report filed over MCP doesn't get assistant answers in its chat, since no bot check opened it./mcpfiles to the same demo tracker, so it can't reach a real one either. See Try it on the demo. - Handoffs don't go anywhere. The chat says that in a real install this goes to the team's Discord inbox.
- Limits: everyone shares one monthly AI budget (
budgets.monthlyTotal, $3). When it's spent, the chat says so and still links plain docs search results. Every chat passes a Turnstile bot check, signed in or not. Messages are capped in length and per chat, and both messages and chats are capped per IP per hour (demo:inconfig/demo.yaml). Attachments and the playground are off.
Service variables:
Add a volume at /data as usual. The docs come from knowledge: in config/demo.yaml, so no DOCS_* variables are needed.
With DEMO=true, Wicket refuses to start if any LINEAR_*, GITHUB_ISSUES_*, DISCORD_*, RESEND_*, EMAIL_* or TEAM_DISCORD_IDS variable is set, if RELAY isn't none, if TEAM_DEV_LOGIN=true, or if IDENTITY_SECRET or the Turnstile keys are missing. It also refuses settings with appTools, announcements.feed or assistant.helpForum. So it can't be pointed at Escape Director's real Linear, GitHub, Discord or API by mistake.
To try it locally, use Cloudflare's always-pass test keys:
Profiles, rules and budgets
How the assistant behaves lives in one YAML file: config/wicket.yaml, or the YAML pasted into the WICKET_CONFIG variable. config/wicket.example.yaml lists every option.
- Theme (top level) sets the widget's look for everyone, with the same fields as
Wicket.init({ theme }), so the embed snippet can stay bare. - Assistant (top level) applies everywhere, including the community help forum:
instructionsfor facts every answer should know,code(declineby default: no code, it links the closest guide or example;snippetsallows short snippets adapted from examples it has read), andhelpForum(falseby default;trueanswers new#helpposts, which no per-person budget covers). - Profiles set whether the assistant answers at all, extra instructions, whether it stays on topic (
offTopic: declineby default, so it won't do general coding or homework;topicswidens what counts), the model and effort, a monthly budget per person, and what the widget shows (title, welcome text, placeholder, quick starts). Options passed toWicket.init()still win. - Rules pick a profile from whether someone is signed in, their
plan, and the page they're on. Signed in and plan come only from a verified token; the page comes from the widget. - Visitors can get the assistant too, without opening a hole in your budget: give their profile
budgetScope: sharedso they all spend from one pot, andbotCheck: trueso each conversation starts with a Cloudflare Turnstile check (setTURNSTILE_SITE_KEYandTURNSTILE_SECRET_KEY; without them those visitors go straight to the team).tickets: falsestops the assistant logging reports for people it can't follow up with. - Report shortcuts:
report: bug,featureorbothputs "Report a bug" and "Request a feature" on the widget's start screen, under an "Ask a question" card. Choosing one tags the conversation straight away, before the first message, and the tag stays until something is logged. For a bug, the assistant's first reply offers a known fix from the docs, if there is one, and proposes the steps from the widget's recent activity for the person to confirm ("Looks like you paused the game, then sent a Clue from the Room Dashboard. Is that right, and does it happen every time?"), at most two short questions. Unless they say the fix solved it, it logs the bug in its next reply with what it has: the confirmed steps under## Steps to reproduce, the widget's context, and the trail under## Recent activity. A feature request is restated and logged. Either way a repeat goes on the ticket that already exists, and the assistant never decides whether a report is worth filing. The shortcuts are an extra way in: the assistant still logs bugs, ideas and docs gaps it hears about in any conversation on its own, just as without them. It'snoneby default. The server checks the profile, so a browser can't start a report where the profile doesn't offer one, and budgets and rate limits apply as usual. Shortcuts need a tracker and the assistant; on a profile withtickets: falsethey're off, and the boot log says so. - Follow-ups:
followUps: truehas the assistant suggest two or three questions to ask next with each answer, shown as chips. They're written with the answer, so they cost no extra call. - Budgets count what each person's assistant answers cost this calendar month (UTC), from what the AI Gateway billed for each response, or from token usage and list prices when it doesn't say. Signed-in people are counted by user id, visitors by IP. Each person has one total across all profiles; a profile's
budgetis the point where that profile stops answering, so giving every profile the same number makes it a single shared budget. Near the limit the widget says so; at the limit their messages go to the team instead.monthlyTotaldoes the same for everyone at once. Prices for current Claude models and GPT-6 Luna are built in; add others underbudgets.prices.
On boot the log lists each profile and anything that won't work as written, such as rules about sign-in without IDENTITY_SECRET.
Configuration
See .env.example. The main settings:
How it fits together
Each external tool sits behind an adapter interface in src/adapters/types.ts (KnowledgeSource, Relay), so Slack, other docs sources or trackers plug in without touching the core.
Development
Comparing models
evals/cases.yaml is a set of real-world questions, each with the kind of reply it should get (an answer that links the right page, a handoff, a polite decline, and so on). npm run eval sends each one to the model with your .env settings and docs, scores the replies without an AI judge, and prints pass rate, cost, time and tool calls per model:
Each case runs as a chat with a signed-in person, through the same conversation code as the server, with a fake tracker that starts from the file's backlog of open tickets. Routing cases (kind: route) check what landed in it: a repeat report added to the right existing ticket, a new bug, idea or docs gap filed once with the right kind, or nothing logged for a how-to question. Cases with report: bug or report: feature start from the widget's shortcut, so the assistant should gather the details and log them rather than decide whether to; for a bug it offers a fix from the docs first, and logs nothing only when the person says the fix worked. A case's trail is sent as the widget's recent activity; kind: steps checks that the assistant proposes the steps from it for the person to confirm instead of asking what they did. Every case runs with the shortcuts on, so the routing cases also check that the assistant keeps logging on its own. No real ticket is ever created.
Full replies are saved to evals/results/ (not committed). A run of every case twice on two models costs well under a dollar.
来源:README.md,提交 e522919
工具
0版本历史
1- v1.0.0最新Nov 14, 2026
评分
已满足适用检查项的 85%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通必需25 分
- 已声明认证方式必需10 分
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分