内容
# 太阳影子计时器
<!-- mcp-name: io.github.lihtness/gnomon-mcp -->
[](https://pypi.org/project/gnomon-mcp/) [](https://pypi.org/project/gnomon-mcp/) [](LICENSE) [](https://registry.modelcontextprotocol.io/v0/servers?search=gnomon)
> 太阳影子计时器:将影子转化为时间。
一个用于模型所需的基本实用工具的小型MCP服务器:日期、 日历、 算术、 单位转换。 使用它可以让您的助手停止进行数学和日期数学的“下一次预测”。
## 为什么
大型语言模型(LLM)默认情况下不擅长算术和日期数学。 它们生成的答案看似合理,但通常会因小错误而导致结果错误——这正是很难在长篇回复中察觉到的错误类型。 `gnomon-mcp` 通过MCP公开了确定性的Python实现,以便您的模型可以计算而不是猜测。
### 什么时候应该使用gnomon
任何情况下,如果下一个合理的标记不是正确答案时,都应该使用gnomon。具体来说:
- **重要的数学运算** — 超出简单的心算的任何运算,任何带有小数点的运算,任何复合运算。 调用 `calc`。
- **“今天是几号” / “还有多久” / “过了多久”** — 模型的训练截止日期不是今天。 调用 `now` 获取快照; 调用 `calendar` 并带上 `until`/`since`/`diff` 获取时间间隔; 调用 `parse` 获取自然语言日期(“下周四”)。
- **跨月/年边界的日期运算** — 增加30天,找到季度末,计算工作日。 模型经常会犯这些错误。 调用 `calendar` 并带上 `add` / `business_days`。
- **单位转换** — 调用 `calc_convert`。 永远不要凭估计进行“千克→磅”或“摄氏度→华氏度”的转换。
- **表格行工作负载** — 当同一类型的计算需要在表格的每一行上运行时,两个批处理工具(`calendar`,`calc`)都接受一个列表并按顺序返回一个列表。 一次调用,N个结果。
经验法则:如果您会让同事“仔细检查这个数字”,请改为调用gnomon。
### 与其他MCP服务器的比较
时间 和 数学 已经有几个MCP服务器——官方的 [`Time`](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/time) 参考(仅时区), [`mcp-time`](https://github.com/TheoBrigitte/mcp-time) 和 [`mcp-datetime`](https://github.com/ZeparHyfar/mcp-datetime) (日期格式化/时区), [`calculator-server`](https://github.com/avisangle/calculator-server) (数学+单位,无日期),以及像 [`agent-utils-mcp`](https://github.com/aparajithn/agent-utils-mcp) (正则表达式/哈希/JWT)这样的捆绑包。 gnomon的范围更窄:
- **批量优先。** `calendar(ops)` 和 `calc(expressions)` 接受列表; 一个工具调用涵盖整个表格列,而非N个调用。
- **真正的 `now()`。** 一个调用返回18个字段——ISO周、季度、财政年、年日、`is_weekend`等——而不仅仅是 `{iso, tz}`。
- **日期 *和* 数学 *和* 单位在一个线路中。** 无需组合三个独立的服务器。
- **内置自然语言日期** (“下周四”,“3小时后”)无需单独的NLP服务器。
如果您只需要时区转换,则官方的 `Time` 服务器就足够了。 如果您想要一个广泛的实用工具包(正则表达式、哈希、编码、JWT),则 `agent-utils-mcp` 更合适。 gnomon用于基本的日期算术和数学核心,批量处理。
## 工具
### 日历
两个工具:
- **`now(tz?)`** — 独立使用。 返回当前时刻的丰富字典快照。 一次调用即可获取关于“当前时刻”的所有信息。
- **`calendar(ops)`** — 批量调度器。 每个项目选择自己的操作。 设计用于表格行工作负载(例如,一次调用为每行计算时间间隔)。
**`now(tz?)`** 返回:
```python
{
"iso": "2026-05-25T14:30:45+00:00",
"date": "2026-05-25",
"time": "14:30:45",
"unix": 1779345045,
"tz": "UTC",
"year": 2026, "month": 5, "month_name": "五月", "day": 25,
"weekday": "星期一", "weekday_num": 0, # 0=星期一
"day_of_year": 145, "week_of_year": 22, # ISO周
"quarter": 2, "fiscal_year_us_gov": 2026, # 财政年从10月1日开始
"hour": 14, "minute": 30, "second": 45,
"is_weekend": False,
}
```
**`calendar(ops)`** 操作:
| 操作 | 参数 | 返回值 |
|---|---|---|
| `diff` | `start, end, unit` | `end - start` — 两个已知日期之间的时间间隔 |
| `until` | `target, unit, tz?` | `target - now` — 到达未来某个时间点的时间(如果已过去则为负) |
| `since` | `source, unit, tz?` | `now - source` — 自过去某个时间点以来经过的时间(如果未来则为负) |
| `add` | `date, n, unit` | `date + n units`的ISO(`seconds\|...\|weeks`,加上`months\|years`日历感知) |
| `weekday` | `date` | `"星期一"`..`"星期日"` |
| `business_days` | `start, end` | 工作日计数(周一至周五)(开始包含,结束排除) |
| `parse` | `natural, tz?` | 自然语言的ISO(“下周四”,“3小时后”) |
| `format` | `date, fmt` | strftime格式化的字符串 |
`diff`/`until`/`since`的单位: `seconds`, `minutes`, `hours`, `days`, `weeks`.
示例 — 一次调用计算多个值:
```python
calendar([
{"op": "until", "target": "2026-12-31", "unit": "days"}, # 今年剩余的天数
{"op": "since", "source": "2026-01-01", "unit": "days"}, # 今年已过去的天数
{"op": "diff", "start": "2026-01-01", "end": "2026-12-31", "unit": "days"},
{"op": "weekday", "date": "2026-05-25"}, # "星期一"
{"op": "add", "date": "2026-05-25", "n": 1, "unit": "months"},
{"op": "parse", "natural": "下周四", "tz": "America/Los_Angeles"},
])
```
### 计算器
| 工具 | 用途 |
|---|---|
| `calc(expressions)` | 评估一个Python表达式列表并返回结果列表。 加载了数学(`sqrt`、`sin`、`log`、`pi`、`e`等)、统计(`mean`、`median`、`stdev`、`variance`)和实用内置函数(`abs`、`round`、`min`、`max`、`sum`、`range`、`sorted`等)。 批量输入/输出,保留顺序。 |
| `calc_convert(value, from_unit, to_unit)` | 通过Pint进行单位转换(`meter` → `foot`,`kg` → `lb`,`degC` → `degF`等)。 |
示例:
```python
calc(["2 + 3 * 4"]) # [14]
calc(["sqrt(16)", "sin(pi/2)"]) # [4.0, 1.0]
calc(["mean([1, 2, 3, 4])"]) # [2.5]
calc(["sum(range(101))"]) # [5050]
calc(["(25 / 100) * 100"]) # [25.0]
```
## 未来的工具(草图)
同样的逻辑——*如果模型可能会胡乱猜测,公开一个确定性的版本*——指向其他几个值得构建的基本功能。 这些都尚未实现; 它们是候选者,按重要性从高到低列出:
1. **文本测量** — `count(text, unit)` 用于字符/字/行/句子/LLM令牌。 代理经常会误判“长度是多少”和“是否适合上下文窗口”。
2. **正则表达式匹配/替换** — `regex_find(pattern, text)` 和 `regex_sub(pattern, repl, text)`。 模型会胡乱猜测哪些子字符串与正则表达式匹配; 真实的引擎可以终结争论。
3. **结构化数据提取** — `jq(path, json)` / `jsonpath(path, json)`。 通过路径从嵌套的blob中读取值,不会出现拼写错误。
4. **哈希和编码** — `hash(text, algo)` (sha256,md5,blake2),`encode(text, scheme)` / `decode(text, scheme)` (base64,十六进制,网址,jwt-payload)。 所有模型都自信地编造错误答案。
5. **十进制货币数学** — 在Python的`Decimal`下求值且显式舍入的`money(expr)`。 `calc`基于浮点数,对于货币来说是不安全的。
6. **假期感知的工作日** — 扩展 `calendar.business_days`,添加一个 `country` (或 `calendar`)参数,以便排除美国/英国/印度的假期。 当前实现只知道周末。
7. **Cron描述/下一次触发** — `cron_describe("0 9 * * 1-5")` → 人类易读的英文; `cron_next(expr, n)` → 下一次触发时间。 模型经常会误读cron字段。
8. **目标模型的令牌计数** — 通过tiktoken / Anthropic分词器的`count_tokens(text, model)`。 让代理为自己的提示和输出预算,而不是猜测。
如果您需要其中之一,请提出问题(或拉取请求 — 每个都是一个小而独立的模块,适合现有的 `tools/` 布局)。
## 安装
推荐:无需安装 — 按需使用 [`uv`](https://docs.astral.sh/uv/):
```bash
uvx gnomon-mcp # 为任何客户端提供stdio MCP服务,随时可用
uvx gnomon-mcp --demo # 调用每个工具一次并打印结果(无需MCP客户端)
```
或全局安装:
```bash
pip install gnomon-mcp
```
## 将其连接到您的代理
所有配方都假设 `uvx gnomon-mcp`。 如果您更喜欢固定的安装,请将命令替换为 `gnomon-mcp`(不带 `uvx`)。
### Claude 代码
```bash
claude mcp add gnomon -- uvx gnomon-mcp
```
或编辑 `~/.claude.json` / 项目 `.mcp.json`:
```json
{
"mcpServers": {
"gnomon": { "command": "uvx", "args": ["gnomon-mcp"] }
}
}
```
### Claude 桌面版
`claude_desktop_config.json`:
```json
{
"mcpServers": {
"gnomon": { "command": "uvx", "args": ["gnomon-mcp"] }
}
}
```
### 光标
`~/.cursor/mcp.json`(或项目中的 `.cursor/mcp.json`):
```json
{
"mcpServers": {
"gnomon": { "command": "uvx", "args": ["gnomon-mcp"] }
}
}
```
### 继续
`~/.continue/config.yaml`:
```yaml
mcpServers:
- name: gnomon
command: uvx
args: ["gnomon-mcp"]
```
### 任何其他客户端(通用stdio)
将 `uvx gnomon-mcp` 作为子进程启动,并通过stdin/stdout进行MCP通信。 这是整个集成。
### 主机/远程(HTTP传输)
适用于团队共享实例或无法启动本地子进程的代理:
```bash
uvx gnomon-mcp --transport streamable-http --host 0.0.0.0 --port 8000
# 也支持:--transport sse
```
然后将您的MCP客户端指向 `http://<host>:8000/mcp`(或 `/sse` 用于SSE传输)。
## 告诉您的代理实际使用它
MCP工具描述故意简洁,以保持持久上下文成本最小(所有四个工具约150个令牌)。 更丰富的“何时使用gnomon”的指南存在于Claude Code技能中,该技能按需加载。
### 选项A — Claude Code插件(一次命令,推荐)
该插件一次性配置了MCP服务器 *和* 技能。 在Claude Code内部:
/plugin marketplace add lihtness/gnomon-mcp
/plugin install gnomon@gnomon-mcp
这注册了 `gnomon` 作为MCP服务器(通过 `uvx` 自动启动)并安装了按需技能。 技能主体仅在任务触发时加载; 持久上下文对于四个工具描述保持约150个令牌,加上技能的名称和摘要约40个令牌。
### 选项B — 手动技能安装(无插件)
如果您已经使用 `claude mcp add gnomon -- uvx gnomon-mcp` 配置了MCP服务器,并且只需要技能:
```bash
mkdir -p ~/.claude/skills/gnomon
curl -fsSL https://raw.githubusercontent.com/lihtness/gnomon-mcp/main/skills/gnomon/SKILL.md \
-o ~/.claude/skills/gnomon/SKILL.md
```
### 选项C — 粘贴到您的系统提示(非Claude Code代理)
对于不支持技能的代理,请将此简短版本粘贴到您的系统提示或 `CLAUDE.md` 中:
```text
您拥有gnomon:用于日期和数学的确定性工具。 使用它们代替
猜测。
- `now` — 当前时刻(您的训练截止日期不是今天)。
- `calendar(ops)` — 批量日期数学:diff/until/since/add/weekday/
business_days/parse(自然语言)/format。
- `calc(expressions)` — 批量Python求值; 加载数学 + 统计 + 常用
内置函数。
- `calc_convert(value, from, to)` — 通过Pint进行单位转换。
两个批量工具都接受一个列表并返回一个列表。 优先使用一次批量调用
而不是多次小调用。
```
## 开发
```bash
git clone https://github.com/lihtness/gnomon-mcp
cd gnomon-mcp
pip install -e ".[dev]"
pytest
```
## 许可证
MIT