Skip to content

Repository files navigation

cjdrift

AI-native MCP toolchain for Cangjie developers.

Exposes a curated set of Cangjie-aware tools to any MCP-compatible LLM client — Claude Desktop, Cursor, Windsurf, Continue, OpenAI Agents, Cherry Studio, and friends — so the model can search the standard library, run cjpm / cjlint / cjfmt, scaffold a new project, look up the central registry, or read a source file, all without leaving the chat.

cjdrift is one binary that ships as a Cangjie 1.1.3 third-party library. You can import it into your own project, embed the MCP server into a larger app, or run it as a standalone cjdrift command that talks to the LLM over stdio.

Why this exists

The Cangjie ecosystem has a lot of moving parts: cjc, cjpm, cjlint, cjfmt, cjcov, cjtrace-recover, std.ast, the central registry at pkg.cangjie-lang.cn, the cangjie-tpc and cj-awesome package indexes, the docs site at cangjie-lang.cn/docs, the HCIA-Cangjie developer certification, the language server, and so on. When you ask an LLM to "add a function that reads JSON from a file", the model has to remember all of these moving parts and guess at API names.

cjdrift gives the LLM tools for every one of those parts:

When the LLM needs to ... It calls
... find a Cangjie stdlib API cangjie_apis
... read the long-form docs for one API cangjie_doc
... find an idiomatic snippet for a task cangjie_patterns
... run cjpm build / cjpm test cangjie_run
... run cjlint and get a structured list cangjie_lint
... format a file with cjfmt cangjie_fmt
... look up a package on the registry cangjie_pkg_search
... start a new project cangjie_scaffold
... understand a compiler / runtime error cangjie_explain
... read a source file cangjie_read_file
... write a file cangjie_write_file
... list a directory cangjie_list_dir

Every tool is read-only by default. The only state-changing tool (cangjie_write_file) requires an explicit confirm: true from the model, which the MCP client surfaces to the human before invoking.

Install

# from your Cangjie project directory
cjpm add cjdrift

Or, if you want the binary too:

git clone https://gitcode.com/jiangzeyu-2026/cjdrift
cd cjdrift
cjpm build
./target/release/cjdrift server    # run the MCP server
./target/release/cjdrift version   # print the version
./target/release/cjdrift tools     # list built-in tool names
./target/release/cjdrift search "ArrayList"
./target/release/cjdrift explain "cannot find symbol"

Wire it into an LLM client

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "cjdrift": {
      "command": "cjpm",
      "args": ["run", "--", "server"],
      "cwd": "/path/to/cjdrift"
    }
  }
}

Restart Claude Desktop. You should see the 11 cangjie_* tools in the tool palette.

Cursor / Windsurf

Both follow the same MCP config format. In ~/.cursor/mcp.json (or ~/.codeium/mcp.json):

{
  "mcpServers": {
    "cjdrift": {
      "command": "cjpm",
      "args": ["run", "--", "server"]
    }
  }
}

Continue.dev

Add to ~/.continue/config.json:

{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "name": "cjdrift",
        "transport": {
          "type": "stdio",
          "command": "cjpm",
          "args": ["run", "--", "server"]
        }
      }
    ]
  }
}

Use as a library

If you are building a Cangjie IDE plugin, an in-house agent platform, or just want to drive cjdrift from your own code:

import cjdrift

main(): Int64 {
    // The default registry exposes all 11 built-in tools over stdio.
    return cjdrift.runDefaultServer()
}

For finer control, build a registry with only the tools you need:

import cjdrift.core.{Server, ServerConfig, ToolRegistry, Transport}
import cjdrift.tools.{CjapiTool, CjlintTool, ExplainTool}
import cjdrift.knowledge.{ApiIndexLoader, builtinIndex, Explainer}
import std.io.{InputStream, OutputStream}

main(): Int64 {
    let registry = ToolRegistry()
    let idx = ApiIndexLoader().load()
    registry.register(CjapiTool(idx))
    registry.register(CjlintTool())
    registry.register(ExplainTool(Explainer()))

    let transport = Transport(InputStream.stdin(), OutputStream.stdout())
    let server = Server(ServerConfig(), registry, transport)
    return server.run()
}

Tool reference

