cysic-mcp
Exposes the Cysic AI model to any MCP client over stdio, with server-side session memory and a tone-rewriting tool.
README
cysic-mcp
A Model Context Protocol (MCP) server in
TypeScript/Node.js that exposes the Cysic AI model
(minimax-m3) to any MCP client over stdio, with server-side session
memory and a tone-rewriting tool.
Problem
AI assistants and other MCP clients need a uniform way to call an LLM, manage multi-turn conversations across many requests, and rewrite text in different tones — but most existing LLM SDKs are HTTP-first and require per-integration boilerplate. A Cysic AI user has to:
- Wire
axios(orfetch) with the rightAuthorization: Bearer …header. - Implement retry/backoff for
429/5xx/ network failures. - Validate every tool input with
zodso a misbehaving client cannot crash the server. - Manage session state for multi-turn chat.
- Plug the whole thing into their MCP client.
cysic-mcp collapses all five into a single npm install + one
configuration file.
Solution
cysic-mcp is a single, small Node.js process that speaks the MCP
stdio transport. It registers exactly:
- 3 tools:
cysic_chat,cysic_session,cysic_humanize - 2 resources:
cysic://models,cysic://sessions/{id} - 2 prompts:
code_review,humanize_text
…and nothing more. The HTTP layer is a typed CysicClient wrapper around
axios with explicit timeout + exponential-backoff retries. All tool inputs
are validated by zod. All configuration is environment-driven; the server
fails fast at startup if the required CYSIC_API_KEY is missing.
Feature Checklist
The shipped surface, one item per row:
- [x] Tool:
cysic_chat { prompt, system?, temperature? }— single-turn chat with the Cysic AI model.promptis required (min length 1);systemoverrides the default "You are a helpful assistant." preamble;temperatureis optional in[0, 2]. - [x] Tool:
cysic_session { session_id, message }— multi-turn chat with server-side history. The server keeps the full conversation persession_idin an in-processMap; each call sends the entire history to the model and appends the assistant reply. Sessions are created lazily on first use. - [x] Tool:
cysic_humanize { text, tone? }— rewritetextin a requested tone.tonedefaults toneutraland acceptsneutral | friendly | formal | concise | confident. Internally uses a tone-specific system prompt and a low sampling temperature (0.2forconcise,0.4otherwise) to keep rewrites stable. - [x] Resource:
cysic://models— static catalog of models served by this MCP server, rendered as a JSONtext/plainpayload (e.g.{ models: [{ id: "minimax-m3", provider: "cysic", default: true }] }). - [x] Resource:
cysic://sessions/{id}— read template for a single session's message history. The{id}path segment is thesession_id. Returns the JSON-serialized message array; missing sessions return[]. - [x] Prompt:
code_review { language?, code }— render a senior-level code-review prompt for a code snippet.languageis optional (e.g."TypeScript");codeis required. The prompt returns two messages the client can render as a chat template. - [x] Prompt:
humanize_text { tone?, text }— render a prompt that mirrors thecysic_humanizetool contract so an MCP client can present it as a chat template without invoking the tool.
Distinctive features (innovation callouts):
- [x] Server-side session memory —
cysic_sessionkeeps a per-idMap<string, Message[]>so the client does not have to round-trip history. History is in-process; sessions are lost on restart and are not shared across processes (acceptable for a single-instance stdio MCP server). - [x]
cysic_humanizetone rewriting — five built-in tones (neutral,friendly,formal,concise,confident), each with its own instruction string and temperature. The same tone vocabulary is reused by thehumanize_textprompt so the prompt and the tool stay in lock-step.
Architecture
+----------------------+ stdio JSON-RPC +------------------+
| MCP client (e.g. | <--------------------------> | cysic-mcp |
| Claude Desktop, | | (Node.js) |
| any stdio MCP host) | | |
+----------------------+ | src/server.ts |
| | |
| v |
| src/tools/ |
| src/resources/ |
| src/prompts/ |
| | |
| v |
| CysicClient |
| (axios + retry) |
+--------+---------+
|
v
POST /v1/chat/completions
https://token-ai.cysic.xyz
Project layout
src/
server.ts # MCP server bootstrap, transport wiring
config.ts # env loading (loadConfig)
cysicClient.ts # axios wrapper + retry/backoff
state.ts # in-process session Map (sessions)
errors.ts # CysicError + toMcpErrorMessage sanitizer
tones.ts # shared tone vocabulary (used by tool + prompt)
mcpShims.ts # untyped SDK registration shims
tools/
index.ts # registerTools(server, client, state)
cysicChat.ts # cysic_chat tool
cysicSession.ts # cysic_session tool
cysicHumanize.ts # cysic_humanize tool
resources/
index.ts # registerResources(server, state)
models.ts # cysic://models resource
session.ts # cysic://sessions/{id} resource template
prompts/
index.ts # registerPrompts(server)
codeReview.ts # code_review prompt
humanizeText.ts # humanize_text prompt
tests/
cysicClient.test.ts # 8 tests (a-e per AC-3, plus a few extras)
structure.test.ts # 5 tests defending the AC-5 module split
dist/ # tsc output (gitignored)
Install
cysic-mcp requires Node.js >= 18.17 (for native fetch /
AbortController; we still use axios per the project rubric for
explicit timeout + retry control).
git clone <this-repo> cysic-mcp
cd cysic-mcp
npm install
npm run build
The build emits dist/server.js, which is the entry point referenced by
the start script and the cysic-mcp bin.
Configure
Copy the example env file and fill in your real Cysic API key:
cp .env.example .env
# then edit .env and set CYSIC_API_KEY=...
The full set of environment variables:
| Variable | Required | Default | Description |
|---|---|---|---|
CYSIC_API_KEY |
yes | — | Bearer token for the Cysic AI endpoint. Never echoed in logs. |
CYSIC_BASE_URL |
no | https://token-ai.cysic.xyz/v1 |
Base URL for the Cysic AI OpenAI-compatible API. |
CYSIC_MODEL |
no | minimax-m3 |
Default model used by the tools when no per-call override is given. |
CYSIC_TIMEOUT_MS |
no | 30000 |
Per-request HTTP timeout in milliseconds. |
CYSIC_MAX_RETRIES |
no | 3 |
Retries on 429 / 5xx / network errors (exponential backoff + jitter). |
If CYSIC_API_KEY is missing or empty, the server fails fast at
startup with a clear error message that names the variable (but does
not echo the value).
Run
Production (after npm run build):
npm start
# equivalent to: node dist/server.js
Development (live TypeScript via tsx):
npm run dev
# equivalent to: tsx src/server.ts
The server uses the MCP stdio transport. There is no HTTP port to
scrape; stdout is reserved for the MCP JSON-RPC stream. All fatal
startup errors are written to stderr so they do not corrupt the MCP
channel.
MCP Client Registration
Point your MCP client at the compiled entry point. The exact JSON shape depends on the client; the two common forms are below.
Claude Desktop (claude_desktop_config.json)
Add this entry under mcpServers:
{
"mcpServers": {
"cysic": {
"command": "node",
"args": ["/absolute/path/to/cysic-mcp/dist/server.js"],
"env": {
"CYSIC_API_KEY": "sk-your-real-key-here"
}
}
}
}
If you prefer the .env file approach, omit the env block and let the
server read it from disk:
{
"mcpServers": {
"cysic": {
"command": "node",
"args": ["/absolute/path/to/cysic-mcp/dist/server.js"]
}
}
}
Generic stdio MCP config
Any MCP host that speaks stdio can launch the server as a child process. The minimum invocation is:
{
"command": "node",
"args": ["dist/server.js"],
"cwd": "/absolute/path/to/cysic-mcp",
"env": {
"CYSIC_API_KEY": "sk-your-real-key-here",
"CYSIC_BASE_URL": "https://token-ai.cysic.xyz/v1",
"CYSIC_MODEL": "minimax-m3"
}
}
For a development-mode build, swap node + dist/server.js for
npx tsx src/server.ts and the host will run the TypeScript source
directly.
Example Tool Calls
The examples below are copy-pasteable. The exact wire format depends on
your MCP client; the JSON argument shape is what the server validates
with zod.
cysic_chat — single-turn chat
{
"name": "cysic_chat",
"arguments": {
"prompt": "What is the capital of France?",
"system": "You are a concise geography tutor.",
"temperature": 0.2
}
}
Returns:
{
"content": [{ "type": "text", "text": "Paris." }],
"isError": false
}
cysic_session — multi-turn chat with server-side history
Turn 1:
{
"name": "cysic_session",
"arguments": {
"session_id": "user-42",
"message": "Hi, my name is Alice."
}
}
Turn 2 (the server sends the full [user, assistant, user] history to
the model):
{
"name": "cysic_session",
"arguments": {
"session_id": "user-42",
"message": "What's my name?"
}
}
The full history can be inspected at runtime by reading the
cysic://sessions/user-42 resource.
cysic_humanize — tone rewriting
{
"name": "cysic_humanize",
"arguments": {
"text": "We're gonna ship the thing on Friday. Probably.",
"tone": "formal"
}
}
tone defaults to neutral; the full set of accepted values is
neutral | friendly | formal | concise | confident.
cysic://models — model catalog
{ "uri": "cysic://models" }
Returns a JSON payload listing the Cysic AI models served by this
server (currently { id: "minimax-m3", provider: "cysic", default: true }).
cysic://sessions/{id} — per-session history
{ "uri": "cysic://sessions/user-42" }
Returns the JSON-serialized message array for user-42. Missing
sessions return [].
code_review prompt
{
"name": "code_review",
"arguments": {
"language": "TypeScript",
"code": "const x: number = 1; console.log(x);"
}
}
Renders two messages the client can show as a chat template: a "you are a senior TypeScript engineer…" brief and a fenced code block to review.
humanize_text prompt
{
"name": "humanize_text",
"arguments": {
"tone": "confident",
"text": "I think maybe we could try to ship this?"
}
}
Renders two messages that mirror the cysic_humanize tool contract
(the tone instruction as the first message, the text to rewrite as the
second). Because the MCP PromptMessage.role enum is restricted to
"user" | "assistant", both messages are emitted with role: "user";
the "system" intent from the plan is preserved by the
two-message shape, not by a literal role: "system".
Testing
Unit tests use vitest and stub the HTTP layer
with nock so no real network is ever
made.
npm test
The current suite covers:
tests/cysicClient.test.ts— 8 tests across the AC-3 cases (a) 200 returns first choice, (b) 429 retried then succeeds, (c) 500 retried then fails with noapiKeyin the message, (d) 400 fails fast withcode: BAD_REQUESTand is not retried, (e) request body includesmodelandmessages, plus extras for temperature pass-through, per-call model override, and empty-messages rejection.tests/structure.test.ts— 5 tests importing every per-featureregisterXfunction and theCysicError/toMcpErrorMessage/TONE_VALUES/temperatureForTone/TONE_INSTRUCTIONSexports from the compileddist/tree, to defend the AC-5 module split.
License
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。