口号
一 主控程序 该服务器允许人工智能助手存储和检索提示、片段和由简短、人类可读的码字键入的任意文本。将其视为您和LLM之间的共享剪贴板——说“将此另存为 *猎鹰*“,然后稍后”给我看看 *猎鹰*".
内置Go。支持SQLite、PostgreSQL和libSQL/Turso。通过stdio、SSE或流式HTTP运行。
现在支持libSQL/Turso --将Watchword指向托管的Turso数据库,用于边缘的SQLite兼容存储。看 Libsql/turso 在......下面
为什么
LLM对话是短暂的。Watchword为您的助手提供了持久的命名存储,因此它可以在令人难忘的关键字下保存有用的提示、模板、代码片段或任何文本,并在会话中回忆它们。
特性
- 10个MCP工具 用于存储、检索、搜索、列出、还原、删除条目和文件上传/下载
- S3文件存储 --通过预签名的URL上传/下载高达1GB的文件(适用于AWS S3和Cloudflare R2)
- 碰撞解决 --如果取了关键字,服务器会自动附加后缀(
rabbit->rabbit2) - SQLite、PostgreSQL或libSQL/Turso 后端
- 自动过期 --条目在可配置的TTL后过期(或永不过期
ttl_hours: 0) - 承载令牌和JWT/JWKS身份验证 --为服务帐户提供可选的命名令牌
- 每次参赛
created_by追踪 --从JWT身份声明或命名的静态令牌填充,出现在读取/列表/搜索响应中 - 健康终点 用于Kubernetes活性/就绪性探测
- 可定制的工具描述 --调整LLM看到的提示
config.yaml - 运输:stdio、SSE、流式HTTP或组合HTTP模式
快速开始
构建
go build -o watchword ./cmd/server使用SQLite(stdio)运行
WORDSTORE_AUTH_TOKEN=secret ./watchword --config config.yaml使用Docker+PostgreSQL运行
docker compose up -d这将通过端口8001上的HTTP传输启动PostgreSQL和Watchword:
- 流式HTTP:
http://localhost:8001/mcp - 上海证券交易所
http://localhost:8001/sse
仅运行PostgreSQL(用于本地stdio开发)
docker compose -f docker-compose.postgres.yml up -d然后在端口5434上的数据库上本地运行二进制文件。
连接到MCP客户端
克劳德桌面
添加 claude_desktop_config.json:
{
"mcpServers": {
"watchword": {
"command": "/path/to/watchword",
"args": ["--config", "/path/to/config.yaml"],
"env": {
"WORDSTORE_AUTH_TOKEN": "your-secret-token"
}
}
}
}克劳德代码(stdio)
claude mcp add watchword /path/to/watchword -- --config /path/to/config.yamlClaude代码(通过Docker流式传输HTTP)
claude mcp add-json watchword '{"type":"http","url":"http://localhost:8001/mcp"}'或添加到 ~/.mcp.json:
{
"mcpServers": {
"watchword": {
"type": "http",
"url": "http://localhost:8001/mcp"
}
}
}MCP工具
文本条目
| 工具 | 说明 |
|---|---|
store_entry | 在关键字下存储有效载荷。自动通过添加数字后缀来解决冲突。 |
get_entry | 通过UUID检索条目。返回完整的有效载荷。 |
get_entry_by_word | 按条目的确切关键字检索条目。返回完整的有效载荷。 |
search_entries | 使用SQL LIKE模式搜索条目(例如。 %cat%).返回精简摘要(无有效负载)。 |
search_words | 轻量级关键字搜索——只返回单词、ID、状态和类型。非常适合浏览。 |
list_entries | 列出具有过滤、排序和分页功能的条目。返回精简摘要(无有效负载)。 |
restore_entry | 将过期的条目恢复为活动状态。 |
delete_entry | 通过UUID永久删除条目 或关键字. |
代币节约设计:list_entries,search_entries,以及search_words故意省略有效载荷内容以保持响应较小。使用get_entry或get_entry_by_word检索特定条目的完整内容。
文件条目(需要S3)
这些工具仅在配置S3时可用。文件数据从不通过MCP服务器,只交换预签名的URL。
| 工具 | 说明 |
|---|---|
upload_file | 创建一个文件条目并获取一个预签名的PUT URL。使用上传 curl -X PUT -T file ''. |
download_file | 获取文件条目的预签名Get URL。下载 curl -o file ''. |
当通过以下方式获取文件条目时 get_entry 或 get_entry_by_word,响应中包含使用提示 download_file 而不是返回原始文件内容。
配置
所有设置均已生效 config.yaml。每个值都可以用前缀为环境变量的值覆盖 WORDSTORE_.
服务器
| 设置 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
server.transport | WORDSTORE_SERVER_TRANSPORT | stdio | stdio, sse, streamable-http,或 http |
server.sse_port | WORDSTORE_SERVER_SSE_PORT | 8080 | 仅用于苏格兰和南方能源公司运输的港口 |
server.http_port | WORDSTORE_SERVER_HTTP_PORT | 8080 | HTTP/可流式HTTP传输端口 |
server.health_port | WORDSTORE_SERVER_HEALTH_PORT | 8081 | 运行状况终结点端口(0表示禁用) |
数据库
| 设置 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
database.driver | WORDSTORE_DATABASE_DRIVER | sqlite | sqlite, postgres,或 libsql |
database.sqlite.path | WORDSTORE_DATABASE_SQLITE_PATH | ./data/word-store.db | SQLite文件路径 |
database.postgres.dsn | WORDSTORE_DATABASE_POSTGRES_DSN | PostgreSQL连接字符串 | |
database.libsql.url | WORDSTORE_DATABASE_LIBSQL_URL | libsql/turso数据库URL(例如。 libsql://my-db-org.turso.io) | |
database.libsql.auth_token | WORDSTORE_DATABASE_LIBSQL_AUTH_TOKEN | Turso身份验证令牌(请勿使用 config.yaml;通过env传递) |
SQLite并发
SQLite后端配置为安全的并发读写:
- WAL日志模式 --一个作者可以同时运行多个读者。
busy_timeout=5000--写入程序在锁争用时最多等待5秒,而不是立即失败。BEGIN IMMEDIATE每笔交易 --防止读写流中的繁忙快照(冲突解决、文件操作)。synchronous=NORMAL+foreign_keys=1应用于每个池连接。- 有界连接池 根据CPU计数确定大小。
SQLite仍然在全局范围内序列化写入程序——这是SQLite的不变性——但读取器并行运行,写入争用被繁忙的超时所吸收。对于大多数MCP工作负载来说,这已经足够了;只有当你需要跨进程编写器或集中式数据库时,才可以使用PostgreSQL。
从PostgreSQL切换到SQLite
驱动程序选择是一个配置翻转;后端之间没有自动数据迁移。
1.更新配置 --要么编辑 config.yaml:
database:
driver: "sqlite"
sqlite:
path: "./data/word-store.db"…或通过env-var重写(优先于 config.yaml):
export WORDSTORE_DATABASE_DRIVER=sqlite
export WORDSTORE_DATABASE_SQLITE_PATH=./data/word-store.db
./watchword目录在 path 在启动时创建,迁移在第一次启动时运行。
2.Docker --默认值 docker-compose.yml 与口号一起启动PostgreSQL。要在SQLite上运行,请停止该组合堆栈(docker compose down)并直接运行二进制文件或使用compose覆盖来删除 postgres 服务,集 WORDSTORE_DATABASE_DRIVER=sqlite 加 WORDSTORE_DATABASE_SQLITE_PATH=/data/word-store.db,并在以下位置挂载一个命名卷 /data 因此DB文件在容器重启后仍然存在。
3.迁移数据(可选) --切换驱动程序从空数据库开始。如果你需要携带物品,请丢弃 entries PostgreSQL中的表(COPY entries TO STDOUT (FORMAT csv, HEADER))并将其加载到SQLite中 .import;模式是等效的,但PostgreSQL timestamptz 在转储过程中,列必须转换为SQLite的RFC3339字符串。
Libsql/turso
相同的 migrations/sqlite/*.sql 迁移运行不变;模式和SQL与本地SQLite文件相同。与本地SQLite后端相比,唯一的行为差异是:
- 没有客户端语法。
journal_mode,busy_timeout,synchronous,foreign_keys在Turso上由服务器控制——不应用本地后端使用的URI pragma格式。 - 递延交易。 Turso没有暴露
_txlock=immediate;碰撞解决仍然依赖于(word, status)独特的约束是真理的源泉。
配置(环境驱动,建议用于机密):
export WORDSTORE_DATABASE_DRIVER=libsql
export WORDSTORE_DATABASE_LIBSQL_URL='libsql://your-db-org.turso.io'
export WORDSTORE_DATABASE_LIBSQL_AUTH_TOKEN=''
./watchword或在 config.yaml:
database:
driver: "libsql"
libsql:
url: "libsql://your-db-org.turso.io"
# auth_token: prefer WORDSTORE_DATABASE_LIBSQL_AUTH_TOKEN env to keep tokens out of source control通过Turso CLI获取URL+身份验证令牌:
turso db create watchword
turso db show watchword --url # → libsql://watchword-.turso.io
turso db tokens create watchword # → eyJhbGciOi...认证
| 设置 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
auth.enabled | WORDSTORE_AUTH_ENABLED | true | 启用/禁用身份验证 |
auth.tokens | WORDSTORE_AUTH_TOKENS | 逗号分隔的承载令牌(匿名-- created_by 左为空) | |
auth.named_tokens | 列表 {name, token} 对。使用命名令牌记录的请求 created_by = name。参见 追踪谁创建了条目. | ||
WORDSTORE_AUTH_TOKEN | 用于stdio传输验证的令牌 |
JWT/JWKS
| 设置 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
auth.jwt.jwks_url | WORDSTORE_AUTH_JWT_JWKS_URL | 用于公钥发现的JWKS端点(在以下情况下需要 jwt 块存在) | |
auth.jwt.issuer | WORDSTORE_AUTH_JWT_ISSUER | 预计 iss claim(完全匹配——Auth0发出尾随斜线,Keycloak不发出) | |
auth.jwt.audience | WORDSTORE_AUTH_JWT_AUDIENCE | 预计 aud 声明(推荐用于OAuth--RFC 8707) | |
auth.jwt.required_scopes | WORDSTORE_AUTH_JWT_REQUIRED_SCOPES | 逗号分隔的范围必须全部存在;对照 scope claim(空格分隔字符串)和 scp 索赔(数组)。如果未设置,签名+iss+aud就足够了。 | |
auth.jwt.identity_claim | WORDSTORE_AUTH_JWT_IDENTITY_CLAIM | sub | 用于填充的索赔 created_by 在存储的条目上。常见替代方案: email, preferred_username. |
受保护资源元数据(RFC 9728)
MCP OAuth需要使用草案规范服务 /.well-known/oauth-protected-resource 因此MCP客户端(如Claude.ai)可以发现您的授权服务器。
| 设置 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
auth.resource_metadata.resource | WORDSTORE_AUTH_RESOURCE | 此MCP服务器的规范URI(例如。 https://watchword.example.com) | |
auth.resource_metadata.authorization_servers | WORDSTORE_AUTH_AUTHORIZATION_SERVERS | 逗号分隔的授权服务器颁发者URI | |
auth.resource_metadata.bearer_methods_supported | WORDSTORE_AUTH_BEARER_METHODS | header | 逗号分隔的承载方法 |
auth.resource_metadata.scopes_supported | WORDSTORE_AUTH_SCOPES_SUPPORTED | 逗号分隔的范围(可选) |
配置后,401响应包括 WWW-Authenticate 标题与 resource_metadata 符合MCP规范的URL。
传统授权服务器元数据
为了向后兼容2025-03-26 MCP规范,Watchword也可以提供 /.well-known/oauth-authorization-server。这仅在Watchword本身充当授权服务器时才需要。两者都需要 jwt 和 oauth_metadata 阻碍。
| 设置 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
auth.oauth_metadata.authorization_endpoint | WORDSTORE_AUTH_OAUTH_AUTHORIZATION_ENDPOINT | 授权端点URL | |
auth.oauth_metadata.token_endpoint | WORDSTORE_AUTH_OAUTH_TOKEN_ENDPOINT | 令牌端点URL |
MCP OAuth与Claude.ai
要使用OAuth将Claude.ai连接到Watchword,您需要:
- 授权服务器 (例如Auth0、Keycloak、Cloudflare Workers)发放JWT访问令牌
- 监视字配置为资源服务器 包含RFC 9728元数据
OAuth的配置示例:
auth:
enabled: true
resource_metadata:
resource: "https://watchword.example.com"
authorization_servers:
- "https://auth.example.com"
jwt:
jwks_url: "https://auth.example.com/.well-known/jwks.json"
issuer: "https://auth.example.com/"
audience: "https://watchword.example.com"OAuth流程的工作原理如下:
- Claude向Watchword发送未经身份验证的请求
- 监视词返回
401随着WWW-Authenticate: Bearer resource_metadata="https://watchword.example.com/.well-known/oauth-protected-resource" - Claude获取受保护的资源元数据以发现授权服务器
- Claude与授权服务器进行身份验证并获得JWT
- Claude向发送请求
Authorization: Bearer - Watchword验证JWT签名(通过JWKS)、发布者和受众
在Claude的授权服务器中注册这些重定向URI:
https://claude.ai/api/mcp/auth_callbackhttps://claude.com/api/mcp/auth_callbackhttp://localhost:6274/oauth/callback(克劳德密码)
供应商特定注意事项
监视词一次验证一个IdP。选择钥匙斗篷 或 Auth0(或Cloudflare Workers OAuth提供者);现成的配置住在 examples/keycloak.yaml 和 examples/auth0.yaml.
钥匙斗篷
jwks_url:{base}/realms/{realm}/protocol/openid-connect/certsissuer:{base}/realms/{realm}(无尾随斜线)audience:默认情况下,Keycloak放置account在aud.将其视为有效受众接受任何领域用户-它不将令牌绑定到此API。创建一个 *观众* 发出自定义值的客户端作用域(例如。watchword),将其分配给您的客户端,并设置audience到这个值。- 作用域:定义客户端作用域(例如。
watchword:read,watchword:write)并要求他们required_scopesKeycloak将他们送入scope索赔。
身份验证0
jwks_url:https://{tenant}.auth0.com/.well-known/jwks.jsonissuer:https://{tenant}.auth0.com/(尾随斜线--Auth0发出它iss完全匹配)audience:Auth0 API中的API标识符(例如。https://watchword.example.com/api)- 作用域:在Auth0 API上定义它们并授予应用程序/用户;Auth0将它们发送到
scope索赔。
云耀
这里显示了两种不同的Cloudflare产品——它们的行为不同:
- Cloudflare Workers OAuth提供程序 (模式在
docs/cloudflare-worker-oauth-proxy.md)--符合Watchword的承载令牌流。工人发布自己的JWT;aud就是工人盖章的内容。集audience对于该值,点jwks_url/issuer在Worker的众所周知的端点,并将其视为Auth0/Keycloak。 - Cloudflare 访问 (零信任应用门控) *不* 干净地合身。Access在
Cf-Access-Jwt-Assertionheader(和cookie),不是Authorization: Bearer.aud是每份申请 *申请AUD* 标签(来自Access仪表板的十六进制字符串);JWKS在https://.cloudflareaccess.com/cdn-cgi/access/certs发行人是https://.cloudflareaccess.com。最好用作普通MCP身份验证前面的前门,而不是MCP身份验证本身。
如何 aud 根据提供者进行形状设置
aud 通过以下方式执行 jwt.WithAudience (精确匹配),它接受字符串或数组——只需要匹配一个条目。每个提供商的问题:
| 提供者 | 地点 aud 来源于 | 形状 | 要放什么 audience |
|---|---|---|---|
| Keycloak | 客户端作用域上的受众协议映射器 | 字符串或数组(通常包括 "account") | 受众映射器发出的自定义值(例如。 "watchword").不要将其设置为 "account" --它接受每个域用户。 |
| Auth0 | audience 查询参数已发送至 /authorize | 阵列,通常 [, "https://{tenant}.auth0.com/userinfo"] | API标识符(与第一个数组条目匹配)。如果客户忽略 audience 在 /authorize,Auth0返回一个不透明的令牌(不是JWT)——这些令牌将无法验证。 |
| Cloudflare Worker OAuth | 无论Worker代码标记什么 | 取决于Worker | Worker使用的确切值。 |
| Cloudflare Access | 应用程序AUD标签 | 字符串(十六进制) | 来自Access仪表板的应用程序AUD。注意:Access使用非-Authorization 头,因此交换它需要更改中间件。 |
追踪谁创建了条目
Watchword在每个新条目上以可空的形式记录创建者的身份 created_by 列。立柱表面 get_entry, get_entry_by_word, list_entries, search_entries, search_words, store_entry, restore_entry,以及 upload_file 响应。它留下来了 null 匿名电话。
哪里 created_by 来自:
- JWT请求: 价值
auth.jwt.identity_claim(默认值sub).设置为email或preferred_username如果你想要一个人类可读的标签。 - 命名静态令牌: 这
name的匹配auth.named_tokens进入。 - 平原
auth.tokens: 匿名(created_by为null)--这些令牌没有关联的标识。 - 身份验证已禁用: 匿名。
auth:
enabled: true
named_tokens:
- name: ci-bot
token: "ci-secret-xyz"
- name: alice
token: "alice-secret-xyz"
jwt:
jwks_url: "https://{tenant}.auth0.com/.well-known/jwks.json"
issuer: "https://{tenant}.auth0.com/"
audience: "https://watchword.example.com/api"
identity_claim: "email"恢复过期条目会保留原始条目 created_by;它不会被恢复器覆盖。
所需范围
auth.jwt.required_scopes 在发行者/受众之上强制执行细粒度访问。每个列出的范围都必须出现在 scope claim(空格分隔字符串,由Auth0和Keycloak使用)或 scp 索赔(数组)。如果没有此选项,则接受来自配置的颁发者/受众的任何有效令牌。
auth:
jwt:
jwks_url: "https://{tenant}.auth0.com/.well-known/jwks.json"
issuer: "https://{tenant}.auth0.com/"
audience: "https://watchword.example.com/api"
required_scopes:
- "watchword:read"
- "watchword:write"S3文件存储(可选)
配置后,监视字寄存器 upload_file 和 download_file 工具。文件存储在S3(或任何与S3兼容的服务,如Cloudflare R2)中,并通过预签名的URL传输——MCP服务器从不接触文件数据。
| 设置 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
s3.enabled | WORDSTORE_S3_ENABLED | *(未设置)* | 设置为 false 强制禁用S3,即使其他 s3.* / WORDSTORE_S3_* 值存在。适用于可能泄漏部分S3环境变量的环境。 |
s3.endpoint | WORDSTORE_S3_ENDPOINT | *(空=AWS)* | 自定义端点URL(R2、MinIO需要) |
s3.region | WORDSTORE_S3_REGION | AWS区域(例如。 eu-central-1) | |
s3.bucket | WORDSTORE_S3_BUCKET | S3存储桶名称 | |
s3.key_prefix | WORDSTORE_S3_KEY_PREFIX | *(空)* | 每个新对象键前都添加了可选的文件夹/前缀(例如。 tenants/acme).现有条目保留其存储的密钥。 |
s3.presign_ttl_minutes | WORDSTORE_S3_PRESIGN_TTL_MINUTES | 15 | 预签名URL的有效期 |
s3.max_file_size_bytes | WORDSTORE_S3_MAX_FILE_SIZE_BYTES | 1073741824 | 最大文件大小(默认1GB) |
WORDSTORE_S3_ACCESS_KEY_ID | S3访问密钥(仅限env-var,从不在配置文件中) | ||
WORDSTORE_S3_SECRET_ACCESS_KEY | S3密钥(仅限env-var,从不在配置文件中) |
Cloudflare R2的配置示例:
s3:
endpoint: "https://.r2.cloudflarestorage.com"
region: "auto"
bucket: "watchword-files"
presign_ttl_minutes: 15
max_file_size_bytes: 1073741824export WORDSTORE_S3_ACCESS_KEY_ID="your-r2-access-key"
export WORDSTORE_S3_SECRET_ACCESS_KEY="your-r2-secret-key"AWS S3的配置示例:
s3:
region: "eu-central-1"
bucket: "watchword-files"S3对象清理:过期的文件条目不会自动删除S3对象。使用 S3生命周期规则 用于垃圾收集。
如果 s3 未配置,仅注册了原始的基于文本的工具,不依赖于S3。部分S3配置(例如,区域设置但没有存储桶,或缺少凭据)不起作用 不 启动失败——Watchword会记录一条警告,并在禁用文件工具的情况下继续。在某些环境中显式禁用S3 WORDSTORE_S3_* env变量可能会泄漏(例如共享的k8s ConfigMaps),设置 s3.enabled: false (或 WORDSTORE_S3_ENABLED=false)--加载配置后,整个S3块将被丢弃。
过期
| 设置 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
expiration.enabled | WORDSTORE_EXPIRATION_ENABLED | true | 运行后台过期工作程序 |
expiration.interval_hours | WORDSTORE_EXPIRATION_INTERVAL_HOURS | 24 | 工人多久检查一次过期的条目 |
expiration.ttl_hours | WORDSTORE_EXPIRATION_TTL_HOURS | 168 | 新条目的默认TTL(7天)。 0 =永不过期 |
要完全禁用过期,请设置 expiration.enabled: false 和 expiration.ttl_hours: 0。单个条目可以通过传递来覆盖默认TTL ttl_hours 存储时(设置为 0 无过期)。
日志记录
| 设置 | 环境变量 | 默认值 | 描述 |
|---|---|---|---|
logging.level | WORDSTORE_LOGGING_LEVEL | info | debug, info, warn, error |
logging.format | WORDSTORE_LOGGING_FORMAT | json | json 或 text |
健康终点
可在单独的端口上使用(默认 8081)用于监控和Kubernetes探测。
| 端点 | 目的 | 响应 |
|---|---|---|
GET /healthz/live | 活体探针 | 200 如果进程正在运行 |
GET /healthz/ready | 准备就绪探针 | 200 如果数据库是可访问的, 503 否则 |
GET /status | 详细状态 | 200 包含版本、正常运行时间、数据库状态、内存、goroutine计数 |
部署
码头工人
docker build -t watchword:latest .
docker compose up -dKubernetes
使用 http Kubernetes的传输——它同时服务于流式HTTP(/mcp)苏格兰和南方能源公司(/sse)在一个港口。
# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: watchword-config
data:
config.yaml: |
server:
transport: "http"
http_port: 8080
health_port: 8081
database:
driver: "postgres"
auth:
enabled: true
expiration:
enabled: true
interval_hours: 24
ttl_hours: 168
logging:
level: "info"
format: "json"
---
# Secret — auth settings via env vars
apiVersion: v1
kind: Secret
metadata:
name: watchword-secret
type: Opaque
stringData:
WORDSTORE_AUTH_TOKENS: "your-token-here"
WORDSTORE_DATABASE_POSTGRES_DSN: "postgres://watchword:changeme@postgres:5432/watchword?sslmode=require"
# MCP OAuth (RFC 9728) — uncomment to enable
# WORDSTORE_AUTH_RESOURCE: "https://watchword.example.com"
# WORDSTORE_AUTH_AUTHORIZATION_SERVERS: "https://auth.example.com"
# WORDSTORE_AUTH_JWT_JWKS_URL: "https://auth.example.com/.well-known/jwks.json"
# WORDSTORE_AUTH_JWT_ISSUER: "https://auth.example.com/"
# WORDSTORE_AUTH_JWT_AUDIENCE: "https://watchword.example.com"
---
# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: watchword
spec:
replicas: 1
selector:
matchLabels:
app: watchword
template:
metadata:
labels:
app: watchword
spec:
containers:
- name: watchword
image: your-registry/watchword:1.0.0
args: ["--config", "/etc/watchword/config.yaml"]
ports:
- name: http
containerPort: 8080
- name: health
containerPort: 8081
envFrom:
- secretRef:
name: watchword-secret
volumeMounts:
- name: config
mountPath: /etc/watchword
readOnly: true
livenessProbe:
httpGet:
path: /healthz/live
port: health
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz/ready
port: health
initialDelaySeconds: 3
periodSeconds: 5
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
volumes:
- name: config
configMap:
name: watchword-config
---
# Service
apiVersion: v1
kind: Service
metadata:
name: watchword
spec:
selector:
app: watchword
ports:
- name: http
port: 8080
targetPort: http
- name: health
port: 8081
targetPort: health笔记:
- 复制品:对同一PostgreSQL运行多个副本是安全的——冲突解决使用数据库级唯一约束。
- 迁移:启动时自动运行(通过跟踪
schema_migrations桌子)。 - 秘密:切勿在ConfigMap中放置令牌。使用Kubernetes Secrets或外部秘密管理器。
测试
go test ./...建筑
cmd/server/main.go Entry point, config loading, DI wiring, graceful shutdown
internal/domain/ Entry struct, validation, sentinel errors
internal/config/ YAML + env var config loading
internal/repository/ Repository interface + SQLite/PostgreSQL implementations
internal/service/ Business logic (collision resolution, store, restore, search, file ops)
internal/s3/ S3 presigned URL client (AWS SDK v2)
internal/auth/ Bearer token and JWT/JWKS validation
internal/mcp/ MCP server setup and tool handlers
internal/worker/ Background expiration goroutine
internal/health/ Health/status HTTP endpoints
migrations/ Embedded SQL migrations (SQLite + PostgreSQL)品牌资产
SVG标记在 assets/ 并使用 currentColor,因此它们会拾取周围的文本颜色。
| 资产 | 文件 | 大小 |
|---|---|---|
| 徽标标记 | logo.svg | 200×200 |
图标 favicon.svg | 32×32 | |
| 水平锁定 | lockup.svg | 600×140 |
许可证
______________________________________________________________________
监视词——人工智能代理的持久内存
开源MCP(模型上下文协议)服务器,允许任何AI代理在令人难忘的关键字下存储和调用文本、提示和文件。Claude、ChatGPT、Cursor、Gemini、Copilot、Codex CLI、Kilo Code、Grok CLI和任何其他MCP客户端之间的共享内存。
它的作用
一个代理将结果放在关键字下,另一个代理拾取并继续执行。下一个聊天,另一台机器,队友的设置。没有文件,没有复制粘贴,没有“你能重新发送吗?”
您可以将任何工作(设计决策、研究总结、提示、文件)保存到Watchword中的一个令人难忘的关键字下。任何说MCP的AI工具都可以通过该关键字立即检索它:在下一次聊天中,在另一台机器上,或者在完全不同的设置中由你的队友检索。
主要特点
- 停止发送文件 --直接从你的AI中保存工作。你的队友从他们的AI中检索它。没有附件,没有链接,没有“这是哪个版本?”
- 跨聊天和会话工作 --即使在新的聊天窗口、新的会话或新的上下文中,也要准确地从你离开的地方继续。
- 为您生成的智能关键字 --保存时,您的AI会自动建议一个相关的、人类可读的关键字。
- 适用于任何AI工具 --Claude、Cursor、Copilot、定制代理——如果它说MCP,它就可以使用Watchword。没有供应商锁定。
- 为整个团队共享内存 --一个Watchword实例,在队友之间共享。每个人的人工智能都基于同一个基本事实。
- 开源和自托管 --在您自己的基础设施上部署。您的数据永远不会接触到第三方服务器。麻省理工学院许可。
- 每个条目最多可处理1 GB --大型代码库,完整的研究转储,大量输出。
- 自动过期7天后 --默认情况下,条目会自行清理。支持按条目TTL覆盖。
技术与部署
- Go二进制、Docker镜像或Kubernetes清单
- SQLite用于本地开发和单用户安装(无需设置)
- PostgreSQL用于生产和多副本Kubernetes部署
- 迁移在启动时自动运行
- 在render.com上一键部署蓝图——fork,设置3个secrets,部署
- Turso/libSQL持久存储——空闲层覆盖约500 MB和1B行读取
- 自动HTTPS、自定义域、每次git推送时零停机重新部署
- 免费渲染层+免费Turso层起价为0美元
认证
- 持有者代币(
WORDSTORE_AUTH_TOKENS)对于独奏开发 - 针对任何IdP的JWT/JWKS验证——Auth0、Keycloak、Cognito、Cloudflare Access
- OAuth 2.1+PKCE,通过附带的Cloudflare Worker进行动态客户端注册(RFC 7591)
- RFC 9728/RFC 8414用于MCP客户端自动发现的受保护资源元数据(例如Claude.ai连接器流)
- 受众范围、每个用户的身份声明、命名人类的审计日志
付费附加组件:MCP认证设置指南
Watchword和您团队提供的任何MCP服务器的生产级身份验证蓝图。PDF+复制粘贴配置。一次性购买,终身更新。涵盖了承载令牌、针对Auth0/Keycloak/Cognito/Cloudflare Access的JWT/JWKS、用于Claude.ai连接器的带DCR的Cloudflare Worker OAuth 2.1代理、反向代理模式(Caddy/Nginx/Traefik)和27个经过生产验证的设置陷阱(包括7个未在官方文档中的Auth0 DCR拦截器)。
______________________________________________________________________
👉 访问异端.giglabo.com/tools/watchword
为什么点击? 获取一键渲染部署蓝图、完整部署指南和MCP身份验证设置指南——您需要从中获取的所有内容 git clone 您的整个团队的AI代理可以在不到10分钟的时间内共享到生产MCP服务器。停止在聊天之间粘贴文件。给你的特工一个记忆。