See docs/tools.md for the full input schema and return shape of every tool. Here is a one-liner for each:

  • cangjie_apis — Fuzzy search the offline API index. Returns matches ranked by exact / prefix / substring hit on the type, member, package or signature fields.
  • cangjie_doc — Look up the full record for one entry, with a few related entries from the same package.
  • cangjie_patterns — Search a small library of short idiomatic snippets ("how do I write a unit test?", "how do I parse JSON?", "how do I spawn a future?").
  • cangjie_run — Run an allow-listed cjpm / cjpm / cjc / cjlint / cjfmt subcommand and capture stdout, stderr, exit code, and elapsed time. Anything outside the allow-list is refused for safety.
  • cangjie_lint — Run cjlint, parse its JSON report, and group findings by rule so the LLM sees patterns instead of one-off warnings.
  • cangjie_fmt — Run cjfmt in dry-run mode (default) to emit a unified diff, or in write mode to rewrite a file in place.
  • cangjie_pkg_search — Search the Cangjie central registry with an offline seed list as a safety net.
  • cangjie_scaffold — Generate a ready-to-build project for one of three kinds: executable, library, mcp-server.
  • cangjie_explain — Heuristic explanations for common compiler / runtime error messages, with concrete fix suggestions.
  • cangjie_read_file / cangjie_write_file — Read or write a file under a configured project root. Write requires confirm: true.
  • cangjie_list_dir — List a directory under a configured project root.

Architecture

                    +----------------------------+
                    |  MCP client (Claude etc.)  |
                    |                            |
                    |  LLM <-> JSON-RPC over stdio|
                    +-------------+--------------+
                                  |
                                  v
                    +----------------------------+
                    |  cjdrift server (this)     |
                    |                            |
                    |  Transport  Protocol        |
                    |  Server      Registry      |
                    |                            |
                    |  Tool  Tool  Tool ...      |
                    +-------------+--------------+
                                  |
              +-------------------+-------------------+
              v                   v                   v
        stdio / fs /        cjpm cjlint cjfmt     network
        process             (via std.process)     (registry)

The codebase is layered so that you can swap the transport (stdio, WebSocket, in-memory), the toolset, or the knowledge backend independently. See docs/arch.md for the full architecture write-up.

Safety

cjdrift is a developer's tool, not a security boundary. The LLM ultimately decides which tools to call and what to do with the results. We layer three safety mechanisms on top of whatever the MCP client already provides:

  1. Allow-list for cangjie_run. Only build, test, run, update, clean, lint, fmt, check, info, version. No cjpm add, no shell.
  2. confirm: true for cangjie_write_file. The model must explicitly opt in. The MCP client then surfaces a human prompt.
  3. Path containment for cangjie_*_file and cangjie_list_dir. Paths are resolved against a configured root, and .. segments are rejected unless the caller explicitly opts in.

Compatibility

  • SDK: cjdrift 0.1.0 targets Cangjie 1.1.3 (STS). It is built and tested on Linux x86-64, macOS aarch64, and Windows x86-64.
  • MCP protocol: cjdrift speaks MCP 2025-06-18. Earlier 2024-11-05 clients work; later versions will work as long as the spec stays backwards-compatible (which Anthropic has promised).
  • MCP clients: Claude Desktop 0.7+, Cursor 0.40+, Windsurf 1.5+, Continue 0.9+, OpenAI Agents SDK 0.3+.

Development

# Build and run all unit tests
cjpm test

# Run the server in dev mode (foreground)
cjpm run -- server

# Build a release binary
cjpm build -i
cjpm bundle

# Publish to the central registry
cp cangjie-repo.toml.example cangjie-repo.toml  # then fill in your token
cjpm publish

License

Apache-2.0. See LICENSE.

Acknowledgements

  • The Cangjie team at Huawei for an unusually well-thought-out language and a generous SDK.
  • The Anthropic team for the MCP spec, which is the most pleasant tool protocol I have used.
  • The contributors to cangjie-tpc and cj-awesome for documenting the ecosystem so thoroughly.

About

AI-native MCP toolchain for Cangjie 1.1.3 developers. 12 tools for cjpm/cjlint/cjfmt, std.api search, registry search, scaffolding, error explanation. Cangjie Ecosystem Innovation Challenge entry.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages