Vellum

Vellum

Provides exact text analysis tools for counting characters and words, scoring readability, diffing texts, testing regular expressions, and computing hashes.

Category
访问服务器

README

Vellum

An MCP server that gives exact answers about text · By Shuja Jamal

A language model reads tokens, not characters. Ask one how many letters are in a paragraph and it estimates, often badly. The same is true of diffing two files by eye, or predicting what a regular expression will match without running it.

These are not hard problems. They are simply not the kind of problem a model is built to solve. So it should ask instead.

Live vellum-mcp.vercel.app
Smithery sjshujaj/vellum
Write-up EXPERIENCE.md, on using existing MCPs before building this

The five tools

Tool What it answers Instead of
count_text Characters, words, lines, sentences, bytes an estimate from token count
score_readability Flesch reading ease, grade level, longest sentence an impression
diff_texts Unified diff, lines added and removed, similarity reading both and describing
test_regex Every match, its position and capture groups reasoning about the pattern
hash_text md5, sha1, sha256, sha512 nothing, it cannot

count_text reports visible characters separately from code points, because café is four characters to a person, five to len(), and six bytes. Which of those you want depends on why you asked, so it returns all three.


Using it

Claude Code

claude mcp add --transport http vellum https://vellum-mcp.vercel.app/mcp

Or locally, over stdio:

claude mcp add vellum -- python -m vellum.server

One thing that cost me time when installing somebody else's server: a server added mid-session shows as connected but its tools are not callable until the session restarts. A working install and a usable install are different states.

Claude Desktop

In claude_desktop_config.json:

{
  "mcpServers": {
    "vellum": {
      "command": "python",
      "args": ["-m", "vellum.server"],
      "cwd": "/path/to/vellum-mcp"
    }
  }
}

Running it

pip install -r requirements.txt
python -m vellum.server

That is stdio, which is what a local client speaks. For the HTTP transport and the landing page:

python -m vellum.server --http --port 8000

Then http://localhost:8000 for the page and http://localhost:8000/mcp for the endpoint.


Testing

python tests/test_vellum.py

46 checks. The first half calls the analysis functions directly. The second half is the part that matters: it launches the server as a subprocess and speaks MCP to it, doing the real handshake, listing the tools, calling them and reading the results back. A server whose functions are correct can still fail to speak the protocol, and only the second half would catch that.

python tests/test_deploy.py

Checks the deployed shape before deploying it: that a rewritten request reaches the MCP app at the path it expects, that ?action=demo reaches the demo instead, that the static server card describes tools that actually exist, and that there is exactly one function because that is what the runtime builds.


Deploying

Vercel, for the hosting

vercel

No environment variables and no secrets: every tool is a pure function of its arguments.

The routing is deliberate and worth explaining, because the obvious version does not work.

A Vercel rewrite does not hand the function the path the browser asked for. Rewriting /(.*) to a single function means every request arrives as /api/index, so an app that routes on path answers every URL with its own 404 while looking, from outside, completely dead. I lost an afternoon to exactly that on an earlier project.

And the Python runtime builds one function for the whole project, not one per file. I had api/demo.py sitting next to api/index.py, declared in vercel.json and bundled into the deployment, and /api/demo still returned Vercel's own 404. vercel inspect showed the reason plainly: a single python lambda. Filesystem routing across several Python entrypoints does not happen.

So the deployment is one function plus static files:

/                                  static    public/index.html
/.well-known/mcp/server-card.json  static    generated by build_card.py
/mcp             -> /api/index     function
/api/demo        -> /api/index     function, told apart by ?action=demo

api/index.py dispatches on the query string, because that is the part a rewrite preserves while it replaces the path, and it puts the path back before the MCP app routes on it. There are tests for both, because neither is something you want to discover from a live URL.

The two things that worked first time were the landing page and the server card, and they are exactly the two that never touch a function.

Smithery, for the listing

Smithery's current model is bring your own hosting: you give it a public HTTPS URL to a streamable HTTP server and its gateway proxies to it. There is no container to build.

  1. Deploy to Vercel first and note the URL
  2. Go to smithery.ai/new
  3. Enter https://your-deployment.vercel.app/mcp
  4. Complete the publishing flow

Smithery then reads the server's tools for the listing page. The documented path is a live scan, with a static card at /.well-known/mcp/server-card.json as the fallback when a scan cannot complete.

In practice the fallback was the primary path. The publish log reads:

Server metadata discovered (server card: 5 tools).
Using .well-known/mcp/server-card.json: (5 tools)

So the card was not insurance against a failure, it was the mechanism. build_card.py generates it from the server's own tool definitions, which is why it could not have listed tools that do not exist.

The log also warns that no config schema was provided. That is correct and intended here: every tool is a pure function of its arguments, so there is nothing to prompt a user for. The warning matters for a server that wraps an API and needs a key.

smithery.yaml records the details the publishing flow asks for. Note that it does not drive a build: the older container-based deployment path is no longer how this works.

Both tiers are free. Vercel's hobby tier hosts the function and the static files; Smithery's registry listing costs nothing.


How it is put together

vellum/
  analysis.py    the actual work, with no MCP anywhere in it
  server.py      the five tools, their descriptions, and the transports
api/
  index.py       the one Vercel function: MCP, and the demo behind a query flag
public/
  index.html     the landing page
  .well-known/mcp/server-card.json   generated
tests/
  test_vellum.py  analysis, then a real MCP handshake over stdio
  test_deploy.py  the routing and the card

analysis.py imports nothing from MCP. That is what lets the tests call it directly, and it is why the landing page's demo can call the same functions the tools call rather than being a second implementation that drifts.


Notes on writing tools for a model

The description is the interface. It is not documentation for a developer; it is the only thing the model reads when deciding whether a tool is relevant. A vague one means the tool is never chosen, a wrong one means it is chosen at the wrong moment. So count_text does not say "returns a dictionary of counts". It says to use this when the answer needs to be a precise number, because reading tokens is not the same as counting characters.

Failure should be readable. A broken regex comes back as {"valid": false, "error": ...} rather than an exception, and an unknown hash algorithm names the ones that exist. A model can act on that; it cannot act on a stack trace.

Pick something the model genuinely cannot do. The temptation is to wrap an API and call it a tool, but a "summarise this text" tool adds a network round trip to something the model already does better itself. Counting, hashing and running a regex are real gaps. Filling a real gap is what makes a tool get used rather than politely ignored.


By Shuja Jamal, August 2026.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选