@vllnt/convex-helpers
Typed Convex host-side utilities, trusted-origin and cookie configuration helpers, identity-row glue, and optional MCP tools.
接入你的智能体
发布者自己的命令。不是 PlugMCP 端点。
用我们的密钥与日志托管一份副本。
npx -y @vllnt/[email protected]Claude Code 没有针对本地命令的安装链接。复制下方命令并在终端中运行。
claude mcp add vllnt-convex-helpers -- npx -y @vllnt/convex-helpers@0.1.0在终端中运行。
{ "mcpServers": { "vllnt-convex-helpers": { "command": "npx", "args": [ "-y", "@vllnt/[email protected]" ] } }}claude_desktop_config.json
远程 URL 还是本机命令? 两种安装方式的区别
import { asyncMap, pruneNull, nullThrows } from "@vllnt/convex-helpers";
const docs = pruneNull(await asyncMap(ids, (id) => ctx.db.get(id)));
const doc = nullThrows(await ctx.db.get(id), `Document ${id} not found`);
A helpers library (not a sandboxed Convex component): pure functions and host-ctx glue that run with
the host's ctx — no own tables, no app.use() mounting. Stateful concerns (rate limiting,
idempotency, flags) belong in @convex-dev/* or @vllnt/convex-* components.
See ROADMAP.md for the planned module surface.
asyncMap — parallel async map that preserves orderpruneNull — filter null/undefined from arraysnullThrows — non-null assertion with typed NullDocumentError./better-auth — fail-closed trusted origins + HTTPS cookies for better-auth./identity — identity-row lookup/bootstrap and bounded row-callback counting./mcp — expose Convex functions as MCP tools (createMCPServer + query/mutation/action/resource), default-deny auth, optional cursor pagination./builders — customQuery/customMutation/customAction/customCtx./errors — typed AppError + HTTP-status map./env — defineEnv(zodSchema) cold-start validation./tracing — span emit + traceparent propagation via @vllnt/logger./testing — fixture factories + withIdentity./relationships, ./validators, ./pagination, ./rls, ./triggers, ./http./react — optional tree-shakeable front-end hooks layerpnpm add @vllnt/convex-helpers
convex is a peer dependency:
pnpm add convex
import { asyncMap, pruneNull, nullThrows } from "@vllnt/convex-helpers";
// Parallel fetch with null filtering
const docs = pruneNull(await asyncMap(ids, (id) => ctx.db.get(id)));
// Non-null assertion
const doc = nullThrows(await ctx.db.get(id), `Document ${id} not found`);
./mcpExpose Convex functions to LLM agents over the Model Context Protocol. The ./mcp entry is
tree-shakeable — backend-only consumers pull zero MCP code. It needs two optional peer deps:
pnpm add @modelcontextprotocol/sdk zod
import { createMCPServer, query, mutation } from "@vllnt/convex-helpers/mcp";
import { api } from "./_generated/api";
import { v } from "convex/values";
export const mcp = createMCPServer({
auth: { validate: async (key) => key === process.env.MCP_API_KEY },
tools: {
list_projects: query(api.projects.list, { args: v.object({}), description: "List all projects" }),
create_project: mutation(api.projects.create, {
args: v.object({ name: v.string() }),
description: "Create a project",
}),
},
});
// Mount the route handler (e.g. Next.js App Router)
export const { GET, POST } = mcp.handler();
MCP auth and lifecycle callbacks have a 10-second deadline per callback. A thrown
or timed-out before hook denies dispatch with a generic message. Auth failures
also deny access generically. Success/error hooks cannot undo completed dispatch.
Timeouts stop waiting, not the host callback; callbacks must avoid side effects.
Raw errors are not logged by the library; hosts may observe hook context and must
redact errors, arguments and credentials before logging. Resource failures are
masked without raw logging.
./better-authFail-closed trusted-origin parsing and HTTPS cookie attributes. Does not import
better-auth — the host still calls betterAuth({...}).
import {
cookieSettingsForSite,
trustedOriginsFromCsv,
} from "@vllnt/convex-helpers/better-auth";
const trustedOrigins = trustedOriginsFromCsv(
process.env.CONVEX_SITE_URL ?? "http://localhost:3211",
process.env.BETTER_AUTH_TRUSTED_ORIGINS ?? "",
);
parseTrustedOrigin rejects credentials, paths, query/hash, controls and arbitrary
wildcards. HTTP is allowed only for exact localhost/127.0.0.1 origins. An explicit
previewPattern permits only HTTPS patterns shaped like
https://app-*-org.example.com (one wildcard inside a prefixed/suffixed first label).
The host must trust every deployment matched by its auth provider's wildcard
semantics; syntax validation does not establish deployment ownership.
Invalid extras are discarded; if none survive, the list helpers return undefined,
so the host omits trustedOrigins and retains Better Auth defaults. They do not
validate the host's entire auth configuration. cookieSettingsForSite(siteUrl)
returns secure, HttpOnly, SameSite=None attributes for a valid HTTPS origin only;
it does not replace CSRF/origin protection and is for hosts requiring cross-site cookies.
./identityMap ctx.auth.getUserIdentity() to a host row. The host must configure a trusted
single issuer (subjects are issuer-local). To enforce it locally, pass
{ auth: ctx.auth, trustedIssuer: "https://your-trusted-issuer.example" } as the
helper context. A mismatched or missing issuer rejects before lookup/insert. The
issuer must be host configuration, never a request argument. Omitting it preserves
compatibility and relies on the host's single-issuer auth configuration.
Provide callbacks bound to the same
Convex mutation transaction, including the indexed lookup, for race-safe bootstrap.
Every competing creator must use the same lookup. Actions or remote callbacks are
not race-safe. isAnonymous reflects only a literal true JWT claim; missing/false
claims do not prove a verified or identified account.
retargetRows(rows, apply) processes at most 1000 rows sequentially, counts
patched/deleted/skipped, and propagates failures without starting later rows.
The host supplies bounded pages, authorization for both identities, conflict rules,
continuation, transaction/rollback and logging. It is not a secure account merge.
These helpers neither construct betterAuth nor install its anonymous plugin.
import { getOrCreateFromAuth, retargetRows } from "@vllnt/convex-helpers/identity";
const user = await getOrCreateFromAuth(ctx, {
lookup: (subject) =>
ctx.db.query("users").withIndex("by_betterauth_id", (q) =>
q.eq("betterAuthId", subject),
).unique(),
insert: async (subject) => {
const id = await ctx.db.insert("users", { betterAuthId: subject });
return (await ctx.db.get(id))!;
},
});
Migrating from @vllnt/convex-mcp? Change the import to @vllnt/convex-helpers/mcp — the API is
identical. See docs/API.md for the full ./mcp reference.
See docs/API.md for full API reference with signatures and examples.
pnpm test
pnpm test:coverage # must reach 100%
Tests use vitest with the node environment. 100% coverage is enforced via
vitest.config.mts thresholds. Identity integration tests use convex-test mocks;
they do not prove real Better Auth sessions or anonymous plugin integration.
The separate scripts/local-identity-proof.mjs passed 16 concurrent real local-backend
bootstrap mutations with an injected synthetic identity (one row); this tests indexed
OCC, not login. Consuming apps must verify their actual auth integration independently.
See CONTRIBUTING.md for development setup, code style, and PR guidelines.
Built by bntvllnt · bntvllnt.com · X @bntvllnt
If this is useful, sponsor the work.
Typed host-side helpers for Convex backends — builders, errors, validators, relationships, pagination, HTTP, env, and observability.
{ "mcpServers": { "vllnt-convex-helpers": { "command": "npx", "args": [ "-y", "@vllnt/[email protected]" ] } }}工具
暂无工具列表。远程服务器在首次健康检查后会获得工具列表。
常见问题
在本页复制适用于 Cursor、Claude Desktop、Claude Code 或 VS Code 的 stdio 配置。它使用发布者的安装方式,而不是 PlugMCP 代理。
此记录未列出必需的环境变量。
@vllnt/convex Helpers 通过 stdio 在本地运行。
上次检查时间:2026-11-13。 Typed host-side helpers for Convex backends — builders, errors, validators, relationships, pagination, HTTP, env, and observability.